# HG changeset patch # User Chris Cannam # Date 1151338331 0 # Node ID f47f4c7c158c9ffdeef2a3ea50e34dea4d3af23f # Parent 514ebb0c5c6c2a9eaa74c33ebff15283b5429a6c * Add FFT data server class to provide a file cache mapping for each required set of FFT parameters and source model. Make use of it in feature extraction plugin transform, though not in other places yet. * Add zero-pad option to spectrogram layer and remove window shape option from the property box. To be revised. diff -r 514ebb0c5c6c -r f47f4c7c158c base/FFTCache.cpp --- a/base/FFTCache.cpp Mon Jun 26 16:08:01 2006 +0000 +++ b/base/FFTCache.cpp Mon Jun 26 16:12:11 2006 +0000 @@ -99,3 +99,20 @@ } } +void +FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags) +{ + float max = 0.0; + + for (size_t y = 0; y < m_height; ++y) { + float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]); + float phase = atan2f(imags[y], reals[y]); + phase = princargf(phase); + reals[y] = mag; + imags[y] = phase; + if (mag > max) max = mag; + } + + setColumnAt(x, reals, imags, max); +} + diff -r 514ebb0c5c6c -r f47f4c7c158c base/FFTCache.h --- a/base/FFTCache.h Mon Jun 26 16:08:01 2006 +0000 +++ b/base/FFTCache.h Mon Jun 26 16:12:11 2006 +0000 @@ -36,9 +36,16 @@ virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const = 0; virtual float getPhaseAt(size_t x, size_t y) const = 0; + virtual void getValuesAt(size_t x, size_t y, float &real, float &imaginary) const = 0; + virtual bool haveSetColumnAt(size_t x) const = 0; + + // may modify argument arrays virtual void setColumnAt(size_t x, float *mags, float *phases, float factor) = 0; + // may modify argument arrays + virtual void setColumnAt(size_t x, float *reals, float *imags) = 0; + bool isLocalPeak(size_t x, size_t y) const { float mag = getMagnitudeAt(x, y); if (y > 0 && mag < getMagnitudeAt(x, y - 1)) return false; @@ -98,6 +105,13 @@ return (float(i) / 32767.0) * M_PI; } + virtual void getValuesAt(size_t x, size_t y, float &real, float &imag) const { + float mag = getMagnitudeAt(x, y); + float phase = getPhaseAt(x, y); + real = mag * cosf(phase); + imag = mag * sinf(phase); + } + virtual void setNormalizationFactor(size_t x, float factor) { if (x < m_width) m_factor[x] = factor; } @@ -132,6 +146,8 @@ } } + virtual void setColumnAt(size_t x, float *reals, float *imags); + private: size_t m_width; size_t m_height; diff -r 514ebb0c5c6c -r f47f4c7c158c transform/FeatureExtractionPluginTransform.cpp --- a/transform/FeatureExtractionPluginTransform.cpp Mon Jun 26 16:08:01 2006 +0000 +++ b/transform/FeatureExtractionPluginTransform.cpp Mon Jun 26 16:12:11 2006 +0000 @@ -1,4 +1,3 @@ - /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* @@ -28,6 +27,8 @@ #include "model/DenseTimeValueModel.h" #include "model/NoteModel.h" +#include "fileio/FFTDataServer.h" + #include #include @@ -241,6 +242,7 @@ buffers[ch] = new float[m_blockSize]; } +/*!!! float *fftInput = 0; fftwf_complex *fftOutput = 0; fftwf_plan fftPlan = 0; @@ -256,6 +258,24 @@ std::cerr << "ERROR: FeatureExtractionPluginTransform::run(): fftw_plan failed! Results will be garbage" << std::endl; } } +*/ + + bool frequencyDomain = (m_plugin->getInputDomain() == + Vamp::Plugin::FrequencyDomain); + std::vector fftServers; + + if (frequencyDomain) { + for (size_t ch = 0; ch < channelCount; ++ch) { + fftServers.push_back(FFTDataServer::getInstance + (getInput(), + channelCount == 1 ? m_channel : ch, + HanningWindow, + m_blockSize, + m_stepSize, + m_blockSize, + false)); + } + } long startFrame = m_input->getStartFrame(); long endFrame = m_input->getEndFrame(); @@ -265,7 +285,7 @@ while (1) { - if (fftPlan) { + if (frequencyDomain) { if (blockFrame - int(m_blockSize)/2 > endFrame) break; } else { if (blockFrame >= endFrame) break; @@ -281,15 +301,22 @@ // channelCount is either m_input->channelCount or 1 for (size_t ch = 0; ch < channelCount; ++ch) { - if (fftPlan) { - getFrames(ch, channelCount, - blockFrame - m_blockSize/2, m_blockSize, buffers[ch]); +//!!! if (fftPlan) { +// getFrames(ch, channelCount, +// blockFrame - m_blockSize/2, m_blockSize, buffers[ch]); + + if (frequencyDomain) { + int column = (blockFrame - startFrame) / m_stepSize; + for (size_t i = 0; i < m_blockSize/2; ++i) { + fftServers[ch]->getValuesAt + (column, i, buffers[ch][i*2], buffers[ch][i*2+1]); + } } else { getFrames(ch, channelCount, - blockFrame, m_blockSize, buffers[ch]); + blockFrame, m_blockSize, buffers[ch]); } } - + /*!!! if (fftPlan) { for (size_t ch = 0; ch < channelCount; ++ch) { for (size_t i = 0; i < m_blockSize; ++i) { @@ -308,7 +335,7 @@ } } } - + */ Vamp::Plugin::FeatureSet features = m_plugin->process (buffers, Vamp::RealTime::frame2RealTime(blockFrame, sampleRate)); @@ -325,13 +352,13 @@ blockFrame += m_stepSize; } - +/*!!! if (fftPlan) { fftwf_destroy_plan(fftPlan); fftwf_free(fftInput); fftwf_free(fftOutput); } - +*/ Vamp::Plugin::FeatureSet features = m_plugin->getRemainingFeatures(); for (size_t fi = 0; fi < features[m_outputFeatureNo].size(); ++fi) {