Numbering of regions and voices

This commit is contained in:
Jean Pierre Cimalando 2020-05-17 21:42:57 +02:00
parent d9e49f7dc5
commit f0f4c34ad8
8 changed files with 51 additions and 30 deletions

View file

@ -35,8 +35,8 @@ namespace sfz {
* *
*/ */
struct Region { struct Region {
Region(const MidiState& midiState, absl::string_view defaultPath = "") Region(int regionNumber, const MidiState& midiState, absl::string_view defaultPath = "")
: midiState(midiState), defaultPath(std::move(defaultPath)) : regionNumber(regionNumber), midiState(midiState), defaultPath(std::move(defaultPath))
{ {
ccSwitched.set(); ccSwitched.set();
@ -46,6 +46,14 @@ struct Region {
Region(const Region&) = default; Region(const Region&) = default;
~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? * @brief Triggers on release?
* *
@ -238,6 +246,8 @@ struct Region {
*/ */
float getGainToEffectBus(unsigned number) const noexcept; float getGainToEffectBus(unsigned number) const noexcept;
const int regionNumber {};
// Sound source: sample playback // Sound source: sample playback
FileId sampleId {}; // Sample FileId sampleId {}; // Sample
int sampleQuality { Default::sampleQuality }; int sampleQuality { Default::sampleQuality };

View file

@ -95,7 +95,8 @@ void sfz::Synth::onParseWarning(const SourceRange& range, const std::string& mes
void sfz::Synth::buildRegion(const std::vector<Opcode>& regionOpcodes) void sfz::Synth::buildRegion(const std::vector<Opcode>& regionOpcodes)
{ {
auto lastRegion = absl::make_unique<Region>(resources.midiState, defaultPath); int regionNumber = static_cast<int>(regions.size());
auto lastRegion = absl::make_unique<Region>(regionNumber, resources.midiState, defaultPath);
auto parseOpcodes = [&](const std::vector<Opcode>& opcodes) { auto parseOpcodes = [&](const std::vector<Opcode>& opcodes) {
for (auto& opcode : opcodes) { for (auto& opcode : opcodes) {
@ -1094,7 +1095,7 @@ void sfz::Synth::resetVoices(int numVoices)
voices.reserve(numVoices); voices.reserve(numVoices);
for (int i = 0; i < numVoices; ++i) for (int i = 0; i < numVoices; ++i)
voices.push_back(absl::make_unique<Voice>(resources)); voices.push_back(absl::make_unique<Voice>(i, resources));
voiceViewArray.clear(); voiceViewArray.clear();
voiceViewArray.reserve(numVoices); voiceViewArray.reserve(numVoices);

View file

@ -14,8 +14,8 @@
#include "Interpolators.h" #include "Interpolators.h"
#include "absl/algorithm/container.h" #include "absl/algorithm/container.h"
sfz::Voice::Voice(sfz::Resources& resources) sfz::Voice::Voice(int voiceNumber, sfz::Resources& resources)
: resources(resources) : voiceNumber(voiceNumber), resources(resources)
{ {
filters.reserve(config::filtersPerVoice); filters.reserve(config::filtersPerVoice);
equalizers.reserve(config::eqsPerVoice); equalizers.reserve(config::eqsPerVoice);

View file

@ -32,14 +32,22 @@ public:
/** /**
* @brief Construct a new voice with the midistate singleton * @brief Construct a new voice with the midistate singleton
* *
* @param voiceNumber
* @param midiState * @param midiState
*/ */
Voice(Resources& resources); Voice(int voiceNumber, Resources& resources);
enum class TriggerType { enum class TriggerType {
NoteOn, NoteOn,
NoteOff, NoteOff,
CC 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 * @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 * pitch related transformations so it needs to be propagated from the synth
@ -270,6 +278,8 @@ private:
void setupOscillatorUnison(); void setupOscillatorUnison();
void updateChannelPowers(AudioSpan<float> buffer); void updateChannelPowers(AudioSpan<float> buffer);
const int voiceNumber {};
Region* region { nullptr }; Region* region { nullptr };
enum class State { enum class State {

View file

@ -13,7 +13,7 @@ using namespace sfz::literals;
TEST_CASE("Region activation", "Region tests") TEST_CASE("Region activation", "Region tests")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
SECTION("Basic state") SECTION("Basic state")

View file

@ -14,7 +14,7 @@ using namespace sfz::literals;
TEST_CASE("[Region] Parsing opcodes") TEST_CASE("[Region] Parsing opcodes")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
SECTION("sample") SECTION("sample")
{ {
@ -1672,7 +1672,7 @@ TEST_CASE("[Region] Parsing opcodes")
TEST_CASE("[Region] Non-conforming floating point values in integer opcodes") TEST_CASE("[Region] Non-conforming floating point values in integer opcodes")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "offset", "2014.5" }); region.parseOpcode({ "offset", "2014.5" });
REQUIRE(region.offset == 2014); REQUIRE(region.offset == 2014);
region.parseOpcode({ "pitch_keytrack", "-2.1" }); region.parseOpcode({ "pitch_keytrack", "-2.1" });

View file

@ -13,7 +13,7 @@ using namespace sfz::literals;
TEST_CASE("Basic triggers", "Region triggers") TEST_CASE("Basic triggers", "Region triggers")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
SECTION("key") SECTION("key")
@ -130,7 +130,7 @@ TEST_CASE("Basic triggers", "Region triggers")
TEST_CASE("Legato triggers", "Region triggers") TEST_CASE("Legato triggers", "Region triggers")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
SECTION("First note playing") SECTION("First note playing")
{ {

View file

@ -17,7 +17,7 @@ constexpr int numRandomTests { 64 };
TEST_CASE("[Region] Crossfade in on key") TEST_CASE("[Region] Crossfade in on key")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfin_lokey", "1" }); region.parseOpcode({ "xfin_lokey", "1" });
region.parseOpcode({ "xfin_hikey", "3" }); region.parseOpcode({ "xfin_hikey", "3" });
@ -29,7 +29,7 @@ TEST_CASE("[Region] Crossfade in on key")
TEST_CASE("[Region] Crossfade in on key - 2") TEST_CASE("[Region] Crossfade in on key - 2")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfin_lokey", "1" }); region.parseOpcode({ "xfin_lokey", "1" });
region.parseOpcode({ "xfin_hikey", "5" }); 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") TEST_CASE("[Region] Crossfade in on key - gain")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfin_lokey", "1" }); region.parseOpcode({ "xfin_lokey", "1" });
region.parseOpcode({ "xfin_hikey", "5" }); region.parseOpcode({ "xfin_hikey", "5" });
@ -59,7 +59,7 @@ TEST_CASE("[Region] Crossfade in on key - gain")
TEST_CASE("[Region] Crossfade out on key") TEST_CASE("[Region] Crossfade out on key")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfout_lokey", "51" }); region.parseOpcode({ "xfout_lokey", "51" });
region.parseOpcode({ "xfout_hikey", "55" }); region.parseOpcode({ "xfout_hikey", "55" });
@ -75,7 +75,7 @@ TEST_CASE("[Region] Crossfade out on key")
TEST_CASE("[Region] Crossfade out on key - gain") TEST_CASE("[Region] Crossfade out on key - gain")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfout_lokey", "51" }); region.parseOpcode({ "xfout_lokey", "51" });
region.parseOpcode({ "xfout_hikey", "55" }); region.parseOpcode({ "xfout_hikey", "55" });
@ -92,7 +92,7 @@ TEST_CASE("[Region] Crossfade out on key - gain")
TEST_CASE("[Region] Crossfade in on velocity") TEST_CASE("[Region] Crossfade in on velocity")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfin_lovel", "20" }); region.parseOpcode({ "xfin_lovel", "20" });
region.parseOpcode({ "xfin_hivel", "24" }); region.parseOpcode({ "xfin_hivel", "24" });
@ -109,7 +109,7 @@ TEST_CASE("[Region] Crossfade in on velocity")
TEST_CASE("[Region] Crossfade in on vel - gain") TEST_CASE("[Region] Crossfade in on vel - gain")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfin_lovel", "20" }); region.parseOpcode({ "xfin_lovel", "20" });
region.parseOpcode({ "xfin_hivel", "24" }); region.parseOpcode({ "xfin_hivel", "24" });
@ -127,7 +127,7 @@ TEST_CASE("[Region] Crossfade in on vel - gain")
TEST_CASE("[Region] Crossfade out on vel") TEST_CASE("[Region] Crossfade out on vel")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfout_lovel", "51" }); region.parseOpcode({ "xfout_lovel", "51" });
region.parseOpcode({ "xfout_hivel", "55" }); region.parseOpcode({ "xfout_hivel", "55" });
@ -144,7 +144,7 @@ TEST_CASE("[Region] Crossfade out on vel")
TEST_CASE("[Region] Crossfade out on vel - gain") TEST_CASE("[Region] Crossfade out on vel - gain")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfout_lovel", "51" }); region.parseOpcode({ "xfout_lovel", "51" });
region.parseOpcode({ "xfout_hivel", "55" }); region.parseOpcode({ "xfout_hivel", "55" });
@ -162,7 +162,7 @@ TEST_CASE("[Region] Crossfade out on vel - gain")
TEST_CASE("[Region] Crossfade in on CC") TEST_CASE("[Region] Crossfade in on CC")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfin_locc24", "20" }); region.parseOpcode({ "xfin_locc24", "20" });
region.parseOpcode({ "xfin_hicc24", "24" }); region.parseOpcode({ "xfin_hicc24", "24" });
@ -186,7 +186,7 @@ TEST_CASE("[Region] Crossfade in on CC")
TEST_CASE("[Region] Crossfade in on CC - gain") TEST_CASE("[Region] Crossfade in on CC - gain")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfin_locc24", "20" }); region.parseOpcode({ "xfin_locc24", "20" });
region.parseOpcode({ "xfin_hicc24", "24" }); region.parseOpcode({ "xfin_hicc24", "24" });
@ -210,7 +210,7 @@ TEST_CASE("[Region] Crossfade in on CC - gain")
TEST_CASE("[Region] Crossfade out on CC") TEST_CASE("[Region] Crossfade out on CC")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfout_locc24", "20" }); region.parseOpcode({ "xfout_locc24", "20" });
region.parseOpcode({ "xfout_hicc24", "24" }); region.parseOpcode({ "xfout_hicc24", "24" });
@ -234,7 +234,7 @@ TEST_CASE("[Region] Crossfade out on CC")
TEST_CASE("[Region] Crossfade out on CC - gain") TEST_CASE("[Region] Crossfade out on CC - gain")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "xfout_locc24", "20" }); region.parseOpcode({ "xfout_locc24", "20" });
region.parseOpcode({ "xfout_hicc24", "24" }); 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") TEST_CASE("[Region] Velocity bug for extreme values - veltrack at 0")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "amp_veltrack", "0" }); region.parseOpcode({ "amp_veltrack", "0" });
REQUIRE(region.getNoteGain(64, 127_norm) == 1.0_a); 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") TEST_CASE("[Region] Velocity bug for extreme values - positive veltrack")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "amp_veltrack", "100" }); region.parseOpcode({ "amp_veltrack", "100" });
REQUIRE(region.getNoteGain(64, 127_norm) == 1.0_a); 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") TEST_CASE("[Region] Velocity bug for extreme values - negative veltrack")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "amp_veltrack", "-100" }); region.parseOpcode({ "amp_veltrack", "-100" });
REQUIRE(region.getNoteGain(64, 127_norm) == Approx(0.0).margin(0.0001)); REQUIRE(region.getNoteGain(64, 127_norm) == Approx(0.0).margin(0.0001));
@ -291,7 +291,7 @@ TEST_CASE("[Region] rt_decay")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
midiState.setSampleRate(1000); midiState.setSampleRate(1000);
sfz::Region region { midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "trigger", "release" }); region.parseOpcode({ "trigger", "release" });
region.parseOpcode({ "rt_decay", "10" }); region.parseOpcode({ "rt_decay", "10" });
@ -311,7 +311,7 @@ TEST_CASE("[Region] rt_decay")
TEST_CASE("[Region] Base delay") TEST_CASE("[Region] Base delay")
{ {
sfz::MidiState midiState; sfz::MidiState midiState;
sfz::Region region{ midiState }; sfz::Region region { 0, midiState };
region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "sample", "*sine" });
region.parseOpcode({ "delay", "10" }); region.parseOpcode({ "delay", "10" });
REQUIRE( region.getDelay() == 10.0f ); REQUIRE( region.getDelay() == 10.0f );