Mercurial > hg > qm-dsp
comparison tests/TestResampler.cpp @ 172:17a7d6bb9af6
Construct a currently-failing test on exact frequency in resampler (tracking down error in CQ)
author | Chris Cannam |
---|---|
date | Sat, 10 May 2014 13:41:06 +0100 |
parents | edb86e0d850c |
children | 6a820c2a3eb2 |
comparison
equal
deleted
inserted
replaced
171:5f720340b0dd | 172:17a7d6bb9af6 |
---|---|
148 out[i] = sin(i * M_PI / 4.0); | 148 out[i] = sin(i * M_PI / 4.0); |
149 } | 149 } |
150 testResamplerOneShot(16, 8, 2000, in, 200, out, 256); | 150 testResamplerOneShot(16, 8, 2000, in, 200, out, 256); |
151 } | 151 } |
152 | 152 |
153 double | |
154 measureSinFreq(const vector<double> &v, int rate, int countCycles) | |
155 { | |
156 int n = v.size(); | |
157 int firstCrossing = -1; | |
158 int lastCrossing = -1; | |
159 int nCrossings = 0; | |
160 // count -ve -> +ve transitions | |
161 for (int i = 0; i + 1 < n; ++i) { | |
162 if (v[i] <= 0.0 && v[i+1] > 0.0) { | |
163 if (firstCrossing < 0) firstCrossing = i; | |
164 lastCrossing = i; | |
165 ++nCrossings; | |
166 if (nCrossings == countCycles) break; | |
167 } | |
168 } | |
169 int nCycles = nCrossings - 1; | |
170 if (nCycles <= 0) return 0.0; | |
171 cout << "lastCrossing = " << lastCrossing << ", firstCrossing = " << firstCrossing << ", dist = " << lastCrossing - firstCrossing << ", nCycles = " << nCycles << endl; | |
172 double cycle = double(lastCrossing - firstCrossing) / nCycles; | |
173 return rate / cycle; | |
174 } | |
175 | |
176 void | |
177 testSinFrequency(int freq, | |
178 int sourceRate, | |
179 int targetRate) | |
180 { | |
181 // Resampling a sinusoid and then resampling back should give us a | |
182 // sinusoid of the same frequency as we started with. Let's start | |
183 // with a few thousand cycles of it | |
184 | |
185 int nCycles = 5000; | |
186 | |
187 int duration = int(nCycles * float(sourceRate) / float(freq)); | |
188 cout << "freq = " << freq << ", sourceRate = " << sourceRate << ", targetRate = " << targetRate << ", duration = " << duration << endl; | |
189 | |
190 vector<double> in(duration, 0); | |
191 for (int i = 0; i < duration; ++i) { | |
192 in[i] = sin(i * M_PI * 2.0 * freq / sourceRate); | |
193 } | |
194 | |
195 vector<double> out = Resampler::resample(sourceRate, targetRate, | |
196 in.data(), in.size()); | |
197 | |
198 vector<double> back = Resampler::resample(targetRate, sourceRate, | |
199 out.data(), out.size()); | |
200 | |
201 BOOST_CHECK_EQUAL(in.size(), back.size()); | |
202 | |
203 double inFreq = measureSinFreq(in, sourceRate, nCycles - 2); | |
204 double backFreq = measureSinFreq(back, sourceRate, nCycles - 2); | |
205 | |
206 cout << "inFreq = " << inFreq << ", backFreq = " << backFreq << endl; | |
207 | |
208 BOOST_CHECK_SMALL(inFreq - backFreq, 1e-8); | |
209 | |
210 // for (int i = 0; i < int(in.size()); ++i) { | |
211 // BOOST_CHECK_SMALL(in[i] - back[i], 1e-6); | |
212 // } | |
213 } | |
214 | |
215 BOOST_AUTO_TEST_CASE(downUp2) | |
216 { | |
217 testSinFrequency(440, 44100, 22050); | |
218 } | |
219 | |
220 BOOST_AUTO_TEST_CASE(downUp16) | |
221 { | |
222 testSinFrequency(440, 48000, 3000); | |
223 } | |
224 | |
225 BOOST_AUTO_TEST_CASE(upDown2) | |
226 { | |
227 testSinFrequency(440, 44100, 88200); | |
228 } | |
229 | |
230 BOOST_AUTO_TEST_CASE(upDown16) | |
231 { | |
232 testSinFrequency(440, 3000, 48000); | |
233 } | |
234 | |
153 vector<double> | 235 vector<double> |
154 squareWave(int rate, double freq, int n) | 236 squareWave(int rate, double freq, int n) |
155 { | 237 { |
156 //!!! todo: hoist, test | 238 //!!! todo: hoist, test |
157 vector<double> v(n, 0.0); | 239 vector<double> v(n, 0.0); |