1

I've created a music sequence using coreMIDI and AudioToolBox and would now like to display the current beat position of the looped sequence in the UI. If the loop is only four beats, I would like the display to toggle between 1,2,3,4 and return to 1 as the sequence loops (much like in the transport of a program such a Logic Pro). I've made a function that uses MusicSequenceGetBeatsForSeconds() to calculate the beats based on the amount of time (using CFAbsoluteTimeGetCurrent()) that has passed since play was pressed, but this keeps the value increasing linearly (on beat on of the next measure the display reads "5.0"). How do I read the current beat of the sequence?

derekFairholm
  • 285
  • 1
  • 14

2 Answers2

2

Skip the end of track message; you can't rely on it.

Instead create a MusicSequenceUserCallback. Then add a track to your sequence that holds user events. The actual data in the event doesn't matter.

var event = MusicEventUserData(length: 1, data: (0xAA))
let status = MusicTrackNewUserEvent(markerTrack, endBeat, &event)

Then in the callback look for this arbitrary data value and do that thing you want to do.

let d = eventData.memory
if d.data == 0xAA {

In Swift 2.2, the callback cannot be a closure. So make it a global function.

Gene De Lisa
  • 3,628
  • 1
  • 21
  • 36
  • took a while but finally figured out how to set the user callback etc. Very much appreciated @GeneDeLisa – derekFairholm May 12 '16 at 17:23
  • Glad you got it to work. One thing about those user events. The reason I put them in a separate track is because if you save your sequence to a MDI file and then try to read it into another app like Sibelius, the import will be messed up - notes at incorrect beats. – Gene De Lisa May 13 '16 at 12:01
1

Look at MuscPlayer's MusicPlayerGetTime function instead.

Depending on what you want to do, you can set up a virtual destination as an endpoint for your MusicSequence and in its read block respond to events as they happen.

Gene De Lisa
  • 3,628
  • 1
  • 21
  • 36
  • Thanks @GeneDeLisa, I overlooked the `MusicPlayerGetTime` function. Although it's much cleaner than the function I came up with previously using `CFAbsoluteTime`, it still leaves me with a linear increase in beats even though my sequence is repeating. I looked into the info derived from the MIDIPacketList and can't find anything that would allow me to read the current position in the measure...you'll have to forgive the ignorance--just a pianist trying to learn to program. – derekFairholm May 06 '16 at 16:14
  • Or should I look into creating a function that receives the number of beats in the sequence and resets to 1 after the loop repeats? – derekFairholm May 06 '16 at 16:21
  • Maybe you can look for the MIDI end of track message arriving at your virtual destination and reset your counter when you get one. That would work for any length, not just a 4 beat sequence. – Gene De Lisa May 06 '16 at 17:04
  • ps the packets in the packetList each have a timestamp – Gene De Lisa May 06 '16 at 17:05
  • The MIDI end of track message is a MIDIMetaEvent right? It looks like type 0x2F...having trouble with this though as I added the MIDIMetaEvent to the track but can't seem to read it in the packet list... – derekFairholm May 06 '16 at 19:41