Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVAudioUnitSampler generates sinewaves after headphones route change, iOS 11 iPhone

I'm facing a strange issue on iPhone (iOS 11) when using AVAudioUnitSampler.

Let's say I have a AVAudioUnitSampler initialised with a piano sound. So, every time that I connect or disconnect the headphones I hear the piano sound plus a sinewave tone added to it, which gets louder the more times I connect/disconnect the headphones.

So, to me it feels as if every time that the headphones are plugged/un-plugged, a new audio unit sampler would be internally attached to the sound output (and, since it is un-initialised, it generates just sinewave tones).

The following class already shows the problem. Note that I'm using AudioKit to handle MIDI signals and trigger the sampler (although on that end everything seem to work fine, ie. startNote() and stopNote() get called properly):

class MidiController: NSObject, AKMIDIListener {

    var midi = AKMIDI()
    var engine = AVAudioEngine()
    var samplerUnit = AVAudioUnitSampler()

    override public init() {
        super.init()

        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleRouteChange),
            name: .AVAudioSessionRouteChange,
            object: nil)

        midi.openInput()
        midi.addListener(self)
        engine.attach(samplerUnit)
        engine.connect(samplerUnit, to: engine.outputNode)
        startEngine()
    }

    func startEngine() {
        if (!engine.isRunning) {
            do {
                try self.engine.start()
            } catch  {
                fatalError("couldn't start engine.")
            }
        }
    }

    @objc func handleRouteChange(notification: NSNotification) {
        let deadlineTime = DispatchTime.now() + .milliseconds(100)
        DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
            self.startEngine()
        }
    }

    func receivedMIDINoteOn(noteNumber: MIDINoteNumber, velocity:MIDIVelocity, channel: MIDIChannel) {
        if velocity > 0 {
            samplerUnit.startNote(noteNumber: noteNumber, velocity: 127, channel: 0)
        } else {
            samplerUnit.stopNote(noteNumber: noteNumber, channel: 0)
        }
    }

    func receivedMIDINoteOff(noteNumber: MIDINoteNumber, velocity: MIDIVelocity, channel: MIDIChannel) {
        samplerUnit.stopNote(noteNumber: noteNumber, channel: 0)
    }
}

I have forked AudioKit and replaced the HelloWorld example with a minimal project with which I can reproduce this problem.

Also, I couldn't reproduce this problem on iPad under both iOS 9.3 and 11, so this might be an iPhone-specific problem.

Any help or suggestion on how to continue debugging this would be very welcome, I'm quite puzzled with this and I'm not really an expert on iOS audio development.

Thanks!

like image 529
Eloi Marin Avatar asked Oct 28 '22 23:10

Eloi Marin


1 Answers

You might try checking to see if the engine is started in handleRouteChange and then bounce it if it is instead of just starting it. Let us know if that works.

like image 106
Gene De Lisa Avatar answered Nov 11 '22 15:11

Gene De Lisa