changeset 9:a1539d4e3b08

* Tidy code, start doc
author Chris Cannam
date Sat, 12 Jun 2010 13:08:33 +0100
parents e15ebd222c63
children 25580443645c
files Makefile devuvuzelator-ladspa.cpp devuvuzelator-ladspa.h devuvuzelator-vst.cpp devuvuzelator-vst.h devuvuzelator.cpp fft.cpp median.h params.h
diffstat 9 files changed, 377 insertions(+), 479 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Sat Jun 12 13:08:33 2010 +0100
@@ -0,0 +1,17 @@
+
+CXXFLAGS	:= -DLADSPA -fpic -O3 -ffast-math -msse -msse2 -mfpmath=sse -ftree-vectorize
+
+SOURCES		:= devuvuzelator.cpp devuvuzelator-ladspa.cpp fft.cpp
+OBJECTS		:= devuvuzelator.o devuvuzelator-ladspa.o fft.o
+HEADERS		:= devuvuzelator-ladspa.h params.h median.h
+
+devuvuzelator.so:	$(SOURCES)
+	$(CXX) $^ $(CXXFLAGS) -shared -o $@
+
+clean:		
+	rm -f $(OBJECTS)
+
+devuvuzelator.cpp:	$(HEADERS)
+devuvuzelator-ladspa.cpp:	$(HEADERS)
+fft.cpp:	$(HEADERS)
+
--- a/devuvuzelator-ladspa.cpp	Fri Jun 11 20:20:20 2010 +0100
+++ b/devuvuzelator-ladspa.cpp	Sat Jun 12 13:08:33 2010 +0100
@@ -1,85 +1,12 @@
 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
 
-#include <ladspa.h>
+#include "devuvuzelator-ladspa.h"
+
 #include <alloca.h>
 #include <iostream>
 #include <cmath>
 
-#include "median.h"
-
-#define FFTSIZE 4096
-#define WINSIZE 1024
-
-class Devuvuzelator
-{
-public:
-    static const LADSPA_Descriptor *getDescriptor(unsigned long index);
-
-private:
-    Devuvuzelator(int sampleRate);
-    ~Devuvuzelator();
-
-    enum {
-        InputPort     = 0,
-	OutputPort    = 1,
-        LatencyPort   = 2,
-        FundamentalPort = 3,
-        BandwidthPort = 4,
-        HarmonicsPort = 5,
-        ReductionPort = 6,
-	PortCount     = 7,
-    };
-
-    static const char *const portNames[PortCount];
-    static const LADSPA_PortDescriptor ports[PortCount];
-    static const LADSPA_PortRangeHint hints[PortCount];
-    static const LADSPA_Properties properties;
-    static const LADSPA_Descriptor ladspaDescriptor;
-
-    static LADSPA_Handle instantiate(const LADSPA_Descriptor *, unsigned long);
-    static void connectPort(LADSPA_Handle, unsigned long, LADSPA_Data *);
-    static void activate(LADSPA_Handle);
-    static void run(LADSPA_Handle, unsigned long);
-    static void deactivate(LADSPA_Handle);
-    static void cleanup(LADSPA_Handle);
-
-    void reset();
-    void window(float *);
-    void runImpl(unsigned long);
-    void processFrame();
-    void processSpectralFrame();
-    void updateParameters();
-
-    static void fft(unsigned int n, bool inverse,
-                    double *ri, double *ii, double *ro, double *io);
-
-    int m_sampleRate;
-    float *m_input;
-    float *m_output;
-
-    float m_fundamental;
-    float m_bandwidth;
-    float m_harmonics;
-    float m_reduction;
-
-    float *m_platency;
-    float *m_pfundamental;
-    float *m_pbandwidth;
-    float *m_pharmonics;
-    float *m_preduction;
-
-    const int m_fftsize;
-    const int m_winsize;
-    const int m_increment;
-    int m_fill;
-    int m_read;
-    float *m_buffer;
-    float *m_outacc;
-    double *m_real;
-    double *m_imag;
-    double *m_window;
-    MedianFilter<double> **m_medians;
-};
+#include "params.h"
 
 const char *const
 Devuvuzelator::portNames[PortCount] =
@@ -167,6 +94,7 @@
     m_fftsize(FFTSIZE),
     m_winsize(WINSIZE),
     m_increment(m_winsize/2),
