带混音器的NewTimePitch

时间:2016-01-08 02:47:51

标签: ios core-audio

我的图表工作方式与Apple提供的示例应用程序非常相似。

https://developer.apple.com/library/ios/samplecode/MixerHost/Listings/Classes_MixerHostAudio_m.html#//apple_ref/doc/uid/DTS40010210-Classes_MixerHostAudio_m-DontLinkElementID_6

我的mixerNode由自定义数据(而不是吉他/节拍)提供 - 但设置类似。两个总线都是混音器的立体声。

我正在尝试移动内容,但到目前为止都没有成功。我已经尝试将kAudioUnitSubType_NewTimePitch添加到图形中,但每当我添加它时图形都无法创建。有没有任何一个源代码示例说明我如何使用调音台进行时间换档(换档所有总线)?

以下是一些有效的代码:

// Describe audio component
AudioComponentDescription output_desc;
bzero(&output_desc, sizeof(output_desc));
output_desc.componentType = kAudioUnitType_Output;
output_desc.componentSubType = self.componentSubType;
output_desc.componentFlags = 0;
output_desc.componentFlagsMask = 0;
output_desc.componentManufacturer = kAudioUnitManufacturer_Apple;


// multichannel mixer unit
AudioComponentDescription mixer_desc;
bzero(&mixer_desc, sizeof(mixer_desc));
mixer_desc.componentType = kAudioUnitType_Mixer;
mixer_desc.componentSubType = kAudioUnitSubType_MultiChannelMixer;
mixer_desc.componentFlags = 0;
mixer_desc.componentFlagsMask = 0;
mixer_desc.componentManufacturer = kAudioUnitManufacturer_Apple;

// Describe NewTimePitch component
AudioComponentDescription speed_desc;
bzero(&speed_desc, sizeof(speed_desc));
speed_desc.componentType = kAudioUnitType_FormatConverter;
speed_desc.componentSubType = kAudioUnitSubType_NewTimePitch;
speed_desc.componentFlags = 0;
speed_desc.componentFlagsMask = 0;
speed_desc.componentManufacturer = kAudioUnitManufacturer_Apple;


result = AUGraphAddNode(mGraph, &output_desc, &outputNode);
if (result) { printf("AUGraphNewNode 1 result %ld %4.4s\n", (long)result, (char*)&result); return; }

result = AUGraphAddNode(mGraph, &speed_desc, &timeNode );
if (result) { printf("AUGraphNewNode 2 result %ld %4.4s\n", (long)result, (char*)&result); return; }

result = AUGraphAddNode(mGraph, &mixer_desc, &mixerNode );
if (result) { printf("AUGraphNewNode 3 result %ld %4.4s\n", (long)result, (char*)&result); return; }

result = AUGraphConnectNodeInput(mGraph, mixerNode, 0, outputNode, 0);
if (result) { printf("AUGraphConnectNodeInput mixer-> time result %ld %4.4s\n", (long)result, (char*)&result); return; }

// open the graph AudioUnits are open but not initialized (no resource allocation occurs here)

