blob: 9501d4dcc79ff6ee73a52e88541c5208f7f475eb [file] [log] [blame]
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*******************************************************************
* A test result running on Pixel 3 for comparison.
* The first parameter indicates the channel mask index.
* The second parameter indicates the effect index.
* 0: Automatic Gain Control,
* 1: Acoustic Echo Canceler,
* 2: Noise Suppressor,
* 3: Automatic Gain Control 2
* ---------------------------------------------------------------
* Benchmark Time CPU Iterations
* ---------------------------------------------------------------
* BM_PREPROCESSING/1/0 48179 ns 48041 ns 12349
* BM_PREPROCESSING/1/1 57559 ns 57403 ns 12270
* BM_PREPROCESSING/1/2 17524 ns 17466 ns 39982
* BM_PREPROCESSING/1/3 2608 ns 2599 ns 268399
* BM_PREPROCESSING/2/0 94198 ns 93926 ns 7470
* BM_PREPROCESSING/2/1 109196 ns 108899 ns 6459
* BM_PREPROCESSING/2/2 34098 ns 33986 ns 20576
* BM_PREPROCESSING/2/3 3231 ns 3221 ns 216606
* BM_PREPROCESSING/3/0 141532 ns 141132 ns 5030
* BM_PREPROCESSING/3/1 161199 ns 160745 ns 4387
* BM_PREPROCESSING/3/2 50663 ns 50535 ns 13619
* BM_PREPROCESSING/3/3 3967 ns 3955 ns 177005
* BM_PREPROCESSING/4/0 187032 ns 186486 ns 3706
* BM_PREPROCESSING/4/1 212872 ns 212264 ns 3304
* BM_PREPROCESSING/4/2 67649 ns 67476 ns 10128
* BM_PREPROCESSING/4/3 4728 ns 4713 ns 148547
* BM_PREPROCESSING/5/0 233874 ns 233188 ns 2954
* BM_PREPROCESSING/5/1 262798 ns 262052 ns 2680
* BM_PREPROCESSING/5/2 84592 ns 84368 ns 8203
* BM_PREPROCESSING/5/3 5472 ns 5455 ns 127784
* BM_PREPROCESSING/6/0 284777 ns 283911 ns 2468
* BM_PREPROCESSING/6/1 315631 ns 314726 ns 2233
* BM_PREPROCESSING/6/2 101200 ns 100931 ns 6802
* BM_PREPROCESSING/6/3 6152 ns 6133 ns 113951
* BM_PREPROCESSING/7/0 327207 ns 326153 ns 2112
* BM_PREPROCESSING/7/1 367510 ns 366410 ns 1915
* BM_PREPROCESSING/7/2 118574 ns 118250 ns 5795
* BM_PREPROCESSING/7/3 6956 ns 6935 ns 100783
* BM_PREPROCESSING/8/0 372603 ns 371470 ns 1880
* BM_PREPROCESSING/8/1 418882 ns 417625 ns 1685
* BM_PREPROCESSING/8/2 136155 ns 135777 ns 4986
* BM_PREPROCESSING/8/3 7734 ns 7711 ns 91581
* BM_PREPROCESSING/9/0 424795 ns 423464 ns 1657
* BM_PREPROCESSING/9/1 469073 ns 467687 ns 1506
* BM_PREPROCESSING/9/2 153170 ns 152737 ns 4519
* BM_PREPROCESSING/9/3 8393 ns 8363 ns 83603
* BM_PREPROCESSING/10/0 472440 ns 470926 ns 1489
* BM_PREPROCESSING/10/1 516984 ns 515480 ns 1000
* BM_PREPROCESSING/10/2 168802 ns 168348 ns 4097
* BM_PREPROCESSING/10/3 9127 ns 9100 ns 76913
* BM_PREPROCESSING/11/0 509690 ns 508113 ns 1360
* BM_PREPROCESSING/11/1 569076 ns 567390 ns 1310
* BM_PREPROCESSING/11/2 185678 ns 185165 ns 3729
* BM_PREPROCESSING/11/3 9789 ns 9760 ns 71342
* BM_PREPROCESSING/12/0 563858 ns 562108 ns 1270
* BM_PREPROCESSING/12/1 619656 ns 617791 ns 1198
* BM_PREPROCESSING/12/2 202882 ns 202316 ns 3406
* BM_PREPROCESSING/12/3 10610 ns 10579 ns 66287
* BM_PREPROCESSING/13/0 602944 ns 601094 ns 1167
* BM_PREPROCESSING/13/1 675401 ns 673293 ns 1107
* BM_PREPROCESSING/13/2 220677 ns 220051 ns 3131
* BM_PREPROCESSING/13/3 11301 ns 11265 ns 62022
* BM_PREPROCESSING/14/0 659495 ns 657375 ns 1071
* BM_PREPROCESSING/14/1 726551 ns 724295 ns 1024
* BM_PREPROCESSING/14/2 238595 ns 237922 ns 2901
* BM_PREPROCESSING/14/3 11941 ns 11906 ns 58788
* BM_PREPROCESSING/15/0 698377 ns 696134 ns 1014
* BM_PREPROCESSING/15/1 772532 ns 770217 ns 960
* BM_PREPROCESSING/15/2 253219 ns 252505 ns 2736
* BM_PREPROCESSING/15/3 12669 ns 12632 ns 55452
* BM_PREPROCESSING/16/0 742054 ns 739708 ns 936
* BM_PREPROCESSING/16/1 828029 ns 825484 ns 902
* BM_PREPROCESSING/16/2 272419 ns 271658 ns 2545
* BM_PREPROCESSING/16/3 13473 ns 13431 ns 52088
* BM_PREPROCESSING/17/0 794444 ns 791916 ns 891
* BM_PREPROCESSING/17/1 879429 ns 876704 ns 841
* BM_PREPROCESSING/17/2 290059 ns 289216 ns 2391
* BM_PREPROCESSING/17/3 14257 ns 14210 ns 49425
* BM_PREPROCESSING/18/0 852221 ns 849430 ns 839
* BM_PREPROCESSING/18/1 931121 ns 928308 ns 799
* BM_PREPROCESSING/18/2 307995 ns 307104 ns 2253
* BM_PREPROCESSING/18/3 14947 ns 14900 ns 46872
* BM_PREPROCESSING/19/0 888752 ns 885893 ns 781
* BM_PREPROCESSING/19/1 983398 ns 980285 ns 756
* BM_PREPROCESSING/19/2 325669 ns 324705 ns 2132
* BM_PREPROCESSING/19/3 15677 ns 15629 ns 44693
* BM_PREPROCESSING/20/0 933651 ns 930697 ns 746
* BM_PREPROCESSING/20/1 1033396 ns 1030235 ns 713
* BM_PREPROCESSING/20/2 342081 ns 341077 ns 2031
* BM_PREPROCESSING/20/3 16422 ns 16370 ns 42622
* BM_PREPROCESSING/21/0 982521 ns 979388 ns 706
* BM_PREPROCESSING/21/1 1085340 ns 1081926 ns 682
* BM_PREPROCESSING/21/2 360862 ns 359810 ns 1926
* BM_PREPROCESSING/21/3 17161 ns 17107 ns 40885
* BM_PREPROCESSING/22/0 1043560 ns 1040219 ns 678
* BM_PREPROCESSING/22/1 1137203 ns 1133687 ns 653
* BM_PREPROCESSING/22/2 377421 ns 376315 ns 1841
* BM_PREPROCESSING/22/3 17903 ns 17847 ns 38984
* BM_PREPROCESSING/23/0 1090097 ns 1086523 ns 650
* BM_PREPROCESSING/23/1 1199267 ns 1194231 ns 619
* BM_PREPROCESSING/23/2 395429 ns 394263 ns 1759
* BM_PREPROCESSING/23/3 18879 ns 18818 ns 37242
* BM_PREPROCESSING/24/0 1128638 ns 1125076 ns 629
* BM_PREPROCESSING/24/1 1239909 ns 1236019 ns 598
* BM_PREPROCESSING/24/2 414294 ns 413055 ns 1680
* BM_PREPROCESSING/24/3 19583 ns 19521 ns 35771
*******************************************************************/
#include <audio_effects/effect_aec.h>
#include <audio_effects/effect_agc.h>
#include <array>
#include <climits>
#include <cstdlib>
#include <random>
#include <vector>
#include <audio_effects/effect_agc2.h>
#include <audio_effects/effect_ns.h>
#include <benchmark/benchmark.h>
#include <hardware/audio_effect.h>
#include <log/log.h>
#include <sys/stat.h>
#include <system/audio.h>
extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
constexpr int kSampleRate = 16000;
constexpr float kTenMilliSecVal = 0.01;
constexpr unsigned int kStreamDelayMs = 0;
constexpr effect_uuid_t kEffectUuids[] = {
// agc uuid
{0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
// aec uuid
{0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
// ns uuid
{0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
// agc2 uuid
{0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}},
};
constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
constexpr audio_channel_mask_t kChMasks[] = {
AUDIO_CHANNEL_INDEX_MASK_1, AUDIO_CHANNEL_INDEX_MASK_2, AUDIO_CHANNEL_INDEX_MASK_3,
AUDIO_CHANNEL_INDEX_MASK_4, AUDIO_CHANNEL_INDEX_MASK_5, AUDIO_CHANNEL_INDEX_MASK_6,
AUDIO_CHANNEL_INDEX_MASK_7, AUDIO_CHANNEL_INDEX_MASK_8, AUDIO_CHANNEL_INDEX_MASK_9,
AUDIO_CHANNEL_INDEX_MASK_10, AUDIO_CHANNEL_INDEX_MASK_11, AUDIO_CHANNEL_INDEX_MASK_12,
AUDIO_CHANNEL_INDEX_MASK_13, AUDIO_CHANNEL_INDEX_MASK_14, AUDIO_CHANNEL_INDEX_MASK_15,
AUDIO_CHANNEL_INDEX_MASK_16, AUDIO_CHANNEL_INDEX_MASK_17, AUDIO_CHANNEL_INDEX_MASK_18,
AUDIO_CHANNEL_INDEX_MASK_19, AUDIO_CHANNEL_INDEX_MASK_20, AUDIO_CHANNEL_INDEX_MASK_21,
AUDIO_CHANNEL_INDEX_MASK_22, AUDIO_CHANNEL_INDEX_MASK_23, AUDIO_CHANNEL_INDEX_MASK_24,
};
constexpr size_t kNumChMasks = std::size(kChMasks);
// types of pre processing modules
enum PreProcId {
PREPROC_AGC, // Automatic Gain Control
PREPROC_AEC, // Acoustic Echo Canceler
PREPROC_NS, // Noise Suppressor
PREPROC_AGC2, // Automatic Gain Control 2
PREPROC_NUM_EFFECTS
};
int preProcCreateEffect(effect_handle_t* pEffectHandle, uint32_t effectType,
effect_config_t* pConfig, int sessionId, int ioId) {
if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&kEffectUuids[effectType],
sessionId, ioId, pEffectHandle);
status != 0) {
ALOGE("Audio Preprocessing create returned an error = %d\n", status);
return EXIT_FAILURE;
}
int reply = 0;
uint32_t replySize = sizeof(reply);
if (effectType == PREPROC_AEC) {
if (int status = (**pEffectHandle)
->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG_REVERSE,
sizeof(effect_config_t), pConfig, &replySize, &reply);
status != 0) {
ALOGE("Set config reverse command returned an error = %d\n", status);
return EXIT_FAILURE;
}
}
if (int status = (**pEffectHandle)
->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG,
sizeof(effect_config_t), pConfig, &replySize, &reply);
status != 0) {
ALOGE("Set config command returned an error = %d\n", status);
return EXIT_FAILURE;
}
return reply;
}
int preProcSetConfigParam(effect_handle_t effectHandle, uint32_t paramType, uint32_t paramValue) {
int reply = 0;
uint32_t replySize = sizeof(reply);
uint32_t paramData[2] = {paramType, paramValue};
effect_param_t* effectParam = (effect_param_t*)malloc(sizeof(*effectParam) + sizeof(paramData));
memcpy(&effectParam->data[0], &paramData[0], sizeof(paramData));
effectParam->psize = sizeof(paramData[0]);
(*effectHandle)
->command(effectHandle, EFFECT_CMD_SET_PARAM, sizeof(effect_param_t), effectParam,
&replySize, &reply);
free(effectParam);
return reply;
}
short preProcGetShortVal(float paramValue) {
return static_cast<short>(paramValue * std::numeric_limits<short>::max());
}
static void BM_PREPROCESSING(benchmark::State& state) {
const size_t chMask = kChMasks[state.range(0) - 1];
const size_t channelCount = audio_channel_count_from_in_mask(chMask);
PreProcId effectType = (PreProcId)state.range(1);
int32_t sessionId = 1;
int32_t ioId = 1;
effect_handle_t effectHandle = nullptr;
effect_config_t config{};
config.inputCfg.samplingRate = config.outputCfg.samplingRate = kSampleRate;
config.inputCfg.channels = config.outputCfg.channels = chMask;
config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
if (int status = preProcCreateEffect(&effectHandle, state.range(1), &config, sessionId, ioId);
status != 0) {
ALOGE("Create effect call returned error %i", status);
return;
}
int reply = 0;
uint32_t replySize = sizeof(reply);
if (int status =
(*effectHandle)
->command(effectHandle, EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
status != 0) {
ALOGE("Command enable call returned error %d\n", reply);
return;
}
// Initialize input buffer with deterministic pseudo-random values
const int frameLength = (int)(kSampleRate * kTenMilliSecVal);
std::minstd_rand gen(chMask);
std::uniform_real_distribution<> dis(-1.0f, 1.0f);
std::vector<short> in(frameLength * channelCount);
for (auto& i : in) {
i = preProcGetShortVal(dis(gen));
}
std::vector<short> farIn(frameLength * channelCount);
for (auto& i : farIn) {
i = preProcGetShortVal(dis(gen));
}
std::vector<short> out(frameLength * channelCount);
// Run the test
for (auto _ : state) {
benchmark::DoNotOptimize(in.data());
benchmark::DoNotOptimize(out.data());
benchmark::DoNotOptimize(farIn.data());
audio_buffer_t inBuffer = {.frameCount = (size_t)frameLength, .s16 = in.data()};
audio_buffer_t outBuffer = {.frameCount = (size_t)frameLength, .s16 = out.data()};
audio_buffer_t farInBuffer = {.frameCount = (size_t)frameLength, .s16 = farIn.data()};
if (PREPROC_AEC == effectType) {
if (int status =
preProcSetConfigParam(effectHandle, AEC_PARAM_ECHO_DELAY, kStreamDelayMs);
status != 0) {
ALOGE("preProcSetConfigParam returned Error %d\n", status);
return;
}
}
if (int status = (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
status != 0) {
ALOGE("\nError: Process i = %d returned with error %d\n", (int)state.range(1), status);
return;
}
if (PREPROC_AEC == effectType) {
if (int status =
(*effectHandle)->process_reverse(effectHandle, &farInBuffer, &outBuffer);
status != 0) {
ALOGE("\nError: Process reverse i = %d returned with error %d\n",
(int)state.range(1), status);
return;
}
}
}
benchmark::ClobberMemory();
state.SetComplexityN(state.range(0));
if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle); status != 0) {
ALOGE("release_effect returned an error = %d\n", status);
return;
}
}
static void preprocessingArgs(benchmark::internal::Benchmark* b) {
for (int i = 1; i <= (int)kNumChMasks; i++) {
for (int j = 0; j < (int)kNumEffectUuids; ++j) {
b->Args({i, j});
}
}
}
BENCHMARK(BM_PREPROCESSING)->Apply(preprocessingArgs);
BENCHMARK_MAIN();