diff layer/SpectrumLayer.cpp @ 193:57c2350a8c40

* Add slice layers (so you can display a slice of a colour 3d plot as if it were a spectrum) * Make spectrum layer a subclass of slice layer
author Chris Cannam
date Fri, 26 Jan 2007 16:59:57 +0000
parents 42118892f428
children 4a3bdde1ef13
line wrap: on
line diff
--- a/layer/SpectrumLayer.cpp	Wed Jan 24 17:14:24 2007 +0000
+++ b/layer/SpectrumLayer.cpp	Fri Jan 26 16:59:57 2007 +0000
@@ -22,18 +22,10 @@
 #include "base/Preferences.h"
 #include "base/RangeMapper.h"
 
-#include <QPainter>
-#include <QPainterPath>
-
 SpectrumLayer::SpectrumLayer() :
-    m_model(0),
-    m_channelMode(MixChannels),
+    m_originModel(0),
     m_channel(-1),
     m_channelSet(false),
-    m_colour(Qt::darkBlue),
-    m_energyScale(dBScale),
-    m_normalize(false),
-    m_gain(1.0),
     m_windowSize(1024),
     m_windowType(HanningWindow),
     m_windowHopLevel(2)
@@ -46,45 +38,40 @@
 
 SpectrumLayer::~SpectrumLayer()
 {
-    for (size_t i = 0; i < m_fft.size(); ++i) delete m_fft[i];
+    //!!! delete parent's model
+//    for (size_t i = 0; i < m_fft.size(); ++i) delete m_fft[i];
 }
 
 void
 SpectrumLayer::setModel(DenseTimeValueModel *model)
 {
-    m_model = model;
-    setupFFTs();
+    if (m_originModel == model) return;
+    m_originModel = model;
+    setupFFT();
 }
 
 void
