FFTwrapper.cpp (3194B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 FFTwrapper.c - A wrapper for Fast Fourier Transforms 5 Copyright (C) 2002-2005 Nasca Octavian Paul 6 Author: Nasca Octavian Paul 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 */ 13 14 #include <cmath> 15 #include <cassert> 16 #include <cstring> 17 #include <pthread.h> 18 #include "FFTwrapper.h" 19 20 namespace zyn { 21 22 static pthread_mutex_t *mutex = NULL; 23 24 FFTwrapper::FFTwrapper(int fftsize_) : m_fftsize(fftsize_) 25 { 26 //first one will spawn the mutex (yeah this may be a race itself) 27 if(!mutex) { 28 mutex = new pthread_mutex_t; 29 pthread_mutex_init(mutex, NULL); 30 } 31 32 time = new fftwf_real[m_fftsize]; 33 fft = new fftwf_complex[m_fftsize + 1]; 34 pthread_mutex_lock(mutex); 35 planfftw = fftwf_plan_dft_r2c_1d(m_fftsize, 36 time, 37 fft, 38 FFTW_ESTIMATE); 39 planfftw_inv = fftwf_plan_dft_c2r_1d(m_fftsize, 40 fft, 41 time, 42 FFTW_ESTIMATE); 43 pthread_mutex_unlock(mutex); 44 } 45 46 FFTwrapper::~FFTwrapper() 47 { 48 pthread_mutex_lock(mutex); 49 fftwf_destroy_plan(planfftw); 50 fftwf_destroy_plan(planfftw_inv); 51 pthread_mutex_unlock(mutex); 52 53 delete [] time; 54 delete [] fft; 55 } 56 57 void FFTwrapper::smps2freqs(const FFTsampleBuffer smps, FFTfreqBuffer freqs, FFTsampleBuffer scratch) const 58 { 59 //Load data 60 memcpy((void *)scratch.data, (const void *)smps.data, m_fftsize * sizeof(float)); 61 62 smps2freqs_noconst_input(scratch, freqs); 63 } 64 65 void FFTwrapper::smps2freqs_noconst_input(FFTsampleBuffer smps, FFTfreqBuffer freqs) const 66 { 67 static_assert (sizeof(float) == sizeof(fftwf_real), "sizeof(float) mismatch"); 68 assert(m_fftsize == freqs.fftsize); 69 assert(m_fftsize == smps.fftsize); 70 71 //DFT 72 fftwf_execute_dft_r2c(planfftw, 73 static_cast<fftwf_real*>(smps.data), 74 reinterpret_cast<fftwf_complex*>(freqs.data)); 75 } 76 77 78 void FFTwrapper::freqs2smps(const FFTfreqBuffer freqs, FFTsampleBuffer smps, FFTfreqBuffer scratch) const 79 { 80 //Load data 81 memcpy((void *)scratch.data, (const void *)freqs.data, m_fftsize * sizeof(float)); 82 83 freqs2smps_noconst_input(scratch, smps); 84 } 85 86 87 void FFTwrapper::freqs2smps_noconst_input(FFTfreqBuffer freqs, FFTsampleBuffer smps) const 88 { 89 static_assert (sizeof(fft_t) == sizeof(fftwf_complex), "sizeof(complex) mismatch"); 90 assert(m_fftsize == freqs.fftsize); 91 assert(m_fftsize == smps.fftsize); 92 fftwf_complex* freqs_complex = reinterpret_cast<fftwf_complex*>(freqs.data); 93 94 //Clear unused freq channel 95 freqs_complex[m_fftsize / 2][0] = 0.0f; 96 freqs_complex[m_fftsize / 2][1] = 0.0f; 97 98 //IDFT 99 fftwf_execute_dft_c2r(planfftw_inv, freqs_complex, smps.data); 100 } 101 102 void FFT_cleanup() 103 { 104 fftwf_cleanup(); 105 pthread_mutex_destroy(mutex); 106 delete mutex; 107 mutex = NULL; 108 } 109 110 }