首页 > 解决方案 > 更改 AKSequencer 的长度:奇怪的行为

问题描述

我有一个启用循环的 aksequencer,我想在播放期间更改长度。我已经用 setLength() 和 setLoopInfo() 试过了,但似乎都没有正常工作。

预期行为:如果我有一个 16 拍序列,并且我调用 changeSequenceToLength(12),我希望循环从 1-12 拍开始播放,然后重复。(当然,我应该处理在节拍 12 之后更改长度的情况,但你明白了)。

实际行为:鱼龙混杂。当我使用 setLength(endbeat) 时,它只是删除了 endbeat 之后的 midi 事件,但循环仍然是 16 个节拍。当我调用 setLoopInfo(duration, numloops) 时,它会缩短循环,但从错误的一侧。所以不是打1-12,而是打4-16。当我第一次更改循环持续时间时,它也会出现一些奇怪的口吃。

任何有关如何解决此问题的建议将不胜感激!我也查看了支持苹果 MusicSequence 的文档,但它非常稀疏。

我的代码大致如下:

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)
    }
}

编辑:所以我找到了 AKMusicTrack.setLengthSoft(),所以当我缩短序列时,我的 midi 序列不会被删除。我还阅读了 setLoopInfo 的代码,它确实应该从末端向后创建一个循环(它不应该需要一个 startTime 和偏移量吗??)。但是当我更改序列长度时,我仍然遇到播放口吃​​的问题。

标签: audiokit

解决方案


调用后,setLength()您需要通过调用重新断言循环行为enableLooping()(或者您可以使用setloopInfowhich 将在一个步骤中完成)。但基本上在音序器运行时改变循环长度将是一个问题。

重要的是要理解它AKSequencer本质上是一个围绕 CoreMIDI 的 Swift 包装器MusicSequence,所以它基本上继承了MusicSequence's 的大部分怪癖和限制。其中一个限制是,虽然您可以设置循环范围的“左侧”,但不能设置“右侧” - 它总是会循环回 MusicTimeStamp 0。调用setLoopinfo(或者调用setLength()后跟enableLooping())实际上并没有如您所说,从错误的一侧缩短循环(尽管起初我也认为它正在这样做)。它正确设置了循环长度,但也将播放头传送到“新循环长度”节拍远离“旧循环长度”的位置。因此,如果您将 16 拍循环更改为 12 拍循环,则MusicSequence将从 0 循环到 12,但它会将播放头移动到节拍 4 (16 - 12 = 4)。它不会从 4 播放到 16,而是从 4 播放到 12,它们从 0 循环到 12。有时你可以解决这个问题,你可以在播放时让它工作,但大多数情况下这有点痛苦。最好的解决方案是在更改循环长度时停止播放。CoreMIDI'aMusicSequence不太擅长动态处理变化。


推荐阅读