FFT and Stuff

View: New views
8 Messages — Rating Filter:   Alert me  

FFT and Stuff

by Ronzani Bruno :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi everyone !

This is my first post on that mailing list, and I'm glad someone will
probably help me with my little issue :)

I want to do a filter using a FFT (Fast Fourier Translation) on a
real time music stream.

I spent some hours trying to do it, and I've got some results.

So far what I've managed to do is :

* i get my input signal buffer: 512 discrete values
* i "cut" that signal into n different parts, for instance 4*128 parts
(of course i tried 1*512)
* for each part, I compute the FFT
* there I have to do something on the frequencies I get
* then I compute the IFFT to get my signal back
* I put that signal in my output buffer

What I have is : if I don't do any operations between the FFT and the
IFFT, everything is fine : I hear my original signal without any
perturbation.

But if I try to do something - what I did was : in my frequencies
array (complex numbers), I put all the real and imaginaries values
down to zero in a certain range to have a low-pass filter for instance
-  I heard a distorded sound in output, very bad sound actually.

I don't know if I am very clear, maybe it's the operation itself
(putting all a certain range of values equal to 0) which is bad, but I
didn't find any other way to do what I want.

Basically I just want to make a filter...

Any ideas ?

Thanks a lot,


Bruno Ronzani
--
dupswapdrop -- the music-dsp mailing list and website:
subscription info, FAQ, source code archive, list archive, book reviews, dsp links
http://music.columbia.edu/cmc/music-dsp 
http://music.columbia.edu/mailman/listinfo/music-dsp

Re: FFT and Stuff

by Andrew Capon :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Well I am not expert but you don't really need FFT to make a filter.

Have a look at the code here:

http://www.musicdsp.org/archive.php?classid=3#38

Cheers

Andy

On 29 Oct 2009, at 09:13, Ronzani Bruno wrote:

> Hi everyone !
>
> This is my first post on that mailing list, and I'm glad someone will
> probably help me with my little issue :)
>
> I want to do a filter using a FFT (Fast Fourier Translation) on a
> real time music stream.
>
> I spent some hours trying to do it, and I've got some results.
>
> So far what I've managed to do is :
>
> * i get my input signal buffer: 512 discrete values
> * i "cut" that signal into n different parts, for instance 4*128 parts
> (of course i tried 1*512)
> * for each part, I compute the FFT
> * there I have to do something on the frequencies I get
> * then I compute the IFFT to get my signal back
> * I put that signal in my output buffer
>
> What I have is : if I don't do any operations between the FFT and the
> IFFT, everything is fine : I hear my original signal without any
> perturbation.
>
> But if I try to do something - what I did was : in my frequencies
> array (complex numbers), I put all the real and imaginaries values
> down to zero in a certain range to have a low-pass filter for instance
> -  I heard a distorded sound in output, very bad sound actually.
>
> I don't know if I am very clear, maybe it's the operation itself
> (putting all a certain range of values equal to 0) which is bad, but I
> didn't find any other way to do what I want.
>
> Basically I just want to make a filter...
>
> Any ideas ?
>
> Thanks a lot,
>
>
> Bruno Ronzani
> --
> dupswapdrop -- the music-dsp mailing list and website:
> subscription info, FAQ, source code archive, list archive, book  
> reviews, dsp links
> http://music.columbia.edu/cmc/music-dsp
> http://music.columbia.edu/mailman/listinfo/music-dsp

--
dupswapdrop -- the music-dsp mailing list and website:
subscription info, FAQ, source code archive, list archive, book reviews, dsp links
http://music.columbia.edu/cmc/music-dsp 
http://music.columbia.edu/mailman/listinfo/music-dsp

Re: FFT and Stuff

by Laurent de Soras :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Ronzani Bruno wrote:
>
> But if I try to do something - what I did was : in my frequencies
> array (complex numbers), I put all the real and imaginaries values
> down to zero in a certain range to have a low-pass filter for instance
> -  I heard a distorded sound in output, very bad sound actually.

This is not the proper way to use the FFT to filter a signal.
The reason is that the Fourier transform you're using is
intended to work on periodic signals (of the same period as
the FFT length). Therefore if you modify a block of data in
the frequency domain, the resulting signal back in the time
domain will sound as expected only if it is looped ! If you
try to joind such blocks, you'll end up with a lot of
discontinuities generating clicks and distortion. You
can attenuate this effect by windowing and overlapping
chunks of data, but you'll still get annoying artifacts.

