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);
-}
-