blob: e1623f75841b1e3f2da7341556172e8f6be88fa3 [file] [log] [blame]
Andy Hung546734b2014-04-01 18:31:42 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "audioflinger_resampler_tests"
19
Mark Salyzyn60d02072016-09-29 08:48:48 -070020#include <errno.h>
21#include <fcntl.h>
22#include <math.h>
Andy Hung546734b2014-04-01 18:31:42 -070023#include <stdio.h>
24#include <stdlib.h>
Andy Hung546734b2014-04-01 18:31:42 -070025#include <string.h>
26#include <sys/mman.h>
27#include <sys/stat.h>
Andy Hung546734b2014-04-01 18:31:42 -070028#include <time.h>
Mark Salyzyn60d02072016-09-29 08:48:48 -070029#include <unistd.h>
30
Andy Hung42b01112014-07-20 14:04:19 -070031#include <iostream>
Andy Hung6bd378f2017-10-24 19:23:52 -070032#include <memory>
Mark Salyzyn60d02072016-09-29 08:48:48 -070033#include <utility>
34#include <vector>
35
Andy Hung546734b2014-04-01 18:31:42 -070036#include <gtest/gtest.h>
Mark Salyzyne74bbf12017-01-12 15:10:27 -080037#include <log/log.h>
Andy Hung546734b2014-04-01 18:31:42 -070038#include <media/AudioBufferProvider.h>
Mark Salyzyn60d02072016-09-29 08:48:48 -070039
Andy Hung068561c2017-01-03 17:09:32 -080040#include <media/AudioResampler.h>
Andy Hung6bd378f2017-10-24 19:23:52 -070041#include "../AudioResamplerDyn.h"
42#include "../AudioResamplerFirGen.h"
Andy Hungc0e5ec82014-06-17 14:33:39 -070043#include "test_utils.h"
Andy Hung546734b2014-04-01 18:31:42 -070044
Andy Hungadc5d9c2017-01-05 17:26:08 -080045template <typename T>
46static void printData(T *data, size_t size) {
47 const size_t stride = 8;
48 for (size_t i = 0; i < size; ) {
49 for (size_t j = 0; j < stride && i < size; ++j) {
50 std::cout << data[i++] << ' '; // extra space before newline
51 }
52 std::cout << '\n'; // or endl
53 }
54}
55
Andy Hung075abae2014-04-09 19:36:43 -070056void resample(int channels, void *output,
57 size_t outputFrames, const std::vector<size_t> &outputIncr,
Andy Hung546734b2014-04-01 18:31:42 -070058 android::AudioBufferProvider *provider, android::AudioResampler *resampler)
59{
60 for (size_t i = 0, j = 0; i < outputFrames; ) {
61 size_t thisFrames = outputIncr[j++];
62 if (j >= outputIncr.size()) {
63 j = 0;
64 }
65 if (thisFrames == 0 || thisFrames > outputFrames - i) {
66 thisFrames = outputFrames - i;
67 }
Andy Hung6b3b7e32015-03-29 00:49:22 -070068 size_t framesResampled = resampler->resample(
69 (int32_t*) output + channels*i, thisFrames, provider);
70 // we should have enough buffer space, so there is no short count.
71 ASSERT_EQ(thisFrames, framesResampled);
Andy Hung546734b2014-04-01 18:31:42 -070072 i += thisFrames;
73 }
74}
75
76void buffercmp(const void *reference, const void *test,
77 size_t outputFrameSize, size_t outputFrames)
78{
79 for (size_t i = 0; i < outputFrames; ++i) {
80 int check = memcmp((const char*)reference + i * outputFrameSize,
81 (const char*)test + i * outputFrameSize, outputFrameSize);
82 if (check) {
Glenn Kastena4daf0b2014-07-28 16:34:45 -070083 ALOGE("Failure at frame %zu", i);
Andy Hung546734b2014-04-01 18:31:42 -070084 ASSERT_EQ(check, 0); /* fails */
85 }
86 }
87}
88
Andy Hung075abae2014-04-09 19:36:43 -070089void testBufferIncrement(size_t channels, bool useFloat,
90 unsigned inputFreq, unsigned outputFreq,
Andy Hung546734b2014-04-01 18:31:42 -070091 enum android::AudioResampler::src_quality quality)
92{
Andy Hung3348e362014-07-07 10:21:44 -070093 const audio_format_t format = useFloat ? AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT;
Andy Hung546734b2014-04-01 18:31:42 -070094 // create the provider
Andy Hungc0e5ec82014-06-17 14:33:39 -070095 std::vector<int> inputIncr;
96 SignalProvider provider;
Andy Hung075abae2014-04-09 19:36:43 -070097 if (useFloat) {
98 provider.setChirp<float>(channels,
99 0., outputFreq/2., outputFreq, outputFreq/2000.);
100 } else {
101 provider.setChirp<int16_t>(channels,
102 0., outputFreq/2., outputFreq, outputFreq/2000.);
103 }
Andy Hungc0e5ec82014-06-17 14:33:39 -0700104 provider.setIncr(inputIncr);
Andy Hung546734b2014-04-01 18:31:42 -0700105
106 // calculate the output size
107 size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq;
Andy Hungadc5d9c2017-01-05 17:26:08 -0800108 size_t outputFrameSize = (channels == 1 ? 2 : channels) * (useFloat ? sizeof(float) : sizeof(int32_t));
Andy Hung546734b2014-04-01 18:31:42 -0700109 size_t outputSize = outputFrameSize * outputFrames;
110 outputSize &= ~7;
111
112 // create the resampler
Andy Hung546734b2014-04-01 18:31:42 -0700113 android::AudioResampler* resampler;
114
Andy Hung3348e362014-07-07 10:21:44 -0700115 resampler = android::AudioResampler::create(format, channels, outputFreq, quality);
Andy Hung546734b2014-04-01 18:31:42 -0700116 resampler->setSampleRate(inputFreq);
Andy Hung5e58b0a2014-06-23 19:07:29 -0700117 resampler->setVolume(android::AudioResampler::UNITY_GAIN_FLOAT,
118 android::AudioResampler::UNITY_GAIN_FLOAT);
Andy Hung546734b2014-04-01 18:31:42 -0700119
120 // set up the reference run
121 std::vector<size_t> refIncr;
122 refIncr.push_back(outputFrames);
Andy Hungccbba6e2017-01-05 16:43:35 -0800123 void* reference = calloc(outputFrames, outputFrameSize);
Andy Hung075abae2014-04-09 19:36:43 -0700124 resample(channels, reference, outputFrames, refIncr, &provider, resampler);
Andy Hung546734b2014-04-01 18:31:42 -0700125
126 provider.reset();
127
128#if 0
129 /* this test will fail - API interface issue: reset() does not clear internal buffers */
130 resampler->reset();
131#else
132 delete resampler;
Andy Hung3348e362014-07-07 10:21:44 -0700133 resampler = android::AudioResampler::create(format, channels, outputFreq, quality);
Andy Hung546734b2014-04-01 18:31:42 -0700134 resampler->setSampleRate(inputFreq);
Andy Hung5e58b0a2014-06-23 19:07:29 -0700135 resampler->setVolume(android::AudioResampler::UNITY_GAIN_FLOAT,
136 android::AudioResampler::UNITY_GAIN_FLOAT);
Andy Hung546734b2014-04-01 18:31:42 -0700137#endif
138
139 // set up the test run
140 std::vector<size_t> outIncr;
141 outIncr.push_back(1);
142 outIncr.push_back(2);
143 outIncr.push_back(3);
Andy Hungccbba6e2017-01-05 16:43:35 -0800144 void* test = calloc(outputFrames, outputFrameSize);
Andy Hung075abae2014-04-09 19:36:43 -0700145 inputIncr.push_back(1);
146 inputIncr.push_back(3);
147 provider.setIncr(inputIncr);
148 resample(channels, test, outputFrames, outIncr, &provider, resampler);
Andy Hung546734b2014-04-01 18:31:42 -0700149
150 // check
151 buffercmp(reference, test, outputFrameSize, outputFrames);
152
153 free(reference);
154 free(test);
155 delete resampler;
156}
157
158template <typename T>
159inline double sqr(T v)
160{
161 double dv = static_cast<double>(v);
162 return dv * dv;
163}
164
165template <typename T>
166double signalEnergy(T *start, T *end, unsigned stride)
167{
168 double accum = 0;
169
170 for (T *p = start; p < end; p += stride) {
171 accum += sqr(*p);
172 }
173 unsigned count = (end - start + stride - 1) / stride;
174 return accum / count;
175}
176
Andy Hung42b01112014-07-20 14:04:19 -0700177// TI = resampler input type, int16_t or float
178// TO = resampler output type, int32_t or float
179template <typename TI, typename TO>
Andy Hung546734b2014-04-01 18:31:42 -0700180void testStopbandDownconversion(size_t channels,
181 unsigned inputFreq, unsigned outputFreq,
182 unsigned passband, unsigned stopband,
183 enum android::AudioResampler::src_quality quality)
184{
185 // create the provider
Andy Hungc0e5ec82014-06-17 14:33:39 -0700186 std::vector<int> inputIncr;
187 SignalProvider provider;
Andy Hung42b01112014-07-20 14:04:19 -0700188 provider.setChirp<TI>(channels,
Andy Hungc0e5ec82014-06-17 14:33:39 -0700189 0., inputFreq/2., inputFreq, inputFreq/2000.);
190 provider.setIncr(inputIncr);
Andy Hung546734b2014-04-01 18:31:42 -0700191
192 // calculate the output size
193 size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq;
Andy Hungadc5d9c2017-01-05 17:26:08 -0800194 size_t outputFrameSize = (channels == 1 ? 2 : channels) * sizeof(TO);
Andy Hung546734b2014-04-01 18:31:42 -0700195 size_t outputSize = outputFrameSize * outputFrames;
196 outputSize &= ~7;
197
198 // create the resampler
Andy Hung546734b2014-04-01 18:31:42 -0700199 android::AudioResampler* resampler;
200
Andy Hung42b01112014-07-20 14:04:19 -0700201 resampler = android::AudioResampler::create(
202 is_same<TI, int16_t>::value ? AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_FLOAT,
Andy Hung3348e362014-07-07 10:21:44 -0700203 channels, outputFreq, quality);
Andy Hung546734b2014-04-01 18:31:42 -0700204 resampler->setSampleRate(inputFreq);
Andy Hung5e58b0a2014-06-23 19:07:29 -0700205 resampler->setVolume(android::AudioResampler::UNITY_GAIN_FLOAT,
206 android::AudioResampler::UNITY_GAIN_FLOAT);
Andy Hung546734b2014-04-01 18:31:42 -0700207
208 // set up the reference run
209 std::vector<size_t> refIncr;
210 refIncr.push_back(outputFrames);
Andy Hungccbba6e2017-01-05 16:43:35 -0800211 void* reference = calloc(outputFrames, outputFrameSize);
Andy Hung075abae2014-04-09 19:36:43 -0700212 resample(channels, reference, outputFrames, refIncr, &provider, resampler);
Andy Hung546734b2014-04-01 18:31:42 -0700213
Andy Hung42b01112014-07-20 14:04:19 -0700214 TO *out = reinterpret_cast<TO *>(reference);
Andy Hung546734b2014-04-01 18:31:42 -0700215
216 // check signal energy in passband
217 const unsigned passbandFrame = passband * outputFreq / 1000.;
218 const unsigned stopbandFrame = stopband * outputFreq / 1000.;
219
220 // check each channel separately
Andy Hungadc5d9c2017-01-05 17:26:08 -0800221 if (channels == 1) channels = 2; // workaround (mono duplicates output channel)
222
Andy Hung546734b2014-04-01 18:31:42 -0700223 for (size_t i = 0; i < channels; ++i) {
224 double passbandEnergy = signalEnergy(out, out + passbandFrame * channels, channels);
225 double stopbandEnergy = signalEnergy(out + stopbandFrame * channels,
226 out + outputFrames * channels, channels);
227 double dbAtten = -10. * log10(stopbandEnergy / passbandEnergy);
228 ASSERT_GT(dbAtten, 60.);
229
230#if 0
231 // internal verification
232 printf("if:%d of:%d pbf:%d sbf:%d sbe: %f pbe: %f db: %.2f\n",
233 provider.getNumFrames(), outputFrames,
234 passbandFrame, stopbandFrame, stopbandEnergy, passbandEnergy, dbAtten);
235 for (size_t i = 0; i < 10; ++i) {
Andy Hung42b01112014-07-20 14:04:19 -0700236 std::cout << out[i+passbandFrame*channels] << std::endl;
Andy Hung546734b2014-04-01 18:31:42 -0700237 }
238 for (size_t i = 0; i < 10; ++i) {
Andy Hung42b01112014-07-20 14:04:19 -0700239 std::cout << out[i+stopbandFrame*channels] << std::endl;
Andy Hung546734b2014-04-01 18:31:42 -0700240 }
241#endif
242 }
243
244 free(reference);
245 delete resampler;
246}
247
Andy Hung6bd378f2017-10-24 19:23:52 -0700248void testFilterResponse(
249 size_t channels, unsigned inputFreq, unsigned outputFreq)
250{
251 // create resampler
252 using ResamplerType = android::AudioResamplerDyn<float, float, float>;
253 std::unique_ptr<ResamplerType> rdyn(
254 static_cast<ResamplerType *>(
255 android::AudioResampler::create(
256 AUDIO_FORMAT_PCM_FLOAT,
257 channels,
258 outputFreq,
259 android::AudioResampler::DYN_HIGH_QUALITY)));
260 rdyn->setSampleRate(inputFreq);
261
262 // get design parameters
263 const int phases = rdyn->getPhases();
264 const int halfLength = rdyn->getHalfLength();
265 const float *coefs = rdyn->getFilterCoefs();
266 const double fcr = rdyn->getNormalizedCutoffFrequency();
267 const double tbw = rdyn->getNormalizedTransitionBandwidth();
268 const double attenuation = rdyn->getFilterAttenuation();
269 const double stopbandDb = rdyn->getStopbandAttenuationDb();
270 const double passbandDb = rdyn->getPassbandRippleDb();
271 const double fp = fcr - tbw / 2;
272 const double fs = fcr + tbw / 2;
273
274 printf("inputFreq:%d outputFreq:%d design"
275 " phases:%d halfLength:%d"
276 " fcr:%lf fp:%lf fs:%lf tbw:%lf"
277 " attenuation:%lf stopRipple:%.lf passRipple:%lf"
278 "\n",
279 inputFreq, outputFreq,
280 phases, halfLength,
281 fcr, fp, fs, tbw,
282 attenuation, stopbandDb, passbandDb);
283
284 // verify design parameters
285 constexpr int32_t passSteps = 1000;
286 double passMin, passMax, passRipple, stopMax, stopRipple;
287 android::testFir(coefs, phases, halfLength, fp / phases, fs / phases,
288 passSteps, phases * passSteps /* stopSteps */,
289 passMin, passMax, passRipple,
290 stopMax, stopRipple);
291 printf("inputFreq:%d outputFreq:%d verify"
292 " passMin:%lf passMax:%lf passRipple:%lf stopMax:%lf stopRipple:%lf"
293 "\n",
294 inputFreq, outputFreq,
295 passMin, passMax, passRipple, stopMax, stopRipple);
296
297 ASSERT_GT(stopRipple, 60.); // enough stopband attenuation
298 ASSERT_LT(passRipple, 0.2); // small passband ripple
299 ASSERT_GT(passMin, 0.99); // we do not attenuate the signal (ideally 1.)
300}
301
Andy Hung546734b2014-04-01 18:31:42 -0700302/* Buffer increment test
303 *
304 * We compare a reference output, where we consume and process the entire
305 * buffer at a time, and a test output, where we provide small chunks of input
306 * data and process small chunks of output (which may not be equivalent in size).
307 *
308 * Two subtests - fixed phase (3:2 down) and interpolated phase (147:320 up)
309 */
310TEST(audioflinger_resampler, bufferincrement_fixedphase) {
311 // all of these work
312 static const enum android::AudioResampler::src_quality kQualityArray[] = {
313 android::AudioResampler::LOW_QUALITY,
314 android::AudioResampler::MED_QUALITY,
315 android::AudioResampler::HIGH_QUALITY,
316 android::AudioResampler::VERY_HIGH_QUALITY,
317 android::AudioResampler::DYN_LOW_QUALITY,
318 android::AudioResampler::DYN_MED_QUALITY,
319 android::AudioResampler::DYN_HIGH_QUALITY,
320 };
321
322 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
Andy Hung075abae2014-04-09 19:36:43 -0700323 testBufferIncrement(2, false, 48000, 32000, kQualityArray[i]);
Andy Hung546734b2014-04-01 18:31:42 -0700324 }
325}
326
327TEST(audioflinger_resampler, bufferincrement_interpolatedphase) {
328 // all of these work except low quality
329 static const enum android::AudioResampler::src_quality kQualityArray[] = {
330// android::AudioResampler::LOW_QUALITY,
331 android::AudioResampler::MED_QUALITY,
332 android::AudioResampler::HIGH_QUALITY,
333 android::AudioResampler::VERY_HIGH_QUALITY,
334 android::AudioResampler::DYN_LOW_QUALITY,
335 android::AudioResampler::DYN_MED_QUALITY,
336 android::AudioResampler::DYN_HIGH_QUALITY,
337 };
338
339 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
Andy Hung075abae2014-04-09 19:36:43 -0700340 testBufferIncrement(2, false, 22050, 48000, kQualityArray[i]);
341 }
342}
343
344TEST(audioflinger_resampler, bufferincrement_fixedphase_multi) {
345 // only dynamic quality
346 static const enum android::AudioResampler::src_quality kQualityArray[] = {
347 android::AudioResampler::DYN_LOW_QUALITY,
348 android::AudioResampler::DYN_MED_QUALITY,
349 android::AudioResampler::DYN_HIGH_QUALITY,
350 };
351
352 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
353 testBufferIncrement(4, false, 48000, 32000, kQualityArray[i]);
354 }
355}
356
357TEST(audioflinger_resampler, bufferincrement_interpolatedphase_multi_float) {
358 // only dynamic quality
359 static const enum android::AudioResampler::src_quality kQualityArray[] = {
360 android::AudioResampler::DYN_LOW_QUALITY,
361 android::AudioResampler::DYN_MED_QUALITY,
362 android::AudioResampler::DYN_HIGH_QUALITY,
363 };
364
365 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
366 testBufferIncrement(8, true, 22050, 48000, kQualityArray[i]);
Andy Hung546734b2014-04-01 18:31:42 -0700367 }
368}
369
370/* Simple aliasing test
371 *
372 * This checks stopband response of the chirp signal to make sure frequencies
373 * are properly suppressed. It uses downsampling because the stopband can be
374 * clearly isolated by input frequencies exceeding the output sample rate (nyquist).
375 */
Andy Hung42b01112014-07-20 14:04:19 -0700376TEST(audioflinger_resampler, stopbandresponse_integer) {
Andy Hung546734b2014-04-01 18:31:42 -0700377 // not all of these may work (old resamplers fail on downsampling)
378 static const enum android::AudioResampler::src_quality kQualityArray[] = {
379 //android::AudioResampler::LOW_QUALITY,
380 //android::AudioResampler::MED_QUALITY,
381 //android::AudioResampler::HIGH_QUALITY,
382 //android::AudioResampler::VERY_HIGH_QUALITY,
383 android::AudioResampler::DYN_LOW_QUALITY,
384 android::AudioResampler::DYN_MED_QUALITY,
385 android::AudioResampler::DYN_HIGH_QUALITY,
386 };
387
388 // in this test we assume a maximum transition band between 12kHz and 20kHz.
389 // there must be at least 60dB relative attenuation between stopband and passband.
390 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
Andy Hung42b01112014-07-20 14:04:19 -0700391 testStopbandDownconversion<int16_t, int32_t>(
392 2, 48000, 32000, 12000, 20000, kQualityArray[i]);
Andy Hung546734b2014-04-01 18:31:42 -0700393 }
394
395 // in this test we assume a maximum transition band between 7kHz and 15kHz.
396 // there must be at least 60dB relative attenuation between stopband and passband.
397 // (the weird ratio triggers interpolative resampling)
398 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
Andy Hung42b01112014-07-20 14:04:19 -0700399 testStopbandDownconversion<int16_t, int32_t>(
400 2, 48000, 22101, 7000, 15000, kQualityArray[i]);
Andy Hung546734b2014-04-01 18:31:42 -0700401 }
402}
Andy Hung42b01112014-07-20 14:04:19 -0700403
Andy Hungadc5d9c2017-01-05 17:26:08 -0800404TEST(audioflinger_resampler, stopbandresponse_integer_mono) {
405 // not all of these may work (old resamplers fail on downsampling)
406 static const enum android::AudioResampler::src_quality kQualityArray[] = {
407 //android::AudioResampler::LOW_QUALITY,
408 //android::AudioResampler::MED_QUALITY,
409 //android::AudioResampler::HIGH_QUALITY,
410 //android::AudioResampler::VERY_HIGH_QUALITY,
411 android::AudioResampler::DYN_LOW_QUALITY,
412 android::AudioResampler::DYN_MED_QUALITY,
413 android::AudioResampler::DYN_HIGH_QUALITY,
414 };
415
416 // in this test we assume a maximum transition band between 12kHz and 20kHz.
417 // there must be at least 60dB relative attenuation between stopband and passband.
418 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
419 testStopbandDownconversion<int16_t, int32_t>(
420 1, 48000, 32000, 12000, 20000, kQualityArray[i]);
421 }
422
423 // in this test we assume a maximum transition band between 7kHz and 15kHz.
424 // there must be at least 60dB relative attenuation between stopband and passband.
425 // (the weird ratio triggers interpolative resampling)
426 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
427 testStopbandDownconversion<int16_t, int32_t>(
428 1, 48000, 22101, 7000, 15000, kQualityArray[i]);
429 }
430}
431
Andy Hung42b01112014-07-20 14:04:19 -0700432TEST(audioflinger_resampler, stopbandresponse_integer_multichannel) {
433 // not all of these may work (old resamplers fail on downsampling)
434 static const enum android::AudioResampler::src_quality kQualityArray[] = {
435 //android::AudioResampler::LOW_QUALITY,
436 //android::AudioResampler::MED_QUALITY,
437 //android::AudioResampler::HIGH_QUALITY,
438 //android::AudioResampler::VERY_HIGH_QUALITY,
439 android::AudioResampler::DYN_LOW_QUALITY,
440 android::AudioResampler::DYN_MED_QUALITY,
441 android::AudioResampler::DYN_HIGH_QUALITY,
442 };
443
444 // in this test we assume a maximum transition band between 12kHz and 20kHz.
445 // there must be at least 60dB relative attenuation between stopband and passband.
446 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
447 testStopbandDownconversion<int16_t, int32_t>(
448 8, 48000, 32000, 12000, 20000, kQualityArray[i]);
449 }
450
451 // in this test we assume a maximum transition band between 7kHz and 15kHz.
452 // there must be at least 60dB relative attenuation between stopband and passband.
453 // (the weird ratio triggers interpolative resampling)
454 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
455 testStopbandDownconversion<int16_t, int32_t>(
456 8, 48000, 22101, 7000, 15000, kQualityArray[i]);
457 }
458}
459
460TEST(audioflinger_resampler, stopbandresponse_float) {
461 // not all of these may work (old resamplers fail on downsampling)
462 static const enum android::AudioResampler::src_quality kQualityArray[] = {
463 //android::AudioResampler::LOW_QUALITY,
464 //android::AudioResampler::MED_QUALITY,
465 //android::AudioResampler::HIGH_QUALITY,
466 //android::AudioResampler::VERY_HIGH_QUALITY,
467 android::AudioResampler::DYN_LOW_QUALITY,
468 android::AudioResampler::DYN_MED_QUALITY,
469 android::AudioResampler::DYN_HIGH_QUALITY,
470 };
471
472 // in this test we assume a maximum transition band between 12kHz and 20kHz.
473 // there must be at least 60dB relative attenuation between stopband and passband.
474 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
475 testStopbandDownconversion<float, float>(
476 2, 48000, 32000, 12000, 20000, kQualityArray[i]);
477 }
478
479 // in this test we assume a maximum transition band between 7kHz and 15kHz.
480 // there must be at least 60dB relative attenuation between stopband and passband.
481 // (the weird ratio triggers interpolative resampling)
482 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
483 testStopbandDownconversion<float, float>(
484 2, 48000, 22101, 7000, 15000, kQualityArray[i]);
485 }
486}
487
Andy Hungadc5d9c2017-01-05 17:26:08 -0800488TEST(audioflinger_resampler, stopbandresponse_float_mono) {
489 // not all of these may work (old resamplers fail on downsampling)
490 static const enum android::AudioResampler::src_quality kQualityArray[] = {
491 //android::AudioResampler::LOW_QUALITY,
492 //android::AudioResampler::MED_QUALITY,
493 //android::AudioResampler::HIGH_QUALITY,
494 //android::AudioResampler::VERY_HIGH_QUALITY,
495 android::AudioResampler::DYN_LOW_QUALITY,
496 android::AudioResampler::DYN_MED_QUALITY,
497 android::AudioResampler::DYN_HIGH_QUALITY,
498 };
499
500 // in this test we assume a maximum transition band between 12kHz and 20kHz.
501 // there must be at least 60dB relative attenuation between stopband and passband.
502 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
503 testStopbandDownconversion<float, float>(
504 1, 48000, 32000, 12000, 20000, kQualityArray[i]);
505 }
506
507 // in this test we assume a maximum transition band between 7kHz and 15kHz.
508 // there must be at least 60dB relative attenuation between stopband and passband.
509 // (the weird ratio triggers interpolative resampling)
510 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
511 testStopbandDownconversion<float, float>(
512 1, 48000, 22101, 7000, 15000, kQualityArray[i]);
513 }
514}
515
Andy Hung42b01112014-07-20 14:04:19 -0700516TEST(audioflinger_resampler, stopbandresponse_float_multichannel) {
517 // not all of these may work (old resamplers fail on downsampling)
518 static const enum android::AudioResampler::src_quality kQualityArray[] = {
519 //android::AudioResampler::LOW_QUALITY,
520 //android::AudioResampler::MED_QUALITY,
521 //android::AudioResampler::HIGH_QUALITY,
522 //android::AudioResampler::VERY_HIGH_QUALITY,
523 android::AudioResampler::DYN_LOW_QUALITY,
524 android::AudioResampler::DYN_MED_QUALITY,
525 android::AudioResampler::DYN_HIGH_QUALITY,
526 };
527
528 // in this test we assume a maximum transition band between 12kHz and 20kHz.
529 // there must be at least 60dB relative attenuation between stopband and passband.
530 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
531 testStopbandDownconversion<float, float>(
532 8, 48000, 32000, 12000, 20000, kQualityArray[i]);
533 }
534
535 // in this test we assume a maximum transition band between 7kHz and 15kHz.
536 // there must be at least 60dB relative attenuation between stopband and passband.
537 // (the weird ratio triggers interpolative resampling)
538 for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
539 testStopbandDownconversion<float, float>(
540 8, 48000, 22101, 7000, 15000, kQualityArray[i]);
541 }
542}
543
Andy Hung6bd378f2017-10-24 19:23:52 -0700544TEST(audioflinger_resampler, filterresponse) {
545 std::vector<int> inSampleRates{
546 8000,
547 11025,
548 12000,
549 16000,
550 22050,
551 24000,
552 32000,
553 44100,
554 48000,
555 88200,
556 96000,
557 176400,
558 192000,
559 };
560 std::vector<int> outSampleRates{
561 48000,
562 96000,
563 };
564
565 for (int outSampleRate : outSampleRates) {
566 for (int inSampleRate : inSampleRates) {
567 testFilterResponse(2 /* channels */, inSampleRate, outSampleRate);
568 }
569 }
570}