DSPRelated.com
Forums

Is this correct method for using interpolation?

Started by bobthebullet990 January 5, 2007
Hi all! ...I am curious as to whether I am doing the right thing here or
not! ...Im designing a flanger effect, but what is known as the "zipper
effect" is occuring when i run my algorithm (using the C6711 DSK). I am
confused as to exactly why, because after reading many articles on
interpolation, it seems to me like im doing the correct thing! please may
anyone have a look and let me know... my flanger function is here... [with
a psuedo code main function to show it is being used]...


int main(void){
  /* loop until user switches off flanger effect */
    /* 1.read input and convert to mono */
    /* 2.read switches on DSK and change range and rate if need be */
    /* NOTE: Delay is const, set to 10samples ~aprox~0.5ms sample rate */
    /*       is set to 22.4 kHz. */
    /* 3.send current sample to flanger function and output return data
*/
  /* end of loop */
  return 0;
}

/*************************************************************************/
/**                                                                    
**/
/** FUNCTION    : flanger                                              
**/
/** DESCRIPTION : Function to apply a flanger effect to the input data.
**/
/**               This function returns the flanged audio data sample  
**/
/**               by sample as it is called. It requires parameters:   
**/
/**               + range - determines the range of delay values for   
**/
/**                 the sweep triangular waveform /\/\/\/              
**/
/**               + delay - the constant delay term to apply           
**/
/**               + rate - the rate at which the sweep triangular wave-
**/
/**                 form should change [every x samples]               
**/
/**               + currentSample - latest audio sample from codec     
**/
/**                                                                    
**/
/*************************************************************************/
short int flanger(int range, int delay, int rate, short int
currentSample){
  
  int flangerDelay; /* stores current delay required for flange effect */
  static int i=0;   /* keeps track of time for creating sweep waveform */
  static int sweepValue=0; /* to keep track of current sweep delay     */
  static int sweepFlag=1;  /* keeps track of waveform movement         */
  static int writePtr=0;   /* pointer to newest audio sample in buffer */
  static int readPtr=0;    /* pointer to oldest audio sample in buffer */

  /* is it time to change waveform movement? if not, increment counter */
  if (i >= rate) {
    /* has the maximum possible delay for sweep been reached? */
    if (sweepValue >= range)
      sweepFlag = 0; /* start the \ of triangular waveform */
    else if (sweepValue <= 0)
      sweepFlag = 1; /* start the / of triangular waveform */
    
    /* Is the waveform rising or falling? */ 
    if (sweepFlag==1)
      sweepValue++;
    else
      sweepValue--;

    /* reset i, to start count before waveform changes shape again */
    i=0; 
  }
  else i++;
    
  /* Calculate the total current to delay */
  flangerDelay = sweepValue + delay;
  
  /* Calculate position of the read & write pointers */
  if (flangeHead < flangerDelay)
    readPtr = MAX_DELAY - (flangerDelay - writePtr);
  else
    readPtr = writePtr - flangerDelay;  
  /* has the write pointer reached end of delay buffer? */
  if (writePtr > MAX_DELAY) 
    writePtr=0;
  else 
    writePtr++;
  
  /* now add current audio sample to array and return oldest sample */
  delayArray[writePtr] = currentSample;  
  /* does the sample at the required delay point exist? - interpolation
*/
  if ((delay + range) % flangerDelay)
    /* data sample exists, so return it! */
    return delayArray[readPtr];
  else 
    /* the sample does not exist! interpolate nearest neighbours! */
    return(calculateAverage(delayArray[readPtr],delayArray[readPtr+1]));
    
} /* flanger() */


Many thanks! Matt.



bobthebullet990 wrote:

> Hi all! ...I am curious as to whether I am doing the right thing here or > not! ...Im designing a flanger effect, but what is known as the "zipper > effect" is occuring when i run my algorithm (using the C6711 DSK). I am > confused as to exactly why, because after reading many articles on > interpolation, it seems to me like im doing the correct thing! please may > anyone have a look and let me know... my flanger function is here... [with > a psuedo code main function to show it is being used]... >
-- eww, code: snip --
> >
You'll find that folks often don't go through code on this, or any other group. Mostly because it's _work_. Perhaps you'll get lucky, but if not it may help to post an outline of your algorithm as a bulleted list of no more than five lines. If you use more, get more general. In the mean time I would suggest that you make a really stupid, bone-headed implementation that uses tons of processor ticks and memory but is guaranteed correct, then go back from there to where you want to be. Something like: * Take your original audio clip. * Resample and interpolate it to 1MS/s. * Downsample it, with flanging. * Play it. The only two things you can screw up here are the resampling and the flanging -- and if replace the flanging with a straight downsampling then you can't screw _that_ up either. Once you get that working, then work on doing it using more compact methods, and making it work in real time. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com Posting from Google? See http://cfaj.freeshell.org/google/ "Applied Control Theory for Embedded Systems" came out in April. See details at http://www.wescottdesign.com/actfes/actfes.html
In article <n72dnUHBmot_yAPYnZ2dnUVZ_ternZ2d@giganews.com>,
 "bobthebullet990" <bobthebullet990@hotmail.com> wrote:


|    /* now add current audio sample to array and return oldest sample */
|    delayArray[writePtr] = currentSample;  
|    /* does the sample at the required delay point exist? - interpolation
|  */
|    if ((delay + range) % flangerDelay)
|      /* data sample exists, so return it! */
|      return delayArray[readPtr];
|    else 
|      /* the sample does not exist! interpolate nearest neighbours! */
|      return(calculateAverage(delayArray[readPtr],delayArray[readPtr+1]));

You are using a circular buffer for the data.  What happens when readPtr 
is at the end, but you are accessing readPtr+1 in the above calculation?

   -- Tim Olson