Try
OSStatus propertySetError = 0;
UInt32 allowMixing = true;
propertySetError = AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryMixWithOthers, // 1
sizeof (allowMixing), // 2
&allowMixing // 3
);
Or you can use kAudioUnitType_Mixer type AudioUnit.
AudioComponentDescription MixerUnitDescription;
MixerUnitDescription.componentType = kAudioUnitType_Mixer;
MixerUnitDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer;
MixerUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
MixerUnitDescription.componentFlags = 0;
MixerUnitDescription.componentFlagsMask = 0;
Add them(mixer_unit,voice_processing_unit) into a AUGraph. set input bus count 2 for mixer unit.
UInt32 busCount = 2; // bus count for mixer unit input
status = AudioUnitSetProperty (mixer_unit,
kAudioUnitProperty_ElementCount,
kAudioUnitScope_Input,
0,
&busCount,
sizeof(busCount)
);
Add render callback for each bus of mixer_unit:
for (UInt16 busNumber = 0; busNumber < busCount; ++busNumber) {
AURenderCallbackStruct inputCallbackStruct;
inputCallbackStruct.inputProc = &VoiceMixRenderCallback;
inputCallbackStruct.inputProcRefCon = self;
status = AUGraphSetNodeInputCallback (_mixSaveGraph,
mixerNode,
busNumber,
&inputCallbackStruct
);
if (status) { printf("AudioUnitSetProperty set callback"); return NO; }
}
Connect the mixer_unit's output bus to io_unit's input bus:
status = AUGraphConnectNodeInput (_mixSaveGraph,
mixerNode, // source node
0, // source node output bus number
saveNode, // destination node
0 // desintation node input bus number
);
Start the graph , u'll get reader call back with different Bus number (0 and 1) , like this:
static OSStatus VoiceMixRenderCallback(void * inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData )
{
OSStatus status;
AURecorder *recorder = (AURecorder*)inRefCon;
if (inBusNumber == BUS_ONE && (recorder.isMusicPlaying)) {
//Get data from music file. try ExtAudioFileRead
} else if (inBusNumber == BUS_TWO) {
status = AudioUnitRender(recorder.io_unit, ioActionFlags, inTimeStamp, INPUT_BUS, inNumberFrames, ioData);
//Get data from io unit's input bus.
if (status)
{
printf("AudioUnitRender for record error");
*ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
}
} else {
*ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
}
return noErr;
}