int coreaudio_object_write(struct audio_object *object, const void *data, size_t bytes) { struct coreaudio_object *self = to_coreaudio_object(object); if (!self->initialized) return noErr; bool runningAtStart = self->running; if(!runningAtStart) { TPCircularBufferClear(&(self->circularBuffer)); } char *dataPtr = (char*)data; // copy data to our circular buffer // Poll while we don't have space in the buffer. AudioBufferList *bufferList; UInt32 available; while(bytes > 0) { while((!runningAtStart || self->running) && (available = TPCircularBufferGetAvailableSpace(&(self->circularBuffer), &(self->format))) == 0) usleep(10000); // check we didn't stop if(runningAtStart && (!self->running)) return noErr; bufferList = TPCircularBufferPrepareEmptyAudioBufferListWithAudioFormat(&(self->circularBuffer), &(self->format), available, NULL); // we are writing mono/interleaved data so we have one buffer UInt32 bytesToWrite = min(bytes, bufferList->mBuffers[0].mDataByteSize); bufferList->mBuffers[0].mNumberChannels = (self->format).mChannelsPerFrame; bufferList->mBuffers[0].mDataByteSize = bytesToWrite; memcpy(bufferList->mBuffers[0].mData, dataPtr, bytesToWrite); TPCircularBufferProduceAudioBufferList(&(self->circularBuffer), NULL); dataPtr += bytesToWrite; bytes -= bytesToWrite; if(! runningAtStart) { OSStatus err = AudioOutputUnitStart(self->outputUnit); if(err == noErr) { self->running = TRUE; runningAtStart = TRUE; } else { return err; } } } return noErr; }
bool TPCircularBufferCopyAudioBufferList(TPCircularBuffer *buffer, const AudioBufferList *inBufferList, const AudioTimeStamp *inTimestamp, UInt32 frames, AudioStreamBasicDescription *audioDescription) { int byteCount = inBufferList->mBuffers[0].mDataByteSize; if ( frames != kTPCircularBufferCopyAll ) { byteCount = frames * audioDescription->mBytesPerFrame; assert(byteCount <= inBufferList->mBuffers[0].mDataByteSize); } AudioBufferList *bufferList = TPCircularBufferPrepareEmptyAudioBufferList(buffer, inBufferList->mNumberBuffers, byteCount, inTimestamp); if ( !bufferList ) return false; for ( int i=0; i<bufferList->mNumberBuffers; i++ ) { memcpy(bufferList->mBuffers[i].mData, inBufferList->mBuffers[i].mData, byteCount); } TPCircularBufferProduceAudioBufferList(buffer, NULL); return true; }