lbajardsilogic@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: Sonic Visualiser lbajardsilogic@0: An audio file viewer and annotation editor. lbajardsilogic@0: Centre for Digital Music, Queen Mary, University of London. lbajardsilogic@0: This file copyright 2006 Chris Cannam. lbajardsilogic@0: lbajardsilogic@0: This program is free software; you can redistribute it and/or lbajardsilogic@0: modify it under the terms of the GNU General Public License as lbajardsilogic@0: published by the Free Software Foundation; either version 2 of the lbajardsilogic@0: License, or (at your option) any later version. See the file lbajardsilogic@0: COPYING included with this distribution for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: #include "WindowShapePreview.h" lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: #include "data/fft/FFTapi.h" lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: WindowShapePreview::WindowShapePreview(QWidget *parent) : lbajardsilogic@0: QFrame(parent), lbajardsilogic@0: m_windowType(WindowType(999)) lbajardsilogic@0: { lbajardsilogic@0: QHBoxLayout *layout = new QHBoxLayout; lbajardsilogic@0: layout->setMargin(0); lbajardsilogic@0: setLayout(layout); lbajardsilogic@0: m_windowTimeExampleLabel = new QLabel; lbajardsilogic@0: m_windowFreqExampleLabel = new QLabel; lbajardsilogic@0: layout->addWidget(m_windowTimeExampleLabel); lbajardsilogic@0: layout->addWidget(m_windowFreqExampleLabel); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: WindowShapePreview::~WindowShapePreview() lbajardsilogic@0: { lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: WindowShapePreview::updateLabels() lbajardsilogic@0: { lbajardsilogic@0: int step = 24; lbajardsilogic@0: int peak = 48; lbajardsilogic@0: int w = step * 4, h = 64; lbajardsilogic@0: WindowType type = m_windowType; lbajardsilogic@0: Window windower = Window(type, step * 2); lbajardsilogic@0: lbajardsilogic@0: QPixmap timeLabel(w, h + 1); lbajardsilogic@0: timeLabel.fill(Qt::white); lbajardsilogic@0: QPainter timePainter(&timeLabel); lbajardsilogic@0: lbajardsilogic@0: QPainterPath path; lbajardsilogic@0: lbajardsilogic@0: path.moveTo(0, h - peak + 1); lbajardsilogic@0: path.lineTo(w, h - peak + 1); lbajardsilogic@0: lbajardsilogic@0: timePainter.setPen(Qt::gray); lbajardsilogic@0: timePainter.setRenderHint(QPainter::Antialiasing, true); lbajardsilogic@0: timePainter.drawPath(path); lbajardsilogic@0: lbajardsilogic@0: path = QPainterPath(); lbajardsilogic@0: lbajardsilogic@0: //float acc[w]; lbajardsilogic@0: float *acc = (float*) malloc(w*sizeof(float)); lbajardsilogic@0: for (int i = 0; i < w; ++i) acc[i] = 0.f; lbajardsilogic@0: for (int j = 0; j < 3; ++j) { lbajardsilogic@0: for (int i = 0; i < step * 2; ++i) { lbajardsilogic@0: acc[j * step + i] += windower.getValue(i); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: for (int i = 0; i < w; ++i) { lbajardsilogic@0: int y = h - int(peak * acc[i] + 0.001) + 1; lbajardsilogic@0: if (i == 0) path.moveTo(i, y); lbajardsilogic@0: else path.lineTo(i, y); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: timePainter.drawPath(path); lbajardsilogic@0: timePainter.setRenderHint(QPainter::Antialiasing, false); lbajardsilogic@0: lbajardsilogic@0: path = QPainterPath(); lbajardsilogic@0: lbajardsilogic@0: timePainter.setPen(Qt::black); lbajardsilogic@0: lbajardsilogic@0: for (int i = 0; i < step * 2; ++i) { lbajardsilogic@0: int y = h - int(peak * windower.getValue(i) + 0.001) + 1; lbajardsilogic@0: if (i == 0) path.moveTo(i + step, float(y)); lbajardsilogic@0: else path.lineTo(i + step, float(y)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (type == RectangularWindow) { lbajardsilogic@0: timePainter.drawPath(path); lbajardsilogic@0: path = QPainterPath(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: timePainter.setRenderHint(QPainter::Antialiasing, true); lbajardsilogic@0: path.addRect(0, 0, w, h + 1); lbajardsilogic@0: timePainter.drawPath(path); lbajardsilogic@0: lbajardsilogic@0: QFont font; lbajardsilogic@0: font.setPixelSize(10); lbajardsilogic@0: font.setItalic(true); lbajardsilogic@0: timePainter.setFont(font); lbajardsilogic@0: QString label = tr("V / time"); lbajardsilogic@0: timePainter.drawText(w - timePainter.fontMetrics().width(label) - 4, lbajardsilogic@0: timePainter.fontMetrics().ascent() + 1, label); lbajardsilogic@0: lbajardsilogic@0: m_windowTimeExampleLabel->setPixmap(timeLabel); lbajardsilogic@0: lbajardsilogic@0: int fw = 100; lbajardsilogic@0: lbajardsilogic@0: QPixmap freqLabel(fw, h + 1); lbajardsilogic@0: freqLabel.fill(Qt::white); lbajardsilogic@0: QPainter freqPainter(&freqLabel); lbajardsilogic@0: path = QPainterPath(); lbajardsilogic@0: lbajardsilogic@0: int fftsize = 512; lbajardsilogic@0: lbajardsilogic@0: float *input = (float *)fftf_malloc(fftsize * sizeof(float)); lbajardsilogic@0: fftf_complex *output = lbajardsilogic@0: (fftf_complex *)fftf_malloc(fftsize * sizeof(fftf_complex)); lbajardsilogic@0: fftf_plan plan = fftf_plan_dft_r2c_1d(fftsize, input, output, lbajardsilogic@0: FFTW_ESTIMATE); lbajardsilogic@0: for (int i = 0; i < fftsize; ++i) input[i] = 0.f; lbajardsilogic@0: for (int i = 0; i < step * 2; ++i) { lbajardsilogic@0: input[fftsize/2 - step + i] = windower.getValue(i); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: fftf_execute(plan); lbajardsilogic@0: fftf_destroy_plan(plan); lbajardsilogic@0: lbajardsilogic@0: float maxdb = 0.f; lbajardsilogic@0: float mindb = 0.f; lbajardsilogic@0: bool first = true; lbajardsilogic@0: for (int i = 0; i < fftsize/2; ++i) { lbajardsilogic@0: float power = output[i][0] * output[i][0] + output[i][1] * output[i][1]; lbajardsilogic@0: float db = mindb; lbajardsilogic@0: if (power > 0) { lbajardsilogic@0: db = 20 * log10(power); lbajardsilogic@0: if (first || db > maxdb) maxdb = db; lbajardsilogic@0: if (first || db < mindb) mindb = db; lbajardsilogic@0: first = false; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (mindb > -80.f) mindb = -80.f; lbajardsilogic@0: lbajardsilogic@0: // -- no, don't use the actual mindb -- it's easier to compare lbajardsilogic@0: // plots with a fixed min value lbajardsilogic@0: mindb = -170.f; lbajardsilogic@0: lbajardsilogic@0: float maxval = maxdb + -mindb; lbajardsilogic@0: lbajardsilogic@0: // float ly = h - ((-80.f + -mindb) / maxval) * peak + 1; lbajardsilogic@0: lbajardsilogic@0: path.moveTo(0, h - peak + 1); lbajardsilogic@0: path.lineTo(fw, h - peak + 1); lbajardsilogic@0: lbajardsilogic@0: freqPainter.setPen(Qt::gray); lbajardsilogic@0: freqPainter.setRenderHint(QPainter::Antialiasing, true); lbajardsilogic@0: freqPainter.drawPath(path); lbajardsilogic@0: lbajardsilogic@0: path = QPainterPath(); lbajardsilogic@0: freqPainter.setPen(Qt::black); lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "maxdb = " << maxdb << ", mindb = " << mindb << ", maxval = " <setPixmap(freqLabel); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: WindowShapePreview::setWindowType(WindowType type) lbajardsilogic@0: { lbajardsilogic@0: if (m_windowType == type) return; lbajardsilogic@0: m_windowType = type; lbajardsilogic@0: updateLabels(); lbajardsilogic@0: } lbajardsilogic@0: