diff --git a/stepmania/src/arch/Sound/RageSoundDriver_CA.cpp b/stepmania/src/arch/Sound/RageSoundDriver_CA.cpp index 3175f0ac34..4e377c57b6 100644 --- a/stepmania/src/arch/Sound/RageSoundDriver_CA.cpp +++ b/stepmania/src/arch/Sound/RageSoundDriver_CA.cpp @@ -17,6 +17,10 @@ #include #include #include +#if CURRENT_DRIVER == BROKEN_DRIVER_2 +#include +#endif + const Float64 kSampleRate = 44100.000; const UInt32 kChannelsPerFrame = 2; @@ -25,8 +29,6 @@ const UInt32 kSampleSize = kChannelsPerFrame * kBitsPerChannel / 8; const UInt32 kPacketSize = kSampleSize; -static AudioDeviceID outputDevice; - #if defined(DEBUG) static char *__errorMessage; static char __fourcc[5]; @@ -44,6 +46,10 @@ free(__errorMessage) RageSound_CA::RageSound_CA() { +#if CURRENT_DRIVER != BROKEN_DRIVER_1 && CURRENT_DRIVER != BROKEN_DRIVER_2 + RageException::ThrowNonfatal("Class not finished"); +#endif +#if CURRENT_DRIVER == BROKEN_DRIVER_1 UInt32 thePropertySize = sizeof(AudioDeviceID); OSStatus err; @@ -77,6 +83,12 @@ RageSound_CA::RageSound_CA() err = AudioConverterNew(&idealFormat, &streamFormat, &converter); TEST_ERR(err); + /*thePropertySize = sizeof(UInt32); + UInt32 frames = 1024; + err = AudioStreamSetProperty(outputDevice, NULL, kAudioPropertyWildcardChannel, + kAudioDevicePropertyBufferFrameSize, thePropertySize, &frames); + TEST_ERR(err);*/ + /* Calculate the input buffersize */ thePropertySize = sizeof(UInt32); err = AudioDeviceGetProperty(outputDevice, 0, 0, kAudioDevicePropertyBufferSize, &thePropertySize, @@ -116,10 +128,85 @@ RageSound_CA::RageSound_CA() TEST_ERR(err); latency = 0; //for now +#elif CURRENT_DRIVER == BROKEN_DRIVER_2 + /* Open the default output unit */ + OSStatus err; + ComponentDescription desc; + + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + Component comp = FindNextComponent(NULL, &desc); + RAGE_ASSERT_M(comp != NULL, "Couldn't find the component"); + + err = OpenAComponent(comp, &outputUnit); + TEST_ERR(err); + + /* Set the callback */ + AURenderCallbackStruct callback; + callback.inputProc = GetData; + callback.inputProcRefCon = this; + + err = AudioUnitSetProperty(outputUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &callback, + sizeof(callback)); + TEST_ERR(err); + + /* Set the input format */ + AudioStreamBasicDescription idealFormat; + + idealFormat.mSampleRate = kSampleRate; + idealFormat.mFormatID = kAudioFormatLinearPCM; + idealFormat.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked + | kLinearPCMFormatFlagIsSignedInteger; + idealFormat.mBytesPerPacket = kPacketSize; + idealFormat.mFramesPerPacket = 1; + idealFormat.mBytesPerFrame = kPacketSize; + idealFormat.mChannelsPerFrame = kChannelsPerFrame; + idealFormat.mBitsPerChannel = kBitsPerChannel; + idealFormat.mReserved = 0; + + err = AudioUnitSetProperty(outputUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &idealFormat, + sizeof(idealFormat)); + TEST_ERR(err); + + /* Calculate the latency */ + latency = 0; + + /* Initialize the unit */ + err = AudioUnitInitialize(outputUnit); + TEST_ERR(err); + + /* Get the underlying device */ + UInt32 propertySize = sizeof(outputDevice); + err = AudioUnitGetProperty(outputUnit, + kAudioOutputUnitProperty_CurrentDevice, + kAudioUnitScope_Global, + 0, + &outputDevice, + &propertySize); + TEST_ERR(err); + RAGE_ASSERT(outputDevice); + + /* Start the outputUnit */ + AudioOutputUnitStart(outputUnit); + +#endif } RageSound_CA::~RageSound_CA() { +#if CURRENT_DRIVER == BROKEN_DRIVER_1 OSStatus err; err = AudioDeviceStop(outputDevice, GetData); @@ -130,6 +217,10 @@ RageSound_CA::~RageSound_CA() err = AudioConverterDispose(converter); TEST_ERR(err); +#elif CURRENT_DRIVER == BROKEN_DRIVER_2 + AudioOutputUnitStop(outputUnit); + CloseComponent(outputUnit); +#endif } void RageSound_CA::StartMixing(RageSound *snd) @@ -182,6 +273,7 @@ void RageSound_CA::Update(float delta) } } +#if CURRENT_DRIVER == BROKEN_DRIVER_1 OSStatus RageSound_CA::GetData(AudioDeviceID inDevice, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, @@ -226,13 +318,61 @@ OSStatus RageSound_CA::GetData(AudioDeviceID inDevice, UInt32 size; - OSStatus err = AudioConverterConvertBuffer(THIS->converter, THIS->buffersize, buffer, &size, - outOutputData->mBuffers[0].mData); - - return err; + return AudioConverterConvertBuffer(THIS->converter, THIS->buffersize, buffer, &size, + outOutputData->mBuffers[0].mData); } +#elif CURRENT_DRIVER == BROKEN_DRIVER_2 + +OSStatus RageSound_CA::GetData(void *inRefCon, + AudioUnitRenderActionFlags *inActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumFrames, + AudioBufferList *ioData) +{ + unsigned outputSize = ioData->mBuffers[0].mDataByteSize; + if (!SOUNDMAN) + { + bzero(ioData->mBuffers[0].mData, outputSize); + *inActionFlags = kAudioUnitRenderAction_OutputIsSilence; + return noErr; + } + RageSound_CA *THIS = (RageSound_CA *)inRefCon; + char *buffer = (char *)ioData->mBuffers[0].mData; + + bzero(buffer, THIS->buffersize); + LockMutex L(SOUNDMAN->lock); + static SoundMixBuffer mix; + int position = int(inTimeStamp->mSampleTime); //This should be in frames + bool moreThanOneSound = THIS->sounds.size() > 1; + + for (unsigned i=0; isounds.size(); ++i) + { + if (THIS->sounds[i]->stopping) + continue; + + unsigned got = THIS->sounds[i]->snd->GetPCM(buffer, outputSize, position); + if (moreThanOneSound) + mix.write((SInt16 *)buffer, got / 2); + if (got < outputSize) + { + THIS->sounds[i]->stopping = true; + THIS->sounds[i]->flush_pos = position + got / kSampleSize; + } + } + + if (moreThanOneSound) + mix.read((SInt16 *)buffer); + *inActionFlags = kAudioUnitRenderAction_PostRender; + + return noErr; +} + +#endif + inline int RageSound_CA::ConvertAudioTimeStampToPosition(const AudioTimeStamp *time) { return (int)(time->mSampleTime / time->mRateScalar); + //return int(time->mSampleTime); } diff --git a/stepmania/src/arch/Sound/RageSoundDriver_CA.h b/stepmania/src/arch/Sound/RageSoundDriver_CA.h index 2ed0ca625d..15e3afadd9 100644 --- a/stepmania/src/arch/Sound/RageSoundDriver_CA.h +++ b/stepmania/src/arch/Sound/RageSoundDriver_CA.h @@ -10,14 +10,25 @@ */ #include "RageSoundDriver.h" +#define BROKEN_DRIVER_1 1 +#define BROKEN_DRIVER_2 2 + +#define CURRENT_DRIVER BROKEN_DRIVER_2 struct AudioTimeStamp; struct AudioBufferList; +#if CURRENT_DRIVER == BROKEN_DRIVER_1 struct OpaqueAudioConverter; typedef struct OpaqueAudioConverter *AudioConverterRef; +#endif typedef long OSStatus; typedef unsigned long UInt32; typedef UInt32 AudioDeviceID; +typedef UInt32 AudioUnitRenderActionFlags; +#if CURRENT_DRIVER == BROKEN_DRIVER_2 +struct ComponentInstanceRecord; +typedef struct ComponentInstanceRecord *AudioUnit; +#endif class RageSound_CA : public RageSoundDriver { @@ -30,7 +41,12 @@ private: } *soundPtr; vector sounds; +#if CURRENT_DRIVER == BROKEN_DRIVER_1 AudioConverterRef converter; +#elif CURRENT_DRIVER == BROKEN_DRIVER_2 + AudioUnit outputUnit; +#endif + AudioDeviceID outputDevice; float latency; UInt32 buffersize; @@ -45,6 +61,7 @@ protected: public: RageSound_CA(); virtual ~RageSound_CA(); +#if CURRENT_DRIVER == BROKEN_DRIVER_1 static OSStatus GetData(AudioDeviceID inDevice, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, @@ -52,6 +69,14 @@ public: AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* inClientData); +#elif CURRENT_DRIVER == BROKEN_DRIVER_2 + static OSStatus GetData(void *inRecCon, + AudioUnitRenderActionFlags *inActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumFrames, + AudioBufferList *ioData); +#endif }; #endif RAGE_SOUND_CA