fft filter producing pops with low frequency attenuation

Fd80f81596aa1cf809ceb1c2077e190b
0
rouncer 103 Jun 12, 2012 at 19:02

im using a 2048 long fft, when i attenuate low frequency sine waves it produces popping, how do i get rid of this?
im processing samples in lots of 2048.

void ffteq_process(int samples, int* in, int* out, float* data, int*& memory)
{
int fftsize=11;
int size=2048;
int j;
        
for(j=0;j<samples;j+=size)
{
  int k;
  for(k=0;k<size;k++)
  {
   GRe[k]=in[j+k];
   GIm[k]=0;
  }
  FFT(1,fftsize,GRe,GIm);
        
  for(k=0;k<size/2;k++)
  {
   int b=(31-((powf(1.0/(8192.0*256.0),(float)k/(float)(size/2)))*31))+1; //theres 32 controllers
                                   //to control frequency so i access them here
                    
   double amp=hypot(GRe[k],GIm[k]);
   double phase=atan2(GRe[k],GIm[k]);
                
   float vol=data[b]*2; //this is just accessing the graph that attenuates the frequencies
   if(vol>=1) {vol*=16;vol-=15;};
                    
                    
   amp*=vol;
   GRe[k]=sinf(phase)*amp;
   GIm[k]=cosf(phase)*amp;
   amp=hypot(GRe[(size-1)-k],GIm[(size-1)-k]);
   phase=atan2(GRe[(size-1)-k],GIm[(size-1)-k]);
   amp*=vol;
   GRe[(size-1)-k]=sinf(phase)*amp;
   GIm[(size-1)-k]=cosf(phase)*amp;
                
  }


  FFT(0,fftsize,GRe,GIm);


  for(k=0;k<size;k++)
  {
   out[j+k]=GRe[k];
  }
}
    
}

13 Replies

Please log in or register to post a reply.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Jun 12, 2012 at 19:18

I’d guess it’s happening because the ends of the FFT frames are no longer continuous with the next frame after processing. You might try overlapping the FFT frames a bit and blending across. For instance maybe frame 0 would be samples 0-2047, frame 1 would be 1792-3839 (I overlapped the range by 256), and in the overlapping region from 1792-2047 you’d blend from frame 0 to frame 1.

Fd80f81596aa1cf809ceb1c2077e190b
0
rouncer 103 Jun 12, 2012 at 21:37

yeh that worked, i thought i had a problem at first, but no - it works fine!! :)
its a really nice eq too, and it just so happens to instance many times, the computer makes short work of the fft, and its got good bass response at 2048. cool.

6eaf0e08fe36b2c23ca096562dd7a8b7
0
__________Smile_ 101 Jun 12, 2012 at 21:40

First, keep in mind that fixed size FFT is an approximation of the real frequency representation of some signal (real representation have infinite window). Consequence is that your attenuation function must be smooth enough, i. e. for consecutive frequencies must not differ much. If it’s not smooth enough then you have popping and another errors.

Second,

   double amp=hypot(GRe[k],GIm[k]);
   double phase=atan2(GRe[k],GIm[k]);
   amp*=vol;
   GRe[k]=sinf(phase)*amp;
   GIm[k]=cosf(phase)*amp;

is a very slow equivalent of

   GRe[k]*=vol;
   GIm[k]*=vol;

I recommend you to study complex numbers before working with frequency domain.

Third, for 32-band equalizer or similar processing, doing FFT is probably overkill. You can implement simple analog filters with equivalent simple function of untransformed sound values.

Fd80f81596aa1cf809ceb1c2077e190b
0
rouncer 103 Jun 12, 2012 at 21:54

heres a shot of my music program so far!
shot3i.png

those yellow and blue dots are the synthesizer, it repeats back a wave at a high varying frequency to make a nice bleep. :) the fft eq can soon turn the bleep into drums with a bit of clipping.

