source: src/fft.c @ 01af943

feature/autosinkfeature/constantqfeature/pitchshiftfeature/pydocstringsfeature/timestretchpitchshiftsamplertimestretchyinfft+
Last change on this file since 01af943 was 01af943, checked in by Paul Brossier <piem@piem.org>, 13 years ago

fft.c: reduce size of specdata with COMPLEX_H, fix computations without COMPLEX_H

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2   Copyright (C) 2003 Paul Brossier
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18*/
19
20#include "aubio_priv.h"
21#include "sample.h"
22#include "mathutils.h"
23#include "fft.h"
24
25#if FFTW3F_SUPPORT
26#define fftw_malloc             fftwf_malloc
27#define fftw_free               fftwf_free
28#define fftw_execute            fftwf_execute
29#define fftw_plan_dft_r2c_1d    fftwf_plan_dft_r2c_1d
30#define fftw_plan_dft_c2r_1d    fftwf_plan_dft_c2r_1d
31#define fftw_plan_r2r_1d      fftwf_plan_r2r_1d
32#define fftw_plan               fftwf_plan
33#define fftw_destroy_plan       fftwf_destroy_plan
34#endif
35
36#if FFTW3F_SUPPORT
37#define real_t smpl_t
38#else
39#define real_t lsmp_t
40#endif
41
42struct _aubio_fft_t {
43        uint_t fft_size;
44        uint_t channels;
45        real_t          *in, *out;
46        fft_data_t      *specdata;
47        fftw_plan       pfw, pbw;
48};
49
50static void aubio_fft_getspectrum(fft_data_t * spectrum, smpl_t *norm, smpl_t * phas, uint_t size);
51
52aubio_fft_t * new_aubio_fft(uint_t size) {
53        aubio_fft_t * s = AUBIO_NEW(aubio_fft_t);
54        /* allocate memory */
55        s->in       = AUBIO_ARRAY(real_t,size);
56        s->out      = AUBIO_ARRAY(real_t,size);
57        /* create plans */
58#ifdef HAVE_COMPLEX_H
59  s->fft_size = size/2+1;
60        s->specdata = (fft_data_t*)fftw_malloc(sizeof(fft_data_t)*s->fft_size);
61        s->pfw = fftw_plan_dft_r2c_1d(size, s->in,  s->specdata, FFTW_ESTIMATE);
62        s->pbw = fftw_plan_dft_c2r_1d(size, s->specdata, s->out, FFTW_ESTIMATE);
63#else
64  s->fft_size = size;
65        s->specdata = (fft_data_t*)fftw_malloc(sizeof(fft_data_t)*s->fft_size);
66        s->pfw = fftw_plan_r2r_1d(size, s->in,  s->specdata, FFTW_R2HC, FFTW_ESTIMATE);
67        s->pbw = fftw_plan_r2r_1d(size, s->specdata, s->out, FFTW_HC2R, FFTW_ESTIMATE);
68#endif
69        return s;
70}
71
72void del_aubio_fft(aubio_fft_t * s) {
73        /* destroy data */
74        fftw_destroy_plan(s->pfw);
75        fftw_destroy_plan(s->pbw);
76        fftw_free(s->specdata);
77        AUBIO_FREE(s->out);
78        AUBIO_FREE(s->in );
79        AUBIO_FREE(s);
80}
81
82void aubio_fft_do(const aubio_fft_t * s, 
83                const smpl_t * data, fft_data_t * spectrum, 
84                const uint_t size) {
85        uint_t i;
86        for (i=0;i<size;i++) s->in[i] = data[i];
87        fftw_execute(s->pfw);
88        for (i=0; i < s->fft_size; i++) spectrum[i] = s->specdata[i];
89}
90
91void aubio_fft_rdo(const aubio_fft_t * s, 
92                const fft_data_t * spectrum, 
93                smpl_t * data, 
94                const uint_t size) {
95        uint_t i;
96        const smpl_t renorm = 1./(smpl_t)size;
97        for (i=0; i < s->fft_size; i++) s->specdata[i] = spectrum[i];
98        fftw_execute(s->pbw);
99        for (i=0;i<size;i++) data[i] = s->out[i]*renorm;
100}
101
102#ifdef HAVE_COMPLEX_H
103
104void aubio_fft_getnorm(smpl_t * norm, fft_data_t * spectrum, uint_t size) {
105        uint_t i;
106        for (i=0;i<size/2+1;i++) norm[i] = ABSC(spectrum[i]);
107        //for (i=0;i<size/2+1;i++) AUBIO_DBG("%f\n", norm[i]);
108}
109
110void aubio_fft_getphas(smpl_t * phas, fft_data_t * spectrum, uint_t size) {
111        uint_t i;
112        for (i=0;i<size/2+1;i++) phas[i] = ARGC(spectrum[i]);
113        //for (i=0;i<size/2+1;i++) AUBIO_DBG("%f\n", phas[i]);
114}
115
116void aubio_fft_getspectrum(fft_data_t * spectrum, smpl_t *norm, smpl_t * phas, uint_t size) {
117  uint_t j;
118  for (j=0; j<size/2+1; j++) {
119    spectrum[j]  = CEXPC(I*phas[j]);
120    spectrum[j] *= norm[j];
121  }
122}
123
124#else
125
126void aubio_fft_getnorm(smpl_t * norm, fft_data_t * spectrum, uint_t size) {
127        uint_t i;
128  norm[0] = SQR(spectrum[0]);
129        for (i=1;i<size/2;i++) norm[i] = (SQR(spectrum[i]) + SQR(spectrum[size-i]));
130        norm[size/2] = SQR(spectrum[size/2]);
131        //for (i=0;i<size/2+1;i++) AUBIO_DBG("%f\n", norm[i]);
132}
133
134void aubio_fft_getphas(smpl_t * phas, fft_data_t * spectrum, uint_t size) {
135        uint_t i;
136  phas[0] = 0;
137        for (i=1;i<size/2+1;i++) phas[i] = atan2f(spectrum[size-i] , spectrum[i]);
138  phas[size/2] = 0;
139        //for (i=0;i<size/2+1;i++) AUBIO_DBG("%f\n", phas[i]);
140}
141
142void aubio_fft_getspectrum(fft_data_t * spectrum, smpl_t *norm, smpl_t * phas, uint_t size) {
143  uint_t j;
144  for (j=0; j<size/2+1; j++) {
145    spectrum[j]       = norm[j]*COS(phas[j]);
146  }
147  for (j=1; j<size/2+1; j++) {
148    spectrum[size-j]  = norm[j]*SIN(phas[j]);
149  }
150}
151
152#endif
153
154/* new interface aubio_mfft */
155struct _aubio_mfft_t {
156        aubio_fft_t * fft;      /* fftw interface */
157        fft_data_t ** spec;     /* complex spectral data */
158        uint_t winsize;
159        uint_t channels;
160};
161
162aubio_mfft_t * new_aubio_mfft(uint_t winsize, uint_t channels){
163        uint_t i;
164        aubio_mfft_t * fft = AUBIO_NEW(aubio_mfft_t);
165        fft->winsize       = winsize;
166        fft->channels      = channels;
167        fft->fft           = new_aubio_fft(winsize);
168        fft->spec          = AUBIO_ARRAY(fft_data_t*,channels);
169        for (i=0; i < channels; i++)
170                fft->spec[i] = AUBIO_ARRAY(fft_data_t,winsize);
171        return fft;
172}
173
174/* execute stft */
175void aubio_mfft_do (aubio_mfft_t * fft,fvec_t * in,cvec_t * fftgrain){
176        uint_t i=0;
177        /* execute stft */
178        for (i=0; i < fft->channels; i++) {
179                aubio_fft_do (fft->fft,in->data[i],fft->spec[i],fft->winsize);
180                /* put norm and phase into fftgrain */
181                aubio_fft_getnorm(fftgrain->norm[i], fft->spec[i], fft->winsize);
182                aubio_fft_getphas(fftgrain->phas[i], fft->spec[i], fft->winsize);
183        }
184}
185
186/* execute inverse fourier transform */
187void aubio_mfft_rdo(aubio_mfft_t * fft,cvec_t * fftgrain, fvec_t * out){
188        uint_t i=0;
189        for (i=0; i < fft->channels; i++) {
190                aubio_fft_getspectrum(fft->spec[i],fftgrain->norm[i],fftgrain->phas[i],fft->winsize);
191                aubio_fft_rdo(fft->fft,fft->spec[i],out->data[i],fft->winsize);
192        }
193}
194
195void del_aubio_mfft(aubio_mfft_t * fft) {
196        uint_t i;
197        for (i=0; i < fft->channels; i++)
198                AUBIO_FREE(fft->spec[i]);
199        AUBIO_FREE(fft->spec);
200        del_aubio_fft(fft->fft);
201        AUBIO_FREE(fft);       
202}
Note: See TracBrowser for help on using the repository browser.