annotate widgets/LevelPanWidget.cpp @ 925:76f4b81b766d tonioni

Try using audio level fader logic
author Chris Cannam
date Tue, 24 Mar 2015 16:02:45 +0000
parents cfcdec324712
children bfeabe25a1a3
rev   line source
Chris@923 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@923 2
Chris@923 3 /*
Chris@923 4 Sonic Visualiser
Chris@923 5 An audio file viewer and annotation editor.
Chris@923 6 Centre for Digital Music, Queen Mary, University of London.
Chris@923 7
Chris@923 8 This program is free software; you can redistribute it and/or
Chris@923 9 modify it under the terms of the GNU General Public License as
Chris@923 10 published by the Free Software Foundation; either version 2 of the
Chris@923 11 License, or (at your option) any later version. See the file
Chris@923 12 COPYING included with this distribution for more information.
Chris@923 13 */
Chris@923 14
Chris@923 15 #include "LevelPanWidget.h"
Chris@923 16
Chris@923 17 #include <QPainter>
Chris@923 18 #include <QMouseEvent>
Chris@923 19 #include <QWheelEvent>
Chris@923 20
Chris@923 21 #include "layer/ColourMapper.h"
Chris@925 22 #include "base/AudioLevel.h"
Chris@923 23
Chris@923 24 #include <iostream>
Chris@923 25
Chris@923 26 using std::cerr;
Chris@923 27 using std::endl;
Chris@923 28
Chris@924 29 static const int maxLevel = 4;
Chris@923 30 static const int maxPan = 2; // range is -maxPan to maxPan
Chris@923 31
Chris@923 32 LevelPanWidget::LevelPanWidget(QWidget *parent) :
Chris@923 33 QWidget(parent),
Chris@923 34 m_level(maxLevel),
Chris@923 35 m_pan(0),
Chris@923 36 m_editable(true)
Chris@923 37 {
Chris@923 38 }
Chris@923 39
Chris@923 40 LevelPanWidget::~LevelPanWidget()
Chris@923 41 {
Chris@923 42 }
Chris@923 43
Chris@923 44 void
Chris@925 45 LevelPanWidget::setLevel(float flevel)
Chris@923 46 {
Chris@925 47 int level = AudioLevel::multiplier_to_fader
Chris@925 48 (flevel, maxLevel, AudioLevel::ShortFader);
Chris@925 49 if (level < 0) level = 0;
Chris@925 50 if (level > maxLevel) level = maxLevel;
Chris@925 51 if (level != m_level) {
Chris@925 52 m_level = level;
Chris@925 53 float convertsTo = getLevel();
Chris@925 54 if (fabsf(convertsTo - flevel) > 1e-5) {
Chris@925 55 emitLevelChanged();
Chris@925 56 }
Chris@925 57 update();
Chris@925 58 }
Chris@923 59 }
Chris@923 60
Chris@923 61 void
Chris@923 62 LevelPanWidget::setPan(float pan)
Chris@923 63 {
Chris@923 64 m_pan = int(round(pan * maxPan));
Chris@923 65 if (m_pan < -maxPan) m_pan = -maxPan;
Chris@923 66 if (m_pan > maxPan) m_pan = maxPan;
Chris@923 67 update();
Chris@923 68 }
Chris@923 69
Chris@923 70 void
Chris@923 71 LevelPanWidget::setEditable(bool editable)
Chris@923 72 {
Chris@923 73 m_editable = editable;
Chris@923 74 update();
Chris@923 75 }
Chris@923 76
Chris@923 77 float
Chris@923 78 LevelPanWidget::getLevel() const
Chris@923 79 {
Chris@925 80 return float(AudioLevel::fader_to_multiplier
Chris@925 81 (m_level, maxLevel, AudioLevel::ShortFader));
Chris@923 82 }
Chris@923 83
Chris@923 84 float
Chris@923 85 LevelPanWidget::getPan() const
Chris@923 86 {
Chris@923 87 return float(m_pan) / float(maxPan);
Chris@923 88 }
Chris@923 89
Chris@923 90 void
Chris@923 91 LevelPanWidget::emitLevelChanged()
Chris@923 92 {
Chris@923 93 cerr << "emitting levelChanged(" << getLevel() << ")" << endl;
Chris@923 94 emit levelChanged(getLevel());
Chris@923 95 }
Chris@923 96
Chris@923 97 void
Chris@923 98 LevelPanWidget::emitPanChanged()
Chris@923 99 {
Chris@923 100 cerr << "emitting panChanged(" << getPan() << ")" << endl;
Chris@923 101 emit panChanged(getPan());
Chris@923 102 }
Chris@923 103
Chris@923 104 void
Chris@923 105 LevelPanWidget::mousePressEvent(QMouseEvent *e)
Chris@923 106 {
Chris@923 107 mouseMoveEvent(e);
Chris@923 108 }
Chris@923 109
Chris@923 110 void
Chris@923 111 LevelPanWidget::mouseMoveEvent(QMouseEvent *e)
Chris@923 112 {
Chris@923 113 if (!m_editable) return;
Chris@923 114
Chris@923 115 int level, pan;
Chris@923 116 toCell(e->pos(), level, pan);
Chris@923 117 if (level == m_level && pan == m_pan) {
Chris@923 118 return;
Chris@923 119 }
Chris@923 120 if (level != m_level) {
Chris@923 121 m_level = level;
Chris@923 122 emitLevelChanged();
Chris@923 123 }
Chris@923 124 if (pan != m_pan) {
Chris@923 125 m_pan = pan;
Chris@923 126 emitPanChanged();
Chris@923 127 }
Chris@923 128 update();
Chris@923 129 }
Chris@923 130
Chris@923 131 void
Chris@923 132 LevelPanWidget::mouseReleaseEvent(QMouseEvent *e)
Chris@923 133 {
Chris@923 134 mouseMoveEvent(e);
Chris@923 135 }
Chris@923 136
Chris@923 137 void
Chris@923 138 LevelPanWidget::wheelEvent(QWheelEvent *e)
Chris@923 139 {
Chris@923 140 if (e->modifiers() & Qt::ControlModifier) {
Chris@923 141 if (e->delta() > 0) {
Chris@923 142 if (m_pan < maxPan) {
Chris@923 143 ++m_pan;
Chris@923 144 emitPanChanged();
Chris@923 145 update();
Chris@923 146 }
Chris@923 147 } else {
Chris@923 148 if (m_pan > -maxPan) {
Chris@923 149 --m_pan;
Chris@923 150 emitPanChanged();
Chris@923 151 update();
Chris@923 152 }
Chris@923 153 }
Chris@923 154 } else {
Chris@923 155 if (e->delta() > 0) {
Chris@923 156 if (m_level < maxLevel) {
Chris@923 157 ++m_level;
Chris@923 158 emitLevelChanged();
Chris@923 159 update();
Chris@923 160 }
Chris@923 161 } else {
Chris@923 162 if (m_level > 0) {
Chris@923 163 --m_level;
Chris@923 164 emitLevelChanged();
Chris@923 165 update();
Chris@923 166 }
Chris@923 167 }
Chris@923 168 }
Chris@923 169 }
Chris@923 170
Chris@923 171 void
Chris@923 172 LevelPanWidget::toCell(QPointF loc, int &level, int &pan) const
Chris@923 173 {
Chris@923 174 double w = width(), h = height();
Chris@923 175 int npan = maxPan * 2 + 1;
Chris@924 176 int nlevel = maxLevel + 1;
Chris@924 177 double wcell = w / npan, hcell = h / nlevel;
Chris@923 178 level = int((h - loc.y()) / hcell) + 1;
Chris@924 179 if (level < 0) level = 0;
Chris@923 180 if (level > maxLevel) level = maxLevel;
Chris@923 181 pan = int(loc.x() / wcell) - maxPan;
Chris@923 182 if (pan < -maxPan) pan = -maxPan;
Chris@923 183 if (pan > maxPan) pan = maxPan;
Chris@923 184 }
Chris@923 185
Chris@923 186 QSizeF
Chris@923 187 LevelPanWidget::cellSize() const
Chris@923 188 {
Chris@923 189 double w = width(), h = height();
Chris@923 190 int npan = maxPan * 2 + 1;
Chris@924 191 int nlevel = maxLevel + 1;
Chris@924 192 double wcell = w / npan, hcell = h / nlevel;
Chris@923 193 return QSizeF(wcell, hcell);
Chris@923 194 }
Chris@923 195
Chris@923 196 QPointF
Chris@923 197 LevelPanWidget::cellCentre(int level, int pan) const
Chris@923 198 {
Chris@923 199 QSizeF cs = cellSize();
Chris@923 200 return QPointF(cs.width() * (pan + maxPan) + cs.width() / 2.,
Chris@924 201 height() - cs.height() * (level + 1) + cs.height() / 2.);
Chris@923 202 }
Chris@923 203
Chris@923 204 QSizeF
Chris@923 205 LevelPanWidget::cellLightSize() const
Chris@923 206 {
Chris@923 207 double extent = 3. / 4.;
Chris@923 208 QSizeF cs = cellSize();
Chris@923 209 double m = std::min(cs.width(), cs.height());
Chris@923 210 return QSizeF(m * extent, m * extent);
Chris@923 211 }
Chris@923 212
Chris@923 213 QRectF
Chris@923 214 LevelPanWidget::cellLightRect(int level, int pan) const
Chris@923 215 {
Chris@923 216 QSizeF cls = cellLightSize();
Chris@923 217 QPointF cc = cellCentre(level, pan);
Chris@923 218 return QRectF(cc.x() - cls.width() / 2.,
Chris@923 219 cc.y() - cls.height() / 2.,
Chris@923 220 cls.width(),
Chris@923 221 cls.height());
Chris@923 222 }
Chris@923 223
Chris@923 224 double
Chris@923 225 LevelPanWidget::thinLineWidth() const
Chris@923 226 {
Chris@923 227 double tw = ceil(width() / (maxPan * 2. * 10.));
Chris@923 228 double th = ceil(height() / (maxLevel * 10.));
Chris@923 229 return std::min(th, tw);
Chris@923 230 }
Chris@923 231
Chris@923 232 void
Chris@923 233 LevelPanWidget::paintEvent(QPaintEvent *)
Chris@923 234 {
Chris@923 235 QPainter paint(this);
Chris@923 236 ColourMapper mapper(ColourMapper::Sunset, 0, maxLevel);
Chris@923 237
Chris@923 238 paint.setRenderHint(QPainter::Antialiasing, true);
Chris@923 239
Chris@923 240 QPen pen;
Chris@923 241
Chris@923 242 double thin = thinLineWidth();
Chris@923 243
Chris@923 244 pen.setColor(QColor(127, 127, 127, 127));
Chris@923 245 pen.setWidthF(cellLightSize().width() + thin);
Chris@923 246 pen.setCapStyle(Qt::RoundCap);
Chris@923 247 paint.setPen(pen);
Chris@923 248
Chris@923 249 for (int pan = -maxPan; pan <= maxPan; ++pan) {
Chris@924 250 paint.drawLine(cellCentre(0, pan), cellCentre(maxLevel, pan));
Chris@924 251 }
Chris@924 252
Chris@924 253 if (isEnabled()) {
Chris@924 254 pen.setColor(Qt::black);
Chris@924 255 } else {
Chris@924 256 pen.setColor(Qt::darkGray);
Chris@923 257 }
Chris@923 258
Chris@923 259 pen.setWidthF(thin);
Chris@923 260 pen.setCapStyle(Qt::FlatCap);
Chris@923 261 paint.setPen(pen);
Chris@923 262
Chris@924 263 for (int level = 0; level <= m_level; ++level) {
Chris@924 264 if (isEnabled()) {
Chris@924 265 paint.setBrush(mapper.map(level));
Chris@924 266 }
Chris@924 267 QRectF clr = cellLightRect(level, m_pan);
Chris@924 268 if (m_level == 0) {
Chris@924 269 paint.drawLine(clr.topLeft(), clr.bottomRight());
Chris@924 270 paint.drawLine(clr.bottomLeft(), clr.topRight());
Chris@924 271 } else {
Chris@924 272 paint.drawEllipse(clr);
Chris@924 273 }
Chris@923 274 }
Chris@923 275 }
Chris@923 276
Chris@923 277