Forums

wrong frequency with FFTW

Started by rvhoven April 25, 2005
I'm new to FFTW and I'm trying to get it to recongize a tone.
When I run the fft on a single tone it will recongize
the tone but a the wrong frequency. When I run it with
2 tones it will recongize 2 tones but again at the
wrong frequency and the spacing between the tones are
incorrect. What could I be doing wrong? I have
posted some of the code that I use to compute the
fftw. Thanks in advance.


fftw_plan p;

     unsigned char ulaw;
     static int N=1024;
     int deltaF= 8000/N; //frequency spacing(sample rate/fft size)
     int space =0; //used for freq spacing between samples
     int i=0;
     int k=0;
     double logPS;  //log of power spectrum
     double linear[N];

     fftw_real in[N];//same as double
     fftw_real  out[N], power_spectrum[N/2+1],ps[N/2+1];
     rfftw_plan p;
   

 
     //get a byte from the file and convert ulaw to 16-bit linear
     //the conversion works
     while((ulaw =getbyte(fpin))&& i<N){
   	linear[i]=ulaw2linear(ulaw);
	in[i]=linear[i];
	fprintf(fpout,"%f\n",linear[i]);
        i++;
     }
          
     p = rfftw_create_plan(N, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE);
     
     rfftw_one(p,in,out);
     power_spectrum[0] = out[0]*out[0]; /* DC component */
     logPS = 10*(log10(power_spectrum[0]));
     space = k*deltaF;

     for (k=1; k< (N+1)/2; ++k) /*(k < N/2 rounded up) */
     {	power_spectrum[k] = (out[k]*out[k] + out[N-k]*out[N-k]);
     	logPS = 10*(log10(power_spectrum[k]/N));
	space = k*deltaF;
     }

     if (N%2 ==0) /*N is even */
     { power_spectrum[N/2] = out[N/2]*out[N/2]; /*Nyquist frew. */
     }
     
     rfftw_destroy_plan(p);  
     fclose (fpin);





		
