在 AudioKit 中循环遍历结构数组
Looping Through Arrays of Structs in AudioKit
我正在尝试使用结构数组为音序器播放创建 MIDI 内容。每个结构创建一个 'measure',并且每个小节都有位置、numberOfBeats 和速度的属性。我想循环遍历小节中每个节拍的每个小节,并根据节拍是否是小节中的第一个来播放两个 MIDI 音符中的一个。
下面的代码将正确打印(click1、click2、click2、click1、click 2、click1、click2、click2),但是 MIDI 内容(附加到 wav)只会播放一次,不会前进到数组中的下一个度量。我一直在尝试使用各种循环类型使函数按顺序通过一系列度量来工作,但无法使其正确进行。谢谢!
import UIKit
import AudioKit
class ViewController: UIViewController {
let sequencer = AKSequencer ()
var metronomeTrack1: AKMusicTrack!
var metronomeTrack2: AKMusicTrack!
let click1 = AKMIDISampler()
let click2 = AKMIDISampler ()
func setupTracks() {
metronomeTrack1 = sequencer.newTrack()
metronomeTrack1?.setMIDIOutput(click1.midiIn)
metronomeTrack2 = sequencer.newTrack()
metronomeTrack2?.setMIDIOutput(click2.midiIn)
}
struct Measure {
var location : Int
var numberOfBeats : Int
var tempo : Int
}
var measureOne = Measure(location: 1, numberOfBeats: 4, tempo: 100)
var measureTwo = Measure(location: 2, numberOfBeats: 2, tempo: 100)
var measureThree = Measure(location: 3, numberOfBeats: 4, tempo: 100)
var arrayIndex = [Measure]()
//Variables to track location through loops
var arrayLocator = 0
var beatWatcher = 0
func playMeasures () {
for _ in arrayIndex {
for beats in 0...(arrayIndex[arrayLocator].numberOfBeats - 1) {
if beatWatcher == 0 {
metronomeTrack1?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(beats)), duration: AKDuration(beats: 1))
print("click1")
beatWatcher += 1
} else {
metronomeTrack2?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(beats)), duration: AKDuration(beats: 1))
print("click2")
beatWatcher += 1
if beatWatcher == (arrayIndex[arrayLocator].numberOfBeats) {
beatWatcher = 0
arrayLocator += 1
}
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
arrayIndex = [measureOne, measureTwo, measureThree]
metronomeTrack1?.clear()
metronomeTrack2?.clear()
sequencer.setLength(AKDuration(beats: 100))
AudioKit.output = click1
AudioKit.output = click2
setupTracks()
try! click1.loadWav("blockhigh")
try! click2.loadWav("blocklow")
playMeasures()
sequencer.play()
try!AudioKit.start()
}
}
经过进一步研究;看起来使用步幅是完成循环的最佳方式,并且每个 MIDI 轨道中的 "position" 需要在每个循环中递增 1 才能按正确的顺序添加到序列中。
我正在尝试使用结构数组为音序器播放创建 MIDI 内容。每个结构创建一个 'measure',并且每个小节都有位置、numberOfBeats 和速度的属性。我想循环遍历小节中每个节拍的每个小节,并根据节拍是否是小节中的第一个来播放两个 MIDI 音符中的一个。
下面的代码将正确打印(click1、click2、click2、click1、click 2、click1、click2、click2),但是 MIDI 内容(附加到 wav)只会播放一次,不会前进到数组中的下一个度量。我一直在尝试使用各种循环类型使函数按顺序通过一系列度量来工作,但无法使其正确进行。谢谢!
import UIKit
import AudioKit
class ViewController: UIViewController {
let sequencer = AKSequencer ()
var metronomeTrack1: AKMusicTrack!
var metronomeTrack2: AKMusicTrack!
let click1 = AKMIDISampler()
let click2 = AKMIDISampler ()
func setupTracks() {
metronomeTrack1 = sequencer.newTrack()
metronomeTrack1?.setMIDIOutput(click1.midiIn)
metronomeTrack2 = sequencer.newTrack()
metronomeTrack2?.setMIDIOutput(click2.midiIn)
}
struct Measure {
var location : Int
var numberOfBeats : Int
var tempo : Int
}
var measureOne = Measure(location: 1, numberOfBeats: 4, tempo: 100)
var measureTwo = Measure(location: 2, numberOfBeats: 2, tempo: 100)
var measureThree = Measure(location: 3, numberOfBeats: 4, tempo: 100)
var arrayIndex = [Measure]()
//Variables to track location through loops
var arrayLocator = 0
var beatWatcher = 0
func playMeasures () {
for _ in arrayIndex {
for beats in 0...(arrayIndex[arrayLocator].numberOfBeats - 1) {
if beatWatcher == 0 {
metronomeTrack1?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(beats)), duration: AKDuration(beats: 1))
print("click1")
beatWatcher += 1
} else {
metronomeTrack2?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(beats)), duration: AKDuration(beats: 1))
print("click2")
beatWatcher += 1
if beatWatcher == (arrayIndex[arrayLocator].numberOfBeats) {
beatWatcher = 0
arrayLocator += 1
}
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
arrayIndex = [measureOne, measureTwo, measureThree]
metronomeTrack1?.clear()
metronomeTrack2?.clear()
sequencer.setLength(AKDuration(beats: 100))
AudioKit.output = click1
AudioKit.output = click2
setupTracks()
try! click1.loadWav("blockhigh")
try! click2.loadWav("blocklow")
playMeasures()
sequencer.play()
try!AudioKit.start()
}
}
经过进一步研究;看起来使用步幅是完成循环的最佳方式,并且每个 MIDI 轨道中的 "position" 需要在每个循环中递增 1 才能按正确的顺序添加到序列中。