Voice and synth logic
This commit is contained in:
parent
31c8c1b62e
commit
215a5fdb57
3 changed files with 54 additions and 24 deletions
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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)) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue