AnsweredAssumed Answered

Sample Rate Distortion/Aliasing on ADCs

Question asked by Palaima.Emmett on Jul 9, 2016
Latest reply on Jul 9, 2016 by Palaima.Emmett
Hi, I am doing some audio programming on the STM32F4 and I am noticing that there is some distortion/aliasing happening around the sample rate. I was writing a program that reads the incoming audio into a delay buffer and reads back its contents at a slower rate, pitching down the signal, and this brings this aliasing/distortion into audible range. I have tested this out and have found that the pitch of the aliasing is a division of the sample rate based on how much I am slowing the signal down (i.e. If I play the buffer back at 10% speed with a sample rate of 48000 this will create a 4800Hz tone).

I am wondering if there is any way I can set up my program differently to avoid this aliasing. I am currently setting up sample rate via a 2 step timer set at a frequency of 48000. I use a flag to prevent steps from repeating. I have also tried implementing a simple lowpass filter, but the aliasing still occurs.

Is this an unavoidable biproduct of the onboard ADCs, or is there something I can do to get around this? Any suggestions appreciated, I just figured out how to set a lot of this stuff up so let me know if you see anything flawed in my methodology. Code below. Thanks!

Here is my while loop:

  while (1)
      int timerValue = TIM_GetCounter(TIM2);
      if (timerValue == 1 && timerFlag == 0){
           timerFlag = 1;
           if(delayCounter >= 48000){
                delayCounter -= 48000;
           ADC2ConvertedVoltage = (ADC2ConvertedValue *3300/0xFFF);
           gain = ((float)ADC3ConvertedValue)/4095;
           diveSwitch = ((float)ADC1ConvertedValue[0])/4095;

            filterFeedback = (1.5*ADC2ConvertedValue) - (.5*filterFeedback);

           if(diveSwitch >= .5){
                if(delayCounter < 48000){
                     delay[delayCounter] = filterFeedback;
                if(diveCounter <= 47999 && delayCounter >= 1){
                     //diveIncr = .1;
                     castDiveCounter = (int)diveCounter;
                     interp = diveCounter - castDiveCounter;
                     output = ((float)delay[castDiveCounter]*(1-interp))+((float)delay[castDiveCounter+1]*interp)*(3300/0xFFF);
                     diveCounter += diveIncr;
                     if(diveIncr >= 0.00004){
                            diveIncr -= 0.000004;
                TM_DAC_SetValue(TM_DAC1, output);
                delayCounter = 0;
                output = 0;
                diveCounter = 0;
                diveIncr = 1;
                TM_DAC_SetValue(TM_DAC1, filterFeedback);
             TM_DAC_SetValue(TM_DAC2, ADC2ConvertedVoltage);

      else if (timerValue == 0 && timerFlag == 1){
           timerFlag = 0;