sfizz/tests/ModulationsT.cpp

127 lines
3.6 KiB
C++
Raw Normal View History

2020-07-26 19:25:59 +02:00
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "sfizz/modulations/ModId.h"
#include "sfizz/modulations/ModKey.h"
2020-07-28 22:59:59 +02:00
#include "sfizz/Synth.h"
2020-07-26 19:25:59 +02:00
#include "catch2/catch.hpp"
TEST_CASE("[Modulations] Identifiers")
{
// check that modulations are well defined as either source and target
// and all targets have their default value defined
sfz::ModIds::forEachSourceId([](sfz::ModId id)
{
REQUIRE(sfz::ModIds::isSource(id));
REQUIRE(!sfz::ModIds::isTarget(id));
});
sfz::ModIds::forEachTargetId([](sfz::ModId id)
{
REQUIRE(sfz::ModIds::isTarget(id));
REQUIRE(!sfz::ModIds::isSource(id));
});
}
TEST_CASE("[Modulations] Flags")
{
// check validity of modulation flags
static auto* checkBasicFlags = +[](int flags)
{
REQUIRE(flags != sfz::kModFlagsInvalid);
2020-07-30 13:48:07 +02:00
REQUIRE((bool(flags & sfz::kModIsPerCycle) +
bool(flags & sfz::kModIsPerVoice)) == 1);
2020-07-26 19:25:59 +02:00
};
static auto* checkSourceFlags = +[](int flags)
{
checkBasicFlags(flags);
2020-07-30 13:48:07 +02:00
REQUIRE((bool(flags & sfz::kModIsAdditive) +
bool(flags & sfz::kModIsMultiplicative) +
bool(flags & sfz::kModIsPercentMultiplicative)) == 0);
2020-07-26 19:25:59 +02:00
};
static auto* checkTargetFlags = +[](int flags)
{
checkBasicFlags(flags);
2020-07-30 13:48:07 +02:00
REQUIRE((bool(flags & sfz::kModIsAdditive) +
bool(flags & sfz::kModIsMultiplicative) +
bool(flags & sfz::kModIsPercentMultiplicative)) == 1);
2020-07-26 19:25:59 +02:00
};
sfz::ModIds::forEachSourceId([](sfz::ModId id)
{
checkSourceFlags(sfz::ModIds::flags(id));
});
sfz::ModIds::forEachTargetId([](sfz::ModId id)
{
checkTargetFlags(sfz::ModIds::flags(id));
});
}
TEST_CASE("[Modulations] Display names")
{
// check all modulations are implemented in `toString`
sfz::ModIds::forEachSourceId([](sfz::ModId id)
{
REQUIRE(!sfz::ModKey(id).toString().empty());
});
sfz::ModIds::forEachTargetId([](sfz::ModId id)
{
REQUIRE(!sfz::ModKey(id).toString().empty());
});
}
2020-07-28 22:59:59 +02:00
2020-08-19 07:07:37 +02:00
static std::string createReferenceGraph(std::vector<std::string> lines)
{
const char* defaultConnections[] = {
R"("Controller 7 {curve=4, smooth=10, value=100, step=0}" -> "Amplitude")",
R"("Controller 10 {curve=1, smooth=10, value=100, step=0}" -> "Pan")"
};
for (const char* line : defaultConnections)
lines.push_back(line);
std::sort(lines.begin(), lines.end());
std::string graph;
graph.reserve(1024);
graph += "digraph {\n";
for (const std::string& line : lines) {
graph.push_back('\t');
graph += line;
graph.push_back('\n');
}
graph += "}\n";
return graph;
};
2020-07-28 22:59:59 +02:00
TEST_CASE("[Modulations] Connection graph from SFZ")
{
sfz::Synth synth;
synth.loadSfzString("/modulation.sfz", R"(
<region>
sample=*sine
amplitude_oncc20=59 amplitude_curvecc20=3
pitch_oncc42=71 pitch_smoothcc42=32
pan_oncc36=14.5 pan_stepcc36=1.5
width_oncc425=29
)");
2020-08-19 07:07:37 +02:00
2020-07-28 22:59:59 +02:00
const std::string graph = synth.getResources().modMatrix.toDotGraph();
2020-08-19 07:07:37 +02:00
REQUIRE(graph == createReferenceGraph({
R"("Controller 20 {curve=3, smooth=0, value=59, step=0}" -> "Amplitude")",
R"("Controller 42 {curve=0, smooth=32, value=71, step=0}" -> "Pitch")",
R"("Controller 36 {curve=0, smooth=0, value=14.5, step=1.5}" -> "Pan")",
R"("Controller 425 {curve=0, smooth=0, value=29, step=0}" -> "Width")",
}));
2020-07-28 22:59:59 +02:00
}