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.
Is this correct method for using interpolation?
Started by ●January 5, 2007
Reply by ●January 6, 20072007-01-06
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
Reply by ●January 8, 20072007-01-08
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