comparison data/model/FFTModel.cpp @ 280:daf89d31f45c

* Restore Scale setting which had mistakenly disappeared from spectrum * Some tweaks to spectrum peaks * Make spectrum default to 4096/75%... or is that overdoing it? * Show harmonic cursor even during playback if in measure mode and mouse in relevant pane * Avoid crash when trying to measure a non-layer * Various adjustments to some icons to make them look better in white-on-black schemes
author Chris Cannam
date Fri, 13 Jul 2007 15:54:17 +0000
parents 522f82311e4e
children c022976d18e8
comparison
equal deleted inserted replaced
279:7802b0e2b0ff 280:daf89d31f45c
182 182
183 size_t sampleRate = getSampleRate(); 183 size_t sampleRate = getSampleRate();
184 184
185 std::deque<float> window; 185 std::deque<float> window;
186 std::vector<size_t> inrange; 186 std::vector<size_t> inrange;
187 size_t medianWinSize = getPeakPickWindowSize(type, sampleRate, ymin); 187 float dist = 0.5;
188 size_t medianWinSize = getPeakPickWindowSize(type, sampleRate, ymin, dist);
188 size_t halfWin = medianWinSize/2; 189 size_t halfWin = medianWinSize/2;
189 190
190 size_t binmin; 191 size_t binmin;
191 if (ymin > halfWin) binmin = ymin - halfWin; 192 if (ymin > halfWin) binmin = ymin - halfWin;
192 else binmin = 0; 193 else binmin = 0;
199 200
200 float value = values[bin]; 201 float value = values[bin];
201 202
202 window.push_back(value); 203 window.push_back(value);
203 204
204 medianWinSize = getPeakPickWindowSize(type, sampleRate, bin); 205 // so-called median will actually be the dist*100'th percentile
206 medianWinSize = getPeakPickWindowSize(type, sampleRate, bin, dist);
205 halfWin = medianWinSize/2; 207 halfWin = medianWinSize/2;
206 208
207 while (window.size() > medianWinSize) window.pop_front(); 209 while (window.size() > medianWinSize) window.pop_front();
208 210
209 if (type == MajorPitchAdaptivePeaks) { 211 if (type == MajorPitchAdaptivePeaks) {
211 else binmax = values.size()-1; 213 else binmax = values.size()-1;
212 } 214 }
213 215
214 std::deque<float> sorted(window); 216 std::deque<float> sorted(window);
215 std::sort(sorted.begin(), sorted.end()); 217 std::sort(sorted.begin(), sorted.end());
216 float median = sorted[sorted.size()/2]; 218 float median = sorted[int(sorted.size() * dist)];
217 219
218 if (value > median) { 220 if (value > median) {
219 inrange.push_back(bin); 221 inrange.push_back(bin);
220 } 222 }
221 223
239 241
240 return peaks; 242 return peaks;
241 } 243 }
242 244
243 size_t 245 size_t
244 FFTModel::getPeakPickWindowSize(PeakPickType type, size_t sampleRate, size_t bin) const 246 FFTModel::getPeakPickWindowSize(PeakPickType type, size_t sampleRate,
245 { 247 size_t bin, float &percentile) const
248 {
249 percentile = 0.5;
246 if (type == MajorPeaks) return 10; 250 if (type == MajorPeaks) return 10;
247 if (bin == 0) return 3; 251 if (bin == 0) return 3;
252
248 size_t fftSize = m_server->getFFTSize() >> m_yshift; 253 size_t fftSize = m_server->getFFTSize() >> m_yshift;
249 float binfreq = (sampleRate * bin) / fftSize; 254 float binfreq = (sampleRate * bin) / fftSize;
250 float hifreq = Pitch::getFrequencyForPitch(73, 0, binfreq); 255 float hifreq = Pitch::getFrequencyForPitch(73, 0, binfreq);
256
251 int hibin = lrintf((hifreq * fftSize) / sampleRate); 257 int hibin = lrintf((hifreq * fftSize) / sampleRate);
252 int medianWinSize = hibin - bin; 258 int medianWinSize = hibin - bin;
253 if (medianWinSize < 3) medianWinSize = 3; 259 if (medianWinSize < 3) medianWinSize = 3;
260
261 percentile = 0.5 + (binfreq / sampleRate);
262
254 return medianWinSize; 263 return medianWinSize;
255 } 264 }
256 265
257 FFTModel::PeakSet 266 FFTModel::PeakSet
258 FFTModel::getPeakFrequencies(PeakPickType type, size_t x, 267 FFTModel::getPeakFrequencies(PeakPickType type, size_t x,