annotate widgets/WindowShapePreview.cpp @ 1155:d1bab6a99100 project-file-rework

Cut down vastly on the number of config.pri files and places where their contents has to be effectively duplicated without them
author Chris Cannam
date Mon, 24 Oct 2016 17:53:33 +0100
parents c5a82068bd60
children 07e8ac88bcce
rev   line source
Chris@139 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@139 2
Chris@139 3 /*
Chris@139 4 Sonic Visualiser
Chris@139 5 An audio file viewer and annotation editor.
Chris@139 6 Centre for Digital Music, Queen Mary, University of London.
Chris@139 7 This file copyright 2006 Chris Cannam.
Chris@139 8
Chris@139 9 This program is free software; you can redistribute it and/or
Chris@139 10 modify it under the terms of the GNU General Public License as
Chris@139 11 published by the Free Software Foundation; either version 2 of the
Chris@139 12 License, or (at your option) any later version. See the file
Chris@139 13 COPYING included with this distribution for more information.
Chris@139 14 */
Chris@139 15
Chris@139 16 #include "WindowShapePreview.h"
Chris@139 17
Chris@139 18 #include <QHBoxLayout>
Chris@139 19 #include <QLabel>
Chris@139 20 #include <QPainter>
Chris@139 21 #include <QPainterPath>
Chris@139 22 #include <QFont>
Chris@139 23 #include <QString>
Chris@139 24
Chris@202 25 #include "data/fft/FFTapi.h"
Chris@139 26
Chris@139 27 #include <iostream>
Chris@139 28
Chris@545 29
Chris@139 30 WindowShapePreview::WindowShapePreview(QWidget *parent) :
Chris@139 31 QFrame(parent),
Chris@908 32 m_windowType(HanningWindow)
Chris@139 33 {
Chris@139 34 QHBoxLayout *layout = new QHBoxLayout;
Chris@139 35 layout->setMargin(0);
Chris@139 36 setLayout(layout);
Chris@139 37 m_windowTimeExampleLabel = new QLabel;
Chris@139 38 m_windowFreqExampleLabel = new QLabel;
Chris@139 39 layout->addWidget(m_windowTimeExampleLabel);
Chris@139 40 layout->addWidget(m_windowFreqExampleLabel);
Chris@139 41 }
Chris@139 42
Chris@139 43 WindowShapePreview::~WindowShapePreview()
Chris@139 44 {
Chris@139 45 }
Chris@139 46
Chris@139 47 void
Chris@139 48 WindowShapePreview::updateLabels()
Chris@139 49 {
Chris@139 50 int step = 24;
Chris@908 51 float peak = 48;
Chris@139 52 int w = step * 4, h = 64;
Chris@139 53 WindowType type = m_windowType;
Chris@139 54 Window<float> windower = Window<float>(type, step * 2);
Chris@139 55
Chris@139 56 QPixmap timeLabel(w, h + 1);
Chris@139 57 timeLabel.fill(Qt::white);
Chris@139 58 QPainter timePainter(&timeLabel);
Chris@139 59
Chris@139 60 QPainterPath path;
Chris@139 61
Chris@908 62 path.moveTo(0, float(h) - peak + 1);
Chris@908 63 path.lineTo(w, float(h) - peak + 1);
Chris@139 64
Chris@139 65 timePainter.setPen(Qt::gray);
Chris@139 66 timePainter.setRenderHint(QPainter::Antialiasing, true);
Chris@139 67 timePainter.drawPath(path);
Chris@139 68
Chris@139 69 path = QPainterPath();
Chris@139 70
Chris@1153 71 float *acc = new float[w];
Chris@139 72 for (int i = 0; i < w; ++i) acc[i] = 0.f;
Chris@139 73 for (int j = 0; j < 3; ++j) {
Chris@139 74 for (int i = 0; i < step * 2; ++i) {
Chris@139 75 acc[j * step + i] += windower.getValue(i);
Chris@139 76 }
Chris@139 77 }
Chris@139 78 for (int i = 0; i < w; ++i) {
Chris@908 79 int y = h - int(peak * acc[i] + 0.001f) + 1;
Chris@139 80 if (i == 0) path.moveTo(i, y);
Chris@139 81 else path.lineTo(i, y);
Chris@139 82 }
Chris@1150 83 delete[] acc;
Chris@139 84
Chris@139 85 timePainter.drawPath(path);
Chris@139 86 timePainter.setRenderHint(QPainter::Antialiasing, false);
Chris@139 87
Chris@139 88 path = QPainterPath();
Chris@139 89
Chris@139 90 timePainter.setPen(Qt::black);
Chris@139 91
Chris@139 92 for (int i = 0; i < step * 2; ++i) {
Chris@139 93 int y = h - int(peak * windower.getValue(i) + 0.001) + 1;
Chris@139 94 if (i == 0) path.moveTo(i + step, float(y));
Chris@139 95 else path.lineTo(i + step, float(y));
Chris@139 96 }
Chris@139 97
Chris@139 98 if (type == RectangularWindow) {
Chris@139 99 timePainter.drawPath(path);
Chris@139 100 path = QPainterPath();
Chris@139 101 }
Chris@139 102
Chris@139 103 timePainter.setRenderHint(QPainter::Antialiasing, true);
Chris@139 104 path.addRect(0, 0, w, h + 1);
Chris@139 105 timePainter.drawPath(path);
Chris@139 106
Chris@139 107 QFont font;
Chris@139 108 font.setPixelSize(10);
Chris@139 109 font.setItalic(true);
Chris@139 110 timePainter.setFont(font);
Chris@139 111 QString label = tr("V / time");
Chris@139 112 timePainter.drawText(w - timePainter.fontMetrics().width(label) - 4,
Chris@139 113 timePainter.fontMetrics().ascent() + 1, label);
Chris@139 114
Chris@139 115 m_windowTimeExampleLabel->setPixmap(timeLabel);
Chris@139 116
Chris@139 117 int fw = 100;
Chris@139 118
Chris@139 119 QPixmap freqLabel(fw, h + 1);
Chris@139 120 freqLabel.fill(Qt::white);
Chris@139 121 QPainter freqPainter(&freqLabel);
Chris@139 122 path = QPainterPath();
Chris@139 123
Chris@139 124 int fftsize = 512;
Chris@139 125
Chris@202 126 float *input = (float *)fftf_malloc(fftsize * sizeof(float));
Chris@202 127 fftf_complex *output =
Chris@202 128 (fftf_complex *)fftf_malloc(fftsize * sizeof(fftf_complex));
Chris@202 129 fftf_plan plan = fftf_plan_dft_r2c_1d(fftsize, input, output,
Chris@139 130 FFTW_ESTIMATE);
Chris@139 131 for (int i = 0; i < fftsize; ++i) input[i] = 0.f;
Chris@139 132 for (int i = 0; i < step * 2; ++i) {
Chris@139 133 input[fftsize/2 - step + i] = windower.getValue(i);
Chris@139 134 }
Chris@139 135
Chris@202 136 fftf_execute(plan);
Chris@202 137 fftf_destroy_plan(plan);
Chris@139 138
Chris@139 139 float maxdb = 0.f;
Chris@139 140 float mindb = 0.f;
Chris@139 141 bool first = true;
Chris@139 142 for (int i = 0; i < fftsize/2; ++i) {
Chris@139 143 float power = output[i][0] * output[i][0] + output[i][1] * output[i][1];
Chris@139 144 float db = mindb;
Chris@139 145 if (power > 0) {
Chris@908 146 db = 20.f * log10f(power);
Chris@139 147 if (first || db > maxdb) maxdb = db;
Chris@139 148 if (first || db < mindb) mindb = db;
Chris@139 149 first = false;
Chris@139 150 }
Chris@139 151 }
Chris@139 152
Chris@139 153 if (mindb > -80.f) mindb = -80.f;
Chris@139 154
Chris@139 155 // -- no, don't use the actual mindb -- it's easier to compare
Chris@139 156 // plots with a fixed min value
Chris@139 157 mindb = -170.f;
Chris@139 158
Chris@139 159 float maxval = maxdb + -mindb;
Chris@139 160
Chris@139 161 // float ly = h - ((-80.f + -mindb) / maxval) * peak + 1;
Chris@139 162
Chris@908 163 path.moveTo(0, float(h) - peak + 1);
Chris@908 164 path.lineTo(fw, float(h) - peak + 1);
Chris@139 165
Chris@139 166 freqPainter.setPen(Qt::gray);
Chris@139 167 freqPainter.setRenderHint(QPainter::Antialiasing, true);
Chris@139 168 freqPainter.drawPath(path);
Chris@139 169
Chris@139 170 path = QPainterPath();
Chris@139 171 freqPainter.setPen(Qt::black);
Chris@139 172
Chris@682 173 // cerr << "maxdb = " << maxdb << ", mindb = " << mindb << ", maxval = " <<maxval << endl;
Chris@139 174
Chris@139 175 for (int i = 0; i < fftsize/2; ++i) {
Chris@139 176 float power = output[i][0] * output[i][0] + output[i][1] * output[i][1];
Chris@908 177 float db = 20.f * log10f(power);
Chris@139 178 float val = db + -mindb;
Chris@139 179 if (val < 0) val = 0;
Chris@139 180 float norm = val / maxval;
Chris@908 181 float x = (float(fw) / float(fftsize/2)) * float(i);
Chris@908 182 float y = float(h) - norm * peak + 1;
Chris@139 183 if (i == 0) path.moveTo(x, y);
Chris@139 184 else path.lineTo(x, y);
Chris@139 185 }
Chris@139 186
Chris@139 187 freqPainter.setRenderHint(QPainter::Antialiasing, true);
Chris@139 188 path.addRect(0, 0, fw, h + 1);
Chris@139 189 freqPainter.drawPath(path);
Chris@139 190
Chris@202 191 fftf_free(input);
Chris@202 192 fftf_free(output);
Chris@139 193
Chris@139 194 freqPainter.setFont(font);
Chris@139 195 label = tr("dB / freq");
Chris@139 196 freqPainter.drawText(fw - freqPainter.fontMetrics().width(label) - 4,
Chris@139 197 freqPainter.fontMetrics().ascent() + 1, label);
Chris@139 198
Chris@139 199 m_windowFreqExampleLabel->setPixmap(freqLabel);
Chris@139 200 }
Chris@139 201
Chris@139 202 void
Chris@139 203 WindowShapePreview::setWindowType(WindowType type)
Chris@139 204 {
Chris@139 205 m_windowType = type;
Chris@139 206 updateLabels();
Chris@139 207 }
Chris@139 208