diff options
Diffstat (limited to 'src/sndobj/IFFT.cpp')
-rw-r--r-- | src/sndobj/IFFT.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/src/sndobj/IFFT.cpp b/src/sndobj/IFFT.cpp new file mode 100644 index 0000000..01f693b --- /dev/null +++ b/src/sndobj/IFFT.cpp @@ -0,0 +1,262 @@ + +//////////////////////////////////////////////////////////////////////// +// This file is part of the SndObj library +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Copyright (c)Victor Lazzarini, 1997-2004 +// See License.txt for a disclaimer of all warranties +// and licensing information + +///////////////////////////////////////////////// +// IFFT.cpp: implementation of the IFFT class +// short-time inverse fast fourier transform +// Victor Lazzarini, 2003 +///////////////////////////////////////////////// +#include "IFFT.h" + + +IFFT::IFFT(){ + + m_table = 0; + + // vectorsize equals hopsize + // so that each call of DoProcess adds a + // new window to the overlap-add process + + m_hopsize = DEF_VECSIZE; + m_fftsize = DEF_FFTSIZE; + m_frames = m_fftsize/m_hopsize; + + m_sigframe = new double*[m_frames]; + m_ffttmp = new double[m_fftsize]; + m_counter = new int[m_frames]; + m_halfsize = m_fftsize/2; + m_fund = m_sr/m_fftsize; + int i; + memset(m_ffttmp, 0, m_fftsize*sizeof(double)); + for(i = 0; i < m_frames; i++){ + m_sigframe[i] = new double[m_fftsize]; + memset(m_sigframe[i], 0, m_fftsize*sizeof(double)); + m_counter[i] = i*m_hopsize; + } + + m_plan = rfftw_create_plan(m_fftsize, FFTW_COMPLEX_TO_REAL, FFTW_ESTIMATE); + + AddMsg("fft size", 21); + AddMsg("hop size", 22); + AddMsg("window", 23); + + m_cur = 0; +} + +IFFT::IFFT(Table* window, SndObj* input, int fftsize, int hopsize, + double sr): + SndObj(input,hopsize, sr) +{ + + m_table = window; + + m_hopsize = hopsize; + m_fftsize = fftsize; + + if(m_fftsize){ + m_frames = m_fftsize/m_hopsize; + + m_sigframe = new double*[m_frames]; + m_ffttmp = new double[m_fftsize]; + m_counter = new int[m_frames]; + m_halfsize = m_fftsize/2; + m_fund = m_sr/m_fftsize; + memset(m_ffttmp, 0, m_fftsize*sizeof(double)); + int i; + for(i = 0; i < m_frames; i++){ + m_sigframe[i] = new double[m_fftsize]; + memset(m_sigframe[i], 0, m_fftsize*sizeof(double)); + m_counter[i] = i*m_hopsize; + } + + m_plan = rfftw_create_plan(m_fftsize, FFTW_COMPLEX_TO_REAL, FFTW_ESTIMATE); + } + + AddMsg("fft size", 21); + AddMsg("hop size", 22); + AddMsg("window", 23); + + m_cur = 0; +} + +IFFT::~IFFT(){ + + if(m_fftsize){ +#ifndef WIN + rfftw_destroy_plan(m_plan); +#endif + delete[] m_counter; + delete[] m_ffttmp; + delete[] m_sigframe; + } +} + +void +IFFT::SetFFTSize(int fftsize){ + m_fftsize = fftsize; + ReInit(); +} + +void +IFFT::SetHopSize(int hopsize){ + SetVectorSize(m_hopsize = hopsize); + ReInit(); +} + +void +IFFT::ReInit(){ + + rfftw_destroy_plan(m_plan); + delete[] m_counter; + delete[] m_sigframe; + delete[] m_ffttmp; + delete[] m_output; + + if(!(m_output = new double[m_vecsize])){ + m_error = 1; +#ifdef DEBUG + cout << ErrorMessage(); +#endif + return; + } + + + m_frames = m_fftsize/m_hopsize; + m_sigframe = new double*[m_frames]; + m_ffttmp = new double[m_fftsize]; + m_counter = new int[m_frames]; + m_halfsize = m_fftsize/2; + m_fund = m_sr/m_fftsize; + int i; + for(i = 0; i < m_frames; i++){ + m_sigframe[i] = new double[m_fftsize]; + memset(m_sigframe[i], 0, m_fftsize*sizeof(double)); + m_counter[i] = i*m_hopsize; + } + + m_plan = rfftw_create_plan(m_vecsize, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE); + m_cur =0; + +} + + +int +IFFT::Set(char* mess, double value){ + + switch(FindMsg(mess)){ + + case 21: + SetFFTSize((int) value); + return 1; + + case 22: + SetHopSize((int) value); + return 1; + + default: + return SndObj::Set(mess, value); + + } +} + +int +IFFT::Connect(char* mess, void *input){ + + switch(FindMsg(mess)){ + + case 23: + SetWindow((Table *) input); + return 1; + + default: + return SndObj::Connect(mess, input); + + } + +} + +short +IFFT::DoProcess(){ + + + if(!m_error){ + if(m_input && m_table){ + if(m_enable){ + int i; double out = 0.; + // Put the input fftframe into + // the current (free) signal frame + // and transform it + ifft(m_sigframe[m_cur]); + // set the current signal frame to the next + // one in the circular list + m_counter[m_cur] = 0; + m_cur--; if(m_cur<0) m_cur = m_frames-1; + + for(m_vecpos = 0; m_vecpos < m_vecsize; m_vecpos++){ + // overlap-add the time-domain signal frames + for(i=0; i < m_frames; i++){ + out += m_sigframe[i][m_counter[i]]*m_table->Lookup(m_counter[i]); + m_counter[i]++; + } + // output it. + m_output[m_vecpos] = (double) out; + out = 0.; + } + + return 1; + } else { // if disabled + for(m_vecpos = 0; m_vecpos < m_vecsize; m_vecpos++) + m_output[m_vecpos] = 0.f; + return 1; + } + } else { + m_error = 3; + return 0; + } + } + else + return 0; +} + + + + +void +IFFT::ifft(double* signal) { + + // get input FFT frame and + // prepare data for fftw + + m_ffttmp[0] = m_input->Output(0); + m_ffttmp[m_halfsize] = m_input->Output(1); + for(int i=2, i2=1; i<m_fftsize; i+=2){ + i2 = i/2; + m_ffttmp[i2] = m_input->Output(i); + m_ffttmp[m_fftsize-(i2)] = m_input->Output(i+1); + } + + // Inverse FFT function + rfftw_one(m_plan, m_ffttmp, signal); + +} + + |