如何在 AudioGraph 中将 RemoteIO、Mixer 和 Filter 连接在一起?

Posted

技术标签:

【中文标题】如何在 AudioGraph 中将 RemoteIO、Mixer 和 Filter 连接在一起?【英文标题】:How to connect together RemoteIO, Mixer and Filter in AudioGraph? 【发布时间】:2017-02-21 08:43:22 【问题描述】:

我对 AudioGraph 中的节点连接有疑问。我的想法是接收输入的声音,用混音器调高音量,用低通滤波器进行滤波。

阅读《Learning Core Audio》一书,我能够连接和操作耦合到滤波器的输入,耦合到混音器的输入,但我无法连接这三个元素。

我还查看了 Apple 提供的示例代码,但为我的项目调整它对我不起作用。我报告我的代码:

    AUGraph AudioGraph;



    CheckError(NewAUGraph(&AudioGraph), "No new Graph");




    AUNode rioNode;
    AUNode mixerNode;
    AUNode filterNode;

    AudioComponentDescription AudioCompDescRIO;
    AudioCompDescRIO.componentType  = kAudioUnitType_Output;
    AudioCompDescRIO.componentSubType = kAudioUnitSubType_RemoteIO;
    AudioCompDescRIO.componentManufacturer = kAudioUnitManufacturer_Apple;
    AudioCompDescRIO.componentFlags = 0;
    AudioCompDescRIO.componentFlagsMask = 0;

    CheckError(AUGraphAddNode(AudioGraph, &AudioCompDescRIO, &rioNode), "No add Node");


    AudioComponentDescription AudioCompDescMixer;
    AudioCompDescMixer.componentType = kAudioUnitType_Mixer;
    AudioCompDescMixer.componentSubType = kAudioUnitSubType_MultiChannelMixer;
    AudioCompDescMixer.componentManufacturer = kAudioUnitManufacturer_Apple;
    AudioCompDescMixer.componentFlags = 0;
    AudioCompDescMixer.componentFlagsMask = 0;

    CheckError(AUGraphAddNode(AudioGraph, &AudioCompDescMixer, &mixerNode), "No add Node");


    AudioComponentDescription AudioCompDescFiler;
    AudioCompDescFiler.componentType = kAudioUnitType_Effect;
    AudioCompDescFiler.componentSubType = kAudioUnitSubType_LowPassFilter;
    AudioCompDescFiler.componentManufacturer = kAudioUnitManufacturer_Apple;
    AudioCompDescFiler.componentFlags = 0;
    AudioCompDescFiler.componentFlagsMask = 0;

    CheckError(AUGraphAddNode(AudioGraph, &AudioCompDescFiler, &filterNode), "No add Node");




    CheckError(AUGraphOpen(AudioGraph), "No open Graph");



    AudioUnit rioUnit;
    AudioUnit mixerUnit;
    AudioUnit filterUnit;



    CheckError(AUGraphNodeInfo(AudioGraph, rioNode, NULL, &rioUnit), "No node info");
    CheckError(AUGraphNodeInfo(AudioGraph, mixerNode, NULL, &mixerUnit), "No node info");
    CheckError(AUGraphNodeInfo(AudioGraph, filterNode, NULL, &filterUnit), "No node info");







    UInt32 bytesPerSample = sizeof(Float32);

    AudiostreamBasicDescription asbd;

    bzero(&asbd, sizeof(asbd));
    asbd.mSampleRate = 44100;
    asbd.mFormatID = kAudioFormatLinearPCM;
    asbd.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
    asbd.mBitsPerChannel = 8 * bytesPerSample;
    asbd.mBytesPerFrame = bytesPerSample;
    asbd.mBytesPerPacket = bytesPerSample;
    asbd.mFramesPerPacket = 1;
    asbd.mChannelsPerFrame = 2;





    AudioUnitElement inputElement = 1;


    UInt32 enableIO = 1;
    CheckError(AudioUnitSetProperty(rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, inputElement, &enableIO, sizeof(enableIO)), "No set property");


    AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &asbd, sizeof(asbd));
    AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &asbd, sizeof(asbd));


    AURenderCallbackStruct callbackStruct;
    callbackStruct.inputProc = inputRenderCallback;
    callbackStruct.inputProcRefCon = (__bridge void * _Nullable)(self);
    AUGraphSetNodeInputCallback(AudioGraph, mixerNode, 0, &callbackStruct);




    AUGraphConnectNodeInput(AudioGraph, rioNode, 1, mixerNode, 0);
    AUGraphConnectNodeInput(AudioGraph, mixerNode, 0, filterNode, 0);
    AUGraphConnectNodeInput(AudioGraph, filterNode, 0, rioNode, 0);




    CheckError(AUGraphInitialize(AudioGraph), "No initialize graph");

所以我寻求帮助。我该怎么办?我做好的连接?我必须设置其他属性吗?

感谢您的关注。

【问题讨论】:

【参考方案1】:

