annotate view/AlignmentView.cpp @ 1367:f5566f7271fe waverevision

Rework waveform renderer to use smooth paths, aiming to get near-pixel-identical results when zoomed out far enough for a single path not to be relevant
author Chris Cannam
date Wed, 31 Oct 2018 15:06:32 +0000
parents 13d9b422f7fe
children c8a6fd3f9dff
rev   line source
Chris@867 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@867 2
Chris@867 3 /*
Chris@867 4 Sonic Visualiser
Chris@867 5 An audio file viewer and annotation editor.
Chris@867 6 Centre for Digital Music, Queen Mary, University of London.
Chris@867 7 This file copyright 2006-2014 Chris Cannam and QMUL.
Chris@867 8
Chris@867 9 This program is free software; you can redistribute it and/or
Chris@867 10 modify it under the terms of the GNU General Public License as
Chris@867 11 published by the Free Software Foundation; either version 2 of the
Chris@867 12 License, or (at your option) any later version. See the file
Chris@867 13 COPYING included with this distribution for more information.
Chris@867 14 */
Chris@867 15
Chris@867 16 #include "AlignmentView.h"
Chris@867 17
Chris@867 18 #include <QPainter>
Chris@867 19
Chris@868 20 #include "data/model/SparseOneDimensionalModel.h"
Chris@868 21
Chris@868 22 #include "layer/TimeInstantLayer.h"
Chris@868 23
Chris@867 24 using std::vector;
Chris@867 25
Chris@867 26 AlignmentView::AlignmentView(QWidget *w) :
Chris@867 27 View(w, false),
Chris@867 28 m_above(0),
Chris@867 29 m_below(0)
Chris@867 30 {
Chris@867 31 setObjectName(tr("AlignmentView"));
Chris@867 32 }
Chris@867 33
Chris@867 34 void
Chris@976 35 AlignmentView::globalCentreFrameChanged(sv_frame_t f)
Chris@867 36 {
Chris@867 37 View::globalCentreFrameChanged(f);
Chris@867 38 update();
Chris@867 39 }
Chris@867 40
Chris@867 41 void
Chris@976 42 AlignmentView::viewCentreFrameChanged(View *v, sv_frame_t f)
Chris@867 43 {
Chris@867 44 View::viewCentreFrameChanged(v, f);
Chris@867 45 if (v == m_above) {
Chris@1266 46 m_centreFrame = f;
Chris@1266 47 update();
Chris@867 48 } else if (v == m_below) {
Chris@1266 49 update();
Chris@867 50 }
Chris@867 51 }
Chris@867 52
Chris@867 53 void
Chris@976 54 AlignmentView::viewManagerPlaybackFrameChanged(sv_frame_t)
Chris@867 55 {
Chris@867 56 update();
Chris@867 57 }
Chris@867 58
Chris@867 59 void
Chris@1183 60 AlignmentView::viewAboveZoomLevelChanged(ZoomLevel level, bool)
Chris@867 61 {
Chris@867 62 m_zoomLevel = level;
Chris@867 63 update();
Chris@867 64 }
Chris@867 65
Chris@867 66 void
Chris@1183 67 AlignmentView::viewBelowZoomLevelChanged(ZoomLevel, bool)
Chris@867 68 {
Chris@867 69 update();
Chris@867 70 }
Chris@867 71
Chris@867 72 void
Chris@867 73 AlignmentView::setViewAbove(View *v)
Chris@867 74 {
Chris@867 75 if (m_above) {
Chris@1266 76 disconnect(m_above, 0, this, 0);
Chris@867 77 }
Chris@867 78
Chris@867 79 m_above = v;
Chris@867 80
Chris@867 81 if (m_above) {
Chris@1266 82 connect(m_above,
Chris@1183 83 SIGNAL(zoomLevelChanged(ZoomLevel, bool)),
Chris@1266 84 this,
Chris@1183 85 SLOT(viewAboveZoomLevelChanged(ZoomLevel, bool)));
Chris@867 86 }
Chris@867 87 }
Chris@867 88
Chris@867 89 void
Chris@867 90 AlignmentView::setViewBelow(View *v)
Chris@867 91 {
Chris@867 92 if (m_below) {
Chris@1266 93 disconnect(m_below, 0, this, 0);
Chris@867 94 }
Chris@867 95
Chris@867 96 m_below = v;
Chris@867 97
Chris@867 98 if (m_below) {
Chris@1266 99 connect(m_below,
Chris@1183 100 SIGNAL(zoomLevelChanged(ZoomLevel, bool)),
Chris@1266 101 this,
Chris@1183 102 SLOT(viewBelowZoomLevelChanged(ZoomLevel, bool)));
Chris@867 103 }
Chris@867 104 }
Chris@867 105
Chris@867 106 void
Chris@867 107 AlignmentView::paintEvent(QPaintEvent *)
Chris@867 108 {
Chris@867 109 if (m_above == 0 || m_below == 0 || !m_manager) return;
Chris@867 110
Chris@867 111 bool darkPalette = false;
Chris@867 112 if (m_manager) darkPalette = m_manager->getGlobalDarkBackground();
Chris@867 113
Chris@881 114 QColor fg, bg;
Chris@881 115 if (darkPalette) {
Chris@881 116 fg = Qt::gray;
Chris@881 117 bg = Qt::black;
Chris@881 118 } else {
Chris@881 119 fg = Qt::black;
Chris@881 120 bg = Qt::gray;
Chris@881 121 }
Chris@867 122
Chris@867 123 QPainter paint(this);
Chris@867 124 paint.setPen(QPen(fg, 2));
Chris@867 125 paint.setBrush(Qt::NoBrush);
Chris@867 126 paint.setRenderHint(QPainter::Antialiasing, true);
Chris@867 127
Chris@867 128 paint.fillRect(rect(), bg);
Chris@867 129
Chris@976 130 vector<sv_frame_t> keyFrames = getKeyFrames();
Chris@867 131
Chris@976 132 foreach (sv_frame_t f, keyFrames) {
Chris@1266 133 int ax = m_above->getXForFrame(f);
Chris@1266 134 sv_frame_t rf = m_above->alignToReference(f);
Chris@1266 135 sv_frame_t bf = m_below->alignFromReference(rf);
Chris@1266 136 int bx = m_below->getXForFrame(bf);
Chris@1266 137 paint.drawLine(ax, 0, bx, height());
Chris@867 138 }
Chris@867 139
Chris@867 140 paint.end();
Chris@867 141 }
Chris@867 142
Chris@976 143 vector<sv_frame_t>
Chris@868 144 AlignmentView::getKeyFrames()
Chris@868 145 {
Chris@868 146 if (!m_above) {
Chris@1266 147 return getDefaultKeyFrames();
Chris@868 148 }
Chris@868 149
Chris@868 150 SparseOneDimensionalModel *m = 0;
Chris@868 151
Chris@868 152 // get the topmost such
Chris@868 153 for (int i = 0; i < m_above->getLayerCount(); ++i) {
Chris@1266 154 if (qobject_cast<TimeInstantLayer *>(m_above->getLayer(i))) {
Chris@1266 155 SparseOneDimensionalModel *mm =
Chris@1266 156 qobject_cast<SparseOneDimensionalModel *>
Chris@1266 157 (m_above->getLayer(i)->getModel());
Chris@1266 158 if (mm) m = mm;
Chris@1266 159 }
Chris@868 160 }
Chris@868 161
Chris@868 162 if (!m) {
Chris@1266 163 return getDefaultKeyFrames();
Chris@868 164 }
Chris@868 165
Chris@976 166 vector<sv_frame_t> keyFrames;
Chris@868 167
Chris@868 168 const SparseOneDimensionalModel::PointList pp = m->getPoints();
Chris@868 169 for (SparseOneDimensionalModel::PointList::const_iterator pi = pp.begin();
Chris@1266 170 pi != pp.end(); ++pi) {
Chris@1266 171 keyFrames.push_back(pi->frame);
Chris@868 172 }
Chris@868 173
Chris@868 174 return keyFrames;
Chris@868 175 }
Chris@868 176
Chris@976 177 vector<sv_frame_t>
Chris@868 178 AlignmentView::getDefaultKeyFrames()
Chris@868 179 {
Chris@976 180 vector<sv_frame_t> keyFrames;
Chris@868 181
Chris@868 182 if (!m_above || !m_manager) return keyFrames;
Chris@868 183
Chris@976 184 sv_samplerate_t rate = m_manager->getMainModelSampleRate();
Chris@868 185 if (rate == 0) return keyFrames;
Chris@868 186
Chris@976 187 for (sv_frame_t f = m_above->getModelsStartFrame();
Chris@1266 188 f <= m_above->getModelsEndFrame();
Chris@1266 189 f += sv_frame_t(rate * 5 + 0.5)) {
Chris@1266 190 keyFrames.push_back(f);
Chris@868 191 }
Chris@868 192
Chris@868 193 return keyFrames;
Chris@868 194 }
Chris@868 195
Chris@868 196
Chris@868 197
Chris@868 198
Chris@868 199
Chris@868 200