2012-07-29 71 views
4

我正在尋找一種混合2個或更多midi文件的方法,每個文件都有自己的聲音文件。我已經找到了一個文件的下面的代碼,並試圖做多個音樂播放器,但我想這不應該是正確的方法。我每秒都會聽到一些怪異的流行音樂。ios - 混合midi文件,每個都有自己的聲音字體

那麼有沒有其他方法,也許沒有musicplayer和musicsequence方法,只使用au單位?

這是我在另一個線程中找到的代碼:

-(void) playMusic:(NSString*) name 
{ 
NSString *presetURLPath = [[NSBundle mainBundle] pathForResource:@"GortsMiniPianoJ1" ofType:@"SF2"]; 
NSURL * presetURL = [NSURL fileURLWithPath:presetURLPath]; 
[self loadFromDLSOrSoundFont: (NSURL *)presetURL withPatch: (int)3]; 

NSString *midiFilePath = [[NSBundle mainBundle] pathForResource:name ofType:@"mid"]; 
NSURL * midiFileURL = [NSURL fileURLWithPath:midiFilePath]; 

NewMusicPlayer(&musicPlayer); 

if (NewMusicSequence(&musicSequence) != noErr) 
{ 
    [NSException raise:@"play" format:@"Can't create MusicSequence"]; 
} 

if(MusicSequenceFileLoad(musicSequence, (CFURLRef)midiFileURL, 0, 0 != noErr)) 
{ 
    [NSException raise:@"play" format:@"Can't load MusicSequence"]; 
} 

MusicPlayerSetSequence(musicPlayer, musicSequence); 
MusicSequenceSetAUGraph(musicSequence, _processingGraph); 
MusicPlayerPreroll(musicPlayer); 
MusicPlayerStart(musicPlayer); 
} 

回答

3

多MusicPlayer實例聽起來有點彆扭(保持同步),我有懷疑,多個AUGraphs會工作。我沒有自己嘗試過。

使用唯一實例MusicPlayer的一種方法是將每個MIDI文件中的曲目加載到「主」序列中。您可以爲每個音軌(MusicTrackSetDestNode)分配一個AUSampler節點(帶有獨特的soundFont),並通過AUMixer連接它們。您需要管理每個MIDI文件的速度(使用MusicTrackNewExtendedTempoEvent)以將文件速度分配給相關軌道。在軌道或混音器層面輕鬆處理軌道+軌道音量。

我猜很大程度上取決於你正在使用的MIDI文件的性質。 Fwiw - 我在iOS上進行了很多關於MIDI文件播放的研究,沒有什麼比MusicPlayer更容易使用。但是,如果MusicPlayer不適合您,Bass lib可能值得您關注。

指定的混頻器輸入數量:

// set the bus count 
UInt32 numBuses = BUS_COUNT; // a constant defined elsewhere 
result = AudioUnitSetProperty(mixerUnit, 
           kAudioUnitProperty_ElementCount, 
           kAudioUnitScope_Input, 
           0, 
           &numBuses, 
           sizeof(numBuses)); 

if (noErr != result) {[self printErrorMessage: @"Error setting Bus Count" withStatus: result]; return;} 
+0

太好了,謝謝。我也有這個想法,並開始像這樣編碼,但後來我認爲我只能將音頻分配給MusiqSequences而不是MusicTrack,所以我放棄了這種方法。 – chedda 2012-07-29 10:24:56

+0

我已經實現了您建議的多軌靜音方法 - 並且它適用於一個用例。但是有沒有辦法強制多個玩家同步 - 一個midi時鐘可以在這裏幫助嗎?我想要自主地改變曲目上的播放頭/開始和停止。核心音頻/音頻工具箱中的Abelton應用程序的midi混音部分是不可能建立的嗎? – johndpope 2015-04-24 03:47:43

+0

當我嘗試用調音臺設置多個AUSampler節點時,無法單獨調節音量。即使它們連接到單獨的輸入總線,(通過CAShow驗證),總線0的音量控制着它們全部的音量。 – Jadar 2017-01-02 19:28:08

0

所以我試圖設置節點爲每個軌道,但這並沒有改變任何東西。 soundfont只能設置爲第一個samplerUnit。 下面是如何設置的圖形:

AudioComponentDescription MixerUnitDescription; 
MixerUnitDescription.componentType   = kAudioUnitType_Mixer; 
MixerUnitDescription.componentSubType  = kAudioUnitSubType_MultiChannelMixer; 
MixerUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 
MixerUnitDescription.componentFlags   = 0; 
MixerUnitDescription.componentFlagsMask  = 0; 

AudioComponentDescription cd = {}; 
cd.componentManufacturer  = kAudioUnitManufacturer_Apple; 
cd.componentType = kAudioUnitType_MusicDevice; // type - music device 
cd.componentSubType = kAudioUnitSubType_Sampler; // sub type - sampler to convert our MIDI 

result = NewAUGraph (&_processingGraph); 
result = AUGraphAddNode(self.processingGraph, &MixerUnitDescription, &mixerNode); 

result = AUGraphAddNode (self.processingGraph, &cd, &samplerNode); 

result = AUGraphAddNode (self.processingGraph, &cd, &samplerNode2); 

cd.componentType = kAudioUnitType_Output; // Output 
cd.componentSubType = kAudioUnitSubType_RemoteIO; // Output to speakers 

result = AUGraphAddNode (self.processingGraph, &cd, &ioNode); 
result = AUGraphOpen (self.processingGraph); 

