Hi!
I'm totally new to FT:s (obviosly) and don't know much of the math involved.
I have a real input signal (Fs=44100) which I've transformed to a
complex and I was hoping to be able to regenerate the original signal
manually - just to get the hang of it. It comes "close" :-)
I'm using these fftwl_plans:
long double *in;
fftwl_complex *out;
fftwl_plan plan_forward, plan_backward;
in = (long double*) fftwl_malloc(sizeof(long double)*fft_length);
out = fftwl_alloc_complex(fft_length);
plan_forward = fftwl_plan_dft_r2c_1d( fft_length, in, out, FFTW_EXHAUSTIVE);
plan_backward = fftwl_plan_dft_c2r_1d( fft_length, out, in,
FFTW_EXHAUSTIVE);
I can transform forward and then backward and get the original signal
back (after normalizing it with 1/fft_length).
fft_length=10 bins=fft_length/2+1=6
The forward transformation gives me this (unnormalized):
binFreq -> real img -> amp phase
0.000000 -> {-0.398685, 0.000000} -> { 0.398685, 3.141593}
4410.000000 -> {-1.017359, 0.591153} -> { 1.176640, 2.615212}
8820.000000 -> { 1.187429,-0.732900} -> { 1.395396,-0.552982}
13230.000000 -> { 0.515134,-1.726352} -> { 1.801570,-1.280813}
17640.000000 -> { 0.406585,-0.089637} -> { 0.416349,-0.216991}
22050.000000 -> { 0.383167, 0.000000} -> { 0.383167, 0.000000}
Here's the input signal, the signal after forward+backward FT
(+normalization in the time domain) and then my two generated signals -
one generated from the complex numbers and one from amplitude and phase.
The error in my generated signals seems to be the same.
smp in fwd&back gen(cplx) gen(AmpPhase)
0 0.216806 0.216806 0.215254 0.215254
1 0.141786 0.141786 0.063601 0.063601
2 -0.561061 -0.561061 -0.562613 -0.562613
3 -0.483457 -0.483457 -0.561642 -0.561642
4 0.311432 0.311432 0.309880 0.309880
5 0.341063 0.341063 0.262877 0.262877
6 0.093564 0.093564 0.092012 0.092012
7 0.285536 0.285536 0.207351 0.207351
8 -0.068499 -0.068499 -0.070051 -0.070051
9 -0.675855 -0.675855 -0.754040 -0.754040
Here's some C++ code describing how I try to do it:
typedef struct {
long double amp;
long double phase;
} AmpPhase;
inline void complex2AmpPhase( fftwl_complex &cpl, AmpPhase &ap ) {
long double r,i;
r=cpl[0];
i=cpl[1];
ap.amp = sqrtl( r*r + i*i );
ap.phase = atan2l(i,r);
}
// binFunc( long bin, long sample ) =
// binFreq(bin) * sample * M_TWO_PI / Fs
// ...but is somewhat optimized here
inline long double binFunc( long bin, long sample ) {
return bin * sample * M_TWO_PI/fft_length;
}
// regenerate the signal from the unnormalized FT
for(int samp=0;samp<fft_length;samp++) {
gen_cpx[samp]=0.0;
gen_ap[samp]=0.0;
}
for( int b=0; b<bins; b++ ) {
complex2AmpPhase( out[b], ap );
for(int samp=0;samp<fft_length;samp++) {
gen_cpx[samp] +=
out[b][0] * cosl( binFunc(b,samp) ) -
out[b][1] * sinl( binFunc(b,samp) );
gen_ap[samp] += ap.amp * cosl( binFunc(b,samp) + ap.phase );
}
}
As I said, I normalize the backwards transformation with 1/fft_length
and get the correct signal back but I need to normalize my generated
signals with 2/fft_length to get as close as I'm getting so I must have
messed up bigtime somewhere. :)
If I instead normalize in the frequency domain, the backwards FT still
gives me the correct answer but then my generated signals gets half the
amplitude (same normalization problem).
If I let my insignal be a clean sin() spot on one of the bin frequencies
(8820), this is what I get after normalization:
binFreq -> real img -> amp phase
0.000000 -> { 0.000000, 0.000000} -> { 0.000000, 0.000000}
4410.000000 -> { 0.000000, 0.000000} -> { 0.000000, 0.865899}
8820.000000 -> {-0.000000,-0.500000} -> { 0.500000,-1.570796}
13230.000000 -> { 0.000000,-0.000000} -> { 0.000000,-0.994491}
17640.000000 -> { 0.000000,-0.000000} -> { 0.000000,-0.484800}
22050.000000 -> { 0.000000, 0.000000} -> { 0.000000, 0.000000}
And if I let it be a clean sin() between two bins (11025):
binFreq -> real img -> amp phase
0.000000 -> { 0.100000, 0.000000} -> { 0.100000, 0.000000}
4410.000000 -> { 0.123607,-0.000000} -> { 0.123607,-0.000000}
8820.000000 -> { 0.323607,-0.000000} -> { 0.323607,-0.000000}
13230.000000 -> {-0.323607, 0.000000} -> { 0.323607, 3.141593}
17640.000000 -> {-0.123607, 0.000000} -> { 0.123607, 3.141593}
22050.000000 -> {-0.100000, 0.000000} -> { 0.100000, 3.141593}
And in the generated signals I get from the above, it's clear that
something fishy is going on:
smp in fwd&back gen(cplx) gen(AmpPhase)
0 0.000000 -0.000000 -0.000000 -0.000000
1 1.000000 1.000000 0.600000 0.600000
2 0.000000 0.000000 0.000000 0.000000
3 -1.000000 -1.000000 -0.400000 -0.400000
4 -0.000000 -0.000000 -0.000000 -0.000000
5 1.000000 1.000000 0.600000 0.600000
6 0.000000 0.000000 0.000000 0.000000
7 -1.000000 -1.000000 -0.400000 -0.400000
8 -0.000000 -0.000000 -0.000000 -0.000000
9 1.000000 1.000000 0.600000 0.600000
Sorry for the long post. Any help would be much appreciated!
Kind regards,
Ted Lyngmo