blob: 881ffb188016f6174ed55d7092453f0afb6837ef [file] [log] [blame]
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -08001/*
2 * Copyright 2021 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
Harish Mahendrakar88de9c42021-03-03 12:39:09 -080017#include "EffectTestHelper.h"
18using namespace android;
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -080019
20// Update isBassBoost, if the order of effects is updated
21constexpr effect_uuid_t kEffectUuids[] = {
22 // NXP SW BassBoost
23 {0x8631f300, 0x72e2, 0x11df, 0xb57e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
24 // NXP SW Virtualizer
25 {0x1d4033c0, 0x8557, 0x11df, 0x9f2d, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
26 // NXP SW Equalizer
27 {0xce772f20, 0x847d, 0x11df, 0xbb17, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
28 // NXP SW Volume
29 {0x119341a0, 0x8469, 0x11df, 0x81f9, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
30};
31
32static bool isBassBoost(const effect_uuid_t* uuid) {
33 // Update this, if the order of effects in kEffectUuids is updated
34 return uuid == &kEffectUuids[0];
35}
36
37constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
38
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -080039typedef std::tuple<int, int, int, int, int> SingleEffectTestParam;
40class SingleEffectTest : public ::testing::TestWithParam<SingleEffectTestParam> {
41 public:
42 SingleEffectTest()
Harish Mahendrakar88de9c42021-03-03 12:39:09 -080043 : mChMask(EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -080044 mChannelCount(audio_channel_count_from_out_mask(mChMask)),
Harish Mahendrakar88de9c42021-03-03 12:39:09 -080045 mSampleRate(EffectTestHelper::kSampleRates[std::get<1>(GetParam())]),
46 mFrameCount(EffectTestHelper::kFrameCounts[std::get<2>(GetParam())]),
47 mLoopCount(EffectTestHelper::kLoopCounts[std::get<3>(GetParam())]),
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -080048 mTotalFrameCount(mFrameCount * mLoopCount),
49 mUuid(&kEffectUuids[std::get<4>(GetParam())]) {}
50
51 const size_t mChMask;
52 const size_t mChannelCount;
53 const size_t mSampleRate;
54 const size_t mFrameCount;
55 const size_t mLoopCount;
56 const size_t mTotalFrameCount;
57 const effect_uuid_t* mUuid;
58};
59
60// Tests applying a single effect
61TEST_P(SingleEffectTest, SimpleProcess) {
62 SCOPED_TRACE(testing::Message()
63 << "chMask: " << mChMask << " sampleRate: " << mSampleRate
64 << " frameCount: " << mFrameCount << " loopCount: " << mLoopCount);
65
Harish Mahendrakar88de9c42021-03-03 12:39:09 -080066 EffectTestHelper effect(mUuid, mChMask, mChMask, mSampleRate, mFrameCount, mLoopCount);
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -080067
68 ASSERT_NO_FATAL_FAILURE(effect.createEffect());
Harish Mahendrakar88de9c42021-03-03 12:39:09 -080069 ASSERT_NO_FATAL_FAILURE(effect.setConfig());
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -080070
71 // Initialize input buffer with deterministic pseudo-random values
72 std::vector<float> input(mTotalFrameCount * mChannelCount);
73 std::vector<float> output(mTotalFrameCount * mChannelCount);
74 std::minstd_rand gen(mChMask);
75 std::uniform_real_distribution<> dis(-1.0f, 1.0f);
76 for (auto& in : input) {
77 in = dis(gen);
78 }
79 ASSERT_NO_FATAL_FAILURE(effect.process(input.data(), output.data()));
80 ASSERT_NO_FATAL_FAILURE(effect.releaseEffect());
81}
82
Harish Mahendrakar88de9c42021-03-03 12:39:09 -080083INSTANTIATE_TEST_SUITE_P(
84 EffectBundleTestAll, SingleEffectTest,
85 ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumChMasks),
86 ::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
87 ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
88 ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
89 ::testing::Range(0, (int)kNumEffectUuids)));
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -080090
91typedef std::tuple<int, int, int, int> SingleEffectComparisonTestParam;
92class SingleEffectComparisonTest
93 : public ::testing::TestWithParam<SingleEffectComparisonTestParam> {
94 public:
95 SingleEffectComparisonTest()
Harish Mahendrakar88de9c42021-03-03 12:39:09 -080096 : mSampleRate(EffectTestHelper::kSampleRates[std::get<0>(GetParam())]),
97 mFrameCount(EffectTestHelper::kFrameCounts[std::get<1>(GetParam())]),
98 mLoopCount(EffectTestHelper::kLoopCounts[std::get<2>(GetParam())]),
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -080099 mTotalFrameCount(mFrameCount * mLoopCount),
100 mUuid(&kEffectUuids[std::get<3>(GetParam())]) {}
101
102 const size_t mSampleRate;
103 const size_t mFrameCount;
104 const size_t mLoopCount;
105 const size_t mTotalFrameCount;
106 const effect_uuid_t* mUuid;
107};
108
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -0800109// Compares first two channels in multi-channel output to stereo output when same effect is applied
110TEST_P(SingleEffectComparisonTest, SimpleProcess) {
111 SCOPED_TRACE(testing::Message() << " sampleRate: " << mSampleRate << " frameCount: "
112 << mFrameCount << " loopCount: " << mLoopCount);
113
114 // Initialize mono input buffer with deterministic pseudo-random values
115 std::vector<float> monoInput(mTotalFrameCount);
116
117 std::minstd_rand gen(mSampleRate);
118 std::uniform_real_distribution<> dis(-1.0f, 1.0f);
119 for (auto& in : monoInput) {
120 in = dis(gen);
121 }
122
123 // Generate stereo by repeating mono channel data
124 std::vector<float> stereoInput(mTotalFrameCount * FCC_2);
125 adjust_channels(monoInput.data(), FCC_1, stereoInput.data(), FCC_2, sizeof(float),
126 mTotalFrameCount * sizeof(float) * FCC_1);
127
128 // Apply effect on stereo channels
Harish Mahendrakar88de9c42021-03-03 12:39:09 -0800129 EffectTestHelper stereoEffect(mUuid, AUDIO_CHANNEL_OUT_STEREO, AUDIO_CHANNEL_OUT_STEREO,
130 mSampleRate, mFrameCount, mLoopCount);
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -0800131
132 ASSERT_NO_FATAL_FAILURE(stereoEffect.createEffect());
Harish Mahendrakar88de9c42021-03-03 12:39:09 -0800133 ASSERT_NO_FATAL_FAILURE(stereoEffect.setConfig());
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -0800134
135 std::vector<float> stereoOutput(mTotalFrameCount * FCC_2);
136 ASSERT_NO_FATAL_FAILURE(stereoEffect.process(stereoInput.data(), stereoOutput.data()));
137 ASSERT_NO_FATAL_FAILURE(stereoEffect.releaseEffect());
138
139 // Convert stereo float data to stereo int16_t to be used as reference
140 std::vector<int16_t> stereoRefI16(mTotalFrameCount * FCC_2);
141 memcpy_to_i16_from_float(stereoRefI16.data(), stereoOutput.data(), mTotalFrameCount * FCC_2);
142
Harish Mahendrakar88de9c42021-03-03 12:39:09 -0800143 for (size_t chMask : EffectTestHelper::kChMasks) {
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -0800144 size_t channelCount = audio_channel_count_from_out_mask(chMask);
Harish Mahendrakar88de9c42021-03-03 12:39:09 -0800145 EffectTestHelper testEffect(mUuid, chMask, chMask, mSampleRate, mFrameCount, mLoopCount);
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -0800146
147 ASSERT_NO_FATAL_FAILURE(testEffect.createEffect());
Harish Mahendrakar88de9c42021-03-03 12:39:09 -0800148 ASSERT_NO_FATAL_FAILURE(testEffect.setConfig());
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -0800149
150 std::vector<float> testInput(mTotalFrameCount * channelCount);
151
152 // Repeat mono channel data to all the channels
153 // adjust_channels() zero fills channels > 2, hence can't be used here
154 for (size_t i = 0; i < mTotalFrameCount; ++i) {
155 auto* fp = &testInput[i * channelCount];
156 std::fill(fp, fp + channelCount, monoInput[i]);
157 }
158
159 std::vector<float> testOutput(mTotalFrameCount * channelCount);
160 ASSERT_NO_FATAL_FAILURE(testEffect.process(testInput.data(), testOutput.data()));
161 ASSERT_NO_FATAL_FAILURE(testEffect.releaseEffect());
162
163 // Extract first two channels
164 std::vector<float> stereoTestOutput(mTotalFrameCount * FCC_2);
165 adjust_channels(testOutput.data(), channelCount, stereoTestOutput.data(), FCC_2,
166 sizeof(float), mTotalFrameCount * sizeof(float) * channelCount);
167
168 // Convert the test data to int16_t
169 std::vector<int16_t> stereoTestI16(mTotalFrameCount * FCC_2);
170 memcpy_to_i16_from_float(stereoTestI16.data(), stereoTestOutput.data(),
171 mTotalFrameCount * FCC_2);
172
173 if (isBassBoost(mUuid)) {
174 // SNR must be above the threshold
175 float snr = computeSnr<int16_t>(stereoRefI16.data(), stereoTestI16.data(),
176 mTotalFrameCount * FCC_2);
Harish Mahendrakar88de9c42021-03-03 12:39:09 -0800177 ASSERT_GT(snr, EffectTestHelper::kSNRThreshold)
178 << "SNR " << snr << "is lower than " << EffectTestHelper::kSNRThreshold;
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -0800179 } else {
180 ASSERT_EQ(0,
181 memcmp(stereoRefI16.data(), stereoTestI16.data(), mTotalFrameCount * FCC_2))
182 << "First two channels do not match with stereo output \n";
183 }
184 }
185}
186
Harish Mahendrakar88de9c42021-03-03 12:39:09 -0800187INSTANTIATE_TEST_SUITE_P(
188 EffectBundleTestAll, SingleEffectComparisonTest,
189 ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
190 ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
191 ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
192 ::testing::Range(0, (int)kNumEffectUuids)));
Harish Mahendrakar9f33dba2021-02-17 18:25:21 -0800193
194int main(int argc, char** argv) {
195 ::testing::InitGoogleTest(&argc, argv);
196 int status = RUN_ALL_TESTS();
197 ALOGV("Test result = %d\n", status);
198 return status;
199}