IOS9 Beta and MusicTrackLoopInfo

Has anyone been able to loop a MIDI file seamlessly on iOS9 beta? As soon as I try to loop by setting numberOfLoops to 0 in MusicTrackLoopInfo, it will block the application by sending a random MIDI signal to the player. I reported this, but I wonder if anyone found a job. The same code works fine under all other versions of iOS.

MusicTrackLoopInfo loopInfo; loopInfo.loopDuration = loopLength; loopInfo.numberOfLoops = 0; 
+5
source share
3 answers

OK I just heard that iOS9 will ship with this error. Terrible.

Here is the work.

Do not set numberOfLoops at all, OR set numberOfLoops = 1; // means loop cycle Now make a variable (i.e. MyVariableToKeepTrackOfAddedCopies) that keeps track of the number of times you actually do the following:

In your MIDIReadProc, at some point before the track has finished playing, do the following:

 // Copy the track to itself - effectively doubling the length MusicTrack theTrack=nil; MusicTrackGetProperty(theTrack, kSequenceTrackProperty_TrackLength, &trackLen, &trackLenLen); trackLen = 4.0; //<-- this is your real track length MusicTrackCopyInsert(theTrack, 0, trackLen, theTrack, 0); myVariableToKeepTrackOfAddedCopies++; 

So, now your track is twice as long as it ends, and the track will continue. This will work just like a loop, except that you take up more memory, as you make the track length longer after each iteration.

When you stop the sequence / track, cut the track to its original size.

 MusicTrackCut(theTrack, 4.0, 4.0 + (4.0*myVariableToKeepTrackOfAddedCopies)); MusicTrackGetProperty(theTrack, kSequenceTrackProperty_TrackLength, &trackLen, &trackLenLen); 

Annoying, but it works. I just confirmed on iOS9 beta. Hope this helps.

+3
source

This has been fixed since iOS version 9.2

+1
source

Oddly enough, the tempo trajectory does not seem to have this problem. The following code does not block me:

 MusicTrack tempoTrack; OSSTATUS = MusicSequenceGetTempoTrack(self.sequence, &tempoTrack); SafeMusicTrackClear(tempoTrack); //calls into MusicTrackClear MusicTrackNewExtendedTempoEvent(tempoTrack, 0, self.tempo * self.tempoMultiplier); MIDIMetaEvent timeSignatureMetaEvent; timeSignatureMetaEvent.metaEventType = 0x58; timeSignatureMetaEvent.dataLength = 4; timeSignatureMetaEvent.data[0] = 1; timeSignatureMetaEvent.data[1] = 4; timeSignatureMetaEvent.data[2] = 0x18; timeSignatureMetaEvent.data[3] = 0x08; MusicTrackNewMetaEvent(tempoTrack, 0, &timeSignatureMetaEvent); MusicTrackLoopInfo loopInfo; loopInfo.loopDuration = 0.25f; loopInfo.numberOfLoops = 0; MusicTrackSetProperty(tempoTrack, kSequenceTrackProperty_LoopInfo, &loopInfo, sizeof(loopInfo)); 

Unfortunately, it does not seem that the tempo track can actually play notes.


UPDATE:

After several hours of work and finding the best solution to the problem, I settled on a manual loop, sending a custom event at the end of my sequence.

My sequence is created in a method ...

 -(void) loadPacketsForLoopingSequence { SafeMusicTrackClear(loopingTrack); //calls into MusicTrackClear // calculate timestampToPlaySequenceAt -- the starting point of the current sequence iteration, probably in the past, based on MusicPlayerGetTime and the length of the sequence -- here // calculate timestampToPlayNextSequenceAt -- the starting point of the next sequence iteration, based on MusicPlayerGetTime and the length of the sequence -- here // a single iteration of the notes get added to loopingTrack here, starting at timestampToPlaySequenceAt MusicEventUserData event; event.length = 1; event.data[0] = 0xab; //arbitrary designation // -0.5 to make sure we still have time to do the next step in the callback MusicTrackNewUserEvent(loopingTrack, timestampToPlayNextSequenceAt - 0.5, &event); } 

... which is again called in the callback:

 void sequenceCallback(void* inClientData, MusicSequence inSequence, MusicTrack inTrack, MusicTimeStamp inEventTime, const MusicEventUserData* inEventData, MusicTimeStamp inStartSliceBeat, MusicTimeStamp inEndSliceBeat) { CSMidiMusicPlayer* musicPlayer = (CSMidiMusicPlayer*)inClientData; [musicPlayer loadPacketsForLoopingSequence]; } 

The callback must be registered during the init sequence using MusicSequenceSetUserCallback .

It is possible that -0.5 kludge can be completely eliminated by examining the parameters in sequenceCallback and modifying loadPacketsForLoopingSequence to accept the parameter, but I have not received this yet.

I like this solution because it stays in MIDI time and does not change the MIDI file unexpectedly, with state preservation. (New notes are mostly transmitted when you approach the loop marker.)

0
source

All Articles