changeset 1556:ac8da42674ff spectrogram-export

Handle peaks
author Chris Cannam
date Tue, 07 Jan 2020 11:18:57 +0000
parents 745be36202aa
children 3607b0092019
files layer/Colour3DPlotExporter.cpp layer/Colour3DPlotExporter.h
diffstat 2 files changed, 125 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/layer/Colour3DPlotExporter.cpp	Tue Jan 07 11:18:43 2020 +0000
+++ b/layer/Colour3DPlotExporter.cpp	Tue Jan 07 11:18:57 2020 +0000
@@ -19,6 +19,32 @@
 
 #include "VerticalBinLayer.h"
 
+Colour3DPlotExporter::Colour3DPlotExporter(Sources sources, Parameters params) :
+    m_sources(sources),
+    m_params(params)
+{
+    SVCERR << "Colour3DPlotExporter::Colour3DPlotExporter: constructed at "
+           << this << endl;
+}
+
+Colour3DPlotExporter::~Colour3DPlotExporter()
+{
+    SVCERR << "Colour3DPlotExporter[" << this << "]::~Colour3DPlotExporter"
+           << endl;
+}
+
+void
+Colour3DPlotExporter::discardSources()
+{
+    SVCERR << "Colour3DPlotExporter[" << this << "]::discardSources"
+           << endl;
+    QMutexLocker locker(&m_mutex);
+    m_sources.verticalBinLayer = nullptr;
+    m_sources.source = {};
+    m_sources.fft = {};
+    m_sources.provider = nullptr;
+}
+
 QString
 Colour3DPlotExporter::toDelimitedDataString(QString delimiter,
                                             DataExportOptions options,
@@ -29,6 +55,8 @@
 
     BinDisplay binDisplay = m_params.binDisplay;
 
+    (void)options; //!!!
+
     auto model =
         ModelById::getAs<DenseThreeDimensionalModel>(m_sources.source);
     auto fftModel =
@@ -41,6 +69,10 @@
         SVCERR << "ERROR: Colour3DPlotExporter::toDelimitedDataString: Source model and layer required" << endl;
         return {};
     }
+    if ((binDisplay == BinDisplay::PeakFrequencies) && !fftModel) {
+        SVCERR << "ERROR: Colour3DPlotExporter::toDelimitedDataString: FFT model required in peak frequencies mode" << endl;
+        return {};
+    }
 
     int minbin = 0;
     int sh = model->getHeight();
@@ -57,6 +89,14 @@
 
     //!!! todo: what about the other export types besides
     //!!! delimited-data-string ?
+
+    //!!! todo: scripted regression tests for layer exports (of all
+    //!!! types)
+
+    //!!! todo: export selected region only (we have the necessaries
+    //!!! here, but it needs support higher up)
+
+    //!!! todo: option to include timestamps for columns
     
     if (provider) {
 
@@ -73,14 +113,50 @@
     QString s;
     
     for (int i = 0; i < w; ++i) {
+        
         sv_frame_t fr = model->getStartFrame() + i * model->getResolution();
         if (fr < startFrame || fr >= startFrame + duration) {
             continue;
         }
+
+        // Unlike Colour3DPlotRenderer, we don't want to scale or
+        // normalise
+        
+        //!!! (should we be handling phase layer type?)
+
+        auto column = model->getColumn(i);
+        column = ColumnOp::Column(column.data() + minbin,
+                                  column.data() + minbin + nbins);
+        
+        //!!! todo: peaks, frequencies (the things we came here for)
+
         QStringList list;
 
-        //...
+        if (binDisplay == BinDisplay::PeakFrequencies) {
+            
+            FFTModel::PeakSet peaks = fftModel->getPeakFrequencies
+                (FFTModel::AllPeaks, i, minbin, minbin + nbins + 1);
 
+            for (const auto &p: peaks) {
+
+                int bin = p.first;
+                double freq = p.second;
+                float mag = column[bin - minbin];
+
+                list << QString("%1").arg(freq) << QString("%1").arg(mag);
+            }
+
+        } else {
+        
+            if (binDisplay == BinDisplay::PeakBins) {
+                column = ColumnOp::peakPick(column);
+            }
+        
+            for (auto value: column) {
+                list << QString("%1").arg(value);
+            }
+        }
+        
         s += list.join(delimiter) + "\n";
     }
 
--- a/layer/Colour3DPlotExporter.h	Tue Jan 07 11:18:43 2020 +0000
+++ b/layer/Colour3DPlotExporter.h	Tue Jan 07 11:18:57 2020 +0000
@@ -39,22 +39,59 @@
         BinDisplay binDisplay;
     };
     
-    Colour3DPlotExporter(Sources sources, Parameters parameters) :
-        m_sources(sources),
-        m_params(parameters)
-    { }
+    Colour3DPlotExporter(Sources sources, Parameters parameters);
+    ~Colour3DPlotExporter();
 
-    void discardSources() {
-        QMutexLocker locker(&m_mutex);
-        m_sources.verticalBinLayer = nullptr;
-        m_sources.source = {};
-        m_sources.fft = {};
-        m_sources.provider = nullptr;
-    }
+    void discardSources();
 
     QString toDelimitedDataString(QString, DataExportOptions,
                                   sv_frame_t, sv_frame_t) const override;
 
+    
+    // Further Model methods that we just delegate
+
+    bool isOK() const override {
+        if (auto model = ModelById::get(m_sources.source)) {
+            return model->isOK();
+        }
+        return false;
+    }
+        
+    sv_frame_t getStartFrame() const override { 
+        if (auto model = ModelById::get(m_sources.source)) {
+            return model->getStartFrame();
+        }
+        return 0;
+    }
+    
+    sv_frame_t getTrueEndFrame() const override { 
+        if (auto model = ModelById::get(m_sources.source)) {
+            return model->getTrueEndFrame();
+        }
+        return 0;
+    }
+    
+    sv_samplerate_t getSampleRate() const override { 
+        if (auto model = ModelById::get(m_sources.source)) {
+            return model->getSampleRate();
+        }
+        return 0;
+    }
+
+    QString getTypeName() const override {
+        if (auto model = ModelById::get(m_sources.source)) {
+            return model->getTypeName();
+        }
+        return "(exporter)"; // internal fallback, no translation needed
+    }
+
+    int getCompletion() const override {
+        if (auto model = ModelById::get(m_sources.source)) {
+            return model->getCompletion();
+        }
+        return 0;
+    }
+    
 private:
     Sources m_sources;
     Parameters m_params;