+    m_filtersecs(FILTERSECS),
     m_fill(0),
     m_read(0)
 {
@@ -358,130 +286,9 @@
     }
 }
 
-// FFT implementation by Don Cross, public domain.
-// This version scales the forward transform.
-
-void Devuvuzelator::fft(unsigned int n, bool inverse,
-                        double *ri, double *ii, double *ro, double *io)
-{
-    if (!ri || !ro || !io) return;
-
-    unsigned int bits;
-    unsigned int i, j, k, m;
-    unsigned int blockSize, blockEnd;
-
-    double tr, ti;
-
-    if (n < 2) return;
-    if (n & (n-1)) return;
-
-    double angle = 2.0 * M_PI;
-    if (inverse) angle = -angle;
-
-    for (i = 0; ; ++i) {
-	if (n & (1 << i)) {
-	    bits = i;
-	    break;
-	}
-    }
-
-    static unsigned int tableSize = 0;
-    static int *table = 0;
-
-    if (tableSize != n) {
-
-	delete[] table;
-
-	table = new int[n];
-
-	for (i = 0; i < n; ++i) {
-	
-	    m = i;
-
-	    for (j = k = 0; j < bits; ++j) {
-		k = (k << 1) | (m & 1);
-		m >>= 1;
-	    }
-
-	    table[i] = k;
-	}
-
-	tableSize = n;
-    }
-
-    if (ii) {
-	for (i = 0; i < n; ++i) {
-	    ro[table[i]] = ri[i];
-	    io[table[i]] = ii[i];
-	}
-    } else {
-	for (i = 0; i < n; ++i) {
-	    ro[table[i]] = ri[i];
-	    io[table[i]] = 0.0;
-	}
-    }
-
-    blockEnd = 1;
-
-    for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
-
-	double delta = angle / (double)blockSize;
-	double sm2 = -sin(-2 * delta);
-	double sm1 = -sin(-delta);
-	double cm2 = cos(-2 * delta);
-	double cm1 = cos(-delta);
-	double w = 2 * cm1;
-	double ar[3], ai[3];
-
-	for (i = 0; i < n; i += blockSize) {
-
-	    ar[2] = cm2;
-	    ar[1] = cm1;
-
-	    ai[2] = sm2;
-	    ai[1] = sm1;
-
-	    for (j = i, m = 0; m < blockEnd; j++, m++) {
-
-		ar[0] = w * ar[1] - ar[2];
-		ar[2] = ar[1];
-		ar[1] = ar[0];
-
-		ai[0] = w * ai[1] - ai[2];
-		ai[2] = ai[1];
-		ai[1] = ai[0];
-
-		k = j + blockEnd;
-		tr = ar[0] * ro[k] - ai[0] * io[k];
-		ti = ar[0] * io[k] + ai[0] * ro[k];
-
-		ro[k] = ro[j] - tr;
-		io[k] = io[j] - ti;
-
-		ro[j] += tr;
-		io[j] += ti;
-	    }
-	}
-
-	blockEnd = blockSize;
-    }
-
-    if (!inverse) {
-
-	double denom = (double)n;
-
-	for (i = 0; i < n; i++) {
-	    ro[i] /= denom;
-	    io[i] /= denom;
-	}
-    }
-}
-
 const LADSPA_Descriptor *
 ladspa_descriptor(unsigned long ix)
 {
     return Devuvuzelator::getDescriptor(ix);
 }
 
