comparison layer/SpectrumLayer.cpp @ 944:78c152e4db95

Merge from branch tonioni
author Chris Cannam
date Mon, 20 Apr 2015 09:12:17 +0100
parents 4a578a360011
children 94e4952a6774 b8187c83b93a
comparison
equal deleted inserted replaced
896:78e041e45ff0 944:78c152e4db95
299 return; 299 return;
300 } 300 }
301 } 301 }
302 302
303 bool 303 bool
304 SpectrumLayer::getValueExtents(float &, float &, bool &, QString &) const 304 SpectrumLayer::getValueExtents(double &, double &, bool &, QString &) const
305 { 305 {
306 return false; 306 return false;
307 } 307 }
308 308
309 float 309 double
310 SpectrumLayer::getXForBin(int bin, int totalBins, float w) const 310 SpectrumLayer::getXForBin(int bin, int totalBins, double w) const
311 { 311 {
312 if (!m_sliceableModel) return SliceLayer::getXForBin(bin, totalBins, w); 312 if (!m_sliceableModel) return SliceLayer::getXForBin(bin, totalBins, w);
313 313
314 float sampleRate = m_sliceableModel->getSampleRate(); 314 sv_samplerate_t sampleRate = m_sliceableModel->getSampleRate();
315 float binfreq = (sampleRate * bin) / (totalBins * 2); 315 double binfreq = (sampleRate * bin) / (totalBins * 2);
316 316
317 return getXForFrequency(binfreq, w); 317 return getXForFrequency(binfreq, w);
318 } 318 }
319 319
320 int 320 int
321 SpectrumLayer::getBinForX(float x, int totalBins, float w) const 321 SpectrumLayer::getBinForX(double x, int totalBins, double w) const
322 { 322 {
323 if (!m_sliceableModel) return SliceLayer::getBinForX(x, totalBins, w); 323 if (!m_sliceableModel) return SliceLayer::getBinForX(x, totalBins, w);
324 324
325 float sampleRate = m_sliceableModel->getSampleRate(); 325 sv_samplerate_t sampleRate = m_sliceableModel->getSampleRate();
326 float binfreq = getFrequencyForX(x, w); 326 double binfreq = getFrequencyForX(x, w);
327 327
328 return int((binfreq * totalBins * 2) / sampleRate); 328 return int((binfreq * totalBins * 2) / sampleRate);
329 } 329 }
330 330
331 float 331 double
332 SpectrumLayer::getFrequencyForX(float x, float w) const 332 SpectrumLayer::getFrequencyForX(double x, double w) const
333 { 333 {
334 float freq = 0; 334 double freq = 0;
335 if (!m_sliceableModel) return 0; 335 if (!m_sliceableModel) return 0;
336 336
337 int sampleRate = m_sliceableModel->getSampleRate(); 337 sv_samplerate_t sampleRate = m_sliceableModel->getSampleRate();
338 338
339 float maxfreq = float(sampleRate) / 2; 339 double maxfreq = double(sampleRate) / 2;
340 340
341 switch (m_binScale) { 341 switch (m_binScale) {
342 342
343 case LinearBins: 343 case LinearBins:
344 freq = ((x * maxfreq) / w); 344 freq = ((x * maxfreq) / w);
345 break; 345 break;
346 346
347 case LogBins: 347 case LogBins:
348 freq = powf(10.f, (x * log10f(maxfreq)) / w); 348 freq = pow(10.0, (x * log10(maxfreq)) / w);
349 break; 349 break;
350 350
351 case InvertedLogBins: 351 case InvertedLogBins:
352 freq = maxfreq - powf(10.f, ((w - x) * log10f(maxfreq)) / w); 352 freq = maxfreq - pow(10.0, ((w - x) * log10(maxfreq)) / w);
353 break; 353 break;
354 } 354 }
355 355
356 return freq; 356 return freq;
357 } 357 }
358 358
359 float 359 double
360 SpectrumLayer::getXForFrequency(float freq, float w) const 360 SpectrumLayer::getXForFrequency(double freq, double w) const
361 { 361 {
362 float x = 0; 362 double x = 0;
363 if (!m_sliceableModel) return x; 363 if (!m_sliceableModel) return x;
364 364
365 int sampleRate = m_sliceableModel->getSampleRate(); 365 sv_samplerate_t sampleRate = m_sliceableModel->getSampleRate();
366 366
367 float maxfreq = float(sampleRate) / 2; 367 double maxfreq = double(sampleRate) / 2;
368 368
369 switch (m_binScale) { 369 switch (m_binScale) {
370 370
371 case LinearBins: 371 case LinearBins:
372 x = (freq * w) / maxfreq; 372 x = (freq * w) / maxfreq;
373 break; 373 break;
374 374
375 case LogBins: 375 case LogBins:
376 x = (log10f(freq) * w) / log10f(maxfreq); 376 x = (log10(freq) * w) / log10(maxfreq);
377 break; 377 break;
378 378
379 case InvertedLogBins: 379 case InvertedLogBins:
380 if (maxfreq == freq) x = w; 380 if (maxfreq == freq) x = w;
381 else x = w - (log10f(maxfreq - freq) * w) / log10f(maxfreq); 381 else x = w - (log10(maxfreq - freq) * w) / log10(maxfreq);
382 break; 382 break;
383 } 383 }
384 384
385 return x; 385 return x;
386 } 386 }
387 387
388 bool 388 bool
389 SpectrumLayer::getXScaleValue(const View *v, int x, 389 SpectrumLayer::getXScaleValue(const View *v, int x,
390 float &value, QString &unit) const 390 double &value, QString &unit) const
391 { 391 {
392 if (m_xorigins.find(v) == m_xorigins.end()) return false; 392 if (m_xorigins.find(v) == m_xorigins.end()) return false;
393 int xorigin = m_xorigins.find(v)->second; 393 int xorigin = m_xorigins.find(v)->second;
394 value = getFrequencyForX(x - xorigin, v->width() - xorigin - 1); 394 value = getFrequencyForX(x - xorigin, v->width() - xorigin - 1);
395 unit = "Hz"; 395 unit = "Hz";
396 return true; 396 return true;
397 } 397 }
398 398
399 bool 399 bool
400 SpectrumLayer::getYScaleValue(const View *v, int y, 400 SpectrumLayer::getYScaleValue(const View *v, int y,
401 float &value, QString &unit) const 401 double &value, QString &unit) const
402 { 402 {
403 value = getValueForY(y, v); 403 value = getValueForY(y, v);
404 404
405 if (m_energyScale == dBScale || m_energyScale == MeterScale) { 405 if (m_energyScale == dBScale || m_energyScale == MeterScale) {
406 406
407 if (value > 0.f) { 407 if (value > 0.0) {
408 value = 10.f * log10f(value); 408 value = 10.0 * log10(value);
409 if (value < m_threshold) value = m_threshold; 409 if (value < m_threshold) value = m_threshold;
410 } else value = m_threshold; 410 } else value = m_threshold;
411 411
412 unit = "dBV"; 412 unit = "dBV";
413 413
418 return true; 418 return true;
419 } 419 }
420 420
421 bool 421 bool
422 SpectrumLayer::getYScaleDifference(const View *v, int y0, int y1, 422 SpectrumLayer::getYScaleDifference(const View *v, int y0, int y1,
423 float &diff, QString &unit) const 423 double &diff, QString &unit) const
424 { 424 {
425 bool rv = SliceLayer::getYScaleDifference(v, y0, y1, diff, unit); 425 bool rv = SliceLayer::getYScaleDifference(v, y0, y1, diff, unit);
426 if (rv && (unit == "dBV")) unit = "dB"; 426 if (rv && (unit == "dBV")) unit = "dB";
427 return rv; 427 return rv;
428 } 428 }
490 int w = v->width() - xorigin - 1; 490 int w = v->width() - xorigin - 1;
491 491
492 paint.drawLine(xorigin, cursorPos.y(), v->width(), cursorPos.y()); 492 paint.drawLine(xorigin, cursorPos.y(), v->width(), cursorPos.y());
493 paint.drawLine(cursorPos.x(), cursorPos.y(), cursorPos.x(), v->height()); 493 paint.drawLine(cursorPos.x(), cursorPos.y(), cursorPos.x(), v->height());
494 494
495 float fundamental = getFrequencyForX(cursorPos.x() - xorigin, w); 495 double fundamental = getFrequencyForX(cursorPos.x() - xorigin, w);
496 496
497 int hoffset = 2; 497 int hoffset = 2;
498 if (m_binScale == LogBins) hoffset = 13; 498 if (m_binScale == LogBins) hoffset = 13;
499 499
500 v->drawVisibleText(paint, 500 v->drawVisibleText(paint,
510 v->height() - 2 - hoffset, 510 v->height() - 2 - hoffset,
511 pitchLabel, 511 pitchLabel,
512 View::OutlinedText); 512 View::OutlinedText);
513 } 513 }
514 514
515 float value = getValueForY(cursorPos.y(), v); 515 double value = getValueForY(cursorPos.y(), v);
516 float thresh = m_threshold; 516 double thresh = m_threshold;
517 float db = thresh; 517 double db = thresh;
518 if (value > 0.f) db = 10.f * log10f(value); 518 if (value > 0.0) db = 10.0 * log10(value);
519 if (db < thresh) db = thresh; 519 if (db < thresh) db = thresh;
520 520
521 v->drawVisibleText(paint, 521 v->drawVisibleText(paint,
522 xorigin + 2, 522 xorigin + 2,
523 cursorPos.y() - 2, 523 cursorPos.y() - 2,
532 532
533 int harmonic = 2; 533 int harmonic = 2;
534 534
535 while (harmonic < 100) { 535 while (harmonic < 100) {
536 536
537 float hx = lrintf(getXForFrequency(fundamental * harmonic, w)); 537 int hx = int(lrint(getXForFrequency(fundamental * harmonic, w)));
538 hx += xorigin; 538 hx += xorigin;
539 539
540 if (hx < xorigin || hx > v->width()) break; 540 if (hx < xorigin || hx > v->width()) break;
541 541
542 int len = 7; 542 int len = 7;
547 } else { 547 } else {
548 len = 10; 548 len = 10;
549 } 549 }
550 } 550 }
551 551
552 paint.drawLine(int(hx), 552 paint.drawLine(hx,
553 cursorPos.y(), 553 cursorPos.y(),
554 int(hx), 554 hx,
555 cursorPos.y() + len); 555 cursorPos.y() + len);
556 556
557 ++harmonic; 557 ++harmonic;
558 } 558 }
559 559
569 QString genericDesc = SliceLayer::getFeatureDescriptionAux 569 QString genericDesc = SliceLayer::getFeatureDescriptionAux
570 (v, p, false, minbin, maxbin, range); 570 (v, p, false, minbin, maxbin, range);
571 571
572 if (genericDesc == "") return ""; 572 if (genericDesc == "") return "";
573 573
574 float minvalue = 0.f; 574 double minvalue = 0.f;
575 if (minbin < int(m_values.size())) minvalue = m_values[minbin]; 575 if (minbin < int(m_values.size())) minvalue = m_values[minbin];
576 576
577 float maxvalue = minvalue; 577 double maxvalue = minvalue;
578 if (maxbin < int(m_values.size())) maxvalue = m_values[maxbin]; 578 if (maxbin < int(m_values.size())) maxvalue = m_values[maxbin];
579 579
580 if (minvalue > maxvalue) std::swap(minvalue, maxvalue); 580 if (minvalue > maxvalue) std::swap(minvalue, maxvalue);
581 581
582 QString binstr; 582 QString binstr;
583 QString hzstr; 583 QString hzstr;
584 int minfreq = lrintf((minbin * m_sliceableModel->getSampleRate()) / 584 int minfreq = int(lrint((minbin * m_sliceableModel->getSampleRate()) /
585 m_windowSize); 585 m_windowSize));
586 int maxfreq = lrintf((std::max(maxbin, minbin+1) 586 int maxfreq = int(lrint((std::max(maxbin, minbin+1)
587 * m_sliceableModel->getSampleRate()) / 587 * m_sliceableModel->getSampleRate()) /
588 m_windowSize); 588 m_windowSize));
589 589
590 if (maxbin != minbin) { 590 if (maxbin != minbin) {
591 binstr = tr("%1 - %2").arg(minbin+1).arg(maxbin+1); 591 binstr = tr("%1 - %2").arg(minbin+1).arg(maxbin+1);
592 } else { 592 } else {
593 binstr = QString("%1").arg(minbin+1); 593 binstr = QString("%1").arg(minbin+1);
604 } else { 604 } else {
605 valuestr = QString("%1").arg(minvalue); 605 valuestr = QString("%1").arg(minvalue);
606 } 606 }
607 607
608 QString dbstr; 608 QString dbstr;
609 float mindb = AudioLevel::multiplier_to_dB(minvalue); 609 double mindb = AudioLevel::multiplier_to_dB(minvalue);
610 float maxdb = AudioLevel::multiplier_to_dB(maxvalue); 610 double maxdb = AudioLevel::multiplier_to_dB(maxvalue);
611 QString mindbstr; 611 QString mindbstr;
612 QString maxdbstr; 612 QString maxdbstr;
613 if (mindb == AudioLevel::DB_FLOOR) { 613 if (mindb == AudioLevel::DB_FLOOR) {
614 mindbstr = tr("-Inf"); 614 mindbstr = tr("-Inf");
615 } else { 615 } else {
616 mindbstr = QString("%1").arg(lrintf(mindb)); 616 mindbstr = QString("%1").arg(lrint(mindb));
617 } 617 }
618 if (maxdb == AudioLevel::DB_FLOOR) { 618 if (maxdb == AudioLevel::DB_FLOOR) {
619 maxdbstr = tr("-Inf"); 619 maxdbstr = tr("-Inf");
620 } else { 620 } else {
621 maxdbstr = QString("%1").arg(lrintf(maxdb)); 621 maxdbstr = QString("%1").arg(lrint(maxdb));
622 } 622 }
623 if (lrintf(mindb) != lrintf(maxdb)) { 623 if (lrint(mindb) != lrint(maxdb)) {
624 dbstr = tr("%1 - %2").arg(mindbstr).arg(maxdbstr); 624 dbstr = tr("%1 - %2").arg(mindbstr).arg(maxdbstr);
625 } else { 625 } else {
626 dbstr = tr("%1").arg(mindbstr); 626 dbstr = tr("%1").arg(mindbstr);
627 } 627 }
628 628
664 } 664 }
665 665
666 FFTModel *fft = dynamic_cast<FFTModel *> 666 FFTModel *fft = dynamic_cast<FFTModel *>
667 (const_cast<DenseThreeDimensionalModel *>(m_sliceableModel)); 667 (const_cast<DenseThreeDimensionalModel *>(m_sliceableModel));
668 668
669 float thresh = (powf(10, -6) / m_gain) * (m_windowSize / 2.f); // -60dB adj 669 double thresh = (pow(10, -6) / m_gain) * (m_windowSize / 2.0); // -60dB adj
670 670
671 int xorigin = getVerticalScaleWidth(v, false, paint) + 1; 671 int xorigin = getVerticalScaleWidth(v, false, paint) + 1;
672 int w = v->width() - xorigin - 1; 672 int w = v->width() - xorigin - 1;
673 673
674 int pkh = 0; 674 int pkh = 0;
682 682
683 // draw peak lines 683 // draw peak lines
684 684
685 // SVDEBUG << "Showing peaks..." << endl; 685 // SVDEBUG << "Showing peaks..." << endl;
686 686
687 int col = v->getCentreFrame() / fft->getResolution(); 687 int col = int(v->getCentreFrame() / fft->getResolution());
688 688
689 paint.save(); 689 paint.save();
690 paint.setRenderHint(QPainter::Antialiasing, false); 690 paint.setRenderHint(QPainter::Antialiasing, false);
691 paint.setPen(QColor(160, 160, 160)); //!!! 691 paint.setPen(QColor(160, 160, 160)); //!!!
692 692
693 int peakminbin = 0; 693 int peakminbin = 0;
694 int peakmaxbin = fft->getHeight() - 1; 694 int peakmaxbin = fft->getHeight() - 1;
695 float peakmaxfreq = Pitch::getFrequencyForPitch(128); 695 double peakmaxfreq = Pitch::getFrequencyForPitch(128);
696 peakmaxbin = ((peakmaxfreq * fft->getHeight() * 2) / fft->getSampleRate()); 696 peakmaxbin = int(((peakmaxfreq * fft->getHeight() * 2) / fft->getSampleRate()));
697 697
698 FFTModel::PeakSet peaks = fft->getPeakFrequencies 698 FFTModel::PeakSet peaks = fft->getPeakFrequencies
699 (FFTModel::MajorPitchAdaptivePeaks, col, peakminbin, peakmaxbin); 699 (FFTModel::MajorPitchAdaptivePeaks, col, peakminbin, peakmaxbin);
700 700
701 ColourMapper mapper(ColourMapper::BlackOnWhite, 0, 1); 701 ColourMapper mapper(ColourMapper::BlackOnWhite, 0, 1);
702 702
703 BiasCurve curve; 703 BiasCurve curve;
704 getBiasCurve(curve); 704 getBiasCurve(curve);
705 int cs = curve.size(); 705 int cs = int(curve.size());
706 706
707 std::vector<float> values; 707 std::vector<double> values;
708 708
709 for (int bin = 0; bin < fft->getHeight(); ++bin) { 709 for (int bin = 0; bin < fft->getHeight(); ++bin) {
710 float value = m_sliceableModel->getValueAt(col, bin); 710 double value = m_sliceableModel->getValueAt(col, bin);
711 if (bin < cs) value *= curve[bin]; 711 if (bin < cs) value *= curve[bin];
712 values.push_back(value); 712 values.push_back(value);
713 } 713 }
714 714
715 for (FFTModel::PeakSet::iterator i = peaks.begin(); 715 for (FFTModel::PeakSet::iterator i = peaks.begin();
717 717
718 int bin = i->first; 718 int bin = i->first;
719 719
720 // cerr << "bin = " << bin << ", thresh = " << thresh << ", value = " << fft->getMagnitudeAt(col, bin) << endl; 720 // cerr << "bin = " << bin << ", thresh = " << thresh << ", value = " << fft->getMagnitudeAt(col, bin) << endl;
721 721
722 if (!fft->isOverThreshold(col, bin, thresh)) continue; 722 if (!fft->isOverThreshold(col, bin, float(thresh))) continue;
723 723
724 float freq = i->second; 724 double freq = i->second;
725 725
726 int x = lrintf(getXForFrequency(freq, w)); 726 int x = int(lrint(getXForFrequency(freq, w)));
727 727
728 float norm = 0.f; 728 double norm = 0.f;
729 (void)getYForValue(values[bin], v, norm); // don't need return value, need norm 729 (void)getYForValue(values[bin], v, norm); // don't need return value, need norm
730 730
731 paint.setPen(mapper.map(norm)); 731 paint.setPen(mapper.map(norm));
732 paint.drawLine(xorigin + x, 0, xorigin + x, v->height() - pkh - 1); 732 paint.drawLine(xorigin + x, 0, xorigin + x, v->height() - pkh - 1);
733 } 733 }
760 int px = xorigin, ppx = xorigin; 760 int px = xorigin, ppx = xorigin;
761 paint.setBrush(paint.pen().color()); 761 paint.setBrush(paint.pen().color());
762 762
763 for (int i = 0; i < 128; ++i) { 763 for (int i = 0; i < 128; ++i) {
764 764
765 float f = Pitch::getFrequencyForPitch(i); 765 double f = Pitch::getFrequencyForPitch(i);
766 int x = lrintf(getXForFrequency(f, w)); 766 int x = int(lrint(getXForFrequency(f, w)));
767 767
768 x += xorigin; 768 x += xorigin;
769 769
770 if (i == 0) { 770 if (i == 0) {
771 px = ppx = x; 771 px = ppx = x;
803 } 803 }
804 804
805 if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) { 805 if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) {
806 // black notes 806 // black notes
807 paint.drawLine(x, h - pkh, x, h); 807 paint.drawLine(x, h - pkh, x, h);
808 int rw = lrintf(float(x - px) / 4) * 2; 808 int rw = int(lrint(double(x - px) / 4) * 2);
809 if (rw < 2) rw = 2; 809 if (rw < 2) rw = 2;
810 paint.drawRect(x - rw/2, h - pkh, rw, pkh/2); 810 paint.drawRect(x - rw/2, h - pkh, rw, pkh/2);
811 } else if (n == 0 || n == 5) { 811 } else if (n == 0 || n == 5) {
812 // C, F 812 // C, F
813 if (px < w) { 813 if (px < w) {