Chris@133: Chris@133: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@133: Chris@133: /* Chris@133: Sonic Visualiser Chris@133: An audio file viewer and annotation editor. Chris@133: Centre for Digital Music, Queen Mary, University of London. Chris@195: This file copyright 2006-2007 QMUL. Chris@133: Chris@133: This program is free software; you can redistribute it and/or Chris@133: modify it under the terms of the GNU General Public License as Chris@133: published by the Free Software Foundation; either version 2 of the Chris@133: License, or (at your option) any later version. See the file Chris@133: COPYING included with this distribution for more information. Chris@133: */ Chris@133: Chris@133: #include "SpectrumLayer.h" Chris@133: Chris@133: #include "data/model/FFTModel.h" Chris@133: #include "view/View.h" Chris@153: #include "base/AudioLevel.h" Chris@153: #include "base/Preferences.h" Chris@167: #include "base/RangeMapper.h" Chris@133: Chris@133: SpectrumLayer::SpectrumLayer() : Chris@193: m_originModel(0), Chris@153: m_channel(-1), Chris@153: m_channelSet(false), Chris@153: m_windowSize(1024), Chris@153: m_windowType(HanningWindow), Chris@153: m_windowHopLevel(2) Chris@133: { Chris@153: Preferences *prefs = Preferences::getInstance(); Chris@153: connect(prefs, SIGNAL(propertyChanged(PropertyContainer::PropertyName)), Chris@153: this, SLOT(preferenceChanged(PropertyContainer::PropertyName))); Chris@153: setWindowType(prefs->getWindowType()); Chris@195: Chris@195: setBinScale(LogBins); Chris@133: } Chris@133: Chris@133: SpectrumLayer::~SpectrumLayer() Chris@133: { Chris@193: //!!! delete parent's model Chris@193: // for (size_t i = 0; i < m_fft.size(); ++i) delete m_fft[i]; Chris@133: } Chris@133: Chris@133: void Chris@133: SpectrumLayer::setModel(DenseTimeValueModel *model) Chris@133: { Chris@193: if (m_originModel == model) return; Chris@193: m_originModel = model; Chris@193: setupFFT(); Chris@153: } Chris@153: Chris@153: void Chris@193: SpectrumLayer::setupFFT() Chris@153: { Chris@193: FFTModel *oldFFT = dynamic_cast Chris@193: (const_cast(m_sliceableModel)); Chris@153: Chris@193: if (oldFFT) { Chris@193: setSliceableModel(0); Chris@193: delete oldFFT; Chris@153: } Chris@153: Chris@193: FFTModel *newFFT = new FFTModel(m_originModel, Chris@193: m_channel, Chris@193: m_windowType, Chris@193: m_windowSize, Chris@193: getWindowIncrement(), Chris@193: m_windowSize, Chris@193: true); Chris@153: Chris@193: setSliceableModel(newFFT); Chris@193: Chris@193: newFFT->resume(); Chris@153: } Chris@153: Chris@153: void Chris@153: SpectrumLayer::setChannel(int channel) Chris@153: { Chris@153: m_channelSet = true; Chris@153: Chris@193: FFTModel *fft = dynamic_cast Chris@193: (const_cast(m_sliceableModel)); Chris@193: Chris@153: if (m_channel == channel) { Chris@193: if (fft) fft->resume(); Chris@153: return; Chris@153: } Chris@153: Chris@153: m_channel = channel; Chris@153: Chris@193: if (!fft) setupFFT(); Chris@153: Chris@153: emit layerParametersChanged(); Chris@133: } Chris@133: Chris@153: Layer::PropertyList Chris@153: SpectrumLayer::getProperties() const Chris@153: { Chris@193: PropertyList list = SliceLayer::getProperties(); Chris@153: list.push_back("Window Size"); Chris@153: list.push_back("Window Increment"); Chris@153: return list; Chris@153: } Chris@153: Chris@153: QString Chris@153: SpectrumLayer::getPropertyLabel(const PropertyName &name) const Chris@153: { Chris@153: if (name == "Window Size") return tr("Window Size"); Chris@153: if (name == "Window Increment") return tr("Window Overlap"); Chris@193: return SliceLayer::getPropertyLabel(name); Chris@153: } Chris@153: Chris@153: Layer::PropertyType Chris@153: SpectrumLayer::getPropertyType(const PropertyName &name) const Chris@153: { Chris@193: if (name == "Window Size") return ValueProperty; Chris@193: if (name == "Window Increment") return ValueProperty; Chris@193: return SliceLayer::getPropertyType(name); Chris@153: } Chris@153: Chris@153: QString Chris@153: SpectrumLayer::getPropertyGroupName(const PropertyName &name) const Chris@153: { Chris@153: if (name == "Window Size" || Chris@153: name == "Window Increment") return tr("Window"); Chris@193: return SliceLayer::getPropertyGroupName(name); Chris@153: } Chris@153: Chris@153: int Chris@153: SpectrumLayer::getPropertyRangeAndValue(const PropertyName &name, Chris@153: int *min, int *max) const Chris@153: { Chris@153: int deft = 0; Chris@153: Chris@153: int garbage0, garbage1; Chris@153: if (!min) min = &garbage0; Chris@153: if (!max) max = &garbage1; Chris@153: Chris@193: if (name == "Window Size") { Chris@153: Chris@153: *min = 0; Chris@153: *max = 10; Chris@153: Chris@153: deft = 0; Chris@153: int ws = m_windowSize; Chris@153: while (ws > 32) { ws >>= 1; deft ++; } Chris@153: Chris@153: } else if (name == "Window Increment") { Chris@153: Chris@153: *min = 0; Chris@153: *max = 5; Chris@153: Chris@153: deft = m_windowHopLevel; Chris@153: Chris@153: } else { Chris@193: Chris@193: deft = SliceLayer::getPropertyRangeAndValue(name, min, max); Chris@153: } Chris@153: Chris@153: return deft; Chris@153: } Chris@153: Chris@153: QString Chris@153: SpectrumLayer::getPropertyValueLabel(const PropertyName &name, Chris@153: int value) const Chris@153: { Chris@153: if (name == "Window Size") { Chris@153: return QString("%1").arg(32 << value); Chris@153: } Chris@153: if (name == "Window Increment") { Chris@153: switch (value) { Chris@153: default: Chris@153: case 0: return tr("None"); Chris@153: case 1: return tr("25 %"); Chris@153: case 2: return tr("50 %"); Chris@153: case 3: return tr("75 %"); Chris@153: case 4: return tr("87.5 %"); Chris@153: case 5: return tr("93.75 %"); Chris@153: } Chris@153: } Chris@193: return SliceLayer::getPropertyValueLabel(name, value); Chris@153: } Chris@153: Chris@167: RangeMapper * Chris@167: SpectrumLayer::getNewPropertyRangeMapper(const PropertyName &name) const Chris@167: { Chris@193: return SliceLayer::getNewPropertyRangeMapper(name); Chris@167: } Chris@167: Chris@133: void Chris@153: SpectrumLayer::setProperty(const PropertyName &name, int value) Chris@133: { Chris@193: if (name == "Window Size") { Chris@153: setWindowSize(32 << value); Chris@153: } else if (name == "Window Increment") { Chris@153: setWindowHopLevel(value); Chris@193: } else { Chris@193: SliceLayer::setProperty(name, value); Chris@153: } Chris@153: } Chris@153: Chris@153: void Chris@153: SpectrumLayer::setWindowSize(size_t ws) Chris@153: { Chris@153: if (m_windowSize == ws) return; Chris@153: m_windowSize = ws; Chris@193: setupFFT(); Chris@153: emit layerParametersChanged(); Chris@153: } Chris@153: Chris@153: void Chris@153: SpectrumLayer::setWindowHopLevel(size_t v) Chris@153: { Chris@153: if (m_windowHopLevel == v) return; Chris@153: m_windowHopLevel = v; Chris@193: setupFFT(); Chris@153: emit layerParametersChanged(); Chris@153: } Chris@153: Chris@153: void Chris@153: SpectrumLayer::setWindowType(WindowType w) Chris@153: { Chris@153: if (m_windowType == w) return; Chris@153: m_windowType = w; Chris@193: setupFFT(); Chris@153: emit layerParametersChanged(); Chris@153: } Chris@153: Chris@153: void Chris@153: SpectrumLayer::preferenceChanged(PropertyContainer::PropertyName name) Chris@153: { Chris@153: if (name == "Window Type") { Chris@153: setWindowType(Preferences::getInstance()->getWindowType()); Chris@153: return; Chris@153: } Chris@153: } Chris@153: Chris@153: QString Chris@153: SpectrumLayer::toXmlString(QString indent, QString extraAttributes) const Chris@153: { Chris@153: QString s; Chris@153: Chris@193: s += QString("windowSize=\"%1\" " Chris@193: "windowHopLevel=\"%2\"") Chris@153: .arg(m_windowSize) Chris@193: .arg(m_windowHopLevel); Chris@153: Chris@193: return SliceLayer::toXmlString(indent, extraAttributes + " " + s); Chris@153: } Chris@153: Chris@153: void Chris@153: SpectrumLayer::setProperties(const QXmlAttributes &attributes) Chris@153: { Chris@153: bool ok = false; Chris@153: Chris@153: size_t windowSize = attributes.value("windowSize").toUInt(&ok); Chris@153: if (ok) setWindowSize(windowSize); Chris@153: Chris@153: size_t windowHopLevel = attributes.value("windowHopLevel").toUInt(&ok); Chris@153: if (ok) setWindowHopLevel(windowHopLevel); Chris@133: } Chris@133: Chris@133: bool Chris@133: SpectrumLayer::getValueExtents(float &min, float &max, bool &logarithmic, Chris@133: QString &units) const Chris@133: { Chris@133: return false; Chris@133: } Chris@133: