Jim*_*myB 5 c++ audio xcode buffer audiounit
我写了一个简单的audiounit,它应该交换立体声源的左右声道.对于使用BASS库的命令行程序,此代码的移植版本在C中运行良好,但是我无法在Xcode中使用相同的代码来进行音频处理.
对于例如{1,2,3,4,5,6}的缓冲器输入,我预期立体声反转为{2,1,4,3,6,5}.
我的代码以这种方式正确地反转了样本,但我听到的只是某种低通滤波,而不是样本的立体反转.
输入缓冲区中的前4个值为:0.000104 0.000101 0.000080 0.000113
输出为:0.000101 0.000104 0.000113 0.000080
我是否误解了输入/输出缓冲区的结构方式?
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码不起作用的原因是因为你正在使用AudioUnit内核,它调用你的插件来处理一个音频数据通道(如果我理解的话).虽然在某些情况下内核可能非常方便,但它肯定不适用于执行相互依赖的立体声处理的插件.您正在传递回调中的频道数 - 您是否已检查此值?
无论如何,您应该从AUEffectBase类继承并覆盖该ProcessBufferLists()方法.然后,您将获得一个正确的AudioBufferList结构,其中包含每个音频通道的非隔行缓冲区.与使用内核相比,它还可以更好地控制渲染过程.
编辑:好的,事实证明,内核回调总是传递1个音频通道.另外,Render()我最初建议的覆盖并不是最好的方法.根据AUEffectBase.h源代码中的评论:
如果您的单元处理N到N个通道,并且通道之间没有交互,它可以覆盖NewKernel以为每个通道创建单声道处理对象.否则,不要覆盖NewKernel,而是覆盖ProcessBufferLists.
由于AUEffectBase不是"标准"AudioUnit代码的一部分,您需要将cpp/h文件添加到项目中.它们可以在AudioUnits/AUPublic/OtherBases文件夹中的AudioUnit SDK根目录下找到.所以对于你的插件,它看起来像这样:
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
};
Run Code Online (Sandbox Code Playgroud)
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++;
}
}
Run Code Online (Sandbox Code Playgroud)