WIP for Voices
This commit is contained in:
parent
7815623115
commit
04181f0d10
5 changed files with 59 additions and 5 deletions
|
|
@ -127,4 +127,5 @@ private:
|
||||||
int activeNotesInRange { -1 };
|
int activeNotesInRange { -1 };
|
||||||
int sequenceCounter { 0 };
|
int sequenceCounter { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sfz
|
} // namespace sfz
|
||||||
|
|
@ -11,7 +11,7 @@ using CCValueArray = std::array<uint8_t, 128>;
|
||||||
using CCValuePair = std::pair<uint8_t, float> ;
|
using CCValuePair = std::pair<uint8_t, float> ;
|
||||||
using CCNamePair = std::pair<uint8_t, std::string>;
|
using CCNamePair = std::pair<uint8_t, std::string>;
|
||||||
|
|
||||||
inline std::optional<uint8_t> readNoteValue(const std::string_view&value)
|
inline std::optional<uint8_t> readNoteValue(const std::string_view& value)
|
||||||
{
|
{
|
||||||
switch(hash(value))
|
switch(hash(value))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename)
|
||||||
auto currentRegion = regions.begin();
|
auto currentRegion = regions.begin();
|
||||||
while (currentRegion <= lastRegion)
|
while (currentRegion <= lastRegion)
|
||||||
{
|
{
|
||||||
auto region = &**currentRegion;
|
auto region = currentRegion->get();
|
||||||
|
|
||||||
if (region->isGenerator())
|
if (region->isGenerator())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <random>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz
|
||||||
|
|
@ -44,16 +45,56 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void noteOn(int delay, int channel, int noteNumber, uint8_t velocity);
|
void noteOn(int delay, int channel, int noteNumber, uint8_t velocity)
|
||||||
void noteOff(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 cc(int delay, int channel, int ccNumber, uint8_t ccValue);
|
||||||
void pitchWheel(int delay, int channel, int pitch);
|
void pitchWheel(int delay, int channel, int pitch);
|
||||||
void aftertouch(int delay, int channel, uint8_t aftertouch);
|
void aftertouch(int delay, int channel, uint8_t aftertouch);
|
||||||
void tempo(int delay, float secondsPerQuarter);
|
void tempo(int delay, float secondsPerQuarter);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void callback(std::string_view header, std::vector<Opcode> members) final;
|
void callback(std::string_view header, std::vector<Opcode> members) final;
|
||||||
private:
|
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 hasGlobal { false };
|
||||||
bool hasControl { false };
|
bool hasControl { false };
|
||||||
int numGroups { 0 };
|
int numGroups { 0 };
|
||||||
|
|
@ -81,6 +122,13 @@ private:
|
||||||
StereoBuffer<float> tempBuffer { config::defaultSamplesPerBlock };
|
StereoBuffer<float> tempBuffer { config::defaultSamplesPerBlock };
|
||||||
int samplesPerBlock { config::defaultSamplesPerBlock };
|
int samplesPerBlock { config::defaultSamplesPerBlock };
|
||||||
float sampleRate { config::defaultSampleRate };
|
float sampleRate { config::defaultSampleRate };
|
||||||
|
std::random_device rd { };
|
||||||
|
std::mt19937 randomGenerator { rd() };
|
||||||
|
std::uniform_real_distribution<float> randomDistribution { 0, 1 };
|
||||||
|
float getUniform()
|
||||||
|
{
|
||||||
|
return randomDistribution(randomGenerator);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -27,6 +27,11 @@ public:
|
||||||
dataReady.store(true);
|
dataReady.store(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isFree()
|
||||||
|
{
|
||||||
|
return (region == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
bool registerNoteOn(int delay, int channel, int noteNumber, uint8_t velocity);
|
bool registerNoteOn(int delay, int channel, int noteNumber, uint8_t velocity);
|
||||||
void registerNoteOff(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);
|
bool registerCC(int delay, int channel, int ccNumber, uint8_t ccValue);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue