comparison widgets/WindowShapePreview.cpp @ 1216:dc2af6616c83

Merge from branch 3.0-integration
author Chris Cannam
date Fri, 13 Jan 2017 10:29:50 +0000
parents 6796afa25c88
children d39db4673676
comparison
equal deleted inserted replaced
1048:e8102ff5573b 1216:dc2af6616c83
20 #include <QPainter> 20 #include <QPainter>
21 #include <QPainterPath> 21 #include <QPainterPath>
22 #include <QFont> 22 #include <QFont>
23 #include <QString> 23 #include <QString>
24 24
25 #include "data/fft/FFTapi.h" 25 #include <bqfft/FFT.h>
26 26
27 #include <vector>
28 #include <complex>
27 #include <iostream> 29 #include <iostream>
28 30
29 #ifndef __GNUC__ 31 using namespace std;
30 #include <alloca.h> 32
31 #endif
32 33
33 WindowShapePreview::WindowShapePreview(QWidget *parent) : 34 WindowShapePreview::WindowShapePreview(QWidget *parent) :
34 QFrame(parent), 35 QFrame(parent),
35 m_windowType(HanningWindow) 36 m_windowType(HanningWindow)
36 { 37 {
48 } 49 }
49 50
50 void 51 void
51 WindowShapePreview::updateLabels() 52 WindowShapePreview::updateLabels()
52 { 53 {
53 int step = 24; 54 float scaleRatio = float(QFontMetrics(font()).height()) / 14.f;
54 float peak = 48; 55 if (scaleRatio < 1.f) scaleRatio = 1.f;
55 int w = step * 4, h = 64; 56
57 int step = int(24 * scaleRatio);
58 float peak = float(48 * scaleRatio);
59
60 int w = step * 4, h = int((peak * 4) / 3);
61
56 WindowType type = m_windowType; 62 WindowType type = m_windowType;
57 Window<float> windower = Window<float>(type, step * 2); 63 Window<float> windower = Window<float>(type, step * 2);
58 64
59 QPixmap timeLabel(w, h + 1); 65 QPixmap timeLabel(w, h + 1);
60 timeLabel.fill(Qt::white); 66 timeLabel.fill(Qt::white);
61 QPainter timePainter(&timeLabel); 67 QPainter timePainter(&timeLabel);
62 68
63 QPainterPath path; 69 QPainterPath path;
69 timePainter.setRenderHint(QPainter::Antialiasing, true); 75 timePainter.setRenderHint(QPainter::Antialiasing, true);
70 timePainter.drawPath(path); 76 timePainter.drawPath(path);
71 77
72 path = QPainterPath(); 78 path = QPainterPath();
73 79
74 #ifdef __GNUC__ 80 float *acc = new float[w];
75 float acc[w];
76 #else
77 float *acc = (float *)alloca(w * sizeof(float));
78 #endif
79
80 for (int i = 0; i < w; ++i) acc[i] = 0.f; 81 for (int i = 0; i < w; ++i) acc[i] = 0.f;
81 for (int j = 0; j < 3; ++j) { 82 for (int j = 0; j < 3; ++j) {
82 for (int i = 0; i < step * 2; ++i) { 83 for (int i = 0; i < step * 2; ++i) {
83 acc[j * step + i] += windower.getValue(i); 84 acc[j * step + i] += windower.getValue(i);
84 } 85 }
86 for (int i = 0; i < w; ++i) { 87 for (int i = 0; i < w; ++i) {
87 int y = h - int(peak * acc[i] + 0.001f) + 1; 88 int y = h - int(peak * acc[i] + 0.001f) + 1;
88 if (i == 0) path.moveTo(i, y); 89 if (i == 0) path.moveTo(i, y);
89 else path.lineTo(i, y); 90 else path.lineTo(i, y);
90 } 91 }
92 delete[] acc;
91 93
92 timePainter.drawPath(path); 94 timePainter.drawPath(path);
93 timePainter.setRenderHint(QPainter::Antialiasing, false); 95 timePainter.setRenderHint(QPainter::Antialiasing, false);
94 96
95 path = QPainterPath(); 97 path = QPainterPath();
110 timePainter.setRenderHint(QPainter::Antialiasing, true); 112 timePainter.setRenderHint(QPainter::Antialiasing, true);
111 path.addRect(0, 0, w, h + 1); 113 path.addRect(0, 0, w, h + 1);
112 timePainter.drawPath(path); 114 timePainter.drawPath(path);
113 115
114 QFont font; 116 QFont font;
115 font.setPixelSize(10); 117 font.setPixelSize(int(10 * scaleRatio));
116 font.setItalic(true); 118 font.setItalic(true);
117 timePainter.setFont(font); 119 timePainter.setFont(font);
118 QString label = tr("V / time"); 120 QString label = tr("V / time");
119 timePainter.drawText(w - timePainter.fontMetrics().width(label) - 4, 121 timePainter.drawText(w - timePainter.fontMetrics().width(label) - 4,
120 timePainter.fontMetrics().ascent() + 1, label); 122 timePainter.fontMetrics().ascent() + 1, label);
121 123
122 m_windowTimeExampleLabel->setPixmap(timeLabel); 124 m_windowTimeExampleLabel->setPixmap(timeLabel);
123 125
124 int fw = 100; 126 QPixmap freqLabel(w, h + 1);
125
126 QPixmap freqLabel(fw, h + 1);
127 freqLabel.fill(Qt::white); 127 freqLabel.fill(Qt::white);
128 QPainter freqPainter(&freqLabel); 128 QPainter freqPainter(&freqLabel);
129 path = QPainterPath(); 129 path = QPainterPath();
130 130
131 int fftsize = 512; 131 int fftsize = 512;
132 132
133 float *input = (float *)fftf_malloc(fftsize * sizeof(float)); 133 breakfastquay::FFT fft(fftsize);
134 fftf_complex *output = 134
135 (fftf_complex *)fftf_malloc(fftsize * sizeof(fftf_complex)); 135 vector<float> input(fftsize);
136 fftf_plan plan = fftf_plan_dft_r2c_1d(fftsize, input, output, 136 vector<complex<float>> output(fftsize/2 + 1);
137 FFTW_ESTIMATE); 137
138 for (int i = 0; i < fftsize; ++i) input[i] = 0.f; 138 for (int i = 0; i < fftsize; ++i) input[i] = 0.f;
139 for (int i = 0; i < step * 2; ++i) { 139 for (int i = 0; i < step * 2; ++i) {
140 input[fftsize/2 - step + i] = windower.getValue(i); 140 input[fftsize/2 - step + i] = windower.getValue(i);
141 } 141 }
142 142
143 fftf_execute(plan); 143 fft.forwardInterleaved(input.data(), reinterpret_cast<float *>(output.data()));
144 fftf_destroy_plan(plan);
145 144
146 float maxdb = 0.f; 145 float maxdb = 0.f;
147 float mindb = 0.f; 146 float mindb = 0.f;
148 bool first = true; 147 bool first = true;
149 for (int i = 0; i < fftsize/2; ++i) { 148 for (int i = 0; i < fftsize/2; ++i) {
150 float power = output[i][0] * output[i][0] + output[i][1] * output[i][1]; 149 float power =
150 output[i].real() * output[i].real() +
151 output[i].imag() * output[i].imag();
151 float db = mindb; 152 float db = mindb;
152 if (power > 0) { 153 if (power > 0) {
153 db = 20.f * log10f(power); 154 db = 20.f * log10f(power);
154 if (first || db > maxdb) maxdb = db; 155 if (first || db > maxdb) maxdb = db;
155 if (first || db < mindb) mindb = db; 156 if (first || db < mindb) mindb = db;
166 float maxval = maxdb + -mindb; 167 float maxval = maxdb + -mindb;
167 168
168 // float ly = h - ((-80.f + -mindb) / maxval) * peak + 1; 169 // float ly = h - ((-80.f + -mindb) / maxval) * peak + 1;
169 170
170 path.moveTo(0, float(h) - peak + 1); 171 path.moveTo(0, float(h) - peak + 1);
171 path.lineTo(fw, float(h) - peak + 1); 172 path.lineTo(w, float(h) - peak + 1);
172 173
173 freqPainter.setPen(Qt::gray); 174 freqPainter.setPen(Qt::gray);
174 freqPainter.setRenderHint(QPainter::Antialiasing, true); 175 freqPainter.setRenderHint(QPainter::Antialiasing, true);
175 freqPainter.drawPath(path); 176 freqPainter.drawPath(path);
176 177
178 freqPainter.setPen(Qt::black); 179 freqPainter.setPen(Qt::black);
179 180
180 // cerr << "maxdb = " << maxdb << ", mindb = " << mindb << ", maxval = " <<maxval << endl; 181 // cerr << "maxdb = " << maxdb << ", mindb = " << mindb << ", maxval = " <<maxval << endl;
181 182
182 for (int i = 0; i < fftsize/2; ++i) { 183 for (int i = 0; i < fftsize/2; ++i) {
183 float power = output[i][0] * output[i][0] + output[i][1] * output[i][1]; 184 float power =
185 output[i].real() * output[i].real() +
186 output[i].imag() * output[i].imag();
184 float db = 20.f * log10f(power); 187 float db = 20.f * log10f(power);
185 float val = db + -mindb; 188 float val = db + -mindb;
186 if (val < 0) val = 0; 189 if (val < 0) val = 0;
187 float norm = val / maxval; 190 float norm = val / maxval;
188 float x = (float(fw) / float(fftsize/2)) * float(i); 191 float x = (float(w) / float(fftsize/2)) * float(i);
189 float y = float(h) - norm * peak + 1; 192 float y = float(h) - norm * peak + 1;
190 if (i == 0) path.moveTo(x, y); 193 if (i == 0) path.moveTo(x, y);
191 else path.lineTo(x, y); 194 else path.lineTo(x, y);
192 } 195 }
193 196
194 freqPainter.setRenderHint(QPainter::Antialiasing, true); 197 freqPainter.setRenderHint(QPainter::Antialiasing, true);
195 path.addRect(0, 0, fw, h + 1); 198 path.addRect(0, 0, w, h + 1);
196 freqPainter.drawPath(path); 199 freqPainter.drawPath(path);
197
198 fftf_free(input);
199 fftf_free(output);
200 200
201 freqPainter.setFont(font); 201 freqPainter.setFont(font);
202 label = tr("dB / freq"); 202 label = tr("dB / freq");
203 freqPainter.drawText(fw - freqPainter.fontMetrics().width(label) - 4, 203 freqPainter.drawText(w - freqPainter.fontMetrics().width(label) - 4,
204 freqPainter.fontMetrics().ascent() + 1, label); 204 freqPainter.fontMetrics().ascent() + 1, label);
205 205
206 m_windowFreqExampleLabel->setPixmap(freqLabel); 206 m_windowFreqExampleLabel->setPixmap(freqLabel);
207 } 207 }
208 208