gpt4 book ai didi

audio - AKSequencer 中播放的第一个音符已关闭

转载 作者:行者123 更新时间:2023-12-01 08:57:36 25 4
gpt4 key购买 nike

我正在使用 AKSequencer 创建一系列由 AKMidiSampler 播放的音符。我的问题是,无论我做什么,在更高的速度下,第一个音符总是有一点延迟。

我试过预滚动序列,但无济于事。用 AKSampler 或 AKSamplePlayer 替换 AKMidiSampler(并使用回调轨道播放它们)也无济于事,尽管这让我认为问题可能出在音序器或我创建音符的方式上。

这是我正在做的一个例子(我试图让它尽可能简单):

import UIKit
import AudioKit

class ViewController: UIViewController {

let sequencer = AKSequencer()
let sampler = AKMIDISampler()
let callbackInst = AKCallbackInstrument()

var metronomeTrack : AKMusicTrack?
var callbackTrack : AKMusicTrack?

let numberOfBeats = 8
let tempo = 280.0

var startTime : TimeInterval = 0

override func viewDidLoad() {
super.viewDidLoad()

print("Begin setup.")

// Load .wav sample in AKMidiSampler

do {
try sampler.loadWav("tick")
} catch {
print("sampler.loadWav() failed")
}

// Create tracks for the sequencer and set midi outputs

metronomeTrack = sequencer.newTrack("metronomeTrack")
callbackTrack = sequencer.newTrack("callbackTrack")
metronomeTrack?.setMIDIOutput(sampler.midiIn)
callbackTrack?.setMIDIOutput(callbackInst.midiIn)

// Setup and start AudioKit

AudioKit.output = sampler

do {
try AudioKit.start()
} catch {
print("AudioKit.start() failed")
}

// Set sequencer tempo

sequencer.setTempo(tempo)

// Create the notes

var midiSequenceIndex = 0

for i in 0 ..< numberOfBeats {

// Add notes to tracks

metronomeTrack?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(midiSequenceIndex)), duration: AKDuration(beats: 0.5))
callbackTrack?.add(noteNumber: MIDINoteNumber(midiSequenceIndex), velocity: 100, position: AKDuration(beats: Double(midiSequenceIndex)), duration: AKDuration(beats: 0.5))

print("Adding beat number \(i+1) at position: \(midiSequenceIndex)")
midiSequenceIndex += 1

}

// Set the callback

callbackInst.callback = {status, noteNumber, velocity in

if status == .noteOn {

let currentTime = Date().timeIntervalSinceReferenceDate
let noteDelay = currentTime - ( self.startTime + ( 60.0 / self.tempo ) * Double(noteNumber) )
print("Beat number: \(noteNumber) delay: \(noteDelay)")

} else if ( noteNumber == midiSequenceIndex - 1 ) && ( status == .noteOff) {

print("Sequence ended.\n")
self.toggleMetronomePlayback()

} else {return}

}

// Preroll the sequencer

sequencer.preroll()

print("Setup ended.\n")

}

@IBAction func playButtonPressed(_ sender: UIButton) {

toggleMetronomePlayback()

}


func toggleMetronomePlayback() {

if sequencer.isPlaying == false {

print("Playback started.")
startTime = Date().timeIntervalSinceReferenceDate
sequencer.play()

} else {

sequencer.stop()
sequencer.rewind()

}

}

}

有人能帮忙吗?谢谢。

最佳答案

正如 Aure 评论的那样,启动延迟是一个已知问题。即使有预卷,仍然存在明显的延迟,尤其是在较高节奏时。

但如果您使用的是循环序列,我发现您有时可以通过将序列的“起点”设置为最终 MIDI 事件之后但在循环长度内的位置来减轻延迟的明显程度。如果您能找到一个好的位置,则可以在它循环回您的内容之前消除延迟影响。

确保在需要之前调用 setTime()(例如,在停止序列之后,而不是在准备播放时),因为 setTime() 调用本身可以引入大约 200 毫秒的不稳定。

编辑:事后想想,您可以通过启用循环并使用任意长的序列长度在非循环序列上做同样的事情。如果您需要播放以在 MIDI 内容结束时停止,您可以使用由紧接在最后一个音符之后的 MIDI 事件触发的 AKCallbackInstrument 来实现。

关于audio - AKSequencer 中播放的第一个音符已关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52062316/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com