You'd probably better design a filter working in the time
domain (look on http://www.musicdsp.org as suggested by
Andrew Capon).

Anyway if you want to use an FFT, you can use it to achieve
the convolution needed to process a large FIR filter. Search
for overlap-add or overlap-save techniques. But you'll have
to design a regular FIR before.




--
Laurent de Soras                  |               Ohm Force
DSP developer & Software designer |  Digital Audio Software
http://ldesoras.free.fr           | http://www.ohmforce.com

--
dupswapdrop -- the music-dsp mailing list and website:
subscription info, FAQ, source code archive, list archive, book reviews, dsp links
http://music.columbia.edu/cmc/music-dsp 
http://music.columbia.edu/mailman/listinfo/music-dsp

Re: FFT and Stuff

by Bruno Ronzani :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thanks a lot, Andrew and Laurent (merci Laurent !)

I'm currently trying that simple LP filter (
http://www.musicdsp.org/archive.php?classid=3#38 ).

The thing is I still have a distortion in the sound.

It may be because of the 2 first elements in out(n) = a1 * in + a2 *
in(n-1) + a3 * in(n-2) - b1*out(n-1) - b2*out(n-2)

Because I am working on real time audio, with 512 points buffers, I
don't really know what to do with that elements.

I tried to store the 2 last element of in and out of the previous
buffer, and use them in my new buffer, but it doesn't seem to work.

any suggestions ?

thanks again


2009/10/29 Laurent de Soras <laurent.de.soras@...>:

> Ronzani Bruno wrote:
>>
>> But if I try to do something - what I did was : in my frequencies
>> array (complex numbers), I put all the real and imaginaries values
>> down to zero in a certain range to have a low-pass filter for instance
>> -  I heard a distorded sound in output, very bad sound actually.
>
> This is not the proper way to use the FFT to filter a signal.
> The reason is that the Fourier transform you're using is
> intended to work on periodic signals (of the same period as
> the FFT length). Therefore if you modify a block of data in
> the frequency domain, the resulting signal back in the time
> domain will sound as expected only if it is looped ! If you
> try to joind such blocks, you'll end up with a lot of
> discontinuities generating clicks and distortion. You
> can attenuate this effect by windowing and overlapping
> chunks of data, but you'll still get annoying artifacts.
>
> You'd probably better design a filter working in the time
> domain (look on http://www.musicdsp.org as suggested by
> Andrew Capon).
>
> Anyway if you want to use an FFT, you can use it to achieve
> the convolution needed to process a large FIR filter. Search
> for overlap-add or overlap-save techniques. But you'll have
> to design a regular FIR before.
>
>
>
>
> --
> Laurent de Soras                  |               Ohm Force
> DSP developer & Software designer |  Digital Audio Software
> http://ldesoras.free.fr           | http://www.ohmforce.com
>
> --
> dupswapdrop -- the music-dsp mailing list and website:
> subscription info, FAQ, source code archive, list archive, book reviews, dsp links
> http://music.columbia.edu/cmc/music-dsp
> http://music.columbia.edu/mailman/listinfo/music-dsp
>
--
dupswapdrop -- the music-dsp mailing list and website:
subscription info, FAQ, source code archive, list archive, book reviews, dsp links
http://music.columbia.edu/cmc/music-dsp 
http://music.columbia.edu/mailman/listinfo/music-dsp

Re: FFT and Stuff

by Lubomir I. Ivanov :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

----- Original Message -----
From: "Bruno Ronzani" <ronzani.bruno@...>

> Thanks a lot, Andrew and Laurent (merci Laurent !)
>
> I'm currently trying that simple LP filter (
> http://www.musicdsp.org/archive.php?classid=3#38 ).
>
> The thing is I still have a distortion in the sound.
>
> It may be because of the 2 first elements in out(n) = a1 * in + a2 *
> in(n-1) + a3 * in(n-2) - b1*out(n-1) - b2*out(n-2)
>

the distortion could be caused, for example by internal clipping if some of
the registers overflows, but i cannot really guess for any particular
reason. could be related to other parts of the whole algorithm "chain" as
well (i.e not the filter causing it)

to clarify:
this is difference equation / recursive sequence with constant (presumably)
coefficients for a "direct form I" implementation of a digital biquad
filter. in this case, the "a"s are the coefficients for the zeros, while the
"b"s are for the poles.

seeing something written as "in(n-1)" is a previous value (difference) with
an offset/age of 'n' samples, which should be stored in register-variables
for the recursion to work properly.

