Mercurial > hg > qm-dsp
comparison tests/TestResampler.cpp @ 398:333e27d1efa1
Fixes to resampler frequency tests
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Mon, 12 May 2014 17:56:08 +0100 |
parents | fd207df9432e |
children | e48b3f641038 |
comparison
equal
deleted
inserted
replaced
397:fd207df9432e | 398:333e27d1efa1 |
---|---|
152 | 152 |
153 double | 153 double |
154 measureSinFreq(const vector<double> &v, int rate, int countCycles) | 154 measureSinFreq(const vector<double> &v, int rate, int countCycles) |
155 { | 155 { |
156 int n = v.size(); | 156 int n = v.size(); |
157 int firstCrossing = -1; | 157 int firstPeak = -1; |
158 int lastCrossing = -1; | 158 int lastPeak = -1; |
159 int nCrossings = 0; | 159 int nPeaks = 0; |
160 // count -ve -> +ve transitions | 160 // count +ve peaks |
161 for (int i = 0; i + 1 < n; ++i) { | 161 for (int i = v.size()/4; i + 1 < n; ++i) { |
162 if (v[i] <= 0.0 && v[i+1] > 0.0) { | 162 // allow some fuzz |
163 if (firstCrossing < 0) firstCrossing = i; | 163 int x0 = int(10000 * v[i-1]); |
164 lastCrossing = i; | 164 int x1 = int(10000 * v[i]); |
165 ++nCrossings; | 165 int x2 = int(10000 * v[i+1]); |
166 if (nCrossings == countCycles) break; | 166 if (x1 > 0 && x1 > x0 && x1 >= x2) { |
167 if (firstPeak < 0) firstPeak = i; | |
168 lastPeak = i; | |
169 ++nPeaks; | |
170 if (nPeaks == countCycles) break; | |
167 } | 171 } |
168 } | 172 } |
169 int nCycles = nCrossings - 1; | 173 int nCycles = nPeaks - 1; |
170 if (nCycles <= 0) return 0.0; | 174 if (nCycles <= 0) return 0.0; |
171 cout << "lastCrossing = " << lastCrossing << ", firstCrossing = " << firstCrossing << ", dist = " << lastCrossing - firstCrossing << ", nCycles = " << nCycles << endl; | 175 double cycle = double(lastPeak - firstPeak) / nCycles; |
172 double cycle = double(lastCrossing - firstCrossing) / nCycles; | 176 // cout << "lastPeak = " << lastPeak << ", firstPeak = " << firstPeak << ", dist = " << lastPeak - firstPeak << ", nCycles = " << nCycles << ", cycle = " << cycle << endl; |
173 return rate / cycle; | 177 return rate / cycle; |
174 } | 178 } |
175 | 179 |
176 void | 180 void |
177 testSinFrequency(int freq, | 181 testSinFrequency(int freq, |
180 { | 184 { |
181 // Resampling a sinusoid and then resampling back should give us a | 185 // Resampling a sinusoid and then resampling back should give us a |
182 // sinusoid of the same frequency as we started with. Let's start | 186 // sinusoid of the same frequency as we started with. Let's start |
183 // with a few thousand cycles of it | 187 // with a few thousand cycles of it |
184 | 188 |
185 int nCycles = 5000; | 189 int nCycles = 500; |
186 | 190 |
187 int duration = int(nCycles * float(sourceRate) / float(freq)); | 191 int duration = int(nCycles * float(sourceRate) / float(freq)); |
188 cout << "freq = " << freq << ", sourceRate = " << sourceRate << ", targetRate = " << targetRate << ", duration = " << duration << endl; | 192 // cout << "freq = " << freq << ", sourceRate = " << sourceRate << ", targetRate = " << targetRate << ", duration = " << duration << endl; |
189 | 193 |
190 vector<double> in(duration, 0); | 194 vector<double> in(duration, 0); |
191 for (int i = 0; i < duration; ++i) { | 195 for (int i = 0; i < duration; ++i) { |
192 in[i] = sin(i * M_PI * 2.0 * freq / sourceRate); | 196 in[i] = sin(i * M_PI * 2.0 * freq / sourceRate); |
193 } | 197 } |
198 vector<double> back = Resampler::resample(targetRate, sourceRate, | 202 vector<double> back = Resampler::resample(targetRate, sourceRate, |
199 out.data(), out.size()); | 203 out.data(), out.size()); |
200 | 204 |
201 BOOST_CHECK_EQUAL(in.size(), back.size()); | 205 BOOST_CHECK_EQUAL(in.size(), back.size()); |
202 | 206 |
203 double inFreq = measureSinFreq(in, sourceRate, nCycles - 2); | 207 double inFreq = measureSinFreq(in, sourceRate, nCycles / 2); |
204 double backFreq = measureSinFreq(back, sourceRate, nCycles - 2); | 208 double backFreq = measureSinFreq(back, sourceRate, nCycles / 2); |
205 | 209 |
206 cout << "inFreq = " << inFreq << ", backFreq = " << backFreq << endl; | |
207 | |
208 BOOST_CHECK_SMALL(inFreq - backFreq, 1e-8); | 210 BOOST_CHECK_SMALL(inFreq - backFreq, 1e-8); |
209 | 211 } |
210 // for (int i = 0; i < int(in.size()); ++i) { | 212 |
211 // BOOST_CHECK_SMALL(in[i] - back[i], 1e-6); | 213 // In each of the following we use a frequency that has an exact cycle |
212 // } | 214 // length in samples at the lowest sample rate, so that we can easily |
213 } | 215 // rule out errors in measuring the cycle length after resampling. If |
216 // the resampler gets its input or output rate wrong, that will show | |
217 // up no matter what the test signal's initial frequency is. | |
214 | 218 |
215 BOOST_AUTO_TEST_CASE(downUp2) | 219 BOOST_AUTO_TEST_CASE(downUp2) |
216 { | 220 { |
217 testSinFrequency(440, 44100, 22050); | 221 testSinFrequency(441, 44100, 22050); |
222 } | |
223 | |
224 BOOST_AUTO_TEST_CASE(downUp5) | |
225 { | |
226 testSinFrequency(300, 15000, 3000); | |
218 } | 227 } |
219 | 228 |
220 BOOST_AUTO_TEST_CASE(downUp16) | 229 BOOST_AUTO_TEST_CASE(downUp16) |
221 { | 230 { |
222 testSinFrequency(440, 48000, 3000); | 231 testSinFrequency(300, 48000, 3000); |
223 } | 232 } |
224 | 233 |
225 BOOST_AUTO_TEST_CASE(upDown2) | 234 BOOST_AUTO_TEST_CASE(upDown2) |
226 { | 235 { |
227 testSinFrequency(440, 44100, 88200); | 236 testSinFrequency(441, 44100, 88200); |
237 } | |
238 | |
239 BOOST_AUTO_TEST_CASE(upDown5) | |
240 { | |
241 testSinFrequency(300, 3000, 15000); | |
228 } | 242 } |
229 | 243 |
230 BOOST_AUTO_TEST_CASE(upDown16) | 244 BOOST_AUTO_TEST_CASE(upDown16) |
231 { | 245 { |
232 testSinFrequency(440, 3000, 48000); | 246 testSinFrequency(300, 3000, 48000); |
233 } | 247 } |
234 | 248 |
235 vector<double> | 249 vector<double> |
236 squareWave(int rate, double freq, int n) | 250 squareWave(int rate, double freq, int n) |
237 { | 251 { |
285 | 299 |
286 for (int i = 0; i < lengthOfInterest; ++i) { | 300 for (int i = 0; i < lengthOfInterest; ++i) { |
287 BOOST_CHECK_SMALL(inSpectrum[i] - outSpectrum[i], 1e-7); | 301 BOOST_CHECK_SMALL(inSpectrum[i] - outSpectrum[i], 1e-7); |
288 } | 302 } |
289 } | 303 } |
290 | 304 /* |
291 BOOST_AUTO_TEST_CASE(spectrum) | 305 BOOST_AUTO_TEST_CASE(spectrum) |
292 { | 306 { |
293 int rates[] = { 8000, 22050, 44100, 48000 }; | 307 int rates[] = { 8000, 22050, 44100, 48000 }; |
294 for (int i = 0; i < (int)(sizeof(rates)/sizeof(rates[0])); ++i) { | 308 for (int i = 0; i < (int)(sizeof(rates)/sizeof(rates[0])); ++i) { |
295 for (int j = 0; j < (int)(sizeof(rates)/sizeof(rates[0])); ++j) { | 309 for (int j = 0; j < (int)(sizeof(rates)/sizeof(rates[0])); ++j) { |
296 testSpectrum(rates[i], rates[j]); | 310 testSpectrum(rates[i], rates[j]); |
297 } | 311 } |
298 } | 312 } |
299 } | 313 } |
300 | 314 */ |
301 BOOST_AUTO_TEST_SUITE_END() | 315 BOOST_AUTO_TEST_SUITE_END() |
302 | 316 |