18 #include "base/AudioLevel.h" 20 #include "base/Profiler.h" 21 #include "base/RangeMapper.h" 26 #include <QTextStream> 40 m_autoNormalize(false),
43 m_channelMode(SeparateChannels),
46 m_middleLineHeight(0.5),
63 bool channelsChanged =
false;
67 channelsChanged =
true;
71 m_model->getChannelCount() != model->getChannelCount()) {
72 channelsChanged =
true;
92 list.push_back(
"Scale");
93 list.push_back(
"Gain");
94 list.push_back(
"Normalize Visible Area");
97 list.push_back(
"Channels");
106 if (name ==
"Scale")
return tr(
"Scale");
107 if (name ==
"Gain")
return tr(
"Gain");
108 if (name ==
"Normalize Visible Area")
return tr(
"Normalize Visible Area");
109 if (name ==
"Channels")
return tr(
"Channels");
116 if (name ==
"Normalize Visible Area")
return "normalise";
123 if (name ==
"Gain")
return RangeProperty;
124 if (name ==
"Normalize Visible Area")
return ToggleProperty;
125 if (name ==
"Channels")
return ValueProperty;
126 if (name ==
"Scale")
return ValueProperty;
133 if (name ==
"Gain" ||
134 name ==
"Normalize Visible Area" ||
135 name ==
"Scale")
return tr(
"Scale");
141 int *min,
int *max,
int *deflt)
const 145 int garbage0, garbage1, garbage2;
146 if (!min) min = &garbage0;
147 if (!max) max = &garbage1;
148 if (!deflt) deflt = &garbage2;
150 if (name ==
"Gain") {
156 val = lrint(log10(
m_gain) * 20.0);
157 if (val < *min) val = *min;
158 if (val > *max) val = *max;
160 }
else if (name ==
"Normalize Visible Area") {
165 }
else if (name ==
"Channels") {
174 }
else if (name ==
"Scale") {
193 if (name ==
"Scale") {
196 case 0:
return tr(
"Linear");
197 case 1:
return tr(
"Meter");
198 case 2:
return tr(
"dB");
201 if (name ==
"Channels") {
204 case 0:
return tr(
"Separate");
205 case 1:
return tr(
"Mean");
206 case 2:
return tr(
"Butterfly");
215 if (name ==
"Gain") {
216 return new LinearRangeMapper(-50, 50, -25, 25, tr(
"dB"));
224 if (name ==
"Gain") {
225 setGain(pow(10,
float(value)/20.0));
226 }
else if (name ==
"Normalize Visible Area") {
228 }
else if (name ==
"Channels") {
232 }
else if (name ==
"Scale") {
247 if (
m_gain == gain)
return;
331 int completion = 100;
333 if (
m_model->isReady(&completion))
return 100;
339 bool &, QString &unit)
const 348 min = AudioLevel::multiplier_to_dB(0.0);
349 max = AudioLevel::multiplier_to_dB(1.0);
358 if (sample < 0.0)
return dBscale(-sample, m);
359 float dB = AudioLevel::multiplier_to_dB(sample);
360 if (dB < -50.0)
return 0;
361 if (dB > 0.0)
return m;
362 return int(((dB + 50.0) * m) / 50.0 + 0.1);
367 bool &merging,
bool &mixing)
372 int channels =
m_model->getChannelCount();
373 if (channels == 0)
return 0;
375 int rawChannels = channels;
407 static float meterdbs[] = { -40, -30, -20, -15, -10,
408 -5, -3, -2, -1, -0.5, 0 };
412 int &f0,
int &f1)
const 423 f0 = f0 / modelZoomLevel;
424 f0 = f0 * modelZoomLevel;
429 f1 = f1 / modelZoomLevel;
430 f1 = f1 * modelZoomLevel;
432 return (f0 < m_model->getEndFrame());
441 int modelStart =
m_model->getStartFrame();
442 int modelEnd =
m_model->getEndFrame();
444 int rangeStart, rangeEnd;
446 if (startFrame < modelStart) rangeStart = modelStart;
447 else rangeStart = startFrame;
449 if (endFrame < 0) rangeEnd = 0;
450 else if (endFrame > modelEnd) rangeEnd = modelEnd;
451 else rangeEnd = endFrame;
453 if (rangeEnd < rangeStart) rangeEnd = rangeStart;
455 RangeSummarisableTimeValueModel::Range range =
456 m_model->getSummary(channel, rangeStart, rangeEnd - rangeStart);
458 int minChannel = 0, maxChannel = 0;
459 bool mergingChannels =
false, mixingChannels =
false;
462 mergingChannels, mixingChannels);
464 if (mergingChannels || mixingChannels) {
465 RangeSummarisableTimeValueModel::Range otherRange =
466 m_model->getSummary(1, rangeStart, rangeEnd - rangeStart);
467 range.setMax(std::max(range.max(), otherRange.max()));
468 range.setMin(std::min(range.min(), otherRange.min()));
469 range.setAbsmean(std::min(range.absmean(), otherRange.absmean()));
472 return 1.0 / std::max(fabsf(range.max()), fabsf(range.min()));
484 #ifdef DEBUG_WAVEFORM_PAINT 485 Profiler profiler(
"WaveformLayer::paint",
true);
486 cerr <<
"WaveformLayer::paint (" << rect.x() <<
"," << rect.y()
487 <<
") [" << rect.width() <<
"x" << rect.height() <<
"]: zoom " << zoomLevel << endl;
490 int channels = 0, minChannel = 0, maxChannel = 0;
491 bool mergingChannels =
false, mixingChannels =
false;
494 mergingChannels, mixingChannels);
495 if (channels == 0)
return;
500 bool ready =
m_model->isReady();
505 #ifdef DEBUG_WAVEFORM_PAINT 506 cerr <<
"WaveformLayer::paint: aggressive is true" << endl;
514 #ifdef DEBUG_WAVEFORM_PAINT 516 cerr <<
"WaveformLayer::paint: cache size " <<
m_cache->width() <<
"x" <<
m_cache->height() <<
" differs from view size " << w <<
"x" << h <<
": regenerating aggressive cache" << endl;
525 viewPainter.drawPixmap(rect, *
m_cache, rect);
531 paint->setPen(Qt::NoPen);
533 paint->drawRect(rect);
536 paint->setBrush(Qt::NoBrush);
539 paint = &viewPainter;
542 paint->setRenderHint(QPainter::Antialiasing,
false);
547 if (space > 1.0) space = 2.0 - space;
549 paint->translate(QPointF(0, yt));
550 paint->scale(1.0, space);
553 int x0 = 0, x1 = w - 1;
554 int y0 = 0, y1 = h - 1;
562 if (x1 < v->width()) ++x1;
573 int modelZoomLevel =
m_model->getSummaryBlockSize(zoomLevel);
582 #ifdef DEBUG_WAVEFORM_PAINT 583 cerr <<
"Painting waveform from " << frame0 <<
" to " << frame1 <<
" (" << (x1-x0+1) <<
" pixels at zoom " << zoomLevel <<
" and model zoom " << modelZoomLevel <<
")" << endl;
586 RangeSummarisableTimeValueModel::RangeBlock *ranges =
587 new RangeSummarisableTimeValueModel::RangeBlock;
589 RangeSummarisableTimeValueModel::RangeBlock *otherChannelRanges = 0;
590 RangeSummarisableTimeValueModel::Range range;
595 QColor midColour = baseColour;
596 if (midColour == Qt::black) {
597 midColour = Qt::gray;
599 midColour = midColour.light(150);
601 midColour = midColour.light(50);
608 for (
int ch = minChannel; ch <= maxChannel; ++ch) {
610 int prevRangeBottom = -1, prevRangeTop = -1;
611 QColor prevRangeBottomColour = baseColour, prevRangeTopColour = baseColour;
621 int m = (h / channels) / 2;
622 int my = m + (((ch - minChannel) * h) / channels);
624 #ifdef DEBUG_WAVEFORM_PAINT 625 cerr <<
"ch = " << ch <<
", channels = " << channels <<
", m = " << m <<
", my = " << my <<
", h = " << h << endl;
628 if (my - m > y1 || my + m < y0)
continue;
633 my = m + (((ch - minChannel) * h) / channels);
636 paint->setPen(greys[1]);
637 paint->drawLine(x0, my, x1, my);
646 paint->setPen(QColor(240, 240, 240));
648 for (
int i = 1; i < n; ++i) {
650 float val = 0.0, nval = 0.0;
655 val = (i * gain) / n;
656 if (i > 0) nval = -val;
660 val = AudioLevel::dB_to_multiplier(
meterdbs[i]) * gain;
664 val = AudioLevel::dB_to_multiplier(-(10*n) + i * 10) * gain;
668 if (val < -1.0 || val > 1.0)
continue;
672 if (py >= 0 && abs(y - py) < 10)
continue;
680 paint->drawLine(x0, y, x1, y);
682 paint->drawLine(x0, ny, x1, ny);
687 m_model->getSummaries(ch, frame0, frame1 - frame0,
688 *ranges, modelZoomLevel);
690 #ifdef DEBUG_WAVEFORM_PAINT 691 cerr <<
"channel " << ch <<
": " << ranges->size() <<
" ranges from " << frame0 <<
" to " << frame1 <<
" at zoom level " << modelZoomLevel << endl;
694 if (mergingChannels || mixingChannels) {
695 if (
m_model->getChannelCount() > 1) {
696 if (!otherChannelRanges) {
698 new RangeSummarisableTimeValueModel::RangeBlock;
701 (1, frame0, frame1 - frame0, *otherChannelRanges,
704 if (otherChannelRanges != ranges)
delete otherChannelRanges;
705 otherChannelRanges = ranges;
709 for (
int x = x0; x <= x1; ++x) {
711 range = RangeSummarisableTimeValueModel::Range();
718 cerr <<
"ERROR: WaveformLayer::paint: pixel " << x <<
" has f0 = " << f0 <<
" which is less than range frame0 " << frame0 <<
" for x0 = " << x0 << endl;
722 int i0 = (f0 - frame0) / modelZoomLevel;
723 int i1 = (f1 - frame0) / modelZoomLevel;
725 #ifdef DEBUG_WAVEFORM_PAINT 726 cerr <<
"WaveformLayer::paint: pixel " << x <<
": i0 " << i0 <<
" (f " << f0 <<
"), i1 " << i1 <<
" (f " << f1 <<
")" << endl;
730 cerr <<
"WaveformLayer::paint: ERROR: i1 " << i1 <<
" > i0 " << i0 <<
" plus one (zoom = " << zoomLevel <<
", model zoom = " << modelZoomLevel <<
")" << endl;
733 if (ranges && i0 < (
int)ranges->size()) {
735 range = (*ranges)[i0];
737 if (i1 > i0 && i1 < (
int)ranges->size()) {
738 range.setMax(std::max(range.max(), (*ranges)[i1].max()));
739 range.setMin(std::min(range.min(), (*ranges)[i1].min()));
740 range.setAbsmean((range.absmean() + (*ranges)[i1].absmean()) / 2);
744 #ifdef DEBUG_WAVEFORM_PAINT 745 cerr <<
"No (or not enough) ranges for i0 = " << i0 << endl;
750 int rangeBottom = 0, rangeTop = 0, meanBottom = 0, meanTop = 0;
752 if (mergingChannels) {
754 if (otherChannelRanges && i0 < (
int)otherChannelRanges->size()) {
756 range.setMax(fabsf(range.max()));
757 range.setMin(-fabsf((*otherChannelRanges)[i0].max()));
760 (*otherChannelRanges)[i0].absmean()) / 2);
762 if (i1 > i0 && i1 < (
int)otherChannelRanges->size()) {
767 -fabsf((*otherChannelRanges)[i1].max())));
771 }
else if (mixingChannels) {
773 if (otherChannelRanges && i0 < (
int)otherChannelRanges->size()) {
775 range.setMax((range.max() + (*otherChannelRanges)[i0].max()) / 2);
776 range.setMin((range.min() + (*otherChannelRanges)[i0].min()) / 2);
777 range.setAbsmean((range.absmean() + (*otherChannelRanges)[i0].absmean()) / 2);
787 rangeBottom = int( m * greyLevels * range.min() * gain);
788 rangeTop = int( m * greyLevels * range.max() * gain);
789 meanBottom = int(-m * range.absmean() * gain);
790 meanTop = int( m * range.absmean() * gain);
794 if (!mergingChannels) {
795 int db0 =
dBscale(range.min() * gain, m);
796 int db1 =
dBscale(range.max() * gain, m);
797 rangeTop = std::max(db0, db1);
798 meanTop = std::min(db0, db1);
799 if (mixingChannels) rangeBottom = meanTop;
800 else rangeBottom =
dBscale(range.absmean() * gain, m);
801 meanBottom = rangeBottom;
803 rangeBottom = -
dBscale(range.min() * gain, m * greyLevels);
804 rangeTop =
dBscale(range.max() * gain, m * greyLevels);
805 meanBottom = -
dBscale(range.absmean() * gain, m);
806 meanTop =
dBscale(range.absmean() * gain, m);
811 if (!mergingChannels) {
812 int r0 = abs(AudioLevel::multiplier_to_preview(range.min() * gain, m));
813 int r1 = abs(AudioLevel::multiplier_to_preview(range.max() * gain, m));
814 rangeTop = std::max(r0, r1);
815 meanTop = std::min(r0, r1);
816 if (mixingChannels) rangeBottom = meanTop;
817 else rangeBottom = AudioLevel::multiplier_to_preview(range.absmean() * gain, m);
818 meanBottom = rangeBottom;
820 rangeBottom = -AudioLevel::multiplier_to_preview(range.min() * gain, m * greyLevels);
821 rangeTop = AudioLevel::multiplier_to_preview(range.max() * gain, m * greyLevels);
822 meanBottom = -AudioLevel::multiplier_to_preview(range.absmean() * gain, m);
823 meanTop = AudioLevel::multiplier_to_preview(range.absmean() * gain, m);
828 rangeBottom = my * greyLevels - rangeBottom;
829 rangeTop = my * greyLevels - rangeTop;
830 meanBottom = my - meanBottom;
831 meanTop = my - meanTop;
833 int topFill = (rangeTop % greyLevels);
834 if (topFill > 0) topFill = greyLevels - topFill;
836 int bottomFill = (rangeBottom % greyLevels);
838 rangeTop = rangeTop / greyLevels;
839 rangeBottom = rangeBottom / greyLevels;
841 bool clipped =
false;
843 if (rangeTop < my - m) { rangeTop = my - m; }
844 if (rangeTop > my + m) { rangeTop = my + m; }
845 if (rangeBottom < my - m) { rangeBottom = my - m; }
846 if (rangeBottom > my + m) { rangeBottom = my + m; }
848 if (range.max() <= -1.0 ||
849 range.max() >= 1.0) clipped =
true;
851 if (meanBottom > rangeBottom) meanBottom = rangeBottom;
852 if (meanTop < rangeTop) meanTop = rangeTop;
855 if (meanTop == rangeTop) {
856 if (meanTop < meanBottom) ++meanTop;
857 else drawMean =
false;
860 if (meanBottom > meanTop) --meanBottom;
861 else drawMean =
false;
864 if (x != x0 && prevRangeBottom != -1) {
865 if (prevRangeBottom > rangeBottom + 1 &&
866 prevRangeTop > rangeBottom + 1) {
868 paint->setPen(baseColour);
869 paint->drawLine(x-1, prevRangeTop, x, rangeBottom + 1);
870 paint->setPen(prevRangeTopColour);
871 paint->drawPoint(x-1, prevRangeTop);
872 }
else if (prevRangeBottom < rangeTop - 1 &&
873 prevRangeTop < rangeTop - 1) {
875 paint->setPen(baseColour);
876 paint->drawLine(x-1, prevRangeBottom, x, rangeTop - 1);
877 paint->setPen(prevRangeBottomColour);
878 paint->drawPoint(x-1, prevRangeBottom);
886 paint->setPen(Qt::red);
888 paint->setPen(baseColour);
891 paint->setPen(midColour);
894 #ifdef DEBUG_WAVEFORM_PAINT 895 cerr <<
"range " << rangeBottom <<
" -> " << rangeTop <<
", means " << meanBottom <<
" -> " << meanTop <<
", raw range " << range.min() <<
" -> " << range.max() << endl;
898 if (rangeTop == rangeBottom) {
899 paint->drawPoint(x, rangeTop);
901 paint->drawLine(x, rangeBottom, x, rangeTop);
904 prevRangeTopColour = baseColour;
905 prevRangeBottomColour = baseColour;
909 if (rangeTop < rangeBottom) {
911 (!drawMean || (rangeTop < meanTop - 1))) {
912 paint->setPen(greys[topFill - 1]);
913 paint->drawPoint(x, rangeTop);
914 prevRangeTopColour = greys[topFill - 1];
916 if (bottomFill > 0 &&
917 (!drawMean || (rangeBottom > meanBottom + 1))) {
918 paint->setPen(greys[bottomFill - 1]);
919 paint->drawPoint(x, rangeBottom);
920 prevRangeBottomColour = greys[bottomFill - 1];
927 paint->setPen(midColour);
928 paint->drawLine(x, meanBottom, x, meanTop);
931 prevRangeBottom = rangeBottom;
932 prevRangeTop = rangeTop;
942 if (ready && rect == v->rect()) {
948 viewPainter.drawPixmap(rect, *
m_cache, rect);
951 if (otherChannelRanges != ranges)
delete otherChannelRanges;
964 int modelZoomLevel =
m_model->getSummaryBlockSize(zoomLevel);
971 RealTime rt0 = RealTime::frame2RealTime(f0,
m_model->getSampleRate());
972 RealTime rt1 = RealTime::frame2RealTime(f1,
m_model->getSampleRate());
974 if (f1 != f0 + 1 && (rt0.sec != rt1.sec || rt0.msec() != rt1.msec())) {
975 text += tr(
"Time:\t%1 - %2")
976 .arg(rt0.toText(
true).c_str())
977 .arg(rt1.toText(
true).c_str());
979 text += tr(
"Time:\t%1")
980 .arg(rt0.toText(
true).c_str());
983 int channels = 0, minChannel = 0, maxChannel = 0;
984 bool mergingChannels =
false, mixingChannels =
false;
987 mergingChannels, mixingChannels);
988 if (channels == 0)
return "";
990 for (
int ch = minChannel; ch <= maxChannel; ++ch) {
993 RangeSummarisableTimeValueModel::RangeBlock ranges;
994 m_model->getSummaries(ch, f0, f1 - f0, ranges, blockSize);
996 if (ranges.empty())
continue;
998 RangeSummarisableTimeValueModel::Range range = ranges[0];
1000 QString label = tr(
"Level:");
1001 if (minChannel != maxChannel) {
1002 if (ch == 0) label = tr(
"Left:");
1003 else if (ch == 1) label = tr(
"Right:");
1004 else label = tr(
"Channel %1").arg(ch + 1);
1007 bool singleValue =
false;
1010 if (fabs(range.min()) < 0.01) {
1013 singleValue = (min == max);
1015 int imin = lrint(range.min() * 10000);
1016 int imax = lrint(range.max() * 10000);
1017 singleValue = (imin == imax);
1018 min = float(imin)/10000;
1019 max = float(imax)/10000;
1022 int db = int(AudioLevel::multiplier_to_dB(std::max(fabsf(range.min()),
1023 fabsf(range.max())))
1027 text += tr(
"\n%1\t%2 - %3 (%4 dB peak)")
1028 .arg(label).arg(min).arg(max).arg(
float(db)/100);
1030 text += tr(
"\n%1\t%2 (%3 dB peak)")
1031 .arg(label).arg(min).arg(
float(db)/100);
1041 int channels = 0, minChannel = 0, maxChannel = 0;
1042 bool mergingChannels =
false, mixingChannels =
false;
1045 mergingChannels, mixingChannels);
1046 if (channels == 0)
return 0;
1047 if (maxChannel < minChannel || channel < minChannel)
return 0;
1049 int h = v->height();
1050 int m = (h / channels) / 2;
1057 int my = m + (((channel - minChannel) * h) / channels);
1064 vy = int(m * value);
1068 vy = AudioLevel::multiplier_to_preview(value, m);
1084 int channels = 0, minChannel = 0, maxChannel = 0;
1085 bool mergingChannels =
false, mixingChannels =
false;
1088 mergingChannels, mixingChannels);
1089 if (channels == 0)
return 0;
1090 if (maxChannel < minChannel)
return 0;
1092 int h = v->height();
1093 int m = (h / channels) / 2;
1100 channel = (y * channels) / h + minChannel;
1102 int my = m + (((channel - minChannel) * h) / channels);
1106 float thresh = -50.f;
1111 value = float(vy) / m;
1115 value = AudioLevel::preview_to_multiplier(vy, m);
1119 value = (-thresh * float(vy)) / m + thresh;
1120 value = AudioLevel::dB_to_multiplier(value);
1129 float &value, QString &unit)
const 1137 float thresh = -50.f;
1140 value = 10.f * log10f(value);
1141 if (value < thresh) value = thresh;
1142 }
else value = thresh;
1155 float &diff, QString &unit)
const 1170 float thresh = -50.f;
1172 if (v1 == v0) diff = thresh;
1174 if (v1 > v0) diff = v0 / v1;
1175 else diff = v1 / v0;
1177 diff = 10.f * log10f(diff);
1178 if (diff < thresh) diff = thresh;
1184 diff = fabsf(v1 - v0);
1195 return paint.fontMetrics().width(
"0.0") + 13;
1197 return std::max(
paint.fontMetrics().width(tr(
"0dB")),
1198 paint.fontMetrics().width(tr(
"-Inf"))) + 13;
1209 int channels = 0, minChannel = 0, maxChannel = 0;
1210 bool mergingChannels =
false, mixingChannels =
false;
1213 mergingChannels, mixingChannels);
1214 if (channels == 0)
return;
1216 int h = rect.height(), w = rect.width();
1217 int textHeight =
paint.fontMetrics().height();
1218 int toff = -textHeight/2 +
paint.fontMetrics().ascent() + 1;
1222 for (
int ch = minChannel; ch <= maxChannel; ++ch) {
1224 int lastLabelledY = -1;
1230 for (
int i = 0; i <= n; ++i) {
1232 float val = 0.0, nval = 0.0;
1238 val = (i * gain) / n;
1239 text = QString(
"%1").arg(
float(i) / n);
1240 if (i == 0) text =
"0.0";
1243 if (i == n) text =
"1.0";
1248 val = AudioLevel::dB_to_multiplier(
meterdbs[i]) * gain;
1249 text = QString(
"%1").arg(
meterdbs[i]);
1250 if (i == n) text = tr(
"0dB");
1258 val = AudioLevel::dB_to_multiplier(-(10*n) + i * 10) * gain;
1259 text = QString(
"%1").arg(-(10*n) + i * 10);
1260 if (i == n) text = tr(
"0dB");
1268 if (val < -1.0 || val > 1.0)
continue;
1277 bool spaceForLabel = (i == 0 ||
1278 abs(y - lastLabelledY) >= textHeight - 1);
1280 if (spaceForLabel) {
1284 tx = w - 10 -
paint.fontMetrics().width(text);
1288 if (ty <
paint.fontMetrics().ascent()) {
1289 ty =
paint.fontMetrics().ascent();
1290 }
else if (ty > h -
paint.fontMetrics().descent()) {
1291 ty = h -
paint.fontMetrics().descent();
1295 paint.drawText(tx, ty, text);
1297 lastLabelledY = ty - toff;
1301 if (ty <
paint.fontMetrics().ascent()) {
1302 ty =
paint.fontMetrics().ascent();
1303 }
else if (ty > h -
paint.fontMetrics().descent()) {
1304 ty = h -
paint.fontMetrics().descent();
1308 paint.drawText(tx, ty, text);
1311 paint.drawLine(w - 7, y, w, y);
1312 if (ny != y)
paint.drawLine(w - 7, ny, w, ny);
1316 paint.drawLine(w - 4, y, w, y);
1317 if (ny != y)
paint.drawLine(w - 4, ny, w, ny);
1325 QString indent, QString extraAttributes)
const 1329 QString colourName, colourSpec, darkbg;
1331 (
m_colour, colourName, colourSpec, darkbg);
1333 s += QString(
"gain=\"%1\" " 1336 "channelMode=\"%4\" " 1339 "middleLineHeight=\"%7\" " 1340 "aggressive=\"%8\" " 1341 "autoNormalize=\"%9\"")
1362 float gain = attributes.value(
"gain").toFloat(&ok);
1365 bool showMeans = (attributes.value(
"showMeans") ==
"1" ||
1366 attributes.value(
"showMeans") ==
"true");
1369 bool greyscale = (attributes.value(
"greyscale") ==
"1" ||
1370 attributes.value(
"greyscale") ==
"true");
1374 attributes.value(
"channelMode").toInt(&ok);
1377 int channel = attributes.value(
"channel").toInt(&ok);
1380 Scale scale = (
Scale)attributes.value(
"scale").toInt(&ok);
1383 float middleLineHeight = attributes.value(
"middleLineHeight").toFloat(&ok);
1386 bool aggressive = (attributes.value(
"aggressive") ==
"1" ||
1387 attributes.value(
"aggressive") ==
"true");
1390 bool autoNormalize = (attributes.value(
"autoNormalize") ==
"1" ||
1391 attributes.value(
"autoNormalize") ==
"true");
1405 int val = lrint(log10(
m_gain) * 20.0) + 50;
1406 if (val < 0) val = 0;
1407 if (val > 100) val = 100;
1414 setGain(pow(10,
float(step - 50) / 20.0));
int getFrameForX(int x) const
Return the closest frame to the given pixel x-coordinate.
void connectSignals(const Model *)
void getStringValues(int index, QString &colourName, QString &colourSpec, QString &darkbg) const
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Convert the layer's data (though not those of the model it refers to) into XML for file output.
virtual ViewManager * getViewManager() const
virtual bool hasLightBackground() const
int getZoomLevel() const
Return the zoom level, i.e.
virtual QColor getForegroundQColor(View *v) const
virtual QColor getBaseQColor() const
bool shouldShowScaleGuides() const
std::vector< QColor > getPartialShades(View *v) const
virtual QString getPropertyLabel(const PropertyName &) const
int getStartFrame() const
Retrieve the first visible sample frame on the widget.
virtual QColor getBackgroundQColor(View *v) const
void layerParametersChanged()
void verticalZoomChanged()
virtual void setProperties(const QXmlAttributes &attributes)
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
int getEndFrame() const
Retrieve the last visible sample frame on the widget.
virtual int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const
View is the base class of widgets that display one or more overlaid views of data against a horizonta...
virtual QString getPropertyValueLabel(const PropertyName &, int value) const
virtual PropertyList getProperties() const
virtual PropertyType getPropertyType(const PropertyName &) const
static ColourDatabase * getInstance()
virtual void setProperty(const PropertyName &, int value)