changeset 139:5ec6b60658d8

* Pull window type selector and shape preview out into their own widgets (from the preferences dialog)
author Chris Cannam
date Mon, 11 Sep 2006 15:32:49 +0000
parents 0f1ac9562c76
children b9235b62fe31
files widgets/WindowShapePreview.cpp widgets/WindowShapePreview.h widgets/WindowTypeSelector.cpp widgets/WindowTypeSelector.h widgets/widgets.pro
diffstat 5 files changed, 417 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/WindowShapePreview.cpp	Mon Sep 11 15:32:49 2006 +0000
@@ -0,0 +1,207 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "WindowShapePreview.h"
+
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QPainter>
+#include <QPainterPath>
+#include <QFont>
+#include <QString>
+
+#include <fftw3.h>
+
+#include <iostream>
+
+WindowShapePreview::WindowShapePreview(QWidget *parent) :
+    QFrame(parent),
+    m_windowType(WindowType(999))
+{
+    QHBoxLayout *layout = new QHBoxLayout;
+    layout->setMargin(0);
+    setLayout(layout);
+    m_windowTimeExampleLabel = new QLabel;
+    m_windowFreqExampleLabel = new QLabel;
+    layout->addWidget(m_windowTimeExampleLabel);
+    layout->addWidget(m_windowFreqExampleLabel);
+}
+
+WindowShapePreview::~WindowShapePreview()
+{
+}
+
+void
+WindowShapePreview::updateLabels()
+{
+    int step = 24;
+    int peak = 48;
+    int w = step * 4, h = 64;
+    WindowType type = m_windowType;
+    Window<float> windower = Window<float>(type, step * 2);
+
+    QPixmap timeLabel(w, h + 1);
+    timeLabel.fill(Qt::white);
+    QPainter timePainter(&timeLabel);
+
+    QPainterPath path;
+
+    path.moveTo(0, h - peak + 1);
+    path.lineTo(w, h - peak + 1);
+
+    timePainter.setPen(Qt::gray);
+    timePainter.setRenderHint(QPainter::Antialiasing, true);
+    timePainter.drawPath(path);
+    
+    path = QPainterPath();
+
+    float acc[w];
+    for (int i = 0; i < w; ++i) acc[i] = 0.f;
+    for (int j = 0; j < 3; ++j) {
+        for (int i = 0; i < step * 2; ++i) {
+            acc[j * step + i] += windower.getValue(i);
+        }
+    }
+    for (int i = 0; i < w; ++i) {
+        int y = h - int(peak * acc[i] + 0.001) + 1;
+        if (i == 0) path.moveTo(i, y);
+        else path.lineTo(i, y);
+    }
+
+    timePainter.drawPath(path);
+    timePainter.setRenderHint(QPainter::Antialiasing, false);
+
+    path = QPainterPath();
+
+    timePainter.setPen(Qt::black);
+    
+    for (int i = 0; i < step * 2; ++i) {
+        int y = h - int(peak * windower.getValue(i) + 0.001) + 1;
+        if (i == 0) path.moveTo(i + step, float(y));
+        else path.lineTo(i + step, float(y));
+    }
+
+    if (type == RectangularWindow) {
+        timePainter.drawPath(path);
+        path = QPainterPath();
+    }
+
+    timePainter.setRenderHint(QPainter::Antialiasing, true);
+    path.addRect(0, 0, w, h + 1);
+    timePainter.drawPath(path);
+
+    QFont font;
+    font.setPixelSize(10);
+    font.setItalic(true);
+    timePainter.setFont(font);
+    QString label = tr("V / time");
+    timePainter.drawText(w - timePainter.fontMetrics().width(label) - 4,
+                         timePainter.fontMetrics().ascent() + 1, label);
+
+    m_windowTimeExampleLabel->setPixmap(timeLabel);
+    
+    int fw = 100;
+
+    QPixmap freqLabel(fw, h + 1);
+    freqLabel.fill(Qt::white);
+    QPainter freqPainter(&freqLabel);
+    path = QPainterPath();
+
+    int fftsize = 512;
+
+    float *input = (float *)fftwf_malloc(fftsize * sizeof(float));
+    fftwf_complex *output =
+        (fftwf_complex *)fftwf_malloc(fftsize * sizeof(fftwf_complex));
+    fftwf_plan plan = fftwf_plan_dft_r2c_1d(fftsize, input, output,
+                                            FFTW_ESTIMATE);
+    for (int i = 0; i < fftsize; ++i) input[i] = 0.f;
+    for (int i = 0; i < step * 2; ++i) {
+        input[fftsize/2 - step + i] = windower.getValue(i);
+    }
+    
+    fftwf_execute(plan);
+    fftwf_destroy_plan(plan);
+
+    float maxdb = 0.f;
+    float mindb = 0.f;
+    bool first = true;
+    for (int i = 0; i < fftsize/2; ++i) {
+        float power = output[i][0] * output[i][0] + output[i][1] * output[i][1];
+        float db = mindb;
+        if (power > 0) {
+            db = 20 * log10(power);
+            if (first || db > maxdb) maxdb = db;
+            if (first || db < mindb) mindb = db;
+            first = false;
+        }
+    }
+
+    if (mindb > -80.f) mindb = -80.f;
+
+    // -- no, don't use the actual mindb -- it's easier to compare
+    // plots with a fixed min value
+    mindb = -170.f;
+
+    float maxval = maxdb + -mindb;
+
+//    float ly = h - ((-80.f + -mindb) / maxval) * peak + 1;
+
+    path.moveTo(0, h - peak + 1);
+    path.lineTo(fw, h - peak + 1);
+
+    freqPainter.setPen(Qt::gray);
+    freqPainter.setRenderHint(QPainter::Antialiasing, true);
+    freqPainter.drawPath(path);
+    
+    path = QPainterPath();
+    freqPainter.setPen(Qt::black);
+
+//    std::cerr << "maxdb = " << maxdb << ", mindb = " << mindb << ", maxval = " <<maxval << std::endl;
+
+    for (int i = 0; i < fftsize/2; ++i) {
+        float power = output[i][0] * output[i][0] + output[i][1] * output[i][1];
+        float db = 20 * log10(power);
+        float val = db + -mindb;
+        if (val < 0) val = 0;
+        float norm = val / maxval;
+        float x = (fw / float(fftsize/2)) * i;
+        float y = h - norm * peak + 1;
+        if (i == 0) path.moveTo(x, y);
+        else path.lineTo(x, y);
+    }
+
+    freqPainter.setRenderHint(QPainter::Antialiasing, true);
+    path.addRect(0, 0, fw, h + 1);
+    freqPainter.drawPath(path);
+
+    fftwf_free(input);
+    fftwf_free(output);
+
+    freqPainter.setFont(font);
+    label = tr("dB / freq");
+    freqPainter.drawText(fw - freqPainter.fontMetrics().width(label) - 4,
+                         freqPainter.fontMetrics().ascent() + 1, label);
+
+    m_windowFreqExampleLabel->setPixmap(freqLabel);
+}
+
+void
+WindowShapePreview::setWindowType(WindowType type)
+{
+    if (m_windowType == type) return;
+    m_windowType = type;
+    updateLabels();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/WindowShapePreview.h	Mon Sep 11 15:32:49 2006 +0000
@@ -0,0 +1,44 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#ifndef _WINDOW_SHAPE_PREVIEW_H_
+#define _WINDOW_SHAPE_PREVIEW_H_
+
+#include <QFrame>
+
+#include "base/Window.h"
+
+class QLabel;
+
+class WindowShapePreview : public QFrame
+{
+    Q_OBJECT
+    
+public:
+    WindowShapePreview(QWidget *parent = 0);
+    virtual ~WindowShapePreview();
+
+public slots:
+    void setWindowType(WindowType type);
+
+protected:
+    QLabel *m_windowTimeExampleLabel;
+    QLabel *m_windowFreqExampleLabel;
+    WindowType m_windowType;
+
+    void updateLabels();
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/WindowTypeSelector.cpp	Mon Sep 11 15:32:49 2006 +0000
@@ -0,0 +1,107 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "WindowTypeSelector.h"
+
+#include "WindowShapePreview.h"
+
+#include <QVBoxLayout>
+#include <QComboBox>
+
+#include "base/Preferences.h"
+
+WindowTypeSelector::WindowTypeSelector(WindowType defaultType, QWidget *parent) :
+    QFrame(parent),
+    m_windowType(WindowType(999))
+{
+    QVBoxLayout *layout = new QVBoxLayout;
+    layout->setMargin(0);
+    setLayout(layout);
+
+    // The WindowType enum is in rather a ragbag order -- reorder it here
+    // in a more sensible order
+    m_windows = new WindowType[9];
+    m_windows[0] = HanningWindow;
+    m_windows[1] = HammingWindow;
+    m_windows[2] = BlackmanWindow;
+    m_windows[3] = BlackmanHarrisWindow;
+    m_windows[4] = NuttallWindow;
+    m_windows[5] = GaussianWindow;
+    m_windows[6] = ParzenWindow;
+    m_windows[7] = BartlettWindow;
+    m_windows[8] = RectangularWindow;
+
+    Preferences *prefs = Preferences::getInstance();
+
+    m_windowShape = new WindowShapePreview;
+
+    m_windowCombo = new QComboBox;
+    int min = 0, max = 0, i = 0;
+    int window = int(defaultType);
+    if (window == 999) {
+        window = prefs->getPropertyRangeAndValue("Window Type", &min, &max);
+    }
+    int index = 0;
+    
+    for (i = 0; i <= 8; ++i) {
+        m_windowCombo->addItem(prefs->getPropertyValueLabel("Window Type",
+                                                            m_windows[i]));
+        if (m_windows[i] == window) index = i;
+    }
+
+    m_windowCombo->setCurrentIndex(index);
+
+    layout->addWidget(m_windowShape);
+    layout->addWidget(m_windowCombo);
+
+    connect(m_windowCombo, SIGNAL(currentIndexChanged(int)),
+            this, SLOT(windowIndexChanged(int)));
+    windowIndexChanged(index);
+}
+
+WindowTypeSelector::~WindowTypeSelector()
+{
+    delete[] m_windows;
+}
+
+WindowType
+WindowTypeSelector::getWindowType() const
+{
+    return m_windowType;
+}
+
+void
+WindowTypeSelector::setWindowType(WindowType type)
+{
+    if (type == m_windowType) return;
+    int index;
+    for (index = 0; index <= 8; ++index) {
+        if (m_windows[index] == type) break;
+    }
+    if (index <= 8) m_windowCombo->setCurrentIndex(index);
+    m_windowType = type;
+    m_windowShape->setWindowType(m_windowType);
+}
+
+void
+WindowTypeSelector::windowIndexChanged(int index)
+{
+    WindowType type = m_windows[index];
+    if (type == m_windowType) return;
+    m_windowType = type;
+    m_windowShape->setWindowType(m_windowType);
+    emit windowTypeChanged(type);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/WindowTypeSelector.h	Mon Sep 11 15:32:49 2006 +0000
@@ -0,0 +1,53 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#ifndef _WINDOW_TYPE_SELECTOR_H_
+#define _WINDOW_TYPE_SELECTOR_H_
+
+#include <QFrame>
+
+#include "base/Window.h"
+
+class WindowShapePreview;
+class QComboBox;
+
+class WindowTypeSelector : public QFrame
+{
+    Q_OBJECT
+
+public:
+    WindowTypeSelector(WindowType defaultType = WindowType(999), // 999 -> get from preferences
+                       QWidget *parent = 0);
+    virtual ~WindowTypeSelector();
+
+    WindowType getWindowType() const;
+
+signals:
+    void windowTypeChanged(WindowType type);
+
+public slots:
+    void setWindowType(WindowType type);
+
+protected slots:
+    void windowIndexChanged(int index);
+
+protected:
+    QComboBox *m_windowCombo;
+    WindowShapePreview *m_windowShape;
+    WindowType *m_windows;
+    WindowType m_windowType;
+};
+
+#endif
--- a/widgets/widgets.pro	Tue Sep 05 16:34:54 2006 +0000
+++ b/widgets/widgets.pro	Mon Sep 11 15:32:49 2006 +0000
@@ -24,7 +24,9 @@
            PluginParameterDialog.h \
            PropertyBox.h \
            PropertyStack.h \
-           Thumbwheel.h
+           Thumbwheel.h \
+           WindowShapePreview.h \
+           WindowTypeSelector.h
 SOURCES += AudioDial.cpp \
            Fader.cpp \
            ItemEditDialog.cpp \
@@ -35,4 +37,6 @@
            PluginParameterDialog.cpp \
            PropertyBox.cpp \
            PropertyStack.cpp \
-           Thumbwheel.cpp
+           Thumbwheel.cpp \
+           WindowShapePreview.cpp \
+           WindowTypeSelector.cpp