result = AUGraphConnectNodeInput (self.processingGraph, samplerNode, 0, mixerNode, 0); 
result = AUGraphConnectNodeInput (self.processingGraph, samplerNode2, 0, mixerNode, 1); 

result = AUGraphConnectNodeInput (self.processingGraph, mixerNode, 0, ioNode, 0); 
result = AUGraphNodeInfo (self.processingGraph, samplerNode, 0, &_samplerUnit); 
result = AUGraphNodeInfo (self.processingGraph, samplerNode2, 0, &_samplerUnit2); 
result = AUGraphNodeInfo (self.processingGraph, ioNode, 0, &_ioUnit); 

這是蘋果開發的網頁的示例方法,我修改爲SoundFont音色分配到特定samplerUnit

-(OSStatus) loadFromDLSOrSoundFont: (NSURL *)bankURL withPatch: (int)presetNumber withAudioUnit:(AudioUnit)auUnit{ 

OSStatus result = noErr; 

// fill out a bank preset data structure 
AUSamplerBankPresetData bpdata; 
bpdata.bankURL = (__bridge CFURLRef) bankURL; 
bpdata.bankMSB = kAUSampler_DefaultMelodicBankMSB; 
bpdata.bankLSB = kAUSampler_DefaultBankLSB; 
bpdata.presetID = (UInt8) presetNumber; 

// set the kAUSamplerProperty_LoadPresetFromBank property 
result = AudioUnitSetProperty(auUnit, 
          kAUSamplerProperty_LoadPresetFromBank, 
          kAudioUnitScope_Global, 
          0, 
          &bpdata, 
          sizeof(bpdata)); 

// check for errors 
NSCAssert (result == noErr, 
     @"Unable to set the preset property on the Sampler. Error code:%d '%.4s'", 
     (int) result, 
     (const char *)&result); 

return result; 
} 

然後我做了這兩次讓每個磁道劃分musicSequence

if(MusicSequenceFileLoad(tmpSequence, (__bridge CFURLRef)midiFileURL, 0, 0 != noErr)) 
{ 
    [NSException raise:@"play" format:@"Can't load MusicSequence"]; 
} 


MusicSequenceGetIndTrack(tmpSequence, 0, &tmpTrack); 
MusicSequenceNewTrack(musicSequence, &track); 
MusicTimeStamp trackLen = 0; 
UInt32 trackLenLen = sizeof(trackLen); 
MusicTrackGetProperty(tmpTrack, kSequenceTrackProperty_TrackLength, &trackLen, &trackLenLen); 
MusicTrackCopyInsert(tmpTrack, 0, trackLenLen, track, 0); 

最後:

MusicTrackSetDestNode(track, samplerNode); 
MusicTrackSetDestNode(track2, samplerNode2); 

但是,這不會對的音色庫分配給samplerUnit2

[self loadFromDLSOrSoundFont: (NSURL *)presetURL2 withPatch: (int)0 withAudioUnit:self.samplerUnit2]; 

分配到samplerUnit工作正常。任何想法,我在這裏失蹤?

+0

在網頁上查看所有代碼有點困難,但我沒有看到任何明顯的表現 - 除了我沒有看到您定義混音器輸入數量的位置。你需要這樣做(請參閱我的答案編輯)。此外,CAShow(圖形)是顯示圖形+連接的很好功能。也可以用於序列和曲目:CAShow(序列)。我知道分配獨特的AUSampler來跟蹤作品 - 已經在dev中的一個應用程序中完成了10多首曲目。 – 2012-07-30 02:43:55

+0

非常感謝您的幫助。我按照你所說的設定了公車總數,但那並沒有改變任何東西。 sequnce圖表示2個軌道,這是正確的。連接圖形似乎是正確的對我說: AudioUnitGraph 0x3D0A000: 成員節點: \t節點1:'aumx'mcmx '申請' \t節點2:'aumu'桑普 '申請' \t節點3: 'aumu' 'SAMP' '申請' \t節點4: 'auou' 'rioc' '申請' 連接: \t節點2總線0 =>節點1總線0; \t節點3總線0 =>節點1總線1; \t節點1總線0 =>節點4總線0; – chedda 2012-07-30 03:44:18

+0

如果沒有格式化,看起來有點難以理解,但它*看起來就像它的吸引力。 (fwiw-我喜歡從最低的功能級別向圖中添加節點,因此讀取連接和捕獲任何錯誤有點連貫一些:RemoteIO,Mixer,然後是所有的AUSamplers。)如果一個採樣器在軌道上工作,也許看看你是否可以讓sampler2在同一軌道上工作(即兩個採樣器都可以)。然後兩個都是好的,等等(消除過程)。哦 - 也許只是我的怪癖,但我在添加之前設置了AUSamplers(加載的字體等)。不知道這是否重要。 – 2012-07-30 04:05:52

1

我和你有完全相同的問題。所有曲目都使用第一個聲音文字工具播放。我遵循了你的解決方案,但一開始它不工作。最後,我解決了這個問題。如你所說,調用函數的順序確實是主調。是的。其實,順序調用應該是這樣的:

..... 
MusicSequenceSetAUGraph(s, _processingGraph); 
....... 
MusicTrackSetDestNode(track[i], samplerNodes[i]); 
...... 
[self loadFromDLSOrSoundFont]; 
...... 
MusicPlayerStart(p); 

這在我的項目中工作。

相關問題