1546734b3ab577d46afe863515104a062e88a109bAndy Hung/*
2546734b3ab577d46afe863515104a062e88a109bAndy Hung * Copyright (C) 2014 The Android Open Source Project
3546734b3ab577d46afe863515104a062e88a109bAndy Hung *
4546734b3ab577d46afe863515104a062e88a109bAndy Hung * Licensed under the Apache License, Version 2.0 (the "License");
5546734b3ab577d46afe863515104a062e88a109bAndy Hung * you may not use this file except in compliance with the License.
6546734b3ab577d46afe863515104a062e88a109bAndy Hung * You may obtain a copy of the License at
7546734b3ab577d46afe863515104a062e88a109bAndy Hung *
8546734b3ab577d46afe863515104a062e88a109bAndy Hung *      http://www.apache.org/licenses/LICENSE-2.0
9546734b3ab577d46afe863515104a062e88a109bAndy Hung *
10546734b3ab577d46afe863515104a062e88a109bAndy Hung * Unless required by applicable law or agreed to in writing, software
11546734b3ab577d46afe863515104a062e88a109bAndy Hung * distributed under the License is distributed on an "AS IS" BASIS,
12546734b3ab577d46afe863515104a062e88a109bAndy Hung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13546734b3ab577d46afe863515104a062e88a109bAndy Hung * See the License for the specific language governing permissions and
14546734b3ab577d46afe863515104a062e88a109bAndy Hung * limitations under the License.
15546734b3ab577d46afe863515104a062e88a109bAndy Hung */
16546734b3ab577d46afe863515104a062e88a109bAndy Hung
17546734b3ab577d46afe863515104a062e88a109bAndy Hung//#define LOG_NDEBUG 0
18546734b3ab577d46afe863515104a062e88a109bAndy Hung#define LOG_TAG "audioflinger_resampler_tests"
19546734b3ab577d46afe863515104a062e88a109bAndy Hung
20546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <unistd.h>
21546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <stdio.h>
22546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <stdlib.h>
23546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <fcntl.h>
24546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <string.h>
25546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <sys/mman.h>
26546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <sys/stat.h>
27546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <errno.h>
28546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <time.h>
29546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <math.h>
30546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <vector>
31546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <utility>
3242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung#include <iostream>
33546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <cutils/log.h>
34546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <gtest/gtest.h>
35546734b3ab577d46afe863515104a062e88a109bAndy Hung#include <media/AudioBufferProvider.h>
36546734b3ab577d46afe863515104a062e88a109bAndy Hung#include "AudioResampler.h"
37c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung#include "test_utils.h"
38546734b3ab577d46afe863515104a062e88a109bAndy Hung
39075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hungvoid resample(int channels, void *output,
40075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung        size_t outputFrames, const std::vector<size_t> &outputIncr,
41546734b3ab577d46afe863515104a062e88a109bAndy Hung        android::AudioBufferProvider *provider, android::AudioResampler *resampler)
42546734b3ab577d46afe863515104a062e88a109bAndy Hung{
43546734b3ab577d46afe863515104a062e88a109bAndy Hung    for (size_t i = 0, j = 0; i < outputFrames; ) {
44546734b3ab577d46afe863515104a062e88a109bAndy Hung        size_t thisFrames = outputIncr[j++];
45546734b3ab577d46afe863515104a062e88a109bAndy Hung        if (j >= outputIncr.size()) {
46546734b3ab577d46afe863515104a062e88a109bAndy Hung            j = 0;
47546734b3ab577d46afe863515104a062e88a109bAndy Hung        }
48546734b3ab577d46afe863515104a062e88a109bAndy Hung        if (thisFrames == 0 || thisFrames > outputFrames - i) {
49546734b3ab577d46afe863515104a062e88a109bAndy Hung            thisFrames = outputFrames - i;
50546734b3ab577d46afe863515104a062e88a109bAndy Hung        }
516b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung        size_t framesResampled = resampler->resample(
526b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung                (int32_t*) output + channels*i, thisFrames, provider);
536b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung        // we should have enough buffer space, so there is no short count.
546b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung        ASSERT_EQ(thisFrames, framesResampled);
55546734b3ab577d46afe863515104a062e88a109bAndy Hung        i += thisFrames;
56546734b3ab577d46afe863515104a062e88a109bAndy Hung    }
57546734b3ab577d46afe863515104a062e88a109bAndy Hung}
58546734b3ab577d46afe863515104a062e88a109bAndy Hung
59546734b3ab577d46afe863515104a062e88a109bAndy Hungvoid buffercmp(const void *reference, const void *test,
60546734b3ab577d46afe863515104a062e88a109bAndy Hung        size_t outputFrameSize, size_t outputFrames)
61546734b3ab577d46afe863515104a062e88a109bAndy Hung{
62546734b3ab577d46afe863515104a062e88a109bAndy Hung    for (size_t i = 0; i < outputFrames; ++i) {
63546734b3ab577d46afe863515104a062e88a109bAndy Hung        int check = memcmp((const char*)reference + i * outputFrameSize,
64546734b3ab577d46afe863515104a062e88a109bAndy Hung                (const char*)test + i * outputFrameSize, outputFrameSize);
65546734b3ab577d46afe863515104a062e88a109bAndy Hung        if (check) {
66a4daf0b4f934b800a49f199fb8c09409391c8fc0Glenn Kasten            ALOGE("Failure at frame %zu", i);
67546734b3ab577d46afe863515104a062e88a109bAndy Hung            ASSERT_EQ(check, 0); /* fails */
68546734b3ab577d46afe863515104a062e88a109bAndy Hung        }
69546734b3ab577d46afe863515104a062e88a109bAndy Hung    }
70546734b3ab577d46afe863515104a062e88a109bAndy Hung}
71546734b3ab577d46afe863515104a062e88a109bAndy Hung
72075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hungvoid testBufferIncrement(size_t channels, bool useFloat,
73075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung        unsigned inputFreq, unsigned outputFreq,
74546734b3ab577d46afe863515104a062e88a109bAndy Hung        enum android::AudioResampler::src_quality quality)
75546734b3ab577d46afe863515104a062e88a109bAndy Hung{
763348e36c51e91e78020bcc6578eda83d97c31becAndy Hung    const audio_format_t format = useFloat ? AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT;
77546734b3ab577d46afe863515104a062e88a109bAndy Hung    // create the provider
78c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung    std::vector<int> inputIncr;
79c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung    SignalProvider provider;
80075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    if (useFloat) {
81075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung        provider.setChirp<float>(channels,
82075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung                0., outputFreq/2., outputFreq, outputFreq/2000.);
83075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    } else {
84075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung        provider.setChirp<int16_t>(channels,
85075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung                0., outputFreq/2., outputFreq, outputFreq/2000.);
86075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    }
87c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung    provider.setIncr(inputIncr);
88546734b3ab577d46afe863515104a062e88a109bAndy Hung
89546734b3ab577d46afe863515104a062e88a109bAndy Hung    // calculate the output size
90546734b3ab577d46afe863515104a062e88a109bAndy Hung    size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq;
91075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    size_t outputFrameSize = channels * (useFloat ? sizeof(float) : sizeof(int32_t));
92546734b3ab577d46afe863515104a062e88a109bAndy Hung    size_t outputSize = outputFrameSize * outputFrames;
93546734b3ab577d46afe863515104a062e88a109bAndy Hung    outputSize &= ~7;
94546734b3ab577d46afe863515104a062e88a109bAndy Hung
95546734b3ab577d46afe863515104a062e88a109bAndy Hung    // create the resampler
96546734b3ab577d46afe863515104a062e88a109bAndy Hung    android::AudioResampler* resampler;
97546734b3ab577d46afe863515104a062e88a109bAndy Hung
983348e36c51e91e78020bcc6578eda83d97c31becAndy Hung    resampler = android::AudioResampler::create(format, channels, outputFreq, quality);
99546734b3ab577d46afe863515104a062e88a109bAndy Hung    resampler->setSampleRate(inputFreq);
1005e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung    resampler->setVolume(android::AudioResampler::UNITY_GAIN_FLOAT,
1015e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung            android::AudioResampler::UNITY_GAIN_FLOAT);
102546734b3ab577d46afe863515104a062e88a109bAndy Hung
103546734b3ab577d46afe863515104a062e88a109bAndy Hung    // set up the reference run
104546734b3ab577d46afe863515104a062e88a109bAndy Hung    std::vector<size_t> refIncr;
105546734b3ab577d46afe863515104a062e88a109bAndy Hung    refIncr.push_back(outputFrames);
106546734b3ab577d46afe863515104a062e88a109bAndy Hung    void* reference = malloc(outputSize);
107075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    resample(channels, reference, outputFrames, refIncr, &provider, resampler);
108546734b3ab577d46afe863515104a062e88a109bAndy Hung
109546734b3ab577d46afe863515104a062e88a109bAndy Hung    provider.reset();
110546734b3ab577d46afe863515104a062e88a109bAndy Hung
111546734b3ab577d46afe863515104a062e88a109bAndy Hung#if 0
112546734b3ab577d46afe863515104a062e88a109bAndy Hung    /* this test will fail - API interface issue: reset() does not clear internal buffers */
113546734b3ab577d46afe863515104a062e88a109bAndy Hung    resampler->reset();
114546734b3ab577d46afe863515104a062e88a109bAndy Hung#else
115546734b3ab577d46afe863515104a062e88a109bAndy Hung    delete resampler;
1163348e36c51e91e78020bcc6578eda83d97c31becAndy Hung    resampler = android::AudioResampler::create(format, channels, outputFreq, quality);
117546734b3ab577d46afe863515104a062e88a109bAndy Hung    resampler->setSampleRate(inputFreq);
1185e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung    resampler->setVolume(android::AudioResampler::UNITY_GAIN_FLOAT,
1195e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung            android::AudioResampler::UNITY_GAIN_FLOAT);
120546734b3ab577d46afe863515104a062e88a109bAndy Hung#endif
121546734b3ab577d46afe863515104a062e88a109bAndy Hung
122546734b3ab577d46afe863515104a062e88a109bAndy Hung    // set up the test run
123546734b3ab577d46afe863515104a062e88a109bAndy Hung    std::vector<size_t> outIncr;
124546734b3ab577d46afe863515104a062e88a109bAndy Hung    outIncr.push_back(1);
125546734b3ab577d46afe863515104a062e88a109bAndy Hung    outIncr.push_back(2);
126546734b3ab577d46afe863515104a062e88a109bAndy Hung    outIncr.push_back(3);
127546734b3ab577d46afe863515104a062e88a109bAndy Hung    void* test = malloc(outputSize);
128075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    inputIncr.push_back(1);
129075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    inputIncr.push_back(3);
130075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    provider.setIncr(inputIncr);
131075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    resample(channels, test, outputFrames, outIncr, &provider, resampler);
132546734b3ab577d46afe863515104a062e88a109bAndy Hung
133546734b3ab577d46afe863515104a062e88a109bAndy Hung    // check
134546734b3ab577d46afe863515104a062e88a109bAndy Hung    buffercmp(reference, test, outputFrameSize, outputFrames);
135546734b3ab577d46afe863515104a062e88a109bAndy Hung
136546734b3ab577d46afe863515104a062e88a109bAndy Hung    free(reference);
137546734b3ab577d46afe863515104a062e88a109bAndy Hung    free(test);
138546734b3ab577d46afe863515104a062e88a109bAndy Hung    delete resampler;
139546734b3ab577d46afe863515104a062e88a109bAndy Hung}
140546734b3ab577d46afe863515104a062e88a109bAndy Hung
141546734b3ab577d46afe863515104a062e88a109bAndy Hungtemplate <typename T>
142546734b3ab577d46afe863515104a062e88a109bAndy Hunginline double sqr(T v)
143546734b3ab577d46afe863515104a062e88a109bAndy Hung{
144546734b3ab577d46afe863515104a062e88a109bAndy Hung    double dv = static_cast<double>(v);
145546734b3ab577d46afe863515104a062e88a109bAndy Hung    return dv * dv;
146546734b3ab577d46afe863515104a062e88a109bAndy Hung}
147546734b3ab577d46afe863515104a062e88a109bAndy Hung
148546734b3ab577d46afe863515104a062e88a109bAndy Hungtemplate <typename T>
149546734b3ab577d46afe863515104a062e88a109bAndy Hungdouble signalEnergy(T *start, T *end, unsigned stride)
150546734b3ab577d46afe863515104a062e88a109bAndy Hung{
151546734b3ab577d46afe863515104a062e88a109bAndy Hung    double accum = 0;
152546734b3ab577d46afe863515104a062e88a109bAndy Hung
153546734b3ab577d46afe863515104a062e88a109bAndy Hung    for (T *p = start; p < end; p += stride) {
154546734b3ab577d46afe863515104a062e88a109bAndy Hung        accum += sqr(*p);
155546734b3ab577d46afe863515104a062e88a109bAndy Hung    }
156546734b3ab577d46afe863515104a062e88a109bAndy Hung    unsigned count = (end - start + stride - 1) / stride;
157546734b3ab577d46afe863515104a062e88a109bAndy Hung    return accum / count;
158546734b3ab577d46afe863515104a062e88a109bAndy Hung}
159546734b3ab577d46afe863515104a062e88a109bAndy Hung
16042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung// TI = resampler input type, int16_t or float
16142b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung// TO = resampler output type, int32_t or float
16242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hungtemplate <typename TI, typename TO>
163546734b3ab577d46afe863515104a062e88a109bAndy Hungvoid testStopbandDownconversion(size_t channels,
164546734b3ab577d46afe863515104a062e88a109bAndy Hung        unsigned inputFreq, unsigned outputFreq,
165546734b3ab577d46afe863515104a062e88a109bAndy Hung        unsigned passband, unsigned stopband,
166546734b3ab577d46afe863515104a062e88a109bAndy Hung        enum android::AudioResampler::src_quality quality)
167546734b3ab577d46afe863515104a062e88a109bAndy Hung{
168546734b3ab577d46afe863515104a062e88a109bAndy Hung    // create the provider
169c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung    std::vector<int> inputIncr;
170c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung    SignalProvider provider;
17142b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    provider.setChirp<TI>(channels,
172c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung            0., inputFreq/2., inputFreq, inputFreq/2000.);
173c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung    provider.setIncr(inputIncr);
174546734b3ab577d46afe863515104a062e88a109bAndy Hung
175546734b3ab577d46afe863515104a062e88a109bAndy Hung    // calculate the output size
176546734b3ab577d46afe863515104a062e88a109bAndy Hung    size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq;
17742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    size_t outputFrameSize = channels * sizeof(TO);
178546734b3ab577d46afe863515104a062e88a109bAndy Hung    size_t outputSize = outputFrameSize * outputFrames;
179546734b3ab577d46afe863515104a062e88a109bAndy Hung    outputSize &= ~7;
180546734b3ab577d46afe863515104a062e88a109bAndy Hung
181546734b3ab577d46afe863515104a062e88a109bAndy Hung    // create the resampler
182546734b3ab577d46afe863515104a062e88a109bAndy Hung    android::AudioResampler* resampler;
183546734b3ab577d46afe863515104a062e88a109bAndy Hung
18442b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    resampler = android::AudioResampler::create(
18542b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            is_same<TI, int16_t>::value ? AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_FLOAT,
1863348e36c51e91e78020bcc6578eda83d97c31becAndy Hung            channels, outputFreq, quality);
187546734b3ab577d46afe863515104a062e88a109bAndy Hung    resampler->setSampleRate(inputFreq);
1885e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung    resampler->setVolume(android::AudioResampler::UNITY_GAIN_FLOAT,
1895e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung            android::AudioResampler::UNITY_GAIN_FLOAT);
190546734b3ab577d46afe863515104a062e88a109bAndy Hung
191546734b3ab577d46afe863515104a062e88a109bAndy Hung    // set up the reference run
192546734b3ab577d46afe863515104a062e88a109bAndy Hung    std::vector<size_t> refIncr;
193546734b3ab577d46afe863515104a062e88a109bAndy Hung    refIncr.push_back(outputFrames);
194546734b3ab577d46afe863515104a062e88a109bAndy Hung    void* reference = malloc(outputSize);
195075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    resample(channels, reference, outputFrames, refIncr, &provider, resampler);
196546734b3ab577d46afe863515104a062e88a109bAndy Hung
19742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    TO *out = reinterpret_cast<TO *>(reference);
198546734b3ab577d46afe863515104a062e88a109bAndy Hung
199546734b3ab577d46afe863515104a062e88a109bAndy Hung    // check signal energy in passband
200546734b3ab577d46afe863515104a062e88a109bAndy Hung    const unsigned passbandFrame = passband * outputFreq / 1000.;
201546734b3ab577d46afe863515104a062e88a109bAndy Hung    const unsigned stopbandFrame = stopband * outputFreq / 1000.;
202546734b3ab577d46afe863515104a062e88a109bAndy Hung
203546734b3ab577d46afe863515104a062e88a109bAndy Hung    // check each channel separately
204546734b3ab577d46afe863515104a062e88a109bAndy Hung    for (size_t i = 0; i < channels; ++i) {
205546734b3ab577d46afe863515104a062e88a109bAndy Hung        double passbandEnergy = signalEnergy(out, out + passbandFrame * channels, channels);
206546734b3ab577d46afe863515104a062e88a109bAndy Hung        double stopbandEnergy = signalEnergy(out + stopbandFrame * channels,
207546734b3ab577d46afe863515104a062e88a109bAndy Hung                out + outputFrames * channels, channels);
208546734b3ab577d46afe863515104a062e88a109bAndy Hung        double dbAtten = -10. * log10(stopbandEnergy / passbandEnergy);
209546734b3ab577d46afe863515104a062e88a109bAndy Hung        ASSERT_GT(dbAtten, 60.);
210546734b3ab577d46afe863515104a062e88a109bAndy Hung
211546734b3ab577d46afe863515104a062e88a109bAndy Hung#if 0
212546734b3ab577d46afe863515104a062e88a109bAndy Hung        // internal verification
213546734b3ab577d46afe863515104a062e88a109bAndy Hung        printf("if:%d  of:%d  pbf:%d  sbf:%d  sbe: %f  pbe: %f  db: %.2f\n",
214546734b3ab577d46afe863515104a062e88a109bAndy Hung                provider.getNumFrames(), outputFrames,
215546734b3ab577d46afe863515104a062e88a109bAndy Hung                passbandFrame, stopbandFrame, stopbandEnergy, passbandEnergy, dbAtten);
216546734b3ab577d46afe863515104a062e88a109bAndy Hung        for (size_t i = 0; i < 10; ++i) {
21742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            std::cout << out[i+passbandFrame*channels] << std::endl;
218546734b3ab577d46afe863515104a062e88a109bAndy Hung        }
219546734b3ab577d46afe863515104a062e88a109bAndy Hung        for (size_t i = 0; i < 10; ++i) {
22042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            std::cout << out[i+stopbandFrame*channels] << std::endl;
221546734b3ab577d46afe863515104a062e88a109bAndy Hung        }
222546734b3ab577d46afe863515104a062e88a109bAndy Hung#endif
223546734b3ab577d46afe863515104a062e88a109bAndy Hung    }
224546734b3ab577d46afe863515104a062e88a109bAndy Hung
225546734b3ab577d46afe863515104a062e88a109bAndy Hung    free(reference);
226546734b3ab577d46afe863515104a062e88a109bAndy Hung    delete resampler;
227546734b3ab577d46afe863515104a062e88a109bAndy Hung}
228546734b3ab577d46afe863515104a062e88a109bAndy Hung
229546734b3ab577d46afe863515104a062e88a109bAndy Hung/* Buffer increment test
230546734b3ab577d46afe863515104a062e88a109bAndy Hung *
231546734b3ab577d46afe863515104a062e88a109bAndy Hung * We compare a reference output, where we consume and process the entire
232546734b3ab577d46afe863515104a062e88a109bAndy Hung * buffer at a time, and a test output, where we provide small chunks of input
233546734b3ab577d46afe863515104a062e88a109bAndy Hung * data and process small chunks of output (which may not be equivalent in size).
234546734b3ab577d46afe863515104a062e88a109bAndy Hung *
235546734b3ab577d46afe863515104a062e88a109bAndy Hung * Two subtests - fixed phase (3:2 down) and interpolated phase (147:320 up)
236546734b3ab577d46afe863515104a062e88a109bAndy Hung */
237546734b3ab577d46afe863515104a062e88a109bAndy HungTEST(audioflinger_resampler, bufferincrement_fixedphase) {
238546734b3ab577d46afe863515104a062e88a109bAndy Hung    // all of these work
239546734b3ab577d46afe863515104a062e88a109bAndy Hung    static const enum android::AudioResampler::src_quality kQualityArray[] = {
240546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::LOW_QUALITY,
241546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::MED_QUALITY,
242546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::HIGH_QUALITY,
243546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::VERY_HIGH_QUALITY,
244546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::DYN_LOW_QUALITY,
245546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::DYN_MED_QUALITY,
246546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::DYN_HIGH_QUALITY,
247546734b3ab577d46afe863515104a062e88a109bAndy Hung    };
248546734b3ab577d46afe863515104a062e88a109bAndy Hung
249546734b3ab577d46afe863515104a062e88a109bAndy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
250075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung        testBufferIncrement(2, false, 48000, 32000, kQualityArray[i]);
251546734b3ab577d46afe863515104a062e88a109bAndy Hung    }
252546734b3ab577d46afe863515104a062e88a109bAndy Hung}
253546734b3ab577d46afe863515104a062e88a109bAndy Hung
254546734b3ab577d46afe863515104a062e88a109bAndy HungTEST(audioflinger_resampler, bufferincrement_interpolatedphase) {
255546734b3ab577d46afe863515104a062e88a109bAndy Hung    // all of these work except low quality
256546734b3ab577d46afe863515104a062e88a109bAndy Hung    static const enum android::AudioResampler::src_quality kQualityArray[] = {
257546734b3ab577d46afe863515104a062e88a109bAndy Hung//           android::AudioResampler::LOW_QUALITY,
258546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::MED_QUALITY,
259546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::HIGH_QUALITY,
260546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::VERY_HIGH_QUALITY,
261546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::DYN_LOW_QUALITY,
262546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::DYN_MED_QUALITY,
263546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::DYN_HIGH_QUALITY,
264546734b3ab577d46afe863515104a062e88a109bAndy Hung    };
265546734b3ab577d46afe863515104a062e88a109bAndy Hung
266546734b3ab577d46afe863515104a062e88a109bAndy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
267075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung        testBufferIncrement(2, false, 22050, 48000, kQualityArray[i]);
268075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    }
269075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung}
270075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung
271075abae2a954bf3edf18ad1705c2c0f188454ae0Andy HungTEST(audioflinger_resampler, bufferincrement_fixedphase_multi) {
272075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    // only dynamic quality
273075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    static const enum android::AudioResampler::src_quality kQualityArray[] = {
274075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung            android::AudioResampler::DYN_LOW_QUALITY,
275075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung            android::AudioResampler::DYN_MED_QUALITY,
276075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung            android::AudioResampler::DYN_HIGH_QUALITY,
277075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    };
278075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung
279075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
280075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung        testBufferIncrement(4, false, 48000, 32000, kQualityArray[i]);
281075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    }
282075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung}
283075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung
284075abae2a954bf3edf18ad1705c2c0f188454ae0Andy HungTEST(audioflinger_resampler, bufferincrement_interpolatedphase_multi_float) {
285075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    // only dynamic quality
286075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    static const enum android::AudioResampler::src_quality kQualityArray[] = {
287075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung            android::AudioResampler::DYN_LOW_QUALITY,
288075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung            android::AudioResampler::DYN_MED_QUALITY,
289075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung            android::AudioResampler::DYN_HIGH_QUALITY,
290075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    };
291075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung
292075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
293075abae2a954bf3edf18ad1705c2c0f188454ae0Andy Hung        testBufferIncrement(8, true, 22050, 48000, kQualityArray[i]);
294546734b3ab577d46afe863515104a062e88a109bAndy Hung    }
295546734b3ab577d46afe863515104a062e88a109bAndy Hung}
296546734b3ab577d46afe863515104a062e88a109bAndy Hung
297546734b3ab577d46afe863515104a062e88a109bAndy Hung/* Simple aliasing test
298546734b3ab577d46afe863515104a062e88a109bAndy Hung *
299546734b3ab577d46afe863515104a062e88a109bAndy Hung * This checks stopband response of the chirp signal to make sure frequencies
300546734b3ab577d46afe863515104a062e88a109bAndy Hung * are properly suppressed.  It uses downsampling because the stopband can be
301546734b3ab577d46afe863515104a062e88a109bAndy Hung * clearly isolated by input frequencies exceeding the output sample rate (nyquist).
302546734b3ab577d46afe863515104a062e88a109bAndy Hung */
30342b011166ece30969667e0ff9dcf4832568c9c1aAndy HungTEST(audioflinger_resampler, stopbandresponse_integer) {
304546734b3ab577d46afe863515104a062e88a109bAndy Hung    // not all of these may work (old resamplers fail on downsampling)
305546734b3ab577d46afe863515104a062e88a109bAndy Hung    static const enum android::AudioResampler::src_quality kQualityArray[] = {
306546734b3ab577d46afe863515104a062e88a109bAndy Hung            //android::AudioResampler::LOW_QUALITY,
307546734b3ab577d46afe863515104a062e88a109bAndy Hung            //android::AudioResampler::MED_QUALITY,
308546734b3ab577d46afe863515104a062e88a109bAndy Hung            //android::AudioResampler::HIGH_QUALITY,
309546734b3ab577d46afe863515104a062e88a109bAndy Hung            //android::AudioResampler::VERY_HIGH_QUALITY,
310546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::DYN_LOW_QUALITY,
311546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::DYN_MED_QUALITY,
312546734b3ab577d46afe863515104a062e88a109bAndy Hung            android::AudioResampler::DYN_HIGH_QUALITY,
313546734b3ab577d46afe863515104a062e88a109bAndy Hung    };
314546734b3ab577d46afe863515104a062e88a109bAndy Hung
315546734b3ab577d46afe863515104a062e88a109bAndy Hung    // in this test we assume a maximum transition band between 12kHz and 20kHz.
316546734b3ab577d46afe863515104a062e88a109bAndy Hung    // there must be at least 60dB relative attenuation between stopband and passband.
317546734b3ab577d46afe863515104a062e88a109bAndy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
31842b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung        testStopbandDownconversion<int16_t, int32_t>(
31942b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung                2, 48000, 32000, 12000, 20000, kQualityArray[i]);
320546734b3ab577d46afe863515104a062e88a109bAndy Hung    }
321546734b3ab577d46afe863515104a062e88a109bAndy Hung
322546734b3ab577d46afe863515104a062e88a109bAndy Hung    // in this test we assume a maximum transition band between 7kHz and 15kHz.
323546734b3ab577d46afe863515104a062e88a109bAndy Hung    // there must be at least 60dB relative attenuation between stopband and passband.
324546734b3ab577d46afe863515104a062e88a109bAndy Hung    // (the weird ratio triggers interpolative resampling)
325546734b3ab577d46afe863515104a062e88a109bAndy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
32642b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung        testStopbandDownconversion<int16_t, int32_t>(
32742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung                2, 48000, 22101, 7000, 15000, kQualityArray[i]);
328546734b3ab577d46afe863515104a062e88a109bAndy Hung    }
329546734b3ab577d46afe863515104a062e88a109bAndy Hung}
33042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung
33142b011166ece30969667e0ff9dcf4832568c9c1aAndy HungTEST(audioflinger_resampler, stopbandresponse_integer_multichannel) {
33242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // not all of these may work (old resamplers fail on downsampling)
33342b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    static const enum android::AudioResampler::src_quality kQualityArray[] = {
33442b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::LOW_QUALITY,
33542b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::MED_QUALITY,
33642b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::HIGH_QUALITY,
33742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::VERY_HIGH_QUALITY,
33842b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            android::AudioResampler::DYN_LOW_QUALITY,
33942b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            android::AudioResampler::DYN_MED_QUALITY,
34042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            android::AudioResampler::DYN_HIGH_QUALITY,
34142b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    };
34242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung
34342b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // in this test we assume a maximum transition band between 12kHz and 20kHz.
34442b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // there must be at least 60dB relative attenuation between stopband and passband.
34542b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
34642b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung        testStopbandDownconversion<int16_t, int32_t>(
34742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung                8, 48000, 32000, 12000, 20000, kQualityArray[i]);
34842b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    }
34942b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung
35042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // in this test we assume a maximum transition band between 7kHz and 15kHz.
35142b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // there must be at least 60dB relative attenuation between stopband and passband.
35242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // (the weird ratio triggers interpolative resampling)
35342b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
35442b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung        testStopbandDownconversion<int16_t, int32_t>(
35542b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung                8, 48000, 22101, 7000, 15000, kQualityArray[i]);
35642b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    }
35742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung}
35842b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung
35942b011166ece30969667e0ff9dcf4832568c9c1aAndy HungTEST(audioflinger_resampler, stopbandresponse_float) {
36042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // not all of these may work (old resamplers fail on downsampling)
36142b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    static const enum android::AudioResampler::src_quality kQualityArray[] = {
36242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::LOW_QUALITY,
36342b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::MED_QUALITY,
36442b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::HIGH_QUALITY,
36542b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::VERY_HIGH_QUALITY,
36642b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            android::AudioResampler::DYN_LOW_QUALITY,
36742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            android::AudioResampler::DYN_MED_QUALITY,
36842b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            android::AudioResampler::DYN_HIGH_QUALITY,
36942b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    };
37042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung
37142b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // in this test we assume a maximum transition band between 12kHz and 20kHz.
37242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // there must be at least 60dB relative attenuation between stopband and passband.
37342b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
37442b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung        testStopbandDownconversion<float, float>(
37542b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung                2, 48000, 32000, 12000, 20000, kQualityArray[i]);
37642b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    }
37742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung
37842b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // in this test we assume a maximum transition band between 7kHz and 15kHz.
37942b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // there must be at least 60dB relative attenuation between stopband and passband.
38042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // (the weird ratio triggers interpolative resampling)
38142b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
38242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung        testStopbandDownconversion<float, float>(
38342b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung                2, 48000, 22101, 7000, 15000, kQualityArray[i]);
38442b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    }
38542b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung}
38642b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung
38742b011166ece30969667e0ff9dcf4832568c9c1aAndy HungTEST(audioflinger_resampler, stopbandresponse_float_multichannel) {
38842b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // not all of these may work (old resamplers fail on downsampling)
38942b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    static const enum android::AudioResampler::src_quality kQualityArray[] = {
39042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::LOW_QUALITY,
39142b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::MED_QUALITY,
39242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::HIGH_QUALITY,
39342b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            //android::AudioResampler::VERY_HIGH_QUALITY,
39442b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            android::AudioResampler::DYN_LOW_QUALITY,
39542b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            android::AudioResampler::DYN_MED_QUALITY,
39642b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung            android::AudioResampler::DYN_HIGH_QUALITY,
39742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    };
39842b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung
39942b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // in this test we assume a maximum transition band between 12kHz and 20kHz.
40042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // there must be at least 60dB relative attenuation between stopband and passband.
40142b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
40242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung        testStopbandDownconversion<float, float>(
40342b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung                8, 48000, 32000, 12000, 20000, kQualityArray[i]);
40442b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    }
40542b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung
40642b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // in this test we assume a maximum transition band between 7kHz and 15kHz.
40742b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // there must be at least 60dB relative attenuation between stopband and passband.
40842b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    // (the weird ratio triggers interpolative resampling)
40942b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    for (size_t i = 0; i < ARRAY_SIZE(kQualityArray); ++i) {
41042b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung        testStopbandDownconversion<float, float>(
41142b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung                8, 48000, 22101, 7000, 15000, kQualityArray[i]);
41242b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung    }
41342b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung}
41442b011166ece30969667e0ff9dcf4832568c9c1aAndy Hung
415