@@ -7,6 +7,7 @@ add_executable(sonus-test
|
||||
test.cpp
|
||||
render_snapshot.cpp
|
||||
control.cpp
|
||||
sequence.cpp
|
||||
)
|
||||
find_package(Threads REQUIRED)
|
||||
target_include_directories(sonus-test PRIVATE
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <thread>
|
||||
|
||||
#include <sonus.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
auto fixture() -> sonus::sample_sequence {
|
||||
return {.samples = {{.sample_rate = 48000U, .frames = {0.1F, 0.2F, 0.3F, 0.4F}, .loop_start = 2U, .loop_end = 4U}},
|
||||
.events = {{.sample = 0U, .start_frame = 2U, .duration_frames = 6U}},
|
||||
.release_envelope = {1.0F, 0.5F, 0.0F},
|
||||
.duration_frames = 12U,
|
||||
.max_voices = 2U,
|
||||
.gain = 1.0F};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sequence_sample_clock_and_completion) {
|
||||
auto engine = sonus::engine::create({.sample_rate = 48000U, .channels = 1U, .master_volume = 1.0F, .no_device = true});
|
||||
BOOST_REQUIRE(engine);
|
||||
auto session = engine->play_sequence(fixture());
|
||||
BOOST_REQUIRE(session);
|
||||
auto output = std::array<std::float32_t, 12>{};
|
||||
BOOST_REQUIRE(engine->render(output.data(), output.size()));
|
||||
auto expected = std::array<std::float32_t, 12>{0.0F, 0.0F, 0.1F, 0.2F, 0.3F, 0.4F, 0.3F, 0.4F, 0.3F, 0.2F, 0.0F, 0.0F};
|
||||
BOOST_TEST(output == expected, boost::test_tools::per_element());
|
||||
BOOST_CHECK(session->status() == sonus::playback_status::COMPLETED);
|
||||
engine->collect_finished();
|
||||
BOOST_CHECK(session->status() == sonus::playback_status::COMPLETED);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sequence_cancel_replace_and_independent_unisons) {
|
||||
auto engine = sonus::engine::create({.channels = 1U, .master_volume = 1.0F, .no_device = true});
|
||||
BOOST_REQUIRE(engine);
|
||||
auto value = fixture();
|
||||
value.events.push_back({.sample = 0U, .start_frame = 2U, .duration_frames = 2U});
|
||||
auto first = engine->play_sequence(value);
|
||||
BOOST_REQUIRE(first);
|
||||
auto output = std::array<std::float32_t, 4>{};
|
||||
BOOST_REQUIRE(engine->render(output.data(), output.size()));
|
||||
BOOST_TEST(output[2] == 0.2F);
|
||||
auto second = engine->play_sequence(value);
|
||||
BOOST_REQUIRE(second);
|
||||
BOOST_CHECK(first->status() == sonus::playback_status::STOPPED);
|
||||
second->stop();
|
||||
BOOST_REQUIRE(engine->render(output.data(), output.size()));
|
||||
BOOST_TEST(output[2] == 0.0F);
|
||||
BOOST_CHECK(second->status() == sonus::playback_status::STOPPED);
|
||||
value.max_voices = 1U;
|
||||
BOOST_CHECK(!engine->play_sequence(value));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sequence_concurrent_control) {
|
||||
auto engine = sonus::engine::create({.channels = 1U, .no_device = true});
|
||||
BOOST_REQUIRE(engine);
|
||||
auto render = std::thread{[&] {
|
||||
auto output = std::array<std::float32_t, 128>{};
|
||||
for (auto i = std::uint32_t{}; i < 1000U; ++i) {
|
||||
static_cast<void>(engine->render(output.data(), output.size()));
|
||||
}
|
||||
}};
|
||||
for (auto i = std::uint32_t{}; i < 1000U; ++i) {
|
||||
auto session = engine->play_sequence(fixture());
|
||||
if (session) {
|
||||
session->stop();
|
||||
}
|
||||
engine->collect_finished();
|
||||
}
|
||||
render.join();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sequence_preparation_is_single_use_and_rate_checked) {
|
||||
auto prepared = sonus::prepared_sequence::create(fixture(), 48000U);
|
||||
BOOST_REQUIRE(prepared);
|
||||
auto engine = sonus::engine::create({.channels = 1U, .master_volume = 1.0F, .no_device = true});
|
||||
BOOST_REQUIRE(engine);
|
||||
auto session = engine->play_sequence(std::move(*prepared));
|
||||
BOOST_REQUIRE(session);
|
||||
BOOST_CHECK(!engine->play_sequence(std::move(*prepared)));
|
||||
auto output = std::array<std::float32_t, 12>{};
|
||||
for (auto i = std::size_t{}; i < output.size(); ++i) {
|
||||
BOOST_REQUIRE(engine->render(output.data() + i, 1U));
|
||||
}
|
||||
BOOST_TEST(output[8] == 0.3F);
|
||||
BOOST_CHECK(session->status() == sonus::playback_status::COMPLETED);
|
||||
auto invalid = fixture();
|
||||
invalid.samples[0].loop_end = 0U;
|
||||
BOOST_CHECK(!sonus::prepared_sequence::create(invalid, 48000U));
|
||||
BOOST_CHECK(!sonus::prepared_sequence::create(fixture(), 44100U));
|
||||
auto silent = fixture();
|
||||
silent.samples.clear();
|
||||
silent.events.clear();
|
||||
auto quiet = engine->play_sequence(std::move(silent));
|
||||
BOOST_REQUIRE(quiet);
|
||||
BOOST_REQUIRE(engine->render(output.data(), output.size()));
|
||||
BOOST_CHECK(quiet->status() == sonus::playback_status::COMPLETED);
|
||||
for (auto value : output) {
|
||||
BOOST_TEST(value == 0.0F);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user