> Because I am working on real time audio, with 512 points buffers, I
> don't really know what to do with that elements.
>
> I tried to store the 2 last element of in and out of the previous
> buffer, and use them in my new buffer, but it doesn't seem to work.
>

just run an entire buffer trough the algorithm in a way, that once a buffer
is processed completely, the subsequent buffer should enherit the last 4
register values as intermediate. if that makes any sense... :)

//-------------------
// calculate coefficients here
//....

//-------------------
// to process each sample of the buffer with DF-I
out = a1*in + a2*in_n1 + a3*in_n2 - b1*out_n1 - b2*out_n2;
in_n2 = in_n1;
in_n1 = in;
out_n2 = out_n1;
out_n1 = out;

---

all the best
lubomir
http://www.tu-varna.bg 

--
dupswapdrop -- the music-dsp mailing list and website:
subscription info, FAQ, source code archive, list archive, book reviews, dsp links
http://music.columbia.edu/cmc/music-dsp 
http://music.columbia.edu/mailman/listinfo/music-dsp

Re: FFT and Stuff

by Bruno Ronzani :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hey back :)

So I did manage to improve everything a bit but I still have too many
perturbations.

Note that :
1. the filter is correct, I mean the sound is actually filtered as I
would like it to be. (but with creaks)
2. if I don't apply the filter, my sound is perfect

I use a filter of 800 Hz. You can find a sample (sorry for the song!)
of what I hear there : http://akhost.free.fr/video.wav

Here is my code :


void CFilter::load(StkFloat *bufferIn, StkFloat *bufferOut)
{

        int n = CSoundUtilities::getnBufferFrames();
        this->lowPass(bufferIn,bufferOut,_freq,1.4142135623731);
        _last[0] = bufferIn[n-2];
        _last[1] = bufferIn[n-1];
        _last[2] = bufferOut[n-2];
        _last[3] = bufferOut[n-1];

}


void CFilter::lowPass(StkFloat *in, StkFloat *out, double f, double r)
{

        int N = CSoundUtilities::getnBufferFrames();

        double c = 1.0 / tan(PI * f /  44100);
        double a1 = 1.0 / ( 1.0 + r * c + c * c);
        double a2 = 2* a1;
        double a3 = a1;
        double b1 = 2.0 * ( 1.0 - c*c) * a1;
        double b2 = ( 1.0 - r * c + c * c) * a1;

        out[0] = a1 * in[0] + a2 * _last[0] + a3 * _last[1] - b1*_last[2] -
b2*_last[3];
        out[1] = a1 * in[1] + a2 * _last[1] + a3 * in[0] - b1*_last[3] - b2*out[0];

        for(int n=2;n<N;++n)
        {
                out[n] = a1 * in[n] + a2 * in[n-1] + a3 * in[n-2] - b1*out[n-1] - b2*out[n-2];
        }

}


I hope my code is clear enough !

_last is an array of doubles.

note that I tried several different values for r , and I still have te
creaks... (the less r, the louder creaks)

any ideas ?

thanks !




2009/10/29 Lubomir I. Ivanov <neolit123@...>:

> ----- Original Message -----
> From: "Bruno Ronzani" <ronzani.bruno@...>
>> Thanks a lot, Andrew and Laurent (merci Laurent !)
>>
>> I'm currently trying that simple LP filter (
>> http://www.musicdsp.org/archive.php?classid=3#38 ).
>>
>> The thing is I still have a distortion in the sound.
>>
>> It may be because of the 2 first elements in out(n) = a1 * in + a2 *
>> in(n-1) + a3 * in(n-2) - b1*out(n-1) - b2*out(n-2)
>>
>
> the distortion could be caused, for example by internal clipping if some of
> the registers overflows, but i cannot really guess for any particular
> reason. could be related to other parts of the whole algorithm "chain" as
> well (i.e not the filter causing it)
>
> to clarify:
> this is difference equation / recursive sequence with constant (presumably)
> coefficients for a "direct form I" implementation of a digital biquad
> filter. in this case, the "a"s are the coefficients for the zeros, while the
> "b"s are for the poles.
>
> seeing something written as "in(n-1)" is a previous value (difference) with
> an offset/age of 'n' samples, which should be stored in register-variables
> for the recursion to work properly.
>
>> Because I am working on real time audio, with 512 points buffers, I
>> don't really know what to do with that elements.
>>
>> I tried to store the 2 last element of in and out of the previous
>> buffer, and use them in my new buffer, but it doesn't seem to work.
>>
>
> just run an entire buffer trough the algorithm in a way, that once a buffer
> is processed completely, the subsequent buffer should enherit the last 4
> register values as intermediate. if that makes any sense... :)
>
> //-------------------
> // calculate coefficients here
> //....
>
> //-------------------
> // to process each sample of the buffer with DF-I
> out = a1*in + a2*in_n1 + a3*in_n2 - b1*out_n1 - b2*out_n2;
> in_n2 = in_n1;
> in_n1 = in;
> out_n2 = out_n1;
> out_n1 = out;
>
> ---
>
> all the best
> lubomir
> http://www.tu-varna.bg
>
> --
> dupswapdrop -- the music-dsp mailing list and website:
> subscription info, FAQ, source code archive, list archive, book reviews, dsp links
> http://music.columbia.edu/cmc/music-dsp
> http://music.columbia.edu/mailman/listinfo/music-dsp
>
--
dupswapdrop -- the music-dsp mailing list and website:
subscription info, FAQ, source code archive, list archive, book reviews, dsp links
http://music.columbia.edu/cmc/music-dsp 
http://music.columbia.edu/mailman/listinfo/music-dsp

