Lowpass filter using FFT / inverse FFT need advice
-
- KVRer
- Topic Starter
- 20 posts since 6 Aug, 2011
Maybe someone could help me.
I'm trying to implement lowpass FFT filter in my vst plugin but i have little problem with my filter output. Output sample chunks seems to be "swapped". But if i comment the most important part of filtering, output is OK. Please look at this image:
I'm using LomontFFT for FFT and IFFT, very simple and efficient library.
my BUFFER_SIZE is 2048, samples contain real and imaginary doubles. Thus i have 1024 samples for signal buffer from host.
Filtering seems to work but data chunks are somehow swapped...
Maybe someone had implement filtering using FFT/IFFT? Could you give me some advice what to do? Or what is wrong with my code, because I'm going crazy trying to make this work for couple of days...
Thanx in advance,
Tomek
I'm trying to implement lowpass FFT filter in my vst plugin but i have little problem with my filter output. Output sample chunks seems to be "swapped". But if i comment the most important part of filtering, output is OK. Please look at this image:
I'm using LomontFFT for FFT and IFFT, very simple and efficient library.
my BUFFER_SIZE is 2048, samples contain real and imaginary doubles. Thus i have 1024 samples for signal buffer from host.
Filtering seems to work but data chunks are somehow swapped...
Maybe someone had implement filtering using FFT/IFFT? Could you give me some advice what to do? Or what is wrong with my code, because I'm going crazy trying to make this work for couple of days...
Thanx in advance,
Tomek
-
- KVRist
- 284 posts since 14 Sep, 2006
Some things to consider:
- Did you make sure you apply the exact same gain to every (real,imaginary) coefficient of the FFT?
- What is the shape of your analysis and synthesis windows prior to DFT/IDFT?
- Did you make sure you apply the exact same gain to every (real,imaginary) coefficient of the FFT?
- What is the shape of your analysis and synthesis windows prior to DFT/IDFT?
-
- KVRist
- 374 posts since 4 Oct, 2002
Haven't checked you code in detail, just two random ideas:
1) when you do this kind of stuff (convolution) you have to do complex multiplication
2) also, if you have two chunks of N samples (one is chunk of audio stream, other is filter) you have to do zero padding - add N zeroes at the end of both chunks then FFT then multiply then IFFT with overlap. Without this you will have time domain alias (which sounds like you effect you describe)
1) when you do this kind of stuff (convolution) you have to do complex multiplication
2) also, if you have two chunks of N samples (one is chunk of audio stream, other is filter) you have to do zero padding - add N zeroes at the end of both chunks then FFT then multiply then IFFT with overlap. Without this you will have time domain alias (which sounds like you effect you describe)
-
- KVRer
- Topic Starter
- 20 posts since 6 Aug, 2011
djeroen
I have tried this method first. Only gain the real and imaginary part by the same factor. But this is bad especially for low frequencies (for example kick). So this is not possible. I figured out that i have to multiple FFT of my signal with FFT of the FILTER KERNEL which is generated by IFFT on filter shape. Windowing is applied to KERNEL. This method succesfully filters static generated signal.
But when the signal is dynamicly added to buffer (my host FL Studio gives me chunks of data (every time different length)) i have some problems when getting back IFFT results and i have no idea why.
urosh
I do complex multiplication in the part markered by red square.
I'm still thinking that overlaping is not necessary because i have 1024 audio samples buffer and have to give back to the host only 10 - 150 samples which teoretically i should get from whatever part of my processed buffer. But i do something wrong somewhere...
I have tried this method first. Only gain the real and imaginary part by the same factor. But this is bad especially for low frequencies (for example kick). So this is not possible. I figured out that i have to multiple FFT of my signal with FFT of the FILTER KERNEL which is generated by IFFT on filter shape. Windowing is applied to KERNEL. This method succesfully filters static generated signal.
But when the signal is dynamicly added to buffer (my host FL Studio gives me chunks of data (every time different length)) i have some problems when getting back IFFT results and i have no idea why.
urosh
I do complex multiplication in the part markered by red square.
I'm still thinking that overlaping is not necessary because i have 1024 audio samples buffer and have to give back to the host only 10 - 150 samples which teoretically i should get from whatever part of my processed buffer. But i do something wrong somewhere...
-
- KVRist
- 374 posts since 4 Oct, 2002
maybe we are talking bout different things here. Anyhow, when you do convolution of two arrays, one is N samples other is M samples, result will bw M+N-1 samples long. So when you are doing convolution by multiplication in frequency domain you have to take this into account. Simplest way I can think of is to do zero padding thing. Pad audio chunk and filter impulse resposne with N zeroes. When you FFT them, multiply and IFFT result will be ok. However, instead of N sample chunk you've taken from stream you now have 2N chunk, so you have to add trailing N samples onto next chunk.sikor02 wrote: I'm still thinking that overlaping is not necessary because i have 1024 audio samples buffer and have to give back to the host only 10 - 150 samples which teoretically i should get from whatever part of my processed buffer. But i do something wrong somewhere...
-
- KVRist
- 284 posts since 14 Sep, 2006
You can't do without overlap due to the cyclic properties of the DFT.sikor02 wrote:djeroen
I'm still thinking that overlaping is not necessary because i have 1024 audio samples buffer and have to give back to the host only 10 - 150 samples which teoretically i should get from whatever part of my processed buffer. But i do something wrong somewhere...
If you do complex multiplication (convolution), you will need zero-padding with overlap/add.
With real-valued multiplication, you will need decent analysis and synthesis windows.
Without these, it simply won't work.
-
- KVRAF
- 2458 posts since 3 Oct, 2002 from SF CA USA NA Earth
-
- KVRer
- Topic Starter
- 20 posts since 6 Aug, 2011
Borogove
Thank you
djeroen and urosh
Could you tell me what "trick" should I use to succesfully implement time-overlap or overlap-add method?
I have 1024 samples buffer because i want good frequency resolution (especially in low frequencies [one bin per 43 Hz]) So the size of my filter is also 1024 (or 2048 if you consider real and imagine values)
So if i wanted to implement overlapping in my filter i should take at least 2048 samples of signal to my buffer. I think that will cause pretty long delay.
Is there a way to avoid somehow delay here?
Thank you
djeroen and urosh
Could you tell me what "trick" should I use to succesfully implement time-overlap or overlap-add method?
I have 1024 samples buffer because i want good frequency resolution (especially in low frequencies [one bin per 43 Hz]) So the size of my filter is also 1024 (or 2048 if you consider real and imagine values)
So if i wanted to implement overlapping in my filter i should take at least 2048 samples of signal to my buffer. I think that will cause pretty long delay.
Is there a way to avoid somehow delay here?
-
- KVRist
- 374 posts since 4 Oct, 2002
Hi Tomek,
(disclaimer: I've messed with this stuff long long ago, so take evrything with a grain of salt, or better yet google "FFT convolution" I'm sure a bunch of stuff will come up)
So, you have 1024 samples from input stream. Store those samples at the beginning a 2048 sample long buffer, lest call it InBuff. Set remaining samples in buffer to 0. Let's assume you've constructed filter in frequency domain, then perfomed IFFT and now you have 1024 sample long impulse response of filter. Put that impulse response in 2048 sample long buffer (lets call it FiltBuff) and do same thing as above (first 1024 samples in buffer are impulse response, rest are 0). Now, perform FFT of both InBuff and FiltBuff (if you don't change filter you do FFT of FiltBuff only once). Multyply those, and perform IFFT. Now you have filtered version of those 1024 samples form input but it is 2048 samples long. Take first 1024 samples and add them to output buffer. You will keep those remaining 1024 samples and add them over next buffer. I bet there are more elegant ways to do this but this should work and show in principle how to do it.
(disclaimer: I've messed with this stuff long long ago, so take evrything with a grain of salt, or better yet google "FFT convolution" I'm sure a bunch of stuff will come up)
So, you have 1024 samples from input stream. Store those samples at the beginning a 2048 sample long buffer, lest call it InBuff. Set remaining samples in buffer to 0. Let's assume you've constructed filter in frequency domain, then perfomed IFFT and now you have 1024 sample long impulse response of filter. Put that impulse response in 2048 sample long buffer (lets call it FiltBuff) and do same thing as above (first 1024 samples in buffer are impulse response, rest are 0). Now, perform FFT of both InBuff and FiltBuff (if you don't change filter you do FFT of FiltBuff only once). Multyply those, and perform IFFT. Now you have filtered version of those 1024 samples form input but it is 2048 samples long. Take first 1024 samples and add them to output buffer. You will keep those remaining 1024 samples and add them over next buffer. I bet there are more elegant ways to do this but this should work and show in principle how to do it.
-
- KVRer
- Topic Starter
- 20 posts since 6 Aug, 2011
urosh
Thank you for quick reply. I came up with this idea too just before checking this forum I will try it tomorow. I hope it will work.
I have made quick GUI for my filter to dynamicly view my buffers because i wasn't sure how all 1024 samples in filtered buffer look like.
As the recorded filter output it looks terrible because of small 10 - 200 samples from beggining of the buffer (you can see it in first post). I couldn't see full buffer untill I made GUI.
And what i saw?
Signal is being filtered but there is something strange with the amplitude and phase of the signal. If you are interested what is happening right now before implementing overlapping take a look at my quick demonstration on youtube:
http://www.youtube.com/watch?v=HIlVVv07Ckc
I wonder if this is happening because i didn't use any overlapping...
Thank you for quick reply. I came up with this idea too just before checking this forum I will try it tomorow. I hope it will work.
I have made quick GUI for my filter to dynamicly view my buffers because i wasn't sure how all 1024 samples in filtered buffer look like.
As the recorded filter output it looks terrible because of small 10 - 200 samples from beggining of the buffer (you can see it in first post). I couldn't see full buffer untill I made GUI.
And what i saw?
Signal is being filtered but there is something strange with the amplitude and phase of the signal. If you are interested what is happening right now before implementing overlapping take a look at my quick demonstration on youtube:
http://www.youtube.com/watch?v=HIlVVv07Ckc
I wonder if this is happening because i didn't use any overlapping...
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
I thought the same thing. Took one look at it and thought to myself, "You're hired!"Borogove wrote:I don't have any input on your problem, but I want to say holy shit that initial post is the best "here's what I'm doing and here's my problem" statement I've ever seen in 15 years of internet newsgroups and forums. Thank you.