165 lines
6.0 KiB
C++
165 lines
6.0 KiB
C++
/*
|
|
* Copyright 2022 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.
|
|
*/
|
|
|
|
#include <array>
|
|
#include <dlfcn.h>
|
|
#include <random>
|
|
#include <vector>
|
|
|
|
#include <benchmark/benchmark.h>
|
|
#include <hardware/audio_effect.h>
|
|
#include <log/log.h>
|
|
|
|
audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = [] {
|
|
audio_effect_library_t symbol{};
|
|
void* effectLib = dlopen("libspatialaudio.so", RTLD_NOW);
|
|
if (effectLib) {
|
|
audio_effect_library_t* effectInterface =
|
|
(audio_effect_library_t*)dlsym(effectLib, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
|
|
if (effectInterface == nullptr) {
|
|
ALOGE("dlsym failed: %s", dlerror());
|
|
exit(-1);
|
|
}
|
|
symbol = (audio_effect_library_t)(*effectInterface);
|
|
} else {
|
|
ALOGE("dlopen failed: %s", dlerror());
|
|
exit(-1);
|
|
}
|
|
return symbol;
|
|
}();
|
|
|
|
// channel masks
|
|
constexpr int kInputChMask = AUDIO_CHANNEL_OUT_5POINT1;
|
|
|
|
// sampleRates
|
|
constexpr size_t kSampleRates[] = {
|
|
44100,
|
|
48000,
|
|
96000,
|
|
};
|
|
constexpr size_t kNumSampleRates = std::size(kSampleRates);
|
|
|
|
// duration in ms
|
|
constexpr size_t kDurations[] = {2, 5, 10};
|
|
constexpr size_t kNumDurations = std::size(kDurations);
|
|
|
|
// effect uuids
|
|
constexpr effect_uuid_t kEffectUuid = {
|
|
0xcc4677de, 0xff72, 0x11eb, 0x9a03, {0x02, 0x42, 0xac, 0x13, 0x00, 0x03}};
|
|
|
|
constexpr float kMinAmplitude = -1.0f;
|
|
constexpr float kMaxAmplitude = 1.0f;
|
|
|
|
/*******************************************************************
|
|
* A test result running on Pixel 5 for comparison.
|
|
* The first parameter indicates the sample rate.
|
|
* 0: 44100, 1: 48000, 2: 96000
|
|
* The second parameter indicates the duration in ms.
|
|
* 0: 2, 1: 5, 2: 10
|
|
* -------------------------------------------------------------
|
|
* Benchmark Time CPU Iterations
|
|
* -------------------------------------------------------------
|
|
* BM_SPATIALIZER/0/0 739848 ns 738497 ns 934
|
|
* BM_SPATIALIZER/0/1 1250503 ns 1248337 ns 480
|
|
* BM_SPATIALIZER/0/2 2094092 ns 2090092 ns 310
|
|
* BM_SPATIALIZER/1/0 783114 ns 781626 ns 683
|
|
* BM_SPATIALIZER/1/1 1332951 ns 1330473 ns 452
|
|
* BM_SPATIALIZER/1/2 2258313 ns 2254022 ns 289
|
|
* BM_SPATIALIZER/2/0 1210332 ns 1207957 ns 477
|
|
* BM_SPATIALIZER/2/1 2356259 ns 2351764 ns 269
|
|
* BM_SPATIALIZER/2/2 4267814 ns 4259567 ns 155
|
|
*******************************************************************/
|
|
|
|
static void BM_SPATIALIZER(benchmark::State& state) {
|
|
const size_t sampleRate = kSampleRates[state.range(0)];
|
|
const size_t durationMs = kDurations[state.range(1)];
|
|
const size_t frameCount = durationMs * sampleRate / 1000;
|
|
const size_t inputChannelCount = audio_channel_count_from_out_mask(kInputChMask);
|
|
const size_t outputChannelCount = audio_channel_count_from_out_mask(AUDIO_CHANNEL_OUT_STEREO);
|
|
|
|
// Initialize input buffer with deterministic pseudo-random values
|
|
std::minstd_rand gen(kInputChMask);
|
|
std::uniform_real_distribution<> dis(kMinAmplitude, kMaxAmplitude);
|
|
std::vector<float> input(frameCount * inputChannelCount);
|
|
for (auto& in : input) {
|
|
in = dis(gen);
|
|
}
|
|
|
|
effect_handle_t effectHandle = nullptr;
|
|
if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&kEffectUuid, 1 /* sessionId */,
|
|
1 /* ioId */, &effectHandle);
|
|
status != 0) {
|
|
ALOGE("create_effect returned an error = %d\n", status);
|
|
return;
|
|
}
|
|
|
|
effect_config_t config{};
|
|
config.inputCfg.samplingRate = config.outputCfg.samplingRate = sampleRate;
|
|
config.inputCfg.channels = kInputChMask;
|
|
config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
|
|
config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
|
|
|
|
int reply = 0;
|
|
uint32_t replySize = sizeof(reply);
|
|
if (int status = (*effectHandle)
|
|
->command(effectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t),
|
|
&config, &replySize, &reply);
|
|
status != 0) {
|
|
ALOGE("command returned an error = %d\n", status);
|
|
return;
|
|
}
|
|
|
|
if (int status = (*effectHandle)
|
|
->command(effectHandle, EFFECT_CMD_ENABLE, sizeof(effect_config_t),
|
|
&config, &replySize, &reply);
|
|
status != 0) {
|
|
ALOGE("command returned an error = %d\n", status);
|
|
return;
|
|
}
|
|
|
|
// Run the test
|
|
std::vector<float> output(frameCount * outputChannelCount);
|
|
for (auto _ : state) {
|
|
benchmark::DoNotOptimize(input.data());
|
|
benchmark::DoNotOptimize(output.data());
|
|
|
|
audio_buffer_t inBuffer = {.frameCount = frameCount, .f32 = input.data()};
|
|
audio_buffer_t outBuffer = {.frameCount = frameCount, .f32 = output.data()};
|
|
(*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
|
|
|
|
benchmark::ClobberMemory();
|
|
}
|
|
|
|
state.SetComplexityN(frameCount);
|
|
|
|
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 SPATIALIZERArgs(benchmark::internal::Benchmark* b) {
|
|
for (int i = 0; i < kNumSampleRates; i++) {
|
|
for (int j = 0; j < kNumDurations; ++j) {
|
|
b->Args({i, j});
|
|
}
|
|
}
|
|
}
|
|
|
|
BENCHMARK(BM_SPATIALIZER)->Apply(SPATIALIZERArgs);
|
|
|
|
BENCHMARK_MAIN();
|