[英]iOS9 Beta and MusicTrackLoopInfo
有沒有人能夠在IOS9 Beta上循環播放MIDI文件? 一旦我嘗試通過在MusicTrackLoopInfo中將numberOfLoops設置為0來循環,它會通過向播放器發送隨機MIDI來鎖定應用程序。 我已經報道了,但我想知道是否有人找到了解決方法。 所有其他iOS版本的代碼完全相同。
MusicTrackLoopInfo loopInfo;
loopInfo.loopDuration = loopLength;
loopInfo.numberOfLoops = 0;
好的,我剛才聽說iOS9會附帶這個bug。 可怕。
這是一個解決方法。
不要設置numberOfLoops,或者設置numberOfLoops = 1; //表示循環一次現在創建一個變量(即myVariableToKeepTrackOfAddedCopies)來跟蹤實際執行以下操作的次數:
在您的MIDIReadProc中,在音軌播放完畢之前的某個時刻,請執行以下操作:
// 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++;
所以現在你的賽道在它結束之前是兩倍,賽道將繼續。 這將與循環相同,除非您占用更多內存,因為在每次迭代后使軌道長度更長。
停止序列/軌道時,將軌道剪切回原始大小。
MusicTrackCut(theTrack, 4.0, 4.0 + (4.0*myVariableToKeepTrackOfAddedCopies));
MusicTrackGetProperty(theTrack, kSequenceTrackProperty_TrackLength, &trackLen, &trackLenLen);
刺激,但它的工作原理。 我剛剛在iOS9 beta 5上驗證過。希望它有所幫助。
從iOS 9.2版開始修復此問題
奇怪的是,節奏軌道似乎沒有這個問題。 以下代碼不會鎖定我:
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));
不幸的是,節奏音軌似乎不能真正演奏音符。
經過幾個小時的挖掘並試圖找到問題的更好解決方案后,我決定通過在序列結束時發送用戶事件來手動循環。
我的序列是在方法中創建的......
-(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);
}
...在回調中再次調用:
void sequenceCallback(void* inClientData,
MusicSequence inSequence,
MusicTrack inTrack,
MusicTimeStamp inEventTime,
const MusicEventUserData* inEventData,
MusicTimeStamp inStartSliceBeat,
MusicTimeStamp inEndSliceBeat) {
CSMidiMusicPlayer* musicPlayer = (CSMidiMusicPlayer*)inClientData;
[musicPlayer loadPacketsForLoopingSequence];
}
必須在序列初始化期間使用MusicSequenceSetUserCallback
注冊回調。
通過檢查sequenceCallback
的參數並修改loadPacketsForLoopingSequence
以接受參數,可以完全消除-0.5 loadPacketsForLoopingSequence
,但我還沒有那么遠。
我喜歡這個解決方案,因為它保持在MIDI時間,並且不會以意想不到的狀態方式修改MIDI文件。 (當你接近循環標記時,新注釋基本上會被流入。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.