AudioKit / AudioKit

Audio synthesis, processing, & analysis platform for iOS, macOS and tvOS
http://audiokit.io
MIT License
10.63k stars 1.55k forks source link

AKAppleSequencer lag/stutter in the first notes #1920

Closed frankiesimon closed 4 years ago

frankiesimon commented 4 years ago

I'm using AudioKit 4.9.1 with XCode 11.1, MacOS Mojave 10.14.6 (18G87).

I had a problem with playing MIDI using AKAppleSequencer, it seemed like the first couple of MIDI notes sounded a bit too close together.

This luckily reproduces even in the Playgrounds, Drum Sequencer. Start the sound and you'll hear in the first loop iteration the first drum and hihat are slightly closer together than in the subsequent loops. If you start/stop a few times you'll hear it.

I found this relevant SO question: https://stackoverflow.com/a/52309782/336702

The people who answered considered this to be a start-up lag but based on the original poster's answer this seems to be related to the next notes playing too early rather than having the first one delayed. And I'm not sure I understand how to implement the workaround he suggested anyway.

Please let me know if I can provide more information.

aure commented 4 years ago

This is a long standing bug in Apple's sequencer and since that is closed source we had to write our own. My suggestion is to switch to AKSequencer. I have.

frankiesimon commented 4 years ago

I would be happy to but there is no playground or sample of how to use it in a simple scenario, like connecting to a sampler and playing a MIDI file. Also I couldn't use the callback instrument and there is no way to add tracks.

aure commented 4 years ago
open func addTrack(for node: AKNode) -> AKSequencerTrack {
    let track = AKSequencerTrack(targetNode: node)
    tracks.append(track)
    return track
}
aure commented 4 years ago

I'll work on the playgrounds

frankiesimon commented 4 years ago

I understand this function was added in 4.9.2 but I have to say with XCode 11.1 so I can't upgrade yet.

I initialize AKSequencer with my MIDI file but something is wrong with my signal chain since I'm not hearing sounds, regardless of whether I'm using AKSampler or AKAppleSampler.

I wrote this class to wrap loading a MIDI and playing different ranges of it.

class MIDIPlayer {
    var sampler: AKSampler
    var legacySampler: AKAppleSampler
    var sequencer: AKSequencer

    init(withSfz sfz: String, orSf2 sf2: String) {

        self.sampler = AKSampler()
        self.legacySampler = AKAppleSampler()
        try? legacySampler.loadSoundFont(sf2, preset: 0, bank: 0)
        sampler.loadSFZ(url: Bundle.main.url(forResource: sfz, withExtension: "sfz")!)

        AudioKit.output = sampler
        try? AudioKit.start()
        // Is this the right way to connect the sequencer to the sampler?
        sequencer = AKSequencer(targetNode: sampler)
//        sequencer = AKSequencer(targetNode: legacySampler)
    }

    func setupMIDIFile(_ midiFile: String) {
        if (sequencer.isPlaying) {
            sequencer.stop()
        }
        let midi = AKMIDIFile(url: Bundle.main.url(forResource: midiFile, withExtension: "mid")!)
        sequencer.load(midiFile: midi)
    }

    func play() {
        sequencer.stop()
        sequencer.playFromStart()
    }

    func playBeatRange(from startTime: Float64, to endTime: Float64) {
        sequencer.stop()
        sequencer.length = endTime
        sequencer.playAfterDelay(beats: startTime)
    }

    func isPlaying() -> Bool {
        return sequencer.isPlaying
    }

    func stop() {
        sequencer.stop()
    }
}

Am I missing something obvious in the initialization?

aure commented 4 years ago

I believe your answer is now on https://stackoverflow.com/questions/58833495/how-to-play-midi-with-audiokits-new-aksequencer/58863420#58863420

frankiesimon commented 4 years ago

Thank you for responding! Unfortunately that doesn't work (I am getting a compilation error: Cannot convert value of type 'AKSequencer' to expected argument type 'AKNode?')

I'm sorry to continue the discussion here I am not sure if comments on questions are with notifications.

aure commented 4 years ago

I updated the answer.