result = AUGraphOpen(mGraph);
if (result) { printf("AUGraphOpen result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }

result = AUGraphNodeInfo(mGraph, mixerNode, NULL, &mMixer);
if (result) { printf("AUGraphNodeInfo mixer result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }

result = AUGraphNodeInfo(mGraph, timeNode, NULL, &mTime);
if (result) { printf("AUGraphNodeInfo time result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }

result = AUGraphNodeInfo(mGraph, outputNode, NULL, &mOutput);
if (result) { printf("AUGraphNodeInfo output result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }


UInt32 numbuses = 1;

result = AudioUnitSetProperty(mMixer, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &numbuses, sizeof(numbuses));
if (result) { printf("AudioUnitSetProperty bus result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }


for (int i = 0; i < numbuses; ++i) {
    // setup render callback struct
    AURenderCallbackStruct rcbs;
    rcbs.inputProc = &mixerInput;
    rcbs.inputProcRefCon = (__bridge void *)(outputStream);

    printf("set kAudioUnitProperty_SetRenderCallback for mixer input bus %d\n", i);

    // Set a callback for the specified node's specified input
    result = AUGraphSetNodeInputCallback(mGraph, mixerNode, i, &rcbs);
    // equivalent to AudioUnitSetProperty(mMixer, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, i, &rcbs, sizeof(rcbs));
    if (result) { printf("AUGraphSetNodeInputCallback result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }

    // set input stream format to what we want
    printf("set mixer input kAudioUnitProperty_StreamFormat for bus %d\n", i);

result = AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, i, mAudioFormat.streamDescription, sizeof(AudioStreamBasicDescription));
    if (result) { printf("AudioUnitSetProperty result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }
}

result = AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamInAudioFormat, sizeof(streamInAudioFormat));
if (result) { printf("AudioUnitSetProperty mixer result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }

result = AudioUnitSetProperty(mOutput, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &streamInAudioFormat, sizeof(streamInAudioFormat));
if (result) { printf("AudioUnitSetProperty output result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }

CAShow(mGraph);
// now that we've set everything up we can initialize the graph, this will also validate the connections
result = AUGraphInitialize(mGraph);
if (result) { printf("AUGraphInitialize result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }

此代码有效 - 我有一个可以通过回调将数据泵入的混音器。您可以看到我已经创建了时间节点,但无论我将其插入到图表中,它都会杀死它。我无法在其上设置流格式或其他任何内容。

理想情况下,我想做这样的事情:

result = AUGraphConnectNodeInput(mGraph, mixerNode, 0, timeNode, 0);
result = AUGraphConnectNodeInput(mGraph, timeNode, 0, outputNode, 0);

但这不起作用。

以下是该设置的输出:

AudioUnitGraph 0x385003:
  Member Nodes:
    node 1: 'auou' 'vpio' 'appl', instance 0x134f40b10 O  
    node 2: 'aufc' 'nutp' 'appl', instance 0x134e733b0 O  
    node 3: 'aumx' 'mcmx' 'appl', instance 0x134ea71d0 O  
  Connections:
    node   3 bus   0 => node   2 bus   0  [ 2 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
    node   2 bus   0 => node   1 bus   0  [ 1 ch,      0 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
  Input Callbacks:
    {0x100038ea0, 0x134f7f900} => node   3 bus   0  [2 ch, 44100 Hz]
  CurrentState:
    mLastUpdateError=0, eventsToProcess=F, isInitialized=F, isRunning=F
2016-01-07 23:21:32.230 R5ProTestbed[901:503908] 23:21:32.229 ERROR:    [0x19ff25000] 2776: ConnectAudioUnit failed with error -10868
2016-01-07 23:21:32.230 R5ProTestbed[901:503908] 23:21:32.230 ERROR:    [0x19ff25000] 1682: Initialize failed with error -10868

3 个答案:

答案 0 :(得分:0)

根据CAShow,您当前的图表是这样的: 混合器 - &gt; TimePitch - &gt; VoiceProcess (您的输出节点不在图表中)

您无法另外将调音台输出连接到其他位置 在你的代码中,你有这样的

result = AUGraphConnectNodeInput(mGraph, mixerNode, 0, timeNode, 0);

因此您无法添加

result = AUGraphConnectNodeInput(mGraph, mixerNode, 0, outputNode, 0);

上述两行都会导致图表混乱,并且无法知道您希望混音器输出的位置。

同样,您将混音器输出连接到输出节点

result = AUGraphConnectNodeInput(mGraph, mixerNode, 0, outputNode, 0);

因此,您也不能将时间节点连接到outputNode

result = AUGraphConnectNodeInput(mGraph, timeNode, 0, outputNode, 0);

由于输出Node有两个输入且只能有一个输入,因此将这两个混淆在一起。 这就像你试图建立“Y”连接,就连接而言,你无法做到这一点。

您可以将输出放到一个输入中,这样两条线都会发生冲突。弄清楚你想要它在链中的位置,并将一个输出连接到一个输入 然后将render回调设置为链中的第一个节点。

从你的评论“我正在尝试做混音器 - &gt; newtimepitch-&gt; IO” 你需要制作三个节点,

  • 将调音台输出连接到Time Pitch
  • 将Time Pitch连接到RemoteIO

您需要3个节点。两个AUGraphConnectNodeInput()调用。 将渲染回调连接到调音台。像这样:

result = AUGraphConnectNodeInput(mGraph, mixerNode, 0, timeNode, 0);
result = AUGraphConnectNodeInput(mGraph, timeNode, 0, outputNode, 0); 
像你一样。确保从代码中删除其他节点连接。我无法判断您是否删除了其他连接或将其留在了中并添加了更多连接。

答案 1 :(得分:0)

如果未手动配置错误检查,则默认音频格式可能不合适。您需要将混音器的输出格式设置为时间间隔单位的输入格式,输出节点(RemoteIO?)的输入格式设置为时间间隔单位的输出格式。在连接单元之前需要配置格式。

请勿在时间间距单位上设置格式。获取时间间隔单位的格式,并在时间间距连接的所有内容上设置这些格式。

答案 2 :(得分:0)

hotpaw2在我自己弄清楚之后立即回答。非常感谢。我在混音器和IO的输出上设置StreamFormat,通过停止,转换器能够运行。

//    result = AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamInAudioFormat, sizeof(streamInAudioFormat));
//    if (result) { printf("AudioUnitSetProperty mixer result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }

//    result = AudioUnitSetProperty(mOutput, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &streamInAudioFormat, sizeof(streamInAudioFormat));
//    if (result) { printf("AudioUnitSetProperty output result %ld %08lX %4.4s\n", (long)result, (long)result, (char*)&result); return; }