AudioKit v5: How does one choose the microphone?

1.2k views Asked by At

I am trying to update my project to AudioKit v5, using SPM. As far as I can see in the current documentation, you instantiate the microphone by attaching it to the audio engine input.

However, I am missing what used to be AudioKit.inputDevices (and then AKManager.inputDevices). I used to be able to select my microphone of choice.

How does one select a specific microphone using AudioKit v5 on iOS?

2

There are 2 answers

4
ingconti On

the same for audio kit 4..

Apis are changed.

Seems You should write:

guard let inputs = AKManager.inputDevices else{
    print("NO AK INPUT devices")
    return false
}
3
Ron Regev On

As of November 6, 2020, you need to make sure you are using the v5-develop branch, since v5-main still does not support hardware with 48K sample rate.

Here is code that allows you to choose the microphone according to its debug description:

// AudioKit engine and node definitions
let engine = AudioEngine()
var mic : AudioEngine.InputNode!
var boost : Fader!
var mixer : Mixer!

// Choose device for microphone
if let inputs = AudioEngine.inputDevices {
    // print (inputs) // Uncomment to see the possible inputs
    let micSelection : String = "Front" // On a 2020 iPad pro you can also choose "Back" or "Top"
    var chosenMic : Int = 0
    var micTypeCounter : Int = 0
    for microphones in inputs {
        let micType : String = "\(microphones)"
        if micType.range(of: micSelection) != nil {
            chosenMic = micTypeCounter
        }
        // If we find a wired mic, prefer it
        if micType.range(of: "Wired") != nil {
            chosenMic = micTypeCounter
            break
        }
        // If we find a USB mic (newer devices), prefer it
        if micType.range(of: "USB") != nil {
            chosenMic = micTypeCounter
            break
        }
        micTypeCounter += 1
    }
        
    do {
        try AudioEngine.setInputDevice(inputs[chosenMic])
    } catch {
        print ("Could not set audio inputs: \(error)")
    }
    mic = engine.input
}

Settings.sampleRate = mic.avAudioNode.inputFormat(forBus: 0).sampleRate // This is essential for 48Kbps

// Start AudioKit
if !engine.avEngine.isRunning {
    do {
        boost = Fader(mic)
        // Set boost values here, or leave it for silence
        // Connect mic or boost to any other audio nodes you need
      
        // Set AudioKit's output
        mixer = Mixer(boost) // You can add any other nodes to the mixer
        engine.output = mixer

        // Additional settings
        Settings.audioInputEnabled = true

        // Start engine
        try engine.avEngine.start()
        try Settings.setSession(category: .playAndRecord)
    } catch {
        print ("Could not start AudioKit: \(error)")
    }
}

It is advisable to add a notification for audio route changes to viewDidLoad:

// Notification for monitoring audio route changes
NotificationCenter.default.addObserver(
    self,
    selector: #selector(audioRouteChanged(notification:)),
    name: AVAudioSession.routeChangeNotification,
    object: nil)

This will call

@objc func audioRouteChanged(notification:Notification) {
    // Replicate the code for choosing the microphone here (the first `if let` block)
}

EDIT: To clarify, the reason for the selective use of break in the loop is to create a hierarchy of selected inputs, if more than one is present. You may change the order of the inputs detected at your discretion, or add break to other parts of the loop.