Fd80f81596aa1cf809ceb1c2077e190b
0
rouncer 103 Jun 12, 2012 at 21:57

Thanks for the advice smile, that code adjustment will be going in for sure, I tried an iir filter eq (composed of about 7 notches), but I couldnt find a notch or peak filter that could filter bass very well, the best I got was a 2 pole 2 zeroes but it was really bad actually, the fft filter almost worked first time… im yet to get an amazing sound out of it yet tho… which i know filters are good for if you get them right.

Fd80f81596aa1cf809ceb1c2077e190b
0
rouncer 103 Jun 12, 2012 at 22:28

funnily, i was mucking around with the notch filter again and i was getting better results…. theres something cool about iir filters musically… hmm its strange, anyway i just clipped a bit of bass into this saw tooth and i got some sick brass… that im not getting out of the fft eq. wierd.

6eaf0e08fe36b2c23ca096562dd7a8b7
0
__________Smile_ 101 Jun 12, 2012 at 22:30

Well, to produce good filter you must know analog circuit theory (and complex numbers as part of it). For a peak filter you can use the following code

double peak_filter(double val)
{
    static const double step = 1.0 / 44100;
    static const double freq = 440, beta = 44;
    static const complex<double> mul = exp(complex<double>(-beta, freq) * step);

    static complex<double> accum = 0;
    return (accum = (accum - val) * mul + val).real;
}

It filters a band of width beta around frequency freq. I can’t remember formula for notch filter but it has the same complexity.

Fd80f81596aa1cf809ceb1c2077e190b
0
rouncer 103 Jun 12, 2012 at 22:39

i used this notch filter as a bass booster on a saw, and came up with this brass synth.
[media]http://soundcloud.com/rouncer81/st[/media]

Ill try that filter, thanks a lot. err, im not sure what to do with complex<double>?

6eaf0e08fe36b2c23ca096562dd7a8b7
0
__________Smile_ 101 Jun 12, 2012 at 23:13

complex<double> is simply

struct
{
    double real, imag;
};

with defined mathematical operations. C99 have its analog in <complex.h> (dunno about MSVC support though, use C++ version):

double complex mul = cexp((-beta + freq * I) * step);

Or you can fallback to real numbers:

double mul_re = cos(freq * step) * exp(-beta * step);
double mul_im = sin(freq * step) * exp(-beta * step);

static double acc_re = 0, acc_im = 0;
double res_re = (acc_re - val) * mul_re - acc_im * mul_im + val;
double res_im = (acc_re - val) * mul_im + acc_im * mul_re;
acc_re = res_re;  acc_im = res_im;  return res_re;

Oops, fixed error in filer code from my previous post.

Fd80f81596aa1cf809ceb1c2077e190b
0
rouncer 103 Jun 12, 2012 at 23:51

i tried the filter, it worked but it has poor bass response, bass seems to be the hardest to get and is the most important to have!!! a good bass boost before you distort is always what you do, I need a bass peak that works right down into the sub frequencies.

6eaf0e08fe36b2c23ca096562dd7a8b7
0
__________Smile_ 101 Jun 13, 2012 at 00:17

What exactly do you want to get? What frequency response do you want to achieve? My filter works independent of frequency, maybe you don’t have enough sound output quality?

Fd80f81596aa1cf809ceb1c2077e190b
0
rouncer 103 Jun 13, 2012 at 01:51

good sub response is what i need, maybe your filter is good enough its just maybe im not using these filters right, its tough…

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Jun 13, 2012 at 10:08

That’s the problem with sound, it’s subjective and varies with hardware.

With graphics you can screen grab it and study it in detail and everyone can pretty much see the same thing. If you wrote a wav file from your code we could listen to it, but there is no way of getting all of us to hear the same thing.

Why don’t you grab a copy of a MOD tracker and compare that with the output of your software, then at least you have an idea if it is your code that’s wrong, or your setup is not giving you the sound you want.