changeset 0:31d2a7e07786

Moved all to folder "tempogram".
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Mon, 07 Jul 2014 10:08:14 +0100
parents
children 3fd1a41b089b
files FIRFilter.cpp FIRFilter.h Makefile Tempogram.cpp Tempogram.h WindowFunction.cpp WindowFunction.h plugins.cpp
diffstat 8 files changed, 797 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FIRFilter.cpp	Mon Jul 07 10:08:14 2014 +0100
@@ -0,0 +1,115 @@
+//
+//  FIRFilter.cpp
+//  Tempogram
+//
+//  Created by Carl Bussey on 25/06/2014.
+//  Copyright (c) 2014 Carl Bussey. All rights reserved.
+//
+
+#include "FIRFilter.h"
+#include <cmath>
+#include <vamp-sdk/FFT.h>
+#include <assert.h>
+#include <iostream>
+using namespace std;
+
+using Vamp::FFT;
+
+FIRFilter::FIRFilter(const unsigned int lengthInput, const unsigned int numberOfCoefficients) :
+    _lengthInput(lengthInput),
+    _numberOfCoefficients(numberOfCoefficients),
+    fftInput(NULL),
+    fftCoefficients(NULL),
+    fftReal1(NULL),
+    fftImag1(NULL),
+    fftReal2(NULL),
+    fftImag2(NULL),
+    fftFilteredReal(NULL),
+    fftFilteredImag(NULL),
+    fftOutputReal(NULL),
+    fftOutputImag(NULL)
+{
+    initialise();
+}
+
+FIRFilter::~FIRFilter()
+{
+    cleanup();
+}
+
+void
+FIRFilter::initialise()
+{
+    _lengthFIRFFT = pow(2,(ceil(log2(_lengthInput+_numberOfCoefficients-1))));
+    
+    fftInput = new double[_lengthFIRFFT];
+    fftCoefficients = new double[_lengthFIRFFT];
+    fftReal1 = new double[_lengthFIRFFT];
+    fftImag1 = new double[_lengthFIRFFT];
+    fftReal2 = new double[_lengthFIRFFT];
+    fftImag2 = new double[_lengthFIRFFT];
+    fftFilteredReal = new double[_lengthFIRFFT];
+    fftFilteredImag = new double[_lengthFIRFFT];
+    fftOutputReal = new double[_lengthFIRFFT];
+    fftOutputImag = new double[_lengthFIRFFT];
+    
+    for(int i = 0; i < _lengthFIRFFT; i++){
+        fftInput[i] = fftCoefficients[i] = fftReal1[i] = fftImag1[i] = fftReal2[i] = fftImag2[i] = fftFilteredReal[i] = fftFilteredImag[i] = fftOutputReal[i] = fftOutputImag[i] = 0.0;
+    }
+}
+
+void
+FIRFilter::process(const float* input, const float* coefficients, float* output)
+{
+    float max = 0;
+    for(int i = 0; i < _lengthInput; i++){
+        fftInput[i] = input[i];
+        max = max > fftInput[i] ? max : fftInput[i];
+        //cout << fftInput[i] << endl;
+    }
+    //cout << max << endl;
+    for(int i = 0; i < _numberOfCoefficients; i++){
+        fftCoefficients[i] = coefficients[i];
+        //cout << fftCoefficients[i] << endl;
+    }
+    
+    FFT::forward(_lengthFIRFFT, fftInput, NULL, fftReal1, fftImag1);
+    FFT::forward(_lengthFIRFFT, fftCoefficients, NULL, fftReal2, fftImag2);
+    for (int i = 0; i < _lengthFIRFFT; i++){
+        fftFilteredReal[i] = (fftReal1[i] * fftReal2[i]) - (fftImag1[i] * fftImag2[i]);
+        fftFilteredImag[i] = (fftReal1[i] * fftImag2[i]) + (fftReal2[i] * fftImag1[i]);
+    }
+    FFT::inverse(_lengthFIRFFT, fftFilteredReal, fftFilteredImag, fftOutputReal, fftOutputImag);
+    
+    max = 0;
+    for(int i = 0; i < _lengthInput; i++){
+        output[i] = fftOutputReal[i];
+        max = max > output[i] ? max : output[i];
+    }
+    //cout << max << endl;
+}
+
+void
+FIRFilter::cleanup()
+{
+    delete []fftInput;
+    fftInput = NULL;
+    delete []fftCoefficients;
+    fftCoefficients = NULL;
+    delete []fftReal1;
+    fftReal1 = NULL;
+    delete []fftImag1;
+    fftImag1 = NULL;
+    delete []fftReal2;
+    fftReal2 = NULL;
+    delete []fftImag2;
+    fftImag2 = NULL;
+    delete []fftFilteredReal;
+    fftFilteredReal = NULL;
+    delete []fftFilteredImag;
+    fftFilteredImag = NULL;
+    delete []fftOutputReal;
+    fftOutputReal = NULL;
+    delete []fftOutputImag;
+    fftOutputImag = NULL;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FIRFilter.h	Mon Jul 07 10:08:14 2014 +0100
@@ -0,0 +1,37 @@
+//
+//  FIRFilter.h
+//  Tempogram
+//
+//  Created by Carl Bussey on 25/06/2014.
+//  Copyright (c) 2014 Carl Bussey. All rights reserved.
+//
+
+#ifndef __Tempogram__FIRFilter__
+#define __Tempogram__FIRFilter__
+
+class FIRFilter{
+public:
+    FIRFilter(const unsigned int lengthInput, const unsigned int numberOfCoefficients);
+    ~FIRFilter();
+    void process(const float *input, const float *coefficients, float *output);
+private:
+    unsigned int _lengthInput;
+    unsigned int _numberOfCoefficients;
+    unsigned int _lengthFIRFFT;
+    
+    double *fftInput;
+    double *fftCoefficients;
+    double *fftReal1;
+    double *fftImag1;
+    double *fftReal2;
+    double *fftImag2;
+    double *fftFilteredReal;
+    double *fftFilteredImag;
+    double *fftOutputReal;
+    double *fftOutputImag;
+    
+    void initialise();
+    void cleanup();
+};
+
+#endif /* defined(__Tempogram__FIRFilter__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Mon Jul 07 10:08:14 2014 +0100
@@ -0,0 +1,101 @@
+
+##  Skeleton Makefile for Vamp plugin builds using command-line tools.
+##  This requires GNU make, which is what you get with OS/X, Linux, or
+##  MinGW/Cygwin on Windows.
+##
+##  Rename this to Makefile, and edit as appropriate.
+##  This Makefile WILL NOT WORK until you have edited it as described
+##  below -- the Makefile as supplied does nothing useful at all!
+##
+##  Various sets of options are provided, commented out -- just uncomment
+##  (remove the '#' characters for) the set that most closely resembles
+##  your own situation, and adjust to taste.  Then run "gmake".
+##
+##  (For Windows builds using MS Visual Studio, start instead with the
+##  VampExamplePlugins project found in the build directory of the SDK.)
+
+
+# Edit this to the base name of your plugin library
+#
+PLUGIN_LIBRARY_NAME := tempogram
+
+# Edit this to list the .cpp or .c files in your plugin project
+#
+PLUGIN_SOURCES := Tempogram.cpp FIRFilter.cpp WindowFunction.cpp plugins.cpp
+
+# Edit this to list the .h files in your plugin project
+#
+PLUGIN_HEADERS := Tempogram.h FIRFilter.h WindowFunction.h
+
+# Edit this to the location of the Vamp plugin SDK, relative to your
+# project directory
+#
+VAMP_SDK_DIR := /usr/local/bin
+
+
+## Uncomment these for an OS/X universal binary (32- and 64-bit Intel)
+## supporting 10.5 or newer. Use this if you have OS/X 10.7 with the
+## Xcode 4 command-line tools.
+
+CXX := g++
+CXXFLAGS := -mmacosx-version-min=10.5 -arch x86_64 -I$(VAMP_SDK_DIR) -Wall -fPIC
+PLUGIN_EXT := .dylib
+LDFLAGS := $(CXXFLAGS) -dynamiclib -install_name $(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT) /usr/local/lib/libvamp-sdk.a -exported_symbols_list vamp-plugin.list
+
+
+## Uncomment these for an OS/X universal binary (PPC and 32- and
+## 64-bit Intel) supporting 10.5 or newer. Use this if you have OS/X
+## 10.6 with the Xcode 3 command-line tools.
+
+# CXXFLAGS := -isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 -arch i386 -arch x86_64 -arch ppc -I$(VAMP_SDK_DIR) -Wall -fPIC
+# PLUGIN_EXT := .dylib
+# LDFLAGS := $(CXXFLAGS) -dynamiclib -install_name $(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT) $(VAMP_SDK_DIR)/libvamp-sdk.a -exported_symbols_list vamp-plugin.list
+
+
+## Uncomment these for an OS/X universal binary (PPC and 32- and
+## 64-bit Intel) supporting 10.4 or newer. Use this if you have OS/X
+## 10.4, 10.5 or 10.6 and you have the 10.4 SDK installed.
+
+# CXX := g++-4.0
+# CXXFLAGS := -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -arch i386 -arch x86_64 -arch ppc -I$(VAMP_SDK_DIR) -Wall -fPIC
+# PLUGIN_EXT := .dylib
+# LDFLAGS := $(CXXFLAGS) -dynamiclib -install_name $(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT) $(VAMP_SDK_DIR)/libvamp-sdk.a -exported_symbols_list vamp-plugin.list
+
+
+##  Uncomment these for Linux using the standard tools:
+
+# CXXFLAGS := -I$(VAMP_SDK_DIR) -Wall -fPIC
+# PLUGIN_EXT := .so
+# LDFLAGS := -shared -Wl,-soname=$(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT) $(VAMP_SDK_DIR)/libvamp-sdk.a -Wl,--version-script=vamp-plugin.map
+
+
+##  Uncomment these for a cross-compile from Linux to Windows using MinGW:
+
+# CXX := i586-mingw32msvc-g++
+# CXXFLAGS := -I$(VAMP_SDK_DIR) -Wall 
+# PLUGIN_EXT := .dll
+# LDFLAGS := --static-libgcc -Wl,-soname=$(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT) -shared $(VAMP_SDK_DIR)/libvamp-sdk.a
+
+
+##  Uncomment these for OpenSolaris using SunStudio compiler and GNU make:
+
+# CXX := CC
+# CXXFLAGS := -G -I$(VAMP_SDK_DIR) +w -KPIC
+# PLUGIN_EXT := .so
+# LDFLAGS := -G -h$(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT) $(VAMP_SDK_DIR)/libvamp-sdk.a -Qoption ld -Mvamp-plugin.map
+
+
+
+##  All of the above
+
+PLUGIN_OBJECTS := $(PLUGIN_SOURCES:.cpp=.o)
+PLUGIN_OBJECTS := $(PLUGIN_OBJECTS:.c=.o)
+
+$(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT): $(PLUGIN_OBJECTS)
+	   $(CXX) -o $@ $^ $(LDFLAGS)
+
+$(PLUGIN_OBJECTS): $(PLUGIN_HEADERS)
+
+clean:
+	rm -f *.o *.dylib
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tempogram.cpp	Mon Jul 07 10:08:14 2014 +0100
@@ -0,0 +1,382 @@
+
+// This is a skeleton file for use in creating your own plugin
+// libraries.  Replace MyPlugin and myPlugin throughout with the name
+// of your first plugin class, and fill in the gaps as appropriate.
+
+
+#include "Tempogram.h"
+#include "FIRFilter.h"
+#include "WindowFunction.h"
+#include <vamp-sdk/FFT.h>
+#include <cmath>
+#include <fstream>
+#include <assert.h>
+using Vamp::FFT;
+using namespace std;
+
+Tempogram::Tempogram(float inputSampleRate) :
+    Plugin(inputSampleRate),
+    m_blockSize(0),
+    compressionConstant(1000), //make param
+    previousY(NULL),
+    currentY(NULL),
+    tN(1024), //make param
+    thopSize(512), //make param
+    fftInput(NULL),
+    fftOutputReal(NULL),
+    fftOutputImag(NULL),
+    ncLength(0)
+
+    // Also be sure to set your plugin parameters (presumably stored
+    // in member variables) to their default values here -- the host
+    // will not do that for you
+{
+}
+
+Tempogram::~Tempogram()
+{
+    //delete stuff
+}
+
+string
+Tempogram::getIdentifier() const
+{
+    return "tempogram";
+}
+
+string
+Tempogram::getName() const
+{
+    return "Tempogram";
+}
+
+string
+Tempogram::getDescription() const
+{
+    // Return something helpful here!
+    return "Cyclic Tempogram as described by Peter Grosche and Meinard Muller";
+}
+
+string
+Tempogram::getMaker() const
+{
+    //Your name here
+    return "Carl Bussey";
+}
+
+int
+Tempogram::getPluginVersion() const
+{
+    // Increment this each time you release a version that behaves
+    // differently from the previous one
+    return 1;
+}
+
+string
+Tempogram::getCopyright() const
+{
+    // This function is not ideally named.  It does not necessarily
+    // need to say who made the plugin -- getMaker does that -- but it
+    // should indicate the terms under which it is distributed.  For
+    // example, "Copyright (year). All Rights Reserved", or "GPL"
+    return "";
+}
+
+Tempogram::InputDomain
+Tempogram::getInputDomain() const
+{
+    return FrequencyDomain;
+}
+
+size_t
+Tempogram::getPreferredBlockSize() const
+{
+    return 0; // 0 means "I can handle any block size"
+}
+
+size_t 
+Tempogram::getPreferredStepSize() const
+{
+    //23 ms?
+    return 0; // 0 means "anything sensible"; in practice this
+              // means the same as the block size for TimeDomain
+              // plugins, or half of it for FrequencyDomain plugins
+}
+
+size_t
+Tempogram::getMinChannelCount() const
+{
+    return 1;
+}
+
+size_t
+Tempogram::getMaxChannelCount() const
+{
+    return 1;
+}
+
+Tempogram::ParameterList
+Tempogram::getParameterDescriptors() const
+{
+    ParameterList list;
+
+    // If the plugin has no adjustable parameters, return an empty
+    // list here (and there's no need to provide implementations of
+    // getParameter and setParameter in that case either).
+
+    // Note that it is your responsibility to make sure the parameters
+    // start off having their default values (e.g. in the constructor
+    // above).  The host needs to know the default value so it can do
+    // things like provide a "reset to default" function, but it will
+    // not explicitly set your parameters to their defaults for you if
+    // they have not changed in the mean time.
+
+    ParameterDescriptor C;
+    C.identifier = "C";
+    C.name = "C";
+    C.description = "Spectrogram compression constant, C";
+    C.unit = "";
+    C.minValue = 2;
+    C.maxValue = 10000;
+    C.defaultValue = 1000;
+    C.isQuantized = false;
+    list.push_back(C);
+    
+    ParameterDescriptor tN;
+    tN.identifier = "tN";
+    tN.name = "Tempogram FFT length";
+    tN.description = "Tempogram FFT length.";
+    tN.unit = "";
+    tN.minValue = 128;
+    tN.maxValue = 4096;
+    tN.defaultValue = 1024;
+    tN.isQuantized = true;
+    tN.quantizeStep = 128;
+    list.push_back(tN);
+
+    return list;
+}
+
+float
+Tempogram::getParameter(string identifier) const
+{
+    if (identifier == "C") {
+        return compressionConstant; // return the ACTUAL current value of your parameter here!
+    }
+    if (identifier == "tN"){
+        return tN;
+    }
+    
+    return 0;
+}
+
+void
+Tempogram::setParameter(string identifier, float value) 
+{
+    if (identifier == "C") {
+        compressionConstant = value;// set the actual value of your parameter
+    }
+    if (identifier == "tN") {
+        tN = value;
+    }
+}
+
+Tempogram::ProgramList
+Tempogram::getPrograms() const
+{
+    ProgramList list;
+
+    // If you have no programs, return an empty list (or simply don't
+    // implement this function or getCurrentProgram/selectProgram)
+
+    return list;
+}
+
+string
+Tempogram::getCurrentProgram() const
+{
+    return ""; // no programs
+}
+
+void
+Tempogram::selectProgram(string name)
+{
+}
+
+Tempogram::OutputList
+Tempogram::getOutputDescriptors() const
+{
+    OutputList list;
+
+    // See OutputDescriptor documentation for the possibilities here.
+    // Every plugin must have at least one output.
+
+    OutputDescriptor d;
+    d.identifier = "output";
+    d.name = "Cyclic Tempogram";
+    d.description = "Cyclic Tempogram";
+    d.unit = "";
+    d.hasFixedBinCount = false;
+    //d.binCount = 1;
+    d.hasKnownExtents = false;
+    d.isQuantized = false;
+    d.sampleType = OutputDescriptor::VariableSampleRate;
+    d.sampleRate = 0.0;
+    d.hasDuration = false;
+    list.push_back(d);
+
+    return list;
+}
+
+bool
+Tempogram::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    if (channels < getMinChannelCount() ||
+	channels > getMaxChannelCount()) return false;
+
+    // Real initialisation work goes here!
+    m_blockSize = blockSize;
+    currentY = new float[m_blockSize];
+    previousY = new float[m_blockSize];
+    
+    return true;
+}
+
+void
+Tempogram::reset()
+{
+    // Clear buffers, reset stored values, etc
+}
+
+Tempogram::FeatureSet
+Tempogram::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
+{
+    size_t n = m_blockSize/2 + 1;
+    
+    FeatureSet featureSet;
+    Feature feature;
+    feature.hasTimestamp = false;
+    
+    const float *in = inputBuffers[0];
+    
+    //Calculate log magnitude
+    float sum = 0;
+    for (int i = 0; i < n; i++){
+        float magnitude = sqrt(in[2*i] * in[2*i] + in[2*i + 1] * in[2*i + 1]);
+        currentY[i] = log(1+compressionConstant*magnitude); //should be 1+C*magnitude
+        if(currentY[i] >= previousY[i]){
+            sum += (currentY[i] - previousY[i]);
+        }
+    }
+    
+    noveltyCurve.push_back(sum);
+    
+    float *tmpY = currentY;
+    currentY = previousY;
+    previousY = tmpY;
+    
+    ncTimestamps.push_back(timestamp);
+    
+    return FeatureSet();
+}
+
+void
+Tempogram::initialiseForGRF(){
+    hannN = 129;
+    hannWindow = new float[hannN];
+    hannWindowtN = new float[tN];
+    fftInput = new double[tN];
+    fftOutputReal = new double[tN];
+    fftOutputImag = new double[tN];
+    ncLength = noveltyCurve.size();
+    
+    WindowFunction::hanning(hannWindow, hannN, true);
+}
+
+void
+Tempogram::cleanupForGRF(){
+    delete []hannWindow;
+    hannWindow = NULL;
+    delete []hannWindowtN;
+    hannWindowtN = NULL;
+    delete []fftInput;
+    fftInput = NULL;
+    delete []fftOutputReal;
+    fftOutputReal = NULL;
+    delete []fftOutputImag;
+    fftOutputImag = NULL;
+}
+
+Tempogram::FeatureSet
+Tempogram::getRemainingFeatures()
+{
+    //Make sure this is called at the beginning of the function
+    initialiseForGRF();
+    
+    vector<float> noveltyCurveLocalAverage(ncLength);
+    
+    FIRFilter *filter = new FIRFilter(ncLength, hannN);
+    filter->process(&noveltyCurve[0], hannWindow, &noveltyCurveLocalAverage[0]);
+    delete filter;
+    
+    for(int i = 0; i < ncLength; i++){
+        noveltyCurve[i] -= noveltyCurveLocalAverage[i];
+        noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0;
+    }
+    
+    int i=0;
+    WindowFunction::hanning(hannWindowtN, tN);
+    
+    int index;
+    int start = floor(tN/2 + 0.5);
+    int timestampInc = floor((((float)ncTimestamps[1].nsec - ncTimestamps[0].nsec)/1e9)*(thopSize) + 0.5);
+    //cout << timestampInc << endl;
+    
+    FeatureSet featureSet;
+    
+    while(i < ncLength){
+        Feature feature;
+        Vamp::RealTime timestamp;
+        
+        for (int n = start; n < tN; n++){
+            index = i + n - tN/2;
+            assert (index >= 0);
+            
+            if(index < ncLength){
+                fftInput[n] = noveltyCurve[i + n] * hannWindowtN[n];
+            }
+            else if(index >= ncLength){
+                fftInput[n] = 0.0; //pad the end with zeros
+            }
+            //cout << fftInput[n] << endl;
+        }
+        if (i+tN/2 > ncLength){
+            timestamp = Vamp::RealTime::fromSeconds(ncTimestamps[i].sec + timestampInc);
+        }
+        else{
+            timestamp = ncTimestamps[i + tN/2];
+        }
+        
+        FFT::forward(tN, fftInput, NULL, fftOutputReal, fftOutputImag);
+        
+        //TODO: sample at logarithmic spacing
+        for(int k = 0; k < tN; k++){
+            double fftOutputPower = (fftOutputReal[k]*fftOutputReal[k] + fftOutputImag[k]*fftOutputImag[k]); //Magnitude or power?
+            assert (!isinf(fftOutputPower));
+            
+            feature.values.push_back(fftOutputPower);
+        }
+
+        i += thopSize;
+        start = 0;
+        
+        feature.timestamp = timestamp;
+        feature.hasTimestamp = true;
+        featureSet[0].push_back(feature);
+    }
+    
+    //Make sure this is called at the end of the function
+    cleanupForGRF();
+    
+    return featureSet;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tempogram.h	Mon Jul 07 10:08:14 2014 +0100
@@ -0,0 +1,78 @@
+
+// This is a skeleton file for use in creating your own plugin
+// libraries.  Replace MyPlugin and myPlugin throughout with the name
+// of your first plugin class, and fill in the gaps as appropriate.
+
+
+// Remember to use a different guard symbol in each header!
+#ifndef _TEMPOGRAM_H_
+#define _TEMPOGRAM_H_
+
+#include <vamp-sdk/Plugin.h>
+
+using std::string;
+using std::vector;
+
+class Tempogram : public Vamp::Plugin
+{
+public:
+    Tempogram(float inputSampleRate);
+    virtual ~Tempogram();
+
+    string getIdentifier() const;
+    string getName() const;
+    string getDescription() const;
+    string getMaker() const;
+    int getPluginVersion() const;
+    string getCopyright() const;
+
+    InputDomain getInputDomain() const;
+    size_t getPreferredBlockSize() const;
+    size_t getPreferredStepSize() const;
+    size_t getMinChannelCount() const;
+    size_t getMaxChannelCount() const;
+
+    ParameterList getParameterDescriptors() const;
+    float getParameter(string identifier) const;
+    void setParameter(string identifier, float value);
+
+    ProgramList getPrograms() const;
+    string getCurrentProgram() const;
+    void selectProgram(string name);
+
+    OutputList getOutputDescriptors() const;
+
+    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+    void initialiseForGRF();
+    void cleanupForGRF();
+    void reset();
+
+    FeatureSet process(const float *const *inputBuffers,
+                       Vamp::RealTime timestamp);
+
+    FeatureSet getRemainingFeatures();
+
+protected:
+    // plugin-specific data and methods go here
+    size_t m_blockSize;
+    float compressionConstant;
+    float *previousY;
+    float *currentY;
+    vector<float> noveltyCurve;
+    
+    unsigned int tN;
+    unsigned int thopSize;
+    double * fftInput;
+    double * fftOutputReal;
+    double * fftOutputImag;
+    
+    int ncLength;
+    int hannN;
+    float *hannWindow;
+    float *hannWindowtN;
+    
+    vector<Vamp::RealTime> ncTimestamps;
+};
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WindowFunction.cpp	Mon Jul 07 10:08:14 2014 +0100
@@ -0,0 +1,28 @@
+//
+//  WindowFunction.cpp
+//  Tempogram
+//
+//  Created by Carl Bussey on 26/06/2014.
+//  Copyright (c) 2014 Carl Bussey. All rights reserved.
+//
+
+#include "WindowFunction.h"
+#include <cmath>
+#include <vector>
+#include <iostream>
+using std::vector;
+
+void
+WindowFunction::hanning(float *signal, const unsigned int N, const bool normalise){
+    
+    float sum = 0;
+    for(int i = 0; i < N; i++){
+        signal[i] = 0.5*(1-cos((float)2*M_PI*i/N));
+        sum += signal[i];
+    }
+    if (normalise){
+        for(int i = 0; i < N; i++){
+            signal[i] /= sum;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WindowFunction.h	Mon Jul 07 10:08:14 2014 +0100
@@ -0,0 +1,19 @@
+//
+//  WindowFunction.h
+//  Tempogram
+//
+//  Created by Carl Bussey on 26/06/2014.
+//  Copyright (c) 2014 Carl Bussey. All rights reserved.
+//
+
+#ifndef __Tempogram__WindowFunction__
+#define __Tempogram__WindowFunction__
+
+#include <iostream>
+
+class WindowFunction{
+public:
+    static void hanning(float *signal, const unsigned int N, const bool normalise = false);
+};
+
+#endif /* defined(__Tempogram__WindowFunction__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins.cpp	Mon Jul 07 10:08:14 2014 +0100
@@ -0,0 +1,37 @@
+
+// This is a skeleton file for use in creating your own plugin
+// libraries.  Replace MyPlugin and myPlugin throughout with the name
+// of your first plugin class, and fill in the gaps as appropriate.
+
+
+#include <vamp/vamp.h>
+#include <vamp-sdk/PluginAdapter.h>
+
+#include "Tempogram.h"
+
+
+// Declare one static adapter here for each plugin class in this library.
+
+static Vamp::PluginAdapter<Tempogram> myPluginAdapter;
+
+
+// This is the entry-point for the library, and the only function that
+// needs to be publicly exported.
+
+const VampPluginDescriptor *
+vampGetPluginDescriptor(unsigned int version, unsigned int index)
+{
+    if (version < 1) return 0;
+
+    // Return a different plugin adaptor's descriptor for each index,
+    // and return 0 for the first index after you run out of plugins.
+    // (That's how the host finds out how many plugins are in this
+    // library.)
+
+    switch (index) {
+    case  0: return myPluginAdapter.getDescriptor();
+    default: return 0;
+    }
+}
+
+