00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "WindowShapePreview.h"
00017
00018 #include <QHBoxLayout>
00019 #include <QLabel>
00020 #include <QPainter>
00021 #include <QPainterPath>
00022 #include <QFont>
00023 #include <QString>
00024
00025 #include "data/fft/FFTapi.h"
00026
00027 #include <iostream>
00028
00029 WindowShapePreview::WindowShapePreview(QWidget *parent) :
00030 QFrame(parent),
00031 m_windowType(WindowType(999))
00032 {
00033 QHBoxLayout *layout = new QHBoxLayout;
00034 layout->setMargin(0);
00035 setLayout(layout);
00036 m_windowTimeExampleLabel = new QLabel;
00037 m_windowFreqExampleLabel = new QLabel;
00038 layout->addWidget(m_windowTimeExampleLabel);
00039 layout->addWidget(m_windowFreqExampleLabel);
00040 }
00041
00042 WindowShapePreview::~WindowShapePreview()
00043 {
00044 }
00045
00046 void
00047 WindowShapePreview::updateLabels()
00048 {
00049 int step = 24;
00050 int peak = 48;
00051 int w = step * 4, h = 64;
00052 WindowType type = m_windowType;
00053 Window<float> windower = Window<float>(type, step * 2);
00054
00055 QPixmap timeLabel(w, h + 1);
00056 timeLabel.fill(Qt::white);
00057 QPainter timePainter(&timeLabel);
00058
00059 QPainterPath path;
00060
00061 path.moveTo(0, h - peak + 1);
00062 path.lineTo(w, h - peak + 1);
00063
00064 timePainter.setPen(Qt::gray);
00065 timePainter.setRenderHint(QPainter::Antialiasing, true);
00066 timePainter.drawPath(path);
00067
00068 path = QPainterPath();
00069
00070 float acc[w];
00071 for (int i = 0; i < w; ++i) acc[i] = 0.f;
00072 for (int j = 0; j < 3; ++j) {
00073 for (int i = 0; i < step * 2; ++i) {
00074 acc[j * step + i] += windower.getValue(i);
00075 }
00076 }
00077 for (int i = 0; i < w; ++i) {
00078 int y = h - int(peak * acc[i] + 0.001) + 1;
00079 if (i == 0) path.moveTo(i, y);
00080 else path.lineTo(i, y);
00081 }
00082
00083 timePainter.drawPath(path);
00084 timePainter.setRenderHint(QPainter::Antialiasing, false);
00085
00086 path = QPainterPath();
00087
00088 timePainter.setPen(Qt::black);
00089
00090 for (int i = 0; i < step * 2; ++i) {
00091 int y = h - int(peak * windower.getValue(i) + 0.001) + 1;
00092 if (i == 0) path.moveTo(i + step, float(y));
00093 else path.lineTo(i + step, float(y));
00094 }
00095
00096 if (type == RectangularWindow) {
00097 timePainter.drawPath(path);
00098 path = QPainterPath();
00099 }
00100
00101 timePainter.setRenderHint(QPainter::Antialiasing, true);
00102 path.addRect(0, 0, w, h + 1);
00103 timePainter.drawPath(path);
00104
00105 QFont font;
00106 font.setPixelSize(10);
00107 font.setItalic(true);
00108 timePainter.setFont(font);
00109 QString label = tr("V / time");
00110 timePainter.drawText(w - timePainter.fontMetrics().width(label) - 4,
00111 timePainter.fontMetrics().ascent() + 1, label);
00112
00113 m_windowTimeExampleLabel->setPixmap(timeLabel);
00114
00115 int fw = 100;
00116
00117 QPixmap freqLabel(fw, h + 1);
00118 freqLabel.fill(Qt::white);
00119 QPainter freqPainter(&freqLabel);
00120 path = QPainterPath();
00121
00122 int fftsize = 512;
00123
00124 float *input = (float *)fftf_malloc(fftsize * sizeof(float));
00125 fftf_complex *output =
00126 (fftf_complex *)fftf_malloc(fftsize * sizeof(fftf_complex));
00127 fftf_plan plan = fftf_plan_dft_r2c_1d(fftsize, input, output,
00128 FFTW_ESTIMATE);
00129 for (int i = 0; i < fftsize; ++i) input[i] = 0.f;
00130 for (int i = 0; i < step * 2; ++i) {
00131 input[fftsize/2 - step + i] = windower.getValue(i);
00132 }
00133
00134 fftf_execute(plan);
00135 fftf_destroy_plan(plan);
00136
00137 float maxdb = 0.f;
00138 float mindb = 0.f;
00139 bool first = true;
00140 for (int i = 0; i < fftsize/2; ++i) {
00141 float power = output[i][0] * output[i][0] + output[i][1] * output[i][1];
00142 float db = mindb;
00143 if (power > 0) {
00144 db = 20 * log10(power);
00145 if (first || db > maxdb) maxdb = db;
00146 if (first || db < mindb) mindb = db;
00147 first = false;
00148 }
00149 }
00150
00151 if (mindb > -80.f) mindb = -80.f;
00152
00153
00154
00155 mindb = -170.f;
00156
00157 float maxval = maxdb + -mindb;
00158
00159
00160
00161 path.moveTo(0, h - peak + 1);
00162 path.lineTo(fw, h - peak + 1);
00163
00164 freqPainter.setPen(Qt::gray);
00165 freqPainter.setRenderHint(QPainter::Antialiasing, true);
00166 freqPainter.drawPath(path);
00167
00168 path = QPainterPath();
00169 freqPainter.setPen(Qt::black);
00170
00171
00172
00173 for (int i = 0; i < fftsize/2; ++i) {
00174 float power = output[i][0] * output[i][0] + output[i][1] * output[i][1];
00175 float db = 20 * log10(power);
00176 float val = db + -mindb;
00177 if (val < 0) val = 0;
00178 float norm = val / maxval;
00179 float x = (fw / float(fftsize/2)) * i;
00180 float y = h - norm * peak + 1;
00181 if (i == 0) path.moveTo(x, y);
00182 else path.lineTo(x, y);
00183 }
00184
00185 freqPainter.setRenderHint(QPainter::Antialiasing, true);
00186 path.addRect(0, 0, fw, h + 1);
00187 freqPainter.drawPath(path);
00188
00189 fftf_free(input);
00190 fftf_free(output);
00191
00192 freqPainter.setFont(font);
00193 label = tr("dB / freq");
00194 freqPainter.drawText(fw - freqPainter.fontMetrics().width(label) - 4,
00195 freqPainter.fontMetrics().ascent() + 1, label);
00196
00197 m_windowFreqExampleLabel->setPixmap(freqLabel);
00198 }
00199
00200 void
00201 WindowShapePreview::setWindowType(WindowType type)
00202 {
00203 if (m_windowType == type) return;
00204 m_windowType = type;
00205 updateLabels();
00206 }
00207