0

我叫安东尼奥,来自意大利。
我正在尝试使用 xCode 3.2.6 创建一个音频单元,从 这个链接的示例开始。
这是我的第一个 AU 项目,我没有其他示例可循。
我的项目包含一个 IIR 陷波滤波器。我制作的算法工作正常(我在 Matlab 上测试过),但 AU 不能正常工作(在 AU Lab 上测试过)。.mp3 文件听起来经过过滤,但与方波(我猜是耳朵)之类的东西重叠。
该噪声的频率似乎与 f0 参数成正比。
这是 .cpp 文件代码:

// Filtro.cpp

#include "Filtro.h"
#define pi  3.1415926535



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

COMPONENT_ENTRY(Filtro)


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Filtro::Filtro
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Filtro::Filtro (AudioUnit component) : AUEffectBase (component) {
    CreateElements ();  
    Globals () -> UseIndexedParameters (kNumberOfParameters);
    SetParameter (kParameter_Gain, kDefaultValue_Gain);
    SetParameter (kParameter_f0, kDefaultValue_f0);
    SetParameter (kParameter_Q, kDefaultValue_Q);

//    code for setting default values for the audio unit parameters

}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Filtro::GetParameterInfo
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#pragma mark ____Parameters

ComponentResult Filtro::GetParameterInfo (
                                               AudioUnitScope          inScope,
                                               AudioUnitParameterID    inParameterID,
                                               AudioUnitParameterInfo  &outParameterInfo       
                                               ) {
    ComponentResult result = noErr;
    outParameterInfo.flags =    kAudioUnitParameterFlag_IsWritable        
    | kAudioUnitParameterFlag_IsReadable;
    if (inScope == kAudioUnitScope_Global) {                             
        switch (inParameterID) {
            case kParameter_Gain:                                      
                AUBase::FillInParameterName (
                                         outParameterInfo,
                                         kParamName_Gain,
                                         false
                                         );
            outParameterInfo.unit = kAudioUnitParameterUnit_Decibels;
            outParameterInfo.minValue = kMinimumValue_Gain;
            outParameterInfo.maxValue = kMaximumValue_Gain;
            outParameterInfo.defaultValue = kDefaultValue_Gain;
            break;
        case kParameter_f0:                                        // 9
            AUBase::FillInParameterName (
                                         outParameterInfo,
                                         kParamName_f0,
                                         false
                                         );
            outParameterInfo.unit = kAudioUnitParameterUnit_Hertz;
            outParameterInfo.minValue = kMinimumValue_f0;
            outParameterInfo.maxValue = kMaximumValue_f0;
            outParameterInfo.defaultValue = kDefaultValue_f0;
            outParameterInfo.flags |= kAudioUnitParameterFlag_DisplayLogarithmic;
            break;
        case kParameter_Q:                                        // 9
            AUBase::FillInParameterName (
                                         outParameterInfo,
                                         kParamName_Q,
                                         false
                                         );
            outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
            outParameterInfo.minValue = kMinimumValue_Q;
            outParameterInfo.maxValue = kMaximumValue_Q;
            outParameterInfo.defaultValue = kDefaultValue_Q;
            outParameterInfo.flags |= kAudioUnitParameterFlag_DisplayLogarithmic;
            break;

        default:
            result = kAudioUnitErr_InvalidParameter;
            break;

    }

} else {

    result = kAudioUnitErr_InvalidParameter;

}

return result;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Filtro::GetPropertyInfo
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus            Filtro::GetPropertyInfo (           AudioUnitPropertyID inID,
                                                AudioUnitScope      inScope,
                                                AudioUnitElement    inElement,
                                                UInt32              &outDataSize,
                                                Boolean             &outWritable)
{
        return AUEffectBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Filtro::GetProperty
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus            Filtro::GetProperty(        AudioUnitPropertyID inID,
                                            AudioUnitScope      inScope,
                                            AudioUnitElement    inElement,
                                            void                *outData )
    {
    return AUEffectBase::GetProperty (inID, inScope, inElement, outData);
}


    #pragma mark ____FiltroEffectKernel

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//    Filtro::FiltroKernel::FiltroKernel()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Filtro::FiltroKernel::FiltroKernel (AUEffectBase *inAudioUnit) :

AUKernelBase (inAudioUnit), mSamplesProcessed (0), mCurrentScale (0) // 1
{

    mSampleFrequency = GetSampleRate ();

}




//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Filtro::FiltroKernel::Reset()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Filtro::FiltroKernel::Reset() {
    mCurrentScale        = 0;           
    mSamplesProcessed    = 0;           
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Filtro::FiltroKernel::Process 
void Filtro::FiltroKernel::Process (const Float32   *inSourceP,                                      
                                          Float32         *inDestP,                                         
                                          UInt32          inSamplesToProcess,                             
                                          UInt32          inNumChannels,                                    
                                          bool            &ioSilence                                        
                                          ) {
if (!ioSilence) {                                                       
    const Float32 *sourceP = inSourceP;
    Float32  *destP = inDestP, inputSample, outputSample;
    Float32 Fs= mSampleFrequency;
    int f0;
    float   w0, alpha, b0, b1, b2, a0, a1, a2;
    float gain, dBgain, Q, coeff[5], x[5]={0,0,0,0,0} , out = 0;    

    dBgain = GetParameter (kParameter_Gain);                        //Get parameter from interface
    if (dBgain < kMinimumValue_Gain) dBgain = kMinimumValue_Gain;   //Check the right range
    if (dBgain > kMaximumValue_Gain) dBgain = kMaximumValue_Gain;
    f0 = GetParameter (kParameter_f0);          
    if (f0 < kMinimumValue_f0) f0 = kMinimumValue_f0;
    if (f0 > kMaximumValue_f0) f0 = kMaximumValue_f0;
    Q = GetParameter (kParameter_Q);            
    if (Q < kMinimumValue_Q) Q = kMinimumValue_Q;
    if (Q > kMaximumValue_Q) Q = kMaximumValue_Q;


    w0      = 2*pi*f0/Fs;
    alpha   = sin(w0)*sinh(log(2)/(log(exp(1))*2) * Q * w0/sin(w0));
    b0      = 1;
    b1      = -2*cos(w0);
    b2      = 1;
    a0      = 1 + alpha;
    a1      = -2*cos(w0);
    a2      = 1 - alpha;
    coeff[0] = b0/a0;
    coeff[1] = b1/a0;
    coeff[2] = b2/a0;
    coeff[3] = -a1/a0;
    coeff[4] = -a2/a0;      


    //----------------------------------------------------------------------------------------------//
    //  y(n) = b0/a0 * x(n) + b1/a0 * x(n-1) + b2/a0 * x(n-2) * -a1/a0 * y(n-1) * -a2/a0 * y(n-2)   //
    //----------------------------------------------------------------------------------------------//


    for (int i = inSamplesToProcess; i > 0; --i) {
       int index = static_cast<long>(mSamplesProcessed * mCurrentScale) % 512;  //?

        if ((mNextScale != mCurrentScale) && (index == 0)) {      //?? 
            mCurrentScale = mNextScale;
            mSamplesProcessed = 0;

        }

        if ((mSamplesProcessed >= sampleLimit) && (index == 0)) {  // ??
            mSamplesProcessed = 0;

        }   

        gain            = pow(10, dBgain/20);
        inputSample     = *sourceP;
        x[0]            = inputSample;      //x(n)
        x[3]            = outputSample;     //y(n-1)    
        for (int h = 0; h < 5; h++) {       // Processing output sample
           out = out+x[h]*coeff[h];     
        }
        for (int h = 4; h > 0; h--) {
            x[h]=x[h-1];                    //I/O array shifting
        }
        outputSample        = out * gain;
        out                 = 0;
        *destP              = outputSample;
        sourceP             += 1;
        destP               += 1;
        mSamplesProcessed   += 1;
    }
}
}

这就是头文件:

// Filtro.h

#include "AUEffectBase.h"

#include "AUEffectBase.h"
#include "FiltroVersion.h"

#if AU_DEBUG_DISPATCHER
    #include "AUDebugDispatcher.h"
#endif


#ifndef __Filtro_h__
#define __Filtro_h__


#pragma mark ____Filtro Parameter Constants


static CFStringRef kParamName_Gain      = CFSTR ("Gain");  
static const double kDefaultValue_Gain   = 0;
static const double kMinimumValue_Gain   = -40;
static const double kMaximumValue_Gain   = 0;

static CFStringRef kParamName_f0      = CFSTR ("f0");  
static const int kDefaultValue_f0   = 1048;
static const int kMinimumValue_f0   = 50;
static const int kMaximumValue_f0   = 20000;

static CFStringRef kParamName_Q      = CFSTR ("Q");  
static const double kDefaultValue_Q   = 0.1;
static const double kMinimumValue_Q   = 0.001;
static const double kMaximumValue_Q   = 10;



// parameter identifiers
enum {                                                                    // Defines     constants for identifying the parameters; defines the total number of parameters
kParameter_Gain         = 0,
kParameter_f0           = 1,
kParameter_Q            = 2,
kNumberOfParameters     = 3
};


#pragma mark ____Filtro
class Filtro : public AUEffectBase
{
public:
    Filtro(AudioUnit component);
#if AU_DEBUG_DISPATCHER
    virtual ~Filtro () { delete mDebugDispatcher; }
#endif

    virtual AUKernelBase *      NewKernel() { return new FiltroKernel(this); }

    virtual OSStatus            GetParameterInfo(AudioUnitScope         inScope,
                                             AudioUnitParameterID   inParameterID,
                                             AudioUnitParameterInfo &outParameterInfo);

virtual OSStatus            GetPropertyInfo(AudioUnitPropertyID     inID,
                                            AudioUnitScope          inScope,
                                            AudioUnitElement        inElement,
                                            UInt32 &            outDataSize,
                                            Boolean &           outWritable );

virtual OSStatus            GetProperty(AudioUnitPropertyID     inID,
                                        AudioUnitScope          inScope,
                                        AudioUnitElement        inElement,
                                        void *                  outData);

virtual bool                SupportsTail () { return false; }   // FIND

/*! @method Version */
virtual OSStatus        Version() { return kFiltroVersion; }

//      virtual ComponentResult GetPresets (CFArrayRef *outData) const;
//      virtual OSStatus NewFactoryPresetSet (const AUPreset &inNewFactoryPreset);   

protected:
    class FiltroKernel : public AUKernelBase {

    public:
        FiltroKernel (AUEffectBase *inAudioUnit); // 1
        virtual void Process (
                          const Float32    *inSourceP,
                          Float32          *inDestP,
                          UInt32           inFramesToProcess,
                          UInt32           inNumChannels,       // equal to 1
                          bool             &ioSilence
                          );
    virtual void Reset();

private:
    Float32  mSampleFrequency;                    
    long     mSamplesProcessed;                 
    enum     {sampleLimit = (int) 10E6};         
    float    mCurrentScale;                       
    float    mNextScale;                          
    };
};
#endif#include "FiltroVersion.h"

#if AU_DEBUG_DISPATCHER
    #include "AUDebugDispatcher.h"
#endif


#ifndef __Filtro_h__
#define __Filtro_h__


#pragma mark ____Filtro Parameter Constants



static CFStringRef kParamName_Gain      = CFSTR ("Gain");  
static const double kDefaultValue_Gain   = 0;
static const double kMinimumValue_Gain   = -40;
static const double kMaximumValue_Gain   = 0;

static CFStringRef kParamName_f0      = CFSTR ("f0");  
static const int kDefaultValue_f0   = 1048;
static const int kMinimumValue_f0   = 50;
static const int kMaximumValue_f0   = 20000;

static CFStringRef kParamName_Q      = CFSTR ("Q");  
static const double kDefaultValue_Q   = 0.1;
static const double kMinimumValue_Q   = 0.001;
static const double kMaximumValue_Q   = 10;



// parameter identifiers
enum {                                                                    // Defines     constants for identifying the parameters; defines the total number of parameters
kParameter_Gain         = 0,
kParameter_f0           = 1,
kParameter_Q            = 2,
kNumberOfParameters     = 3
};


#pragma mark ____Filtro
class Filtro : public AUEffectBase
{
public:
    Filtro(AudioUnit component);
#if AU_DEBUG_DISPATCHER
    virtual ~Filtro () { delete mDebugDispatcher; }
#endif

    virtual AUKernelBase *      NewKernel() { return new FiltroKernel(this); }

    virtual OSStatus                GetParameterInfo(AudioUnitScope         inScope,
                                             AudioUnitParameterID   inParameterID,
                                             AudioUnitParameterInfo &outParameterInfo);

virtual OSStatus                GetPropertyInfo(AudioUnitPropertyID     inID,
                                            AudioUnitScope          inScope,
                                            AudioUnitElement        inElement,
                                            UInt32 &            outDataSize,
                                            Boolean &           outWritable );

virtual OSStatus            GetProperty(AudioUnitPropertyID     inID,
                                        AudioUnitScope          inScope,
                                        AudioUnitElement        inElement,
                                        void *                  outData);

virtual bool                SupportsTail () { return false; }

/*! @method Version */
    virtual OSStatus        Version() { return kFiltroVersion; }



protected:
    class FiltroKernel : public AUKernelBase {

    public:
        FiltroKernel (AUEffectBase *inAudioUnit); 
    virtual void Process (
                          const Float32    *inSourceP,
                          Float32          *inDestP,
                          UInt32               inFramesToProcess,
                          UInt32           inNumChannels,   // equal to 1
                          bool             &ioSilence
                          );
    virtual void Reset();

    private:
        Float32  mSampleFrequency;                    
        long     mSamplesProcessed;                   
        enum     {sampleLimit = (int) 10E6};          
    float    mCurrentScale;                      
    float    mNextScale;                          
    };
};
#endif

非常感谢。我希望我的英语不要太差。

4

2 回答 2

0

您的过滤器实现对我来说看起来不正确。也许这很好,但很难遵循。例如,看起来您正在将存储的 x 值转换为存储的 y 值,即使您在下一个循环中清除了它,也有点难以理解。

您可能想在这里查看我是如何做到的:http: //blog.bjornroche.com/2012/08/basic-audio-eqs.html更干净!

此外,您是在处理单声道样本还是多声道音频,因为您的 Process 功能看起来只能按照您对单声道音频的预期工作。(我最近与 AU 合作的时间不足以通过查看您的代码自己回答这个问题)

于 2012-09-15T02:15:58.447 回答
0

问题解决了!!!3 天后,我找到了避免变量重置每个音频帧的正确方法。我只是将这些状态变量声明到 Filtro.h 文件底部的第四行,然后我将它们初始化为 Filtro.cpp 文件中的“AUKernelBase (inAudioUnit)”。我希望它可以对其他人有所帮助。再见。

于 2012-09-15T22:25:22.947 回答