Added benchmarks and tests for AudioBuffers

This commit is contained in:
Paul Ferrand 2019-07-30 01:04:12 +02:00
parent 7773ef81bc
commit 32aaa6b917
8 changed files with 142 additions and 10 deletions

3
.gitmodules vendored
View file

@ -10,3 +10,6 @@
[submodule "external/cxxopts"]
path = external/cxxopts
url = https://github.com/jarro2783/cxxopts
[submodule "external/benchmark"]
path = external/benchmark
url = https://github.com/google/benchmark

View file

@ -6,8 +6,6 @@ project(sfizz VERSION 1.0.0 LANGUAGES CXX)
# Set the highest possible standard
set(CMAKE_CXX_STANDARD 17)
# Disable Abseil tests
set(BUILD_TESTING OFF)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT ANDROID)
add_compile_options(-stdlib=libc++)
@ -15,11 +13,19 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT ANDROID)
add_link_options(-stdlib=libc++) # New command on CMake master, not in 3.12 release
endif()
# Disable Abseil tests
set(BUILD_TESTING OFF)
add_subdirectory(external/abseil-cpp)
add_subdirectory(external/spdlog)
add_subdirectory(external/Catch2)
add_subdirectory(external/cxxopts)
#Disable Benchmark tests and installation
set(BENCHMARK_ENABLE_TESTING OFF)
set(BENCHMARK_ENABLE_INSTALL OFF)
set(BENCHMARK_ENABLE_GTEST_TESTS OFF)
add_subdirectory(external/benchmark)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(COMMON_SOURCES
@ -31,10 +37,6 @@ set(COMMON_SOURCES
)
set(TEST_SOURCES
sources/Opcode.cpp
sources/Synth.cpp
sources/Region.cpp
sources/Parser.cpp
tests/Regex.cpp
tests/Helpers.cpp
tests/Region.cpp
@ -46,6 +48,10 @@ set(TEST_SOURCES
tests/Main.cpp
)
set(BENCHMARK_SOURCES
benchmarks/Main.cpp
benchmarks/AudioBuffers.cpp
)
###############################
add_executable(sfzprint sources/ParserMain.cpp ${COMMON_SOURCES})
@ -74,4 +80,12 @@ target_link_libraries(sfizz_tests stdc++fs)
endif(UNIX)
target_link_libraries(sfizz_tests Catch2::Catch2 absl::strings)
target_include_directories(sfizz_tests SYSTEM PRIVATE sources)
file(COPY "tests" DESTINATION ${CMAKE_BINARY_DIR})
file(COPY "tests" DESTINATION ${CMAKE_BINARY_DIR})
###############################
add_executable(sfizz_bench ${BENCHMARK_SOURCES} ${COMMON_SOURCES})
# Per OS properties
if(UNIX)
target_link_libraries(sfizz_bench stdc++fs)
endif(UNIX)
target_link_libraries(sfizz_bench absl::strings benchmark)

View file

@ -0,0 +1,49 @@
#include <benchmark/benchmark.h>
#include "../sources/AudioBuffer.h"
#include <algorithm>
static void AB_Joint_Fill_float(benchmark::State& state) {
AudioBuffer<float> buffer (65535);
float fillValue = 0.0f;
for (auto _ : state) {
std::fill(buffer.begin(0), buffer.end(0), fillValue);
std::fill(buffer.begin(1), buffer.end(1), fillValue);
fillValue += 1.0f;
}
}
// Register the function as a benchmark
BENCHMARK(AB_Joint_Fill_float);
static void AB_Split_Fill_float(benchmark::State& state) {
SplitAudioBuffer<float> buffer (65535);
float fillValue = 0.0f;
for (auto _ : state) {
std::fill(buffer.begin(0), buffer.end(0), fillValue);
std::fill(buffer.begin(1), buffer.end(1), fillValue);
fillValue += 1.0f;
}
}
BENCHMARK(AB_Split_Fill_float);
static void AB_Joint_Fill_double(benchmark::State& state) {
AudioBuffer<double> buffer (65535);
double fillValue = 0.0;
for (auto _ : state) {
std::fill(buffer.begin(0), buffer.end(0), fillValue);
std::fill(buffer.begin(1), buffer.end(1), fillValue);
fillValue += 1.0;
}
}
// Register the function as a benchmark
BENCHMARK(AB_Joint_Fill_double);
static void AB_Split_Fill_double(benchmark::State& state) {
SplitAudioBuffer<double> buffer (65535);
double fillValue = 0.0;
for (auto _ : state) {
std::fill(buffer.begin(0), buffer.end(0), fillValue);
std::fill(buffer.begin(1), buffer.end(1), fillValue);
fillValue += 1.0;
}
}
BENCHMARK(AB_Split_Fill_double);

3
benchmarks/Main.cpp Normal file
View file

@ -0,0 +1,3 @@
#include <benchmark/benchmark.h>
BENCHMARK_MAIN();

1
external/benchmark vendored Submodule

@ -0,0 +1 @@
Subproject commit 66482d538d6c6041b29ab6a95cf5b6d561fbd306

View file

@ -44,6 +44,30 @@ public:
return nullptr;
}
Type* begin(int channelIndex) noexcept
{
ASSERT(channelIndex >= 0);
return buffer.data() + numFrames * channelIndex;
}
Type* end(int channelIndex) noexcept
{
ASSERT(channelIndex >= 0);
return buffer.data() + numFrames * (channelIndex + 1);
}
// const Type* cbegin(int channelIndex) noexcept
// {
// ASSERT(channelIndex >= 0);
// return buffer.data() + numFrames * channelIndex;
// }
// const Type* cend(int channelIndex) noexcept
// {
// ASSERT(channelIndex >= 0);
// return buffer.data() + numFrames * (channelIndex + 1);
// }
Type& operator()(int channelIndex, int sampleIndex) noexcept
{
return getSample(channelIndex, sampleIndex);
@ -99,13 +123,32 @@ public:
Type* getChannel(int channelIndex) noexcept
{
ASSERT(channelIndex >= 0);
if (channelIndex < NumChannels)
return &buffers[channelIndex].data();
else
return nullptr;
}
Type* begin(int channelIndex) noexcept
{
return buffers[channelIndex].begin();
}
Type* end(int channelIndex) noexcept
{
return buffers[channelIndex].end();
}
// const Type* cbegin(int channelIndex) noexcept
// {
// return buffers[channelIndex].cbegin();
// }
// const Type* cend(int channelIndex) noexcept
// {
// return buffers[channelIndex].cend();
// }
int getNumFrames() const noexcept { return numFrames; }
int getNumChannels() const noexcept { return NumChannels; }
bool empty() const noexcept { return numFrames == 0; }

View file

@ -54,8 +54,8 @@ public:
Type* begin() noexcept { return data(); }
Type* end() noexcept { return data() + alignedSize; }
const Type* cbegin() const noexcept { return data(); }
const Type* cend() const noexcept { return data() + alignedSize; }
// const Type* cbegin() const noexcept { return data(); }
// const Type* cend() const noexcept { return data() + alignedSize; }
private:
size_t largerSize { 0 };
size_t alignedSize { 0 };

View file

@ -91,4 +91,23 @@ TEST_CASE("[AudioBuffer/SplitBuffer] Access 2")
for (auto chanIdx = 0; chanIdx < splitDoubleBuffer.getNumChannels(); ++chanIdx)
for (auto frameIdx = 0; frameIdx < splitDoubleBuffer.getNumFrames(); ++frameIdx)
REQUIRE(splitDoubleBuffer(chanIdx, frameIdx) == static_cast<int>(splitDoubleBuffer.getNumFrames()) * chanIdx + frameIdx);
}
TEST_CASE("[AudioBuffer/SplitBuffer] Iterators")
{
const int size { 256 };
const float fillValue { 2.0f };
AudioBuffer<float> buffer(size);
for (auto chanIdx = 0; chanIdx < buffer.getNumChannels(); ++chanIdx)
std::fill(buffer.begin(chanIdx), buffer.end(chanIdx), fillValue);
for (auto chanIdx = 0; chanIdx < buffer.getNumChannels(); ++chanIdx)
REQUIRE( std::all_of(buffer.begin(chanIdx), buffer.end(chanIdx), [fillValue](auto value) { return value == fillValue; }) );
SplitAudioBuffer<float> splitBuffer(size);
for (auto chanIdx = 0; chanIdx < splitBuffer.getNumChannels(); ++chanIdx)
std::fill(splitBuffer.begin(chanIdx), splitBuffer.end(chanIdx), fillValue);
for (auto chanIdx = 0; chanIdx < splitBuffer.getNumChannels(); ++chanIdx)
REQUIRE( std::all_of(splitBuffer.begin(chanIdx), splitBuffer.end(chanIdx), [fillValue](auto value) { return value == fillValue; }) );
}