Record audio using AVAudioEngine with audio output port setting

To make playback and recording available at the same time, we use these methods to set the AVAudioSession category:

 AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:NULL]; 

Thus, the audio output port switches from the line speaker to the built-in speaker. In the loop recording window, we need to simultaneously work with the line speaker and audio recording from the microphone. To play sound from a linear speaker after setting the AVAudioSession category AVAudioSession we use the method for setting the output audio port:

[[AVAudioSession sharedInstance] overrideOutputAudioPort: error AVAudioSessionPortOverrideSpeaker: nil];

We are trying to organize recording and playback using the AVAudio Engine. AVAudioEngine connection AVAudioEngine :

 // input->inputMixer->mainEqualizer ->tap // 0 0 |0 // | // | // |0 0 0 // recordPlayerNode→recordMixer→meteringMixer→| // 0 1 0 0 | // |->mainMixer->out // | // volumePlayer→| // 0 1 

After running overrideOutputAudioPort, the recording function stops working on iPhone 6S and above. We record as follows:

 if(self.isHeadsetPluggedIn) { volumePlayer.volume = 1; } else { volumePlayer.volume = 0.000001; } [volumePlayer play]; [mainEqualizer installTapOnBus:0 bufferSize:0 format:tempAudioFile.processingFormat block:^(AVAudioPCMBuffer *buf, AVAudioTime *when) { if(self.isRecord) { [volumePlayer scheduleBuffer:buf completionHandler:nil]; recordedFrameCount += buf.frameLength; if (self.isLimitedRecord && recordedFrameCount >= [AVAudioSession sharedInstance].sampleRate * 90) { self.isRecord = false; [self.delegate showAlert:RecTimeLimit]; } NSError *error; [tempAudioFile writeFromBuffer:buf error:&error]; if(error) { NSLog(@"Allert while write to file: %@",error.localizedDescription); } [self updateMetersForMicro]; } else { [mainEqualizer removeTapOnBus:0]; [self.delegate recordDidFinish]; callbackBlock(recordUrl); [mainEngine stop]; } }]; 

During the study, we found an interesting fact - if

volumePlayer.volume = 1;

when the headphones are not connected, then the buffer that comes from the microphone starts to fill up and the sound continues to be recorded, but the effect of a very loud repetition of sound appears in the speaker. Otherwise, PCMBuffer is padded with zeros.

Question: how can we set up AVAudioSession or the recording process so that we can record sound using a microphone and play sound using the line speaker?

PS Recording using AVAudioRecorder works correctly with these settings.

+5
source share

Source: https://habr.com/ru/post/1265218/


All Articles