问题
This topic has been covered Numerous Times, and I have successfully used a AKMIDICallbackInstrument
with the old AKAppleSequencer
in my previous apps.
I am starting to use the new AKSequencer
which is absolutely phenomenal: elegant interface, and easy to use. However, I cannot for my life figure out how to handle callback events with it. I need to use a callback in order to trigger GUI events based on the sequencer playing.
Here is my example code:
private func setMetronome(bpm: BPM, beats:Int)
{
sequencer = AKSequencer(targetNode: metronomeSampler)
sequencer.tempo = bpm
sequencer.loopEnabled = false
sequencer.length = Double(beats)
metroCallback.callback = {status, noteNumber, velocity in
if let midiStatus = AKMIDIStatus(byte: status), midiStatus.type != .noteOn { return }
//Do callback stuff here
}
let metroCallbackTrack = sequencer.addTrack(for: metroCallback)
for i in 0..<beats
{
if i == 0
{
sequencer.add(noteNumber: MIDINoteNumber(67), position: Double(i), duration: 1.0)
metroCallbackTrack.add(noteNumber: MIDINoteNumber(67), position: Double(i), duration: 1.0)
}
else if (i % 4 == 0)
{
sequencer.add(noteNumber: MIDINoteNumber(67), position: Double(i), duration: 1.0)
metroCallbackTrack.add(noteNumber: MIDINoteNumber(60), position: Double(i), duration: 1.0)
}
else
{
sequencer.add(noteNumber: MIDINoteNumber(60), position: Double(i), duration: 1.0)
metroCallbackTrack.add(noteNumber: MIDINoteNumber(60), position: Double(i), duration: 1.0)
}
print("seq count:\(i)")
}
for track in sequencer.tracks
{
print("Adding track to mixer:\(track.length)")
track >>> mixer
}
}
This code correctly creates a sequence of n
number of beats, it plays back through my AKSampler
all is well in the world. Except that no callback events happen (using print statements to confirm)
Thought Process
With AKAppleSequencer
and AKMIDICallbackInstrument
, you could set the globalMIDIOutput
with the AKAppleSequencer
with the midi input of AKMIDICallBackInstrument
.
Now the new AKSequencer
and AKCallbackInstrument
do not have these options, nor does the new AKSequencerTrack
(the old AKAppleSequencer
would use AKMusicTrack
objects which could set midi input/output). In looking at the implementation of the new AKSequencer
, it is driven by AKNode
objects, AKCallbackInstrument
is a AKNode
object and should be able be driven by a track with the right midi data.
I add a track to my sequencer, and from that track, and the necessary midi data that duplicate exactly the midi events I want to callback on and perform my GUI events. However with this approach, it does not seem to call the callback.
Does anyone have any idea how to use these new components with a callback? I really don't want to go back to AKAppleSequencer
unless there is clearly no way to drive callbacks with the new AKSequencer
.
回答1:
To get AKCallbackInstrument
working with the new AKSequencer
, try connecting your callback instrument to your output, e.g.,
metroCallback >>> mixer
Not obvious, but has worked for me.
Edit: including a minimal working version of the new AKSequencer
with AKCallbackInstrument
class SequencerWrapper {
var seq: AKSequencer!
var cbInst: AKCallbackInstrument!
var mixer: AKMixer!
init() {
mixer = AKMixer()
AudioKit.output = mixer
seq = AKSequencer()
cbInst = AKCallbackInstrument()
// set up a track
let track = seq.addTrack(for: cbInst)
for i in 0 ..< 4 {
track.add(noteNumber: 60, position: Double(i), duration: 0.5)
}
track.length = 4.0
track.loopEnabled = true
track >>> mixer // must send track to mixer
// set up the callback instrument
cbInst.callback = { status, note, vel in
guard let status = AKMIDIStatus(byte: status),
let type = status.type,
type == .noteOn else { return }
print("note on: \(note)")
// trigger sampler etc from here
}
cbInst >>> mixer // must send callbackInst to mixer
}
func play() {
seq.playFromStart()
}
}
回答2:
Thanks for the working example @c_booth! Just wanted to add for any dummies like me that couldn't figure out why the above example wasn't working, you will still need to call AudioKit.start().
来源:https://stackoverflow.com/questions/61491639/audiokit-using-the-new-aksequencer-with-any-variety-of-the-callback-instruments