I am working on an iOS app for mixing an audio file with the user's voice input into a new file, and playing the content of this audio file simultaneously. You can just consider this app as a Karaoke player which records both the singer’s voice and the original soundtrack into file while playing the original soundtrack for the singer.
I use AUGraph to establish the audio process flow as:
- One mixer AudioUnit (with type kAudioUnitType_Mixer and subtype kAudioUnitSubType_MultiChannelMixer) with 2 inputs;
- One resampler AudioUnit for necessary sample rate converting( kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter) from the sample rate of the audio file to that of the mic input in order to make formats of the mixer's 2 input buses match;
- Then connect these nodes: Mic’s output(output element of IO node's input scope) —> Mixer’s input 0, Resampler’s input —> Mixer’s input 1, Mixer’s output —> Speaker’s input(input element of IO node's output scope);
- Set a render callback to the resampler by AUGraphSetNodeInputCallback(). This callback function just copies demanded number of audio data frames from the source audio file stream to the destination AudioBufferList, so that the sound is played by the speaker;
- Set a render notify callback to the mixer by AudioUnitAddRenderNotify(). The callback function pulls the mixed audio data and writes it into the destination file.
This process flow works well, but with a fault: It plays the audio mixed with the mic input to the speaker, which is not desired. What I need is to play only the sound from the source audio file data to the speaker, without the singer's voice mixed. The mixed audio is for recording only, not for playback.
I’ve tried several modifications to the above AUGraph, but no one works. An instinctive thought is to use a ’splitter’ audio unit to duplicate resampler’s output audio data into 2 streams, one connected to the mixer’s input and another to the input component of IO node’s output scope(i.e., the speaker's input bus). However, as Apple mentioned in AUComponent.h,
" Except for AUConverter, which is available on both desktop and iPhone, these audio units are only available on the desktop.”
That means we can’t use AudioUnit either with subtype kAudioUnitSubType_Splitter or kAudioUnitSubType_MultiSplitter on iOS.
Actually I’ve tried adding an AudioUnit with subtype kAudioUnitSubType_MultiSplitter and constructing the AUGraph as I thought, and of course with no miracle.
So how should I implement this feature?