Search code examples
macosaudio-processingavaudioengineavaudioplayernodeavaudioconverter

Change audio volume of some channels using AVAudioEngine


I'm working on a mac application that mix audio from a VideoCard and an external audio card.

How can I change volume on each channel (not each source) independently using AVAudioEngine.

Let's say I have an AVAudioPCMBuffer with 16 channels interleaved and I want channel 1 and 2 volume to 50% and other 100%

Should I convert from 1 AVAudioPCMBuffer with 16 channels to 16 mono AVAudioPCMBuffer and have one AVPlayerNode for each of them ? Then change the volume on each AVPlayerNode ?

Or can I keep o is there a way to change the underlying Audio Unit from the AVAudioMixerNode ?

Or should I use CoreAudio AudioUnits directly?


Solution

  • Changing audio volume by channel instead of by input, requires MatrixMixer. AVAudioEngine MainMixer is not a matrix mixer (mxmx) but a multi channel mixer (mcmx).

    In order to use a matrix mixer, use this code:

    AudioComponentDescription   mixerUnitDescription;
    
    mixerUnitDescription.componentType          = kAudioUnitType_Mixer;
    mixerUnitDescription.componentSubType       = kAudioUnitSubType_MatrixMixer;
    mixerUnitDescription.componentManufacturer  = kAudioUnitManufacturer_Apple;
    mixerUnitDescription.componentFlags         = 0;
    mixerUnitDescription.componentFlagsMask     = 0;
    
    [AVAudioUnit instantiateWithComponentDescription:mixerUnitDescription options:0 completionHandler:^(__kindof AVAudioUnit * _Nullable mixer, NSError * _Nullable error) {
    

    }];

    And change audio levels using

    AudioUnitSetParameter([_mixer audioUnit], kMatrixMixerParam_Volume, kAudioUnitScope_Input, i, volume, 0);