From 04181f0d10a71eb088b96ac85b6da425317cb7c6 Mon Sep 17 00:00:00 2001 From: paulfd Date: Fri, 23 Aug 2019 14:16:33 +0200 Subject: [PATCH] WIP for Voices --- sources/Region.h | 1 + sources/SfzHelpers.h | 2 +- sources/Synth.cpp | 2 +- sources/Synth.h | 54 +++++++++++++++++++++++++++++++++++++++++--- sources/Voice.h | 5 ++++ 5 files changed, 59 insertions(+), 5 deletions(-) diff --git a/sources/Region.h b/sources/Region.h index 879504b5..336cbe34 100644 --- a/sources/Region.h +++ b/sources/Region.h @@ -127,4 +127,5 @@ private: int activeNotesInRange { -1 }; int sequenceCounter { 0 }; }; + } // namespace sfz \ No newline at end of file diff --git a/sources/SfzHelpers.h b/sources/SfzHelpers.h index a37ede19..de733152 100644 --- a/sources/SfzHelpers.h +++ b/sources/SfzHelpers.h @@ -11,7 +11,7 @@ using CCValueArray = std::array; using CCValuePair = std::pair ; using CCNamePair = std::pair; -inline std::optional readNoteValue(const std::string_view&value) +inline std::optional readNoteValue(const std::string_view& value) { switch(hash(value)) { diff --git a/sources/Synth.cpp b/sources/Synth.cpp index fc68b096..d4ad9965 100644 --- a/sources/Synth.cpp +++ b/sources/Synth.cpp @@ -127,7 +127,7 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename) auto currentRegion = regions.begin(); while (currentRegion <= lastRegion) { - auto region = &**currentRegion; + auto region = currentRegion->get(); if (region->isGenerator()) { diff --git a/sources/Synth.h b/sources/Synth.h index 97f4bde1..59540ca3 100644 --- a/sources/Synth.h +++ b/sources/Synth.h @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace sfz @@ -44,16 +45,56 @@ public: } } - void noteOn(int delay, int channel, int noteNumber, uint8_t velocity); - void noteOff(int delay, int channel, int noteNumber, uint8_t velocity); + void noteOn(int delay, int channel, int noteNumber, uint8_t velocity) + { + auto randValue = getUniform(); + for (auto& region: regions) + { + if (region->registerNoteOn(channel, noteNumber, velocity, randValue)) + { + auto voice = findFreeVoice(); + if (voice == nullptr) + continue; + + voice->startVoice(region.get(), channel, noteNumber, velocity, Voice::TriggerType::NoteOn); + } + } + } + + void noteOff(int delay, int channel, int noteNumber, uint8_t velocity) + { + auto randValue = getUniform(); + for (auto& region: regions) + { + if (region->registerNoteOff(channel, noteNumber, velocity, randValue)) + { + auto voice = findFreeVoice(); + if (voice == nullptr) + continue; + + voice->startVoice(region.get(), channel, noteNumber, velocity, Voice::TriggerType::NoteOff); + voice->startVoice(region.get(), channel, noteNumber, velocity, Voice::TriggerType::NoteOff); + } + } + } void cc(int delay, int channel, int ccNumber, uint8_t ccValue); void pitchWheel(int delay, int channel, int pitch); void aftertouch(int delay, int channel, uint8_t aftertouch); void tempo(int delay, float secondsPerQuarter); - + protected: void callback(std::string_view header, std::vector members) final; private: + Voice* findFreeVoice() + { + auto freeVoice = absl::c_find_if(voices, [](const auto& voice) { return voice->isFree(); }); + if (freeVoice == voices.end()) + { + DBG("Voices are overloaded, can't start a new note"); + return {}; + } + return freeVoice->get(); + } bool hasGlobal { false }; bool hasControl { false }; int numGroups { 0 }; @@ -81,6 +122,13 @@ private: StereoBuffer tempBuffer { config::defaultSamplesPerBlock }; int samplesPerBlock { config::defaultSamplesPerBlock }; float sampleRate { config::defaultSampleRate }; + std::random_device rd { }; + std::mt19937 randomGenerator { rd() }; + std::uniform_real_distribution randomDistribution { 0, 1 }; + float getUniform() + { + return randomDistribution(randomGenerator); + } }; } \ No newline at end of file diff --git a/sources/Voice.h b/sources/Voice.h index 56f83c07..eb7b8b55 100644 --- a/sources/Voice.h +++ b/sources/Voice.h @@ -27,6 +27,11 @@ public: dataReady.store(true); } + bool isFree() + { + return (region == nullptr); + } + bool registerNoteOn(int delay, int channel, int noteNumber, uint8_t velocity); void registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity); bool registerCC(int delay, int channel, int ccNumber, uint8_t ccValue);