我终于设法运行了所有三个元素。我犯的错误与属性的设置有关。我留下工作代码希望它可以帮助需要它的人。再见!

    CheckError(NewAUGraph(&AudioGraph), "No new Graph");

    AUNode rioNode;
    AUNode mixerNode;
    AUNode filterNode;


    AudioComponentDescription AudioCompDescRIO;
    AudioCompDescRIO.componentType  = kAudioUnitType_Output;
    AudioCompDescRIO.componentSubType = kAudioUnitSubType_RemoteIO;
    AudioCompDescRIO.componentManufacturer = kAudioUnitManufacturer_Apple;
    AudioCompDescRIO.componentFlags = 0;
    AudioCompDescRIO.componentFlagsMask = 0;

    CheckError(AUGraphAddNode(AudioGraph, &AudioCompDescRIO, &rioNode), "No add Node");


    AudioComponentDescription AudioCompDescMixer;
    AudioCompDescMixer.componentType = kAudioUnitType_Mixer;
    AudioCompDescMixer.componentSubType = kAudioUnitSubType_MultiChannelMixer;
    AudioCompDescMixer.componentManufacturer = kAudioUnitManufacturer_Apple;
    AudioCompDescMixer.componentFlags = 0;
    AudioCompDescMixer.componentFlagsMask = 0;

    CheckError(AUGraphAddNode(AudioGraph, &AudioCompDescMixer, &mixerNode), "No add Node");


    AudioComponentDescription AudioCompDescFiler;
    AudioCompDescFiler.componentType = kAudioUnitType_Effect;
    AudioCompDescFiler.componentSubType = kAudioUnitSubType_LowPassFilter;
    AudioCompDescFiler.componentManufacturer = kAudioUnitManufacturer_Apple;
    AudioCompDescFiler.componentFlags = 0;
    AudioCompDescFiler.componentFlagsMask = 0;

    CheckError(AUGraphAddNode(AudioGraph, &AudioCompDescFiler, &filterNode), "No add Node");


    CheckError(AUGraphOpen(AudioGraph), "No open Graph");

    AudioUnit rioUnit;
    AudioUnit mixerUnit;
    AudioUnit filterUnit;


    CheckError(AUGraphNodeInfo(AudioGraph, rioNode, NULL, &rioUnit), "No node info");
    CheckError(AUGraphNodeInfo(AudioGraph, mixerNode, NULL, &mixerUnit), "No node info");
    CheckError(AUGraphNodeInfo(AudioGraph, filterNode, NULL, &filterUnit), "No node info");


    UInt32 bytesPerSample = sizeof(Float32);

    AudioStreamBasicDescription asbd;
    bzero(&asbd, sizeof(asbd));
    asbd.mSampleRate = 44100;
    asbd.mFormatID = kAudioFormatLinearPCM;
    asbd.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
    asbd.mBitsPerChannel = 8 * bytesPerSample;
    asbd.mBytesPerFrame = bytesPerSample;
    asbd.mBytesPerPacket = bytesPerSample;
    asbd.mFramesPerPacket = 1;
    asbd.mChannelsPerFrame = 2;

    AudioUnitElement inputElement = 1;

    AudioUnitSetProperty(rioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, inputElement, &asbd, sizeof(asbd));


    UInt32 enableIO = 1;
    AudioUnitSetProperty(rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, inputElement,  &enableIO, sizeof(enableIO));


    UInt32 mixerElementCount = 3;
    AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &mixerElementCount, sizeof(mixerElementCount));

    AURenderCallbackStruct callbackStruct;
    callbackStruct.inputProc = &inputRenderCallback;
    callbackStruct.inputProcRefCon = (__bridge void *)self;

    AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 1, &callbackStruct, sizeof(callbackStruct));

    AudioUnitSetProperty(mixerUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 2, &callbackStruct, sizeof(callbackStruct));

    AudioUnitSetParameter (mixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, 0, 1, 0);

    AudioUnitSetParameter(filterUnit, kLowPassParam_CutoffFrequency, kAudioUnitScope_Global, 0, 2500, 0);

    AUGraphConnectNodeInput(AudioGraph, rioNode, 1, mixerNode, 0);
    AUGraphConnectNodeInput(AudioGraph, mixerNode, 0, filterNode, 0);
    AUGraphConnectNodeInput(AudioGraph, filterNode, 0, rioNode, 0);

    CAShow(AudioGraph);

    CheckError(AUGraphInitialize(AudioGraph), "No initialize graph");

    AUGraphStart(AudioGraph);

【讨论】:

以上是关于如何在 AudioGraph 中将 RemoteIO、Mixer 和 Filter 连接在一起?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用默认输出设备作为使用 AudioGraph 录制音频的源?

最小化或锁定时继续播放 Audiograph UWP 输出

uwp AudioGraph 音频处理

AudioGraph 可以播放流吗?

AudioGraph DesiredSamplesPerQuantum 属性被忽略

如何为 AudioGraph 添加固定增益?