filteraudiounitmixerremoteioaugraph

How to connect together RemoteIO, Mixer and Filter in AudioGraph?


I have a question about the node connection in AudioGraph. My idea is to receive from input the voice, turn it up volume with a mixer and filter with a low-pass filter.

Reading the book "Learning Core Audio" I was able to connect and to operate the input coupled to the filter, the input coupled to the mixer but I could not join the three elements.

I also looked at the sample code that Apple provides, but adapting it for my project does not work for me. I report my code:

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

So I ask for help. What should I do? The connection I made well? I had to set other properties?

Thank you for your attention.


Solution

  • I finally managed to run all three elements. The mistake I made was related to the setting of the properties. I leave the working code hoping That it can help someone who needs it. Bye!

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