Two-channel recording on the iPhone/iPad: headset

2019-05-07 03:07发布

问题:

For an app, we have a requirement to record from two different audio sources. One mic is a special (throat) mic and it comes with the same connector that the iPhone headset with mic uses.

On a second channel, we would like to record the ambient sounds and the best thing would be if we could just record from the iPhone's/iPad's built-in mic at the same time as we record from the throat mic headset.

Is there any way this is possible? Any other tips?

回答1:

The OS currently only allows an app to connect to one audio source route at a time. The only way to record 2-channels on a stock iOS device is by using an Aple USB to Lightning connector (Camera Connection kit on older models) with a standard USB stereo ADC or an audio mixing panel which has multiple mic inputs.



回答2:

I have found some FAQ on Apple library about how to choose data source from different microphone port, maybe these will be helpful:

https://developer.apple.com/library/ios/qa/qa1799/_index.html

iOS 7 offers developers more flexibility in terms of selecting specific built-in microphones.

Using APIs introduced in iOS 7, developers can perform tasks such as locating a port description that represents the built-in microphone, locating specific microphones like the "front", "back" or "bottom", setting your choice of microphone as the preferred data source, setting the built-in microphone port as the preferred input and even selecting a preferred microphone polar pattern if the hardware supports it. See AVAudioSession.h.

Listing 1 demonstrates how applications can find the AVAudioSessionPortDescription that represents the built-in microphone, locate the front microphone (on iPhone 5 or another device that has a front facing microphone), set the front microphone as the preferred data source and set the built-in microphone port as the preferred input.

Listing 1  Demonstrate Input Selection.

#import <AVFoundation/AVAudioSession.h>
- (void) demonstrateInputSelection
{
    NSError* theError = nil;
    BOOL result = YES;
    AVAudioSession* myAudioSession = [AVAudioSession sharedInstance];
    result = [myAudioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&theError];
    if (!result)
    {
        NSLog(@"setCategory failed");
    }
    result = [myAudioSession setActive:YES error:&theError];
    if (!result)
    {
        NSLog(@"setActive failed");
    }
    // Get the set of available inputs. If there are no audio accessories attached, there will be
    // only one available input -- the built in microphone.
    NSArray* inputs = [myAudioSession availableInputs];
    // Locate the Port corresponding to the built-in microphone.
    AVAudioSessionPortDescription* builtInMicPort = nil;
    for (AVAudioSessionPortDescription* port in inputs)
    {
        if ([port.portType isEqualToString:AVAudioSessionPortBuiltInMic])
        {
            builtInMicPort = port;
            break;
        }
    }
    // Print out a description of the data sources for the built-in microphone
    NSLog(@"There are %u data sources for port :\"%@\"", (unsigned)[builtInMicPort.dataSources count], builtInMicPort);
    NSLog(@"%@", builtInMicPort.dataSources);
    // loop over the built-in mic's data sources and attempt to locate the front microphone
    AVAudioSessionDataSourceDescription* frontDataSource = nil;
    for (AVAudioSessionDataSourceDescription* source in builtInMicPort.dataSources)
    {
        if ([source.orientation isEqual:AVAudioSessionOrientationFront])
        {
            frontDataSource = source;
            break;
        }
    } // end data source iteration
    if (frontDataSource)
    {
        NSLog(@"Currently selected source is \"%@\" for port \"%@\"", builtInMicPort.selectedDataSource.dataSourceName, builtInMicPort.portName);
        NSLog(@"Attempting to select source \"%@\" on port \"%@\"", frontDataSource, builtInMicPort.portName);
        // Set a preference for the front data source.
        theError = nil;
        result = [builtInMicPort setPreferredDataSource:frontDataSource error:&theError];
        if (!result)
        {
            // an error occurred. Handle it!
            NSLog(@"setPreferredDataSource failed");
        }
    }
    // Make sure the built-in mic is selected for input. This will be a no-op if the built-in mic is
    // already the current input Port.
    theError = nil;
    result = [myAudioSession setPreferredInput:builtInMicPort error:&theError];
    if (!result)
    {
        // an error occurred. Handle it!
        NSLog(@"setPreferredInput failed");
    }
}

Listing 1 will produce the following console output when run on an iPhone 5:

There are 3 data sources for port :"<AVAudioSessionPortDescription: 0x14d935a0, type = MicrophoneBuiltIn; name = iPhone Microphone; UID = Built-In Microphone; selectedDataSource = Bottom>"
(
    "<AVAudioSessionDataSourceDescription: 0x14d93800, ID = 1835216945; name = Bottom>",
    "<AVAudioSessionDataSourceDescription: 0x14d938d0, ID = 1835216946; name = Front>",
    "<AVAudioSessionDataSourceDescription: 0x14d93a10, ID = 1835216947; name = Back>"
)
Currently selected source is "Bottom" for port "iPhone Microphone"
Attempting to select source "<AVAudioSessionDataSourceDescription: 0x14d938d0, ID = 1835216946; name = Front>" on port "iPhone Microphone”

UPDATE 14 Nov

Use the code in the front I can set the specific built-in mic on iPhone to record sound, now I’m trying to change the specific mic on iPhone frequently to simulate a stereo record.