int sgi_audio_read(audio_desc_t ad, u_char *buf, int buf_bytes) { long len; UNUSED(ad); assert(audio_fd > 0); if (non_block) { if ((len = ALgetfilled(rp)) < bytes_per_block ) return (0); len = min(len, buf_bytes); } else { len = (long)buf_bytes; } len /= BYTES_PER_SAMPLE; /* We only open device in 16 bit mode */ if (len > QSIZE) { fprintf(stderr, "audio_read: too big!\n"); len = QSIZE; } ALreadsamps(rp, buf, len); return ((int)len * BYTES_PER_SAMPLE); }
int sgi_audio_is_ready(audio_desc_t ad) { UNUSED(ad); assert(audio_fd > 0); if (ALgetfilled(rp) >= ALgetfillpoint(rp)) { return TRUE; } else { return FALSE; } }
/** * @brief Read samples from device * * Try to read @a sampnum samples and returns actual number of recorded * samples currently available. This function will block until * at least one sample can be obtained. * * @param buf [out] samples obtained in this function * @param sampnum [in] wanted number of samples to be read * * @return actural number of read samples, -2 if an error occured. */ int adin_mic_read(SP16 *buf, int sampnum) { long cnt; cnt = ALgetfilled(aport); /* get samples currently stored in queue */ if (cnt > sampnum) cnt = sampnum; if (ALreadsamps(aport, buf, cnt) < 0) { /* get them */ jlog("Error: adin_o2: failed to read sample\n"); return(-2); /* return negative on error */ } return cnt; }
/* * Clean up sound routines. */ void sfxEnd(int waitForSounds) { int idx; endingOnPurpose = 1; if (waitForSounds) { /* wait for sounds to complete */ for (idx=0; idx < nAudioPorts; idx++) { while (ALgetfilled(audioPort[idx]) > 0) sginap(1); ALcloseport(audioPort[idx]); } } else if (soundChild > 0) /* kill childs playing sounds */ kill(soundChild, SIGKILL); if (nAudioPorts > 0) /* reset audio subsystem */ sfxResetAudioHw(); }
/* * Sound handler. */ static void sfxSoundHandler(void *arg) { ALport *ap = (ALport *)arg; Sample samp[MAX_AUDIO_PORTS]; int idx, nap; int treated; int nSounds = 1; int nextPort = 0; long maxSampsPerPass; long sampCount; long pvbuf[2]; struct _sfx ss; struct pollfd pf; prctl(PR_TERMCHILD, 0); (void) signal(SIGHUP, sfxDieGracefully); maxSampsPerPass = 1600; for (idx=0; idx < nAudioPorts; idx++) { samp[idx].id = -1; samp[idx].sample = NULL; samp[idx].sampsToPlay = 0; samp[idx].repeat = 0; } /* * Set sample rate for output device. */ pvbuf[0] = AL_OUTPUT_RATE; pvbuf[1] = AL_RATE_16000; (void) ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2L); /* * Prepare to read from pipe. */ pf.fd = spigot[0]; pf.events = POLLIN | POLLRDNORM | POLLRDBAND; #define EVER ;; for (EVER) { if (nSounds == 0 || (idx=poll(&pf, 1, 0)) > 0) { (void) read(spigot[0], &ss, sizeof(ss)); treated = 0; if (ss.loop == 1 && ss.repeat == 0) { treated = 1; for (idx=0; idx < nAudioPorts; idx++) { if (samp[idx].id == ss.id) { samp[idx].id = -1; samp[idx].repeat = 0; samp[idx].sampsToPlay = 0; samp[idx].sample = NULL; } } } else if (ss.loop == 1 && ss.count > 1) { for (idx=0; idx < nAudioPorts; idx++) { if (samp[idx].id == ss.id) { treated = 1; samp[idx].repeat = ss.repeat; samp[idx].sampsToPlay = (long)ss.soundSize[ss.pitch]; samp[idx].sampsPlayed = 0; samp[idx].sample = ss.soundData[ss.pitch]; } } } if (!treated) { for (idx=0; idx < nAudioPorts; idx++) { nextPort = (nextPort+1) % nAudioPorts; if (samp[nextPort].repeat == 0) break; } samp[nextPort].sample = ss.soundData[ss.pitch]; samp[nextPort].sampsToPlay = (long)ss.soundSize[ss.pitch]; samp[nextPort].sampsPlayed = 0; samp[nextPort].repeat = ss.repeat; samp[nextPort].id = ss.id; } } else if (idx < 0) (void) fprintf(stderr, "panic: input poll failed: %s\n", strerror(errno)); nSounds = 0; nap = 0; for (idx=0; idx < nAudioPorts; idx++) { if (samp[idx].sampsToPlay > 0) { nSounds++; if (ALgetfilled(ap[idx]) > 4000) { nap++; continue; } } if (samp[idx].sampsToPlay >= maxSampsPerPass) { (void) ALwritesamps(ap[idx], samp[idx].sample + samp[idx].sampsPlayed, maxSampsPerPass); samp[idx].sampsPlayed += maxSampsPerPass; samp[idx].sampsToPlay -= maxSampsPerPass; } else if (samp[idx].sampsToPlay > 0) { if ((samp[idx].sampsToPlay%2) == 1) { samp[idx].sampsToPlay -= 1; samp[idx].sampsPlayed += 1; } if (samp[idx].sampsToPlay > 0) (void) ALwritesamps(ap[idx], samp[idx].sample+samp[idx].sampsPlayed, samp[idx].sampsToPlay); if (samp[idx].repeat) { sampCount = maxSampsPerPass - samp[idx].sampsToPlay; samp[idx].sampsToPlay += samp[idx].sampsPlayed - sampCount; samp[idx].sampsPlayed = sampCount; (void) ALwritesamps(ap[idx], samp[idx].sample, sampCount); } else samp[idx].sampsToPlay = 0; } } if (nap == nSounds) sginap(1); } return; }
void MainLoop(ALport alp, FileDescriptor dacfd, FileDescriptor sockfd, SynthState *v1, SynthState *v2) { /* int hwm = 300, lwm = 256; */ int hwm = 1000, lwm = 800; fd_set read_fds, write_fds; /* largest file descriptor to search for */ int nfds = BIGGER_OF(dacfd, sockfd) + 1; printf("MainLoop: dacfd %d, sockfd %d, nfds %d\n", dacfd, sockfd, nfds); time_to_quit = 0; sigset(SIGINT, catch_sigint); /* set sig handler */ while(!time_to_quit) { /* compute sine wave samples while the sound output buffer is below the high water mark */ while (ALgetfilled(alp) < hwm) { Synthesize(alp, v1, v2); } /* Figure out the time tag corresponding to the time in the future that we haven't computed any samples for yet. */ OSCInvokeAllMessagesThatAreReady(OSCTT_PlusSeconds(OSCTT_CurrentTime(), ALgetfilled(alp) / the_sample_rate)); /* set the low water mark, i.e. when we want control from select(2) */ ALsetfillpoint(alp, OUTPUTQUEUESIZE - lwm); /* set up select */ FD_ZERO(&read_fds); /* clear read_fds */ FD_ZERO(&write_fds); /* clear write_fds */ FD_SET(dacfd, &write_fds); FD_SET(sockfd, &read_fds); FD_SET(0, &read_fds); /* stdin */ /* give control back to OS scheduler to put us to sleep until the DAC queue drains and/or a character is available from standard input */ if (select(nfds, &read_fds, &write_fds, (fd_set * )0, (struct timeval *)0) < 0) { /* select reported an error */ perror("bad select"); goto quit; } if(FD_ISSET(sockfd, &read_fds)) { ReceivePacket(sockfd); } /* is there a character in the queue? */ if (FD_ISSET(0, &read_fds)) { /* this will never block */ char c = getchar(); if (c == 'q') { /* quit */ break; } else if ((c <= '9') && (c >= '0')) { /* tweak frequency */ v1->f = 440.0 + 100.0 * (c - '0'); } } } quit: ALcloseport(alp); closeudp(sockfd); }
/*---------------------------------------------------------------------------------------------------*/ static PaError Pa_SgiAudioProcess(internalPortAudioStream *past) /* Spawned by PaHost_StartEngine(). */ { PaError result = paNoError; PaHostSoundControl *pahsc; if (!past) return paBadStreamPtr; pahsc = (PaHostSoundControl*)past->past_DeviceData; if (!pahsc) return paInternalError; past->past_IsActive = 1; /* Wasn't this already done by the calling parent?! */ DBUG(("entering thread.\n")); while (!past->past_StopSoon) /* OR-ing StopSoon and StopNow here gives problems! */ { /*---------------------------------------- INPUT: ------------------------------------*/ if (pahsc->pahsc_NativeInputBuffer) /* Then pahsc_ALportIN should also be there! */ { while (ALgetfilled(pahsc->pahsc_ALportIN) < pahsc->pahsc_SamplesPerInputBuffer) { /* Trying sginap(1); and usleep(); here... things get blocked under IRIX6.2. */ if (past->past_StopNow) /* Don't let ALreadsamps() block */ goto done; } if (ALreadsamps(pahsc->pahsc_ALportIN, (void*)pahsc->pahsc_NativeInputBuffer, pahsc->pahsc_SamplesPerInputBuffer)) /* Number of samples instead */ { /* of number of frames. */ ERR_RPT(("ALreadsamps() failed.\n")); result = paInternalError; goto done; } } /*---------------------------------------------------- USER CALLBACK ROUTINE: ----------*/ /* DBUG(("Calling Pa_CallConvertInt16()...\n")); */ Pa_StartUsageCalculation(past); /* Convert 16 bit native data to */ result = Pa_CallConvertInt16(past, /* user data and call user routine. */ pahsc->pahsc_NativeInputBuffer, pahsc->pahsc_NativeOutputBuffer); Pa_EndUsageCalculation(past); if (result) { DBUG(("Pa_CallConvertInt16() returned %d, stopping...\n", result)); goto done; /* This is apparently NOT an error! */ } /* Just letting the userCallBack stop us. */ /*---------------------------------------- OUTPUT: ------------------------------------*/ if (pahsc->pahsc_NativeOutputBuffer) /* Then pahsc_ALportOUT should also be there! */ { while (ALgetfillable(pahsc->pahsc_ALportOUT) < pahsc->pahsc_SamplesPerOutputBuffer) { /* Trying sginap(1); and usleep(); here... things get blocked under IRIX6.2. */ if (past->past_StopNow) /* Don't let ALwritesamps() block */ goto done; } if (ALwritesamps(pahsc->pahsc_ALportOUT, (void*)pahsc->pahsc_NativeOutputBuffer, pahsc->pahsc_SamplesPerOutputBuffer)) { ERR_RPT(("ALwritesamps() failed.\n")); result = paInternalError; goto done; } } /*-------------------------------------------------------------------------------------*/ } done: /* pahsc->pahsc_ThreadPID = -1; Hu? doesn't help!! (added by Pieter) */ past->past_IsActive = 0; DBUG(("leaving thread.\n")); return result; }
static void drain_audio_port (AudioContext ac) { while (ALgetfilled (ac->ac_port) > 0) sginap(1); }