Utilites: Add abench utility

abench (audio benchmark) is an audio benchmarking utility that allows
testing decoder performance.
This commit is contained in:
kleines Filmröllchen 2021-11-27 17:00:49 +01:00 committed by Brian Gianforcaro
parent 96d02a3e75
commit 9c40311622
Notes: sideshowbarker 2024-07-18 00:34:00 +09:00
2 changed files with 74 additions and 1 deletions

View file

@ -7,7 +7,7 @@ list(APPEND REQUIRED_TARGETS
touch tr true umount uname uniq uptime w wc which whoami xargs yes less
)
list(APPEND RECOMMENDED_TARGETS
adjtime aplay asctl bt checksum chres cksum copy fortune gunzip gzip init keymap lsirq lsof lspci man mknod mktemp
adjtime aplay abench asctl bt checksum chres cksum copy fortune gunzip gzip init keymap lsirq lsof lspci man mknod mktemp
modload modunload nc netstat notify ntpquery open pape passwd pls printf pro shot tar tt unzip zip
)
@ -54,6 +54,7 @@ endforeach()
target_link_libraries(allocate LibMain)
target_link_libraries(aplay LibAudio LibMain)
target_link_libraries(arp LibMain)
target_link_libraries(abench LibAudio LibMain LibCore)
target_link_libraries(asctl LibAudio LibMain)
target_link_libraries(base64 LibMain)
target_link_libraries(basename LibMain)

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2021, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/NumericLimits.h>
#include <AK/Types.h>
#include <LibAudio/Loader.h>
#include <LibCore/ArgsParser.h>
#include <LibCore/ElapsedTimer.h>
#include <LibCore/File.h>
#include <LibCore/System.h>
#include <LibMain/Main.h>
#include <stdio.h>
// The Kernel has problems with large anonymous buffers, so let's limit sample reads ourselves.
static constexpr size_t MAX_CHUNK_SIZE = 1 * MiB / 2;
ErrorOr<int> serenity_main(Main::Arguments args)
{
char const* path = nullptr;
int sample_count = -1;
Core::ArgsParser args_parser;
args_parser.set_general_help("Benchmark audio loading");
args_parser.add_positional_argument(path, "Path to audio file", "path");
args_parser.add_option(sample_count, "How many samples to load at maximum", "sample-count", 's', "samples");
args_parser.parse(args);
TRY(Core::System::unveil(Core::File::absolute_path(path), "r"));
TRY(Core::System::unveil(nullptr, nullptr));
TRY(Core::System::pledge("stdio recvfd rpath", nullptr));
auto maybe_loader = Audio::Loader::create(path);
if (maybe_loader.is_error()) {
warnln("Failed to load audio file: {}", maybe_loader.error().description);
return 1;
}
auto loader = maybe_loader.release_value();
Core::ElapsedTimer sample_timer { true };
u64 total_loader_time = 0;
int remaining_samples = sample_count > 0 ? sample_count : NumericLimits<int>::max();
unsigned total_loaded_samples = 0;
for (;;) {
if (remaining_samples > 0) {
sample_timer = sample_timer.start_new();
auto samples = loader->get_more_samples(min(MAX_CHUNK_SIZE, remaining_samples));
auto elapsed = static_cast<u64>(sample_timer.elapsed());
total_loader_time += static_cast<u64>(elapsed);
if (!samples.is_error()) {
remaining_samples -= samples.value()->sample_count();
total_loaded_samples += samples.value()->sample_count();
if (samples.value()->sample_count() == 0)
break;
} else {
warnln("Error while loading audio: {}", samples.error().description);
return 1;
}
} else
break;
}
auto time_per_sample = static_cast<double>(total_loader_time) / static_cast<double>(total_loaded_samples) * 1000.;
auto playback_time_per_sample = (1. / static_cast<double>(loader->sample_rate())) * 1000'000.;
outln("Loaded {:10d} samples in {:06.3f} s, {:9.3f} µs/sample, {:6.1f}% speed (realtime {:9.3f} µs/sample)", total_loaded_samples, static_cast<double>(total_loader_time) / 1000., time_per_sample, playback_time_per_sample / time_per_sample * 100., playback_time_per_sample);
return 0;
}