5

I am trying to crop and loop a certain part of a MIDI file using AudioKit.

I am using a sequencer and found a couple of things that are close to what I need, but not exactly.

I found a method in AKSequencer called clearRange. With this method I am able to silence the parts of the MIDI I don't want, but I haven't found a way to trim the sequencer and only keep the part I am interested in. Right now only the part I want has sound but I still get the silent parts.

Is there a way to trim a sequencer or to create a new sequencer with only the portion I want to keep from the original one?

Thanks!

mahal tertin
  • 3,239
  • 24
  • 41
  • 1
    There isn't a way built into AudioKit, but isn't just kind of clearing the ranges of all parts that don't match what you do wants? – Aurelius Prochazka Oct 26 '17 at 18:35
  • Hi Aurelius, thanks for your answer! The thing is with that I only can achieve a part of what I want. I have an original track with a certain length. I want to crop a part and create a track that loops the cropped part to fit the same length of the original one. I have been playing around with the sequencer and using `setTime` and `setLength` I was able to get a sequencer that has the portion I want to crop, but I cannot seem to find a way to create a new sequencer looping that part and that is the same length as the original one. Is there any way to achieve this? – Martín Zúñiga Oct 26 '17 at 19:24
  • I don't think its impossible, just haven't done it before. Seems like you're on the right track though. – Aurelius Prochazka Oct 27 '17 at 06:27
  • Awesome, thanks for answering again. I will keep trying and update the question if I find a way to do it. – Martín Zúñiga Oct 27 '17 at 14:58

1 Answers1

2

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.

c_booth
  • 2,185
  • 1
  • 13
  • 22