In order to make avaliable playback and recording at the same time we use these methods for setting AVAudioSession
category:
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:NULL];
By doing so, the output audio port switches from line out speaker to built-in speaker. In the loop recording window we need simultaneously working playback from line out speaker and audio recording from microphone. To play sound from line out speaker after setting AVAudioSession
category we use a method for setting output audio port:
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
We try to arrange both recording and playback using AVAudio Engine.
Structure of AVAudioEngine
connections:
// input->inputMixer->mainEqualizer ->tap
// 0 0 |0
// |
// |
// |0 0 0
// recordPlayerNode→recordMixer→meteringMixer→|
// 0 1 0 0 |
// |->mainMixer->out
// |
// volumePlayer→|
// 0 1
After execution overrideOutputAudioPort the recording feature stops working on iPhone 6S and higher. We perform recording in this manner:
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 investigation we have discovered an interesing fact – if
volumePlayer.volume = 1;
when headphones are not connected, then the buffer that comes from microhone starts to fill and the sound keeps recording, but there appears an effect of a very loud sound repetition in the speaker. Otherwise, PCMBuffer
is filled with zeros.
The question is: how can we set AVAudioSession
, or recording process so we could record audio using a microphone and play audio using line out speaker?
P.S. Recording with AVAudioRecorder
works correctly with these settings.