Mercurial > hg > svgui
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 |