Reputation: 1855
Is it possible to receive audio input from iPhone's built-in microphone, and play that audio through a Bluetooth headset, at the same time?
My goal is to always use the built-in microphone as the input device, even if the output device is a headset, because the built-in microphone is more convenient in my use cases.
I know how to achieve my goal when the output device is a wired headset, like the one that comes bundled with an iPhone. I simply plug the wired headset in, and call the following method:
- (void)selectBuiltInMicrophone
{
AVAudioSession *session = [AVAudioSession sharedInstance];
for (AVAudioSessionPortDescription *port in session.availableInputs)
if ([port.portType isEqualToString:AVAudioSessionPortBuiltInMic]) {
NSError *error;
[session setPreferredInput:port error:&error];
break;
}
}
By calling the above method, the input device will be switched from the wired headset's microphone to iPhone's built-in microphone, while the output device remains unaffected, so the iPhone will record from the built-in microphone and play through the wired headset. This is what I expect.
The problem is, this method does not work when the headset is a Bluetooth one. If I connect a Bluetooth headset to the iPhone, then call the above method, the built-in microphone will becomes the input device, which is great, but the output device will also be changed to iPhone's receiver, which is bad.
It seems that the input and the output of a Bluetooth headset are locked together: you either use both of them, or you use none of them. Is my goal really impossible? Or there exists a way to overcome the apparent limitation?
Upvotes: 9
Views: 6050
Reputation: 103
You can choose a specific microphone while playing audio through a bluetooth audio device.
// set audio session category to .playAndRecord. use do-catch if you need error-handling
try? AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetoothA2DP, .allowBluetooth])
// check if currentRoute is set to a bluetooth audio device
let btOutputTypes: [AVAudioSession.Port] = [.bluetoothHFP, .bluetoothA2DP, .bluetoothLE]
let btOutputs = AVAudioSession.sharedInstance().currentRoute.outputs.filter { btOutputTypes.contains($0.portType) }
// if so, set preferred audio input to built-in mic
if !btOutputs.isEmpty {
let builtInMicInput = AVAudioSession.sharedInstance().availableInputs?.filter { $0.portType == .builtInMic }.first
try? AVAudioSession.sharedInstance().setPreferredInput(builtInMicInput)
} else {
// set default input
try? AVAudioSession.sharedInstance().setPreferredInput(nil)
}
try? AVAudioSession.sharedInstance().setActive(true)
or you can follow detailed instruction from here https://developer.apple.com/library/archive/qa/qa1799/_index.html
EDIT:
It turns out there is easier way to use Built-In Mic as an input while using bluetooth headphone as output.
Just set AVAudioSession's categoryOptions
like this
// allow only A2DP. you may set other mode or options, excluding .allowBluetooth
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [.allowBluetoothA2DP])
By removing .allowBluetooth
from AVAudioSession's categoryOptions
, It won't allow HFP, which is a protocol to use bluetooth device as an input. Thus it will automatically change it's input route to built-in mic.
If you have more than one input (for example, if your device is connected to usbAudio or lineIn input device) you're still gonna need to use setPreferredInput
in order to change your input route to built-in mic.
Upvotes: 4
Reputation:
It is not possible to receive audio input from iPhone's built-in microphone, and play that audio through a Bluetooth headset, at the same time
Upvotes: 4