medfall

A super great game engine
Log | Files | Refs

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 }