3 #include <AudioUnit/AudioUnit.h>
8 struct AudioDataRenderer
16 int TotalNumberOfFrames;
19 char* AudioDataBuffer;
26 void* HandleChannelMixer;
31 return IsInfiniteLoop || NumberOfLoops > 0;
34 void CopyDataToBuffer(
char* &outBuffer,
int nbFrameToCopy,
int nbOfChannels)
36 char* inPtr = AudioDataBuffer +
sizeof(short) * nbOfChannels * CurrentFrame;
37 int sizeToCopy =
sizeof(short) * nbFrameToCopy * nbOfChannels;
39 memcpy(outBuffer, inPtr, sizeToCopy);
41 CurrentFrame += nbFrameToCopy;
42 outBuffer += sizeToCopy;
45 int AudioDataMixerCallback(uint busIndex,
int totalNbOfFrameToWrite, AudioBufferList* data)
47 char* outPtr = (
char*)data->mBuffers[0].mData;
49 int remainingFramesToWrite = totalNbOfFrameToWrite;
50 while (remainingFramesToWrite > 0)
52 int nbOfFrameToWrite = std::min(remainingFramesToWrite, (ShouldBeLooped() ? LoopEndPoint : TotalNumberOfFrames) - CurrentFrame);
54 CopyDataToBuffer(outPtr, nbOfFrameToWrite, NumberOfChannels);
56 remainingFramesToWrite -= nbOfFrameToWrite;
59 if (ShouldBeLooped() && CurrentFrame >= LoopEndPoint)
62 CurrentFrame = LoopStartPoint;
66 if (CurrentFrame >= TotalNumberOfFrames)
68 AudioUnitSetParameter((AudioUnit)HandleChannelMixer, kMultiChannelMixerParam_Enable, kAudioUnitScope_Input, busIndex, 0, 0);
69 AudioUnitSetParameter((AudioUnit)Handle3DMixer, k3DMixerParam_Enable, kAudioUnitScope_Input, busIndex, 0, 0);
77 int sizeToBlank =
sizeof(short) * NumberOfChannels * remainingFramesToWrite;
78 memset(outPtr, 0, sizeToBlank);
87 OSStatus RendererCallbackChannelMixer(uint busNumber, uint numberFrames, AudioBufferList* data)
92 OSStatus ret = AudioDataMixerCallback(busNumber, (
int)numberFrames, data);
97 OSStatus RendererCallback3DMixer(uint busNumber, uint numberFrames, AudioBufferList* data)
102 return AudioDataMixerCallback(busNumber, (
int)numberFrames, data);
106 static OSStatus NullRenderCallback (
void *inRefCon,
107 AudioUnitRenderActionFlags *ioActionFlags,
108 const AudioTimeStamp *inTimeStamp,
110 UInt32 inNumberFrames,
111 AudioBufferList *ioData)
113 memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize);
118 static OSStatus DefaultRenderCallbackChannelMixer (
void *inRefCon,
119 AudioUnitRenderActionFlags *ioActionFlags,
120 const AudioTimeStamp *inTimeStamp,
122 UInt32 inNumberFrames,
123 AudioBufferList *ioData)
125 return ((AudioDataRenderer*)inRefCon)->RendererCallbackChannelMixer(inBusNumber, inNumberFrames, ioData);
128 static OSStatus DefaultRenderCallback3DMixer (
void *inRefCon,
129 AudioUnitRenderActionFlags *ioActionFlags,
130 const AudioTimeStamp *inTimeStamp,
132 UInt32 inNumberFrames,
133 AudioBufferList *ioData)
135 return ((AudioDataRenderer*)inRefCon)->RendererCallback3DMixer(inBusNumber, inNumberFrames, ioData);
138 static AURenderCallbackStruct NullRenderCallbackStruct = { NullRenderCallback, NULL };
140 static std::map<uint, AURenderCallbackStruct*> BusIndexToChannelMixerCallbackStructures;
141 static std::map<uint, AURenderCallbackStruct*> BusIndexTo3DMixerCallbackStructures;
143 extern "C" int SetInputRenderCallbackToChannelMixerDefault(
void* inUnit, uint element,
void* userData)
145 AURenderCallbackStruct* pCallbackData =
new AURenderCallbackStruct;
146 pCallbackData->inputProc = DefaultRenderCallbackChannelMixer;
147 pCallbackData->inputProcRefCon = userData;
149 int status = AudioUnitSetProperty((AudioUnit)inUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, element, pCallbackData,
sizeof(AURenderCallbackStruct));
152 if(BusIndexToChannelMixerCallbackStructures.find(element) != BusIndexToChannelMixerCallbackStructures.end())
154 if(BusIndexToChannelMixerCallbackStructures[element] != NULL)
156 delete BusIndexToChannelMixerCallbackStructures[element];
157 BusIndexToChannelMixerCallbackStructures[element] = NULL;
160 BusIndexToChannelMixerCallbackStructures[element] = pCallbackData;
165 extern "C" int SetInputRenderCallbackTo3DMixerDefault(
void* inUnit, uint element,
void* userData)
167 AURenderCallbackStruct* pCallbackData =
new AURenderCallbackStruct;
168 pCallbackData->inputProc = DefaultRenderCallback3DMixer;
169 pCallbackData->inputProcRefCon = userData;
171 int status = AudioUnitSetProperty((AudioUnit)inUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, element, pCallbackData,
sizeof(AURenderCallbackStruct));
174 if(BusIndexTo3DMixerCallbackStructures.find(element) != BusIndexTo3DMixerCallbackStructures.end())
176 if(BusIndexTo3DMixerCallbackStructures[element] != NULL)
178 delete BusIndexTo3DMixerCallbackStructures[element];
179 BusIndexTo3DMixerCallbackStructures[element] = NULL;
182 BusIndexTo3DMixerCallbackStructures[element] = pCallbackData;
187 extern "C" int SetInputRenderCallbackToNull(
void* inUnit, uint element)
189 return AudioUnitSetProperty((AudioUnit)inUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, element, &NullRenderCallbackStruct,
sizeof(AURenderCallbackStruct));