00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "SliceLayer.h"
00018
00019 #include "view/View.h"
00020 #include "base/AudioLevel.h"
00021 #include "base/RangeMapper.h"
00022 #include "base/RealTime.h"
00023 #include "base/ColourMapper.h"
00024 #include "base/ColourDatabase.h"
00025
00026 #include "PaintAssistant.h"
00027
00028 #include <QPainter>
00029 #include <QPainterPath>
00030 #include <QTextStream>
00031
00032
00033 SliceLayer::SliceLayer() :
00034 m_sliceableModel(0),
00035 m_colourMap(0),
00036 m_energyScale(dBScale),
00037 m_samplingMode(SampleMean),
00038 m_plotStyle(PlotSteps),
00039 m_binScale(LinearBins),
00040 m_normalize(false),
00041 m_threshold(0.0),
00042 m_initialThreshold(0.0),
00043 m_gain(1.0),
00044 m_currentf0(0),
00045 m_currentf1(0)
00046 {
00047 }
00048
00049 SliceLayer::~SliceLayer()
00050 {
00051
00052 }
00053
00054 void
00055 SliceLayer::setSliceableModel(const Model *model)
00056 {
00057 const DenseThreeDimensionalModel *sliceable =
00058 dynamic_cast<const DenseThreeDimensionalModel *>(model);
00059
00060 if (model && !sliceable) {
00061 std::cerr << "WARNING: SliceLayer::setSliceableModel(" << model
00062 << "): model is not a DenseThreeDimensionalModel" << std::endl;
00063 }
00064
00065 if (m_sliceableModel == sliceable) return;
00066
00067 m_sliceableModel = sliceable;
00068
00069 connectSignals(m_sliceableModel);
00070
00071 emit modelReplaced();
00072 }
00073
00074 void
00075 SliceLayer::sliceableModelReplaced(const Model *orig, const Model *replacement)
00076 {
00077 std::cerr << "SliceLayer::sliceableModelReplaced(" << orig << ", " << replacement << ")" << std::endl;
00078
00079 if (orig == m_sliceableModel) {
00080 setSliceableModel
00081 (dynamic_cast<const DenseThreeDimensionalModel *>(replacement));
00082 }
00083 }
00084
00085 void
00086 SliceLayer::modelAboutToBeDeleted(Model *m)
00087 {
00088 std::cerr << "SliceLayer::modelAboutToBeDeleted(" << m << ")" << std::endl;
00089
00090 if (m == m_sliceableModel) {
00091 setSliceableModel(0);
00092 }
00093 }
00094
00095 QString
00096 SliceLayer::getFeatureDescription(View *v, QPoint &p) const
00097 {
00098 int minbin, maxbin, range;
00099 return getFeatureDescription(v, p, true, minbin, maxbin, range);
00100 }
00101
00102 QString
00103 SliceLayer::getFeatureDescription(View *v, QPoint &p,
00104 bool includeBinDescription,
00105 int &minbin, int &maxbin, int &range) const
00106 {
00107 minbin = 0;
00108 maxbin = 0;
00109 if (!m_sliceableModel) return "";
00110
00111 int xorigin = m_xorigins[v];
00112 int w = v->width() - xorigin - 1;
00113
00114 int mh = m_sliceableModel->getHeight();
00115 minbin = getBinForX(p.x() - xorigin, mh, w);
00116 maxbin = getBinForX(p.x() - xorigin + 1, mh, w);
00117
00118 if (minbin >= mh) minbin = mh - 1;
00119 if (maxbin >= mh) maxbin = mh - 1;
00120 if (minbin < 0) minbin = 0;
00121 if (maxbin < 0) maxbin = 0;
00122
00123 int sampleRate = m_sliceableModel->getSampleRate();
00124
00125 size_t f0 = m_currentf0;
00126 size_t f1 = m_currentf1;
00127
00128 RealTime rt0 = RealTime::frame2RealTime(f0, sampleRate);
00129 RealTime rt1 = RealTime::frame2RealTime(f1, sampleRate);
00130
00131 range = f1 - f0 + 1;
00132
00133 QString rtrangestr = QString("%1 s").arg((rt1 - rt0).toText().c_str());
00134
00135 if (includeBinDescription) {
00136
00137 float minvalue = 0.f;
00138 if (minbin < int(m_values.size())) minvalue = m_values[minbin];
00139
00140 float maxvalue = minvalue;
00141 if (maxbin < int(m_values.size())) maxvalue = m_values[maxbin];
00142
00143 if (minvalue > maxvalue) std::swap(minvalue, maxvalue);
00144
00145 QString binstr;
00146 if (maxbin != minbin) {
00147 binstr = tr("%1 - %2").arg(minbin+1).arg(maxbin+1);
00148 } else {
00149 binstr = QString("%1").arg(minbin+1);
00150 }
00151
00152 QString valuestr;
00153 if (maxvalue != minvalue) {
00154 valuestr = tr("%1 - %2").arg(minvalue).arg(maxvalue);
00155 } else {
00156 valuestr = QString("%1").arg(minvalue);
00157 }
00158
00159 QString description = tr("Time:\t%1 - %2\nRange:\t%3 samples (%4)\nBin:\t%5\n%6 value:\t%7")
00160 .arg(QString::fromStdString(rt0.toText(true)))
00161 .arg(QString::fromStdString(rt1.toText(true)))
00162 .arg(range)
00163 .arg(rtrangestr)
00164 .arg(binstr)
00165 .arg(m_samplingMode == NearestSample ? tr("First") :
00166 m_samplingMode == SampleMean ? tr("Mean") : tr("Peak"))
00167 .arg(valuestr);
00168
00169 return description;
00170
00171 } else {
00172
00173 QString description = tr("Time:\t%1 - %2\nRange:\t%3 samples (%4)")
00174 .arg(QString::fromStdString(rt0.toText(true)))
00175 .arg(QString::fromStdString(rt1.toText(true)))
00176 .arg(range)
00177 .arg(rtrangestr);
00178
00179 return description;
00180 }
00181 }
00182
00183 float
00184 SliceLayer::getXForBin(int bin, int count, float w) const
00185 {
00186 float x = 0;
00187
00188 switch (m_binScale) {
00189
00190 case LinearBins:
00191 x = (float(w) * bin) / count;
00192 break;
00193
00194 case LogBins:
00195 x = (float(w) * log10f(bin + 1)) / log10f(count + 1);
00196 break;
00197
00198 case InvertedLogBins:
00199 x = w - (float(w) * log10f(count - bin - 1)) / log10f(count);
00200 break;
00201 }
00202
00203 return x;
00204 }
00205
00206 int
00207 SliceLayer::getBinForX(float x, int count, float w) const
00208 {
00209 int bin = 0;
00210
00211 switch (m_binScale) {
00212
00213 case LinearBins:
00214 bin = int((x * count) / w + 0.0001);
00215 break;
00216
00217 case LogBins:
00218 bin = int(powf(10.f, (x * log10f(count + 1)) / w) - 1 + 0.0001);
00219 break;
00220
00221 case InvertedLogBins:
00222 bin = count + 1 - int(powf(10.f, (log10f(count) * (w - x)) / float(w)) + 0.0001);
00223 break;
00224 }
00225
00226 return bin;
00227 }
00228
00229 float
00230 SliceLayer::getYForValue(float value, const View *v, float &norm) const
00231 {
00232 norm = 0.f;
00233
00234 if (m_yorigins.find(v) == m_yorigins.end()) return 0;
00235
00236 value *= m_gain;
00237
00238 int yorigin = m_yorigins[v];
00239 int h = m_heights[v];
00240 float thresh = getThresholdDb();
00241
00242 float y = 0.f;
00243
00244 if (h <= 0) return y;
00245
00246 switch (m_energyScale) {
00247
00248 case dBScale:
00249 {
00250 float db = thresh;
00251 if (value > 0.f) db = 10.f * log10f(value);
00252 if (db < thresh) db = thresh;
00253 norm = (db - thresh) / -thresh;
00254 y = yorigin - (float(h) * norm);
00255 break;
00256 }
00257
00258 case MeterScale:
00259 y = AudioLevel::multiplier_to_preview(value, h);
00260 norm = float(y) / float(h);
00261 y = yorigin - y;
00262 break;
00263
00264 default:
00265
00266 norm = (fabsf(value) - m_threshold);
00267 if (norm < 0) norm = 0;
00268 y = yorigin - (float(h) * norm);
00269 break;
00270 }
00271
00272 return y;
00273 }
00274
00275 float
00276 SliceLayer::getValueForY(float y, const View *v) const
00277 {
00278 float value = 0.f;
00279
00280 if (m_yorigins.find(v) == m_yorigins.end()) return value;
00281
00282 int yorigin = m_yorigins[v];
00283 int h = m_heights[v];
00284 float thresh = getThresholdDb();
00285
00286 if (h <= 0) return value;
00287
00288 y = yorigin - y;
00289
00290 switch (m_energyScale) {
00291
00292 case dBScale:
00293 {
00294 float db = ((y / h) * -thresh) + thresh;
00295 value = powf(10.f, db/10.f);
00296 break;
00297 }
00298
00299 case MeterScale:
00300 value = AudioLevel::preview_to_multiplier(lrintf(y), h);
00301 break;
00302
00303 default:
00304 value = y / h + m_threshold;
00305 }
00306
00307 return value / m_gain;
00308 }
00309
00310 void
00311 SliceLayer::paint(View *v, QPainter &paint, QRect rect) const
00312 {
00313 if (!m_sliceableModel || !m_sliceableModel->isOK() ||
00314 !m_sliceableModel->isReady()) return;
00315
00316 paint.save();
00317 paint.setRenderHint(QPainter::Antialiasing, false);
00318
00319 if (v->getViewManager() && v->getViewManager()->shouldShowScaleGuides()) {
00320 if (!m_scalePoints.empty()) {
00321 paint.setPen(QColor(240, 240, 240));
00322 for (size_t i = 0; i < m_scalePoints.size(); ++i) {
00323 paint.drawLine(0, m_scalePoints[i], rect.width(), m_scalePoints[i]);
00324 }
00325 }
00326 }
00327
00328 paint.setPen(getBaseQColor());
00329
00330 int xorigin = getVerticalScaleWidth(v, paint) + 1;
00331 int w = v->width() - xorigin - 1;
00332
00333 m_xorigins[v] = xorigin;
00334
00335 int yorigin = v->height() - 20 - paint.fontMetrics().height() - 7;
00336 int h = yorigin - paint.fontMetrics().height() - 8;
00337
00338 m_yorigins[v] = yorigin;
00339 m_heights[v] = h;
00340
00341 if (h <= 0) return;
00342
00343 QPainterPath path;
00344
00345 size_t mh = m_sliceableModel->getHeight();
00346
00347 int divisor = 0;
00348
00349 m_values.clear();
00350 for (size_t bin = 0; bin < mh; ++bin) {
00351 m_values.push_back(0.f);
00352 }
00353
00354 size_t f0 = v->getCentreFrame();
00355 int f0x = v->getXForFrame(f0);
00356 f0 = v->getFrameForX(f0x);
00357 size_t f1 = v->getFrameForX(f0x + 1);
00358 if (f1 > f0) --f1;
00359
00360
00361
00362 size_t res = m_sliceableModel->getResolution();
00363 size_t col0 = f0 / res;
00364 size_t col1 = col0;
00365 if (m_samplingMode != NearestSample) col1 = f1 / res;
00366 f0 = col0 * res;
00367 f1 = (col1 + 1) * res - 1;
00368
00369
00370
00371 m_currentf0 = f0;
00372 m_currentf1 = f1;
00373
00374 BiasCurve curve;
00375 getBiasCurve(curve);
00376 size_t cs = curve.size();
00377
00378 for (size_t col = col0; col <= col1; ++col) {
00379 for (size_t bin = 0; bin < mh; ++bin) {
00380 float value = m_sliceableModel->getValueAt(col, bin);
00381 if (bin < cs) value *= curve[bin];
00382 if (m_samplingMode == SamplePeak) {
00383 if (value > m_values[bin]) m_values[bin] = value;
00384 } else {
00385 m_values[bin] += value;
00386 }
00387 }
00388 ++divisor;
00389 }
00390
00391 float max = 0.f;
00392 for (size_t bin = 0; bin < mh; ++bin) {
00393 if (m_samplingMode == SampleMean) m_values[bin] /= divisor;
00394 if (m_values[bin] > max) max = m_values[bin];
00395 }
00396 if (max != 0.f && m_normalize) {
00397 for (size_t bin = 0; bin < mh; ++bin) {
00398 m_values[bin] /= max;
00399 }
00400 }
00401
00402 float py = 0;
00403 float nx = xorigin;
00404
00405 ColourMapper mapper(m_colourMap, 0, 1);
00406
00407 for (size_t bin = 0; bin < mh; ++bin) {
00408
00409 float x = nx;
00410 nx = xorigin + getXForBin(bin + 1, mh, w);
00411
00412 float value = m_values[bin];
00413 float norm = 0.f;
00414 float y = getYForValue(value, v, norm);
00415
00416 if (m_plotStyle == PlotLines) {
00417
00418 if (bin == 0) {
00419 path.moveTo(x, y);
00420 } else {
00421 path.lineTo(x, y);
00422 }
00423
00424 } else if (m_plotStyle == PlotSteps) {
00425
00426 if (bin == 0) {
00427 path.moveTo(x, y);
00428 } else {
00429 path.lineTo(x, y);
00430 }
00431 path.lineTo(nx, y);
00432
00433 } else if (m_plotStyle == PlotBlocks) {
00434
00435 path.moveTo(x, yorigin);
00436 path.lineTo(x, y);
00437 path.lineTo(nx, y);
00438 path.lineTo(nx, yorigin);
00439 path.lineTo(x, yorigin);
00440
00441 } else if (m_plotStyle == PlotFilledBlocks) {
00442
00443 paint.fillRect(QRectF(x, y, nx - x, yorigin - y), mapper.map(norm));
00444 }
00445
00446 py = y;
00447 }
00448
00449 if (m_plotStyle != PlotFilledBlocks) {
00450 paint.drawPath(path);
00451 }
00452 paint.restore();
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 }
00496
00497 int
00498 SliceLayer::getVerticalScaleWidth(View *, QPainter &paint) const
00499 {
00500 if (m_energyScale == LinearScale) {
00501 return std::max(paint.fontMetrics().width("0.0") + 13,
00502 paint.fontMetrics().width("x10-10"));
00503 } else {
00504 return std::max(paint.fontMetrics().width(tr("0dB")),
00505 paint.fontMetrics().width(tr("-Inf"))) + 13;
00506 }
00507 }
00508
00509 void
00510 SliceLayer::paintVerticalScale(View *v, QPainter &paint, QRect rect) const
00511 {
00512 float thresh = m_threshold;
00513 if (m_energyScale != LinearScale) {
00514 thresh = AudioLevel::dB_to_multiplier(getThresholdDb());
00515 }
00516
00517
00518
00519
00520 int yorigin = v->height() - 20 - paint.fontMetrics().height() - 6;
00521 int h = yorigin - paint.fontMetrics().height() - 8;
00522 if (h < 0) return;
00523
00524 QRect actual(rect.x(), rect.y() + yorigin - h, rect.width(), h);
00525
00526 int mult = 1;
00527
00528 PaintAssistant::paintVerticalLevelScale
00529 (paint, actual, thresh, 1.0 / m_gain,
00530 PaintAssistant::Scale(m_energyScale),
00531 mult,
00532 const_cast<std::vector<int> *>(&m_scalePoints));
00533
00534 if (mult != 1 && mult != 0) {
00535 int log = lrintf(log10f(mult));
00536 QString a = tr("x10");
00537 QString b = QString("%1").arg(-log);
00538 paint.drawText(3, 8 + paint.fontMetrics().ascent(), a);
00539 paint.drawText(3 + paint.fontMetrics().width(a),
00540 3 + paint.fontMetrics().ascent(), b);
00541 }
00542 }
00543
00544 Layer::PropertyList
00545 SliceLayer::getProperties() const
00546 {
00547 PropertyList list = SingleColourLayer::getProperties();
00548 list.push_back("Plot Type");
00549
00550 list.push_back("Scale");
00551 list.push_back("Normalize");
00552 list.push_back("Threshold");
00553 list.push_back("Gain");
00554 list.push_back("Bin Scale");
00555
00556 return list;
00557 }
00558
00559 QString
00560 SliceLayer::getPropertyLabel(const PropertyName &name) const
00561 {
00562 if (name == "Plot Type") return tr("Plot Type");
00563 if (name == "Scale") return tr("Scale");
00564 if (name == "Normalize") return tr("Normalize");
00565 if (name == "Threshold") return tr("Threshold");
00566 if (name == "Gain") return tr("Gain");
00567 if (name == "Sampling Mode") return tr("Sampling Mode");
00568 if (name == "Bin Scale") return tr("Plot X Scale");
00569 return SingleColourLayer::getPropertyLabel(name);
00570 }
00571
00572 QString
00573 SliceLayer::getPropertyIconName(const PropertyName &name) const
00574 {
00575 if (name == "Normalize") return "normalise";
00576 return "";
00577 }
00578
00579 Layer::PropertyType
00580 SliceLayer::getPropertyType(const PropertyName &name) const
00581 {
00582 if (name == "Gain") return RangeProperty;
00583 if (name == "Normalize") return ToggleProperty;
00584 if (name == "Threshold") return RangeProperty;
00585 if (name == "Plot Type") return ValueProperty;
00586 if (name == "Scale") return ValueProperty;
00587 if (name == "Sampling Mode") return ValueProperty;
00588 if (name == "Bin Scale") return ValueProperty;
00589 if (name == "Colour" && m_plotStyle == PlotFilledBlocks) return ValueProperty;
00590 return SingleColourLayer::getPropertyType(name);
00591 }
00592
00593 QString
00594 SliceLayer::getPropertyGroupName(const PropertyName &name) const
00595 {
00596 if (name == "Scale" ||
00597 name == "Normalize" ||
00598 name == "Sampling Mode" ||
00599 name == "Threshold" ||
00600 name == "Gain") return tr("Scale");
00601 if (name == "Plot Type" ||
00602 name == "Bin Scale") return tr("Plot Type");
00603 return SingleColourLayer::getPropertyGroupName(name);
00604 }
00605
00606 int
00607 SliceLayer::getPropertyRangeAndValue(const PropertyName &name,
00608 int *min, int *max, int *deflt) const
00609 {
00610 int val = 0;
00611
00612 int garbage0, garbage1, garbage2;
00613 if (!min) min = &garbage0;
00614 if (!max) max = &garbage1;
00615 if (!deflt) deflt = &garbage2;
00616
00617 if (name == "Gain") {
00618
00619 *min = -50;
00620 *max = 50;
00621 *deflt = 0;
00622
00623 std::cerr << "gain is " << m_gain << ", mode is " << m_samplingMode << std::endl;
00624
00625 val = lrint(log10(m_gain) * 20.0);
00626 if (val < *min) val = *min;
00627 if (val > *max) val = *max;
00628
00629 } else if (name == "Threshold") {
00630
00631 *min = -80;
00632 *max = 0;
00633
00634 *deflt = lrintf(AudioLevel::multiplier_to_dB(m_initialThreshold));
00635 if (*deflt < *min) *deflt = *min;
00636 if (*deflt > *max) *deflt = *max;
00637
00638 val = lrintf(AudioLevel::multiplier_to_dB(m_threshold));
00639 if (val < *min) val = *min;
00640 if (val > *max) val = *max;
00641
00642 } else if (name == "Normalize") {
00643
00644 val = (m_normalize ? 1 : 0);
00645 *deflt = 0;
00646
00647 } else if (name == "Colour" && m_plotStyle == PlotFilledBlocks) {
00648
00649 *min = 0;
00650 *max = ColourMapper::getColourMapCount() - 1;
00651 *deflt = 0;
00652
00653 val = m_colourMap;
00654
00655 } else if (name == "Scale") {
00656
00657 *min = 0;
00658 *max = 2;
00659 *deflt = (int)dBScale;
00660
00661 val = (int)m_energyScale;
00662
00663 } else if (name == "Sampling Mode") {
00664
00665 *min = 0;
00666 *max = 2;
00667 *deflt = (int)SampleMean;
00668
00669 val = (int)m_samplingMode;
00670
00671 } else if (name == "Plot Type") {
00672
00673 *min = 0;
00674 *max = 3;
00675 *deflt = (int)PlotSteps;
00676
00677 val = (int)m_plotStyle;
00678
00679 } else if (name == "Bin Scale") {
00680
00681 *min = 0;
00682 *max = 2;
00683 *deflt = (int)LinearBins;
00684
00685
00686 val = (int)m_binScale;
00687
00688 } else {
00689 val = SingleColourLayer::getPropertyRangeAndValue(name, min, max, deflt);
00690 }
00691
00692 return val;
00693 }
00694
00695 QString
00696 SliceLayer::getPropertyValueLabel(const PropertyName &name,
00697 int value) const
00698 {
00699 if (name == "Colour" && m_plotStyle == PlotFilledBlocks) {
00700 return ColourMapper::getColourMapName(value);
00701 }
00702 if (name == "Scale") {
00703 switch (value) {
00704 default:
00705 case 0: return tr("Linear");
00706 case 1: return tr("Meter");
00707 case 2: return tr("dB");
00708 }
00709 }
00710 if (name == "Sampling Mode") {
00711 switch (value) {
00712 default:
00713 case 0: return tr("Any");
00714 case 1: return tr("Mean");
00715 case 2: return tr("Peak");
00716 }
00717 }
00718 if (name == "Plot Type") {
00719 switch (value) {
00720 default:
00721 case 0: return tr("Lines");
00722 case 1: return tr("Steps");
00723 case 2: return tr("Blocks");
00724 case 3: return tr("Colours");
00725 }
00726 }
00727 if (name == "Bin Scale") {
00728 switch (value) {
00729 default:
00730 case 0: return tr("Linear Bins");
00731 case 1: return tr("Log Bins");
00732 case 2: return tr("Rev Log Bins");
00733 }
00734 }
00735 return SingleColourLayer::getPropertyValueLabel(name, value);
00736 }
00737
00738 RangeMapper *
00739 SliceLayer::getNewPropertyRangeMapper(const PropertyName &name) const
00740 {
00741 if (name == "Gain") {
00742 return new LinearRangeMapper(-50, 50, -25, 25, tr("dB"));
00743 }
00744 if (name == "Threshold") {
00745 return new LinearRangeMapper(-80, 0, -80, 0, tr("dB"));
00746 }
00747 return SingleColourLayer::getNewPropertyRangeMapper(name);
00748 }
00749
00750 void
00751 SliceLayer::setProperty(const PropertyName &name, int value)
00752 {
00753 if (name == "Gain") {
00754 setGain(pow(10, float(value)/20.0));
00755 } else if (name == "Threshold") {
00756 if (value == -80) setThreshold(0.0);
00757 else setThreshold(AudioLevel::dB_to_multiplier(value));
00758 } else if (name == "Colour" && m_plotStyle == PlotFilledBlocks) {
00759 setFillColourMap(value);
00760 } else if (name == "Scale") {
00761 switch (value) {
00762 default:
00763 case 0: setEnergyScale(LinearScale); break;
00764 case 1: setEnergyScale(MeterScale); break;
00765 case 2: setEnergyScale(dBScale); break;
00766 }
00767 } else if (name == "Plot Type") {
00768 setPlotStyle(PlotStyle(value));
00769 } else if (name == "Sampling Mode") {
00770 switch (value) {
00771 default:
00772 case 0: setSamplingMode(NearestSample); break;
00773 case 1: setSamplingMode(SampleMean); break;
00774 case 2: setSamplingMode(SamplePeak); break;
00775 }
00776 } else if (name == "Bin Scale") {
00777 switch (value) {
00778 default:
00779 case 0: setBinScale(LinearBins); break;
00780 case 1: setBinScale(LogBins); break;
00781 case 2: setBinScale(InvertedLogBins); break;
00782 }
00783 } else if (name == "Normalize") {
00784 setNormalize(value ? true : false);
00785 } else {
00786 SingleColourLayer::setProperty(name, value);
00787 }
00788 }
00789
00790 void
00791 SliceLayer::setFillColourMap(int map)
00792 {
00793 if (m_colourMap == map) return;
00794 m_colourMap = map;
00795 emit layerParametersChanged();
00796 }
00797
00798 void
00799 SliceLayer::setEnergyScale(EnergyScale scale)
00800 {
00801 if (m_energyScale == scale) return;
00802 m_energyScale = scale;
00803 emit layerParametersChanged();
00804 }
00805
00806 void
00807 SliceLayer::setSamplingMode(SamplingMode mode)
00808 {
00809 if (m_samplingMode == mode) return;
00810 m_samplingMode = mode;
00811 emit layerParametersChanged();
00812 }
00813
00814 void
00815 SliceLayer::setPlotStyle(PlotStyle style)
00816 {
00817 if (m_plotStyle == style) return;
00818 bool colourTypeChanged = (style == PlotFilledBlocks ||
00819 m_plotStyle == PlotFilledBlocks);
00820 m_plotStyle = style;
00821 if (colourTypeChanged) {
00822 emit layerParameterRangesChanged();
00823 }
00824 emit layerParametersChanged();
00825 }
00826
00827 void
00828 SliceLayer::setBinScale(BinScale scale)
00829 {
00830 if (m_binScale == scale) return;
00831 m_binScale = scale;
00832 emit layerParametersChanged();
00833 }
00834
00835 void
00836 SliceLayer::setNormalize(bool n)
00837 {
00838 if (m_normalize == n) return;
00839 m_normalize = n;
00840 emit layerParametersChanged();
00841 }
00842
00843 void
00844 SliceLayer::setThreshold(float thresh)
00845 {
00846 if (m_threshold == thresh) return;
00847 m_threshold = thresh;
00848 emit layerParametersChanged();
00849 }
00850
00851 void
00852 SliceLayer::setGain(float gain)
00853 {
00854 if (m_gain == gain) return;
00855 m_gain = gain;
00856 emit layerParametersChanged();
00857 }
00858
00859 float
00860 SliceLayer::getThresholdDb() const
00861 {
00862 if (m_threshold == 0.0) return -80.f;
00863 float db = AudioLevel::multiplier_to_dB(m_threshold);
00864 return db;
00865 }
00866
00867 int
00868 SliceLayer::getDefaultColourHint(bool darkbg, bool &impose)
00869 {
00870 impose = false;
00871 return ColourDatabase::getInstance()->getColourIndex
00872 (QString(darkbg ? "Bright Blue" : "Blue"));
00873 }
00874
00875 void
00876 SliceLayer::toXml(QTextStream &stream,
00877 QString indent, QString extraAttributes) const
00878 {
00879 QString s;
00880
00881 s += QString("colourScheme=\"%1\" "
00882 "energyScale=\"%2\" "
00883 "samplingMode=\"%3\" "
00884 "gain=\"%4\" "
00885 "normalize=\"%5\"")
00886 .arg(m_colourMap)
00887 .arg(m_energyScale)
00888 .arg(m_samplingMode)
00889 .arg(m_gain)
00890 .arg(m_normalize ? "true" : "false");
00891
00892 SingleColourLayer::toXml(stream, indent, extraAttributes + " " + s);
00893 }
00894
00895 void
00896 SliceLayer::setProperties(const QXmlAttributes &attributes)
00897 {
00898 bool ok = false;
00899
00900 SingleColourLayer::setProperties(attributes);
00901
00902 EnergyScale scale = (EnergyScale)
00903 attributes.value("energyScale").toInt(&ok);
00904 if (ok) setEnergyScale(scale);
00905
00906 SamplingMode mode = (SamplingMode)
00907 attributes.value("samplingMode").toInt(&ok);
00908 if (ok) setSamplingMode(mode);
00909
00910 int colourMap = attributes.value("colourScheme").toInt(&ok);
00911 if (ok) setFillColourMap(colourMap);
00912
00913 float gain = attributes.value("gain").toFloat(&ok);
00914 if (ok) setGain(gain);
00915
00916 bool normalize = (attributes.value("normalize").trimmed() == "true");
00917 setNormalize(normalize);
00918 }
00919
00920 bool
00921 SliceLayer::getValueExtents(float &, float &, bool &, QString &) const
00922 {
00923 return false;
00924 }
00925