我有一个从AKKeyboardView记录MIDI数据的应用程序。在录制之前,用户可以使用键盘进行操作,但是当他们想要开始录制时,请单击一个按钮。
点击按钮后会发生以下情况:
let sequencer = AKSequencer()
func buttonClicked() {
sequencer.rewind()
sequencer.play()
}
我当前面临的问题是,我想记录键盘数据大约四秒钟,然后如果用户仍在记录键盘的MIDI,则重新启动4秒。
如果currentPosition的节拍大于4,我试图通过使用noteOn函数倒带音序器来修复它,但是效果不佳。我还尝试使用currentRelativePosition代替,但是如果您长时间按住某个键,它将崩溃。
这是我的AKKeyboardDelegate代码:
var noteDict = [MIDINoteNumber: Double]()
var isMIDIRecording = false
func noteOn(note: MIDINoteNumber) {
var currentPosition = sequencer.currentPosition
var beats = currentPosition.beats
self.noteDict[note] = beats
bank.play(noteNumber: note, velocity: 127)
}
func noteOff(note: MIDINoteNumber) {
let currentPosition = sequencer.currentPosition
let endTime = currentPosition.beats
if let startTime = noteDict[note] {
let durationInBeats = abs(endTime - startTime)
let noteDuration = AKDuration(beats: durationInBeats)
if isMIDIRecording {
musicTrack.add(noteNumber: note, velocity: 127, position: currentPosition, duration: noteDuration)
}
noteDict[note] = nil
}
bank.stop(noteNumber: note)
}
这是我用于初始化音序器和AudioKit的代码。
let callbackInstrument = AKCallbackInstrument()
var bank = AKFMOscillatorBank(waveform: AKTable(.triangle), attackDuration: 0.01, decayDuration: 0.03, sustainLevel: 0.02, releaseDuration: 0.01)
AudioKit.output = bank
do {
try AudioKit.start()
} catch {
print("AudioKit couldn't be started")
fatalError()
}
handleCallbackInstrument()
// create two tracks for the sequencer
let metronomeTrack = sequencer.newTrack("metronome track")
let musicTrack = sequencer.newTrack("music track")
musicTrack.setMIDIOutput(callbackInstrument.midiIn)
musicTrack.setLength(AKDuration(beats: 4))
for i in 0 ..< 4 {
// this will trigger the sampler on the four down beats
metronomeTrack?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(i)), duration: AKDuration(beats: 0.5))
}
// get the sequencer ready
sequencer.enableLooping(AKDuration(beats: 4))
sequencer.setTempo(120)
非常感谢任何帮助或指针。