• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #pragma once
18 
19 #include <array>
20 #include <audio_utils/channels.h>
21 #include <audio_utils/primitives.h>
22 #include <climits>
23 #include <cstdlib>
24 #include <gtest/gtest.h>
25 #include <hardware/audio_effect.h>
26 #include <log/log.h>
27 #include <random>
28 #include <stdint.h>
29 #include <system/audio.h>
30 #include <vector>
31 
32 namespace android {
33 template <typename T>
computeSnr(const T * ref,const T * tst,size_t count)34 static float computeSnr(const T* ref, const T* tst, size_t count) {
35     double signal{};
36     double noise{};
37 
38     for (size_t i = 0; i < count; ++i) {
39         const double value(ref[i]);
40         const double diff(tst[i] - value);
41         signal += value * value;
42         noise += diff * diff;
43     }
44     // Initialized to large value to handle
45     // cases where ref and tst match exactly
46     float snr = FLT_MAX;
47     if (signal > 0.0f && noise > 0.0f) {
48         snr = 10.f * log(signal / noise);
49     }
50     return snr;
51 }
52 
53 template <typename T>
areNearlySame(const T * ref,const T * tst,size_t count)54 static float areNearlySame(const T* ref, const T* tst, size_t count) {
55     T delta;
56     if constexpr (std::is_floating_point_v<T>) {
57         delta = std::numeric_limits<T>::epsilon();
58     } else {
59         delta = 1;
60     }
61     for (size_t i = 0; i < count; ++i) {
62         const double diff(tst[i] - ref[i]);
63         if (abs(diff) > delta) {
64             return false;
65         }
66     }
67     return true;
68 }
69 
70 class EffectTestHelper {
71   public:
EffectTestHelper(const effect_uuid_t * uuid,size_t inChMask,size_t outChMask,size_t sampleRate,size_t frameCount,size_t loopCount)72     EffectTestHelper(const effect_uuid_t* uuid, size_t inChMask, size_t outChMask,
73                      size_t sampleRate, size_t frameCount, size_t loopCount)
74         : mUuid(uuid),
75           mInChMask(inChMask),
76           mInChannelCount(audio_channel_count_from_out_mask(mInChMask)),
77           mOutChMask(outChMask),
78           mOutChannelCount(audio_channel_count_from_out_mask(mOutChMask)),
79           mSampleRate(sampleRate),
80           mFrameCount(frameCount),
81           mLoopCount(loopCount) {}
82     void createEffect();
83     void releaseEffect();
84     void setConfig();
85     template <typename VALUE_DTYPE>
setParam(uint32_t type,VALUE_DTYPE const value)86     void setParam(uint32_t type, VALUE_DTYPE const value) {
87         int reply = 0;
88         uint32_t replySize = sizeof(reply);
89 
90         uint8_t paramData[sizeof(effect_param_t) + sizeof(type) + sizeof(value)];
91         auto effectParam = (effect_param_t*)paramData;
92 
93         memcpy(&effectParam->data[0], &type, sizeof(type));
94         memcpy(&effectParam->data[sizeof(type)], &value, sizeof(value));
95         effectParam->psize = sizeof(type);
96         effectParam->vsize = sizeof(value);
97         int status = (*mEffectHandle)
98                              ->command(mEffectHandle, EFFECT_CMD_SET_PARAM,
99                                        sizeof(effect_param_t) + sizeof(type) + sizeof(value),
100                                        effectParam, &replySize, &reply);
101         ASSERT_EQ(status, 0) << "set_param returned an error " << status;
102         ASSERT_EQ(reply, 0) << "set_param reply non zero " << reply;
103     };
104     void process(float* input, float* output);
105 
106     // Corresponds to SNR for 1 bit difference between two int16_t signals
107     static constexpr float kSNRThreshold = 90.308998;
108 
109     static constexpr audio_channel_mask_t kChMasks[] = {
110             AUDIO_CHANNEL_OUT_MONO,          AUDIO_CHANNEL_OUT_STEREO,
111             AUDIO_CHANNEL_OUT_2POINT1,       AUDIO_CHANNEL_OUT_2POINT0POINT2,
112             AUDIO_CHANNEL_OUT_QUAD,          AUDIO_CHANNEL_OUT_QUAD_BACK,
113             AUDIO_CHANNEL_OUT_QUAD_SIDE,     AUDIO_CHANNEL_OUT_SURROUND,
114             AUDIO_CHANNEL_INDEX_MASK_4,      AUDIO_CHANNEL_OUT_2POINT1POINT2,
115             AUDIO_CHANNEL_OUT_3POINT0POINT2, AUDIO_CHANNEL_OUT_PENTA,
116             AUDIO_CHANNEL_INDEX_MASK_5,      AUDIO_CHANNEL_OUT_3POINT1POINT2,
117             AUDIO_CHANNEL_OUT_5POINT1,       AUDIO_CHANNEL_OUT_5POINT1_BACK,
118             AUDIO_CHANNEL_OUT_5POINT1_SIDE,  AUDIO_CHANNEL_INDEX_MASK_6,
119             AUDIO_CHANNEL_OUT_6POINT1,       AUDIO_CHANNEL_INDEX_MASK_7,
120             AUDIO_CHANNEL_OUT_5POINT1POINT2, AUDIO_CHANNEL_OUT_7POINT1,
121             AUDIO_CHANNEL_INDEX_MASK_8,      AUDIO_CHANNEL_INDEX_MASK_9,
122             AUDIO_CHANNEL_INDEX_MASK_10,     AUDIO_CHANNEL_INDEX_MASK_11,
123             AUDIO_CHANNEL_INDEX_MASK_12,     AUDIO_CHANNEL_INDEX_MASK_13,
124             AUDIO_CHANNEL_INDEX_MASK_14,     AUDIO_CHANNEL_INDEX_MASK_15,
125             AUDIO_CHANNEL_INDEX_MASK_16,     AUDIO_CHANNEL_INDEX_MASK_17,
126             AUDIO_CHANNEL_INDEX_MASK_18,     AUDIO_CHANNEL_INDEX_MASK_19,
127             AUDIO_CHANNEL_INDEX_MASK_20,     AUDIO_CHANNEL_INDEX_MASK_21,
128             AUDIO_CHANNEL_INDEX_MASK_22,     AUDIO_CHANNEL_INDEX_MASK_23,
129             AUDIO_CHANNEL_INDEX_MASK_24,
130     };
131 
132     static constexpr size_t kNumChMasks = std::size(kChMasks);
133 
134     static constexpr size_t kSampleRates[] = {8000,  11025, 12000, 16000, 22050,  24000, 32000,
135                                               44100, 48000, 88200, 96000, 176400, 192000};
136 
137     static constexpr size_t kNumSampleRates = std::size(kSampleRates);
138 
139     static constexpr size_t kFrameCounts[] = {4, 2048};
140 
141     static constexpr size_t kNumFrameCounts = std::size(kFrameCounts);
142 
143     static constexpr size_t kLoopCounts[] = {1, 4};
144 
145     static constexpr size_t kNumLoopCounts = std::size(kLoopCounts);
146 
147   private:
148     const effect_uuid_t* mUuid;
149     const size_t mInChMask;
150     const size_t mInChannelCount;
151     const size_t mOutChMask;
152     const size_t mOutChannelCount;
153     const size_t mSampleRate;
154     const size_t mFrameCount;
155     const size_t mLoopCount;
156     effect_handle_t mEffectHandle{};
157 };
158 }  // namespace android
159