Re: FFT and Stuff

by contact-68 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


----- Original Message -----
From: "Bruno Ronzani" <ronzani.bruno@...>
To: "A discussion list for music-related DSP" <music-dsp@...>
Sent: Thursday, October 29, 2009 4:05 PM
Subject: Re: [music-dsp] FFT and Stuff


> Hey back :)
>
> So I did manage to improve everything a bit but I still have too many
> perturbations.
>
> Note that :
> 1. the filter is correct, I mean the sound is actually filtered as I
> would like it to be. (but with creaks)
> 2. if I don't apply the filter, my sound is perfect
>
> I use a filter of 800 Hz. You can find a sample (sorry for the song!)
> of what I hear there : http://akhost.free.fr/video.wav
>
> Here is my code :
>
>
> void CFilter::load(StkFloat *bufferIn, StkFloat *bufferOut)
> {
>
> int n = CSoundUtilities::getnBufferFrames();
> this->lowPass(bufferIn,bufferOut,_freq,1.4142135623731);
> _last[0] = bufferIn[n-2];
> _last[1] = bufferIn[n-1];
> _last[2] = bufferOut[n-2];
> _last[3] = bufferOut[n-1];
>
> }
>
>
> void CFilter::lowPass(StkFloat *in, StkFloat *out, double f, double r)
> {
>
> int N = CSoundUtilities::getnBufferFrames();
>
> double c = 1.0 / tan(PI * f /  44100);
> double a1 = 1.0 / ( 1.0 + r * c + c * c);
> double a2 = 2* a1;
> double a3 = a1;
> double b1 = 2.0 * ( 1.0 - c*c) * a1;
> double b2 = ( 1.0 - r * c + c * c) * a1;
>
> out[0] = a1 * in[0] + a2 * _last[0] + a3 * _last[1] - b1*_last[2] -
> b2*_last[3];
> out[1] = a1 * in[1] + a2 * _last[1] + a3 * in[0] - b1*_last[3] -
> b2*out[0];
>
> for(int n=2;n<N;++n)
> {
> out[n] = a1 * in[n] + a2 * in[n-1] + a3 * in[n-2] - b1*out[n-1] -
> b2*out[n-2];
> }
>
> }

It may be less confusing to store the last samples in the filter loop as you
go, most examples of this are like the following:

// n goes from 0 to full buffer size.
out[n] = a1 * in[n] + a2 * x1 + a3 * x2 - b1 * y1 - b2* y2;
x2 = x1; x1 = in[n];
y2 = y1; y1 = out[n];

This way you'll also be O.K. if your output buffer is the same location as
your input buffer.
Only reset all the x and y variabls to 0 at the initiation of your code, and
they do not need to be reset if you change filter coeffs.

Dave

p.s. wav link broken.

--
dupswapdrop -- the music-dsp mailing list and website:
subscription info, FAQ, source code archive, list archive, book reviews, dsp links
http://music.columbia.edu/cmc/music-dsp 
http://music.columbia.edu/mailman/listinfo/music-dsp

Re: FFT and Stuff

by Bruno Ronzani :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Sorry for the broken link.

I did exactly what you told me to do.

... AND IT WORKS !

thank you so much everyone !

Here is the code of my class :

CFilter::CFilter(double intensity, int frequency):
CEffect(intensity),
_freq(frequency),
x1(0),x2(0),
y1(0),y2(0)
{
}


