1 /*
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 
17 #include <audio_effects/effect_presetreverb.h>
18 #include <VectorArithmetic.h>
19 
20 #include "EffectTestHelper.h"
21 using namespace android;
22 
23 constexpr effect_uuid_t kEffectUuids[] = {
24         // NXP SW insert environmental reverb
25         {0xc7a511a0, 0xa3bb, 0x11df, 0x860e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
26         // NXP SW insert preset reverb
27         {0x172cdf00, 0xa3bc, 0x11df, 0xa72f, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
28         // NXP SW auxiliary environmental reverb
29         {0x4a387fc0, 0x8ab3, 0x11df, 0x8bad, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
30         // NXP SW auxiliary preset reverb
31         {0xf29a1400, 0xa3bb, 0x11df, 0x8ddc, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
32 };
33 
34 constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
35 
36 static constexpr audio_channel_mask_t kChMasks[] = {
37         AUDIO_CHANNEL_OUT_MONO,          AUDIO_CHANNEL_OUT_STEREO,
38         AUDIO_CHANNEL_OUT_2POINT1,       AUDIO_CHANNEL_OUT_5POINT1,
39         AUDIO_CHANNEL_OUT_7POINT1POINT4, AUDIO_CHANNEL_INDEX_MASK_23,
40         AUDIO_CHANNEL_OUT_22POINT2,
41 };
42 
43 static constexpr size_t kNumChMasks = std::size(kChMasks);
44 
45 static constexpr size_t kSampleRates[] = {8000, 11025, 44100, 48000, 192000};
46 
47 static constexpr size_t kNumSampleRates = std::size(kSampleRates);
48 
49 static constexpr size_t kFrameCounts[] = {4, 512};
50 
51 static constexpr size_t kNumFrameCounts = std::size(kFrameCounts);
52 
53 static constexpr size_t kLoopCounts[] = {1, 4};
54 
55 static constexpr size_t kNumLoopCounts = std::size(kLoopCounts);
56 
isAuxMode(const effect_uuid_t * uuid)57 static bool isAuxMode(const effect_uuid_t* uuid) {
58     // Update this, if the order of effects in kEffectUuids is updated
59     return (uuid == &kEffectUuids[2] || uuid == &kEffectUuids[3]);
60 }
61 
62 constexpr int kPresets[] = {
63         REVERB_PRESET_NONE,      REVERB_PRESET_SMALLROOM,  REVERB_PRESET_MEDIUMROOM,
64         REVERB_PRESET_LARGEROOM, REVERB_PRESET_MEDIUMHALL, REVERB_PRESET_LARGEHALL,
65         REVERB_PRESET_PLATE,
66 };
67 
68 constexpr size_t kNumPresets = std::size(kPresets);
69 
70 typedef std::tuple<int, int, int, int, int, int> SingleEffectTestParam;
71 class SingleEffectTest : public ::testing::TestWithParam<SingleEffectTestParam> {
72   public:
SingleEffectTest()73     SingleEffectTest()
74         : mSampleRate(kSampleRates[std::get<1>(GetParam())]),
75           mFrameCount(kFrameCounts[std::get<2>(GetParam())]),
76           mLoopCount(kLoopCounts[std::get<3>(GetParam())]),
77           mTotalFrameCount(mFrameCount * mLoopCount),
78           mUuid(&kEffectUuids[std::get<4>(GetParam())]),
79           mInChMask(isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO
80                                      : kChMasks[std::get<0>(GetParam())]),
81           mInChannelCount(audio_channel_count_from_out_mask(mInChMask)),
82           mOutChMask(kChMasks[std::get<0>(GetParam())]),
83           mOutChannelCount(audio_channel_count_from_out_mask(mOutChMask)),
84           mPreset(kPresets[std::get<5>(GetParam())]) {}
85 
86     const size_t mSampleRate;
87     const size_t mFrameCount;
88     const size_t mLoopCount;
89     const size_t mTotalFrameCount;
90     const effect_uuid_t* mUuid;
91     const size_t mInChMask;
92     const size_t mInChannelCount;
93     const size_t mOutChMask;
94     const size_t mOutChannelCount;
95     const size_t mPreset;
96 };
97 
98 // Tests applying a single effect
TEST_P(SingleEffectTest,SimpleProcess)99 TEST_P(SingleEffectTest, SimpleProcess) {
100     SCOPED_TRACE(testing::Message() << "outChMask: " << mOutChMask << " sampleRate: " << mSampleRate
101                                     << " frameCount: " << mFrameCount
102                                     << " loopCount: " << mLoopCount << " preset: " << mPreset);
103 
104     EffectTestHelper effect(mUuid, mInChMask, mOutChMask, mSampleRate, mFrameCount, mLoopCount);
105 
106     ASSERT_NO_FATAL_FAILURE(effect.createEffect());
107     ASSERT_NO_FATAL_FAILURE(effect.setConfig());
108     ASSERT_NO_FATAL_FAILURE(effect.setParam(REVERB_PARAM_PRESET, mPreset));
109 
110     // Initialize input buffer with deterministic pseudo-random values
111     std::vector<float> input(mTotalFrameCount * mInChannelCount);
112     std::vector<float> output(mTotalFrameCount * mOutChannelCount);
113     std::minstd_rand gen(mOutChMask);
114     std::uniform_real_distribution<> dis(-1.0f, 1.0f);
115     for (auto& in : input) {
116         in = dis(gen);
117     }
118     ASSERT_NO_FATAL_FAILURE(effect.process(input.data(), output.data()));
119     ASSERT_NO_FATAL_FAILURE(effect.releaseEffect());
120 }
121 
122 INSTANTIATE_TEST_SUITE_P(
123         EffectReverbTestAll, SingleEffectTest,
124         ::testing::Combine(::testing::Range(0, (int)kNumChMasks),
125                            ::testing::Range(0, (int)kNumSampleRates),
126                            ::testing::Range(0, (int)kNumFrameCounts),
127                            ::testing::Range(0, (int)kNumLoopCounts),
128                            ::testing::Range(0, (int)kNumEffectUuids),
129                            ::testing::Range(0, (int)kNumPresets)));
130 
131 typedef std::tuple<int, int, int, int, int> SingleEffectComparisonTestParam;
132 class SingleEffectComparisonTest
133     : public ::testing::TestWithParam<SingleEffectComparisonTestParam> {
134   public:
SingleEffectComparisonTest()135     SingleEffectComparisonTest()
136         : mSampleRate(kSampleRates[std::get<0>(GetParam())]),
137           mFrameCount(kFrameCounts[std::get<1>(GetParam())]),
138           mLoopCount(kLoopCounts[std::get<2>(GetParam())]),
139           mTotalFrameCount(mFrameCount * mLoopCount),
140           mUuid(&kEffectUuids[std::get<3>(GetParam())]),
141           mPreset(kPresets[std::get<4>(GetParam())]) {}
142 
143     const size_t mSampleRate;
144     const size_t mFrameCount;
145     const size_t mLoopCount;
146     const size_t mTotalFrameCount;
147     const effect_uuid_t* mUuid;
148     const size_t mPreset;
149 };
150 
151 // Compares first two channels in multi-channel output to stereo output when same effect is applied
TEST_P(SingleEffectComparisonTest,SimpleProcess)152 TEST_P(SingleEffectComparisonTest, SimpleProcess) {
153     SCOPED_TRACE(testing::Message()
154                  << " sampleRate: " << mSampleRate << " frameCount: " << mFrameCount
155                  << " loopCount: " << mLoopCount << " preset: " << mPreset);
156 
157     // Initialize mono input buffer with deterministic pseudo-random values
158     std::vector<float> monoInput(mTotalFrameCount);
159 
160     std::minstd_rand gen(mSampleRate);
161     std::uniform_real_distribution<> dis(-1.0f, 1.0f);
162     for (auto& in : monoInput) {
163         in = dis(gen);
164     }
165 
166     // Generate stereo by repeating mono channel data
167     std::vector<float> stereoInput(mTotalFrameCount * FCC_2);
168     adjust_channels(monoInput.data(), FCC_1, stereoInput.data(), FCC_2, sizeof(float),
169                     mTotalFrameCount * sizeof(float) * FCC_1);
170 
171     // Apply effect on stereo channels
172     EffectTestHelper stereoEffect(
173             mUuid, isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO,
174             AUDIO_CHANNEL_OUT_STEREO, mSampleRate, mFrameCount, mLoopCount);
175 
176     ASSERT_NO_FATAL_FAILURE(stereoEffect.createEffect());
177     ASSERT_NO_FATAL_FAILURE(stereoEffect.setConfig());
178     ASSERT_NO_FATAL_FAILURE(stereoEffect.setParam(REVERB_PARAM_PRESET, mPreset));
179 
180     std::vector<float> stereoOutput(mTotalFrameCount * FCC_2);
181     ASSERT_NO_FATAL_FAILURE(stereoEffect.process(
182             (isAuxMode(mUuid) ? monoInput.data() : stereoInput.data()), stereoOutput.data()));
183     ASSERT_NO_FATAL_FAILURE(stereoEffect.releaseEffect());
184 
185     // Average of both channels data is stored for mono comparison
186     std::vector<float> monoOutput(mTotalFrameCount);
187     From2iToMono_Float((const float*)stereoOutput.data(), monoOutput.data(), mTotalFrameCount);
188 
189     // Convert stereo float data to stereo int16_t to be used as reference
190     std::vector<int16_t> stereoRefI16(mTotalFrameCount * FCC_2);
191     memcpy_to_i16_from_float(stereoRefI16.data(), stereoOutput.data(), mTotalFrameCount * FCC_2);
192 
193     // mono int16_t to be used as refernece for mono comparison
194     std::vector<int16_t> monoRefI16(mTotalFrameCount);
195     memcpy_to_i16_from_float(monoRefI16.data(), monoOutput.data(), mTotalFrameCount);
196 
197     for (size_t outChMask : kChMasks) {
198         size_t outChannelCount = audio_channel_count_from_out_mask(outChMask);
199         size_t inChMask = isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO : outChMask;
200 
201         EffectTestHelper testEffect(mUuid, inChMask, outChMask, mSampleRate, mFrameCount,
202                                     mLoopCount);
203 
204         ASSERT_NO_FATAL_FAILURE(testEffect.createEffect());
205         ASSERT_NO_FATAL_FAILURE(testEffect.setConfig());
206         ASSERT_NO_FATAL_FAILURE(testEffect.setParam(REVERB_PARAM_PRESET, mPreset));
207 
208         std::vector<float> testInput(mTotalFrameCount * outChannelCount);
209 
210         // Repeat mono channel data to all the channels
211         // adjust_channels() zero fills channels > 2, hence can't be used here
212         for (size_t i = 0; i < mTotalFrameCount; ++i) {
213             auto* fp = &testInput[i * outChannelCount];
214             std::fill(fp, fp + outChannelCount, monoInput[i]);
215         }
216 
217         std::vector<float> testOutput(mTotalFrameCount * outChannelCount);
218         ASSERT_NO_FATAL_FAILURE(testEffect.process(
219                 (isAuxMode(mUuid) ? monoInput.data() : testInput.data()), testOutput.data()));
220         ASSERT_NO_FATAL_FAILURE(testEffect.releaseEffect());
221 
222         if (outChannelCount == FCC_1) {
223             // Convert the test data to int16_t
224             std::vector<int16_t> monoTestI16(mTotalFrameCount);
225             memcpy_to_i16_from_float(monoTestI16.data(), testOutput.data(), mTotalFrameCount);
226 
227             ASSERT_EQ(0, memcmp(monoRefI16.data(), monoTestI16.data(), mTotalFrameCount * FCC_2))
228                     << "Mono channel do not match with reference output \n";
229         } else {
230             // Extract first two channels
231             std::vector<float> stereoTestOutput(mTotalFrameCount * FCC_2);
232             adjust_channels(testOutput.data(), outChannelCount, stereoTestOutput.data(), FCC_2,
233                             sizeof(float), mTotalFrameCount * sizeof(float) * outChannelCount);
234 
235             // Convert the test data to int16_t
236             std::vector<int16_t> stereoTestI16(mTotalFrameCount * FCC_2);
237             memcpy_to_i16_from_float(stereoTestI16.data(), stereoTestOutput.data(),
238                                      mTotalFrameCount * FCC_2);
239 
240             ASSERT_EQ(0,
241                       memcmp(stereoRefI16.data(), stereoTestI16.data(), mTotalFrameCount * FCC_2))
242                     << "First two channels do not match with stereo output \n";
243         }
244     }
245 }
246 
247 INSTANTIATE_TEST_SUITE_P(
248         EffectReverbTestAll, SingleEffectComparisonTest,
249         ::testing::Combine(::testing::Range(0, (int)kNumSampleRates),
250                            ::testing::Range(0, (int)kNumFrameCounts),
251                            ::testing::Range(0, (int)kNumLoopCounts),
252                            ::testing::Range(0, (int)kNumEffectUuids),
253                            ::testing::Range(0, (int)kNumPresets)));
254 
main(int argc,char ** argv)255 int main(int argc, char** argv) {
256     ::testing::InitGoogleTest(&argc, argv);
257     int status = RUN_ALL_TESTS();
258     ALOGV("Test result = %d\n", status);
259     return status;
260 }
261