-SpectrumLayer::setupFFTs()
+SpectrumLayer::setupFFT()
 {
-    for (size_t i = 0; i < m_fft.size(); ++i) delete m_fft[i];
-    m_fft.clear();
-
-    int minChannel = m_channel, maxChannel = m_channel;
+    FFTModel *oldFFT = dynamic_cast<FFTModel *>
+        (const_cast<DenseThreeDimensionalModel *>(m_sliceableModel));
     
-    if (m_channel == -1 &&
-        m_channelMode != MixChannels) {
-        minChannel = 0;
-        maxChannel = 0;
-        if (m_model->getChannelCount() > 1) {
-            maxChannel = m_model->getChannelCount() - 1;
-        }
+    if (oldFFT) {
+        setSliceableModel(0);
+        delete oldFFT;
     }
 
-    for (int c = minChannel; c <= maxChannel; ++c) {
-        
-        m_fft.push_back(new FFTModel(m_model,
-                                     c,
-                                     HanningWindow,
-                                     m_windowSize,
-                                     getWindowIncrement(),
-                                     m_windowSize,
-                                     true));
+    FFTModel *newFFT = new FFTModel(m_originModel,
+                                    m_channel,
+                                    m_windowType,
+                                    m_windowSize,
+                                    getWindowIncrement(),
+                                    m_windowSize,
+                                    true);
 
-        if (m_channelSet) m_fft[m_fft.size()-1]->resume();
-    }
+    setSliceableModel(newFFT);
+
+    newFFT->resume();
 }
 
 void
@@ -92,133 +79,44 @@
 {
     m_channelSet = true;
 
+    FFTModel *fft = dynamic_cast<FFTModel *>
+        (const_cast<DenseThreeDimensionalModel *>(m_sliceableModel));
+
     if (m_channel == channel) {
-        for (size_t i = 0; i < m_fft.size(); ++i) {
-            m_fft[i]->resume();
-        }
+        if (fft) fft->resume();
         return;
     }
 
     m_channel = channel;
 
-    if (!m_fft.empty()) setupFFTs();
+    if (!fft) setupFFT();
 
     emit layerParametersChanged();
 }
 
-void
-SpectrumLayer::paint(View *v, QPainter &paint, QRect rect) const
-{
-    if (m_fft.empty()) return;
-    if (!m_channelSet) {
-        for (size_t i = 0; i < m_fft.size(); ++i) {
-            m_fft[i]->resume();
-        }
-    }
-
-    FFTModel *fft = m_fft[0]; //!!! for now
-
-    int windowIncrement = getWindowIncrement();
-
-    size_t f = v->getCentreFrame();
-
-    int w = (v->width() * 2) / 3;
-    int xorigin = (v->width() / 2) - (w / 2);
-    
-    int h = (v->height() * 2) / 3;
-    int yorigin = (v->height() / 2) + (h / 2);
-
-    size_t column = f / windowIncrement;
-
-    paint.save();
-    paint.setPen(m_colour);
-    paint.setRenderHint(QPainter::Antialiasing, false);
-    
-    QPainterPath path;
-    float thresh = -80.f;
-
-    for (size_t bin = 0; bin < fft->getHeight(); ++bin) {
-
-        float x = xorigin + (float(w) * bin) / fft->getHeight();
-        float mag;
-        if (m_normalize) {
-            mag = fft->getNormalizedMagnitudeAt(column, bin);
-        } else {
-            mag = fft->getMagnitudeAt(column, bin);
-        }
-        mag *= m_gain;
-        float y = 0.f;
- 
-        switch (m_energyScale) {
-
-        case dBScale:
-        {
-            float db = thresh;
-            if (mag > 0.f) db = 10.f * log10f(mag);
-            if (db < thresh) db = thresh;
-            float val = (db - thresh) / -thresh;
-            y = yorigin - (float(h) * val);
-            break;
-        }
-
-        case MeterScale:
-            y = yorigin - AudioLevel::multiplier_to_preview(mag, h);
-            break;
-
-        default:
-            y = yorigin - (float(h) * mag);
-            break;
-        }
-
-        if (bin == 0) {
-            path.moveTo(x, y);
-        } else {
-            path.lineTo(x, y);
-        }
-    }
-
-    paint.drawPath(path);
-    paint.restore();
-
-}
-
 Layer::PropertyList
 SpectrumLayer::getProperties() const
 {
-    PropertyList list;
-    list.push_back("Colour");
-    list.push_back("Scale");
-    list.push_back("Normalize");
-    list.push_back("Gain");
+    PropertyList list = SliceLayer::getProperties();
     list.push_back("Window Size");
     list.push_back("Window Increment");
-
-    if (m_model && m_model->getChannelCount() > 1 && m_channel == -1) {
-        list.push_back("Channels");
-    }
-
     return list;
 }
 
 QString
 SpectrumLayer::getPropertyLabel(const PropertyName &name) const
 {
-    if (name == "Colour") return tr("Colour");
-    if (name == "Energy Scale") return tr("Scale");
-    if (name == "Channels") return tr("Channels");
     if (name == "Window Size") return tr("Window Size");
     if (name == "Window Increment") return tr("Window Overlap");
-    if (name == "Normalize") return tr("Normalize");
-    if (name == "Gain") return tr("Gain");
-    return "";
+    return SliceLayer::getPropertyLabel(name);
 }
 
 Layer::PropertyType
 SpectrumLayer::getPropertyType(const PropertyName &name) const
 {
-    if (name == "Gain") return RangeProperty;
-    if (name == "Normalize") return ToggleProperty;
-    return ValueProperty;
+    if (name == "Window Size") return ValueProperty;
+    if (name == "Window Increment") return ValueProperty;
+    return SliceLayer::getPropertyType(name);
 }
 
 QString
@@ -226,10 +124,7 @@
 {
     if (name == "Window Size" ||
 	name == "Window Increment") return tr("Window");
-    if (name == "Scale" ||
-        name == "Normalize" ||
-        name == "Gain") return tr("Energy Scale");
-    return QString();
+    return SliceLayer::getPropertyGroupName(name);
 }
 
 int
@@ -242,47 +137,7 @@
     if (!min) min = &garbage0;
     if (!max) max = &garbage1;
 
-    if (name == "Gain") {
-
-	*min = -50;
-	*max = 50;
-
-	deft = lrint(log10(m_gain) * 20.0);
-	if (deft < *min) deft = *min;
-	if (deft > *max) deft = *max;
-
-    } else if (name == "Normalize") {
-	
-	deft = (m_normalize ? 1 : 0);
-
-    } else if (name == "Colour") {
-
-	*min = 0;
-	*max = 5;
-
-	if (m_colour == Qt::black) deft = 0;
-	else if (m_colour == Qt::darkRed) deft = 1;
-	else if (m_colour == Qt::darkBlue) deft = 2;
-	else if (m_colour == Qt::darkGreen) deft = 3;
-	else if (m_colour == QColor(200, 50, 255)) deft = 4;
-	else if (m_colour == QColor(255, 150, 50)) deft = 5;
-
-    } else if (name == "Channels") {
-
-        *min = 0;
-        *max = 2;
-        if (m_channelMode == MixChannels) deft = 1;
-        else if (m_channelMode == OverlayChannels) deft = 2;
-        else deft = 0;
-
-    } else if (name == "Scale") {
-
-	*min = 0;
-	*max = 2;
-
-	deft = (int)m_energyScale;
-
-    } else if (name == "Window Size") {
+    if (name == "Window Size") {
 
 	*min = 0;
 	*max = 10;
@@ -299,7 +154,8 @@
         deft = m_windowHopLevel;
     
     } else {
-	deft = Layer::getPropertyRangeAndValue(name, min, max);
+
+        deft = SliceLayer::getPropertyRangeAndValue(name, min, max);
     }
 
     return deft;
@@ -309,33 +165,6 @@
 SpectrumLayer::getPropertyValueLabel(const PropertyName &name,
 				    int value) const
 {
-    if (name == "Colour") {
-	switch (value) {
-	default:
-	case 0: return tr("Black");
-	case 1: return tr("Red");
-	case 2: return tr("Blue");
-	case 3: return tr("Green");
-	case 4: return tr("Purple");
-	case 5: return tr("Orange");
-	}
-    }
-    if (name == "Scale") {
-	switch (value) {
-	default:
-	case 0: return tr("Linear");
-	case 1: return tr("Meter");
-	case 2: return tr("dB");
-	}
-    }
-    if (name == "Channels") {
-        switch (value) {
-        default:
-        case 0: return tr("Separate");
-        case 1: return tr("Mean");
-        case 2: return tr("Overlay");
-        }
-    }
     if (name == "Window Size") {
 	return QString("%1").arg(32 << value);
     }
@@ -350,83 +179,33 @@
 	case 5: return tr("93.75 %");
 	}
     }
-    return tr("<unknown>");
+    return SliceLayer::getPropertyValueLabel(name, value);
 }
 
 RangeMapper *
 SpectrumLayer::getNewPropertyRangeMapper(const PropertyName &name) const
 {
-    if (name == "Gain") {
-        return new LinearRangeMapper(-50, 50, -25, 25, tr("dB"));
-    }
-    return 0;
+    return SliceLayer::getNewPropertyRangeMapper(name);
 }
 
 void
 SpectrumLayer::setProperty(const PropertyName &name, int value)
 {
-    if (name == "Gain") {
-	setGain(pow(10, float(value)/20.0));
-    } else if (name == "Colour") {
-	switch (value) {
-	default:
-	case 0:	setBaseColour(Qt::black); break;
-	case 1: setBaseColour(Qt::darkRed); break;
-	case 2: setBaseColour(Qt::darkBlue); break;
-	case 3: setBaseColour(Qt::darkGreen); break;
-	case 4: setBaseColour(QColor(200, 50, 255)); break;
-	case 5: setBaseColour(QColor(255, 150, 50)); break;
-	}
-    } else if (name == "Channels") {
-        if (value == 1) setChannelMode(MixChannels);
-        else if (value == 2) setChannelMode(OverlayChannels);
-        else setChannelMode(SeparateChannels);
-    } else if (name == "Scale") {
-	switch (value) {
-	default:
-	case 0: setEnergyScale(LinearScale); break;
-	case 1: setEnergyScale(MeterScale); break;
-	case 2: setEnergyScale(dBScale); break;
-	}
-    } else if (name == "Window Size") {
+    if (name == "Window Size") {
 	setWindowSize(32 << value);
     } else if (name == "Window Increment") {
         setWindowHopLevel(value);
-    } else if (name == "Normalize") {
-	setNormalize(value ? true : false);
+    } else {
+        SliceLayer::setProperty(name, value);
     }
 }
 
 void
-SpectrumLayer::setBaseColour(QColor colour)
-{
-    if (m_colour == colour) return;
-    m_colour = colour;
-    emit layerParametersChanged();
-}
-
-void
-SpectrumLayer::setChannelMode(ChannelMode channelMode)
-{
-    if (m_channelMode == channelMode) return;
-    m_channelMode = channelMode;
-    emit layerParametersChanged();
-}
-
-void
-SpectrumLayer::setEnergyScale(EnergyScale scale)
-{
-    if (m_energyScale == scale) return;
-    m_energyScale = scale;
-    emit layerParametersChanged();
-}
-
-void
 SpectrumLayer::setWindowSize(size_t ws)
 {
     if (m_windowSize == ws) return;
     m_windowSize = ws;
-    setupFFTs();
+    setupFFT();
     emit layerParametersChanged();
 }
 
@@ -435,7 +214,7 @@
 {
     if (m_windowHopLevel == v) return;
     m_windowHopLevel = v;
-    setupFFTs();
+    setupFFT();
     emit layerParametersChanged();
 }
 
@@ -444,23 +223,7 @@
 {
     if (m_windowType == w) return;
     m_windowType = w;
-    setupFFTs();
-    emit layerParametersChanged();
-}
-
-void
-SpectrumLayer::setNormalize(bool n)
-{
-    if (m_normalize == n) return;
-    m_normalize = n;
-    emit layerParametersChanged();
-}
-
-void
-SpectrumLayer::setGain(float gain)
-{
-    if (m_gain == gain) return;
-    m_gain = gain;
+    setupFFT();
     emit layerParametersChanged();
 }
 
@@ -478,24 +241,12 @@
 {
     QString s;
     
-    s += QString("colour=\"%1\" "
-		 "channelMode=\"%2\" "
-		 "channel=\"%3\" "
-		 "energyScale=\"%4\" "
-		 "windowSize=\"%5\" "
-		 "windowHopLevel=\"%6\" "
-                 "gain=\"%7\" "
-                 "normalize=\"%8\"")
-	.arg(encodeColour(m_colour))
-	.arg(m_channelMode)
-	.arg(m_channel)
-	.arg(m_energyScale)
+    s += QString("windowSize=\"%1\" "
+		 "windowHopLevel=\"%2\"")
         .arg(m_windowSize)
-        .arg(m_windowHopLevel)
-        .arg(m_gain)
-        .arg(m_normalize ? "true" : "false");
+        .arg(m_windowHopLevel);
 
-    return Layer::toXmlString(indent, extraAttributes + " " + s);
+    return SliceLayer::toXmlString(indent, extraAttributes + " " + s);
 }
 
 void
@@ -503,36 +254,11 @@
 {
     bool ok = false;
 
-    QString colourSpec = attributes.value("colour");
-    if (colourSpec != "") {
-	QColor colour(colourSpec);
-	if (colour.isValid()) {
-	    setBaseColour(QColor(colourSpec));
-	}
-    }
-
-    ChannelMode channelMode = (ChannelMode)
-	attributes.value("channelMode").toInt(&ok);
-    if (ok) setChannelMode(channelMode);
-
-    int channel = attributes.value("channel").toInt(&ok);
-    if (ok) setChannel(channel);
-
-    EnergyScale scale = (EnergyScale)
-	attributes.value("energyScale").toInt(&ok);
-    if (ok) setEnergyScale(scale);
-
     size_t windowSize = attributes.value("windowSize").toUInt(&ok);
     if (ok) setWindowSize(windowSize);
 
     size_t windowHopLevel = attributes.value("windowHopLevel").toUInt(&ok);
     if (ok) setWindowHopLevel(windowHopLevel);
-
-    float gain = attributes.value("gain").toFloat(&ok);
-    if (ok) setGain(gain);
-
-    bool normalize = (attributes.value("normalize").trimmed() == "true");
-    setNormalize(normalize);
 }
 
 bool