Mercurial > hg > qm-vamp-plugins
view plugins/AdaptiveSpectrogram.h @ 104:d8ad747eb907
* first crack at threading cut code
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Tue, 12 May 2009 17:57:41 +0000 |
parents | ef22bed1626a |
children | abbc482aaad2 |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* QM Vamp Plugin Set Centre for Digital Music, Queen Mary, University of London. All rights reserved. */ #ifndef _ADAPTIVE_SPECTROGRAM_H_ #define _ADAPTIVE_SPECTROGRAM_H_ #include <vamp-sdk/Plugin.h> #include <cmath> #include <vector> #include "thread/Thread.h" class AdaptiveSpectrogram : public Vamp::Plugin { public: AdaptiveSpectrogram(float inputSampleRate); virtual ~AdaptiveSpectrogram(); bool initialise(size_t channels, size_t stepSize, size_t blockSize); void reset(); InputDomain getInputDomain() const { return TimeDomain; } std::string getIdentifier() const; std::string getName() const; std::string getDescription() const; std::string getMaker() const; int getPluginVersion() const; std::string getCopyright() const; size_t getPreferredStepSize() const; size_t getPreferredBlockSize() const; ParameterList getParameterDescriptors() const; float getParameter(std::string id) const; void setParameter(std::string id, float value); OutputList getOutputDescriptors() const; FeatureSet process(const float *const *inputBuffers, Vamp::RealTime timestamp); FeatureSet getRemainingFeatures(); protected: int m_w; int m_n; struct Spectrogram { int resolution; int width; double **data; Spectrogram(int r, int w) : resolution(r), width(w) { data = new double *[width]; for (int i = 0; i < width; ++i) data[i] = new double[resolution]; } ~Spectrogram() { for (int i = 0; i < width; ++i) delete[] data[i]; delete[] data; } }; struct Spectrograms { int minres; int maxres; int n; Spectrogram **spectrograms; Spectrograms(int mn, int mx, int widthofmax) : minres(mn), maxres(mx) { n = log2(maxres/minres) + 1; spectrograms = new Spectrogram *[n]; int r = mn; for (int i = 0; i < n; ++i) { spectrograms[i] = new Spectrogram(r, widthofmax * (mx / r)); r = r * 2; } } ~Spectrograms() { for (int i = 0; i < n; ++i) { delete spectrograms[i]; } delete[] spectrograms; } }; struct Cutting { enum Cut { Horizontal, Vertical, Finished }; Cut cut; Cutting *first; Cutting *second; double cost; double value; ~Cutting() { delete first; delete second; } }; class CutThread : public Thread { public: CutThread(const AdaptiveSpectrogram *as) : m_as(as), // m_busy(false), // m_computed(false), m_result(0), m_workToDoC("CutThread: work to do"), m_workToDo(false), m_workDoneC("CutThread: work done"), m_workDone(false), m_finishing(false) { } ~CutThread() { } void cut(const Spectrograms &s, int res, int x, int y, int h) { m_workToDoC.lock(); // std::cerr << "locked in main thread" << std::endl; m_s = &s; m_res = res; m_x = x; m_y = y; m_h = h; // m_busy = true; // m_computed = false; m_workToDo = true; m_workDone = false; m_workToDoC.signal(); m_workDoneC.lock(); m_workToDoC.unlock(); } Cutting *get() { // std::cerr << "about to wait within main thread" << std::endl; // m_workDoneC must be locked from prior call to cut() while (!m_workDone) m_workDoneC.wait(); // std::cerr << "waited within main thread" << std::endl; // m_workDoneC.lock(); // while (!m_computed) { // std::cerr << "waiting within main thread" << std::endl; // m_condition.wait(); // } Cutting *c = m_result; m_result = 0; m_workDoneC.unlock(); return c; } /* bool busy() { return m_busy; } */ void finish() { m_finishing = true; m_workToDoC.signal(); } protected: virtual void run() { m_workToDoC.lock(); // std::cerr << "locked within run function" << std::endl; while (!m_finishing) { // if (!m_busy) { // std::cerr << "waiting within run function" << std::endl; // m_condition.wait(); // } while (!m_workToDo && !m_finishing) m_workToDoC.wait(); // std::cerr << "waited within run function" << std::endl; if (m_finishing) { break; } if (m_workToDo) { // std::cerr << "cut thread " << this << ": calling cut" << std::endl; m_result = m_as->cut(*m_s, m_res, m_x, m_y, m_h); // std::cerr << "cut returning" << std::endl; // m_computed = true; // m_busy = false; m_workToDo = false; m_workDone = true; // std::cerr << "signalling completion from run function" << std::endl; m_workDoneC.signal(); } } m_workToDoC.unlock(); } const AdaptiveSpectrogram *m_as; const Spectrograms *m_s; int m_res; int m_x; int m_y; int m_h; // bool m_busy; // bool m_computed; Cutting *m_result; Condition m_workToDoC; bool m_workToDo; Condition m_workDoneC; bool m_workDone; bool m_finishing; }; mutable std::vector<CutThread *> m_cutThreads;//!!! mutable blargh ///!!! Mutex m_threadMutex; mutable bool m_first; //!!! gross double xlogx(double x) const { if (x == 0.0) return 0.0; else return x * log(x); } double cost(const Spectrogram &s, int x, int y) const { return xlogx(s.data[x][y]); } double value(const Spectrogram &s, int x, int y) const { return s.data[x][y]; } Cutting *cut(const Spectrograms &, int res, int x, int y, int h) const; void getSubCuts(const Spectrograms &, int res, int x, int y, int h, Cutting *&top, Cutting *&bottom, Cutting *&left, Cutting *&right) const; void printCutting(Cutting *, std::string) const; void assemble(const Spectrograms &, const Cutting *, std::vector<std::vector<float> > &, int x, int y, int w, int h) const; }; #endif