Mercurial > hg > svcore
comparison data/model/FFTModel.cpp @ 929:59e7fe1b1003 warnfix_no_size_t
Unsigned removals and warning fixes in data/
author | Chris Cannam |
---|---|
date | Tue, 17 Jun 2014 14:33:42 +0100 |
parents | e802e550a1f2 |
children | a8aed8a85e09 |
comparison
equal
deleted
inserted
replaced
928:6a94bb528e9d | 929:59e7fe1b1003 |
---|---|
29 #endif | 29 #endif |
30 | 30 |
31 FFTModel::FFTModel(const DenseTimeValueModel *model, | 31 FFTModel::FFTModel(const DenseTimeValueModel *model, |
32 int channel, | 32 int channel, |
33 WindowType windowType, | 33 WindowType windowType, |
34 size_t windowSize, | 34 int windowSize, |
35 size_t windowIncrement, | 35 int windowIncrement, |
36 size_t fftSize, | 36 int fftSize, |
37 bool polar, | 37 bool polar, |
38 StorageAdviser::Criteria criteria, | 38 StorageAdviser::Criteria criteria, |
39 size_t fillFromColumn) : | 39 int fillFromColumn) : |
40 //!!! ZoomConstraint! | 40 //!!! ZoomConstraint! |
41 m_server(0), | 41 m_server(0), |
42 m_xshift(0), | 42 m_xshift(0), |
43 m_yshift(0) | 43 m_yshift(0) |
44 { | 44 { |
54 criteria, | 54 criteria, |
55 fillFromColumn); | 55 fillFromColumn); |
56 | 56 |
57 if (!m_server) return; // caller should check isOK() | 57 if (!m_server) return; // caller should check isOK() |
58 | 58 |
59 size_t xratio = windowIncrement / m_server->getWindowIncrement(); | 59 int xratio = windowIncrement / m_server->getWindowIncrement(); |
60 size_t yratio = m_server->getFFTSize() / fftSize; | 60 int yratio = m_server->getFFTSize() / fftSize; |
61 | 61 |
62 while (xratio > 1) { | 62 while (xratio > 1) { |
63 if (xratio & 0x1) { | 63 if (xratio & 0x1) { |
64 cerr << "ERROR: FFTModel: Window increment ratio " | 64 cerr << "ERROR: FFTModel: Window increment ratio " |
65 << windowIncrement << " / " | 65 << windowIncrement << " / " |
103 | 103 |
104 FFTDataServer * | 104 FFTDataServer * |
105 FFTModel::getServer(const DenseTimeValueModel *model, | 105 FFTModel::getServer(const DenseTimeValueModel *model, |
106 int channel, | 106 int channel, |
107 WindowType windowType, | 107 WindowType windowType, |
108 size_t windowSize, | 108 int windowSize, |
109 size_t windowIncrement, | 109 int windowIncrement, |
110 size_t fftSize, | 110 int fftSize, |
111 bool polar, | 111 bool polar, |
112 StorageAdviser::Criteria criteria, | 112 StorageAdviser::Criteria criteria, |
113 size_t fillFromColumn) | 113 int fillFromColumn) |
114 { | 114 { |
115 // Obviously, an FFT model of channel C (where C != -1) of an | 115 // Obviously, an FFT model of channel C (where C != -1) of an |
116 // aggregate model is the same as the FFT model of the appropriate | 116 // aggregate model is the same as the FFT model of the appropriate |
117 // channel of whichever model that aggregate channel is drawn | 117 // channel of whichever model that aggregate channel is drawn |
118 // from. We should use that model here, in case we already have | 118 // from. We should use that model here, in case we already have |
157 polar, | 157 polar, |
158 criteria, | 158 criteria, |
159 fillFromColumn); | 159 fillFromColumn); |
160 } | 160 } |
161 | 161 |
162 size_t | 162 int |
163 FFTModel::getSampleRate() const | 163 FFTModel::getSampleRate() const |
164 { | 164 { |
165 return isOK() ? m_server->getModel()->getSampleRate() : 0; | 165 return isOK() ? m_server->getModel()->getSampleRate() : 0; |
166 } | 166 } |
167 | 167 |
168 FFTModel::Column | 168 FFTModel::Column |
169 FFTModel::getColumn(size_t x) const | 169 FFTModel::getColumn(int x) const |
170 { | 170 { |
171 Profiler profiler("FFTModel::getColumn", false); | 171 Profiler profiler("FFTModel::getColumn", false); |
172 | 172 |
173 Column result; | 173 Column result; |
174 | 174 |
175 result.clear(); | 175 result.clear(); |
176 size_t h = getHeight(); | 176 int h = getHeight(); |
177 result.reserve(h); | 177 result.reserve(h); |
178 | 178 |
179 #ifdef __GNUC__ | 179 #ifdef __GNUC__ |
180 float magnitudes[h]; | 180 float magnitudes[h]; |
181 #else | 181 #else |
182 float *magnitudes = (float *)alloca(h * sizeof(float)); | 182 float *magnitudes = (float *)alloca(h * sizeof(float)); |
183 #endif | 183 #endif |
184 | 184 |
185 if (m_server->getMagnitudesAt(x << m_xshift, magnitudes)) { | 185 if (m_server->getMagnitudesAt(x << m_xshift, magnitudes)) { |
186 | 186 |
187 for (size_t y = 0; y < h; ++y) { | 187 for (int y = 0; y < h; ++y) { |
188 result.push_back(magnitudes[y]); | 188 result.push_back(magnitudes[y]); |
189 } | 189 } |
190 | 190 |
191 } else { | 191 } else { |
192 for (size_t i = 0; i < h; ++i) result.push_back(0.f); | 192 for (int i = 0; i < h; ++i) result.push_back(0.f); |
193 } | 193 } |
194 | 194 |
195 return result; | 195 return result; |
196 } | 196 } |
197 | 197 |
198 QString | 198 QString |
199 FFTModel::getBinName(size_t n) const | 199 FFTModel::getBinName(int n) const |
200 { | 200 { |
201 size_t sr = getSampleRate(); | 201 int sr = getSampleRate(); |
202 if (!sr) return ""; | 202 if (!sr) return ""; |
203 QString name = tr("%1 Hz").arg((n * sr) / ((getHeight()-1) * 2)); | 203 QString name = tr("%1 Hz").arg((n * sr) / ((getHeight()-1) * 2)); |
204 return name; | 204 return name; |
205 } | 205 } |
206 | 206 |
207 bool | 207 bool |
208 FFTModel::estimateStableFrequency(size_t x, size_t y, float &frequency) | 208 FFTModel::estimateStableFrequency(int x, int y, float &frequency) |
209 { | 209 { |
210 if (!isOK()) return false; | 210 if (!isOK()) return false; |
211 | 211 |
212 size_t sampleRate = m_server->getModel()->getSampleRate(); | 212 int sampleRate = m_server->getModel()->getSampleRate(); |
213 | 213 |
214 size_t fftSize = m_server->getFFTSize() >> m_yshift; | 214 int fftSize = m_server->getFFTSize() >> m_yshift; |
215 frequency = (float(y) * sampleRate) / fftSize; | 215 frequency = (float(y) * sampleRate) / fftSize; |
216 | 216 |
217 if (x+1 >= getWidth()) return false; | 217 if (x+1 >= getWidth()) return false; |
218 | 218 |
219 // At frequency f, a phase shift of 2pi (one cycle) happens in 1/f sec. | 219 // At frequency f, a phase shift of 2pi (one cycle) happens in 1/f sec. |
226 // = 2pi * (h * b) / w. | 226 // = 2pi * (h * b) / w. |
227 | 227 |
228 float oldPhase = getPhaseAt(x, y); | 228 float oldPhase = getPhaseAt(x, y); |
229 float newPhase = getPhaseAt(x+1, y); | 229 float newPhase = getPhaseAt(x+1, y); |
230 | 230 |
231 size_t incr = getResolution(); | 231 int incr = getResolution(); |
232 | 232 |
233 float expectedPhase = oldPhase + (2.0 * M_PI * y * incr) / fftSize; | 233 float expectedPhase = oldPhase + (2.0 * M_PI * y * incr) / fftSize; |
234 | 234 |
235 float phaseError = princargf(newPhase - expectedPhase); | 235 float phaseError = princargf(newPhase - expectedPhase); |
236 | 236 |
245 | 245 |
246 return true; | 246 return true; |
247 } | 247 } |
248 | 248 |
249 FFTModel::PeakLocationSet | 249 FFTModel::PeakLocationSet |
250 FFTModel::getPeaks(PeakPickType type, size_t x, size_t ymin, size_t ymax) | 250 FFTModel::getPeaks(PeakPickType type, int x, int ymin, int ymax) |
251 { | 251 { |
252 Profiler profiler("FFTModel::getPeaks"); | 252 Profiler profiler("FFTModel::getPeaks"); |
253 | 253 |
254 FFTModel::PeakLocationSet peaks; | 254 FFTModel::PeakLocationSet peaks; |
255 if (!isOK()) return peaks; | 255 if (!isOK()) return peaks; |
268 float values[n]; | 268 float values[n]; |
269 #else | 269 #else |
270 float *values = (float *)alloca(n * sizeof(float)); | 270 float *values = (float *)alloca(n * sizeof(float)); |
271 #endif | 271 #endif |
272 getMagnitudesAt(x, values, minbin, maxbin - minbin + 1); | 272 getMagnitudesAt(x, values, minbin, maxbin - minbin + 1); |
273 for (size_t bin = ymin; bin <= ymax; ++bin) { | 273 for (int bin = ymin; bin <= ymax; ++bin) { |
274 if (bin == minbin || bin == maxbin) continue; | 274 if (bin == minbin || bin == maxbin) continue; |
275 if (values[bin - minbin] > values[bin - minbin - 1] && | 275 if (values[bin - minbin] > values[bin - minbin - 1] && |
276 values[bin - minbin] > values[bin - minbin + 1]) { | 276 values[bin - minbin] > values[bin - minbin + 1]) { |
277 peaks.insert(bin); | 277 peaks.insert(bin); |
278 } | 278 } |
289 // For peak picking we use a moving median window, picking the | 289 // For peak picking we use a moving median window, picking the |
290 // highest value within each continuous region of values that | 290 // highest value within each continuous region of values that |
291 // exceed the median. For pitch adaptivity, we adjust the window | 291 // exceed the median. For pitch adaptivity, we adjust the window |
292 // size to a roughly constant pitch range (about four tones). | 292 // size to a roughly constant pitch range (about four tones). |
293 | 293 |
294 size_t sampleRate = getSampleRate(); | 294 int sampleRate = getSampleRate(); |
295 | 295 |
296 std::deque<float> window; | 296 std::deque<float> window; |
297 std::vector<size_t> inrange; | 297 std::vector<int> inrange; |
298 float dist = 0.5; | 298 float dist = 0.5; |
299 | 299 |
300 size_t medianWinSize = getPeakPickWindowSize(type, sampleRate, ymin, dist); | 300 int medianWinSize = getPeakPickWindowSize(type, sampleRate, ymin, dist); |
301 size_t halfWin = medianWinSize/2; | 301 int halfWin = medianWinSize/2; |
302 | 302 |
303 size_t binmin; | 303 int binmin; |
304 if (ymin > halfWin) binmin = ymin - halfWin; | 304 if (ymin > halfWin) binmin = ymin - halfWin; |
305 else binmin = 0; | 305 else binmin = 0; |
306 | 306 |
307 size_t binmax; | 307 int binmax; |
308 if (ymax + halfWin < values.size()) binmax = ymax + halfWin; | 308 if (ymax + halfWin < values.size()) binmax = ymax + halfWin; |
309 else binmax = values.size()-1; | 309 else binmax = values.size()-1; |
310 | 310 |
311 size_t prevcentre = 0; | 311 int prevcentre = 0; |
312 | 312 |
313 for (size_t bin = binmin; bin <= binmax; ++bin) { | 313 for (int bin = binmin; bin <= binmax; ++bin) { |
314 | 314 |
315 float value = values[bin]; | 315 float value = values[bin]; |
316 | 316 |
317 window.push_back(value); | 317 window.push_back(value); |
318 | 318 |
319 // so-called median will actually be the dist*100'th percentile | 319 // so-called median will actually be the dist*100'th percentile |
320 medianWinSize = getPeakPickWindowSize(type, sampleRate, bin, dist); | 320 medianWinSize = getPeakPickWindowSize(type, sampleRate, bin, dist); |
321 halfWin = medianWinSize/2; | 321 halfWin = medianWinSize/2; |
322 | 322 |
323 while (window.size() > medianWinSize) { | 323 while ((int)window.size() > medianWinSize) { |
324 window.pop_front(); | 324 window.pop_front(); |
325 } | 325 } |
326 | 326 |
327 size_t actualSize = window.size(); | 327 int actualSize = window.size(); |
328 | 328 |
329 if (type == MajorPitchAdaptivePeaks) { | 329 if (type == MajorPitchAdaptivePeaks) { |
330 if (ymax + halfWin < values.size()) binmax = ymax + halfWin; | 330 if (ymax + halfWin < values.size()) binmax = ymax + halfWin; |
331 else binmax = values.size()-1; | 331 else binmax = values.size()-1; |
332 } | 332 } |
333 | 333 |
334 std::deque<float> sorted(window); | 334 std::deque<float> sorted(window); |
335 std::sort(sorted.begin(), sorted.end()); | 335 std::sort(sorted.begin(), sorted.end()); |
336 float median = sorted[int(sorted.size() * dist)]; | 336 float median = sorted[int(sorted.size() * dist)]; |
337 | 337 |
338 size_t centrebin = 0; | 338 int centrebin = 0; |
339 if (bin > actualSize/2) centrebin = bin - actualSize/2; | 339 if (bin > actualSize/2) centrebin = bin - actualSize/2; |
340 | 340 |
341 while (centrebin > prevcentre || bin == binmin) { | 341 while (centrebin > prevcentre || bin == binmin) { |
342 | 342 |
343 if (centrebin > prevcentre) ++prevcentre; | 343 if (centrebin > prevcentre) ++prevcentre; |
348 inrange.push_back(centrebin); | 348 inrange.push_back(centrebin); |
349 } | 349 } |
350 | 350 |
351 if (centre <= median || centrebin+1 == values.size()) { | 351 if (centre <= median || centrebin+1 == values.size()) { |
352 if (!inrange.empty()) { | 352 if (!inrange.empty()) { |
353 size_t peakbin = 0; | 353 int peakbin = 0; |
354 float peakval = 0.f; | 354 float peakval = 0.f; |
355 for (size_t i = 0; i < inrange.size(); ++i) { | 355 for (int i = 0; i < (int)inrange.size(); ++i) { |
356 if (i == 0 || values[inrange[i]] > peakval) { | 356 if (i == 0 || values[inrange[i]] > peakval) { |
357 peakval = values[inrange[i]]; | 357 peakval = values[inrange[i]]; |
358 peakbin = inrange[i]; | 358 peakbin = inrange[i]; |
359 } | 359 } |
360 } | 360 } |
370 } | 370 } |
371 | 371 |
372 return peaks; | 372 return peaks; |
373 } | 373 } |
374 | 374 |
375 size_t | 375 int |
376 FFTModel::getPeakPickWindowSize(PeakPickType type, size_t sampleRate, | 376 FFTModel::getPeakPickWindowSize(PeakPickType type, int sampleRate, |
377 size_t bin, float &percentile) const | 377 int bin, float &percentile) const |
378 { | 378 { |
379 percentile = 0.5; | 379 percentile = 0.5; |
380 if (type == MajorPeaks) return 10; | 380 if (type == MajorPeaks) return 10; |
381 if (bin == 0) return 3; | 381 if (bin == 0) return 3; |
382 | 382 |
383 size_t fftSize = m_server->getFFTSize() >> m_yshift; | 383 int fftSize = m_server->getFFTSize() >> m_yshift; |
384 float binfreq = (sampleRate * bin) / fftSize; | 384 float binfreq = (sampleRate * bin) / fftSize; |
385 float hifreq = Pitch::getFrequencyForPitch(73, 0, binfreq); | 385 float hifreq = Pitch::getFrequencyForPitch(73, 0, binfreq); |
386 | 386 |
387 int hibin = lrintf((hifreq * fftSize) / sampleRate); | 387 int hibin = lrintf((hifreq * fftSize) / sampleRate); |
388 int medianWinSize = hibin - bin; | 388 int medianWinSize = hibin - bin; |
392 | 392 |
393 return medianWinSize; | 393 return medianWinSize; |
394 } | 394 } |
395 | 395 |
396 FFTModel::PeakSet | 396 FFTModel::PeakSet |
397 FFTModel::getPeakFrequencies(PeakPickType type, size_t x, | 397 FFTModel::getPeakFrequencies(PeakPickType type, int x, |
398 size_t ymin, size_t ymax) | 398 int ymin, int ymax) |
399 { | 399 { |
400 Profiler profiler("FFTModel::getPeakFrequencies"); | 400 Profiler profiler("FFTModel::getPeakFrequencies"); |
401 | 401 |
402 PeakSet peaks; | 402 PeakSet peaks; |
403 if (!isOK()) return peaks; | 403 if (!isOK()) return peaks; |
404 PeakLocationSet locations = getPeaks(type, x, ymin, ymax); | 404 PeakLocationSet locations = getPeaks(type, x, ymin, ymax); |
405 | 405 |
406 size_t sampleRate = getSampleRate(); | 406 int sampleRate = getSampleRate(); |
407 size_t fftSize = m_server->getFFTSize() >> m_yshift; | 407 int fftSize = m_server->getFFTSize() >> m_yshift; |
408 size_t incr = getResolution(); | 408 int incr = getResolution(); |
409 | 409 |
410 // This duplicates some of the work of estimateStableFrequency to | 410 // This duplicates some of the work of estimateStableFrequency to |
411 // allow us to retrieve the phases in two separate vertical | 411 // allow us to retrieve the phases in two separate vertical |
412 // columns, instead of jumping back and forth between columns x and | 412 // columns, instead of jumping back and forth between columns x and |
413 // x+1, which may be significantly slower if re-seeking is needed | 413 // x+1, which may be significantly slower if re-seeking is needed |
416 for (PeakLocationSet::iterator i = locations.begin(); | 416 for (PeakLocationSet::iterator i = locations.begin(); |
417 i != locations.end(); ++i) { | 417 i != locations.end(); ++i) { |
418 phases.push_back(getPhaseAt(x, *i)); | 418 phases.push_back(getPhaseAt(x, *i)); |
419 } | 419 } |
420 | 420 |
421 size_t phaseIndex = 0; | 421 int phaseIndex = 0; |
422 for (PeakLocationSet::iterator i = locations.begin(); | 422 for (PeakLocationSet::iterator i = locations.begin(); |
423 i != locations.end(); ++i) { | 423 i != locations.end(); ++i) { |
424 float oldPhase = phases[phaseIndex]; | 424 float oldPhase = phases[phaseIndex]; |
425 float newPhase = getPhaseAt(x+1, *i); | 425 float newPhase = getPhaseAt(x+1, *i); |
426 float expectedPhase = oldPhase + (2.0 * M_PI * *i * incr) / fftSize; | 426 float expectedPhase = oldPhase + (2.0 * M_PI * *i * incr) / fftSize; |