-#include "devuvuzelator.cpp"
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/devuvuzelator-ladspa.h	Sat Jun 12 13:08:33 2010 +0100
@@ -0,0 +1,82 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+#ifndef _DEVUVUZELATOR_LADSPA_H_
+#define _DEVUVUZELATOR_LADSPA_H_
+
+#include <ladspa.h>
+
+#include "median.h"
+
+class Devuvuzelator
+{
+public:
+    static const LADSPA_Descriptor *getDescriptor(unsigned long index);
+
+private:
+    Devuvuzelator(int sampleRate);
+    ~Devuvuzelator();
+
+    enum {
+        InputPort     = 0,
+	OutputPort    = 1,
+        LatencyPort   = 2,
+        FundamentalPort = 3,
+        BandwidthPort = 4,
+        HarmonicsPort = 5,
+        ReductionPort = 6,
+	PortCount     = 7,
+    };
+
+    static const char *const portNames[PortCount];
+    static const LADSPA_PortDescriptor ports[PortCount];
+    static const LADSPA_PortRangeHint hints[PortCount];
+    static const LADSPA_Properties properties;
+    static const LADSPA_Descriptor ladspaDescriptor;
+
+    static LADSPA_Handle instantiate(const LADSPA_Descriptor *, unsigned long);
+    static void connectPort(LADSPA_Handle, unsigned long, LADSPA_Data *);
+    static void activate(LADSPA_Handle);
+    static void run(LADSPA_Handle, unsigned long);
+    static void deactivate(LADSPA_Handle);
+    static void cleanup(LADSPA_Handle);
+
+    void reset();
+    void window(float *);
+    void runImpl(unsigned long);
+    void processFrame();
+    void processSpectralFrame();
+    void updateParameters();
+
+    static void fft(unsigned int n, bool inverse,
+                    double *ri, double *ii, double *ro, double *io);
+
+    int m_sampleRate;
+    float *m_input;
+    float *m_output;
+
+    float m_fundamental;
+    float m_bandwidth;
+    float m_harmonics;
+    float m_reduction;
+
+    float *m_platency;
+    float *m_pfundamental;
+    float *m_pbandwidth;
+    float *m_pharmonics;
+    float *m_preduction;
+
+    const int m_fftsize;
+    const int m_winsize;
+    const int m_increment;
+    const float m_filtersecs;
+    int m_fill;
+    int m_read;
+    float *m_buffer;
+    float *m_outacc;
+    double *m_real;
+    double *m_imag;
+    double *m_window;
+    MedianFilter<double> **m_medians;
+};
+
+#endif
--- a/devuvuzelator-vst.cpp	Fri Jun 11 20:20:20 2010 +0100
+++ b/devuvuzelator-vst.cpp	Sat Jun 12 13:08:33 2010 +0100
@@ -1,95 +1,17 @@
 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
 
+#include "devuvuzelator-vst.h"
+
 #define _USE_MATH_DEFINES
-
+#include <cmath>
 #include <iostream>
-#include <cmath>
 #include <cstdio>
 
-#include "public.sdk/source/vst2.x/audioeffect.h"
+#include "params.h"
 
 #define snprintf _snprintf
 #define alloca _alloca
 
-#define FFTSIZE 1024
-#define WINSIZE 1024
-
-#include "median.h"
-
-class Devuvuzelator : public AudioEffect
-{
-    enum {
-        FundamentalParam = 0,
-        BandwidthParam = 1,
-        HarmonicsParam = 2,
-        ReductionParam = 3,
-        NumParams      = 4
-    };
-
-public:
-    Devuvuzelator(audioMasterCallback cb);
-    ~Devuvuzelator();
-
-    virtual void getEffectName(char *n) {
-        vst_strncpy(n, "Devuvuzelator", kVstMaxEffectNameLen);
-    }
-    virtual void getProductString(char *n) {
-        vst_strncpy(n, "Devuvuzelator", kVstMaxProductStrLen);
-    }
-    virtual void getVendorString(char *n) {
-        vst_strncpy(n, "Queen Mary, University of London", kVstMaxVendorStrLen);
-    }
-
-    virtual void setParameter(VstInt32 index, float value);
-    virtual float getParameter(VstInt32 index);
-    virtual void getParameterLabel(VstInt32 index, char* label);
-    virtual void getParameterDisplay(VstInt32 index, char* text);
-    virtual void getParameterName(VstInt32 index, char* text);
-    
-    virtual void setSampleRate (float sampleRate) {
-        m_sampleRate = sampleRate;
-        AudioEffect::setSampleRate(sampleRate);
-    }
-
-    virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) {
-        m_input = inputs[0];
-        m_output = outputs[0];
-        runImpl(sampleFrames);
-    }
-
-    void reset();
-    void window(float *);
-    void runImpl(unsigned long);
-    void processFrame();
-    void processSpectralFrame();
-
-    static void fft(unsigned int n, bool inverse,
-                    double *ri, double *ii, double *ro, double *io);
-
-    float m_sampleRate;
-    float *m_input;
-    float *m_output;
-
-    float m_fundamental;
-    float m_bandwidth;
-    int m_harmonics;
-    float m_reduction;
-
-    const int m_fftsize;
-    const int m_winsize;
-    const int m_increment;
-    int m_fill;
-    int m_read;
-    float *m_buffer;
-    float *m_outacc;
-	double *m_frame;
-	double *m_spare;
-    double *m_real;
-    double *m_imag;
-    double *m_window;
-    MedianFilter<double> **m_medians;
-};
-
 // VST params 0->1
 
 void
