annotate widgets/Fader.cpp @ 1127:9fb8dfd7ce4c 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 4a578a360011
children a34a2a25907c
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@0 7
Chris@59 8 This program is free software; you can redistribute it and/or
Chris@59 9 modify it under the terms of the GNU General Public License as
Chris@59 10 published by the Free Software Foundation; either version 2 of the
Chris@59 11 License, or (at your option) any later version. See the file
Chris@59 12 COPYING included with this distribution for more information.
Chris@0 13 */
Chris@0 14
Chris@0 15 /**
Chris@0 16 * Horizontal audio fader and meter widget.
Chris@0 17 *
Chris@0 18 * Based on the vertical fader and meter widget from the Hydrogen drum
Chris@0 19 * machine. (Any poor taste that has crept in during the
Chris@0 20 * modifications for this application is entirely my own, however.)
Chris@0 21 * The following copyright notice applies to code from this file, and
Chris@0 22 * also to the files in icons/fader_*.png (also modified by me). --cc
Chris@0 23 */
Chris@0 24
Chris@0 25 /**
Chris@0 26 * Hydrogen
Chris@0 27 * Copyright(c) 2002-2005 by Alex >Comix< Cominu [comix@users.sourceforge.net]
Chris@0 28 * http://www.hydrogen-music.org
Chris@0 29 */
Chris@0 30
Chris@0 31
Chris@0 32 #include "Fader.h"
Chris@0 33
Chris@0 34 #include "base/AudioLevel.h"
Chris@0 35
Chris@0 36 #include <QMouseEvent>
Chris@0 37 #include <QPixmap>
Chris@0 38 #include <QWheelEvent>
Chris@0 39 #include <QPaintEvent>
Chris@0 40 #include <QPainter>
Chris@187 41 #include <QInputDialog>
Chris@187 42
Chris@187 43 #include <iostream>
Chris@0 44
Chris@0 45 Fader::Fader(QWidget *parent, bool withoutKnob) :
Chris@0 46 QWidget(parent),
Chris@0 47 m_withoutKnob(withoutKnob),
Chris@0 48 m_value(1.0),
Chris@0 49 m_peakLeft(0.0),
Chris@187 50 m_peakRight(0.0),
Chris@857 51 m_mousePressed(false),
Chris@857 52 m_mousePressX(0),
Chris@857 53 m_mousePressValue(0)
Chris@0 54 {
Chris@0 55 setMinimumSize(116, 23);
Chris@0 56 setMaximumSize(116, 23);
Chris@0 57 resize(116, 23);
Chris@0 58
Chris@0 59 QString background_path = ":/icons/fader_background.png";
Chris@0 60 bool ok = m_back.load(background_path);
Chris@0 61 if (ok == false) {
Chris@682 62 cerr << "Fader: Error loading pixmap" << endl;
Chris@0 63 }
Chris@0 64
Chris@0 65 QString leds_path = ":/icons/fader_leds.png";
Chris@0 66 ok = m_leds.load(leds_path);
Chris@0 67 if (ok == false) {
Chris@682 68 cerr << "Error loading pixmap" << endl;
Chris@0 69 }
Chris@0 70
Chris@0 71 QString knob_path = ":/icons/fader_knob.png";
Chris@0 72 ok = m_knob.load(knob_path);
Chris@0 73 if (ok == false) {
Chris@682 74 cerr << "Error loading pixmap" << endl;
Chris@0 75 }
Chris@0 76
Chris@0 77 QString clip_path = ":/icons/fader_knob_red.png";
Chris@0 78 ok = m_clip.load(clip_path);
Chris@0 79 if (ok == false) {
Chris@682 80 cerr << "Error loading pixmap" << endl;
Chris@0 81 }
Chris@0 82 }
Chris@0 83
Chris@0 84 Fader::~Fader()
Chris@0 85 {
Chris@0 86
Chris@0 87 }
Chris@0 88
Chris@0 89 void
Chris@0 90 Fader::mouseMoveEvent(QMouseEvent *ev)
Chris@0 91 {
Chris@141 92 if (ev->button() == Qt::MidButton) {
Chris@187 93 setValue(1.0);
Chris@187 94 emit valueChanged(1.0);
Chris@187 95 update();
Chris@144 96 ev->accept();
Chris@141 97 return;
Chris@141 98 }
Chris@187 99 if (!m_mousePressed) return;
Chris@141 100
Chris@187 101 int x = ev->x();
Chris@187 102 int diff = x - m_mousePressX;
Chris@187 103 if (diff == 0) return;
Chris@0 104
Chris@187 105 int vx = AudioLevel::multiplier_to_fader
Chris@187 106 (m_mousePressValue, getMaxX(), AudioLevel::LongFader);
Chris@0 107
Chris@187 108 vx += diff;
Chris@0 109
Chris@187 110 if (vx > getMaxX()) vx = getMaxX();
Chris@187 111 if (vx < 0) vx = 0;
Chris@187 112
Chris@908 113 float fval = (float)AudioLevel::fader_to_multiplier
Chris@187 114 (vx, getMaxX(), AudioLevel::LongFader);
Chris@0 115
Chris@0 116 setValue(fval);
Chris@0 117 emit valueChanged(fval);
Chris@187 118 ev->accept();
Chris@0 119 }
Chris@0 120
Chris@0 121
Chris@0 122 void
Chris@132 123 Fader::mouseReleaseEvent(QMouseEvent *ev)
Chris@132 124 {
Chris@187 125 if (m_mousePressed) {
Chris@187 126 mouseMoveEvent(ev);
Chris@187 127 m_mousePressed = false;
Chris@187 128 }
Chris@132 129 }
Chris@132 130
Chris@132 131 void
Chris@0 132 Fader::mouseDoubleClickEvent(QMouseEvent *)
Chris@0 133 {
Chris@187 134 bool ok = false;
Chris@908 135 float min = (float)AudioLevel::fader_to_dB
Chris@187 136 (0, getMaxX(), AudioLevel::LongFader);
Chris@908 137 float max = (float)AudioLevel::fader_to_dB
Chris@187 138 (getMaxX(), getMaxX(), AudioLevel::LongFader);
Chris@908 139 float deft = (float)AudioLevel::multiplier_to_dB(m_value);
Chris@187 140
Chris@908 141 float dB = (float)QInputDialog::getDouble
Chris@187 142 (this,
Chris@187 143 tr("Enter new fader level"),
Chris@187 144 tr("New fader level, from %1 to %2 dBFS:").arg(min).arg(max),
Chris@187 145 deft, min, max, 3, &ok);
Chris@187 146
Chris@187 147 if (ok) {
Chris@908 148 float value = (float)AudioLevel::dB_to_multiplier(dB);
Chris@187 149 setValue(value);
Chris@187 150 emit valueChanged(value);
Chris@187 151 update();
Chris@187 152 }
Chris@0 153 }
Chris@0 154
Chris@0 155 void
Chris@0 156 Fader::mousePressEvent(QMouseEvent *ev)
Chris@0 157 {
Chris@187 158 if (ev->button() == Qt::MidButton ||
Chris@187 159 ((ev->button() == Qt::LeftButton) &&
Chris@187 160 (ev->modifiers() & Qt::ControlModifier))) {
Chris@82 161 setValue(1.0);
Chris@82 162 emit valueChanged(1.0);
Chris@82 163 update();
Chris@82 164 return;
Chris@82 165 }
Chris@82 166
Chris@187 167 if (ev->button() != Qt::LeftButton) return;
Chris@187 168 m_mousePressed = true;
Chris@187 169 m_mousePressX = ev->x();
Chris@187 170 m_mousePressValue = getValue();
Chris@0 171 }
Chris@0 172
Chris@0 173
Chris@0 174 void
Chris@0 175 Fader::wheelEvent(QWheelEvent *ev)
Chris@0 176 {
Chris@0 177 ev->accept();
Chris@0 178
Chris@0 179 //!!! needs improvement
Chris@0 180
Chris@0 181 if (ev->delta() > 0) {
Chris@908 182 setValue(m_value * 1.f);
Chris@0 183 } else {
Chris@908 184 setValue(m_value / 1.f);
Chris@0 185 }
Chris@0 186
Chris@0 187 update();
Chris@0 188 emit valueChanged(getValue());
Chris@0 189 }
Chris@0 190
Chris@189 191 void
Chris@189 192 Fader::enterEvent(QEvent *)
Chris@189 193 {
Chris@189 194 emit mouseEntered();
Chris@189 195 }
Chris@189 196
Chris@189 197 void
Chris@189 198 Fader::leaveEvent(QEvent *)
Chris@189 199 {
Chris@189 200 emit mouseLeft();
Chris@189 201 }
Chris@0 202
Chris@0 203 void
Chris@0 204 Fader::setValue(float v)
Chris@0 205 {
Chris@908 206 float max = (float)AudioLevel::dB_to_multiplier(10.0);
Chris@0 207
Chris@0 208 if (v > max) {
Chris@0 209 v = max;
Chris@0 210 } else if (v < 0.0) {
Chris@0 211 v = 0.0;
Chris@0 212 }
Chris@0 213
Chris@0 214 if (m_value != v) {
Chris@0 215 m_value = v;
Chris@908 216 float db = (float)AudioLevel::multiplier_to_dB(m_value);
Chris@187 217 QString text;
Chris@0 218 if (db <= AudioLevel::DB_FLOOR) {
Chris@187 219 text = tr("Level: Off");
Chris@0 220 } else {
Chris@187 221 text = tr("Level: %1%2.%3%4 dB")
Chris@187 222 .arg(db < 0.0 ? "-" : "")
Chris@187 223 .arg(abs(int(db)))
Chris@187 224 .arg(abs(int(db * 10.0) % 10))
Chris@187 225 .arg(abs(int(db * 100.0) % 10));
Chris@0 226 }
Chris@682 227 cerr << "Fader: setting tooltip to \"" << text << "\"" << endl;
Chris@187 228 QWidget::setToolTip(text);
Chris@0 229 update();
Chris@0 230 }
Chris@0 231 }
Chris@0 232
Chris@0 233
Chris@0 234 float
Chris@0 235 Fader::getValue()
Chris@0 236 {
Chris@0 237 return m_value;
Chris@0 238 }
Chris@0 239
Chris@0 240
Chris@0 241
Chris@0 242 void
Chris@0 243 Fader::setPeakLeft(float peak)
Chris@0 244 {
Chris@0 245 if (this->m_peakLeft != peak) {
Chris@0 246 this->m_peakLeft = peak;
Chris@0 247 update();
Chris@0 248 }
Chris@0 249 }
Chris@0 250
Chris@0 251
Chris@0 252 void
Chris@0 253 Fader::setPeakRight(float peak)
Chris@0 254 {
Chris@0 255 if (this->m_peakRight != peak) {
Chris@0 256 this->m_peakRight = peak;
Chris@0 257 update();
Chris@0 258 }
Chris@0 259 }
Chris@0 260
Chris@0 261
Chris@0 262 void
Chris@0 263 Fader::paintEvent(QPaintEvent *)
Chris@0 264 {
Chris@0 265 QPainter painter(this);
Chris@0 266
Chris@0 267 // background
Chris@0 268 painter.drawPixmap(rect(), m_back, QRect(0, 0, 116, 23));
Chris@0 269
Chris@0 270 int offset_L = AudioLevel::multiplier_to_fader(m_peakLeft, 116,
Chris@0 271 AudioLevel::IEC268LongMeter);
Chris@0 272
Chris@0 273 painter.drawPixmap(QRect(0, 0, offset_L, 11), m_leds,
Chris@0 274 QRect(0, 0, offset_L, 11));
Chris@0 275
Chris@0 276 int offset_R = AudioLevel::multiplier_to_fader(m_peakRight, 116,
Chris@0 277 AudioLevel::IEC268LongMeter);
Chris@0 278
Chris@0 279 painter.drawPixmap(QRect(0, 11, offset_R, 11), m_leds,
Chris@0 280 QRect(0, 11, offset_R, 11));
Chris@0 281
Chris@0 282 if (m_withoutKnob == false) {
Chris@0 283
Chris@0 284 static const uint knob_width = 29;
Chris@0 285 static const uint knob_height = 9;
Chris@0 286
Chris@0 287 int x = AudioLevel::multiplier_to_fader(m_value, 116 - knob_width,
Chris@0 288 AudioLevel::LongFader);
Chris@0 289
Chris@0 290 bool clipping = (m_peakLeft > 1.0 || m_peakRight > 1.0);
Chris@0 291
Chris@0 292 painter.drawPixmap(QRect(x, 7, knob_width, knob_height),
Chris@0 293 clipping ? m_clip : m_knob,
Chris@0 294 QRect(0, 0, knob_width, knob_height));
Chris@0 295 }
Chris@0 296 }
Chris@0 297
Chris@187 298 int
Chris@187 299 Fader::getMaxX() const
Chris@187 300 {
Chris@187 301 return 116 - 12;
Chris@187 302 }