darwin_audio_output.cc (2462B)
1 #include <AudioToolbox/AudioToolbox.h> 2 3 #include "intrinsics.h" 4 #include "log.h" 5 #include "platform_audio_output.h" 6 7 void audio_output_init() { } 8 void audio_output_term() { } 9 10 static OSStatus audio_output_callback( 11 void * data, 12 AudioUnitRenderActionFlags * ioActionFlags, 13 const AudioTimeStamp * inTimeStamp, 14 u32 inBusNumber, u32 num_samples, 15 AudioBufferList * buffers 16 ) { 17 ASSERT( ARRAY_COUNT( device->buffer.samples ) % num_samples == 0 ); 18 19 AudioOutputDevice * device = ( AudioOutputDevice * ) data; 20 21 s16 * samples = ( s16 * ) buffers->mBuffers[ 0 ].mData; 22 23 u32 cursor = load_acquire( &device->buffer.cursor ); 24 memcpy( samples, &device->buffer.samples[ cursor ], num_samples * sizeof( s16 ) ); 25 store_release( &device->buffer.cursor, ( cursor + num_samples ) % ARRAY_COUNT( device->buffer.samples ) ); 26 27 return 0; 28 } 29 30 void audio_output_open( AudioOutputDevice * device, AudioOutputCallback callback ) { 31 memset( &device->buffer, 0, sizeof( device->buffer ) ); 32 33 AudioComponentDescription desc = { }; 34 desc.componentType = kAudioUnitType_Output; 35 desc.componentSubType = kAudioUnitSubType_DefaultOutput; 36 desc.componentManufacturer = kAudioUnitManufacturer_Apple; 37 38 device->component = AudioComponentFindNext( NULL, &desc ); 39 if( device->component == NULL ) { 40 FATAL( "AudioComponentFindNext" ); 41 } 42 43 if( AudioComponentInstanceNew( device->component, &device->unit ) ) { 44 FATAL( "AudioComponentInstanceNew" ); 45 } 46 47 AudioUnitInitialize( device->unit ); 48 49 const int rate = 44100; 50 const int channels = 1; 51 AudioStreamBasicDescription stream_format = { }; 52 stream_format.mSampleRate = rate; 53 stream_format.mFormatID = kAudioFormatLinearPCM; 54 stream_format.mFormatFlags = kAudioFormatFlagIsSignedInteger; 55 stream_format.mFramesPerPacket = 1; 56 stream_format.mChannelsPerFrame = channels; 57 stream_format.mBitsPerChannel = 16; 58 stream_format.mBytesPerPacket = channels * 2; 59 stream_format.mBytesPerFrame = channels * 2; 60 61 AudioUnitSetProperty( device->unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &stream_format, sizeof( stream_format ) ); 62 63 AURenderCallbackStruct cb = { }; 64 cb.inputProc = audio_output_callback; 65 cb.inputProcRefCon = device; 66 67 AudioUnitSetProperty( device->unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &cb, sizeof( AURenderCallbackStruct ) ); 68 69 AudioOutputUnitStart( device->unit ); 70 } 71 72 void audio_output_close( AudioOutputDevice * device ) { 73 FATAL( "need to implement audio_output_close" ); 74 }