与合唱失真

时间:2013-11-15 19:28:03

标签: c++ xcode signal-processing core-audio effects

我是新手,可以插入开发和C ++。我正在尝试使用XCode音频单元模板编写合唱插件。但是,当我用正弦波测试插头时,我可以听到一些轻微的失真。我相信我使用的插值技术做错了,即使我经历了一千次并且无法弄清楚我做错了什么。这是我编写的代码,包括音频单元的重要部分:

    private: //state variables...
      enum {kWaveArraySize = 2000}; //number of points in the LFO sine array to hold the points
      float mSine[kWaveArraySize]; 
      float *waveArrayPointer;      //pointer to point in the array Variable to hold Sampling Rate
      Float32 SR;                   
      long mSamplesProcessed;          //variable to keep track of samples processed

      enum {sampleLimit = (int)10E6};  //limit to reset sine wave
      float mCurrentScale, mNextScale; //scaling factor for the LFO sine
      TAUBuffer<Float32> Buffer;       //circular buffer
      Float32 rawIndex;                //raw read Index
      UInt32 ReadIndex, NextIndex;     //the Read Index and the sample  after the Read Index for Linear Interpolation


      UInt32 WriteIndex;               //the Write Index
      UInt32 BufferSize;               //Size of Buffer
      UInt32 MaxBufferSize;            //Allocated Number of Samples
      Float32 DelayTime;               //Delay Time going to be calculated according to LFO

      Float32 inputSample, outputSample,
                        freq, Depth,               //Variables to hold the frequency of the LFO and Depth parameter

                        samplesPerCycle,           //number of samples per LFO cycle
                        InterpOutput,              //interpolated output variable
              fracDelay, DryValue, WetValue;  //fractional Delay, Dry and Wet value variables





VibratoUnit::VibratoUnitKernel::VibratoUnitKernel (AUEffectBase *inAudioUnit) : AUKernelBase (inAudioUnit),
mSamplesProcessed(0), mCurrentScale(0)
{
   for (int i = 0; i<kWaveArraySize; ++i)       //loop to calculate one cycle of LFO

   {
      double radians = i * 2.0 * pi / kWaveArraySize;
      mSine[i] = (sin(radians) + 1.0) * 0.5;
   }
   SR = GetSampleRate();
   BufferSize = SR;
   MaxBufferSize = BufferSize + 20;
   Buffer.AllocateClear(MaxBufferSize);
   ReadIndex = MaxBufferSize - 1;     
   WriteIndex = MaxBufferSize - 1;   //Give both ReadIndex and WriteIndex a Value outside the buffer so they would be reset to 0 in the process method



void      VibratoUnit::VibratoUnitKernel::Reset() //Reset and clear
{                                                       
   mCurrentScale = 0;
   mSamplesProcessed = 0;
   Buffer.Clear();
}





//------------------PROCESS METHOD-----------------------//

void      VibratoUnit::VibratoUnitKernel::Process(   const Float32    *inSourceP,
                                                    Float32          *inDestP,
                                                    UInt32          inFramesToProcess,
                                                    UInt32         inNumChannels,
                                                    bool         &ioSilence )
{



   UInt32 nSampleFrames = inFramesToProcess;
   const Float32 *sourceP = inSourceP;
   Float32 *destP = inDestP;
   freq = GetParameter(kParamFreq);
   Depth = GetParameter(kParamDepth);
   Depth = (SR/1000.0)*Depth;
   WetValue = GetParameter(kParamDryWet);
   DryValue = 1.0 - WetValue;
   waveArrayPointer = &mSine[0];
   samplesPerCycle = SR/freq;
   mNextScale = kWaveArraySize/samplesPerCycle;

   //----processing loop----//
   while (nSampleFrames-- > 0) {
      int index = static_cast<long> (mSamplesProcessed * mCurrentScale)%kWaveArraySize; //Find index for in the LFO wave table

      if ((mNextScale != mCurrentScale) && (index == 0))
      {
         mCurrentScale = mNextScale;
         mSamplesProcessed = 0;      //change LFO in 0 crossing
      }
      if ((mSamplesProcessed >= sampleLimit) && (index == 0))
      {
         mSamplesProcessed = 0;  // reset samples processed
      }
      if (WriteIndex >= BufferSize)   //reset write Index if goes outside the buffer

      {
         WriteIndex = 0;
      }
      inputSample = *sourceP;         

      sourceP += inNumChannels;   

      DelayTime = waveArrayPointer[index]; //receive raw sine value between 0 and 1

      DelayTime = (Depth*DelayTime)+Depth; //calculate delay value according to sine wave

      rawIndex = WriteIndex - DelayTime;   //calculate rawIndex relative to the write Index position


      if (rawIndex < 0) {
         rawIndex = BufferSize + rawIndex;
      }

      ReadIndex = (UInt32)rawIndex;        //calculate readIndex according to rawIndex position


      fracDelay = DelayTime - (UInt32)DelayTime; //calculate fractional delay time

      NextIndex = ReadIndex + 1;                 //for interpolation

      if (NextIndex >= BufferSize)               //bounds checking
      {
         NextIndex = 0;
      }

      InterpOutput = (fracDelay*Buffer[ReadIndex]) + ((1.0-fracDelay)*Buffer[NextIndex]);                    //calculate interpolated value

      Buffer[ReadIndex] = InterpOutput;  //write the interpolated output to buffer



      Buffer[WriteIndex] = inputSample;  //write inputsample to buffer
      outputSample = (Buffer[ReadIndex]*WetValue) + (inputSample * DryValue);                                //read output sample from buffer
      WriteIndex++;             //increment writeIndex


      mSamplesProcessed++;      //increment samplesprocessed
      *destP = outputSample;
      destP += inNumChannels;
   }
} 

提前感谢您的帮助。

0 个答案:

没有答案