Mercurial > hg > svcore
comparison data/model/test/TestWaveformOversampler.h @ 1537:c5092ca1c6e5 zoom
Tests for waveform oversampling
author | Chris Cannam |
---|---|
date | Wed, 26 Sep 2018 14:44:38 +0100 |
parents | |
children | fa67fbbff8fc |
comparison
equal
deleted
inserted
replaced
1536:eb10ed56d5a4 | 1537:c5092ca1c6e5 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 | |
8 This program is free software; you can redistribute it and/or | |
9 modify it under the terms of the GNU General Public License as | |
10 published by the Free Software Foundation; either version 2 of the | |
11 License, or (at your option) any later version. See the file | |
12 COPYING included with this distribution for more information. | |
13 */ | |
14 | |
15 #ifndef TEST_WAVEFORM_OVERSAMPLER_H | |
16 #define TEST_WAVEFORM_OVERSAMPLER_H | |
17 | |
18 #include "../WaveformOversampler.h" | |
19 #include "../WritableWaveFileModel.h" | |
20 | |
21 #include "../../../base/BaseTypes.h" | |
22 | |
23 #include <QObject> | |
24 #include <QtTest> | |
25 | |
26 class TestWaveformOversampler : public QObject | |
27 { | |
28 Q_OBJECT | |
29 | |
30 public: | |
31 TestWaveformOversampler() { | |
32 m_source = floatvec_t(5000, 0.f); | |
33 m_source[0] = 1.f; | |
34 m_source[2500] = 0.5f; | |
35 m_source[2501] = -0.5f; | |
36 m_source[4999] = -1.f; | |
37 for (int i = 4000; i < 4900; ++i) { | |
38 m_source[i] = sin(double(i - 1000) * M_PI / 50.0); | |
39 } | |
40 m_sourceModel = new WritableWaveFileModel(8000, 1); | |
41 const float *d = m_source.data(); | |
42 QVERIFY(m_sourceModel->addSamples(&d, m_source.size())); | |
43 m_sourceModel->writeComplete(); | |
44 } | |
45 | |
46 ~TestWaveformOversampler() { | |
47 delete m_sourceModel; | |
48 } | |
49 | |
50 private: | |
51 floatvec_t m_source; | |
52 WritableWaveFileModel *m_sourceModel; | |
53 | |
54 void compareStrided(floatvec_t obtained, floatvec_t expected, int stride) { | |
55 QCOMPARE(obtained.size(), expected.size() * stride); | |
56 float threshold = 1e-10f; | |
57 for (int i = 0; in_range_for(expected, i); ++i) { | |
58 if (fabsf(obtained[i * stride] - expected[i]) > threshold) { | |
59 cerr << "At position " << i * stride << ": " | |
60 << obtained[i * stride] << " != " << expected[i] | |
61 << endl; | |
62 QCOMPARE(obtained, expected); | |
63 } | |
64 } | |
65 } | |
66 | |
67 void compareVecs(floatvec_t obtained, floatvec_t expected) { | |
68 compareStrided(obtained, expected, 1); | |
69 } | |
70 | |
71 floatvec_t get(sv_frame_t sourceStartFrame, | |
72 sv_frame_t sourceFrameCount, | |
73 sv_frame_t oversampleBy) { | |
74 return WaveformOversampler::getOversampledData | |
75 (m_sourceModel, 0, | |
76 sourceStartFrame, sourceFrameCount, oversampleBy); | |
77 } | |
78 | |
79 void testVerbatim(sv_frame_t sourceStartFrame, | |
80 sv_frame_t sourceFrameCount, | |
81 int oversampleBy, | |
82 floatvec_t expected) { | |
83 floatvec_t output = | |
84 get(sourceStartFrame, sourceFrameCount, oversampleBy); | |
85 compareVecs(output, expected); | |
86 } | |
87 | |
88 void testStrided(sv_frame_t sourceStartFrame, | |
89 sv_frame_t sourceFrameCount, | |
90 int oversampleBy, | |
91 floatvec_t expected) { | |
92 // check only the values that are expected to be precisely the | |
93 // original samples | |
94 floatvec_t output = | |
95 get(sourceStartFrame, sourceFrameCount, oversampleBy); | |
96 compareStrided(output, expected, oversampleBy); | |
97 } | |
98 | |
99 floatvec_t sourceSubset(sv_frame_t start, sv_frame_t length) { | |
100 return floatvec_t(m_source.begin() + start, | |
101 m_source.begin() + start + length); | |
102 } | |
103 | |
104 private slots: | |
105 void testWholeVerbatim() { | |
106 testVerbatim(0, 5000, 1, m_source); | |
107 } | |
108 | |
109 void testSubsetsVerbatim() { | |
110 testVerbatim(0, 500, 1, sourceSubset(0, 500)); | |
111 testVerbatim(4500, 500, 1, sourceSubset(4500, 500)); | |
112 testVerbatim(2000, 1000, 1, sourceSubset(2000, 1000)); | |
113 } | |
114 | |
115 void testOverlapsVerbatim() { | |
116 // overlapping the start -> result should be zero-padded to | |
117 // preserve start frame | |
118 floatvec_t expected = sourceSubset(0, 400); | |
119 expected.insert(expected.begin(), 100, 0.f); | |
120 testVerbatim(-100, 500, 1, expected); | |
121 | |
122 // overlapping the end -> result should be truncated to | |
123 // preserve source length | |
124 expected = sourceSubset(4600, 400); | |
125 testVerbatim(4600, 500, 1, expected); | |
126 } | |
127 | |
128 void testWhole2x() { | |
129 testStrided(0, 5000, 2, m_source); | |
130 | |
131 // check for windowed sinc values between the original samples | |
132 floatvec_t output = get(0, 5000, 2); | |
133 QVERIFY(output[1] - 0.6358 < 0.0001); | |
134 QVERIFY(output[3] + 0.2099 < 0.0001); | |
135 } | |
136 | |
137 void testWhole3x() { | |
138 testStrided(0, 5000, 3, m_source); | |
139 | |
140 // check for windowed sinc values between the original samples | |
141 floatvec_t output = get(0, 5000, 3); | |
142 QVERIFY(output[1] > 0.7); | |
143 QVERIFY(output[2] > 0.4); | |
144 QVERIFY(output[4] < -0.1); | |
145 QVERIFY(output[5] < -0.1); | |
146 } | |
147 | |
148 void testWhole4x() { | |
149 testStrided(0, 5000, 4, m_source); | |
150 | |
151 // check for windowed sinc values between the original samples | |
152 floatvec_t output = get(0, 5000, 4); | |
153 QVERIFY(output[1] - 0.9000 < 0.0001); | |
154 QVERIFY(output[2] - 0.6358 < 0.0001); | |
155 QVERIFY(output[3] - 0.2993 < 0.0001); | |
156 QVERIFY(output[5] + 0.1787 < 0.0001); | |
157 QVERIFY(output[6] + 0.2099 < 0.0001); | |
158 QVERIFY(output[7] + 0.1267 < 0.0001); | |
159 | |
160 // alternate values at 2n should equal all values at n | |
161 output = get(0, 5000, 4); | |
162 floatvec_t half = get(0, 5000, 2); | |
163 compareStrided(output, half, 2); | |
164 } | |
165 | |
166 void testWhole8x() { | |
167 testStrided(0, 5000, 8, m_source); | |
168 | |
169 // alternate values at 2n should equal all values at n | |
170 floatvec_t output = get(0, 5000, 8); | |
171 floatvec_t half = get(0, 5000, 4); | |
172 compareStrided(output, half, 2); | |
173 } | |
174 | |
175 void testWhole10x() { | |
176 testStrided(0, 5000, 10, m_source); | |
177 | |
178 // alternate values at 2n should equal all values at n | |
179 floatvec_t output = get(0, 5000, 10); | |
180 floatvec_t half = get(0, 5000, 5); | |
181 compareStrided(output, half, 2); | |
182 } | |
183 | |
184 void testWhole16x() { | |
185 testStrided(0, 5000, 16, m_source); | |
186 | |
187 // alternate values at 2n should equal all values at n | |
188 floatvec_t output = get(0, 5000, 16); | |
189 floatvec_t half = get(0, 5000, 8); | |
190 compareStrided(output, half, 2); | |
191 } | |
192 | |
193 void testSubsets4x() { | |
194 testStrided(0, 500, 4, sourceSubset(0, 500)); | |
195 testStrided(4500, 500, 4, sourceSubset(4500, 500)); | |
196 testStrided(2000, 1000, 4, sourceSubset(2000, 1000)); | |
197 } | |
198 | |
199 void testOverlaps4x() { | |
200 // overlapping the start -> result should be zero-padded to | |
201 // preserve start frame | |
202 floatvec_t expected = sourceSubset(0, 400); | |
203 expected.insert(expected.begin(), 100, 0.f); | |
204 testStrided(-100, 500, 4, expected); | |
205 | |
206 // overlapping the end -> result should be truncated to | |
207 // preserve source length | |
208 expected = sourceSubset(4600, 400); | |
209 testStrided(4600, 500, 4, expected); | |
210 } | |
211 | |
212 void testSubsets15x() { | |
213 testStrided(0, 500, 15, sourceSubset(0, 500)); | |
214 testStrided(4500, 500, 15, sourceSubset(4500, 500)); | |
215 testStrided(2000, 1000, 15, sourceSubset(2000, 1000)); | |
216 } | |
217 | |
218 void testOverlaps15x() { | |
219 // overlapping the start -> result should be zero-padded to | |
220 // preserve start frame | |
221 floatvec_t expected = sourceSubset(0, 400); | |
222 expected.insert(expected.begin(), 100, 0.f); | |
223 testStrided(-100, 500, 15, expected); | |
224 | |
225 // overlapping the end -> result should be truncated to | |
226 // preserve source length | |
227 expected = sourceSubset(4600, 400); | |
228 testStrided(4600, 500, 15, expected); | |
229 } | |
230 }; | |
231 | |
232 | |
233 #endif |