• 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 #include <random>
18 #include <vector>
19 
20 #include <audio_effects/effect_downmix.h>
21 #include <audio_utils/channels.h>
22 #include <audio_utils/primitives.h>
23 #include <audio_utils/Statistics.h>
24 #include <benchmark/benchmark.h>
25 #include <log/log.h>
26 #include <system/audio.h>
27 
28 #include "EffectDownmix.h"
29 
30 extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
31 
32 static constexpr audio_channel_mask_t kChannelPositionMasks[] = {
33     AUDIO_CHANNEL_OUT_FRONT_LEFT,
34     AUDIO_CHANNEL_OUT_FRONT_CENTER,
35     AUDIO_CHANNEL_OUT_STEREO,
36     AUDIO_CHANNEL_OUT_2POINT1,
37     AUDIO_CHANNEL_OUT_2POINT0POINT2,
38     AUDIO_CHANNEL_OUT_QUAD,
39     AUDIO_CHANNEL_OUT_QUAD_BACK,
40     AUDIO_CHANNEL_OUT_QUAD_SIDE,
41     AUDIO_CHANNEL_OUT_SURROUND,
42     AUDIO_CHANNEL_OUT_2POINT1POINT2,
43     AUDIO_CHANNEL_OUT_3POINT0POINT2,
44     AUDIO_CHANNEL_OUT_PENTA,
45     AUDIO_CHANNEL_OUT_3POINT1POINT2,
46     AUDIO_CHANNEL_OUT_5POINT1,
47     AUDIO_CHANNEL_OUT_5POINT1_BACK,
48     AUDIO_CHANNEL_OUT_5POINT1_SIDE,
49     AUDIO_CHANNEL_OUT_6POINT1,
50     AUDIO_CHANNEL_OUT_5POINT1POINT2,
51     AUDIO_CHANNEL_OUT_7POINT1,
52     AUDIO_CHANNEL_OUT_5POINT1POINT4,
53     AUDIO_CHANNEL_OUT_7POINT1POINT2,
54     AUDIO_CHANNEL_OUT_7POINT1POINT4,
55     AUDIO_CHANNEL_OUT_13POINT_360RA,
56     AUDIO_CHANNEL_OUT_22POINT2,
57 };
58 
59 static constexpr effect_uuid_t downmix_uuid = {
60     0x93f04452, 0xe4fe, 0x41cc, 0x91f9, {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}};
61 
62 static constexpr size_t kFrameCount = 1000;
63 
64 /*
65 Pixel 3XL
66 downmix_benchmark:
67   #BM_Downmix/0     4723 ns    4708 ns       148694
68   #BM_Downmix/1     4717 ns    4702 ns       148873
69   #BM_Downmix/2     4803 ns    4788 ns       145893
70   #BM_Downmix/3     5056 ns    5041 ns       139110
71   #BM_Downmix/4     4710 ns    4696 ns       149625
72   #BM_Downmix/5     1514 ns    1509 ns       463694
73   #BM_Downmix/6     1513 ns    1509 ns       463451
74   #BM_Downmix/7     1516 ns    1511 ns       463899
75   #BM_Downmix/8     4445 ns    4431 ns       157831
76   #BM_Downmix/9     5081 ns    5065 ns       138412
77   #BM_Downmix/10    4354 ns    4341 ns       161247
78   #BM_Downmix/11    4411 ns    4397 ns       158893
79   #BM_Downmix/12    4434 ns    4420 ns       157992
80   #BM_Downmix/13    4845 ns    4830 ns       144873
81   #BM_Downmix/14    4851 ns    4835 ns       144954
82   #BM_Downmix/15    4884 ns    4870 ns       144233
83   #BM_Downmix/16    5832 ns    5813 ns       120565
84   #BM_Downmix/17    5241 ns    5224 ns       133927
85   #BM_Downmix/18    5044 ns    5028 ns       139131
86   #BM_Downmix/19    5244 ns    5227 ns       132315
87   #BM_Downmix/20    5943 ns    5923 ns       117759
88   #BM_Downmix/21    5990 ns    5971 ns       117263
89   #BM_Downmix/22    4468 ns    4454 ns       156689
90   #BM_Downmix/23    7306 ns    7286 ns        95911
91 --
92 downmix_benchmark: (generic fold)
93   #BM_Downmix/0     4722 ns    4707 ns       149847
94   #BM_Downmix/1     4714 ns    4698 ns       148748
95   #BM_Downmix/2     4794 ns    4779 ns       145661
96   #BM_Downmix/3     5053 ns    5035 ns       139172
97   #BM_Downmix/4     4695 ns    4678 ns       149762
98   #BM_Downmix/5     4381 ns    4368 ns       159675
99   #BM_Downmix/6     4387 ns    4373 ns       160267
100   #BM_Downmix/7     4732 ns    4717 ns       148514
101   #BM_Downmix/8     4430 ns    4415 ns       158133
102   #BM_Downmix/9     5101 ns    5084 ns       138353
103   #BM_Downmix/10    4356 ns    4343 ns       160821
104   #BM_Downmix/11    4397 ns    4383 ns       159995
105   #BM_Downmix/12    4438 ns    4424 ns       158117
106   #BM_Downmix/13    5243 ns    5226 ns       133863
107   #BM_Downmix/14    5259 ns    5242 ns       131855
108   #BM_Downmix/15    5245 ns    5228 ns       133686
109   #BM_Downmix/16    5829 ns    5809 ns       120543
110   #BM_Downmix/17    5245 ns    5228 ns       133533
111   #BM_Downmix/18    5935 ns    5916 ns       118282
112   #BM_Downmix/19    5263 ns    5245 ns       133657
113   #BM_Downmix/20    5998 ns    5978 ns       114693
114   #BM_Downmix/21    5989 ns    5969 ns       117450
115   #BM_Downmix/22    4442 ns    4431 ns       157913
116   #BM_Downmix/23    7309 ns    7290 ns        95797
117 */
118 
BM_Downmix(benchmark::State & state)119 static void BM_Downmix(benchmark::State& state) {
120     const audio_channel_mask_t channelMask = kChannelPositionMasks[state.range(0)];
121     const size_t channelCount = audio_channel_count_from_out_mask(channelMask);
122     const int sampleRate = 48000;
123 
124     // Initialize input buffer with deterministic pseudo-random values
125     std::minstd_rand gen(channelMask);
126     std::uniform_real_distribution<> dis(-1.0f, 1.0f);
127     std::vector<float> input(kFrameCount * channelCount);
128     std::vector<float> output(kFrameCount * 2);
129     for (auto& in : input) {
130         in = dis(gen);
131     }
132     effect_handle_t effectHandle = nullptr;
133     if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(
134             &downmix_uuid, 1, 1, &effectHandle);
135         status != 0) {
136         ALOGE("create_effect returned an error = %d\n", status);
137         return;
138     }
139 
140     effect_config_t config{};
141     config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
142     config.inputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
143     config.inputCfg.bufferProvider.getBuffer = nullptr;
144     config.inputCfg.bufferProvider.releaseBuffer = nullptr;
145     config.inputCfg.bufferProvider.cookie = nullptr;
146     config.inputCfg.mask = EFFECT_CONFIG_ALL;
147 
148     config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
149     config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
150     config.outputCfg.bufferProvider.getBuffer = nullptr;
151     config.outputCfg.bufferProvider.releaseBuffer = nullptr;
152     config.outputCfg.bufferProvider.cookie = nullptr;
153     config.outputCfg.mask = EFFECT_CONFIG_ALL;
154 
155     config.inputCfg.samplingRate = sampleRate;
156     config.inputCfg.channels = channelMask;
157 
158     config.outputCfg.samplingRate = sampleRate;
159     config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; // output always stereo
160 
161     int reply = 0;
162     uint32_t replySize = sizeof(reply);
163     if (int status = (*effectHandle)
164             ->command(effectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t),
165                     &config, &replySize, &reply);
166         status != 0) {
167         ALOGE("command returned an error = %d\n", status);
168         return;
169     }
170 
171     if (int status = (*effectHandle)
172             ->command(effectHandle, EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
173         status != 0) {
174         ALOGE("Command enable call returned error %d\n", reply);
175         return;
176     }
177 
178     // Run the test
179     for (auto _ : state) {
180         benchmark::DoNotOptimize(input.data());
181         benchmark::DoNotOptimize(output.data());
182 
183         audio_buffer_t inBuffer = {.frameCount = kFrameCount, .f32 = input.data()};
184         audio_buffer_t outBuffer = {.frameCount = kFrameCount, .f32 = output.data()};
185         (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
186 
187         benchmark::ClobberMemory();
188     }
189 
190     state.SetComplexityN(state.range(0));
191 
192     if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle); status != 0) {
193         ALOGE("release_effect returned an error = %d\n", status);
194         return;
195     }
196 }
197 
DownmixArgs(benchmark::internal::Benchmark * b)198 static void DownmixArgs(benchmark::internal::Benchmark* b) {
199     for (int i = 0; i < (int)std::size(kChannelPositionMasks); i++) {
200         b->Args({i});
201     }
202 }
203 
204 BENCHMARK(BM_Downmix)->Apply(DownmixArgs);
205 
206 BENCHMARK_MAIN();
207