Hi Fons :)
On 11/25/2009 09:32 PM, [email protected] wrote:
> process (input, output)
> {
> // both input, output are of size fftsize/2
>
> 1. R1 <= IP * W1
> 2. R2 <= input * W2
> 3. IP <= input
> 4. FFT, callback, IFFT
> 5. output <= (R1 + OP) * scale
> 6. OP <= R2
> }
Now, that works ! I'm attaching the fixed code for the records.
I've tried hard to understand where the problem was, and one thing I'm sure
about is that you fft'ize a given block of input twice, once with the ascending
part of the window applied (in R1), then again the same block of data multiplied
with the descending part of the window (in R2).
I'm still far from properly understanding these matters and I was indeed not
doing this. In my code, a given block of fftsize/2 input frames was either
multiplied with the ascending or the descending half-window, but not by both
subsequently, which obviously resulted in a loss of information.
Now, how I managed to get this running in Octave is a mistery to me ;)
Anyway you method did solve my problem, and I now still have a lot of work,
because I need all of this to run with integers (fixed point fft) and the joys
of overflow..
Thanks!
--
Olivier
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "transform.h"
struct Transform {
int fftsize;
TransformCallback callback;
void * callback_data;
fftwf_plan fft;
fftwf_plan ifft;
float * real;
fftwf_complex * cplx;
float * window;
int16_t * input_save;
float * output_save;
};
static void generate_hanning(float *window, int size) {
int i;
float factor = 2.f * M_PI / (size - 1.f);
for (i = 0; i < size; i++) {
window[i] = (1.f - cos(i * factor)) / 2.f;
}
}
Transform *transform_new(int fftsize, TransformCallback callback, void *data) {
Transform *self = calloc(1, sizeof(Transform));
self->fftsize = fftsize;
self->callback = callback;
self->callback_data = data;
self->cplx = fftwf_malloc((fftsize / 2 + 1) * sizeof(*self->cplx));
self->real = fftwf_malloc(fftsize * sizeof(*self->real));
self->input_save = calloc(fftsize / 2, sizeof(*self->input_save));
self->output_save = calloc(fftsize / 2, sizeof(*self->output_save));
self->fft = fftwf_plan_dft_r2c_1d(fftsize, self->real, self->cplx, FFTW_ESTIMATE);
self->ifft = fftwf_plan_dft_c2r_1d(fftsize, self->cplx, self->real, FFTW_ESTIMATE);
self->window = calloc(fftsize, sizeof(*self->window));
generate_hanning(self->window, fftsize);
return self;
}
void transform_destroy(Transform *self) {
fftwf_free(self->real);
fftwf_free(self->cplx);
free(self->input_save);
free(self->output_save);
free(self->window);
fftwf_destroy_plan(self->ifft);
fftwf_destroy_plan(self->fft);
free(self);
}
void transform_process(Transform *self, int16_t *input, int16_t *output) {
int i;
int buffer_size = self->fftsize / 2;
float *real1 = self->real;
float *real2 = self->real + buffer_size;
float *window1 = self->window;
float *window2 = self->window + buffer_size;
for (i = 0; i < buffer_size; i++) {
real1[i] = self->input_save[i] / (float) INT16_MAX * window1[i];
real2[i] = input[i] / (float) INT16_MAX * window2[i];
}
memcpy(self->input_save, input, buffer_size * sizeof(*input));
fftwf_execute(self->fft);
self->callback(self->cplx, self->callback_data);
fftwf_execute(self->ifft);
float scale = INT16_MAX / (float) self->fftsize;
for (i = 0; i < buffer_size; i++) {
output[i] = (real1[i] + self->output_save[i]) * scale;
}
memcpy(self->output_save, real2, buffer_size * sizeof(*real2));
}
#ifndef TRANSFORM_H
#define TRANSFORM_H
#include <stdint.h>
#include <fftw3.h>
typedef struct Transform Transform;
typedef void (* TransformCallback)(fftwf_complex *freqdata, void *data);
Transform * transform_new(int fftsize, TransformCallback callback, void *data);
void transform_destroy(Transform *self);
/* Processes fftsize/2 input frames, calls callback with the freqdata,
and fills output with fftsize/2 frames */
void transform_process(Transform *self, int16_t *input, int16_t *output);
#endif // TRANSFORM_H
_______________________________________________
Linux-audio-dev mailing list
[email protected]
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev