summaryrefslogtreecommitdiff
path: root/src/sndobj/FFT.cpp
diff options
context:
space:
mode:
authorJohn Glover <glover.john@gmail.com>2011-06-24 18:17:23 +0100
committerJohn Glover <glover.john@gmail.com>2011-06-24 18:17:23 +0100
commit416bd737074a287ea47106c73ea6bcfde40a75a8 (patch)
tree74562303d4f4f2f2e010f7e13cba41dc4852b50c /src/sndobj/FFT.cpp
parentd26519464dcbf8c3682348167c29454961facefe (diff)
downloadsimpl-416bd737074a287ea47106c73ea6bcfde40a75a8.tar.gz
simpl-416bd737074a287ea47106c73ea6bcfde40a75a8.tar.bz2
simpl-416bd737074a287ea47106c73ea6bcfde40a75a8.zip
Change to using distutils.
Currently only builds the simplsndobj module
Diffstat (limited to 'src/sndobj/FFT.cpp')
-rw-r--r--src/sndobj/FFT.cpp265
1 files changed, 265 insertions, 0 deletions
diff --git a/src/sndobj/FFT.cpp b/src/sndobj/FFT.cpp
new file mode 100644
index 0000000..cee737d
--- /dev/null
+++ b/src/sndobj/FFT.cpp
@@ -0,0 +1,265 @@
+
+////////////////////////////////////////////////////////////////////////
+// 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
+
+/////////////////////////////////////////////////
+// FFT.cpp : implementation of the FFT class
+// short-time fast fourier transform
+// Victor Lazzarini, 2003
+/////////////////////////////////////////////////
+#include "FFT.h"
+
+FFT::FFT(){
+
+ m_table = 0;
+
+ // hopsize controls decimation
+ // we have vecsize/hopsize overlapping frames
+ // the vector size is also equal the fftsize
+ // so that each call to DoProcess produces a
+ // new fft frame at the output
+ // since SndObj has already allocated the output
+ // we have to reset the vector size
+
+ m_fftsize = DEF_FFTSIZE;
+ SetVectorSize(DEF_FFTSIZE);
+ m_hopsize = DEF_VECSIZE;
+
+ 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_REAL_TO_COMPLEX, FFTW_ESTIMATE);
+
+ AddMsg("scale", 21);
+ AddMsg("fft size", 22);
+ AddMsg("hop size", 23);
+ AddMsg("window", 24);
+ m_scale = 1.f;
+ m_norm = m_fftsize;
+ m_cur =0;
+}
+
+
+FFT::FFT(Table* window, SndObj* input, double scale,
+ int fftsize, int hopsize, double sr):
+ SndObj(input, fftsize, sr){
+
+ m_table = window;
+
+ m_hopsize = hopsize;
+ m_fftsize = 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_REAL_TO_COMPLEX, FFTW_ESTIMATE);
+
+ AddMsg("scale", 21);
+ AddMsg("fft size", 22);
+ AddMsg("hop size", 23);
+ AddMsg("window", 24);
+ m_scale = scale;
+ m_norm = m_fftsize/m_scale;
+ m_cur =0;
+}
+
+
+FFT::~FFT(){
+#ifndef WIN
+ rfftw_destroy_plan(m_plan);
+#endif
+ delete[] m_counter;
+ delete[] m_sigframe;
+ delete[] m_ffttmp;
+}
+
+void
+FFT::SetFFTSize(int fftsize){
+ SetVectorSize(m_fftsize = fftsize);
+ ReInit();
+}
+
+void
+FFT::SetHopSize(int hopsize){
+ m_hopsize = hopsize;
+ ReInit();
+}
+
+void
+FFT::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;
+ m_norm = m_fftsize/m_scale;
+}
+
+
+int
+FFT::Set(char* mess, double value){
+
+ switch(FindMsg(mess)){
+
+ case 21:
+ SetScale(value);
+ return 1;
+
+ case 22:
+ SetFFTSize((int) value);
+ return 1;
+
+ case 23:
+ SetHopSize((int) value);
+ return 1;
+
+ default:
+ return SndObj::Set(mess, value);
+
+ }
+}
+
+int
+FFT::Connect(char* mess, void *input){
+
+ switch(FindMsg(mess)){
+
+ case 24:
+ SetWindow((Table *) input);
+ return 1;
+
+ default:
+ return SndObj::Connect(mess, input);
+
+ }
+
+}
+
+short
+FFT::DoProcess(){
+
+ if(!m_error){
+ if(m_input && m_table){
+ if(m_enable){
+ int i; double sig = 0.f;
+ for(m_vecpos = 0; m_vecpos < m_hopsize; m_vecpos++) {
+ // signal input
+ sig = m_input->Output(m_vecpos);
+ // distribute to the signal fftframes and apply the window
+ // according to a time pointer (kept by counter[n])
+ for(i=0;i < m_frames; i++){
+ m_sigframe[i][m_counter[i]]= sig*m_table->Lookup(m_counter[i]);
+ m_counter[i]++;
+ }
+ }
+ // every hopsize samples
+ // set the current sigframe to be transformed
+ m_cur--; if(m_cur<0) m_cur = m_frames-1;
+ // transform it and fill the output buffer
+ fft(m_sigframe[m_cur]);
+ // zero the current sigframe time pointer
+ m_counter[m_cur] = 0;
+ return 1;
+
+ } else { // if disabled
+ for(m_vecpos=0; m_vecpos < m_hopsize; m_vecpos++)
+ m_output[m_vecpos] = 0.f;
+ return 1;
+ }
+ } else {
+ m_error = 3;
+ return 0;
+ }
+ }
+ else
+ return 0;
+}
+
+void
+FFT::fft(double* signal){
+
+ // FFT function
+ rfftw_one(m_plan, signal, m_ffttmp);
+
+ // re-arrange output into re, im format
+ // packing re[0] and re[nyquist] together,
+ // normalise it and fill the output buffer
+
+ m_output[0] = m_ffttmp[0]/m_norm;
+ m_output[1] = m_ffttmp[m_halfsize]/m_norm;
+ for(int i=2, i2=1; i<m_fftsize; i+=2){
+ i2 = i/2;
+ m_output[i] = m_ffttmp[i2]/m_norm;
+ m_output[i+1] = m_ffttmp[m_fftsize-(i2)]/m_norm;
+ }
+
+
+}
+