comparison layer/Colour3DPlotExporter.cpp @ 1561:d6f9fac336b3 spectrogram-export

Handle scale factor, needed for all spectrogram export; handle thresholding (using gain/normalisation for threshold calculation) in peak frequency export
author Chris Cannam
date Thu, 09 Jan 2020 14:34:51 +0000
parents e6e7a8dc3b38
children 62b7699e5bfe
comparison
equal deleted inserted replaced
1560:27f3e64489e1 1561:d6f9fac336b3
113 113
114 sv_frame_t fr = model->getStartFrame() + i * model->getResolution(); 114 sv_frame_t fr = model->getStartFrame() + i * model->getResolution();
115 if (fr < startFrame || fr >= startFrame + duration) { 115 if (fr < startFrame || fr >= startFrame + duration) {
116 continue; 116 continue;
117 } 117 }
118
119 // Unlike Colour3DPlotRenderer, we don't want to scale or
120 // normalise
121
122 //!!! (but might we want to threshold? we get a lot of
123 //!!! spurious output [i.e. elements not readily visible on
124 //!!! screen] for peak freqs)
125 118
126 //!!! (+ should we be handling phase layer type?) 119 //!!! (+ phase layer type)
127 120
128 auto column = model->getColumn(i); 121 auto column = model->getColumn(i);
129 column = ColumnOp::Column(column.data() + minbin, 122 column = ColumnOp::Column(column.data() + minbin,
130 column.data() + minbin + nbins); 123 column.data() + minbin + nbins);
124
125 // The scale factor is always applied
126 column = ColumnOp::applyGain(column, m_params.scaleFactor);
131 127
132 QStringList list; 128 QStringList list;
133 129
134 if (binDisplay == BinDisplay::PeakFrequencies) { 130 if (binDisplay == BinDisplay::PeakFrequencies) {
135 131
136 FFTModel::PeakSet peaks = fftModel->getPeakFrequencies 132 FFTModel::PeakSet peaks = fftModel->getPeakFrequencies
137 (FFTModel::AllPeaks, i, minbin, minbin + nbins - 1); 133 (FFTModel::AllPeaks, i, minbin, minbin + nbins - 1);
138 134
135 // We don't apply normalisation or gain to the output, but
136 // we *do* perform thresholding when exporting the
137 // peak-frequency spectrogram, to give the user an
138 // opportunity to cut irrelevant peaks. And to make that
139 // match the display, we have to apply both normalisation
140 // and gain locally for thresholding
141
142 auto toTest = ColumnOp::normalize(column, m_params.normalization);
143 toTest = ColumnOp::applyGain(toTest, m_params.gain);
144
139 for (const auto &p: peaks) { 145 for (const auto &p: peaks) {
140 146
141 int bin = p.first; 147 int bin = p.first;
148
149 if (toTest[bin - minbin] < m_params.threshold) {
150 continue;
151 }
152
142 double freq = p.second; 153 double freq = p.second;
143 float mag = column[bin - minbin]; 154 double value = column[bin - minbin];
144 155
145 list << QString("%1").arg(freq) << QString("%1").arg(mag); 156 list << QString("%1").arg(freq) << QString("%1").arg(value);
146 } 157 }
147 158
148 } else { 159 } else {
149 160
150 if (binDisplay == BinDisplay::PeakBins) { 161 if (binDisplay == BinDisplay::PeakBins) {
158 169
159 s += list.join(delimiter) + "\n"; 170 s += list.join(delimiter) + "\n";
160 } 171 }
161 172
162 return s; 173 return s;
163
164
165 //!!! For reference, this is the body of
166 //!!! EditableDenseThreeDimensionalModel::toDelimitedDataString
167 /*
168 QString s;
169 for (int i = 0; in_range_for(m_data, i); ++i) {
170 sv_frame_t fr = m_startFrame + i * m_resolution;
171 if (fr >= startFrame && fr < startFrame + duration) {
172 QStringList list;
173 for (int j = 0; in_range_for(m_data.at(i), j); ++j) {
174 list << QString("%1").arg(m_data.at(i).at(j));
175 }
176 s += list.join(delimiter) + "\n";
177 }
178 }
179 return s;
180 */
181 } 174 }
182 175