Mercurial > hg > svcore
diff data/model/FFTModel.cpp @ 1090:420fc961c0c4 simple-fft-model
Gut the old code, but don't replace it yet (so nothing will link yet)
author | Chris Cannam |
---|---|
date | Fri, 12 Jun 2015 14:51:46 +0100 |
parents | 0fd3661bcfff |
children | bdebff3265ae |
line wrap: on
line diff
--- a/data/model/FFTModel.cpp Fri Jun 12 13:46:44 2015 +0100 +++ b/data/model/FFTModel.cpp Fri Jun 12 14:51:46 2015 +0100 @@ -15,7 +15,6 @@ #include "FFTModel.h" #include "DenseTimeValueModel.h" -#include "AggregateWaveModel.h" #include "base/Profiler.h" #include "base/Pitch.h" @@ -23,178 +22,43 @@ #include <algorithm> #include <cassert> +#include <deque> #ifndef __GNUC__ #include <alloca.h> #endif +using namespace std; + FFTModel::FFTModel(const DenseTimeValueModel *model, int channel, WindowType windowType, int windowSize, int windowIncrement, - int fftSize, - bool polar, - StorageAdviser::Criteria criteria, - sv_frame_t fillFromFrame) : - //!!! ZoomConstraint! - m_server(0), - m_xshift(0), - m_yshift(0) + int fftSize) : + m_model(model), + m_channel(channel), + m_windowType(windowType), + m_windowSize(windowSize), + m_windowIncrement(windowIncrement), + m_fftSize(fftSize), + m_windower(windowType, windowSize) { - setSourceModel(const_cast<DenseTimeValueModel *>(model)); //!!! hmm. - - m_server = getServer(model, - channel, - windowType, - windowSize, - windowIncrement, - fftSize, - polar, - criteria, - fillFromFrame); - - if (!m_server) return; // caller should check isOK() - - int xratio = windowIncrement / m_server->getWindowIncrement(); - int yratio = m_server->getFFTSize() / fftSize; - - while (xratio > 1) { - if (xratio & 0x1) { - cerr << "ERROR: FFTModel: Window increment ratio " - << windowIncrement << " / " - << m_server->getWindowIncrement() - << " must be a power of two" << endl; - assert(!(xratio & 0x1)); - } - ++m_xshift; - xratio >>= 1; - } - - while (yratio > 1) { - if (yratio & 0x1) { - cerr << "ERROR: FFTModel: FFT size ratio " - << m_server->getFFTSize() << " / " << fftSize - << " must be a power of two" << endl; - assert(!(yratio & 0x1)); - } - ++m_yshift; - yratio >>= 1; - } } FFTModel::~FFTModel() { - if (m_server) FFTDataServer::releaseInstance(m_server); } void FFTModel::sourceModelAboutToBeDeleted() { - if (m_sourceModel) { - cerr << "FFTModel[" << this << "]::sourceModelAboutToBeDeleted(" << m_sourceModel << ")" << endl; - if (m_server) { - FFTDataServer::releaseInstance(m_server); - m_server = 0; - } - FFTDataServer::modelAboutToBeDeleted(m_sourceModel); + if (m_model) { + cerr << "FFTModel[" << this << "]::sourceModelAboutToBeDeleted(" << m_model << ")" << endl; + m_model = 0; } } -FFTDataServer * -FFTModel::getServer(const DenseTimeValueModel *model, - int channel, - WindowType windowType, - int windowSize, - int windowIncrement, - int fftSize, - bool polar, - StorageAdviser::Criteria criteria, - sv_frame_t fillFromFrame) -{ - // Obviously, an FFT model of channel C (where C != -1) of an - // aggregate model is the same as the FFT model of the appropriate - // channel of whichever model that aggregate channel is drawn - // from. We should use that model here, in case we already have - // the data for it or will be wanting the same data again later. - - // If the channel is -1 (i.e. mixture of all channels), then we - // can't do this shortcut unless the aggregate model only has one - // channel or contains exactly all of the channels of a single - // other model. That isn't very likely -- if it were the case, - // why would we be using an aggregate model? - - if (channel >= 0) { - - const AggregateWaveModel *aggregate = - dynamic_cast<const AggregateWaveModel *>(model); - - if (aggregate && channel < aggregate->getComponentCount()) { - - AggregateWaveModel::ModelChannelSpec spec = - aggregate->getComponent(channel); - - return getServer(spec.model, - spec.channel, - windowType, - windowSize, - windowIncrement, - fftSize, - polar, - criteria, - fillFromFrame); - } - } - - // The normal case - - return FFTDataServer::getFuzzyInstance(model, - channel, - windowType, - windowSize, - windowIncrement, - fftSize, - polar, - criteria, - fillFromFrame); -} - -sv_samplerate_t -FFTModel::getSampleRate() const -{ - return isOK() ? m_server->getModel()->getSampleRate() : 0; -} - -FFTModel::Column -FFTModel::getColumn(int x) const -{ - Profiler profiler("FFTModel::getColumn", false); - - Column result; - - result.clear(); - int h = getHeight(); - result.reserve(h); - -#ifdef __GNUC__ - float magnitudes[h]; -#else - float *magnitudes = (float *)alloca(h * sizeof(float)); -#endif - - if (m_server->getMagnitudesAt(x << m_xshift, magnitudes)) { - - for (int y = 0; y < h; ++y) { - result.push_back(magnitudes[y]); - } - - } else { - for (int i = 0; i < h; ++i) result.push_back(0.f); - } - - return result; -} - QString FFTModel::getBinName(int n) const { @@ -209,10 +73,7 @@ { if (!isOK()) return false; - sv_samplerate_t sampleRate = m_server->getModel()->getSampleRate(); - - int fftSize = m_server->getFFTSize() >> m_yshift; - frequency = double(y * sampleRate) / fftSize; + frequency = double(y * getSampleRate()) / m_fftSize; if (x+1 >= getWidth()) return false; @@ -230,17 +91,15 @@ int incr = getResolution(); - double expectedPhase = oldPhase + (2.0 * M_PI * y * incr) / fftSize; + double expectedPhase = oldPhase + (2.0 * M_PI * y * incr) / m_fftSize; double phaseError = princarg(newPhase - expectedPhase); -// bool stable = (fabsf(phaseError) < (1.1f * (m_windowIncrement * M_PI) / m_fftSize)); - // The new frequency estimate based on the phase error resulting // from assuming the "native" frequency of this bin frequency = - (sampleRate * (expectedPhase + phaseError - oldPhase)) / + (getSampleRate() * (expectedPhase + phaseError - oldPhase)) / (2.0 * M_PI * incr); return true; @@ -293,8 +152,8 @@ sv_samplerate_t sampleRate = getSampleRate(); - std::deque<float> window; - std::vector<int> inrange; + deque<float> window; + vector<int> inrange; float dist = 0.5; int medianWinSize = getPeakPickWindowSize(type, sampleRate, ymin, dist); @@ -331,8 +190,8 @@ else binmax = values.size()-1; } - std::deque<float> sorted(window); - std::sort(sorted.begin(), sorted.end()); + deque<float> sorted(window); + sort(sorted.begin(), sorted.end()); float median = sorted[int(float(sorted.size()) * dist)]; int centrebin = 0; @@ -380,15 +239,14 @@ if (type == MajorPeaks) return 10; if (bin == 0) return 3; - int fftSize = m_server->getFFTSize() >> m_yshift; - double binfreq = (sampleRate * bin) / fftSize; + double binfreq = (getSampleRate() * bin) / m_fftSize; double hifreq = Pitch::getFrequencyForPitch(73, 0, binfreq); - int hibin = int(lrint((hifreq * fftSize) / sampleRate)); + int hibin = int(lrint((hifreq * m_fftSize) / getSampleRate())); int medianWinSize = hibin - bin; if (medianWinSize < 3) medianWinSize = 3; - percentile = 0.5f + float(binfreq / sampleRate); + percentile = 0.5f + float(binfreq / getSampleRate()); return medianWinSize; } @@ -404,7 +262,6 @@ PeakLocationSet locations = getPeaks(type, x, ymin, ymax); sv_samplerate_t sampleRate = getSampleRate(); - int fftSize = m_server->getFFTSize() >> m_yshift; int incr = getResolution(); // This duplicates some of the work of estimateStableFrequency to @@ -412,7 +269,7 @@ // columns, instead of jumping back and forth between columns x and // x+1, which may be significantly slower if re-seeking is needed - std::vector<float> phases; + vector<float> phases; for (PeakLocationSet::iterator i = locations.begin(); i != locations.end(); ++i) { phases.push_back(getPhaseAt(x, *i)); @@ -423,13 +280,11 @@ i != locations.end(); ++i) { double oldPhase = phases[phaseIndex]; double newPhase = getPhaseAt(x+1, *i); - double expectedPhase = oldPhase + (2.0 * M_PI * *i * incr) / fftSize; + double expectedPhase = oldPhase + (2.0 * M_PI * *i * incr) / m_fftSize; double phaseError = princarg(newPhase - expectedPhase); double frequency = (sampleRate * (expectedPhase + phaseError - oldPhase)) / (2 * M_PI * incr); -// bool stable = (fabsf(phaseError) < (1.1f * (incr * M_PI) / fftSize)); -// if (stable) peaks[*i] = frequency; ++phaseIndex; } @@ -437,12 +292,3 @@ return peaks; } -FFTModel::FFTModel(const FFTModel &model) : - DenseThreeDimensionalModel(), - m_server(model.m_server), - m_xshift(model.m_xshift), - m_yshift(model.m_yshift) -{ - FFTDataServer::claimInstance(m_server); -} -