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 }