Initial
This commit is contained in:
parent
31103d11a2
commit
171a5e5083
14 changed files with 4390 additions and 1946 deletions
|
|
@ -144,9 +144,9 @@ public:
|
|||
#ifndef NDEBUG
|
||||
~BufferPool()
|
||||
{
|
||||
DBG("Max buffers used: " << maxBuffersUsed);
|
||||
DBG("Max index buffers used: " << maxIndexBuffersUsed);
|
||||
DBG("Max stereo buffers used: " << maxStereoBuffersUsed);
|
||||
// DBG("Max buffers used: " << maxBuffersUsed);
|
||||
// DBG("Max index buffers used: " << maxIndexBuffersUsed);
|
||||
// DBG("Max stereo buffers used: " << maxStereoBuffersUsed);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "SfzHelpers.h"
|
||||
#include <vector>
|
||||
#include <absl/algorithm/container.h>
|
||||
#include <absl/types/optional.h>
|
||||
|
||||
namespace sfz {
|
||||
/**
|
||||
|
|
@ -57,6 +58,22 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the held object at the index, or a default value if not present
|
||||
*
|
||||
* @param index
|
||||
* @return const ValueType&
|
||||
*/
|
||||
absl::optional<ValueType> get(int index) const noexcept
|
||||
{
|
||||
auto it = absl::c_lower_bound(container, index, CCDataComparator<ValueType> {});
|
||||
if (it == container.end() || it->cc != index) {
|
||||
return {};
|
||||
} else {
|
||||
return it->data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value at index or emplace a new one if not present
|
||||
*
|
||||
|
|
|
|||
|
|
@ -207,8 +207,8 @@ namespace Default
|
|||
constexpr Range<int> pitchVeltrackRange { -12000, 12000 };
|
||||
constexpr int transpose { 0 };
|
||||
constexpr Range<int> transposeRange { -127, 127 };
|
||||
constexpr int tune { 0 };
|
||||
constexpr Range<int> tuneRange { -12000, 12000 }; // ±100 in SFZv1, more in ARIA
|
||||
constexpr float tune { 0 };
|
||||
constexpr Range<float> tuneRange { -12000, 12000 }; // ±100 in SFZv1, more in ARIA
|
||||
constexpr Range<float> tuneCCRange { -12000, 12000 };
|
||||
constexpr Range<int> bendBoundRange { -12000, 12000 };
|
||||
constexpr Range<int> bendStepRange { 1, 1200 };
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ public:
|
|||
private:
|
||||
template <char Tag>
|
||||
sfizz_arg_t make_arg(OscDecayedType<Tag> value);
|
||||
|
||||
private:
|
||||
void* data_ = nullptr;
|
||||
sfizz_receive_t* receive_ = nullptr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ inline void Client::receive(int delay, const char* path, OscDecayedType<Sig>...
|
|||
typedef struct Nothing {} type; \
|
||||
typedef type decayed_type; \
|
||||
static inline sfizz_arg_t make_arg(decayed_type v) { \
|
||||
sfizz_arg_t a; (void)v; return a; \
|
||||
sfizz_arg_t a {}; (void)v; return a; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1936,3 +1936,31 @@ bool sfz::Region::disabled() const noexcept
|
|||
{
|
||||
return (sampleEnd == 0);
|
||||
}
|
||||
|
||||
absl::optional<float> sfz::Region::ccModDepth(int cc, ModId id) const noexcept
|
||||
{
|
||||
const ModKey target = ModKey::createNXYZ(id, getId());
|
||||
for (const sfz::Region::Connection& conn : connections) {
|
||||
if (conn.source.id() == sfz::ModId::Controller && conn.target == target) {
|
||||
auto p = conn.source.parameters();
|
||||
if (p.cc == cc)
|
||||
return conn.sourceDepth;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
absl::optional<sfz::ModKey::Parameters> sfz::Region::ccModParameters(int cc, ModId id) const noexcept
|
||||
{
|
||||
const ModKey target = ModKey::createNXYZ(id, getId());
|
||||
for (const sfz::Region::Connection& conn : connections) {
|
||||
if (conn.source.id() == sfz::ModId::Controller && conn.target == target) {
|
||||
auto p = conn.source.parameters();
|
||||
if (p.cc == cc)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -303,6 +303,24 @@ struct Region {
|
|||
*/
|
||||
bool disabled() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Extract the source depth modifier for a given cc and id.
|
||||
*
|
||||
* @param cc
|
||||
* @param id
|
||||
* @return absl::optional<float>
|
||||
*/
|
||||
absl::optional<float> ccModDepth(int cc, ModId id) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Extract the parameters for a given modulation cc and id.
|
||||
*
|
||||
* @param cc
|
||||
* @param id
|
||||
* @return float
|
||||
*/
|
||||
absl::optional<ModKey::Parameters> ccModParameters(int cc, ModId id) const noexcept;
|
||||
|
||||
const NumericId<Region> id;
|
||||
|
||||
// Sound source: sample playback
|
||||
|
|
@ -412,7 +430,7 @@ struct Region {
|
|||
float pitchRandom { Default::pitchRandom }; // pitch_random
|
||||
int pitchVeltrack { Default::pitchVeltrack }; // pitch_veltrack
|
||||
int transpose { Default::transpose }; // transpose
|
||||
int tune { Default::tune }; // tune
|
||||
float tune { Default::tune }; // tune
|
||||
int bendUp { Default::bendUp };
|
||||
int bendDown { Default::bendDown };
|
||||
int bendStep { Default::bendStep };
|
||||
|
|
|
|||
|
|
@ -676,7 +676,10 @@ void Synth::Impl::finalizeSfzLoad()
|
|||
|
||||
++currentRegionIndex;
|
||||
}
|
||||
DBG("Removing " << (regions_.size() - currentRegionCount) << " out of " << regions_.size() << " regions");
|
||||
if (currentRegionCount < regions_.size()) {
|
||||
DBG("Removing " << (regions_.size() - currentRegionCount)
|
||||
<< " out of " << regions_.size() << " regions");
|
||||
}
|
||||
regions_.resize(currentRegionCount);
|
||||
|
||||
// collect all CCs used in regions, with matrix not yet connected
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -4,7 +4,8 @@
|
|||
project(sfizz)
|
||||
|
||||
set(SFIZZ_TEST_SOURCES
|
||||
RegionT.cpp
|
||||
DirectRegionT.cpp
|
||||
RegionValuesT.cpp
|
||||
TestHelpers.h
|
||||
TestHelpers.cpp
|
||||
ParsingT.cpp
|
||||
|
|
|
|||
112
tests/DirectRegionT.cpp
Normal file
112
tests/DirectRegionT.cpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
// 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 "TestHelpers.h"
|
||||
#include "sfizz/MidiState.h"
|
||||
#include "sfizz/Region.h"
|
||||
#include "sfizz/SfzHelpers.h"
|
||||
#include "sfizz/modulations/ModId.h"
|
||||
#include "sfizz/modulations/ModKey.h"
|
||||
#include "catch2/catch.hpp"
|
||||
#include <stdexcept>
|
||||
using namespace Catch::literals;
|
||||
using namespace sfz::literals;
|
||||
using namespace sfz;
|
||||
|
||||
TEST_CASE("[Direct Region Tests] amp_velcurve")
|
||||
{
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "amp_velcurve_6", "0.4" });
|
||||
REQUIRE(region.velocityPoints.back() == std::pair<uint8_t, float>(6, 0.4f));
|
||||
region.parseOpcode({ "amp_velcurve_127", "-1.0" });
|
||||
REQUIRE(region.velocityPoints.back() == std::pair<uint8_t, float>(127, 0.0f));
|
||||
region.parseOpcode({ "amp_velcurve_008", "0.3" });
|
||||
REQUIRE(region.velocityPoints.back() == std::pair<uint8_t, float>(8, 0.3f));
|
||||
region.parseOpcode({ "amp_velcurve_064", "0.9" });
|
||||
REQUIRE(region.velocityPoints.back() == std::pair<uint8_t, float>(64, 0.9f));
|
||||
}
|
||||
|
||||
TEST_CASE("[Direct Region Tests] Release and release key")
|
||||
{
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "lokey", "63" });
|
||||
region.parseOpcode({ "hikey", "65" });
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
SECTION("Release key without sustain")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release_key" });
|
||||
midiState.ccEvent(0, 64, 0.0f);
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
REQUIRE( region.registerNoteOff(63, 0.5f, 0.0f) );
|
||||
}
|
||||
SECTION("Release key with sustain")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release_key" });
|
||||
midiState.ccEvent(0, 64, 1.0f);
|
||||
REQUIRE( !region.registerCC(64, 1.0f) );
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
REQUIRE( region.registerNoteOff(63, 0.5f, 0.0f) );
|
||||
}
|
||||
|
||||
SECTION("Release without sustain")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release" });
|
||||
midiState.ccEvent(0, 64, 0.0f);
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
REQUIRE( region.registerNoteOff(63, 0.5f, 0.0f) );
|
||||
}
|
||||
|
||||
SECTION("Release with sustain")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release" });
|
||||
midiState.ccEvent(0, 64, 1.0f);
|
||||
midiState.noteOnEvent(0, 63, 0.5f);
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
REQUIRE( !region.registerNoteOff(63, 0.5f, 0.0f) );
|
||||
REQUIRE( region.delayedReleases.size() == 1 );
|
||||
std::vector<std::pair<int, float>> expected = {
|
||||
{ 63, 0.5f }
|
||||
};
|
||||
REQUIRE( region.delayedReleases == expected );
|
||||
}
|
||||
|
||||
SECTION("Release with sustain and 2 notes")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release" });
|
||||
midiState.ccEvent(0, 64, 1.0f);
|
||||
midiState.noteOnEvent(0, 63, 0.5f);
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
midiState.noteOnEvent(0, 64, 0.6f);
|
||||
REQUIRE( !region.registerNoteOn(64, 0.6f, 0.0f) );
|
||||
REQUIRE( !region.registerNoteOff(63, 0.0f, 0.0f) );
|
||||
REQUIRE( !region.registerNoteOff(64, 0.2f, 0.0f) );
|
||||
REQUIRE( region.delayedReleases.size() == 2 );
|
||||
std::vector<std::pair<int, float>> expected = {
|
||||
{ 63, 0.5f },
|
||||
{ 64, 0.6f }
|
||||
};
|
||||
REQUIRE( region.delayedReleases == expected );
|
||||
}
|
||||
|
||||
SECTION("Release with sustain and 2 notes but 1 outside")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release" });
|
||||
midiState.ccEvent(0, 64, 1.0f);
|
||||
midiState.noteOnEvent(0, 63, 0.5f);
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
midiState.noteOnEvent(0, 66, 0.6f);
|
||||
REQUIRE( !region.registerNoteOn(66, 0.6f, 0.0f) );
|
||||
REQUIRE( !region.registerNoteOff(63, 0.0f, 0.0f) );
|
||||
REQUIRE( !region.registerNoteOff(66, 0.2f, 0.0f) );
|
||||
REQUIRE( region.delayedReleases.size() == 1 );
|
||||
std::vector<std::pair<int, float>> expected = {
|
||||
{ 63, 0.5f }
|
||||
};
|
||||
REQUIRE( region.delayedReleases == expected );
|
||||
}
|
||||
}
|
||||
1894
tests/RegionT.cpp
1894
tests/RegionT.cpp
File diff suppressed because it is too large
Load diff
|
|
@ -6,17 +6,20 @@
|
|||
|
||||
#include "sfizz/Defaults.h"
|
||||
#include "sfizz/Region.h"
|
||||
#include "sfizz/MidiState.h"
|
||||
#include "sfizz/SfzHelpers.h"
|
||||
#include "catch2/catch.hpp"
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
using namespace Catch::literals;
|
||||
using namespace sfz::literals;
|
||||
using namespace sfz;
|
||||
constexpr int numRandomTests { 64 };
|
||||
|
||||
TEST_CASE("[Region] Crossfade in on key")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfin_lokey", "1" });
|
||||
region.parseOpcode({ "xfin_hikey", "3" });
|
||||
|
|
@ -27,8 +30,8 @@ TEST_CASE("[Region] Crossfade in on key")
|
|||
|
||||
TEST_CASE("[Region] Crossfade in on key - 2")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfin_lokey", "1" });
|
||||
region.parseOpcode({ "xfin_hikey", "5" });
|
||||
|
|
@ -42,8 +45,8 @@ TEST_CASE("[Region] Crossfade in on key - 2")
|
|||
|
||||
TEST_CASE("[Region] Crossfade in on key - gain")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfin_lokey", "1" });
|
||||
region.parseOpcode({ "xfin_hikey", "5" });
|
||||
|
|
@ -57,8 +60,8 @@ TEST_CASE("[Region] Crossfade in on key - gain")
|
|||
|
||||
TEST_CASE("[Region] Crossfade out on key")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfout_lokey", "51" });
|
||||
region.parseOpcode({ "xfout_hikey", "55" });
|
||||
|
|
@ -73,8 +76,8 @@ TEST_CASE("[Region] Crossfade out on key")
|
|||
|
||||
TEST_CASE("[Region] Crossfade out on key - gain")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfout_lokey", "51" });
|
||||
region.parseOpcode({ "xfout_hikey", "55" });
|
||||
|
|
@ -90,8 +93,8 @@ TEST_CASE("[Region] Crossfade out on key - gain")
|
|||
|
||||
TEST_CASE("[Region] Crossfade in on velocity")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfin_lovel", "20" });
|
||||
region.parseOpcode({ "xfin_hivel", "24" });
|
||||
|
|
@ -107,8 +110,8 @@ TEST_CASE("[Region] Crossfade in on velocity")
|
|||
|
||||
TEST_CASE("[Region] Crossfade in on vel - gain")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfin_lovel", "20" });
|
||||
region.parseOpcode({ "xfin_hivel", "24" });
|
||||
|
|
@ -125,8 +128,8 @@ TEST_CASE("[Region] Crossfade in on vel - gain")
|
|||
|
||||
TEST_CASE("[Region] Crossfade out on vel")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfout_lovel", "51" });
|
||||
region.parseOpcode({ "xfout_hivel", "55" });
|
||||
|
|
@ -142,8 +145,8 @@ TEST_CASE("[Region] Crossfade out on vel")
|
|||
|
||||
TEST_CASE("[Region] Crossfade out on vel - gain")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfout_lovel", "51" });
|
||||
region.parseOpcode({ "xfout_hivel", "55" });
|
||||
|
|
@ -160,8 +163,8 @@ TEST_CASE("[Region] Crossfade out on vel - gain")
|
|||
|
||||
TEST_CASE("[Region] Crossfade in on CC")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfin_locc24", "20" });
|
||||
region.parseOpcode({ "xfin_hicc24", "24" });
|
||||
|
|
@ -184,8 +187,8 @@ TEST_CASE("[Region] Crossfade in on CC")
|
|||
|
||||
TEST_CASE("[Region] Crossfade in on CC - gain")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfin_locc24", "20" });
|
||||
region.parseOpcode({ "xfin_hicc24", "24" });
|
||||
|
|
@ -208,8 +211,8 @@ TEST_CASE("[Region] Crossfade in on CC - gain")
|
|||
}
|
||||
TEST_CASE("[Region] Crossfade out on CC")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfout_locc24", "20" });
|
||||
region.parseOpcode({ "xfout_hicc24", "24" });
|
||||
|
|
@ -232,8 +235,8 @@ TEST_CASE("[Region] Crossfade out on CC")
|
|||
|
||||
TEST_CASE("[Region] Crossfade out on CC - gain")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "xfout_locc24", "20" });
|
||||
region.parseOpcode({ "xfout_hicc24", "24" });
|
||||
|
|
@ -257,8 +260,8 @@ TEST_CASE("[Region] Crossfade out on CC - gain")
|
|||
|
||||
TEST_CASE("[Region] Velocity bug for extreme values - veltrack at 0")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "amp_veltrack", "0" });
|
||||
REQUIRE(region.getNoteGain(64, 127_norm) == 1.0_a);
|
||||
|
|
@ -268,8 +271,8 @@ TEST_CASE("[Region] Velocity bug for extreme values - veltrack at 0")
|
|||
|
||||
TEST_CASE("[Region] Velocity bug for extreme values - positive veltrack")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "amp_veltrack", "100" });
|
||||
REQUIRE(region.getNoteGain(64, 127_norm) == 1.0_a);
|
||||
|
|
@ -278,8 +281,8 @@ TEST_CASE("[Region] Velocity bug for extreme values - positive veltrack")
|
|||
|
||||
TEST_CASE("[Region] Velocity bug for extreme values - negative veltrack")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "amp_veltrack", "-100" });
|
||||
REQUIRE(region.getNoteGain(64, 127_norm) == Approx(0.0).margin(0.0001));
|
||||
|
|
@ -288,29 +291,29 @@ TEST_CASE("[Region] Velocity bug for extreme values - negative veltrack")
|
|||
|
||||
TEST_CASE("[Region] rt_decay")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
MidiState midiState;
|
||||
midiState.setSampleRate(1000);
|
||||
sfz::Region region { 0, midiState };
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "trigger", "release" });
|
||||
region.parseOpcode({ "rt_decay", "10" });
|
||||
midiState.noteOnEvent(0, 64, 64_norm);
|
||||
midiState.advanceTime(100);
|
||||
REQUIRE( region.getBaseVolumedB(64) == Approx(sfz::Default::volume - 1.0f).margin(0.1) );
|
||||
REQUIRE( region.getBaseVolumedB(64) == Approx(Default::volume - 1.0f).margin(0.1) );
|
||||
region.parseOpcode({ "rt_decay", "20" });
|
||||
midiState.noteOnEvent(0, 64, 64_norm);
|
||||
midiState.advanceTime(100);
|
||||
REQUIRE( region.getBaseVolumedB(64) == Approx(sfz::Default::volume - 2.0f).margin(0.1) );
|
||||
REQUIRE( region.getBaseVolumedB(64) == Approx(Default::volume - 2.0f).margin(0.1) );
|
||||
region.parseOpcode({ "trigger", "attack" });
|
||||
midiState.noteOnEvent(0, 64, 64_norm);
|
||||
midiState.advanceTime(100);
|
||||
REQUIRE( region.getBaseVolumedB(64) == Approx(sfz::Default::volume).margin(0.1) );
|
||||
REQUIRE( region.getBaseVolumedB(64) == Approx(Default::volume).margin(0.1) );
|
||||
}
|
||||
|
||||
TEST_CASE("[Region] Base delay")
|
||||
{
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region { 0, midiState };
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
region.parseOpcode({ "delay", "10" });
|
||||
REQUIRE( region.getDelay() == 10.0f );
|
||||
|
|
@ -322,3 +325,36 @@ TEST_CASE("[Region] Base delay")
|
|||
REQUIRE( (delay >= 10.0 && delay <= 20.0) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("[Region] Offsets with CCs")
|
||||
{
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
|
||||
region.parseOpcode({ "offset_cc4", "255" });
|
||||
region.parseOpcode({ "offset", "10" });
|
||||
REQUIRE( region.getOffset() == 10 );
|
||||
midiState.ccEvent(0, 4, 127_norm);
|
||||
REQUIRE( region.getOffset() == 265 );
|
||||
midiState.ccEvent(0, 4, 100_norm);
|
||||
REQUIRE( region.getOffset() == 210 );
|
||||
midiState.ccEvent(0, 4, 10_norm);
|
||||
REQUIRE( region.getOffset() == 30 );
|
||||
midiState.ccEvent(0, 4, 0);
|
||||
REQUIRE( region.getOffset() == 10 );
|
||||
}
|
||||
|
||||
TEST_CASE("[Region] Pitch variation with veltrack")
|
||||
{
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
|
||||
REQUIRE(region.getBasePitchVariation(60.0, 0_norm) == 1.0);
|
||||
REQUIRE(region.getBasePitchVariation(60.0, 64_norm) == 1.0);
|
||||
REQUIRE(region.getBasePitchVariation(60.0, 127_norm) == 1.0);
|
||||
region.parseOpcode({ "pitch_veltrack", "1200" });
|
||||
REQUIRE(region.getBasePitchVariation(60.0, 0_norm) == 1.0);
|
||||
REQUIRE(region.getBasePitchVariation(60.0, 64_norm) == Approx(centsFactor(600.0)).margin(0.01f));
|
||||
REQUIRE(region.getBasePitchVariation(60.0, 127_norm) == Approx(centsFactor(1200.0)).margin(0.01f));
|
||||
}
|
||||
|
||||
|
|
|
|||
3033
tests/RegionValuesT.cpp
Normal file
3033
tests/RegionValuesT.cpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue