AudioKit Conflict between Midi Instrument and Mic behavior

Viewed 36

I am trying to make my app produce midi notes at the same time listening to the input from the mic:

var engine = AudioEngine()
var initialDevice: Device!

var mic: AudioEngine.InputNode!
var tappableNodeA: Fader!
var tappableNodeB: Fader!
var tappableNodeC: Fader!
var silence: Fader!

var tracker: PitchTap! 
private var instrument = MIDISampler(name: "Instrument 1")

func noteOn(note: MIDINoteNumber) {
    instrument.play(noteNumber: note, velocity: 90, channel: 0)
}

func noteOff(note: MIDINoteNumber) {
    instrument.stop(noteNumber: note, channel: 0)
}
override func viewDidLoad() {
    super.viewDidLoad()
    
    print("init started ")
    guard let input = engine.input else { fatalError() }

    guard let device = engine.inputDevice else { fatalError() }
    print("input selected")
    initialDevice = device
    engine.output = instrument
    mic = input
    tappableNodeA = Fader(mic)
    tappableNodeB = Fader(tappableNodeA)
    tappableNodeC = Fader(tappableNodeB)
    silence = Fader(tappableNodeC, gain: 0)
    engine.output = silence
    print("objects init")
    tracker = PitchTap(mic) { pitch, amp in
        DispatchQueue.main.async {
            self.update(pitch[0], amp[0])
        }
    }
    start()
    // other init that are not related        
}

The start function is written below:

func start() {
    
    do {
        if let fileURL = Bundle.main.url(forResource: "Sounds/Sampler Instruments/sawPiano1", withExtension: "exs") {
            try instrument.loadInstrument(url: fileURL)
        } else {
            Log("Could not find file")
        }
    } catch {
        Log("Could not load instrument")
    }


do {
        try engine.start()
        tracker.start()
    } catch let err {
        print("caught error at start")
        Log(err)
    }
}

As long as I making the first try call to set up the instrument I get the following error:

*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: _engine != nil

Why the would the condition be false?

1 Answers

Ok, so the solution was to separate the calls into two functions, and position the first call before tapNode configuration:

var engine = AudioEngine()
var initialDevice: Device!

var mic: AudioEngine.InputNode!
var tappableNodeA: Fader!
var tappableNodeB: Fader!
var tappableNodeC: Fader!
var silence: Fader!

var tracker: PitchTap! 
private var instrument = MIDISampler(name: "Instrument 1")

func noteOn(note: MIDINoteNumber) {
    instrument.play(noteNumber: note, velocity: 90, channel: 0)
}

func noteOff(note: MIDINoteNumber) {
    instrument.stop(noteNumber: note, channel: 0)
}
override func viewDidLoad() {
    super.viewDidLoad()
    
    print("init started ")
    guard let input = engine.input else { fatalError() }

    guard let device = engine.inputDevice else { fatalError() }
    print("input selected")
    initialDevice = device
    engine.output = instrument
    start1()
    mic = input
    tappableNodeA = Fader(mic)
    tappableNodeB = Fader(tappableNodeA)
    tappableNodeC = Fader(tappableNodeB)
    silence = Fader(tappableNodeC, gain: 0)
    engine.output = silence
    print("objects init")
    tracker = PitchTap(mic) { pitch, amp in
        DispatchQueue.main.async {
            self.update(pitch[0], amp[0])
        }
    }
    start()
    // other init that are not related        
}


func start1(){
    do {

        if let fileURL = Bundle.main.url(forResource: "Sounds/Sampler Instruments/sawPiano1", withExtension: "exs") {
            try instrument.loadInstrument(url: fileURL)

        } else {
            Log("Could not find file")
        }
    } catch let err {
        Log("Could not load instrument")
        Log(err)
    }

}
func start() {
  
    do {
        try engine.start()
        tracker.start()
    } catch let err {
        print("caught error at start")
        Log(err)
    }
    
}

Although the exception is now gone, there is still no sound being played for some reason.

Related