Mercurial > hg > qm-vamp-plugins
changeset 109:0dd97d053053
* tidy, make threading a parameter, fix offset error in fft input
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Wed, 13 May 2009 17:41:41 +0000 |
parents | 42e4f785a636 |
children | be419e04899a |
files | plugins/AdaptiveSpectrogram.cpp plugins/AdaptiveSpectrogram.h |
diffstat | 2 files changed, 53 insertions(+), 56 deletions(-) [+] |
line wrap: on
line diff
--- a/plugins/AdaptiveSpectrogram.cpp Wed May 13 13:32:43 2009 +0000 +++ b/plugins/AdaptiveSpectrogram.cpp Wed May 13 17:41:41 2009 +0000 @@ -25,13 +25,12 @@ //#define DEBUG_VERBOSE 1 -static const int cutThreadCount = 4; - AdaptiveSpectrogram::AdaptiveSpectrogram(float inputSampleRate) : Plugin(inputSampleRate), m_w(8), m_n(3), - m_first(true) + m_threaded(true), + m_threadsInUse(false) { } @@ -155,6 +154,18 @@ desc2.valueNames.push_back("16384"); list.push_back(desc2); + ParameterDescriptor desc3; + desc3.identifier = "threaded"; + desc3.name = "Multi-threaded processing"; + desc3.description = "Perform calculations in several threads in parallel"; + desc3.unit = ""; + desc3.minValue = 0; + desc3.maxValue = 1; + desc3.defaultValue = 1; + desc3.isQuantized = true; + desc3.quantizeStep = 1; + list.push_back(desc3); + return list; } @@ -163,6 +174,7 @@ { if (id == "n") return m_n+1; else if (id == "w") return m_w+1; + else if (id == "threaded") return (m_threaded ? 1 : 0); return 0.f; } @@ -175,7 +187,9 @@ } else if (id == "w") { int w = lrintf(value); if (w >= 1 && w <= 14) m_w = w-1; - } + } else if (id == "threaded") { + m_threaded = (value > 0.5); + } } AdaptiveSpectrogram::OutputList @@ -228,18 +242,25 @@ if (m_fftThreads.find(w) == m_fftThreads.end()) { m_fftThreads[w] = new FFTThread(w); } - m_fftThreads[w]->calculate(inputBuffers[0], s, index, maxwid); + if (m_threaded) { + m_fftThreads[w]->startCalculation(inputBuffers[0], s, index, maxwid); + } else { + m_fftThreads[w]->setParameters(inputBuffers[0], s, index, maxwid); + m_fftThreads[w]->performTask(); + } w *= 2; ++index; } - w = minwid; - while (w <= maxwid) { - m_fftThreads[w]->await(); - w *= 2; + if (m_threaded) { + w = minwid; + while (w <= maxwid) { + m_fftThreads[w]->await(); + w *= 2; + } } - m_first = true;//!!! + m_threadsInUse = false; Cutting *cutting = cut(s, maxwid/2, 0, 0, maxwid/2); @@ -291,59 +312,32 @@ Cutting *&top, Cutting *&bottom, Cutting *&left, Cutting *&right) const { - if (m_first) {//!!! + if (m_threaded && !m_threadsInUse) { - m_first = false; + m_threadsInUse = true; if (m_cutThreads.empty()) { for (int i = 0; i < 4; ++i) { -// for (int i = 0; i < 1; ++i) { CutThread *t = new CutThread(this); -// t->start(); m_cutThreads.push_back(t); } -// sleep(1); //!!! } -// int threadIndices[4]; -// int found = 0; -// for (int i = 0; i < m_cutThreads.size(); ++i) { -// if (!m_cutThreads[i]->busy()) { -// threadIndices[found] = i; -// if (++found == 4) break; -// } -// } + // Cut threads 0 and 1 calculate the top and bottom halves; + // threads 2 and 3 calculate left and right. -// if (found == 4) { - - // enough threads available; use them. Need to avoid threads calling back on cut() in this class before we have made all of our threads busy (otherwise the recursive call is likely to claim threads further down our threadIndices before we do) -- hence m_threadMutex - - //!!! no, thread mutex not a good way, need a claim() call on each thread or something - -// m_threadMutex.lock(); + // The "vertical" division is a top/bottom split. + // Splitting this way keeps us in the same resolution, + // but with two vertical subregions of height h/2. m_cutThreads[0]->cut(s, res, x, y + h/2, h/2); // top m_cutThreads[1]->cut(s, res, x, y, h/2); // bottom m_cutThreads[2]->cut(s, res/2, 2 * x, y/2, h/2); // left m_cutThreads[3]->cut(s, res/2, 2 * x + 1, y/2, h/2); // right -// std::cerr << "set up all four" << std::endl; - top = m_cutThreads[0]->get(); bottom = m_cutThreads[1]->get(); left = m_cutThreads[2]->get(); right = m_cutThreads[3]->get(); -/* - bottom = cut(s, res, x, y, h/2); - - // The "horizontal" division is a left/right split. Splitting - // this way places us in resolution res/2, which has lower - // vertical resolution but higher horizontal resolution. We - // need to double x accordingly. - - left = cut(s, res/2, 2 * x, y/2, h/2); - right = cut(s, res/2, 2 * x + 1, y/2, h/2); -*/ -// std::cerr << "got all four" << std::endl; } else {
--- a/plugins/AdaptiveSpectrogram.h Wed May 13 13:32:43 2009 +0000 +++ b/plugins/AdaptiveSpectrogram.h Wed May 13 17:41:41 2009 +0000 @@ -54,6 +54,7 @@ protected: int m_w; int m_n; + bool m_threaded; struct Spectrogram { @@ -133,12 +134,9 @@ int getW() const { return m_w; } - void calculate(const float *timeDomain, Spectrograms &s, - int res, int maxwidth) { - m_in = timeDomain; - m_s = &s; - m_res = res; - m_maxwid = maxwidth; + void startCalculation(const float *timeDomain, Spectrograms &s, + int res, int maxwidth) { + setParameters(timeDomain, s, res, maxwidth); startTask(); } @@ -146,12 +144,19 @@ awaitTask(); } - protected: + void setParameters(const float *timeDomain, Spectrograms &s, + int res, int maxwidth) { + m_in = timeDomain; + m_s = &s; + m_res = res; + m_maxwid = maxwidth; + } + void performTask() { for (int i = 0; i < m_maxwid / m_w; ++i) { int origin = m_maxwid/4 - m_w/4; // for 50% overlap for (int j = 0; j < m_w; ++j) { - m_rin[j] = m_in[j]; + m_rin[j] = m_in[origin + i * m_w/2 + j]; } m_window.cut(m_rin); m_fft->process(false, m_rin, m_rout, m_iout); @@ -216,10 +221,8 @@ Cutting *m_result; }; - mutable std::vector<CutThread *> m_cutThreads;//!!! mutable blargh - -///!!! Mutex m_threadMutex; -mutable bool m_first; //!!! gross + mutable std::vector<CutThread *> m_cutThreads; + mutable bool m_threadsInUse; double xlogx(double x) const { if (x == 0.0) return 0.0;