4

3 つの MusicTracks を含む MusicSequence を保持する MusicPlayer があります。3 つの AUSampler ノードをマルチチャンネル ミキサーに接続して AUGraph をセットアップしました。マルチチャンネル ミキサーは出力ノードに接続されています。

私はサウンドフォントを使用しており、ここで説明されているように、3 つの異なる MusicTracks を 3 つの異なる楽器で再生したいと考えています。しかし、私が入手したコードは機能しません。代わりに、1 つの部分しか再生しません。

次のように 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);

次に、SoundFont から 3 つのインストゥルメント (SoundFont の ID 0、1、および 2) を次のようにロードし、SoundFont の「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 を再生すると、1 つのパートしか再生されません。異なる楽器を使用しようとすると問題が発生します。標準の MusicPlayer セットアップで単一の楽器を使用すると (上記のように AUGraph を編集するのではなく)、正常に動作します。

誰かが私が間違っていることを知っていますか?

4

2 に答える 2

4

私は解決策を見つけました。サウンドフォントからインストゥルメントをロードする前に、次の行が必要です:

MusicSequenceSetAUGraph(testSequence, self.processingGraph);

インストゥルメントがサウンドフォントから読み込まれる前、およびさまざまな MusicTracks が AUSampler ノードに割り当てられる前に、この行が実行される限り、機能しているように見えます。必要に応じて、すべてのパートが異なるインストゥルメントで再生されます。関連する質問に対するこの回答は、これを理解するのに役立ちました。

于 2013-04-06T12:33:25.393 に答える
0

私はあなたとまったく同じ問題を抱えていました。すべてのトラックは、最初のサウンド フォント インストゥルメントで再生されます。私はあなたの解決策に従いましたが、最初はうまくいきません。最後に、問題を解決します。あなたが言ったように、関数を呼び出すシーケンスは本当に重要です。はい、そうです。実際、シーケンス呼び出しは次のようになります。

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

これは私のプロジェクトで機能します。ところで、コードを共有していただきありがとうございます。本当に助かりました:)

于 2014-03-06T08:00:54.413 に答える