Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 37:21d061e66177
* Make the frequency estimation mode in the spectrogram layer actually useful,
and make sure it gets mostly the right results... Still some tidying to do
in here.
author | Chris Cannam |
---|---|
date | Wed, 22 Feb 2006 17:45:18 +0000 |
parents | c28ebb4ba4de |
children | beb801473743 |
comparison
equal
deleted
inserted
replaced
36:c28ebb4ba4de | 37:21d061e66177 |
---|---|
37 m_channel(0), | 37 m_channel(0), |
38 m_windowSize(1024), | 38 m_windowSize(1024), |
39 m_windowType(HanningWindow), | 39 m_windowType(HanningWindow), |
40 m_windowOverlap(50), | 40 m_windowOverlap(50), |
41 m_gain(1.0), | 41 m_gain(1.0), |
42 m_threshold(0.0), | |
42 m_colourRotation(0), | 43 m_colourRotation(0), |
44 m_minFrequency(0), | |
43 m_maxFrequency(8000), | 45 m_maxFrequency(8000), |
44 m_colourScale(dBColourScale), | 46 m_colourScale(dBColourScale), |
45 m_colourScheme(DefaultColours), | 47 m_colourScheme(DefaultColours), |
46 m_frequencyScale(LinearFrequencyScale), | 48 m_frequencyScale(LinearFrequencyScale), |
47 m_frequencyAdjustment(RawFrequency), | 49 m_binDisplay(AllBins), |
48 m_normalizeColumns(false), | 50 m_normalizeColumns(false), |
49 m_cache(0), | 51 m_cache(0), |
50 m_phaseAdjustCache(0), | 52 m_phaseAdjustCache(0), |
51 m_cacheInvalid(true), | 53 m_cacheInvalid(true), |
52 m_pixmapCache(0), | 54 m_pixmapCache(0), |
60 setWindowSize(8192); | 62 setWindowSize(8192); |
61 setWindowOverlap(90); | 63 setWindowOverlap(90); |
62 setWindowType(ParzenWindow); | 64 setWindowType(ParzenWindow); |
63 setMaxFrequency(1000); | 65 setMaxFrequency(1000); |
64 setColourScale(LinearColourScale); | 66 setColourScale(LinearColourScale); |
67 } else if (config == MelodicPeaks) { | |
68 setWindowSize(4096); | |
69 setWindowOverlap(90); | |
70 setWindowType(BlackmanWindow); | |
71 setMaxFrequency(1500); | |
72 setMinFrequency(40); | |
73 setFrequencyScale(LogFrequencyScale); | |
74 setColourScale(dBColourScale); | |
75 setBinDisplay(PeakFrequencies); | |
76 setNormalizeColumns(true); | |
65 } | 77 } |
66 | 78 |
67 if (m_view) m_view->setLightBackground(false); | 79 if (m_view) m_view->setLightBackground(false); |
68 m_view->addLayer(this); | 80 m_view->addLayer(this); |
69 } | 81 } |
124 list.push_back(tr("Colour Scale")); | 136 list.push_back(tr("Colour Scale")); |
125 list.push_back(tr("Window Type")); | 137 list.push_back(tr("Window Type")); |
126 list.push_back(tr("Window Size")); | 138 list.push_back(tr("Window Size")); |
127 list.push_back(tr("Window Overlap")); | 139 list.push_back(tr("Window Overlap")); |
128 list.push_back(tr("Normalize")); | 140 list.push_back(tr("Normalize")); |
141 list.push_back(tr("Bin Display")); | |
142 list.push_back(tr("Threshold")); | |
129 list.push_back(tr("Gain")); | 143 list.push_back(tr("Gain")); |
130 list.push_back(tr("Colour Rotation")); | 144 list.push_back(tr("Colour Rotation")); |
145 list.push_back(tr("Min Frequency")); | |
131 list.push_back(tr("Max Frequency")); | 146 list.push_back(tr("Max Frequency")); |
132 list.push_back(tr("Frequency Scale")); | 147 list.push_back(tr("Frequency Scale")); |
133 list.push_back(tr("Frequency Adjustment")); | |
134 return list; | 148 return list; |
135 } | 149 } |
136 | 150 |
137 Layer::PropertyType | 151 Layer::PropertyType |
138 SpectrogramLayer::getPropertyType(const PropertyName &name) const | 152 SpectrogramLayer::getPropertyType(const PropertyName &name) const |
139 { | 153 { |
140 if (name == tr("Gain")) return RangeProperty; | 154 if (name == tr("Gain")) return RangeProperty; |
141 if (name == tr("Colour Rotation")) return RangeProperty; | 155 if (name == tr("Colour Rotation")) return RangeProperty; |
142 if (name == tr("Normalize")) return ToggleProperty; | 156 if (name == tr("Normalize")) return ToggleProperty; |
157 if (name == tr("Threshold")) return RangeProperty; | |
143 return ValueProperty; | 158 return ValueProperty; |
144 } | 159 } |
145 | 160 |
146 QString | 161 QString |
147 SpectrogramLayer::getPropertyGroupName(const PropertyName &name) const | 162 SpectrogramLayer::getPropertyGroupName(const PropertyName &name) const |
150 name == tr("Window Type") || | 165 name == tr("Window Type") || |
151 name == tr("Window Overlap")) return tr("Window"); | 166 name == tr("Window Overlap")) return tr("Window"); |
152 if (name == tr("Colour") || | 167 if (name == tr("Colour") || |
153 name == tr("Colour Rotation")) return tr("Colour"); | 168 name == tr("Colour Rotation")) return tr("Colour"); |
154 if (name == tr("Gain") || | 169 if (name == tr("Gain") || |
170 name == tr("Threshold") || | |
155 name == tr("Normalize") || | 171 name == tr("Normalize") || |
172 name == tr("Bin Display") || | |
156 name == tr("Colour Scale")) return tr("Scale"); | 173 name == tr("Colour Scale")) return tr("Scale"); |
157 if (name == tr("Max Frequency") || | 174 if (name == tr("Max Frequency") || |
175 name == tr("Min Frequency") || | |
158 name == tr("Frequency Scale") || | 176 name == tr("Frequency Scale") || |
159 name == tr("Frequency Adjustment")) return tr("Frequency"); | 177 name == tr("Frequency Adjustment")) return tr("Range"); |
160 return QString(); | 178 return QString(); |
161 } | 179 } |
162 | 180 |
163 int | 181 int |
164 SpectrogramLayer::getPropertyRangeAndValue(const PropertyName &name, | 182 SpectrogramLayer::getPropertyRangeAndValue(const PropertyName &name, |
174 | 192 |
175 *min = -50; | 193 *min = -50; |
176 *max = 50; | 194 *max = 50; |
177 | 195 |
178 deft = lrint(log10(m_gain) * 20.0); | 196 deft = lrint(log10(m_gain) * 20.0); |
197 if (deft < *min) deft = *min; | |
198 if (deft > *max) deft = *max; | |
199 | |
200 } else if (name == tr("Threshold")) { | |
201 | |
202 *min = -50; | |
203 *max = 0; | |
204 | |
205 deft = lrintf(AudioLevel::multiplier_to_dB(m_threshold)); | |
179 if (deft < *min) deft = *min; | 206 if (deft < *min) deft = *min; |
180 if (deft > *max) deft = *max; | 207 if (deft > *max) deft = *max; |
181 | 208 |
182 } else if (name == tr("Colour Rotation")) { | 209 } else if (name == tr("Colour Rotation")) { |
183 | 210 |
221 *min = 0; | 248 *min = 0; |
222 *max = 4; | 249 *max = 4; |
223 | 250 |
224 deft = m_windowOverlap / 25; | 251 deft = m_windowOverlap / 25; |
225 if (m_windowOverlap == 90) deft = 4; | 252 if (m_windowOverlap == 90) deft = 4; |
253 | |
254 } else if (name == tr("Min Frequency")) { | |
255 | |
256 *min = 0; | |
257 *max = 9; | |
258 | |
259 switch (m_minFrequency) { | |
260 case 0: default: deft = 0; break; | |
261 case 10: deft = 1; break; | |
262 case 20: deft = 2; break; | |
263 case 40: deft = 3; break; | |
264 case 100: deft = 4; break; | |
265 case 250: deft = 5; break; | |
266 case 500: deft = 6; break; | |
267 case 1000: deft = 7; break; | |
268 case 4000: deft = 8; break; | |
269 case 10000: deft = 9; break; | |
270 } | |
226 | 271 |
227 } else if (name == tr("Max Frequency")) { | 272 } else if (name == tr("Max Frequency")) { |
228 | 273 |
229 *min = 0; | 274 *min = 0; |
230 *max = 9; | 275 *max = 9; |
246 | 291 |
247 *min = 0; | 292 *min = 0; |
248 *max = 1; | 293 *max = 1; |
249 deft = (int)m_frequencyScale; | 294 deft = (int)m_frequencyScale; |
250 | 295 |
251 } else if (name == tr("Frequency Adjustment")) { | 296 } else if (name == tr("Bin Display")) { |
252 | 297 |
253 *min = 0; | 298 *min = 0; |
254 *max = 2; | 299 *max = 2; |
255 deft = (int)m_frequencyAdjustment; | 300 deft = (int)m_binDisplay; |
256 | 301 |
257 } else if (name == tr("Normalize")) { | 302 } else if (name == tr("Normalize")) { |
258 | 303 |
259 deft = (m_normalizeColumns ? 1 : 0); | 304 deft = (m_normalizeColumns ? 1 : 0); |
260 | 305 |
281 } | 326 } |
282 } | 327 } |
283 if (name == tr("Colour Scale")) { | 328 if (name == tr("Colour Scale")) { |
284 switch (value) { | 329 switch (value) { |
285 default: | 330 default: |
286 case 0: return tr("Level Linear"); | 331 case 0: return tr("Linear"); |
287 case 1: return tr("Level Meter"); | 332 case 1: return tr("Meter"); |
288 case 2: return tr("Level dB"); | 333 case 2: return tr("dB"); |
289 case 3: return tr("Phase"); | 334 case 3: return tr("Phase"); |
290 } | 335 } |
291 } | 336 } |
292 if (name == tr("Window Type")) { | 337 if (name == tr("Window Type")) { |
293 switch ((WindowType)value) { | 338 switch ((WindowType)value) { |
310 case 0: return tr("0%"); | 355 case 0: return tr("0%"); |
311 case 1: return tr("25%"); | 356 case 1: return tr("25%"); |
312 case 2: return tr("50%"); | 357 case 2: return tr("50%"); |
313 case 3: return tr("75%"); | 358 case 3: return tr("75%"); |
314 case 4: return tr("90%"); | 359 case 4: return tr("90%"); |
360 } | |
361 } | |
362 if (name == tr("Min Frequency")) { | |
363 switch (value) { | |
364 default: | |
365 case 0: return tr("None"); | |
366 case 1: return tr("10 Hz"); | |
367 case 2: return tr("20 Hz"); | |
368 case 3: return tr("40 Hz"); | |
369 case 4: return tr("100 Hz"); | |
370 case 5: return tr("250 Hz"); | |
371 case 6: return tr("500 Hz"); | |
372 case 7: return tr("1 KHz"); | |
373 case 8: return tr("4 KHz"); | |
374 case 9: return tr("10 KHz"); | |
315 } | 375 } |
316 } | 376 } |
317 if (name == tr("Max Frequency")) { | 377 if (name == tr("Max Frequency")) { |
318 switch (value) { | 378 switch (value) { |
319 default: | 379 default: |
334 default: | 394 default: |
335 case 0: return tr("Linear"); | 395 case 0: return tr("Linear"); |
336 case 1: return tr("Log"); | 396 case 1: return tr("Log"); |
337 } | 397 } |
338 } | 398 } |
339 if (name == tr("Frequency Adjustment")) { | 399 if (name == tr("Bin Display")) { |
340 switch (value) { | 400 switch (value) { |
341 default: | 401 default: |
342 case 0: return tr("Bins"); | 402 case 0: return tr("All Bins"); |
343 case 1: return tr("Pitches"); | 403 case 1: return tr("Peak Bins"); |
344 case 2: return tr("Peaks"); | 404 case 2: return tr("Frequencies"); |
345 } | 405 } |
346 } | 406 } |
347 return tr("<unknown>"); | 407 return tr("<unknown>"); |
348 } | 408 } |
349 | 409 |
350 void | 410 void |
351 SpectrogramLayer::setProperty(const PropertyName &name, int value) | 411 SpectrogramLayer::setProperty(const PropertyName &name, int value) |
352 { | 412 { |
353 if (name == tr("Gain")) { | 413 if (name == tr("Gain")) { |
354 setGain(pow(10, float(value)/20.0)); | 414 setGain(pow(10, float(value)/20.0)); |
415 } else if (name == tr("Threshold")) { | |
416 if (value == -50) setThreshold(0.0); | |
417 else setThreshold(AudioLevel::dB_to_multiplier(value)); | |
355 } else if (name == tr("Colour Rotation")) { | 418 } else if (name == tr("Colour Rotation")) { |
356 setColourRotation(value); | 419 setColourRotation(value); |
357 } else if (name == tr("Colour")) { | 420 } else if (name == tr("Colour")) { |
358 if (m_view) m_view->setLightBackground(value == 2); | 421 if (m_view) m_view->setLightBackground(value == 2); |
359 switch (value) { | 422 switch (value) { |
370 } else if (name == tr("Window Size")) { | 433 } else if (name == tr("Window Size")) { |
371 setWindowSize(32 << value); | 434 setWindowSize(32 << value); |
372 } else if (name == tr("Window Overlap")) { | 435 } else if (name == tr("Window Overlap")) { |
373 if (value == 4) setWindowOverlap(90); | 436 if (value == 4) setWindowOverlap(90); |
374 else setWindowOverlap(25 * value); | 437 else setWindowOverlap(25 * value); |
438 } else if (name == tr("Min Frequency")) { | |
439 switch (value) { | |
440 default: | |
441 case 0: setMinFrequency(0); break; | |
442 case 1: setMinFrequency(10); break; | |
443 case 2: setMinFrequency(20); break; | |
444 case 3: setMinFrequency(40); break; | |
445 case 4: setMinFrequency(100); break; | |
446 case 5: setMinFrequency(250); break; | |
447 case 6: setMinFrequency(500); break; | |
448 case 7: setMinFrequency(1000); break; | |
449 case 8: setMinFrequency(4000); break; | |
450 case 9: setMinFrequency(10000); break; | |
451 } | |
375 } else if (name == tr("Max Frequency")) { | 452 } else if (name == tr("Max Frequency")) { |
376 switch (value) { | 453 switch (value) { |
377 case 0: setMaxFrequency(500); break; | 454 case 0: setMaxFrequency(500); break; |
378 case 1: setMaxFrequency(1000); break; | 455 case 1: setMaxFrequency(1000); break; |
379 case 2: setMaxFrequency(1500); break; | 456 case 2: setMaxFrequency(1500); break; |
398 switch (value) { | 475 switch (value) { |
399 default: | 476 default: |
400 case 0: setFrequencyScale(LinearFrequencyScale); break; | 477 case 0: setFrequencyScale(LinearFrequencyScale); break; |
401 case 1: setFrequencyScale(LogFrequencyScale); break; | 478 case 1: setFrequencyScale(LogFrequencyScale); break; |
402 } | 479 } |
403 } else if (name == tr("Frequency Adjustment")) { | 480 } else if (name == tr("Bin Display")) { |
404 switch (value) { | 481 switch (value) { |
405 default: | 482 default: |
406 case 0: setFrequencyAdjustment(RawFrequency); break; | 483 case 0: setBinDisplay(AllBins); break; |
407 case 1: setFrequencyAdjustment(PhaseAdjustedFrequency); break; | 484 case 1: setBinDisplay(PeakBins); break; |
408 case 2: setFrequencyAdjustment(PhaseAdjustedPeaks); break; | 485 case 2: setBinDisplay(PeakFrequencies); break; |
409 } | 486 } |
410 } else if (name == "Normalize") { | 487 } else if (name == "Normalize") { |
411 setNormalizeColumns(value ? true : false); | 488 setNormalizeColumns(value ? true : false); |
412 } | 489 } |
413 } | 490 } |
531 { | 608 { |
532 return m_gain; | 609 return m_gain; |
533 } | 610 } |
534 | 611 |
535 void | 612 void |
536 SpectrogramLayer::setMaxFrequency(size_t mf) | 613 SpectrogramLayer::setThreshold(float threshold) |
537 { | 614 { |
538 if (m_maxFrequency == mf) return; | 615 if (m_threshold == threshold) return; //!!! inadequate for floats! |
616 | |
617 m_mutex.lock(); | |
618 m_cacheInvalid = true; | |
619 m_pixmapCacheInvalid = true; | |
620 | |
621 m_threshold = threshold; | |
622 | |
623 m_mutex.unlock(); | |
624 | |
625 emit layerParametersChanged(); | |
626 | |
627 fillCache(); | |
628 } | |
629 | |
630 float | |
631 SpectrogramLayer::getThreshold() const | |
632 { | |
633 return m_threshold; | |
634 } | |
635 | |
636 void | |
637 SpectrogramLayer::setMinFrequency(size_t mf) | |
638 { | |
639 if (m_minFrequency == mf) return; | |
539 | 640 |
540 m_mutex.lock(); | 641 m_mutex.lock(); |
541 // don't need to invalidate main cache here | 642 // don't need to invalidate main cache here |
542 m_pixmapCacheInvalid = true; | 643 m_pixmapCacheInvalid = true; |
543 | 644 |
544 m_maxFrequency = mf; | 645 m_minFrequency = mf; |
545 | 646 |
546 m_mutex.unlock(); | 647 m_mutex.unlock(); |
547 | 648 |
548 emit layerParametersChanged(); | 649 emit layerParametersChanged(); |
549 } | 650 } |
550 | 651 |
551 size_t | 652 size_t |
552 SpectrogramLayer::getMaxFrequency() const | 653 SpectrogramLayer::getMinFrequency() const |
553 { | 654 { |
554 return m_maxFrequency; | 655 return m_minFrequency; |
555 } | 656 } |
556 | 657 |
557 void | 658 void |
558 SpectrogramLayer::setColourRotation(int r) | 659 SpectrogramLayer::setMaxFrequency(size_t mf) |
559 { | 660 { |
661 if (m_maxFrequency == mf) return; | |
662 | |
560 m_mutex.lock(); | 663 m_mutex.lock(); |
561 // don't need to invalidate main cache here | 664 // don't need to invalidate main cache here |
562 m_pixmapCacheInvalid = true; | 665 m_pixmapCacheInvalid = true; |
666 | |
667 m_maxFrequency = mf; | |
668 | |
669 m_mutex.unlock(); | |
670 | |
671 emit layerParametersChanged(); | |
672 } | |
673 | |
674 size_t | |
675 SpectrogramLayer::getMaxFrequency() const | |
676 { | |
677 return m_maxFrequency; | |
678 } | |
679 | |
680 void | |
681 SpectrogramLayer::setColourRotation(int r) | |
682 { | |
683 m_mutex.lock(); | |
684 // don't need to invalidate main cache here | |
685 m_pixmapCacheInvalid = true; | |
563 | 686 |
564 if (r < 0) r = 0; | 687 if (r < 0) r = 0; |
565 if (r > 256) r = 256; | 688 if (r > 256) r = 256; |
566 int distance = r - m_colourRotation; | 689 int distance = r - m_colourRotation; |
567 | 690 |
643 { | 766 { |
644 return m_frequencyScale; | 767 return m_frequencyScale; |
645 } | 768 } |
646 | 769 |
647 void | 770 void |
648 SpectrogramLayer::setFrequencyAdjustment(FrequencyAdjustment frequencyAdjustment) | 771 SpectrogramLayer::setBinDisplay(BinDisplay binDisplay) |
649 { | 772 { |
650 if (m_frequencyAdjustment == frequencyAdjustment) return; | 773 if (m_binDisplay == binDisplay) return; |
651 | 774 |
652 m_mutex.lock(); | 775 m_mutex.lock(); |
653 | 776 |
654 m_cacheInvalid = true; | 777 m_cacheInvalid = true; |
655 m_pixmapCacheInvalid = true; | 778 m_pixmapCacheInvalid = true; |
656 | 779 |
657 m_frequencyAdjustment = frequencyAdjustment; | 780 m_binDisplay = binDisplay; |
658 | 781 |
659 m_mutex.unlock(); | 782 m_mutex.unlock(); |
660 | 783 |
661 fillCache(); | 784 fillCache(); |
662 | 785 |
663 emit layerParametersChanged(); | 786 emit layerParametersChanged(); |
664 } | 787 } |
665 | 788 |
666 SpectrogramLayer::FrequencyAdjustment | 789 SpectrogramLayer::BinDisplay |
667 SpectrogramLayer::getFrequencyAdjustment() const | 790 SpectrogramLayer::getBinDisplay() const |
668 { | 791 { |
669 return m_frequencyAdjustment; | 792 return m_binDisplay; |
670 } | 793 } |
671 | 794 |
672 void | 795 void |
673 SpectrogramLayer::setNormalizeColumns(bool n) | 796 SpectrogramLayer::setNormalizeColumns(bool n) |
674 { | 797 { |
806 { | 929 { |
807 if (m_cacheInvalid || !m_cache) return; | 930 if (m_cacheInvalid || !m_cache) return; |
808 | 931 |
809 int formerRotation = m_colourRotation; | 932 int formerRotation = m_colourRotation; |
810 | 933 |
811 m_cache->setColour(0, Qt::white); | 934 m_cache->setColour(NO_VALUE, Qt::white); |
812 | 935 |
813 for (int pixel = 1; pixel < 256; ++pixel) { | 936 for (int pixel = 1; pixel < 256; ++pixel) { |
814 | 937 |
815 QColor colour; | 938 QColor colour; |
816 int hue, px; | 939 int hue, px; |
864 { | 987 { |
865 if (!m_cache) return; | 988 if (!m_cache) return; |
866 | 989 |
867 QColor newPixels[256]; | 990 QColor newPixels[256]; |
868 | 991 |
869 newPixels[0] = m_cache->getColour(0); | 992 newPixels[NO_VALUE] = m_cache->getColour(NO_VALUE); |
870 | 993 |
871 for (int pixel = 1; pixel < 256; ++pixel) { | 994 for (int pixel = 1; pixel < 256; ++pixel) { |
872 int target = pixel + distance; | 995 int target = pixel + distance; |
873 while (target < 1) target += 255; | 996 while (target < 1) target += 255; |
874 while (target > 255) target -= 255; | 997 while (target > 255) target -= 255; |
889 const Window<double> &windower, | 1012 const Window<double> &windower, |
890 bool resetStoredPhase) const | 1013 bool resetStoredPhase) const |
891 { | 1014 { |
892 static std::vector<double> storedPhase; | 1015 static std::vector<double> storedPhase; |
893 | 1016 |
894 bool phaseAdjust = | 1017 bool phaseAdjust = (m_binDisplay == PeakFrequencies); |
895 (m_frequencyAdjustment == PhaseAdjustedFrequency || | |
896 m_frequencyAdjustment == PhaseAdjustedPeaks); | |
897 bool haveStoredPhase = true; | 1018 bool haveStoredPhase = true; |
898 size_t sampleRate = 0; | 1019 size_t sampleRate = 0; |
899 | |
900 static int counter = 0; | |
901 | 1020 |
902 if (phaseAdjust) { | 1021 if (phaseAdjust) { |
903 if (resetStoredPhase || (storedPhase.size() != windowSize / 2)) { | 1022 if (resetStoredPhase || (storedPhase.size() != windowSize / 2)) { |
904 haveStoredPhase = false; | 1023 haveStoredPhase = false; |
905 storedPhase.clear(); | 1024 storedPhase.clear(); |
906 for (size_t i = 0; i < windowSize / 2; ++i) { | 1025 for (size_t i = 0; i < windowSize / 2; ++i) { |
907 storedPhase.push_back(0.0); | 1026 storedPhase.push_back(0.0); |
908 } | 1027 } |
909 counter = 0; | 1028 } |
910 } | |
911 ++counter; | |
912 sampleRate = m_model->getSampleRate(); | 1029 sampleRate = m_model->getSampleRate(); |
913 } | 1030 } |
914 | 1031 |
915 int startFrame = increment * column; | 1032 int startFrame = increment * column; |
916 int endFrame = startFrame + windowSize; | 1033 int endFrame = startFrame + windowSize; |
937 for (size_t i = 0; i < windowSize; ++i) { | 1054 for (size_t i = 0; i < windowSize; ++i) { |
938 input[i] *= m_gain; | 1055 input[i] *= m_gain; |
939 } | 1056 } |
940 } | 1057 } |
941 | 1058 |
1059 if (m_channel == -1) { | |
1060 int channels = m_model->getChannelCount(); | |
1061 if (channels > 1) { | |
1062 for (size_t i = 0; i < windowSize; ++i) { | |
1063 input[i] /= channels; | |
1064 } | |
1065 } | |
1066 } | |
1067 | |
942 windower.cut(input); | 1068 windower.cut(input); |
943 | 1069 |
944 for (size_t i = 0; i < windowSize/2; ++i) { | 1070 for (size_t i = 0; i < windowSize/2; ++i) { |
945 double temp = input[i]; | 1071 double temp = input[i]; |
946 input[i] = input[i + windowSize/2]; | 1072 input[i] = input[i + windowSize/2]; |
950 fftw_execute(plan); | 1076 fftw_execute(plan); |
951 | 1077 |
952 bool interrupted = false; | 1078 bool interrupted = false; |
953 | 1079 |
954 double prevMag = 0.0; | 1080 double prevMag = 0.0; |
955 | |
956 double maxMag = 0.0; | 1081 double maxMag = 0.0; |
1082 | |
957 if (m_normalizeColumns) { | 1083 if (m_normalizeColumns) { |
958 for (size_t i = 0; i < windowSize/2; ++i) { | 1084 for (size_t i = 0; i < windowSize/2; ++i) { |
959 double mag = sqrt(output[i][0] * output[i][0] + | 1085 double mag = sqrt(output[i][0] * output[i][0] + |
960 output[i][1] * output[i][1]); | 1086 output[i][1] * output[i][1]); |
961 mag /= windowSize / 2; | 1087 mag /= windowSize / 2; |
962 if (mag > maxMag) maxMag = mag; | 1088 if (mag > maxMag) maxMag = mag; |
963 } | 1089 } |
964 } | 1090 } |
965 | 1091 |
1092 if (maxMag == 0.0) maxMag = 1.0; | |
1093 | |
1094 bool peaksOnly = (m_binDisplay == PeakBins || | |
1095 m_binDisplay == PeakFrequencies); | |
1096 | |
966 for (size_t i = 0; i < windowSize / 2; ++i) { | 1097 for (size_t i = 0; i < windowSize / 2; ++i) { |
967 | 1098 |
968 int value = 0; | 1099 int value = 0; |
969 double phase = 0.0; | 1100 double phase = 0.0; |
970 | 1101 |
971 double mag = sqrt(output[i][0] * output[i][0] + | 1102 double mag = sqrt(output[i][0] * output[i][0] + |
972 output[i][1] * output[i][1]); | 1103 output[i][1] * output[i][1]); |
973 mag /= windowSize / 2; | 1104 |
974 | 1105 mag /= (windowSize / 2); |
975 if (m_normalizeColumns && maxMag > 0.0) { | 1106 if (m_normalizeColumns) mag /= maxMag; |
976 mag /= maxMag; | 1107 |
977 } | 1108 bool showThis = true; |
1109 | |
1110 if (peaksOnly) { | |
1111 if (mag < prevMag) showThis = false; | |
1112 else { | |
1113 double nextMag = 0.0; | |
1114 if (i < windowSize / 2 - 1) { | |
1115 nextMag = sqrt(output[i+1][0] * output[i+1][0] + | |
1116 output[i+1][1] * output[i+1][1]); | |
1117 nextMag /= windowSize / 2; | |
1118 if (m_normalizeColumns) nextMag /= maxMag; | |
1119 } | |
1120 if (mag < nextMag) showThis = false; | |
1121 } | |
1122 prevMag = mag; | |
1123 } | |
1124 | |
1125 if (mag < m_threshold) showThis = false; | |
978 | 1126 |
979 if (phaseAdjust || (m_colourScale == PhaseColourScale)) { | 1127 if (phaseAdjust || (m_colourScale == PhaseColourScale)) { |
980 | 1128 phase = atan2(output[i][1], output[i][0]); |
981 // phase = atan2(-output[i][1], output[i][0]); | 1129 phase = MathUtilities::princarg(phase); |
982 // phase = atan2(output[i][1], output[i][0]); | |
983 phase = atan2(output[i][0], output[i][1]); | |
984 // phase = MathUtilities::princarg(phase); | |
985 } | 1130 } |
986 | 1131 |
987 if (phaseAdjust && m_phaseAdjustCache && haveStoredPhase) { | 1132 if (phaseAdjust && m_phaseAdjustCache) { |
988 | 1133 m_phaseAdjustCache->setValueAt(column, i, 0); |
989 bool peak = true; | 1134 } |
990 // if (m_frequencyAdjustment == PhaseAdjustedPeaks) { | 1135 |
991 if (true) { //!!! | 1136 if (phaseAdjust && m_phaseAdjustCache && haveStoredPhase && showThis) { |
992 if (mag < prevMag) peak = false; | 1137 |
993 else { | 1138 double freq = (double(i) * sampleRate) / m_windowSize; |
994 double nextMag = 0.0; | 1139 double prevPhase = storedPhase[i]; |
995 if (i < windowSize / 2 - 1) { | 1140 |
996 nextMag = sqrt(output[i+1][0] * output[i+1][0] + | 1141 // At frequency f, phase shift of 2pi (one cycle) happens in 1/f sec. |
997 output[i+1][1] * output[i+1][1]); | 1142 // At hopsize h and sample rate sr, one hop happens in h/sr sec. |
998 nextMag /= windowSize / 2; | 1143 // At window size w, for bin i, f is i*sr/w. |
999 if (m_normalizeColumns && maxMag > 0.0) { | 1144 // thus 2pi phase shift happens in w/(b*sr) sec. |
1000 nextMag /= maxMag; | 1145 // We need to know what phase shift we expect from h/sr sec. |
1001 } | 1146 // -> 2pi * ((h/sr) / (w/(i*sr))) |
1002 } | 1147 // = 2pi * ((h * i * sr) / (w * sr)) |
1003 if (mag < nextMag) peak = false; | 1148 // = 2pi * (h * i) / w. |
1004 } | 1149 |
1005 prevMag = mag; | 1150 double expectedPhase = |
1006 } | 1151 prevPhase + (2.0 * M_PI * i * increment) / m_windowSize; |
1007 | 1152 |
1008 if (!peak) { | 1153 double phaseError = MathUtilities::princarg(phase - expectedPhase); |
1154 | |
1155 if (fabs(phaseError) < (1.1 * (increment * M_PI) / m_windowSize)) { | |
1156 | |
1157 // The new frequency estimate based on the phase error | |
1158 // resulting from assuming the "native" frequency of this bin | |
1159 | |
1160 double newFreq = | |
1161 (sampleRate * | |
1162 (expectedPhase + phaseError - prevPhase)) / | |
1163 (2 * M_PI * increment); | |
1164 | |
1165 // Convert the frequency difference to an unsigned char | |
1166 // for storage in the phase adjust cache | |
1167 | |
1168 double binRange = (double(i + 1) * sampleRate) / windowSize - freq; | |
1169 | |
1170 int offset = lrint(((newFreq - freq) / binRange) * 100); | |
1171 | |
1009 if (m_cacheInvalid || m_exiting) { | 1172 if (m_cacheInvalid || m_exiting) { |
1010 interrupted = true; | 1173 interrupted = true; |
1011 break; | 1174 break; |
1012 } | 1175 } |
1013 m_phaseAdjustCache->setValueAt(column, i, SCHAR_MIN); | 1176 |
1014 } else { | 1177 if (offset >= SCHAR_MIN && offset <= SCHAR_MAX) { |
1015 | 1178 signed char coff = offset; |
1016 if (i < 100 && counter == 10) { | 1179 m_phaseAdjustCache->setValueAt(column, i, (unsigned char)coff); |
1017 | 1180 } else { |
1018 // if (counter == 10) { | 1181 |
1019 | 1182 if (fabs(phaseError) < ((increment * M_PI) / m_windowSize)) { |
1020 double freq = (double(i) * sampleRate) / m_windowSize; | 1183 std::cerr << "WARNING: Phase error " << phaseError << " ( < " << ((increment * M_PI) / m_windowSize) << ") but offset " << offset << " out of range" << std::endl; |
1021 // std::cout << "\nbin = " << i << " initial estimate freq = " << freq | 1184 } |
1022 // << " mag = " << mag << std::endl; | 1185 } |
1023 | 1186 } |
1024 double prevPhase = storedPhase[i]; | 1187 } |
1025 | 1188 |
1026 // If the frequency is 100Hz and the sample rate is | 1189 if (phaseAdjust) storedPhase[i] = phase; |
1027 // 10000Hz and we have 1000 samples (1/10sec) per bin, | |
1028 // then we expect phase 0 | |
1029 | |
1030 // 2pi happens in 1/freq sec | |
1031 // one hop happens in hopsize/sr sec | |
1032 // freq is bin*sr / windowsize | |
1033 // thus 2pi happens in windowsize/(bin*sr) sec | |
1034 | |
1035 // need to know what phase increment we expect from | |
1036 // hopsize/sr sec | |
1037 // must be 2pi * ((hopsize/sr) / (windowsize/(bin*sr))) | |
1038 // = 2pi * ((hopsize * bin * sr) / (windowsize * sr)) | |
1039 // = 2pi * (hopsize * bin) / windowsize | |
1040 | |
1041 double expectedPhase = | |
1042 prevPhase + (2.0 * M_PI * i * increment) / m_windowSize; | |
1043 | |
1044 double phaseError = MathUtilities::princarg(phase - expectedPhase); | |
1045 | |
1046 // if (fabs(phaseError) > (1.2 * (increment * M_PI) / m_windowSize)) { | |
1047 // std::cout << "error > " << (1.2 * (increment * M_PI) / m_windowSize) << std::endl; | |
1048 // }// else { | |
1049 | |
1050 std::cout << "prev = " << prevPhase << ", phase = " << phase | |
1051 << ", exp = " << expectedPhase << " prin = " << MathUtilities::princarg(expectedPhase) << ", error = " | |
1052 << phaseError << " inc = " << increment << " i = " << i << ", pi = " << M_PI << std::endl; | |
1053 | |
1054 double newFreq = | |
1055 (sampleRate * | |
1056 (expectedPhase + phaseError - prevPhase)) / | |
1057 //(prevPhase - (expectedPhase + phaseError))) / | |
1058 (2 * M_PI * increment); | |
1059 | |
1060 std::cout << freq << " (" << Pitch::getPitchLabelForFrequency(freq).toStdString() << ") -> " << newFreq << " (" << Pitch::getPitchLabelForFrequency(newFreq).toStdString() << ")" << std::endl; | |
1061 // } | |
1062 | |
1063 double binRange = (double(i + 1) * sampleRate) / windowSize - freq; | |
1064 | |
1065 int offset = lrint(((newFreq - freq) / binRange) * 10);//!!! | |
1066 | |
1067 if (m_cacheInvalid || m_exiting) { | |
1068 interrupted = true; | |
1069 break; | |
1070 } | |
1071 if (offset > SCHAR_MIN && offset <= SCHAR_MAX) { | |
1072 signed char coff = offset; | |
1073 m_phaseAdjustCache->setValueAt(column, i, (unsigned char)coff); | |
1074 } else { | |
1075 m_phaseAdjustCache->setValueAt(column, i, 0); | |
1076 } | |
1077 } | |
1078 } | |
1079 | |
1080 storedPhase[i] = phase; | |
1081 } | |
1082 | 1190 |
1083 if (m_colourScale == PhaseColourScale) { | 1191 if (m_colourScale == PhaseColourScale) { |
1084 | 1192 |
1085 phase = MathUtilities::princarg(phase); | 1193 value = int((phase * 127 / M_PI) + 128); |
1086 value = int((phase * 128 / M_PI) + 128); | |
1087 | 1194 |
1088 } else { | 1195 } else { |
1089 | 1196 |
1090 switch (m_colourScale) { | 1197 switch (m_colourScale) { |
1091 | 1198 |
1092 default: | 1199 default: |
1093 case LinearColourScale: | 1200 case LinearColourScale: |
1094 value = int(mag * 50 * 256); | 1201 value = int(mag * 50 * 255) + 1; |
1095 break; | 1202 break; |
1096 | 1203 |
1097 case MeterColourScale: | 1204 case MeterColourScale: |
1098 value = AudioLevel::multiplier_to_preview(mag * 50, 256); | 1205 value = AudioLevel::multiplier_to_preview(mag * 50, 255) + 1; |
1099 break; | 1206 break; |
1100 | 1207 |
1101 case dBColourScale: | 1208 case dBColourScale: |
1102 mag = 20.0 * log10(mag); | 1209 mag = 20.0 * log10(mag); |
1103 mag = (mag + 80.0) / 80.0; | 1210 mag = (mag + 80.0) / 80.0; |
1104 if (mag < 0.0) mag = 0.0; | 1211 if (mag < 0.0) mag = 0.0; |
1105 if (mag > 1.0) mag = 1.0; | 1212 if (mag > 1.0) mag = 1.0; |
1106 value = int(mag * 256); | 1213 value = int(mag * 255) + 1; |
1107 } | 1214 } |
1108 } | 1215 } |
1109 | 1216 |
1110 if (value > 254) value = 254; | 1217 if (value > UCHAR_MAX) value = UCHAR_MAX; |
1111 if (value < 0) value = 0; | 1218 if (value < 0) value = 0; |
1112 | 1219 |
1113 if (m_cacheInvalid || m_exiting) { | 1220 if (m_cacheInvalid || m_exiting) { |
1114 interrupted = true; | 1221 interrupted = true; |
1115 break; | 1222 break; |
1116 } | 1223 } |
1117 | 1224 |
1118 m_cache->setValueAt(column, i, value + 1); | 1225 if (showThis) { |
1226 m_cache->setValueAt(column, i, value); | |
1227 } else { | |
1228 m_cache->setValueAt(column, i, NO_VALUE); | |
1229 } | |
1119 } | 1230 } |
1120 | 1231 |
1121 return !interrupted; | 1232 return !interrupted; |
1122 } | 1233 } |
1123 | 1234 |
1138 } | 1249 } |
1139 | 1250 |
1140 void | 1251 void |
1141 SpectrogramLayer::Cache::resize(size_t width, size_t height) | 1252 SpectrogramLayer::Cache::resize(size_t width, size_t height) |
1142 { | 1253 { |
1254 std::cerr << "SpectrogramLayer::Cache[" << this << "]::resize(" << width << "x" << height << ")" << std::endl; | |
1143 m_values = (unsigned char *) | 1255 m_values = (unsigned char *) |
1144 realloc(m_values, m_width * m_height * sizeof(unsigned char)); | 1256 realloc(m_values, m_width * m_height * sizeof(unsigned char)); |
1145 if (!m_values) throw std::bad_alloc(); | 1257 if (!m_values) throw std::bad_alloc(); |
1146 MUNLOCK(m_values, m_width * m_height * sizeof(unsigned char)); | 1258 MUNLOCK(m_values, m_width * m_height * sizeof(unsigned char)); |
1147 } | 1259 } |
1185 } | 1297 } |
1186 | 1298 |
1187 void | 1299 void |
1188 SpectrogramLayer::Cache::fill(unsigned char value) | 1300 SpectrogramLayer::Cache::fill(unsigned char value) |
1189 { | 1301 { |
1302 std::cerr << "SpectrogramLayer::Cache[" << this << "]::fill(" << value << ")" << std::endl; | |
1190 for (size_t i = 0; i < m_width * m_height; ++i) { | 1303 for (size_t i = 0; i < m_width * m_height; ++i) { |
1191 m_values[i] = value; | 1304 m_values[i] = value; |
1192 } | 1305 } |
1193 } | 1306 } |
1194 | 1307 |
1259 height != m_layer.m_cache->getHeight()) { | 1372 height != m_layer.m_cache->getHeight()) { |
1260 m_layer.m_cache->resize(width, height); | 1373 m_layer.m_cache->resize(width, height); |
1261 } | 1374 } |
1262 | 1375 |
1263 m_layer.setCacheColourmap(); | 1376 m_layer.setCacheColourmap(); |
1264 m_layer.m_cache->fill(0); | 1377 m_layer.m_cache->fill(NO_VALUE); |
1265 | 1378 |
1266 if (m_layer.m_frequencyAdjustment == PhaseAdjustedFrequency || | 1379 if (m_layer.m_binDisplay == PeakFrequencies) { |
1267 m_layer.m_frequencyAdjustment == PhaseAdjustedPeaks) { | |
1268 | 1380 |
1269 if (!m_layer.m_phaseAdjustCache) { | 1381 if (!m_layer.m_phaseAdjustCache) { |
1270 m_layer.m_phaseAdjustCache = new Cache(width, height); | 1382 m_layer.m_phaseAdjustCache = new Cache(width, height); |
1271 } else if (width != m_layer.m_phaseAdjustCache->getWidth() || | 1383 } else if (width != m_layer.m_phaseAdjustCache->getWidth() || |
1272 height != m_layer.m_phaseAdjustCache->getHeight()) { | 1384 height != m_layer.m_phaseAdjustCache->getHeight()) { |
1304 | 1416 |
1305 if (!plan) { | 1417 if (!plan) { |
1306 std::cerr << "WARNING: fftw_plan_dft_r2c_1d(" << windowSize << ") failed!" << std::endl; | 1418 std::cerr << "WARNING: fftw_plan_dft_r2c_1d(" << windowSize << ") failed!" << std::endl; |
1307 fftw_free(input); | 1419 fftw_free(input); |
1308 fftw_free(output); | 1420 fftw_free(output); |
1421 m_layer.m_mutex.lock(); | |
1309 continue; | 1422 continue; |
1310 } | 1423 } |
1311 | 1424 |
1312 int counter = 0; | 1425 int counter = 0; |
1313 int updateAt = (end / windowIncrement) / 20; | 1426 int updateAt = (end / windowIncrement) / 20; |
1329 interrupted = true; | 1442 interrupted = true; |
1330 m_fillExtent = 0; | 1443 m_fillExtent = 0; |
1331 break; | 1444 break; |
1332 } | 1445 } |
1333 | 1446 |
1334 if (++counter == updateAt) { | 1447 if (++counter == updateAt || f == visibleEnd - 1) { |
1335 if (f < end) m_fillExtent = f; | 1448 if (f < end) m_fillExtent = f; |
1336 m_fillCompletion = size_t(100 * fabsf(float(f - visibleStart) / | 1449 m_fillCompletion = size_t(100 * fabsf(float(f - visibleStart) / |
1337 float(end - start))); | 1450 float(end - start))); |
1338 counter = 0; | 1451 counter = 0; |
1339 } | 1452 } |
1340 } | 1453 } |
1454 | |
1455 m_layer.m_cachedInitialVisibleArea = true; | |
1456 std::cerr << "SpectrogramLayer::CacheFillThread::run: visible bit done" << std::endl; | |
1341 } | 1457 } |
1342 | |
1343 m_layer.m_cachedInitialVisibleArea = true; | |
1344 | 1458 |
1345 if (!interrupted && doVisibleFirst) { | 1459 if (!interrupted && doVisibleFirst) { |
1346 | 1460 |
1347 for (size_t f = visibleEnd; f < end; f += windowIncrement) { | 1461 for (size_t f = visibleEnd; f < end; f += windowIncrement) { |
1348 | 1462 |
1354 m_fillExtent = 0; | 1468 m_fillExtent = 0; |
1355 break; | 1469 break; |
1356 } | 1470 } |
1357 | 1471 |
1358 | 1472 |
1359 if (++counter == updateAt) { | 1473 if (++counter == updateAt || f == end - 1) { |
1360 if (f < end) m_fillExtent = f; | 1474 m_fillExtent = f; |
1361 m_fillCompletion = size_t(100 * fabsf(float(f - visibleStart) / | 1475 m_fillCompletion = size_t(100 * fabsf(float(f - visibleStart) / |
1362 float(end - start))); | 1476 float(end - start))); |
1363 counter = 0; | 1477 counter = 0; |
1364 } | 1478 } |
1365 } | 1479 } |
1384 interrupted = true; | 1498 interrupted = true; |
1385 m_fillExtent = 0; | 1499 m_fillExtent = 0; |
1386 break; | 1500 break; |
1387 } | 1501 } |
1388 | 1502 |
1389 if (++counter == updateAt) { | 1503 if (++counter == updateAt || |
1504 f == visibleEnd - 1 || | |
1505 f == remainingEnd - 1) { | |
1390 m_fillExtent = f; | 1506 m_fillExtent = f; |
1391 m_fillCompletion = baseCompletion + | 1507 m_fillCompletion = baseCompletion + |
1392 size_t(100 * fabsf(float(f - start) / | 1508 size_t(100 * fabsf(float(f - start) / |
1393 float(end - start))); | 1509 float(end - start))); |
1394 counter = 0; | 1510 counter = 0; |
1546 | 1662 |
1547 int sr = m_model->getSampleRate(); | 1663 int sr = m_model->getSampleRate(); |
1548 | 1664 |
1549 bool haveAdj = false; | 1665 bool haveAdj = false; |
1550 | 1666 |
1667 bool peaksOnly = (m_binDisplay == PeakBins || | |
1668 m_binDisplay == PeakFrequencies); | |
1669 | |
1551 for (int q = q0i; q <= q1i; ++q) { | 1670 for (int q = q0i; q <= q1i; ++q) { |
1552 | 1671 |
1553 for (int s = s0i; s <= s1i; ++s) { | 1672 for (int s = s0i; s <= s1i; ++s) { |
1554 | 1673 |
1555 float binfreq = (sr * q) / m_windowSize; | 1674 float binfreq = (sr * q) / m_windowSize; |
1556 if (q == q0i) freqMin = binfreq; | 1675 if (q == q0i) freqMin = binfreq; |
1557 if (q == q1i) freqMax = binfreq; | 1676 if (q == q1i) freqMax = binfreq; |
1677 | |
1678 if (m_cache->getValueAt(s, q) == NO_VALUE) { | |
1679 continue; | |
1680 } | |
1558 | 1681 |
1559 if ((m_frequencyAdjustment == PhaseAdjustedFrequency || | 1682 if (m_binDisplay == PeakFrequencies && |
1560 m_frequencyAdjustment == PhaseAdjustedPeaks) && | |
1561 m_phaseAdjustCache) { | 1683 m_phaseAdjustCache) { |
1562 | 1684 |
1563 unsigned char cadj = m_phaseAdjustCache->getValueAt(s, q); | 1685 unsigned char cadj = m_phaseAdjustCache->getValueAt(s, q); |
1564 int adjust = int((signed char)cadj); | 1686 int adjust = int((signed char)cadj); |
1565 if (adjust == SCHAR_MIN && | |
1566 m_frequencyAdjustment == PhaseAdjustedPeaks) { | |
1567 continue; | |
1568 } | |
1569 | 1687 |
1570 float nextBinFreq = (sr * (q + 1)) / m_windowSize; | 1688 float nextBinFreq = (sr * (q + 1)) / m_windowSize; |
1571 float fadjust = (adjust * (nextBinFreq - binfreq)) / 10.0;//!!! | 1689 float fadjust = (adjust * (nextBinFreq - binfreq)) / 100.0;//!!! |
1572 float f = binfreq + fadjust; | 1690 float f = binfreq + fadjust; |
1573 if (!haveAdj || f < adjFreqMin) adjFreqMin = f; | 1691 if (!haveAdj || f < adjFreqMin) adjFreqMin = f; |
1574 if (!haveAdj || f > adjFreqMax) adjFreqMax = f; | 1692 if (!haveAdj || f > adjFreqMax) adjFreqMax = f; |
1575 haveAdj = true; | 1693 haveAdj = true; |
1576 } | 1694 } |
1597 int q1i = int(q1); | 1715 int q1i = int(q1); |
1598 | 1716 |
1599 int s0i = int(s0 + 0.001); | 1717 int s0i = int(s0 + 0.001); |
1600 int s1i = int(s1); | 1718 int s1i = int(s1); |
1601 | 1719 |
1720 bool rv = false; | |
1721 | |
1602 if (m_mutex.tryLock()) { | 1722 if (m_mutex.tryLock()) { |
1603 if (m_cache && !m_cacheInvalid) { | 1723 if (m_cache && !m_cacheInvalid) { |
1604 | 1724 |
1605 int cw = m_cache->getWidth(); | 1725 int cw = m_cache->getWidth(); |
1606 int ch = m_cache->getHeight(); | 1726 int ch = m_cache->getHeight(); |
1609 | 1729 |
1610 for (int q = q0i; q <= q1i; ++q) { | 1730 for (int q = q0i; q <= q1i; ++q) { |
1611 for (int s = s0i; s <= s1i; ++s) { | 1731 for (int s = s0i; s <= s1i; ++s) { |
1612 if (s >= 0 && q >= 0 && s < cw && q < ch) { | 1732 if (s >= 0 && q >= 0 && s < cw && q < ch) { |
1613 int value = int(m_cache->getValueAt(s, q)); | 1733 int value = int(m_cache->getValueAt(s, q)); |
1734 if (value == NO_VALUE) continue; | |
1614 if (min == -1 || value < min) min = value; | 1735 if (min == -1 || value < min) min = value; |
1615 if (max == -1 || value > max) max = value; | 1736 if (max == -1 || value > max) max = value; |
1616 } | 1737 } |
1617 } | 1738 } |
1618 } | 1739 } |
1619 | 1740 |
1620 if (min < 0) return false; | 1741 if (min >= 0) { |
1621 | 1742 dbMin = (float(min) / 256.0) * 80.0 - 80.0; |
1622 dbMin = (float(min) / 256.0) * 80.0 - 80.0; | 1743 dbMax = (float(max + 1) / 256.0) * 80.0 - 80.1; |
1623 dbMax = (float(max + 1) / 256.0) * 80.0 - 80.1; | 1744 rv = true; |
1624 | 1745 } |
1625 m_mutex.unlock(); | |
1626 return true; | |
1627 } | 1746 } |
1628 | 1747 |
1629 m_mutex.unlock(); | 1748 m_mutex.unlock(); |
1630 } | 1749 } |
1631 | 1750 |
1632 return false; | 1751 return rv; |
1633 } | 1752 } |
1634 | 1753 |
1635 void | 1754 void |
1636 SpectrogramLayer::paint(QPainter &paint, QRect rect) const | 1755 SpectrogramLayer::paint(QPainter &paint, QRect rect) const |
1637 { | 1756 { |
1651 | 1770 |
1652 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1771 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1653 std::cerr << "SpectrogramLayer::paint(): About to lock" << std::endl; | 1772 std::cerr << "SpectrogramLayer::paint(): About to lock" << std::endl; |
1654 #endif | 1773 #endif |
1655 | 1774 |
1656 /* | 1775 m_mutex.lock(); |
1657 if (m_cachedInitialVisibleArea) { | |
1658 if (!m_mutex.tryLock()) { | |
1659 m_view->update(); | |
1660 return; | |
1661 } | |
1662 } else { | |
1663 */ | |
1664 m_mutex.lock(); | |
1665 // } | |
1666 | 1776 |
1667 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1777 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1668 std::cerr << "SpectrogramLayer::paint(): locked" << std::endl; | 1778 std::cerr << "SpectrogramLayer::paint(): locked" << std::endl; |
1669 #endif | 1779 #endif |
1670 | 1780 |
1792 QImage scaled(w, h, QImage::Format_RGB32); | 1902 QImage scaled(w, h, QImage::Format_RGB32); |
1793 scaled.fill(0); | 1903 scaled.fill(0); |
1794 | 1904 |
1795 float ymag[h]; | 1905 float ymag[h]; |
1796 float ydiv[h]; | 1906 float ydiv[h]; |
1907 | |
1908 int sr = m_model->getSampleRate(); | |
1797 | 1909 |
1798 size_t bins = m_windowSize / 2; | 1910 size_t bins = m_windowSize / 2; |
1799 int sr = m_model->getSampleRate(); | |
1800 | |
1801 if (m_maxFrequency > 0) { | 1911 if (m_maxFrequency > 0) { |
1802 bins = int((double(m_maxFrequency) * m_windowSize) / sr + 0.1); | 1912 bins = int((double(m_maxFrequency) * m_windowSize) / sr + 0.1); |
1803 if (bins > m_windowSize / 2) bins = m_windowSize / 2; | 1913 if (bins > m_windowSize / 2) bins = m_windowSize / 2; |
1804 } | 1914 } |
1805 | 1915 |
1916 size_t minbin = 0; | |
1917 if (m_minFrequency > 0) { | |
1918 minbin = int((double(m_minFrequency) * m_windowSize) / sr + 0.1); | |
1919 if (minbin >= bins) minbin = bins - 1; | |
1920 } | |
1921 | |
1922 float minFreq = (float(minbin) * sr) / m_windowSize; | |
1806 float maxFreq = (float(bins) * sr) / m_windowSize; | 1923 float maxFreq = (float(bins) * sr) / m_windowSize; |
1807 | 1924 |
1808 m_mutex.unlock(); | 1925 m_mutex.unlock(); |
1809 | 1926 |
1810 for (int x = 0; x < w; ++x) { | 1927 for (int x = 0; x < w; ++x) { |
1832 } | 1949 } |
1833 | 1950 |
1834 int s0i = int(s0 + 0.001); | 1951 int s0i = int(s0 + 0.001); |
1835 int s1i = int(s1); | 1952 int s1i = int(s1); |
1836 | 1953 |
1837 for (int q = 0; q < bins; ++q) { | 1954 for (int q = minbin; q < bins; ++q) { |
1838 | 1955 |
1839 for (int s = s0i; s <= s1i; ++s) { | 1956 for (int s = s0i; s <= s1i; ++s) { |
1840 | 1957 |
1841 float sprop = 1.0; | 1958 float sprop = 1.0; |
1842 if (s == s0i) sprop *= (s + 1) - s0; | 1959 if (s == s0i) sprop *= (s + 1) - s0; |
1843 if (s == s1i) sprop *= s1 - s; | 1960 if (s == s1i) sprop *= s1 - s; |
1844 | 1961 |
1845 float f0 = (float(q) * sr) / m_windowSize; | 1962 float f0 = (float(q) * sr) / m_windowSize; |
1846 float f1 = (float(q + 1) * sr) / m_windowSize; | 1963 float f1 = (float(q + 1) * sr) / m_windowSize; |
1847 | 1964 |
1848 if ((m_frequencyAdjustment == PhaseAdjustedFrequency || | 1965 if ((m_binDisplay == PeakFrequencies) && |
1849 m_frequencyAdjustment == PhaseAdjustedPeaks) && | |
1850 m_phaseAdjustCache) { | 1966 m_phaseAdjustCache) { |
1851 | 1967 |
1852 unsigned char cadj = m_phaseAdjustCache->getValueAt(s, q); | 1968 unsigned char cadj = m_phaseAdjustCache->getValueAt(s, q); |
1853 int adjust = int((signed char)cadj); | 1969 int adjust = int((signed char)cadj); |
1854 | 1970 float fadjust = (adjust * (f1 - f0)) / 100.0; |
1855 if (adjust == SCHAR_MIN && | |
1856 m_frequencyAdjustment == PhaseAdjustedPeaks) { | |
1857 continue; | |
1858 } | |
1859 | |
1860 float fadjust = (adjust * (f1 - f0)) / 10.0;//!!! was 100 | |
1861 f0 = f1 = f0 + fadjust; | 1971 f0 = f1 = f0 + fadjust; |
1862 } | 1972 } |
1863 | 1973 |
1864 float y0 = h - (h * f1) / maxFreq; | 1974 float y0 = h - (h * (f1 - minFreq)) / maxFreq; |
1865 float y1 = h - (h * f0) / maxFreq; | 1975 float y1 = h - (h * (f0 - minFreq)) / maxFreq; |
1976 | |
1977 //!!! We want a general View::getYForFrequency and inverse | |
1978 // that can be passed min freq, max freq and log/linear. We | |
1979 // can then introduce a central correspondence between, say, | |
1980 // spectrogram layer and a frequency-scaled MIDI layer on the | |
1981 // same view. | |
1866 | 1982 |
1867 if (m_frequencyScale == LogFrequencyScale) { | 1983 if (m_frequencyScale == LogFrequencyScale) { |
1868 | 1984 |
1869 float maxf = m_maxFrequency; | 1985 //!!! also, shouldn't be recalculating this every time! |
1870 if (maxf == 0.0) maxf = float(sr) / 2; | 1986 |
1987 // float maxf = m_maxFrequency; | |
1988 // if (maxf == 0.0) maxf = float(sr) / 2; | |
1871 | 1989 |
1872 float minf = float(sr) / m_windowSize; | 1990 // float minf = float(sr) / m_windowSize; |
1873 | 1991 |
1874 float maxlogf = log10f(maxf); | 1992 float maxlogf = log10f(maxFreq); |
1875 float minlogf = log10f(minf); | 1993 float minlogf; |
1994 | |
1995 if (minFreq > 0) minlogf = log10f(minFreq); | |
1996 else minlogf = log10f(float(sr) / m_windowSize); | |
1876 | 1997 |
1877 y0 = h - (h * (log10f(f1) - minlogf)) / (maxlogf - minlogf); | 1998 y0 = h - (h * (log10f(f1) - minlogf)) / (maxlogf - minlogf); |
1878 y1 = h - (h * (log10f(f0) - minlogf)) / (maxlogf - minlogf); | 1999 y1 = h - (h * (log10f(f0) - minlogf)) / (maxlogf - minlogf); |
1879 } | 2000 } |
1880 | 2001 |
1886 if (y < 0 || y >= h) continue; | 2007 if (y < 0 || y >= h) continue; |
1887 | 2008 |
1888 float yprop = sprop; | 2009 float yprop = sprop; |
1889 if (y == y0i) yprop *= (y + 1) - y0; | 2010 if (y == y0i) yprop *= (y + 1) - y0; |
1890 if (y == y1i) yprop *= y1 - y; | 2011 if (y == y1i) yprop *= y1 - y; |
1891 | 2012 |
1892 ymag[y] += yprop * m_cache->getValueAt(s, q); | 2013 int value = m_cache->getValueAt(s, q); |
2014 if (value == NO_VALUE) continue; | |
2015 | |
2016 ymag[y] += yprop * value; | |
1893 ydiv[y] += yprop; | 2017 ydiv[y] += yprop; |
1894 } | 2018 } |
1895 } | 2019 } |
1896 } | 2020 } |
1897 | 2021 |
1912 } | 2036 } |
1913 | 2037 |
1914 | 2038 |
1915 m_mutex.unlock(); | 2039 m_mutex.unlock(); |
1916 } | 2040 } |
1917 | |
1918 #ifdef NOT_DEFINED | |
1919 for (int y = 0; y < h; ++y) { | |
1920 | |
1921 m_mutex.lock(); | |
1922 if (m_cacheInvalid) { | |
1923 m_mutex.unlock(); | |
1924 break; | |
1925 } | |
1926 | |
1927 int cw = m_cache->getWidth(); | |
1928 int ch = m_cache->getHeight(); | |
1929 | |
1930 float q0 = 0, q1 = 0; | |
1931 | |
1932 if (!getYBinRange(y0 + y, q0, q1)) { | |
1933 for (int x = 0; x < w; ++x) { | |
1934 assert(x <= scaled.width()); | |
1935 scaled.setPixel(x, y, qRgb(0, 0, 0)); | |
1936 } | |
1937 m_mutex.unlock(); | |
1938 continue; | |
1939 } | |
1940 | |
1941 int q0i = int(q0 + 0.001); | |
1942 int q1i = int(q1); | |
1943 | |
1944 for (int x = 0; x < w; ++x) { | |
1945 | |
1946 float s0 = 0, s1 = 0; | |
1947 | |
1948 if (!getXBinRange(x0 + x, s0, s1)) { | |
1949 assert(x <= scaled.width()); | |
1950 scaled.setPixel(x, y, qRgb(0, 0, 0)); | |
1951 continue; | |
1952 } | |
1953 | |
1954 int s0i = int(s0 + 0.001); | |
1955 int s1i = int(s1); | |
1956 | |
1957 float total = 0, divisor = 0; | |
1958 | |
1959 for (int s = s0i; s <= s1i; ++s) { | |
1960 | |
1961 float sprop = 1.0; | |
1962 if (s == s0i) sprop *= (s + 1) - s0; | |
1963 if (s == s1i) sprop *= s1 - s; | |
1964 | |
1965 for (int q = q0i; q <= q1i; ++q) { | |
1966 | |
1967 float qprop = sprop; | |
1968 if (q == q0i) qprop *= (q + 1) - q0; | |
1969 if (q == q1i) qprop *= q1 - q; | |
1970 | |
1971 if (s >= 0 && q >= 0 && s < cw && q < ch) { | |
1972 total += qprop * m_cache->getValueAt(s, q); | |
1973 divisor += qprop; | |
1974 } | |
1975 } | |
1976 } | |
1977 | |
1978 if (divisor > 0.0) { | |
1979 int pixel = int(total / divisor); | |
1980 if (pixel > 255) pixel = 255; | |
1981 if (pixel < 1) pixel = 1; | |
1982 assert(x <= scaled.width()); | |
1983 QColor c = m_cache->getColour(pixel); | |
1984 scaled.setPixel(x, y, | |
1985 qRgb(c.red(), c.green(), c.blue())); | |
1986 /* | |
1987 float pixel = total / divisor; | |
1988 float lq = pixel - int(pixel); | |
1989 float hq = int(pixel) + 1 - pixel; | |
1990 int pixNum = int(pixel); | |
1991 QRgb low = m_cache->color(pixNum > 255 ? 255 : pixNum); | |
1992 QRgb high = m_cache->color(pixNum > 254 ? 255 : pixNum + 1); | |
1993 QRgb mixed = qRgb | |
1994 (qRed(low) * lq + qRed(high) * hq + 0.01, | |
1995 qGreen(low) * lq + qGreen(high) * hq + 0.01, | |
1996 qBlue(low) * lq + qBlue(high) * hq + 0.01); | |
1997 scaled.setPixel(x, y, mixed); | |
1998 */ | |
1999 } else { | |
2000 assert(x <= scaled.width()); | |
2001 scaled.setPixel(x, y, qRgb(0, 0, 0)); | |
2002 } | |
2003 } | |
2004 | |
2005 m_mutex.unlock(); | |
2006 } | |
2007 #endif | |
2008 | 2041 |
2009 paint.drawImage(x0, y0, scaled); | 2042 paint.drawImage(x0, y0, scaled); |
2010 | 2043 |
2011 if (recreateWholePixmapCache) { | 2044 if (recreateWholePixmapCache) { |
2012 delete m_pixmapCache; | 2045 delete m_pixmapCache; |
2076 if (!getXBinSourceRange(x, rtMin, rtMax)) return ""; | 2109 if (!getXBinSourceRange(x, rtMin, rtMax)) return ""; |
2077 if (getXYBinSourceRange(x, y, dbMin, dbMax)) haveDb = true; | 2110 if (getXYBinSourceRange(x, y, dbMin, dbMax)) haveDb = true; |
2078 | 2111 |
2079 QString adjFreqText = "", adjPitchText = ""; | 2112 QString adjFreqText = "", adjPitchText = ""; |
2080 | 2113 |
2081 if ((m_frequencyAdjustment == PhaseAdjustedFrequency || | 2114 if ((m_binDisplay == PeakFrequencies) && |
2082 m_frequencyAdjustment == PhaseAdjustedPeaks) && | |
2083 m_phaseAdjustCache) { | 2115 m_phaseAdjustCache) { |
2084 | 2116 |
2085 if (!getAdjustedYBinSourceRange(x, y, freqMin, freqMax, | 2117 if (!getAdjustedYBinSourceRange(x, y, freqMin, freqMax, |
2086 adjFreqMin, adjFreqMax)) return ""; | 2118 adjFreqMin, adjFreqMax)) return ""; |
2087 | 2119 |
2223 | 2255 |
2224 s += QString("channel=\"%1\" " | 2256 s += QString("channel=\"%1\" " |
2225 "windowSize=\"%2\" " | 2257 "windowSize=\"%2\" " |
2226 "windowType=\"%3\" " | 2258 "windowType=\"%3\" " |
2227 "windowOverlap=\"%4\" " | 2259 "windowOverlap=\"%4\" " |
2228 "gain=\"%5\" ") | 2260 "gain=\"%5\" " |
2261 "threshold=\"%6\" ") | |
2229 .arg(m_channel) | 2262 .arg(m_channel) |
2230 .arg(m_windowSize) | 2263 .arg(m_windowSize) |
2231 .arg(m_windowType) | 2264 .arg(m_windowType) |
2232 .arg(m_windowOverlap) | 2265 .arg(m_windowOverlap) |
2233 .arg(m_gain); | 2266 .arg(m_gain) |
2234 | 2267 .arg(m_threshold); |
2235 s += QString("maxFrequency=\"%1\" " | 2268 |
2236 "colourScale=\"%2\" " | 2269 s += QString("minFrequency=\"%1\" " |
2237 "colourScheme=\"%3\" " | 2270 "maxFrequency=\"%2\" " |
2238 "frequencyScale=\"%4\" " | 2271 "colourScale=\"%3\" " |
2239 "frequencyAdjustment=\"%5\" " | 2272 "colourScheme=\"%4\" " |
2240 "normalizeColumns=\"%6\"") | 2273 "colourRotation=\"%5\" " |
2274 "frequencyScale=\"%6\" " | |
2275 "binDisplay=\"%7\" " | |
2276 "normalizeColumns=\"%8\"") | |
2277 .arg(m_minFrequency) | |
2241 .arg(m_maxFrequency) | 2278 .arg(m_maxFrequency) |
2242 .arg(m_colourScale) | 2279 .arg(m_colourScale) |
2243 .arg(m_colourScheme) | 2280 .arg(m_colourScheme) |
2281 .arg(m_colourRotation) | |
2244 .arg(m_frequencyScale) | 2282 .arg(m_frequencyScale) |
2245 .arg(m_frequencyAdjustment) | 2283 .arg(m_binDisplay) |
2246 .arg(m_normalizeColumns ? "true" : "false"); | 2284 .arg(m_normalizeColumns ? "true" : "false"); |
2247 | 2285 |
2248 return Layer::toXmlString(indent, extraAttributes + " " + s); | 2286 return Layer::toXmlString(indent, extraAttributes + " " + s); |
2249 } | 2287 } |
2250 | 2288 |
2267 if (ok) setWindowOverlap(windowOverlap); | 2305 if (ok) setWindowOverlap(windowOverlap); |
2268 | 2306 |
2269 float gain = attributes.value("gain").toFloat(&ok); | 2307 float gain = attributes.value("gain").toFloat(&ok); |
2270 if (ok) setGain(gain); | 2308 if (ok) setGain(gain); |
2271 | 2309 |
2310 float threshold = attributes.value("threshold").toFloat(&ok); | |
2311 if (ok) setThreshold(threshold); | |
2312 | |
2313 size_t minFrequency = attributes.value("minFrequency").toUInt(&ok); | |
2314 if (ok) setMinFrequency(minFrequency); | |
2315 | |
2272 size_t maxFrequency = attributes.value("maxFrequency").toUInt(&ok); | 2316 size_t maxFrequency = attributes.value("maxFrequency").toUInt(&ok); |
2273 if (ok) setMaxFrequency(maxFrequency); | 2317 if (ok) setMaxFrequency(maxFrequency); |
2274 | 2318 |
2275 ColourScale colourScale = (ColourScale) | 2319 ColourScale colourScale = (ColourScale) |
2276 attributes.value("colourScale").toInt(&ok); | 2320 attributes.value("colourScale").toInt(&ok); |
2278 | 2322 |
2279 ColourScheme colourScheme = (ColourScheme) | 2323 ColourScheme colourScheme = (ColourScheme) |
2280 attributes.value("colourScheme").toInt(&ok); | 2324 attributes.value("colourScheme").toInt(&ok); |
2281 if (ok) setColourScheme(colourScheme); | 2325 if (ok) setColourScheme(colourScheme); |
2282 | 2326 |
2327 int colourRotation = attributes.value("colourRotation").toInt(&ok); | |
2328 if (ok) setColourRotation(colourRotation); | |
2329 | |
2283 FrequencyScale frequencyScale = (FrequencyScale) | 2330 FrequencyScale frequencyScale = (FrequencyScale) |
2284 attributes.value("frequencyScale").toInt(&ok); | 2331 attributes.value("frequencyScale").toInt(&ok); |
2285 if (ok) setFrequencyScale(frequencyScale); | 2332 if (ok) setFrequencyScale(frequencyScale); |
2286 | 2333 |
2287 FrequencyAdjustment frequencyAdjustment = (FrequencyAdjustment) | 2334 BinDisplay binDisplay = (BinDisplay) |
2288 attributes.value("frequencyAdjustment").toInt(&ok); | 2335 attributes.value("binDisplay").toInt(&ok); |
2289 if (ok) setFrequencyAdjustment(frequencyAdjustment); | 2336 if (ok) setBinDisplay(binDisplay); |
2290 | 2337 |
2291 bool normalizeColumns = | 2338 bool normalizeColumns = |
2292 (attributes.value("normalizeColumns").trimmed() == "true"); | 2339 (attributes.value("normalizeColumns").trimmed() == "true"); |
2293 setNormalizeColumns(normalizeColumns); | 2340 setNormalizeColumns(normalizeColumns); |
2294 } | 2341 } |