annotate widgets/WindowShapePreview.cpp @ 282:d9319859a4cf tip

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