@@ -164,14 +86,15 @@
     m_fftsize(FFTSIZE),
     m_winsize(WINSIZE),
     m_increment(m_winsize/2),
+    m_filtersecs(FILTERSECS),
     m_fill(0),
     m_read(0)
 {
     m_buffer = new float[m_winsize];
     m_outacc = new float[m_winsize * 2];
     m_window = new double[m_winsize];
-	m_frame = new double[m_fftsize];
-	m_spare = new double[m_fftsize];
+    m_frame = new double[m_fftsize];
+    m_spare = new double[m_fftsize];
     m_real = new double[m_fftsize];
     m_imag = new double[m_fftsize];
     m_medians = new MedianFilter<double> *[m_fftsize/2+1];
@@ -201,8 +124,8 @@
 {
     delete[] m_buffer;
     delete[] m_outacc;
-	delete[] m_frame;
-	delete[] m_spare;
+    delete[] m_frame;
+    delete[] m_spare;
     delete[] m_real;
     delete[] m_imag;
     delete[] m_window;
@@ -234,51 +157,19 @@
     if (!m_input || !m_output) return;
 
     const int sc = sampleCount;
-/*
-	static FILE *blah = 0;
-	if (!blah) {
-		blah = fopen("d:\\devuvu-counts.txt", "w");
-	}
 
-	if (m_input == m_output) fprintf(blah, "in-place\n");
-*/
-	float *output = m_output;
-	if (m_input == m_output) {
-		output = (float *)alloca(sampleCount * sizeof(float));
-	}
-/*	
-	float inmean = 0;
-	for (int i = 0; i < sc; ++i) {
-		inmean += m_input[i] * m_input[i];
-		fprintf(blah, "i:%d:%f ", i, m_input[i]);
-	}
-	inmean/=sc;
-	inmean = sqrt(inmean);
+    float *output = m_output;
+    if (m_input == m_output) {
+        output = (float *)alloca(sampleCount * sizeof(float));
+    }
 
-	fprintf(blah, "%d\n", (int)sampleCount);
-	fflush(blah);
-*/
-	int oi = 0;
-	for (int ii = 0; ii < sc; ++ii) {
+    int oi = 0;
+    for (int ii = 0; ii < sc; ++ii) {
 
-		output[oi++] = m_outacc[m_read++];
-//	m_output[oi++] = inmean * float(ii%100)/100;
-//	m_read++;
+        output[oi++] = m_outacc[m_read++];
         if (m_fill == m_winsize) {
 
             processFrame();
-/*
-	for (int i = 0; i < m_winsize; ++i) {
-		float v = m_buffer[i];
-		fprintf(blah, "%f ", v);
-		m_outacc[m_winsize + i] = m_buffer[i];//m_input[i];//m_buffer[i] ;//* m_window[i];
-	}
-	fprintf(blah, "\n");
-
-//			for (int j = 0; j < m_winsize; ++j) {
-//				m_outacc[m_winsize+j] = inmean * float(j%100)/100;
-//			}
-*/
 
             for (int j = m_increment; j < m_winsize; ++j) {
                 m_buffer[j - m_increment] = m_buffer[j];
@@ -295,34 +186,18 @@
             m_fill = m_fill - m_increment;
             m_read = m_read - m_increment;
         }
-/*
-		fprintf(blah, "%d:%f ", ii, m_input[ii]);
-*/
-		m_buffer[m_fill] = m_input[ii];
-		++m_fill;
+        m_buffer[m_fill] = m_input[ii];
+        ++m_fill;
     }
 
-	static int block = 0;
-	for (int i = 0; i < sc; ++i) {
-//		m_output[i] = float(block % 100) / 100;
-//		m_output[i] = inmean * float(i % 100) / 100;
-	}
-	++block;
-
-	if (m_input == m_output) {
-		for (int i = 0; i < sc; ++i) m_output[i] = output[i];
-	}
+    if (m_input == m_output) {
+        for (int i = 0; i < sc; ++i) m_output[i] = output[i];
+    }
 }
 
 void
 Devuvuzelator::processFrame()
 {
-/*	for (int i = 0; i < m_winsize; ++i) {
-		m_outacc[m_winsize + i] += m_buffer[i] ;//* m_window[i];
-	}
-	return;
-*/
-
     for (int i = 0; i < m_fftsize; ++i) {
         m_frame[i] = 0.0;
     }
@@ -336,7 +211,7 @@
 
     fft(m_fftsize, false, m_frame, 0, m_real, m_imag);
 
-//    processSpectralFrame();
+    processSpectralFrame();
 
     for (int i = 0; i < m_fftsize/2-1; ++i) {
         m_real[m_fftsize-i-1] =  m_real[i+1];
@@ -353,129 +228,9 @@
     }
 }
 
-// FFT implementation by Don Cross, public domain.
-// This version scales the forward transform.
-
-void Devuvuzelator::fft(unsigned int n, bool inverse,
-                        double *ri, double *ii, double *ro, double *io)
-{
-    if (!ri || !ro || !io) return;
-
-    unsigned int bits;
-    unsigned int i, j, k, m;
-    unsigned int blockSize, blockEnd;
-
-    double tr, ti;
-
-    if (n < 2) return;
-    if (n & (n-1)) return;
-
-    double angle = 2.0 * M_PI;
-    if (inverse) angle = -angle;
-
-    for (i = 0; ; ++i) {
-	if (n & (1 << i)) {
-	    bits = i;
-	    break;
-	}
-    }
-
-    static unsigned int tableSize = 0;
-    static int *table = 0;
-
-    if (tableSize != n) {
-
-	delete[] table;
-
-	table = new int[n];
-
-	for (i = 0; i < n; ++i) {
-	
-	    m = i;
-
-	    for (j = k = 0; j < bits; ++j) {
-		k = (k << 1) | (m & 1);
-		m >>= 1;
-	    }
-
-	    table[i] = k;
-	}
-
-	tableSize = n;
-    }
-
-    if (ii) {
-	for (i = 0; i < n; ++i) {
-	    ro[table[i]] = ri[i];
-	    io[table[i]] = ii[i];
-	}
-    } else {
-	for (i = 0; i < n; ++i) {
-	    ro[table[i]] = ri[i];
-	    io[table[i]] = 0.0;
-	}
-    }
-
-    blockEnd = 1;
-
-    for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
-
-	double delta = angle / (double)blockSize;
-	double sm2 = -sin(-2 * delta);
-	double sm1 = -sin(-delta);
-	double cm2 = cos(-2 * delta);
-	double cm1 = cos(-delta);
-	double w = 2 * cm1;
-	double ar[3], ai[3];
-
-	for (i = 0; i < n; i += blockSize) {
-
-	    ar[2] = cm2;
-	    ar[1] = cm1;
-
-	    ai[2] = sm2;
-	    ai[1] = sm1;
-
-	    for (j = i, m = 0; m < blockEnd; j++, m++) {
-
-		ar[0] = w * ar[1] - ar[2];
-		ar[2] = ar[1];
-		ar[1] = ar[0];
-
-		ai[0] = w * ai[1] - ai[2];
-		ai[2] = ai[1];
-		ai[1] = ai[0];
-
-		k = j + blockEnd;
-		tr = ar[0] * ro[k] - ai[0] * io[k];
-		ti = ar[0] * io[k] + ai[0] * ro[k];
-
-		ro[k] = ro[j] - tr;
-		io[k] = io[j] - ti;
-
-		ro[j] += tr;
-		io[j] += ti;
-	    }
-	}
-
-	blockEnd = blockSize;
-    }
-
-    if (!inverse) {
-
-	double denom = (double)n;
-
-	for (i = 0; i < n; i++) {
-	    ro[i] /= denom;
-	    io[i] /= denom;
-	}
-    }
-}
-
 AudioEffect *createEffectInstance(audioMasterCallback audioMaster)
 {
     return new Devuvuzelator(audioMaster);
 }
 
-#include "devuvuzelator.cpp"
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/devuvuzelator-vst.h	Sat Jun 12 13:08:33 2010 +0100
@@ -0,0 +1,84 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+#ifndef _DEVUVUZELATOR_VST_H_
+#define _DEVUVUZELATOR_VST_H_
+
+#include "public.sdk/source/vst2.x/audioeffect.h"
+#include "median.h"
+
+class Devuvuzelator : public AudioEffect
+{
+    enum {
+        FundamentalParam = 0,
+        BandwidthParam = 1,
+        HarmonicsParam = 2,
+        ReductionParam = 3,
+        NumParams      = 4
+    };
+
+public:
+    Devuvuzelator(audioMasterCallback cb);
+    ~Devuvuzelator();
+
+    virtual void getEffectName(char *n) {
+        vst_strncpy(n, "Devuvuzelator", kVstMaxEffectNameLen);
+    }
+    virtual void getProductString(char *n) {
+        vst_strncpy(n, "Devuvuzelator", kVstMaxProductStrLen);
+    }
+    virtual void getVendorString(char *n) {
+        vst_strncpy(n, "Queen Mary, University of London", kVstMaxVendorStrLen);
+    }
+
+    virtual void setParameter(VstInt32 index, float value);
+    virtual float getParameter(VstInt32 index);
+    virtual void getParameterLabel(VstInt32 index, char* label);
+    virtual void getParameterDisplay(VstInt32 index, char* text);
+    virtual void getParameterName(VstInt32 index, char* text);
+    
+    virtual void setSampleRate (float sampleRate) {
+        m_sampleRate = sampleRate;
+        AudioEffect::setSampleRate(sampleRate);
+    }
+
+    virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) {
+        m_input = inputs[0];
+        m_output = outputs[0];
+        runImpl(sampleFrames);
+    }
+
+    void reset();
+    void window(float *);
+    void runImpl(unsigned long);
+    void processFrame();
+    void processSpectralFrame();
+
+    static void fft(unsigned int n, bool inverse,
+                    double *ri, double *ii, double *ro, double *io);
+
+    float m_sampleRate;
+    float *m_input;
+    float *m_output;
+
+    float m_fundamental;
+    float m_bandwidth;
+    int m_harmonics;
+    float m_reduction;
+
+    const int m_fftsize;
+    const int m_winsize;
+    const int m_increment;
+    const float m_filtersecs;
+    int m_fill;
+    int m_read;
+    float *m_buffer;
+    float *m_outacc;
+    double *m_frame;
+    double *m_spare;
+    double *m_real;
+    double *m_imag;
+    double *m_window;
+    MedianFilter<double> **m_medians;
+};
+
+#endif
--- a/devuvuzelator.cpp	Fri Jun 11 20:20:20 2010 +0100
+++ b/devuvuzelator.cpp	Sat Jun 12 13:08:33 2010 +0100
@@ -1,19 +1,29 @@
 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
 
+#ifdef VST
+#include "devuvuzelator-vst.h"
+#else
+#ifdef LADSPA
+#include "devuvuzelator-ladspa.h"
+#else
+#error Need to define either VST or LADSPA
+#endif
+#endif
+
 void
 Devuvuzelator::processSpectralFrame()
 {
     const int hs = m_fftsize/2 + 1;
     double *mags = (double *)alloca(hs * sizeof(double));
-    double *ratios = (double *)alloca(hs * sizeof(double));
     for (int i = 0; i < hs; ++i) {
-        ratios[i] = 1.0;
         mags[i] = sqrt(m_real[i] * m_real[i] + m_imag[i] * m_imag[i]);
     }
 
     double lowfun = m_fundamental - m_bandwidth/2;
     double highfun = m_fundamental + m_bandwidth/2;
 
+    int ix = 0;
+
     for (int h = 1; h <= m_harmonics; ++h) {
 
         double lowfreq = lowfun * h;
@@ -23,30 +33,31 @@
         int highbin = 0.5 + (m_fftsize * highfreq) / m_sampleRate;
 
         for (int i = lowbin; i <= highbin; ++i) {
-/*
+
             if (!m_medians[i]) {
-                const float filtersecs = 5.f;
-                int filterlen = (filtersecs * m_sampleRate) / m_increment;
+                // allocation in RT context, sorry! but this happens only
+                // the first time through
+                int filterlen = (m_filtersecs * m_sampleRate) / m_increment;
                 m_medians[i] = new MedianFilter<double>(filterlen);
             }
 
             m_medians[i]->push(mags[i]);
             double threshold = m_medians[i]->getAt(m_reduction);
 
-			*/
-			double threshold = 0.0;
-			if (mags[i] > threshold && mags[i] > 0.0) {
+            if (ix++ == 2) {
+                std::cerr << "threshold = " << threshold << std::endl;
+            }
+
+            if (mags[i] > threshold && mags[i] > 0.0) {
                 double target = mags[i] - threshold;
-                ratios[i] = (target / mags[i]);
+                double ratio = (target / mags[i]);
+                m_real[i] *= ratio;
+                m_imag[i] *= ratio;
             } else {
-                ratios[i] = 0.0;
+                m_real[i] = 0.0;
+                m_imag[i] = 0.0;
             }
         }
     }
-
-    for (int i = 0; i < hs; ++i) {
-        m_real[i] *= ratios[i];
-        m_imag[i] *= ratios[i];
-    }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fft.cpp	Sat Jun 12 13:08:33 2010 +0100
@@ -0,0 +1,131 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+#ifdef VST
+#include "devuvuzelator-vst.h"
+#else
+#ifdef LADSPA
+#include "devuvuzelator-ladspa.h"
+#else
+#error Need to define either VST or LADSPA
+#endif
+#endif
+
+// FFT implementation by Don Cross, public domain.
+// This version scales the forward transform.
+
+void Devuvuzelator::fft(unsigned int n, bool inverse,
+                        double *ri, double *ii, double *ro, double *io)
+{
+    if (!ri || !ro || !io) return;
+
+    unsigned int bits;
+    unsigned int i, j, k, m;
+    unsigned int blockSize, blockEnd;
+
+    double tr, ti;
+
+    if (n < 2) return;
+    if (n & (n-1)) return;
+
+    double angle = 2.0 * M_PI;
+    if (inverse) angle = -angle;
+
+    for (i = 0; ; ++i) {
+	if (n & (1 << i)) {
+	    bits = i;
+	    break;
+	}
+    }
+
+    static unsigned int tableSize = 0;
+    static int *table = 0;
+
+    if (tableSize != n) {
+
+	delete[] table;
+
+	table = new int[n];
+
+	for (i = 0; i < n; ++i) {
+	
+	    m = i;
+
+	    for (j = k = 0; j < bits; ++j) {
+		k = (k << 1) | (m & 1);
+		m >>= 1;
+	    }
+
+	    table[i] = k;
+	}
+
+	tableSize = n;
+    }
+
+    if (ii) {
+	for (i = 0; i < n; ++i) {
+	    ro[table[i]] = ri[i];
+	    io[table[i]] = ii[i];
+	}
+    } else {
+	for (i = 0; i < n; ++i) {
+	    ro[table[i]] = ri[i];
+	    io[table[i]] = 0.0;
+	}
+    }
+
+    blockEnd = 1;
+
+    for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
+
+	double delta = angle / (double)blockSize;
+	double sm2 = -sin(-2 * delta);
+	double sm1 = -sin(-delta);
+	double cm2 = cos(-2 * delta);
+	double cm1 = cos(-delta);
+	double w = 2 * cm1;
+	double ar[3], ai[3];
+
+	for (i = 0; i < n; i += blockSize) {
+
+	    ar[2] = cm2;
+	    ar[1] = cm1;
+
+	    ai[2] = sm2;
+	    ai[1] = sm1;
+
+	    for (j = i, m = 0; m < blockEnd; j++, m++) {
+
+		ar[0] = w * ar[1] - ar[2];
+		ar[2] = ar[1];
+		ar[1] = ar[0];
+
+		ai[0] = w * ai[1] - ai[2];
+		ai[2] = ai[1];
+		ai[1] = ai[0];
+
+		k = j + blockEnd;
+		tr = ar[0] * ro[k] - ai[0] * io[k];
+		ti = ar[0] * io[k] + ai[0] * ro[k];
+
+		ro[k] = ro[j] - tr;
+		io[k] = io[j] - ti;
+
+		ro[j] += tr;
+		io[j] += ti;
+	    }
+	}
+
+	blockEnd = blockSize;
+    }
+
+    if (!inverse) {
+
+	double denom = (double)n;
+
+	for (i = 0; i < n; i++) {
+	    ro[i] /= denom;
+	    io[i] /= denom;
+	}
+    }
+}
+
--- a/median.h	Fri Jun 11 20:20:20 2010 +0100
+++ b/median.h	Sat Jun 12 13:08:33 2010 +0100
@@ -5,6 +5,8 @@
 
 #include <algorithm>
 #include <cassert>
+#include <cmath>
+#include <iostream>
 
 template <typename T>
 class MedianFilter
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/params.h	Sat Jun 12 13:08:33 2010 +0100
@@ -0,0 +1,9 @@
+
+#ifndef _PARAMS_H_
+#define _PARAMS_H_
+
+#define FFTSIZE 2048
+#define WINSIZE 1024
+#define FILTERSECS 4.0
+
+#endif