'Mic input through headphones and output to iPhone speakers

Is there any way yet of being able to use wired headphones' mic as input and iPhone speakers as output using the high level AVFoundation framework: AVAudioSession, AVAudioPlayerNode, AVAudioEngine? If not then any way by using the low level Core Audio framework?

I tried all that I could so far with AVFoundation using the following:

import UIKit
import AVFoundation

class ViewController: UIViewController, AVAudioRecorderDelegate {

    let audioSession = AVAudioSession.sharedInstance()
    let player = AVAudioPlayerNode()
    let engine = AVAudioEngine()

    override func viewDidLoad() {
        super.viewDidLoad()

        do{
            try audioSession.setCategory(AVAudioSession.Category.playAndRecord, options: [.allowBluetoothA2DP])
            try audioSession.overrideOutputAudioPort(.speaker)
            try audioSession.setMode(.measurement)
            try audioSession.setActive(true)

        } catch{
            print(error.localizedDescription)
        }
        enableHeadsetMic()
        let input = engine.inputNode

        engine.attach(player)

        let bus = 0
        let inputFormat = input.inputFormat(forBus: bus)

        engine.connect(player, to: engine.outputNode, format: inputFormat)

        input.installTap(onBus: bus, bufferSize: 512, format: inputFormat) { (buffer, time) -> Void in
            self.player.scheduleBuffer(buffer)
            print(buffer)
        }
    }

    private func enableHeadsetMic() {
        guard let availableInputs = audioSession.availableInputs,
              let headsetMic = availableInputs.first(where: {$0.portType == .headsetMic })

        else {
            print("The device must have headset microphone.")
            return
        }
        do {
            try audioSession.setPreferredInput(headsetMic)
        } catch {
            print("Error in setting preferred input to headset mic")
        }
    }

    @IBAction func start(_ sender: UIButton) {

        try! engine.start()
        player.play()
        print("started")
    }

    @IBAction func stop(_ sender: UIButton) {
        engine.stop()
        player.stop()
        print("stopped")
    }

}

But this makes the headphone speakers be the speakers, or if I put the enableHeadsetMic() call before the try audioSession.overrideOutputAudioPort(.speaker) then the iPhone mic becomes the mic instead of the headphone mic, so far only the headphones can be mic and speakers, or iPhone can be mic and speakers, but not input from headphones and the output to iPhone.

Another part of the question is: is it possible to have AirPods mic as input and iPhone speaker as output? Someone on a previous stackoverflow post mentioned that by setting options: [.allowBluetoothA2DP] would allow for certain bluetooth mics to be used while playing through iPhone speaker. Is this true? I don't have AirPods to test this out on, but curious if it would work.

And to go back to core audio, is there a way in Core Audio to take input from headphones' mic, and send output to iPhone speakers?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source