# HG changeset patch # User Chris Cannam # Date 1578580491 0 # Node ID d6f9fac336b37d195066a1ed189d8d0cb06a5929 # Parent 27f3e64489e16a537b64b71e7ae563d6c87c5121 Handle scale factor, needed for all spectrogram export; handle thresholding (using gain/normalisation for threshold calculation) in peak frequency export diff -r 27f3e64489e1 -r d6f9fac336b3 layer/Colour3DPlotExporter.cpp --- a/layer/Colour3DPlotExporter.cpp Thu Jan 09 14:29:21 2020 +0000 +++ b/layer/Colour3DPlotExporter.cpp Thu Jan 09 14:34:51 2020 +0000 @@ -115,19 +115,15 @@ if (fr < startFrame || fr >= startFrame + duration) { continue; } - - // Unlike Colour3DPlotRenderer, we don't want to scale or - // normalise - - //!!! (but might we want to threshold? we get a lot of - //!!! spurious output [i.e. elements not readily visible on - //!!! screen] for peak freqs) - //!!! (+ should we be handling phase layer type?) + //!!! (+ phase layer type) auto column = model->getColumn(i); column = ColumnOp::Column(column.data() + minbin, column.data() + minbin + nbins); + + // The scale factor is always applied + column = ColumnOp::applyGain(column, m_params.scaleFactor); QStringList list; @@ -136,13 +132,28 @@ FFTModel::PeakSet peaks = fftModel->getPeakFrequencies (FFTModel::AllPeaks, i, minbin, minbin + nbins - 1); + // We don't apply normalisation or gain to the output, but + // we *do* perform thresholding when exporting the + // peak-frequency spectrogram, to give the user an + // opportunity to cut irrelevant peaks. And to make that + // match the display, we have to apply both normalisation + // and gain locally for thresholding + + auto toTest = ColumnOp::normalize(column, m_params.normalization); + toTest = ColumnOp::applyGain(toTest, m_params.gain); + for (const auto &p: peaks) { int bin = p.first; + + if (toTest[bin - minbin] < m_params.threshold) { + continue; + } + double freq = p.second; - float mag = column[bin - minbin]; - - list << QString("%1").arg(freq) << QString("%1").arg(mag); + double value = column[bin - minbin]; + + list << QString("%1").arg(freq) << QString("%1").arg(value); } } else { @@ -160,23 +171,5 @@ } return s; - - - //!!! For reference, this is the body of - //!!! EditableDenseThreeDimensionalModel::toDelimitedDataString - /* - QString s; - for (int i = 0; in_range_for(m_data, i); ++i) { - sv_frame_t fr = m_startFrame + i * m_resolution; - if (fr >= startFrame && fr < startFrame + duration) { - QStringList list; - for (int j = 0; in_range_for(m_data.at(i), j); ++j) { - list << QString("%1").arg(m_data.at(i).at(j)); - } - s += list.join(delimiter) + "\n"; - } - } - return s; - */ } diff -r 27f3e64489e1 -r d6f9fac336b3 layer/Colour3DPlotExporter.h --- a/layer/Colour3DPlotExporter.h Thu Jan 09 14:29:21 2020 +0000 +++ b/layer/Colour3DPlotExporter.h Thu Jan 09 14:34:51 2020 +0000 @@ -33,10 +33,36 @@ struct Parameters { Parameters() : - binDisplay(BinDisplay::AllBins) { } + binDisplay(BinDisplay::AllBins), + scaleFactor(1.0), + threshold(0.0), + gain(1.0), + normalization(ColumnNormalization::None) { } /** Selection of bins to include in the export. */ BinDisplay binDisplay; + + /** Initial scale factor (e.g. for FFT scaling). This factor + * is actually applied to exported values, in contrast to the + * gain value below based on the ColourScale parameter. */ + double scaleFactor; + + /** Threshold below which every value is mapped to background + * pixel 0 in the display, matching the ColourScale object + * parameters. This is used for thresholding in + * peak-frequency output only. */ + double threshold; + + /** Gain that is applied before thresholding, in the display, + * matching the ColourScale object parameters. This is used + * only to determined the thresholding level. The exported + * values have the scaleFactor applied, but not this gain. */ + double gain; + + /** Type of column normalization. Again, this is only used to + * calculate thresholding level. The exported values are + * un-normalized. */ + ColumnNormalization normalization; }; Colour3DPlotExporter(Sources sources, Parameters parameters);