Изменить длину AKSequencer: странное поведение - PullRequest
0 голосов
/ 02 июня 2018

У меня есть aksequencer с поддержкой петель, и я хочу изменить длину во время воспроизведения.Я пробовал это с setLength () и setLoopInfo (), но ни один из них, кажется, не работает правильно.

Ожидаемое поведение: если у меня есть 16-битная последовательность, и я вызываю changeSequenceToLength (12), я ожидаюЦикл, чтобы играть от ударов 1-12, и повторите.(конечно, я должен разобраться со случаем, когда я изменяю длину после удара 12, но вы понимаете).

Фактическое поведение: смешанная сумка.Когда я использую setLength (endbeat), он просто удаляет события midi после endbeat, но цикл все равно 16 ударов.Когда я вызываю setLoopInfo (duration, numloops), он сокращает цикл, но не с той стороны.Таким образом, вместо 1-12, он играет 4-16.Это также делает странное заикание, когда я впервые изменяю длительность цикла.

Любые предложения о том, как подойти к этому, будут высоко оценены!Я также посмотрел документы для поддержки MusicSequence для Apple, но он довольно скудный.

Мой код выглядит примерно так:

import AudioKit
import AudioKitUI

final class Sequencer: AKSequencer {
    static let shared = Sequencer() //Singleton

    var numBeats = 16 // Number of spaces in the grid
    var beatLength = 1/4.0
    var sequenceDuration: AKDuration {
        get {
            return AKDuration(beats: (numBeats * beatLength))
        }
    }

    private override init() {
        super.init()
        setTempo(120.0)
        for _ in 0..<8 {
            let track = newTrack()
        }
        let callback = AKCallbackInstrument() { status, note, velocity in
            //send midi messages...
        }
        let midiNode = AKMIDINode(node: callback)
        setLength(sequenceDuration)
        AudioKit.output = midiNode
        AudioKit.start()
        midiNode.enableMIDI(Midi.shared.client, name: "midiNode midi in")
        enableLooping()
    }

    func changeSequenceToLength(length: Int) {
        numBeats = length
        setLength(sequenceDuration)
        //  setLoopInfo(sequenceDuration, numberOfLoops: 50)
    }
}

edit: Итак, я нашел AKMusicTrack.setLengthSoft (), поэтому моя последовательность миди не удаляется, когда я укорачиваю последовательность.Я также прочитал код для setLoopInfo, и он действительно должен создавать цикл от конца назад (не должен ли он принимать startTime и смещение ??).Но у меня все еще возникают проблемы с заиканием воспроизведения при изменении длины последовательности.

1 Ответ

0 голосов
/ 02 июня 2018

После того, как вы позвоните setLength(), вам нужно заново заявить о циклическом поведении, вызвав enableLooping() (или вы можете использовать setloopInfo, что сделает оба за один шаг).Но в основном изменение длины цикла во время работы секвенсора будет проблемой.

Важно понимать, что AKSequencer - это, по сути, оболочка Swift вокруг CoreMIDI MusicSequence, поэтому она в основном наследует большую часть MusicSequence 'Причуды и ограничения.Одним из этих ограничений является то, что, хотя вы можете установить «левую сторону» диапазона цикла, вы не можете установить «правую сторону» - он всегда будет возвращаться к MusicTimeStamp 0. Вызов setLoopinfo (или альтернативный вызов setLength() с последующимна enableLooping()) фактически не укорачивает цикл с той стороны, как вы говорите (хотя я тоже думал, что сначала это было так).Он правильно устанавливает длину цикла, но также телепортирует точку воспроизведения в положение, которое «новая длина цикла» отбивает от «старой длины цикла».Поэтому, если вы измените цикл с 16 ударами на цикл с 12 ударами, MusicSequence будет повторять цикл от 0 до 12, но переместит точку воспроизведения на 4 (16 - 12 = 4).Он не будет воспроизводиться с 4 до 16, но с 4 до 12, их цикл от 0 до 12. Иногда вы можете обойти это , вы можете сделать эту работу во время игры, но в основном это своего родаболь.Лучшее решение - остановить воспроизведение при изменении длины цикла.CoreMIDI'a MusicSequence не очень хорошо справляется с динамическими изменениями.

...