Audio recording using AVAudioEngine with setting output audio port
Asked Answered
A

0

8

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.

Acyl answered 9/3, 2017 at 8:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.