我有一个相当复杂的应用程序,到目前为止一直在与AKAppleSequencer一起使用,但是由于某些奇怪的行为以及该音序器不时弹出的错误,我一直希望迁移到较新的AKSequencer。不幸的是,新的音序器似乎没有出现在Playgrounds或大量文档中,因此我一直在做一些猜测。我已经按照似乎合理的方式进行了所有连接,并且正如我提到的那样,与AKAppleSequencer可以正常工作,但是与AKSequencer一起运行时,却没有任何输出。
我的代码结构被分解为多个部分,因此节点图在不同的位置建立,因此,我必须在这里以大块的形式显示它,并删除不相关的行。
// This happens during setup
mainMixer = AKMixer()
mainMixer.volume = volume
AudioKit.output = mainMixer
// In later code, the sequencer is constructed
sequencer = AKSequencer()
sequencer!.tempo = tempo
// After the sequencer is created, I create various nodes and tracks, like this
let trackNode = trackDefinition.createNode()
let track = sequencer.addTrack(for: trackNode)
track >>> mainMixer
那里有一行,我在名为trackDefinition的东西上调用“ createNode()”。我认为该类的细节在这里不相关,但是这是该方法代码主体的示例。非常简单。
func createNode() -> AKNode {
let pad = AKMIDISampler()
do {
try pad.loadSoundFont(partConfiguration.settings["soundFontName"]!,
preset: Int(partConfiguration.settings["preset"]!)!,
bank: Int(partConfiguration.settings["bank"]!)!)
} catch {
print("Error while loading Sound Font in PadTrackDefinition: \(error)")
}
return pad
}
该代码似乎运行正常。我只是想说明一下,我正在创建一个AKMIDISampler节点,加载一个声音字体,然后使用该节点在AKSequencer中创建一个轨道。然后,将音轨附加到主混音器上以进行输出。
我使用AudioKit.printConnections()获得了一些确认,这就是下面的样子。
(1]AUMultiChannelMixer <2 ch, 44100 Hz, Float32, non-inter> -> (0]AudioDeviceOutput) bus: 0
(2]Local AKSequencerTrack <2 ch, 44100 Hz, Float32, non-inter> -> (1]AUMultiChannelMixer) bus: 0
非常简单... 跟踪>>>混音器>>>输出播放时不发出声音。
我也这样尝试过:
(0]AUSampler <2 ch, 44100 Hz, Float32, non-inter> -> (2]AUMultiChannelMixer) bus: 0
(2]AUMultiChannelMixer <2 ch, 44100 Hz, Float32, non-inter> -> (1]AudioDeviceOutput) bus: 0
因此是AKMIDISampler >>>混音器>>>输出(并且采样器用于创建轨道)。这也没有任何声音。
我在StackOverflow上也看到了类似问题的this answer,因此我尝试了这种方法。这给了我这个连接图:
(0]AUMultiChannelMixer <2 ch, 44100 Hz, Float32, non-inter> -> (1]AudioDeviceOutput) bus: 0
(2]Local AKSequencerTrack <2 ch, 44100 Hz, Float32, non-inter> -> (0]AUMultiChannelMixer) bus: 0
(3]AUSampler <2 ch, 44100 Hz, Float32, non-inter> -> (0]AUMultiChannelMixer) bus: 1
将是[AKMIDISampler,Track] >>> Mixer >>> Output。仍然...没有声音。
我在这里做错了什么?是否有一些更特定的方法将新的音序器轨道连接到我不了解的信号图中?
UPDATE:奇怪/有趣/有趣的附录,如果我在节点构造代码之后立即添加此代码,它将产生预期的音符,因此我知道至少音频引擎本身已连接:
let midiNode = trackNode as! AKMIDISampler
try! midiNode.play(noteNumber: 60,
velocity: MIDIVelocity(127),
channel: MIDIChannel(8))
我想出了这一点,并希望在此处将答案发布给可能对此感到困惑的未来开发人员,以及让AudioKit核心团队了解的内容,以便他们可以理解API中可能不明显的内容。
这里的问题根源是,尽管两者的API极为相似,但AKSequencer是not的替代品AKAppleSequencer。
需要指出的一点:我已经确认,实际上有必要将轨道本身和轨道的目标节点都添加到信号链中,以获取声音输出。因此,从上面的示例中,您需要以下示例:[[AKMIDISampler,Track] >>>混音器>>>输出
这有点怪异和令人困惑,因为要在它们之间放置效果节点根本不清楚。我还没有玩过,但是让这些节点都成为信号链中的兄弟姐妹似乎很奇怪。我认为它看起来像这样:Track >>> AKMIDISampler >>>混音器>>>输出
对我来说更有意义。哦,很好。
无论如何,我提到其他一些因素是问题的根源。关键区别在于,使用AKAppleSequencer,音轨长度可以从0开始,然后随着向其添加其他音符而增加。这是我使用的方法,因为我从空轨道开始,然后按程序填充它们。
使用new AKSequencer,它似乎无法正常工作。长度开始为4.0,而不是0,并且在向轨道添加注释时不会自动增长。我必须手动计算适合音符的长度,然后使用track.length = desiredLength
设置该长度。好消息是,AKSequencer能够理解使用轨道的长度,因此您可以仅在轨道上设置它,而不是在音序器本身上进行设置。
[另一个值得注意的区别是stop()
在定序器上的行为。在AKAppleSequencer上,调用stop()
也会停止所有音符的播放。在新的AKSequencer上,相同的方法将使音符继续演奏。您需要像这样在轨道上循环:
sequencer.stop()
for track in sequencer.tracks {
track.stopPlayingNotes()
}
我知道AKSequencer是全新的,所以可以预料到这样的事情。从长远来看,我仍然希望它会比AKAppleSequencer更好。
我希望这种解释能帮助像我这样的人,他们陷入了切换到新音序器的困扰!