【问题标题】:Can't set multiple musical instruments in iOS using MusicPlayer and AUGraph无法在 iOS 中使用 MusicPlayer 和 AUGraph 设置多个乐器
【发布时间】:2013-03-27 15:31:30
【问题描述】:

我有一个 MusicPlayer,它包含一个包含 3 个 MusicTrack 的 MusicSequence。我已经设置了一个 AUGraph,其中 3 个 AUSampler 节点插入到多通道混音器中,该混音器又连接到输出节点。

我正在使用 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);

然后我从 SoundFont(SoundFont 中的 ID 0、1 和 2)加载 3 种乐器,如下所示,传入 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 时,我只听到一个部分正在播放。尝试使用不同乐器时会出现问题 - 当我使用具有标准 MusicPlayer 设置的单个乐器时(而不是像上面那样编辑 AUGraph),它可以正常工作。

有人知道我做错了什么吗?

【问题讨论】:

    标签: objective-c core-audio mixer


    【解决方案1】:

    我遇到了和你一样的问题。所有曲目都使用第一个声音字体乐器播放。 我遵循了您的解决方案,但起初它不起作用。最后,我解决了这个问题。 正如您所提到的,调用函数的顺序确实很重要。是的。其实序列调用应该是这样的:

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

    这适用于我的项目。 顺便说一句,感谢您分享您的代码。真的有帮助:)

    【讨论】:

      【解决方案2】:

      我找到了解决方案。在从 SoundFont 加载乐器之前,需要以下行:

      MusicSequenceSetAUGraph(testSequence, self.processingGraph);
      

      只要这条线的运行点出现在从 SoundFont 加载乐器之前以及在为各种 MusicTrack 分配 AUSampler 节点之前,它似乎就可以工作 - 所有部分都根据需要在不同的乐器上演奏。 This answer 到一个相关问题帮助我解决了这个问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-17
        • 1970-01-01
        • 2014-09-14
        相关资源
        最近更新 更多