0

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?

Ron Regev
  • 459
  • 2
  • 18

2 Answers2

3

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.

Ron Regev
  • 459
  • 2
  • 18
  • Is there an equivalent to mic.avAudioNode.inputFormat(forBus: 0).sampleRate for AudioKit 4 and macOS? – daxmacrog Nov 11 '20 at 03:04
  • Regarding my above comment, I would still be curious, but I solved my sample rate mismatch errors by migrating to AudioKit 5 Developer branch. It seems I no longer need to set the input sample rate at all (I was hardcoding to 48.0), which is fantastic. I can even switch my active input from 44.1 to 48.0 and vice-versa (via Audio Midi Setup) without a glitch. Thanks AudioKit folks! – daxmacrog Nov 12 '20 at 16:12
  • 1
    @daxmacrog - the equivalent code in my AK4 implementation is: AKSettings.sampleRate = AKManager.engine.inputNode.inputFormat(forBus: 0).sampleRate – Ron Regev Nov 13 '20 at 07:32
0

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
}
ingconti
  • 10,876
  • 3
  • 61
  • 48
  • I am sorry - this does not work for me. Installing AudioKit via SPM (v5-main), and when trying to use AKManager I get "Cannot find 'AKManager' in scope". I just updated the Swift Package to the latest v5-main revision. – Ron Regev Nov 05 '20 at 13:57
  • EDIT: When I first posted the question this did not work, but now AudioEngine (and NOT AKManager) does have inputDevices included. Trying now to figure out how to do what used to be mic.setDevice. – Ron Regev Nov 05 '20 at 14:03
  • very strange I did replace "AUDIIKit" with "AKManager" and my old apps now work fine. – ingconti Nov 05 '20 at 15:38
  • This is true for v4.11 (which compiles fine on Xcode 12), but not v5. – Ron Regev Nov 06 '20 at 08:40