SliceLayer.cpp

Go to the documentation of this file.
00001 
00002 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00003 
00004 /*
00005     Sonic Visualiser
00006     An audio file viewer and annotation editor.
00007     Centre for Digital Music, Queen Mary, University of London.
00008     This file copyright 2006-2007 QMUL.
00009     
00010     This program is free software; you can redistribute it and/or
00011     modify it under the terms of the GNU General Public License as
00012     published by the Free Software Foundation; either version 2 of the
00013     License, or (at your option) any later version.  See the file
00014     COPYING included with this distribution for more information.
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 //        std::cerr << "thresh = " << m_threshold << std::endl;
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; // for use in getFeatureDescription
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; // for getYForValue etc
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 //    std::cerr << "centre frame " << v->getCentreFrame() << ", x " << f0x << ", f0 " << f0 << ", f1 " << f1 << std::endl;
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 //    std::cerr << "resolution " << res << ", col0 " << col0 << ", col1 " << col1 << ", f0 " << f0 << ", f1 " << f1 << std::endl;
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     QPoint discard;
00455 
00456     if (v->getViewManager() && v->getViewManager()->shouldShowFrameCount() &&
00457         v->shouldIlluminateLocalFeatures(this, discard)) {
00458 
00459         int sampleRate = m_sliceableModel->getSampleRate();
00460 
00461         QString startText = QString("%1 / %2")
00462             .arg(QString::fromStdString
00463                  (RealTime::frame2RealTime
00464                   (f0, sampleRate).toText(true)))
00465             .arg(f0);
00466 
00467         QString endText = QString(" %1 / %2")
00468             .arg(QString::fromStdString
00469                  (RealTime::frame2RealTime
00470                   (f1, sampleRate).toText(true)))
00471             .arg(f1);
00472 
00473         QString durationText = QString("(%1 / %2) ")
00474             .arg(QString::fromStdString
00475                  (RealTime::frame2RealTime
00476                   (f1 - f0 + 1, sampleRate).toText(true)))
00477             .arg(f1 - f0 + 1);
00478 
00479         v->drawVisibleText
00480             (paint, xorigin + 5,
00481              paint.fontMetrics().ascent() + 5,
00482              startText, View::OutlinedText);
00483         
00484         v->drawVisibleText
00485             (paint, xorigin + 5,
00486              paint.fontMetrics().ascent() + paint.fontMetrics().height() + 10,
00487              endText, View::OutlinedText);
00488         
00489         v->drawVisibleText
00490             (paint, xorigin + 5,
00491              paint.fontMetrics().ascent() + 2*paint.fontMetrics().height() + 15,
00492              durationText, View::OutlinedText);
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 //    int h = (rect.height() * 3) / 4;
00518 //    int y = (rect.height() / 2) - (h / 2);
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 //    list.push_back("Sampling Mode");
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 //        *max = 1; // I don't think we really do want to offer inverted log
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 

Generated on Wed Feb 20 15:45:28 2008 for SonicVisualiser by  doxygen 1.5.1