void CFilter::load(StkFloat *bufferIn, StkFloat *bufferOut)
{
        this->lowPass(bufferIn,bufferOut,_freq,1);
}

void CFilter::lowPass(StkFloat *in, StkFloat *out, double f, double r)
{

        int N = CSoundUtilities::getnBufferFrames();

        double c = 1.0 / tan(PI * f /  44100);
        double a1 = 1.0 / ( 1.0 + r * c + c * c);
        double a2 = 2* a1;
        double a3 = a1;
        double b1 = 2.0 * ( 1.0 - c*c) * a1;
        double b2 = ( 1.0 - r * c + c * c) * a1;

        for(int n=0;n<N;++n)
        {
                out[n] = a1 * in[n] + a2 * x1 + a3 * x2 - b1 * y1 - b2 * y2;
                x2 = x1;
                x1 = in[n];
                y2 = y1;
                y1 = out[n];
        }

}

2009/10/29 contact <contact@...>:

>
> ----- Original Message -----
> From: "Bruno Ronzani" <ronzani.bruno@...>
> To: "A discussion list for music-related DSP" <music-dsp@...>
> Sent: Thursday, October 29, 2009 4:05 PM
> Subject: Re: [music-dsp] FFT and Stuff
>
>
>> Hey back :)
>>
>> So I did manage to improve everything a bit but I still have too many
>> perturbations.
>>
>> Note that :
>> 1. the filter is correct, I mean the sound is actually filtered as I
>> would like it to be. (but with creaks)
>> 2. if I don't apply the filter, my sound is perfect
>>
>> I use a filter of 800 Hz. You can find a sample (sorry for the song!)
>> of what I hear there : http://akhost.free.fr/video.wav
>>
>> Here is my code :
>>
>>
>> void CFilter::load(StkFloat *bufferIn, StkFloat *bufferOut)
>> {
>>
>> int n = CSoundUtilities::getnBufferFrames();
>> this->lowPass(bufferIn,bufferOut,_freq,1.4142135623731);
>> _last[0] = bufferIn[n-2];
>> _last[1] = bufferIn[n-1];
>> _last[2] = bufferOut[n-2];
>> _last[3] = bufferOut[n-1];
>>
>> }
>>
>>
>> void CFilter::lowPass(StkFloat *in, StkFloat *out, double f, double r)
>> {
>>
>> int N = CSoundUtilities::getnBufferFrames();
>>
>> double c = 1.0 / tan(PI * f /  44100);
>> double a1 = 1.0 / ( 1.0 + r * c + c * c);
>> double a2 = 2* a1;
>> double a3 = a1;
>> double b1 = 2.0 * ( 1.0 - c*c) * a1;
>> double b2 = ( 1.0 - r * c + c * c) * a1;
>>
>> out[0] = a1 * in[0] + a2 * _last[0] + a3 * _last[1] - b1*_last[2] -
>> b2*_last[3];
>> out[1] = a1 * in[1] + a2 * _last[1] + a3 * in[0] - b1*_last[3] -
>> b2*out[0];
>>
>> for(int n=2;n<N;++n)
>> {
>> out[n] = a1 * in[n] + a2 * in[n-1] + a3 * in[n-2] - b1*out[n-1] -
>> b2*out[n-2];
>> }
>>
>> }
>
> It may be less confusing to store the last samples in the filter loop as you
> go, most examples of this are like the following:
>
> // n goes from 0 to full buffer size.
> out[n] = a1 * in[n] + a2 * x1 + a3 * x2 - b1 * y1 - b2* y2;
> x2 = x1; x1 = in[n];
> y2 = y1; y1 = out[n];
>
> This way you'll also be O.K. if your output buffer is the same location as
> your input buffer.
> Only reset all the x and y variabls to 0 at the initiation of your code, and
> they do not need to be reset if you change filter coeffs.
>
> Dave
>
> p.s. wav link broken.
>
> --
> dupswapdrop -- the music-dsp mailing list and website:
> subscription info, FAQ, source code archive, list archive, book reviews, dsp links
> http://music.columbia.edu/cmc/music-dsp
> http://music.columbia.edu/mailman/listinfo/music-dsp
>
--
dupswapdrop -- the music-dsp mailing list and website:
subscription info, FAQ, source code archive, list archive, book reviews, dsp links
http://music.columbia.edu/cmc/music-dsp 
http://music.columbia.edu/mailman/listinfo/music-dsp