Voice and synth logic

This commit is contained in:
paulfd 2019-08-23 20:48:44 +02:00
parent 31c8c1b62e
commit 215a5fdb57
3 changed files with 54 additions and 24 deletions

View file

@ -9,15 +9,14 @@ std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(
if (!std::filesystem::exists(file)) if (!std::filesystem::exists(file))
return {}; return {};
SndfileHandle sndFile ( reinterpret_cast<const char*>(file.c_str()) ); SndfileHandle sndFile(reinterpret_cast<const char*>(file.c_str()));
FileInformation returnedValue; FileInformation returnedValue;
returnedValue.end = static_cast<uint32_t>(sndFile.frames()); returnedValue.end = static_cast<uint32_t>(sndFile.frames());
returnedValue.sampleRate = static_cast<double>(sndFile.samplerate()); returnedValue.sampleRate = static_cast<double>(sndFile.samplerate());
SF_INSTRUMENT instrumentInfo; SF_INSTRUMENT instrumentInfo;
sndFile.command(SFC_GET_INSTRUMENT, &instrumentInfo, sizeof(instrumentInfo)); sndFile.command(SFC_GET_INSTRUMENT, &instrumentInfo, sizeof(instrumentInfo));
if (instrumentInfo.loop_count == 1) if (instrumentInfo.loop_count == 1) {
{
returnedValue.loopBegin = instrumentInfo.loops[0].start; returnedValue.loopBegin = instrumentInfo.loops[0].start;
returnedValue.loopEnd = instrumentInfo.loops[0].end; returnedValue.loopEnd = instrumentInfo.loops[0].end;
} }
@ -34,8 +33,7 @@ std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(
void sfz::FilePool::enqueueLoading(Voice* voice, std::string_view sample, int numFrames) void sfz::FilePool::enqueueLoading(Voice* voice, std::string_view sample, int numFrames)
{ {
if (!loadingQueue.try_enqueue({ voice, sample, numFrames })) if (!loadingQueue.try_enqueue({ voice, sample, numFrames })) {
{
DBG("Problem enqueuing a file read for file " << sample); DBG("Problem enqueuing a file read for file " << sample);
} }
} }
@ -43,31 +41,27 @@ void sfz::FilePool::enqueueLoading(Voice* voice, std::string_view sample, int nu
void sfz::FilePool::loadingThread() void sfz::FilePool::loadingThread()
{ {
FileLoadingInformation fileToLoad {}; FileLoadingInformation fileToLoad {};
while (!quitThread) while (!quitThread) {
{
if (!loadingQueue.wait_dequeue_timed(fileToLoad, 1ms)) if (!loadingQueue.wait_dequeue_timed(fileToLoad, 1ms))
continue; continue;
if (fileToLoad.voice == nullptr) if (fileToLoad.voice == nullptr) {
{
DBG("Background thread error: voice is null."); DBG("Background thread error: voice is null.");
continue; continue;
} }
DBG("Background loading of: " << fileToLoad.sample); DBG("Background loading of: " << fileToLoad.sample);
std::filesystem::path file { rootDirectory / fileToLoad.sample }; std::filesystem::path file { rootDirectory / fileToLoad.sample };
if (!std::filesystem::exists(file)) if (!std::filesystem::exists(file)) {
{
DBG("Background thread: no file " << fileToLoad.sample << " exists."); DBG("Background thread: no file " << fileToLoad.sample << " exists.");
continue; continue;
} }
SndfileHandle sndFile ( reinterpret_cast<const char*>(file.c_str()) ); SndfileHandle sndFile(reinterpret_cast<const char*>(file.c_str()));
auto fileLoaded = std::make_unique<StereoBuffer<float>>(fileToLoad.numFrames); auto fileLoaded = std::make_unique<StereoBuffer<float>>(fileToLoad.numFrames);
auto readBuffer = std::make_unique<Buffer<float>>(fileToLoad.numFrames * 2); auto readBuffer = std::make_unique<Buffer<float>>(fileToLoad.numFrames * 2);
sndFile.readf(readBuffer->data(), fileToLoad.numFrames); sndFile.readf(readBuffer->data(), fileToLoad.numFrames);
fileLoaded->readInterleaved(*readBuffer); fileLoaded->readInterleaved(*readBuffer);
fileToLoad.voice->setFileData(std::move(fileLoaded)); fileToLoad.voice->setFileData(std::move(fileLoaded));
} }
} }

View file

@ -3,6 +3,7 @@
#include "Parser.h" #include "Parser.h"
#include "Region.h" #include "Region.h"
#include "SfzHelpers.h" #include "SfzHelpers.h"
#include "absl/types/span.h"
#include <optional> #include <optional>
#include <random> #include <random>
#include <set> #include <set>
@ -36,6 +37,8 @@ public:
void renderBlock(StereoBuffer<float>& buffer) void renderBlock(StereoBuffer<float>& buffer)
{ {
buffer.fill(0.0f);
for (auto& voice : voices) { for (auto& voice : voices) {
voice->renderBlock(tempBuffer); voice->renderBlock(tempBuffer);
buffer.add(tempBuffer); buffer.add(tempBuffer);
@ -45,11 +48,16 @@ public:
void noteOn(int delay, int channel, int noteNumber, uint8_t velocity) void noteOn(int delay, int channel, int noteNumber, uint8_t velocity)
{ {
auto randValue = getUniform(); auto randValue = getUniform();
for (auto& voice : voices)
voice->registerNoteOn(delay, channel, noteNumber, velocity);
for (auto& region : regions) { for (auto& region : regions) {
if (region->registerNoteOn(channel, noteNumber, velocity, randValue)) { if (region->registerNoteOn(channel, noteNumber, velocity, randValue)) {
for (auto& voice: voices)
{
if (voice->checkOffGroup(delay, region->group))
noteOff(delay, voice->getTriggerChannel(), voice->getTriggerNumber(), 0);
}
auto voice = findFreeVoice(); auto voice = findFreeVoice();
if (voice == nullptr) if (voice == nullptr)
continue; continue;
@ -62,11 +70,8 @@ public:
void noteOff(int delay, int channel, int noteNumber, uint8_t velocity) void noteOff(int delay, int channel, int noteNumber, uint8_t velocity)
{ {
auto randValue = getUniform(); auto randValue = getUniform();
for (auto& voice : voices) { for (auto& voice : voices)
if (voice->registerNoteOff(delay, channel, noteNumber, velocity)) { voice->registerNoteOff(delay, channel, noteNumber, velocity);
// do something
}
}
for (auto& region : regions) { for (auto& region : regions) {
if (region->registerNoteOff(channel, noteNumber, velocity, randValue)) { if (region->registerNoteOff(channel, noteNumber, velocity, randValue)) {

View file

@ -32,8 +32,7 @@ public:
return (region == nullptr); return (region == nullptr);
} }
void registerNoteOn(int delay, int channel, int noteNumber, uint8_t velocity); void registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity);
bool 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);
void registerPitchWheel(int delay, int channel, int pitch); void registerPitchWheel(int delay, int channel, int pitch);
void registerAftertouch(int delay, int channel, uint8_t aftertouch); void registerAftertouch(int delay, int channel, uint8_t aftertouch);
@ -45,6 +44,38 @@ public:
buffer.fill(0.0f); buffer.fill(0.0f);
} }
bool checkOffGroup(int delay [[maybe_unused]], uint32_t group) noexcept
{
if (region != nullptr && triggerType == TriggerType::NoteOn && region->offBy && *region->offBy == group )
{
// TODO: release
return true;
}
return false;
}
int getTriggerNumber() const
{
return triggerNumber;
}
int getTriggerChannel() const
{
return triggerNumber;
}
uint8_t getTriggerValue() const
{
return triggerNumber;
}
TriggerType getTriggerType() const
{
return triggerType;
}
void reset() void reset()
{ {
dataReady.store(false); dataReady.store(false);