From f0f4c34ad8e52f2624b7db608d87c158d38aaee2 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Sun, 17 May 2020 21:42:57 +0200 Subject: [PATCH] Numbering of regions and voices --- src/sfizz/Region.h | 14 ++++++++++-- src/sfizz/Synth.cpp | 5 +++-- src/sfizz/Voice.cpp | 4 ++-- src/sfizz/Voice.h | 12 +++++++++- tests/RegionActivationT.cpp | 2 +- tests/RegionT.cpp | 4 ++-- tests/RegionTriggersT.cpp | 4 ++-- tests/RegionValueComputationsT.cpp | 36 +++++++++++++++--------------- 8 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/sfizz/Region.h b/src/sfizz/Region.h index 5ce49ff8..9b6e01b2 100644 --- a/src/sfizz/Region.h +++ b/src/sfizz/Region.h @@ -35,8 +35,8 @@ namespace sfz { * */ struct Region { - Region(const MidiState& midiState, absl::string_view defaultPath = "") - : midiState(midiState), defaultPath(std::move(defaultPath)) + Region(int regionNumber, const MidiState& midiState, absl::string_view defaultPath = "") + : regionNumber(regionNumber), midiState(midiState), defaultPath(std::move(defaultPath)) { ccSwitched.set(); @@ -46,6 +46,14 @@ struct Region { Region(const Region&) = default; ~Region() = default; + /** + * @brief Get the number which identifies this region, also its index + */ + int getIdNumber() const noexcept + { + return regionNumber; + } + /** * @brief Triggers on release? * @@ -238,6 +246,8 @@ struct Region { */ float getGainToEffectBus(unsigned number) const noexcept; + const int regionNumber {}; + // Sound source: sample playback FileId sampleId {}; // Sample int sampleQuality { Default::sampleQuality }; diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 2718a1e1..b46a18b6 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -95,7 +95,8 @@ void sfz::Synth::onParseWarning(const SourceRange& range, const std::string& mes void sfz::Synth::buildRegion(const std::vector& regionOpcodes) { - auto lastRegion = absl::make_unique(resources.midiState, defaultPath); + int regionNumber = static_cast(regions.size()); + auto lastRegion = absl::make_unique(regionNumber, resources.midiState, defaultPath); auto parseOpcodes = [&](const std::vector& opcodes) { for (auto& opcode : opcodes) { @@ -1094,7 +1095,7 @@ void sfz::Synth::resetVoices(int numVoices) voices.reserve(numVoices); for (int i = 0; i < numVoices; ++i) - voices.push_back(absl::make_unique(resources)); + voices.push_back(absl::make_unique(i, resources)); voiceViewArray.clear(); voiceViewArray.reserve(numVoices); diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 6ae90db2..2f3ebe05 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -14,8 +14,8 @@ #include "Interpolators.h" #include "absl/algorithm/container.h" -sfz::Voice::Voice(sfz::Resources& resources) -: resources(resources) +sfz::Voice::Voice(int voiceNumber, sfz::Resources& resources) +: voiceNumber(voiceNumber), resources(resources) { filters.reserve(config::filtersPerVoice); equalizers.reserve(config::eqsPerVoice); diff --git a/src/sfizz/Voice.h b/src/sfizz/Voice.h index a709eb58..0c7937c7 100644 --- a/src/sfizz/Voice.h +++ b/src/sfizz/Voice.h @@ -32,14 +32,22 @@ public: /** * @brief Construct a new voice with the midistate singleton * + * @param voiceNumber * @param midiState */ - Voice(Resources& resources); + Voice(int voiceNumber, Resources& resources); enum class TriggerType { NoteOn, NoteOff, CC }; + /** + * @brief Get the number which identifies this voice, its index + */ + int getIdNumber() const noexcept + { + return voiceNumber; + } /** * @brief Change the sample rate of the voice. This is used to compute all * pitch related transformations so it needs to be propagated from the synth @@ -270,6 +278,8 @@ private: void setupOscillatorUnison(); void updateChannelPowers(AudioSpan buffer); + const int voiceNumber {}; + Region* region { nullptr }; enum class State { diff --git a/tests/RegionActivationT.cpp b/tests/RegionActivationT.cpp index e65934b7..41990934 100644 --- a/tests/RegionActivationT.cpp +++ b/tests/RegionActivationT.cpp @@ -13,7 +13,7 @@ using namespace sfz::literals; TEST_CASE("Region activation", "Region tests") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); SECTION("Basic state") diff --git a/tests/RegionT.cpp b/tests/RegionT.cpp index db2c9511..c683cd96 100644 --- a/tests/RegionT.cpp +++ b/tests/RegionT.cpp @@ -14,7 +14,7 @@ using namespace sfz::literals; TEST_CASE("[Region] Parsing opcodes") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; SECTION("sample") { @@ -1672,7 +1672,7 @@ TEST_CASE("[Region] Parsing opcodes") TEST_CASE("[Region] Non-conforming floating point values in integer opcodes") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "offset", "2014.5" }); REQUIRE(region.offset == 2014); region.parseOpcode({ "pitch_keytrack", "-2.1" }); diff --git a/tests/RegionTriggersT.cpp b/tests/RegionTriggersT.cpp index 75f5d9b5..4ee56cde 100644 --- a/tests/RegionTriggersT.cpp +++ b/tests/RegionTriggersT.cpp @@ -13,7 +13,7 @@ using namespace sfz::literals; TEST_CASE("Basic triggers", "Region triggers") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); SECTION("key") @@ -130,7 +130,7 @@ TEST_CASE("Basic triggers", "Region triggers") TEST_CASE("Legato triggers", "Region triggers") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); SECTION("First note playing") { diff --git a/tests/RegionValueComputationsT.cpp b/tests/RegionValueComputationsT.cpp index e6547b01..50deb231 100644 --- a/tests/RegionValueComputationsT.cpp +++ b/tests/RegionValueComputationsT.cpp @@ -17,7 +17,7 @@ constexpr int numRandomTests { 64 }; TEST_CASE("[Region] Crossfade in on key") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_lokey", "1" }); region.parseOpcode({ "xfin_hikey", "3" }); @@ -29,7 +29,7 @@ TEST_CASE("[Region] Crossfade in on key") TEST_CASE("[Region] Crossfade in on key - 2") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_lokey", "1" }); region.parseOpcode({ "xfin_hikey", "5" }); @@ -44,7 +44,7 @@ TEST_CASE("[Region] Crossfade in on key - 2") TEST_CASE("[Region] Crossfade in on key - gain") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_lokey", "1" }); region.parseOpcode({ "xfin_hikey", "5" }); @@ -59,7 +59,7 @@ TEST_CASE("[Region] Crossfade in on key - gain") TEST_CASE("[Region] Crossfade out on key") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_lokey", "51" }); region.parseOpcode({ "xfout_hikey", "55" }); @@ -75,7 +75,7 @@ TEST_CASE("[Region] Crossfade out on key") TEST_CASE("[Region] Crossfade out on key - gain") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_lokey", "51" }); region.parseOpcode({ "xfout_hikey", "55" }); @@ -92,7 +92,7 @@ TEST_CASE("[Region] Crossfade out on key - gain") TEST_CASE("[Region] Crossfade in on velocity") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_lovel", "20" }); region.parseOpcode({ "xfin_hivel", "24" }); @@ -109,7 +109,7 @@ TEST_CASE("[Region] Crossfade in on velocity") TEST_CASE("[Region] Crossfade in on vel - gain") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_lovel", "20" }); region.parseOpcode({ "xfin_hivel", "24" }); @@ -127,7 +127,7 @@ TEST_CASE("[Region] Crossfade in on vel - gain") TEST_CASE("[Region] Crossfade out on vel") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_lovel", "51" }); region.parseOpcode({ "xfout_hivel", "55" }); @@ -144,7 +144,7 @@ TEST_CASE("[Region] Crossfade out on vel") TEST_CASE("[Region] Crossfade out on vel - gain") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_lovel", "51" }); region.parseOpcode({ "xfout_hivel", "55" }); @@ -162,7 +162,7 @@ TEST_CASE("[Region] Crossfade out on vel - gain") TEST_CASE("[Region] Crossfade in on CC") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_locc24", "20" }); region.parseOpcode({ "xfin_hicc24", "24" }); @@ -186,7 +186,7 @@ TEST_CASE("[Region] Crossfade in on CC") TEST_CASE("[Region] Crossfade in on CC - gain") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_locc24", "20" }); region.parseOpcode({ "xfin_hicc24", "24" }); @@ -210,7 +210,7 @@ TEST_CASE("[Region] Crossfade in on CC - gain") TEST_CASE("[Region] Crossfade out on CC") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_locc24", "20" }); region.parseOpcode({ "xfout_hicc24", "24" }); @@ -234,7 +234,7 @@ TEST_CASE("[Region] Crossfade out on CC") TEST_CASE("[Region] Crossfade out on CC - gain") { sfz::MidiState midiState; - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_locc24", "20" }); region.parseOpcode({ "xfout_hicc24", "24" }); @@ -259,7 +259,7 @@ 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 { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "amp_veltrack", "0" }); REQUIRE(region.getNoteGain(64, 127_norm) == 1.0_a); @@ -270,7 +270,7 @@ 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 { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "amp_veltrack", "100" }); REQUIRE(region.getNoteGain(64, 127_norm) == 1.0_a); @@ -280,7 +280,7 @@ 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 { midiState }; + sfz::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)); @@ -291,7 +291,7 @@ TEST_CASE("[Region] rt_decay") { sfz::MidiState midiState; midiState.setSampleRate(1000); - sfz::Region region { midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "trigger", "release" }); region.parseOpcode({ "rt_decay", "10" }); @@ -311,7 +311,7 @@ TEST_CASE("[Region] rt_decay") TEST_CASE("[Region] Base delay") { sfz::MidiState midiState; - sfz::Region region{ midiState }; + sfz::Region region { 0, midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "delay", "10" }); REQUIRE( region.getDelay() == 10.0f );