2012-08-10 63 views
1

我正在通过MusicPlayer播放MIDI序列,这是从MIDI文件加载的,我希望在播放时将序列更改为另一个序列。 当我试试这个:如何从一个音乐序列切换到另一个没有时间延迟

MusicPlayerSetSequence(_player, sequence); 
MusicSequenceSetAUGraph(sequence, _processingGraph); 

停止播放。所以我再次启动它回来,并设置与

MusicPlayerSetTime(_player, currentTime); 

所以它再次播放上序列停止的地方的时候,但有一点延迟。 我试图将时间间隔添加到currentTime,我通过获取停止前和重新开始后的时间来获取时间间隔。但仍然有延迟。

我想知道是否有替代停止 - >改变序列 - >再次启动。

+0

嘿 - 你是否放弃了合并曲目的方法?我终于找到了一些时间让它工作。你的文件有点隐藏 - 不知道为什么。下面是一个关于你的MIDI文件/ sf2 +一个随机midi/sf2的例子(我有过)(http://dl.dropbox.com/u/34715839/MusicPlayerTracksFromFiles.zip) - 干杯 – 2012-08-10 04:31:54

+0

哦 - 这里有个bug设置跟踪循环时的文件:使用的trackLen值来自sourceTrack。在设置循环长度之前,应该从目标轨道重新计算此值。此外,发现最简单的.mid文件的奇怪是由于它有2首曲目 - 第一首是空的 - 所以复制该曲目==沉默。 – 2012-08-10 07:54:41

+0

不,我没有,我找到了自己的解决方案,并提出了另一个答案(http://stackoverflow.com/questions/11706042)。但感谢无论如何,我相信你的代码将帮助我优化我的。我仍然试图弄清楚你是如何循环序列的,因为它没有在正确的时间循环。我做 - '如果(时间> = trackLen)MusicPlayerSetTime(_player,0);' – chedda 2012-08-10 08:54:30

回答

1

因为

MusicPlayerSetSequence(_player, sequence); 
MusicSequenceSetAUGraph(sequence, _processingGraph); 

仍然会导致播放器停止,仍然可以听到稍微休息一下。 所以不是更新musicSequence,我说干就干,改变了轨道,而不是,这不会造成任何中断的内容:

MusicTrack currentTrack; 
MusicTrack currentTrack2; 
MusicSequenceGetIndTrack(musicSequence, 0, &currentTrack); 
MusicSequenceGetIndTrack(musicSequence, 1, &currentTrack2); 
MusicTrackClear(currentTrack, 0, _trackLen); 
MusicTrackClear(currentTrack2, 0, _trackLen); 

MusicSequence tmpSequence; 
switch (number) { 
    case 0: 
     tmpSequence = musicSequence1; 
     break; 
    case 1: 
     tmpSequence = musicSequence2; 
     break; 
    case 2: 
     tmpSequence = musicSequence3; 
     break; 
    case 3: 
     tmpSequence = musicSequence4; 
     break; 

    default: 
     tmpSequence = musicSequence1; 
     break; 
} 

MusicTrack tmpTrack; 
MusicTrack tmpTrack2; 
MusicSequenceGetIndTrack(tmpSequence, 0, &tmpTrack); 
MusicSequenceGetIndTrack(tmpSequence, 1, &tmpTrack2); 
MusicTimeStamp trackLen = 0; 
UInt32 trackLenLenLen = sizeof(trackLen); 
MusicTrackGetProperty(tmpTrack, kSequenceTrackProperty_TrackLength, &trackLen, &trackLenLenLen); 
_trackLen = trackLen; 
MusicTrackCopyInsert(tmpTrack, 0, _trackLen, currentTrack, 0); 
MusicTrackCopyInsert(tmpTrack2, 0, _trackLen, currentTrack2, 0); 

节点没有断开,没有更新的图形,没有停止播放。

2

如果您正在添加和移除轨道或切换序列,您肯定需要管理AUSamplers。处理AUSampler可能更清洁,为每个新轨道创建一个新的轨道,但它也可以“回收”AUSamplers,但这意味着您需要跟踪它们。

管理AUSamplers意味着当您不再使用某个实例时(例如,如果您删除或替换MusicTrack),您需要将其与AUMixer实例断开连接,将其从AUGraph实例中删除,然后更新AUGraph。

有很多方法可以处理所有这些。为了方便跟踪AUSampler实例的总线数量,加载的声音字体以及其他一些东西,我使用名为SamplerAudioUnit的NSObject的子类来包含所有需要的属性和方法。音乐曲目相同 - 我有一个Track类 - 但这可能不需要在您的项目中。

虽然是AUSamplers需要管理的性能和内存的要点。如果一个实例不再被使用,它应该被移除,并且AUMixer总线输入被释放。

顺便说一句 - 我检查文档,显然没有技术限制混音器总线的数量 - 但数量确实需要指定。

// this is not cut and paste code - just an example of managing the AUSampler instance 

- (OSStatus)deleteTrack:(Track*) trackObj 
{ 
    OSStatus result = noErr; 

    // turn off MP if playing 
    BOOL MPstate = [self isPlaying]; 
    if (MPstate){ 
     MusicPlayerStop(player); 
    } 

    //-disconnect node from mixer + update list of mixer buses 
    SamplerAudioUnit * samplerObj = trackObj.sampler; 
    UInt32 busNumber = samplerObj.busNumber; 

    result = AUGraphDisconnectNodeInput(graph, mixerNode, busNumber); 
    if (result) {[self printErrorMessage: @"AUGraphDisconnectNodeInput" withStatus: result];} 

    [self clearMixerBusState: busNumber]; // routine that keeps track of available busses 

    result = MusicSequenceDisposeTrack(sequence, trackObj.track); 
    if (result) {[self printErrorMessage: @"MusicSequenceDisposeTrack" withStatus: result];} 

    // remove AUSampler node 
    result = AUGraphRemoveNode(graph, samplerObj.samplerNode); 
    if (result) {[self printErrorMessage: @"AUGraphRemoveNode" withStatus: result];} 

    result = AUGraphUpdate(graph, NULL); 
    if (result) {[self printErrorMessage: @"AUGraphUpdate" withStatus: result];} 
    samplerObj = nil; 
    trackObj = nil; 

    if (MPstate){ 
     MusicPlayerStart(player); 
    } 

    // CAShow(graph); 
    // CAShow(sequence); 

    return result; 
} 
+0

断开连接,删除和创建新节点解决了问题。非常感谢你。 – chedda 2012-08-13 01:35:48