Loops iOS9测试版和MusicTrackLoopInfo

Loops iOS9测试版和MusicTrackLoopInfo,loops,ios8,midi,Loops,Ios8,Midi,有没有人能够在IOS9测试版上毫无问题地循环MIDI文件? 当我在MusicTrackLoopInfo中将numberOfLoops设置为0尝试循环时,它会通过向播放器发送随机MIDI来锁定应用程序。我已经报告过了,但我想知道是否有人找到了工作。同样的代码在所有其他iOS版本下都能完美工作 MusicTrackLoopInfo loopInfo; loopInfo.loopDuration = loopLength; loopInfo.numberOfLoops = 0; 好的,我刚刚听说iO

有没有人能够在IOS9测试版上毫无问题地循环MIDI文件? 当我在MusicTrackLoopInfo中将numberOfLoops设置为0尝试循环时,它会通过向播放器发送随机MIDI来锁定应用程序。我已经报告过了,但我想知道是否有人找到了工作。同样的代码在所有其他iOS版本下都能完美工作

MusicTrackLoopInfo loopInfo;
loopInfo.loopDuration = loopLength;
loopInfo.numberOfLoops = 0;

好的,我刚刚听说iOS9将附带这个bug。糟透了

这里有一个变通办法

根本不要设置numberOfLoops,或者设置numberOfLoops=1;//表示循环一次 现在制作一个变量(即myVariableToKeepTrackOfAddedCopies),用于跟踪实际执行以下操作的次数:

// 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++;
在曲目播放结束前的某个时间点,在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++;

令人恼火,但它有效。我刚刚在iOS9 beta 5上进行了验证。希望能有帮助。

奇怪的是,节奏音轨似乎没有这个问题。以下代码未为我锁定:

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 kludge,但我还没有做到这一点


我喜欢这个解决方案,因为它停留在MIDI时间,不会以意外的、有状态的方式修改MIDI文件。(当你靠近一个循环标记时,新的音符基本上会流进来。)

从iOS 9.2版开始,这是固定的,显然这不是一个好的解决方案,因为轨迹越来越长。答案是将音乐播放器设置为开始,但我不知道如何在要求的时间精确设置开始。如果有人知道如何将开始时间设置在准确的时刻,那就太好了!你好,Aron,我正在努力解决同一问题,但不幸的是,您提出的解决方案不符合我的技术案例。如果有帮助的话,我一直在关注这个苹果论坛的帖子:以及这个核心音频帖子:据我所知,苹果确实知道这个问题,并且已经证实iOS9附带了这个bug。我不知道他们什么时候能真正解决这个问题。我很久以前提交了一个示例项目,但修复程序从未提交给GM。我也在等待。为什么代码对你不起作用?嗨@aron-所以作为权宜之计,我最终采用了你建议的方法,不过因为我使用了几个MIDI曲目并实时更改它们,所以需要一些欺骗才能使其正常工作。我最终使用了一个MIDI用户事件(和MusicSequenceUserCallback),因为我可以将它配置为只触发一次(而不是miidiredproc)。我还不得不将这项工作转移到后台线程,因为在AudioToolbox中运行了一定时间后,出于某种原因,我会遇到致命的EXC#u BAD#u访问。谢谢你的帮助!我相信这将在9.1之后的下一个iOS版本中得到修复。我刚刚收到一封来自苹果的关于我为这个问题打开的bug报告的电子邮件——他们已经表示,这个bug已经在iOS 9.2测试版中得到修复。我已经下载了测试版,并在模拟器和设备(9.2测试版)上确认此问题已得到修复。我不确定这将于何时向公众发布,但很高兴知道修复正在进行中。