annotate data/model/TextModel.h @ 1196:c7b9c902642f spectrogram-minor-refactor

Fix threshold in spectrogram -- it wasn't working in the last release. There is a new protocol for this. Formerly the threshold parameter had a range from -50dB to 0 with the default at -50, and -50 treated internally as "no threshold". However, there was a hardcoded, hidden internal threshold for spectrogram colour mapping at -80dB with anything below this being rounded to zero. Now the threshold parameter has range -81 to -1 with the default at -80, -81 is treated internally as "no threshold", and there is no hidden internal threshold. So the default behaviour is the same as before, an effective -80dB threshold, but it is now possible to change this in both directions. Sessions reloaded from prior versions may look slightly different because, if the session says there should be no threshold, there will now actually be no threshold instead of having the hidden internal one. Still need to do something in the UI to make it apparent that the -81dB setting removes the threshold entirely. This is at least no worse than the previous, also obscured, magic -50dB setting.
author Chris Cannam
date Mon, 01 Aug 2016 16:21:01 +0100
parents 57633d605547
children 48e9f538e6e9
rev   line source
Chris@147 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@147 2
Chris@147 3 /*
Chris@147 4 Sonic Visualiser
Chris@147 5 An audio file viewer and annotation editor.
Chris@147 6 Centre for Digital Music, Queen Mary, University of London.
Chris@147 7 This file copyright 2006 Chris Cannam.
Chris@147 8
Chris@147 9 This program is free software; you can redistribute it and/or
Chris@147 10 modify it under the terms of the GNU General Public License as
Chris@147 11 published by the Free Software Foundation; either version 2 of the
Chris@147 12 License, or (at your option) any later version. See the file
Chris@147 13 COPYING included with this distribution for more information.
Chris@147 14 */
Chris@147 15
Chris@147 16 #ifndef _TEXT_MODEL_H_
Chris@147 17 #define _TEXT_MODEL_H_
Chris@147 18
Chris@147 19 #include "SparseModel.h"
Chris@302 20 #include "base/XmlExportable.h"
Chris@147 21 #include "base/RealTime.h"
Chris@147 22
Chris@423 23 #include <QStringList>
Chris@423 24
Chris@147 25 /**
Chris@147 26 * Text point type for use in a SparseModel. This represents a piece
Chris@147 27 * of text at a given time and y-value in the [0,1) range (indicative
Chris@147 28 * of height on the window). Intended for casual textual annotations.
Chris@147 29 */
Chris@147 30
Chris@302 31 struct TextPoint : public XmlExportable
Chris@147 32 {
Chris@147 33 public:
Chris@1038 34 TextPoint(sv_frame_t _frame) : frame(_frame), height(0.0f) { }
Chris@1038 35 TextPoint(sv_frame_t _frame, float _height, QString _label) :
Chris@147 36 frame(_frame), height(_height), label(_label) { }
Chris@147 37
Chris@147 38 int getDimensions() const { return 2; }
Chris@147 39
Chris@1038 40 sv_frame_t frame;
Chris@147 41 float height;
Chris@147 42 QString label;
Chris@338 43
Chris@338 44 QString getLabel() const { return label; }
Chris@147 45
Chris@314 46 void toXml(QTextStream &stream, QString indent = "",
Chris@314 47 QString extraAttributes = "") const
Chris@147 48 {
Chris@314 49 stream << QString("%1<point frame=\"%2\" height=\"%3\" label=\"%4\" %5/>\n")
Chris@302 50 .arg(indent).arg(frame).arg(height)
Chris@302 51 .arg(encodeEntities(label)).arg(extraAttributes);
Chris@147 52 }
Chris@147 53
Chris@1060 54 QString toDelimitedDataString(QString delimiter, DataExportOptions, sv_samplerate_t sampleRate) const
Chris@147 55 {
Chris@147 56 QStringList list;
Chris@147 57 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
Chris@147 58 list << QString("%1").arg(height);
Chris@318 59 if (label != "") list << label;
Chris@147 60 return list.join(delimiter);
Chris@147 61 }
Chris@147 62
Chris@147 63 struct Comparator {
Chris@147 64 bool operator()(const TextPoint &p1,
Chris@147 65 const TextPoint &p2) const {
Chris@147 66 if (p1.frame != p2.frame) return p1.frame < p2.frame;
Chris@147 67 if (p1.height != p2.height) return p1.height < p2.height;
Chris@147 68 return p1.label < p2.label;
Chris@147 69 }
Chris@147 70 };
Chris@147 71
Chris@147 72 struct OrderComparator {
Chris@147 73 bool operator()(const TextPoint &p1,
Chris@147 74 const TextPoint &p2) const {
Chris@147 75 return p1.frame < p2.frame;
Chris@147 76 }
Chris@147 77 };
Chris@147 78 };
Chris@147 79
Chris@147 80
Chris@147 81 // Make this a class rather than a typedef so it can be predeclared.
Chris@147 82
Chris@147 83 class TextModel : public SparseModel<TextPoint>
Chris@147 84 {
Chris@423 85 Q_OBJECT
Chris@423 86
Chris@147 87 public:
Chris@1040 88 TextModel(sv_samplerate_t sampleRate, int resolution, bool notifyOnAdd = true) :
Chris@147 89 SparseModel<TextPoint>(sampleRate, resolution, notifyOnAdd)
Chris@147 90 { }
Chris@147 91
Chris@288 92 virtual void toXml(QTextStream &out,
Chris@288 93 QString indent = "",
Chris@288 94 QString extraAttributes = "") const
Chris@147 95 {
Chris@288 96 SparseModel<TextPoint>::toXml
Chris@288 97 (out,
Chris@288 98 indent,
Chris@147 99 QString("%1 subtype=\"text\"")
Chris@147 100 .arg(extraAttributes));
Chris@147 101 }
Chris@345 102
Chris@345 103 QString getTypeName() const { return tr("Text"); }
Chris@424 104
Chris@424 105 /**
Chris@424 106 * TabularModel methods.
Chris@424 107 */
Chris@424 108
Chris@424 109 virtual int getColumnCount() const
Chris@424 110 {
Chris@424 111 return 4;
Chris@424 112 }
Chris@424 113
Chris@424 114 virtual QString getHeading(int column) const
Chris@424 115 {
Chris@424 116 switch (column) {
Chris@424 117 case 0: return tr("Time");
Chris@424 118 case 1: return tr("Frame");
Chris@424 119 case 2: return tr("Height");
Chris@424 120 case 3: return tr("Label");
Chris@424 121 default: return tr("Unknown");
Chris@424 122 }
Chris@424 123 }
Chris@424 124
Chris@424 125 virtual QVariant getData(int row, int column, int role) const
Chris@424 126 {
Chris@425 127 if (column < 2) {
Chris@425 128 return SparseModel<TextPoint>::getData
Chris@425 129 (row, column, role);
Chris@425 130 }
Chris@425 131
Chris@608 132 PointListConstIterator i = getPointListIteratorForRow(row);
Chris@424 133 if (i == m_points.end()) return QVariant();
Chris@424 134
Chris@424 135 switch (column) {
Chris@424 136 case 2: return i->height;
Chris@424 137 case 3: return i->label;
Chris@424 138 default: return QVariant();
Chris@424 139 }
Chris@424 140 }
Chris@424 141
Chris@424 142 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
Chris@424 143 {
Chris@425 144 if (column < 2) {
Chris@425 145 return SparseModel<TextPoint>::getSetDataCommand
Chris@425 146 (row, column, value, role);
Chris@425 147 }
Chris@425 148
Chris@740 149 if (role != Qt::EditRole) return 0;
Chris@424 150 PointListIterator i = getPointListIteratorForRow(row);
Chris@740 151 if (i == m_points.end()) return 0;
Chris@424 152 EditCommand *command = new EditCommand(this, tr("Edit Data"));
Chris@424 153
Chris@424 154 Point point(*i);
Chris@424 155 command->deletePoint(point);
Chris@424 156
Chris@424 157 switch (column) {
Chris@1038 158 case 2: point.height = float(value.toDouble()); break;
Chris@424 159 case 3: point.label = value.toString(); break;
Chris@424 160 }
Chris@424 161
Chris@424 162 command->addPoint(point);
Chris@424 163 return command->finish();
Chris@424 164 }
Chris@424 165
Chris@424 166 virtual bool isColumnTimeValue(int column) const
Chris@424 167 {
Chris@424 168 return (column < 2);
Chris@424 169 }
Chris@424 170
Chris@424 171 virtual SortType getSortType(int column) const
Chris@424 172 {
Chris@424 173 if (column == 3) return SortAlphabetical;
Chris@424 174 return SortNumeric;
Chris@424 175 }
Chris@424 176
Chris@147 177 };
Chris@147 178
Chris@147 179
Chris@147 180 #endif
Chris@147 181
Chris@147 182
Chris@147 183