Невозможно установить несколько музыкальных инструментов в iOS с помощью MusicPlayer и AUGraph

У меня есть MusicPlayer, который содержит MusicSequence, содержащий 3 MusicTracks. Я настроил AUGraph с 3 узлами AUSampler, подключенными к многоканальному микшеру, который, в свою очередь, подключен к выходному узлу.

Я использую SoundFont и хочу, чтобы мои 3 разных MusicTracks воспроизводились на 3 разных музыкальных инструментах, как описано здесь. Однако код, который у меня есть, не работает - вместо этого он воспроизводит только одну из частей.

Я создаю 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 инструмента из SoundFont (идентификаторы 0, 1 и 2 в SoundFont) следующим образом, передавая «bankURL» SoundFont:

// 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));

Наконец, я установил узлы AUSampler для использования каждым MusicTrack следующим образом:

//-------------------------------------------------
// 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, как я делал выше), он работает нормально.

Кто-нибудь знает, что я делаю неправильно?


person user1295558    schedule 05.04.2013    source источник


Ответы (2)


Я нашел решение. Перед загрузкой инструментов из SoundFont необходима следующая строка:

MusicSequenceSetAUGraph(testSequence, self.processingGraph);

Пока точка, в которой запускается эта строка, происходит до того, как инструменты загружаются из SoundFont и до того, как различные MusicTracks назначаются узлам AUSampler, кажется, что это работает - все партии воспроизводятся на разных инструментах, как хотелось бы. Этот ответ на связанный вопрос помог мне понять это.

person user1295558    schedule 06.04.2013

У меня была точно такая же проблема, как у вас. Все треки воспроизводятся с первым звуком шрифтового инструмента. Я следовал вашему решению, но сначала оно не сработало. Наконец решаю проблему. Как вы упомянули, последовательность вызова функций действительно имеет значение. Да это так. На самом деле вызов последовательности должен быть таким:

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

Это работает в моем проекте. Кстати, спасибо, что поделились своими кодами. Реально помогло :)

person dqshll    schedule 06.03.2014