2013-04-05 93 views
4

我有一个MusicPlayer,其中包含一个包含3个音乐轨道的MusicSequence。我已经建立了一个AUGraph,其中3个AUSampler节点插入多声道混音器,而后者又连接到输出节点。无法在iOS中使用MusicPlayer和AUGraph设置多个乐器

我正在使用SoundFont,并希望我的3种不同的MusicTrack可以在3种不同的乐器上演奏,如here所述。但是,我得到的代码不起作用 - 相反,它只扮演其中一个部分。

我创建AUGraph如下:

NewAUGraph (&_processingGraph); 
AUNode samplerNode, samplerNodeTwo, samplerNodeThree, ioNode, mixerNode; 

AudioComponentDescription cd = {}; 
cd.componentManufacturer  = kAudioUnitManufacturer_Apple; 

//---------------------------------------- 
// Add 3 Sampler unit nodes to the graph 
//---------------------------------------- 
cd.componentType = kAudioUnitType_MusicDevice; 
cd.componentSubType = kAudioUnitSubType_Sampler; 

AUGraphAddNode (self.processingGraph, &cd, &samplerNode); 
AUGraphAddNode (self.processingGraph, &cd, &samplerNodeTwo); 
AUGraphAddNode (self.processingGraph, &cd, &samplerNodeThree); 

//----------------------------------- 
// 2. Add a Mixer unit node to the graph 
//----------------------------------- 
cd.componentType   = kAudioUnitType_Mixer; 
cd.componentSubType  = kAudioUnitSubType_MultiChannelMixer; 

AUGraphAddNode (self.processingGraph, &cd, &mixerNode); 

//-------------------------------------- 
// 3. Add the Output unit node to the graph 
//-------------------------------------- 
cd.componentType = kAudioUnitType_Output; 
cd.componentSubType = kAudioUnitSubType_RemoteIO; // Output to speakers 

AUGraphAddNode (self.processingGraph, &cd, &ioNode); 

//--------------- 
// Open the graph 
//--------------- 
AUGraphOpen (self.processingGraph); 

//----------------------------------------------------------- 
// Obtain the mixer unit instance from its corresponding node 
//----------------------------------------------------------- 
AUGraphNodeInfo (
          self.processingGraph, 
          mixerNode, 
          NULL, 
          &mixerUnit 
          ); 

//-------------------------------- 
// Set the bus count for the mixer 
//-------------------------------- 
UInt32 numBuses = 3; 
AudioUnitSetProperty(mixerUnit, 
           kAudioUnitProperty_ElementCount, 
           kAudioUnitScope_Input, 
           0, 
           &numBuses, 
           sizeof(numBuses)); 



//------------------ 
// Connect the nodes 
//------------------ 

AUGraphConnectNodeInput (self.processingGraph, samplerNode, 0, mixerNode, 0); 
AUGraphConnectNodeInput (self.processingGraph, samplerNodeTwo, 0, mixerNode, 1); 
AUGraphConnectNodeInput (self.processingGraph, samplerNodeThree, 0, mixerNode, 2); 

// Connect the mixer unit to the output unit 
AUGraphConnectNodeInput (self.processingGraph, mixerNode, 0, ioNode, 0); 

// Obtain references to all of the audio units from their nodes 
AUGraphNodeInfo (self.processingGraph, samplerNode, 0, &_samplerUnit); 
AUGraphNodeInfo (self.processingGraph, samplerNodeTwo, 0, &_samplerUnitTwo); 
AUGraphNodeInfo (self.processingGraph, samplerNodeThree, 0, &_samplerUnitThree); 
AUGraphNodeInfo (self.processingGraph, ioNode, 0, &_ioUnit); 

我然后从音色库加载3台仪器(IDS 0,1和在音色库2)如下,传入的音色库的“bankURL” :

// Load the first instrument 
AUSamplerBankPresetData bpdata; 
bpdata.bankURL = (__bridge CFURLRef) bankURL; 
bpdata.bankMSB = kAUSampler_DefaultMelodicBankMSB; 
bpdata.bankLSB = kAUSampler_DefaultBankLSB; 
bpdata.presetID = (UInt8) 0; 

AudioUnitSetProperty(self.samplerUnit, 
           kAUSamplerProperty_LoadPresetFromBank, 
           kAudioUnitScope_Global, 
           0, 
           &bpdata, 
           sizeof(bpdata)); 

// Load the second instrument 
AUSamplerBankPresetData bpdataTwo; 
bpdataTwo.bankURL = (__bridge CFURLRef) bankURL; 
bpdataTwo.bankMSB = kAUSampler_DefaultMelodicBankMSB; 
bpdataTwo.bankLSB = kAUSampler_DefaultBankLSB; 
bpdataTwo.presetID = (UInt8) 1; 

AudioUnitSetProperty(self.samplerUnitTwo, 
           kAUSamplerProperty_LoadPresetFromBank, 
           kAudioUnitScope_Global, 
           0, 
           &bpdataTwo, 
           sizeof(bpdataTwo)); 

// Load the third instrument 
AUSamplerBankPresetData bpdataThree; 
bpdataThree.bankURL = (__bridge CFURLRef) bankURL; 
bpdataThree.bankMSB = kAUSampler_DefaultMelodicBankMSB; 
bpdataThree.bankLSB = kAUSampler_DefaultBankLSB; 
bpdataThree.presetID = (UInt8) 2; 

AudioUnitSetProperty(self.samplerUnitThree, 
           kAUSamplerProperty_LoadPresetFromBank, 
           kAudioUnitScope_Global, 
           0, 
           &bpdataThree, 
           sizeof(bpdataThree)); 

最后,我设置由每个MusicTrack使用的AUSampler节点如下:

//------------------------------------------------- 
// Set the AUSampler nodes to be used by each track 
//------------------------------------------------- 
MusicTrack track, trackTwo, trackThree; 
MusicSequenceGetIndTrack(testSequence, 0, &track); 
MusicSequenceGetIndTrack(testSequence, 1, &trackTwo); 
MusicSequenceGetIndTrack(testSequence, 2, &trackThree); 

AUNode samplerNode, samplerNodeTwo, samplerNodeThree; 
AUGraphGetIndNode (self.processingGraph, 0, &samplerNode); 
AUGraphGetIndNode (self.processingGraph, 1, &samplerNodeTwo); 
AUGraphGetIndNode (self.processingGraph, 2, &samplerNodeThree); 

MusicTrackSetDestNode(track, samplerNode); 
MusicTrackSetDestNode(trackTwo, samplerNodeTwo); 
MusicTrackSetDestNode(trackThree, samplerNodeThree); 

但是,当我播放MusicPlayer时,我只听到一个部分播放。尝试使用不同乐器时会出现问题 - 当我使用带有标准MusicPlayer设置的单个乐器(而不是像上面那样编辑AUGraph)时,它可以正常工作。

有没有人有任何想法我做错了什么?

回答

4

我找到了解决方案。加载从音色库仪器前,需要以下行:

MusicSequenceSetAUGraph(testSequence, self.processingGraph); 

只要在此线运行点自带的工具是从音色库加载和各种MusicTracks分配AUSampler节点之前前,它似乎工作 - 所有部分都根据需要在不同的乐器上演奏。 This answer到一个相关的问题帮我弄明白了。

0

我和你有完全相同的问题。所有曲目都使用第一个声音文字工具播放。 我遵循你的解决方案,但它一开始不工作。最后,我解决了这个问题。如你所说,调用函数的顺序确实是主调。是的。其实,顺序调用应该是这样的:

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

这在我的项目中工作。 顺便说一句,感谢您分享您的代码。真的帮了:)