This message was sent using the Comp.DSP web interface on
www.DSPRelated.com
"rvhoven" <rvhoven@rogers.com> wrote in message 
news:W8SdnekhO5Gc4PDfRVn-sg@giganews.com...
> I'm new to FFTW and I'm trying to get it to recongize a tone. > When I run the fft on a single tone it will recongize > the tone but a the wrong frequency. When I run it with > 2 tones it will recongize 2 tones but again at the > wrong frequency and the spacing between the tones are > incorrect. What could I be doing wrong? I have > posted some of the code that I use to compute the > fftw. Thanks in advance.
Instead of doing all the log stuff, etc. I would test fftw with very simple code. Let fs=1.0 Let N=1024 so that frequency interval is 1/1024. There are 1024 samples in time and in frequency. The frequency samples run from frequency 0 to 1-1/1024. If the first tone is at 200/1024 then there should be components around frequency samples 201 and 1024-200 if I have the indexing just right. Anyway, somewhere around those indices. If the second tone is at 100/1024 then there should be components around frequency samples 101 and 1024-100. If that's not what you get, then something quite fundamental is wrong. Fred Fred
rvhoven wrote:
> I'm new to FFTW and I'm trying to get it to recongize a tone. > When I run the fft on a single tone it will recongize > the tone but a the wrong frequency. When I run it with > 2 tones it will recongize 2 tones but again at the > wrong frequency and the spacing between the tones are > incorrect. What could I be doing wrong? I have > posted some of the code that I use to compute the > fftw. Thanks in advance.
I see you use a function called fft_real. I'd expect at least parts of your problem to be related to I/O formats in the routine. An FFT that works on real-valued inputs produces a complex-valued result. However, the complex-valued output is symmetric, so one really needs only half the complex-valued data. You need only half the data points but each point comrise a real and imaginary value, so the total number of numbers (eh...) is the same. Your declarations show that both the real-valued input and the complex-valued output consist of N double numbers. I am pretty sure the output consists of only half the spectrum, but that both the real and imaginary parts are available in that one array of doubles. So go back to the documentation of your FFT routine and see how the output is formatted. Rune
> >rvhoven wrote: >> I'm new to FFTW and I'm trying to get it to recongize a tone. >> When I run the fft on a single tone it will recongize >> the tone but a the wrong frequency. When I run it with >> 2 tones it will recongize 2 tones but again at the >> wrong frequency and the spacing between the tones are >> incorrect. What could I be doing wrong? I have >> posted some of the code that I use to compute the >> fftw. Thanks in advance. > >I see you use a function called fft_real. I'd expect at least >parts of your problem to be related to I/O formats in the routine. >An FFT that works on real-valued inputs produces a complex-valued >result. However, the complex-valued output is symmetric, so one >really needs only half the complex-valued data. You need only >half the data points but each point comrise a real and imaginary >value, so the total number of numbers (eh...) is the same. > >Your declarations show that both the real-valued input and the >complex-valued output consist of N double numbers. I am pretty >sure the output consists of only half the spectrum, but that >both the real and imaginary parts are available in that one >array of doubles. > >So go back to the documentation of your FFT routine and see >how the output is formatted. > >Rune > >
Rune, I got my layout for the FFTW tutorial in Chapter 2.3 pg 7. The array is out array is DC,r1,r2,...,r(n/2),i((n+1)/2-1),....,i2,i1 Therefore the first half of my array is real and the second half is imaginary and I only have N/2+1 data points. rvhoven This message was sent using the Comp.DSP web interface on www.DSPRelated.com
rvhoven wrote:
> > > >rvhoven wrote: > >> I'm new to FFTW and I'm trying to get it to recongize a tone. > >> When I run the fft on a single tone it will recongize > >> the tone but a the wrong frequency. When I run it with > >> 2 tones it will recongize 2 tones but again at the > >> wrong frequency and the spacing between the tones are > >> incorrect. What could I be doing wrong? I have > >> posted some of the code that I use to compute the > >> fftw. Thanks in advance. > > > >I see you use a function called fft_real. I'd expect at least > >parts of your problem to be related to I/O formats in the routine. > >An FFT that works on real-valued inputs produces a complex-valued > >result. However, the complex-valued output is symmetric, so one > >really needs only half the complex-valued data. You need only > >half the data points but each point comrise a real and imaginary > >value, so the total number of numbers (eh...) is the same. > > > >Your declarations show that both the real-valued input and the > >complex-valued output consist of N double numbers. I am pretty > >sure the output consists of only half the spectrum, but that > >both the real and imaginary parts are available in that one > >array of doubles. > > > >So go back to the documentation of your FFT routine and see > >how the output is formatted. > > > >Rune > > > > > > Rune, > I got my layout for the FFTW tutorial in Chapter 2.3 pg 7. The array
is
> out array is DC,r1,r2,...,r(n/2),i((n+1)/2-1),....,i2,i1 > > Therefore the first half of my array is real and the second half is > imaginary and I only have N/2+1 data points.
Ah, I was right, then. In order to find out what is going on, rearrange the real and imaginary parts to an array of ~N/2 complex numbers. Note that the DC component is always real-valued with real-valued data, so the routine does probably not return an imaginary part for it. Next, compute the spectrum magnitude response from the complex numbers as mag[n] = sqrt(r[n]^2+i[n]^2); /* n = 0,...,~N/2 */ and plot it. Are the signal components still in the wrong place? If so, could you generate a small example like this: N = 64 The number of samples f1 = 4/64 Frequency of first component f2 = 17/64 Frequency of second component x(n) = sin(f1*2*pi) + cos(f2*2*pi) When you run your FFT on these data, you should have the following (assuming C-style indexing, starting at n=0): out[17] = 1 The cos term out[60] = 1 The sin term mag[4] = 1 mag[17] = 1 although I suspect the numbers will be 8 rather than 1. This is a normalization question that each implementation of the FFT does in its own way. All other entries in the arrays 'out' and 'mag' should vanish. Rune
Rune Allnor wrote:
> and plot it. Are the signal components still in the wrong > place? If so, could you generate a small example like this: > > N = 64 The number of samples > f1 = 4/64 Frequency of first component > f2 = 17/64 Frequency of second component > > x(n) = sin(f1*2*pi) + cos(f2*2*pi)
This should of course be x(n) = sin(f1*2*pi*n) + cos(f2*2*pi*n) Rune