static void Mac_UnlockAudio(_THIS) { SInt32 oldval; oldval = DecrementAtomic((SInt32 *) &audio_is_locked); if ( oldval != 1 ) /* != 1 means audio is still locked. */ return; /* Did we miss the chance to mix in an interrupt? Do it now. */ if ( BitAndAtomic (0xFFFFFFFF, (UInt32 *) &need_to_mix) ) { /* * Note that this could be a problem if you missed an interrupt * while the audio was locked, and get preempted by a second * interrupt here, but that means you locked for way too long anyhow. */ mix_buffer (this, buffer[fill_me]); } }
static void callBackProc(SndChannel * chan, SndCommand * cmd_passed) { UInt32 play_me; SndCommand cmd; SDL_AudioDevice *audio = (SDL_AudioDevice *) chan->userInfo; IncrementAtomic((SInt32 *) & need_to_mix); fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */ play_me = !fill_me; /* filled buffer to play _now_ */ if (!audio->enabled) { return; } /* queue previously mixed buffer for playback. */ header.samplePtr = (Ptr) buffer[play_me]; cmd.cmd = bufferCmd; cmd.param1 = 0; cmd.param2 = (long) &header; SndDoCommand(chan, &cmd, 0); SDL_memset(buffer[fill_me], 0, audio->spec.size); /* * if audio device isn't locked, mix the next buffer to be queued in * the memory block that just finished playing. */ if (!BitAndAtomic(0xFFFFFFFF, (UInt32 *) & audio_is_locked)) { mix_buffer(audio, buffer[fill_me]); } /* set this callback to run again when current buffer drains. */ if (running) { cmd.cmd = callBackCmd; cmd.param1 = 0; cmd.param2 = play_me; SndDoCommand(chan, &cmd, 0); } }
PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames ) { PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio; char *cbuf = (char *) buffer; PaError ret = paNoError; VVDBUG(("WriteStream()\n")); while( frames > 0 ) { long avail = 0; long toWrite; do { avail = RingBuffer_GetWriteAvailable( &blio->outputRingBuffer ); /* printf( "Write Buffer is %%%g full: %ld of %ld.\n", 100 - 100 * (float)avail / (float) blio->outputRingBuffer.bufferSize, avail, blio->outputRingBuffer.bufferSize ); */ if( avail == 0 ) { #ifdef PA_MAC_BLIO_MUTEX /*block while full*/ ret = UNIX_ERR( pthread_mutex_lock( &blio->outputMutex ) ); if( ret ) return ret; while( blio->isOutputFull ) { ret = UNIX_ERR( pthread_cond_wait( &blio->outputCond, &blio->outputMutex ) ); if( ret ) return ret; } ret = UNIX_ERR( pthread_mutex_unlock( &blio->outputMutex ) ); if( ret ) return ret; #else Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL ); #endif } } while( avail == 0 ); toWrite = MIN( avail, frames * blio->outputSampleSize * blio->outChan ); toWrite -= toWrite % blio->outputSampleSize * blio->outChan ; RingBuffer_Write( &blio->outputRingBuffer, (void *)cbuf, toWrite ); cbuf += toWrite; frames -= toWrite / ( blio->outputSampleSize * blio->outChan ); #ifdef PA_MAC_BLIO_MUTEX if( toWrite == avail ) { /* we just filled up the buffer, so we need to mark it as filled. */ ret = blioSetIsOutputFull( blio, true ); if( ret ) return ret; /* of course, in the meantime, we may have emptied the buffer, so so check for that, too, to avoid a race condition. */ if( RingBuffer_GetWriteAvailable( &blio->outputRingBuffer ) ) { blioSetIsOutputFull( blio, false ); if( ret ) return ret; } } #endif } /* Report either paNoError or paOutputUnderflowed. */ /* may also want to report other errors, but this is non-standard. */ ret = blio->statusFlags & paOutputUnderflow; /* report underflow only once: */ if( ret ) { //Mihai: replacing OSAtomicAnd32 with BitAndAtomic //OSAtomicAnd32( ~paOutputUnderflow, &blio->statusFlags ); BitAndAtomic( ~paOutputUnderflow, &blio->statusFlags ); ret = paOutputUnderflowed; } return ret; }
PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames ) { PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio; char *cbuf = (char *) buffer; PaError ret = paNoError; VVDBUG(("ReadStream()\n")); while( frames > 0 ) { long avail; long toRead; do { avail = RingBuffer_GetReadAvailable( &blio->inputRingBuffer ); /* printf( "Read Buffer is %%%g full: %ld of %ld.\n", 100 * (float)avail / (float) blio->inputRingBuffer.bufferSize, avail, blio->inputRingBuffer.bufferSize ); */ if( avail == 0 ) { #ifdef PA_MAC_BLIO_MUTEX /**block when empty*/ ret = UNIX_ERR( pthread_mutex_lock( &blio->inputMutex ) ); if( ret ) return ret; while( blio->isInputEmpty ) { ret = UNIX_ERR( pthread_cond_wait( &blio->inputCond, &blio->inputMutex ) ); if( ret ) return ret; } ret = UNIX_ERR( pthread_mutex_unlock( &blio->inputMutex ) ); if( ret ) return ret; #else Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL ); #endif } } while( avail == 0 ); toRead = MIN( avail, frames * blio->inputSampleSize * blio->inChan ); toRead -= toRead % blio->inputSampleSize * blio->inChan ; RingBuffer_Read( &blio->inputRingBuffer, (void *)cbuf, toRead ); cbuf += toRead; frames -= toRead / ( blio->inputSampleSize * blio->inChan ); if( toRead == avail ) { #ifdef PA_MAC_BLIO_MUTEX /* we just emptied the buffer, so we need to mark it as empty. */ ret = blioSetIsInputEmpty( blio, true ); if( ret ) return ret; /* of course, in the meantime, the callback may have put some sats in, so so check for that, too, to avoid a race condition. */ if( RingBuffer_GetReadAvailable( &blio->inputRingBuffer ) ) { blioSetIsInputEmpty( blio, false ); if( ret ) return ret; } #endif } } /* Report either paNoError or paInputOverflowed. */ /* may also want to report other errors, but this is non-standard. */ ret = blio->statusFlags & paInputOverflow; /* report underflow only once: */ if( ret ) { //Mihai: replacing OSAtomicAnd32 with BitAndAtomic //OSAtomicAnd32( ~paInputOverflow, &blio->statusFlags ); BitAndAtomic( ~paInputOverflow, &blio->statusFlags ); ret = paInputOverflowed; } return ret; }