I've written a simple audiounit that should swap the left and right channels of a stereo source. A ported version of this code worked fine in C for a command-line program that used the BASS library, but I'm having trouble getting the same code to work in Xcode for an audiounit.
For a buffer input of, for example, {1, 2, 3, 4, 5, 6}, i would expect the stereo reversal to be {2, 1, 4, 3, 6, 5}.
My code correctly reverses the samples in this manner, but all I hear is some sort of low-pass filtering, rather than a stereo reversal of samples.
The first 4 values in my input buffer are: 0.000104 0.000101 0.000080 0.000113
The output is: 0.000101 0.000104 0.000113 0.000080
Have I misunderstood something about the way the input/output buffers are structured?
void        First::FirstKernel::Process(    const Float32   *inSourceP,
                                                Float32         *inDestP,
                                                UInt32          inSamplesToProcess,
                                                UInt32          inNumChannels, 
                                                bool            &ioSilence )
{
if (!ioSilence) {                                                 
    const Float32 *sourceP = inSourceP;  
    Float32  *destP = inDestP;  
    for (int i = inSamplesToProcess/2; i>0; --i) { 
        *(destP+1) = *sourceP;
        *destP = *(sourceP+1);
        sourceP = sourceP +2;
        destP = destP +2;
}   
}   
}
                The reason that this code isn't working is because you are using AudioUnit kernels, which call your plugin to process a single channel of audio data (if I understand correctly). While kernels can be quite convenient in some cases, it's definitely not going to work for a plugin which does interdependent stereo processing. You are being passed the number of channels in your callback -- have you checked this value?
Regardless, you should instead inherit from the AUEffectBase class and override the ProcessBufferLists() method. Then you will get a proper AudioBufferList structure which contains non-interlaced buffers for each audio channel. It will also give you much finer control over the rendering process than using kernels.
Edit: Ok, it turns out that the Kernel callback is always being passed 1 channel of audio. Also, overridding Render() as I originally suggested is not the best way to do this. According to a comment in the AUEffectBase.h source code:
If your unit processes N to N channels, and there are no interactions between channels, it can override NewKernel to create a mono processing object per channel. Otherwise, don't override NewKernel, and instead, override ProcessBufferLists.
As AUEffectBase isn't part of the "standard" AudioUnit code, you will need to add the cpp/h files into your project. They can be found under the AudioUnit SDK root in the AudioUnits/AUPublic/OtherBases folder. So for your plugin, that would look something like this:
MyEffect.h:
#include "AUEffectBase.h"
class MyEffect : public AUEffectBase {
public:
  // Constructor, other overridden methods, etc.
  virtual OSStatus ProcessBufferLists(AudioUnitRenderActionFlags &ioActionFlags,
                                      const AudioBufferList &inBuffer,
                                      AudioBufferList &outBuffer,
                                      UInt32 inFramesToProcess);
private:
  // Private member variables, methods
};
MyEffect.cpp:
// Other stuff ....
OSStatus MyEffect::ProcessBufferLists(AudioUnitRenderActionFlags &ioActionFlags,
                                      const AudioBufferList &inBuffer,
                                      AudioBufferList &outBuffer,
                                      UInt32 inFramesToProcess) {
  const float *srcBufferL = (Float32 *)inBuffer.mBuffers[0].mData;
  const float *srcBufferR = (Float32 *)inBuffer.mBuffers[1].mData;
  float *destBufferL = (Float32 *)outBuffer.mBuffers[0].mData;
  float *destBufferR = (Float32 *)outBuffer.mBuffers[1].mData;
  for(UInt32 frame = 0; frame < inFramesToProcess; ++frame) {
    *destBufferL++ = *srcBufferL++;
    *destBufferR++ = *srcBufferR++;
  }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With