Recording only incoming input microphone while players are running.

Hi all,

I'm playing lots of audio files with AVAudioPlayerNode. While the players are running I start recording.

But recording file mixing all of the audio incoming players+microphone input. I want to isolated input stream,i want to record only mic input.

Is it possible to record only incoming built in microphone when built speaker is running?

How can i isolated input from mic and players output?


My sample code block:


_engine = [[AVAudioEngine alloc] init];

_inputNode= _engine.inputNode;

_outputNode = _engine.outputNode;

_recordingMixer = [[AVAudioMixerNode alloc] init];

[_engine attachNode:_player];

[_engine attachNode:_player1];

[_engine attachNode:_player2];

AVAudioFormat *stereoFormat = [amenFile processingFormat];

AVAudioFormat *stereoFormat1 = [bassFile processingFormat];

AVAudioFormat *stereoFormat2 = [pianoFile processingFormat];

NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:

[NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,

[NSNumber numberWithFloat:44100.0], AVSampleRateKey,

[NSNumber numberWithInt: 2], AVNumberOfChannelsKey,

nil];

_recordingFormat = [[AVAudioFormat alloc] initWithSettings:recordSettings];

AVAudioMixerNode *mainMixer = [_engine mainMixerNode];

/

[_engine connect:_player to:mainMixer format:stereoFormat];

[_engine connect:_player1 to:mainMixer format:stereoFormat1];

[_engine connect:_player2 to:mainMixer format:stereoFormat2];



NSError *error;

if (!_mixerOutputFileURL) _mixerOutputFileURL = [NSURL URLWithString:[NSTemporaryDirectory() stringByAppendingString:@"mixerOutput.m4a"]];

AVAudioMixerNode *mainMixer = [_engine mainMixerNode];

AVAudioFile *mixerOutputFile = [[AVAudioFile alloc] initForWriting:_mixerOutputFileURL settings:_recordingFormat.settings error:&error];

NSAssert(mixerOutputFile != nil, @"mixerOutputFile is nil, %@", [error localizedDescription]);

[_inputNode installTapOnBus: 0 bufferSize:4096 format:[_inputNode inputFormatForBus:0] block:^(AVAudioPCMBuffer *bufferTwo, AVAudioTime *when) {

NSError *error;

NSAssert([mixerOutputFile writeFromBuffer:bufferTwo error:&error], @"error writing buffer two data to file, %@", [error localizedDescription]);

}];

[self startEngine];

_isRecording = YES;

Replies

I think the concept you are looking for is acoustic echo cancelation, which is enabled by using the VoiceProcessingIO Audio Unit.


Another method of isolation is physical separation, where you move the microphone far enough away from the speaker that the microphone no longer can pick up a significant amount of any sound produced by the speaker. Plugging in and using an external headset might do this.

The AUVoiceProcessing unit (kAudioUnitSubType_VoiceProcessingIO) can do this even when using the build in mic / speakers, but unfortunately you cannot currently replace the RemoteI/O instance which is used with the AVAudioEngine.

Hello theanalogkid,

is it still not possible in iOS 12?

I'm also wondering if there is an update on this. With the deprecation of AUGraph, it would be nice to be able to use the VoiceProccessingIO unit with AVAudioEngine.


I'm currently rewriting the audio engine on a VoIP app, and I'm using AUGraph and v2 AudioUnits because they are the only APIs that support the VPIO unit, but I'm kind of banking on the fact that these deprecated APIs won't be removed soon. Is this still the recommended approach for VoIP apps?