diff data/model/EditableDenseThreeDimensionalModel.cpp @ 152:21792a550ec9 last-cc-copyright

* Move the current DenseThreeDimensionalModel to EditableDenseThreeDimensionalModel (wow!), and make DTDM an abstract base * Move FFTFuzzyAdapter to FFTModel as a new subclass of DTDM
author Chris Cannam
date Mon, 31 Jul 2006 17:05:18 +0000
parents
children 9c652f2c39b1
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/model/EditableDenseThreeDimensionalModel.cpp	Mon Jul 31 17:05:18 2006 +0000
@@ -0,0 +1,317 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "EditableDenseThreeDimensionalModel.h"
+
+#include <QTextStream>
+
+EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate,
+                                                                       size_t resolution,
+                                                                       size_t yBinCount,
+                                                                       bool notifyOnAdd) :
+    m_sampleRate(sampleRate),
+    m_resolution(resolution),
+    m_yBinCount(yBinCount),
+    m_minimum(0.0),
+    m_maximum(0.0),
+    m_notifyOnAdd(notifyOnAdd),
+    m_sinceLastNotifyMin(-1),
+    m_sinceLastNotifyMax(-1),
+    m_completion(100)
+{
+}    
+
+bool
+EditableDenseThreeDimensionalModel::isOK() const
+{
+    return true;
+}
+
+size_t
+EditableDenseThreeDimensionalModel::getSampleRate() const
+{
+    return m_sampleRate;
+}
+
+size_t
+EditableDenseThreeDimensionalModel::getStartFrame() const
+{
+    return 0;
+}
+
+size_t
+EditableDenseThreeDimensionalModel::getEndFrame() const
+{
+    return m_resolution * m_data.size() + (m_resolution - 1);
+}
+
+Model *
+EditableDenseThreeDimensionalModel::clone() const
+{
+    EditableDenseThreeDimensionalModel *model =
+        new EditableDenseThreeDimensionalModel
+	(m_sampleRate, m_resolution, m_yBinCount);
+
+    model->m_minimum = m_minimum;
+    model->m_maximum = m_maximum;
+
+    for (size_t i = 0; i < m_data.size(); ++i) {
+	model->setBinValues(i * m_resolution, m_data[i]);
+    }
+
+    return model;
+}
+
+size_t
+EditableDenseThreeDimensionalModel::getResolution() const
+{
+    return m_resolution;
+}
+
+void
+EditableDenseThreeDimensionalModel::setResolution(size_t sz)
+{
+    m_resolution = sz;
+}
+
+size_t
+EditableDenseThreeDimensionalModel::getYBinCount() const
+{
+    return m_yBinCount;
+}
+
+void
+EditableDenseThreeDimensionalModel::setYBinCount(size_t sz)
+{
+    m_yBinCount = sz;
+}
+
+float
+EditableDenseThreeDimensionalModel::getMinimumLevel() const
+{
+    return m_minimum;
+}
+
+void
+EditableDenseThreeDimensionalModel::setMinimumLevel(float level)
+{
+    m_minimum = level;
+}
+
+float
+EditableDenseThreeDimensionalModel::getMaximumLevel() const
+{
+    return m_maximum;
+}
+
+void
+EditableDenseThreeDimensionalModel::setMaximumLevel(float level)
+{
+    m_maximum = level;
+}
+
+void
+EditableDenseThreeDimensionalModel::getBinValues(long windowStart,
+					 BinValueSet &result) const
+{
+    QMutexLocker locker(&m_mutex);
+    
+    long index = windowStart / m_resolution;
+
+    if (index >= 0 && index < long(m_data.size())) {
+	result = m_data[index];
+    } else {
+	result.clear();
+    }
+
+    while (result.size() < m_yBinCount) result.push_back(m_minimum);
+}
+
+float
+EditableDenseThreeDimensionalModel::getBinValue(long windowStart,
+					size_t n) const
+{
+    QMutexLocker locker(&m_mutex);
+    
+    long index = windowStart / m_resolution;
+
+    if (index >= 0 && index < long(m_data.size())) {
+	const BinValueSet &s = m_data[index];
+	if (n < s.size()) return s[n];
+    }
+
+    return m_minimum;
+}
+
+void
+EditableDenseThreeDimensionalModel::setBinValues(long windowStart,
+					 const BinValueSet &values)
+{
+    QMutexLocker locker(&m_mutex);
+
+    long index = windowStart / m_resolution;
+
+    while (index >= long(m_data.size())) {
+	m_data.push_back(BinValueSet());
+    }
+
+    bool newExtents = (m_data.empty() && (m_minimum == m_maximum));
+    bool allChange = false;
+
+    for (size_t i = 0; i < values.size(); ++i) {
+	if (newExtents || values[i] < m_minimum) {
+	    m_minimum = values[i];
+	    allChange = true;
+	}
+	if (newExtents || values[i] > m_maximum) {
+	    m_maximum = values[i];
+	    allChange = true;
+	}
+    }
+
+    m_data[index] = values;
+
+    if (m_notifyOnAdd) {
+	if (allChange) {
+	    emit modelChanged();
+	} else {
+	    emit modelChanged(windowStart, windowStart + m_resolution);
+	}
+    } else {
+	if (allChange) {
+	    m_sinceLastNotifyMin = -1;
+	    m_sinceLastNotifyMax = -1;
+	    emit modelChanged();
+	} else {
+	    if (m_sinceLastNotifyMin == -1 ||
+		windowStart < m_sinceLastNotifyMin) {
+		m_sinceLastNotifyMin = windowStart;
+	    }
+	    if (m_sinceLastNotifyMax == -1 ||
+		windowStart > m_sinceLastNotifyMax) {
+		m_sinceLastNotifyMax = windowStart;
+	    }
+	}
+    }
+}
+
+QString
+EditableDenseThreeDimensionalModel::getBinName(size_t n) const
+{
+    if (m_binNames.size() > n) return m_binNames[n];
+    else return "";
+}
+
+void
+EditableDenseThreeDimensionalModel::setBinName(size_t n, QString name)
+{
+    while (m_binNames.size() <= n) m_binNames.push_back("");
+    m_binNames[n] = name;
+    emit modelChanged();
+}
+
+void
+EditableDenseThreeDimensionalModel::setBinNames(std::vector<QString> names)
+{
+    m_binNames = names;
+    emit modelChanged();
+}
+
+void
+EditableDenseThreeDimensionalModel::setCompletion(int completion)
+{
+    if (m_completion != completion) {
+	m_completion = completion;
+
+	if (completion == 100) {
+
+	    m_notifyOnAdd = true; // henceforth
+	    emit modelChanged();
+
+	} else if (!m_notifyOnAdd) {
+
+	    if (m_sinceLastNotifyMin >= 0 &&
+		m_sinceLastNotifyMax >= 0) {
+		emit modelChanged(m_sinceLastNotifyMin,
+				  m_sinceLastNotifyMax + m_resolution);
+		m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
+	    } else {
+		emit completionChanged();
+	    }
+	} else {
+	    emit completionChanged();
+	}	    
+    }
+}
+
+void
+EditableDenseThreeDimensionalModel::toXml(QTextStream &out,
+                                  QString indent,
+                                  QString extraAttributes) const
+{
+    // For historical reasons we read and write "resolution" as "windowSize"
+
+    out << Model::toXmlString
+	(indent, QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6")
+	 .arg(m_resolution)
+	 .arg(m_yBinCount)
+	 .arg(m_minimum)
+	 .arg(m_maximum)
+	 .arg(getObjectExportId(&m_data))
+	 .arg(extraAttributes));
+
+    out << indent;
+    out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n")
+	.arg(getObjectExportId(&m_data));
+
+    for (size_t i = 0; i < m_binNames.size(); ++i) {
+	if (m_binNames[i] != "") {
+	    out << indent + "  ";
+	    out << QString("<bin number=\"%1\" name=\"%2\"/>\n")
+		.arg(i).arg(m_binNames[i]);
+	}
+    }
+
+    for (size_t i = 0; i < m_data.size(); ++i) {
+	out << indent + "  ";
+	out << QString("<row n=\"%1\">").arg(i);
+	for (size_t j = 0; j < m_data[i].size(); ++j) {
+	    if (j > 0) out << " ";
+	    out << m_data[i][j];
+	}
+	out << QString("</row>\n");
+    }
+
+    out << indent + "</dataset>\n";
+}
+
+QString
+EditableDenseThreeDimensionalModel::toXmlString(QString indent,
+					QString extraAttributes) const
+{
+    QString s;
+
+    {
+        QTextStream out(&s);
+        toXml(out, indent, extraAttributes);
+    }
+
+    return s;
+}
+
+#ifdef INCLUDE_MOCFILES
+#include "EditableDenseThreeDimensionalModel.moc.cpp"
+#endif
+