One frustrating limitation of Apple's MusicSequence
(which AKSequencer
is based on) is that although you can easily set the 'right side' of the looping section, the left side will always loop back to zero and cannot be changed. So to crop from the left side, you need to isolate the section that you want to loop and shift it over so that the start of your loop is at zero.
As of AudioKit 4.2.4, this is possible. Use AKMusicTrack's .getMIDINoteData()
to get an array of AKMIDINoteData
structs whose content can be edited and then used to replace the original data. If you had a 16 beat track and you wanted to loop the last four beats, you could do something ike this:
let loopStart = 12.0
let loopLength = 4.0
// keep track of the original track contents
let originalLength = 16.0
let originalContents = track.getMIDINoteData()
// isolate the segment for looping and shift it to the start of the track
let loopSegment = originalContents.filter { loopStart ..< (loopStart + loopLength) ~= $0.position.beats }
let shiftedSegment = loopSegment.map { AKMIDINoteData(noteNumber: $0.noteNumber,
velocity: $0.velocity,
channel: $0.channel,
duration: $0.duration,
position: AKDuration(beats: $0.position.beats - loopStart))
}
// replace the track contents with the loop, and assert the looping behaviour
track.replaceMIDINoteData(with: shiftedSegment)
seq.setLength(AKDuration(beats: loopLength))
seq.enableLooping()
// and to get back to the original:
track.replaceMIDINoteData(with: originalContents)
seq.setLength(AKDuration(beats: originalLength))
seq.enableLooping()
If you wanted to looping section to repeat for the length of the original sequence, then you could use the shiftedSegment
as a template and build a 16 beat sequence from it.