[英]AudioKit ios AKSequencer Not Restarting Playback Accurately
我正在嘗試使用AudioKit在小節的每個節拍上播放聲音。 雖然我實現了從代碼本關於通過AudioKit回調類似的問題,我似乎無法得到序更新變化和回放正常。 它將准確地播放一次,但是在倒退並更改值后,它將僅使用初始值(或完全不播放)。
我的意圖是創建一個具有每個小節拍值的小節結構,然后使用MIDI和回調播放取決於多少個小節拍的不同聲音。 謝謝!
import UIKit
import AudioKit
class ViewController: UIViewController {
let sequencer = AKSequencer()
let click = AKSynthSnare()
let callbackInst = AKCallbackInstrument()
// Create the struct that defines each line
struct Line {
var name: String
var measures: Int
var beatsPerMeasure: Int
func totalBeats() -> Int {
return (measures * beatsPerMeasure)
}
}
// Initialize intro line
var intro = Line(name: "Intro", measures: 0, beatsPerMeasure: 0)
// A function to create/update/playback the sequence on button press
func playBack() {
let metronomeTrack = sequencer.newTrack()
metronomeTrack?.setMIDIOutput(click.midiIn)
let callbackTrack = sequencer.newTrack()
callbackTrack?.setMIDIOutput(callbackInst.midiIn)
for steps in 0 ... Int(measuresRowOneValue) {
// this will trigger the sampler on the four down beats
metronomeTrack?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(steps)), duration: AKDuration(beats: 0.5))
// set the midiNote number to the current beat number
callbackTrack?.add(noteNumber: MIDINoteNumber(steps), velocity: 100, position: AKDuration(beats: Double(steps)), duration: AKDuration(beats: 0.5))
// set the callback
callbackInst.callback = {status, noteNumber, velocity in
guard status == .noteOn else { return }
print("beat number: \(noteNumber + 1)")
}
}
}
@IBOutlet weak var rowOneLocationOne: UIImageView!
// Listener for UI display values
var measuresRowOneValue: Int = 0 {
didSet {
intro.measures = measuresRowOneValue
}
}
@IBAction func rowOnePlusButton(_ sender: UIButton) {
measuresRowOneValue += 1
}
@IBAction func rowOneMinusButton(_ sender: UIButton) {
measuresRowOneValue -= 1
}
@IBAction func playbackStart(_ sender: UIButton) {
playBack()
sequencer.play()
}
@IBAction func playbackStop(_ sender: UIButton) {
sequencer.stop()
}
@IBAction func playbackRestart(_ sender: UIButton) {
sequencer.rewind()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
AudioKit.output = click
try!AudioKit.start()
}
}
您的代碼中有一些令人困惑的地方,所以我不確定這是否是您唯一的問題,但是最小的是,每次更改序列的長度時,都需要先調用setLength()
然后再調用enableLooping
。 基本上,默認情況下(即,除非您明確設置長度),序列的長度將是序列中最長軌道的長度。 在您的“播放”方法中,您是在曲目的頂部添加曲目,而不會刪除舊曲目,因此無法知道序列需要多長時間。
您的“播放”方法正在做兩個不同的事情(都不涉及播放)。 您可能要分手。 您可以使用setup()
來完成只需要做一次的事情(創建軌道,設置其輸出,設置回調)和一個rewriteSequence()
方法,當您想要重寫軌道。 這樣,您可以重復使用現有軌道,而不必不斷創建新軌道。
var metronomeTrack: AKMusicTrack!
var callbackTrack: AKMusicTrack!
// call this just once at the start
func setup() {
metronomeTrack = sequencer.newTrack()
metronomeTrack?.setMIDIOutput(click.midiIn)
callbackTrack = sequencer.newTrack()
callbackTrack?.setMIDIOutput(callbackInst.midiIn)
callbackInst.callback = {status, noteNumber, velocity in
guard status == .noteOn else { return }
print("beat number: \(noteNumber + 1)")
}
}
// call this each time you want to change the sequence
func rewriteSequence() {
metronomeTrack?.clear()
callbackTrack?.clear()
for steps in 0 ... Int(measuresRowOneValue) {
metronomeTrack?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(steps)), duration: AKDuration(beats: 0.5))
callbackTrack?.add(noteNumber: MIDINoteNumber(steps), velocity: 100, position: AKDuration(beats: Double(steps)), duration: AKDuration(beats: 0.5))
}
// This will make sure it loops correctly:
sequencer.setLength(AKDuration(beats: Double(measuresRowOneValue)))
sequencer.enableLooping()
}
我希望這有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.