Added a ticket system so that if the background loader fails to provide the file in time it gets discarded.
This commit is contained in:
parent
dd08115dc4
commit
32efd60ec9
6 changed files with 36 additions and 19 deletions
|
|
@ -85,9 +85,9 @@ std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(
|
||||||
return returnedValue;
|
return returnedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::FilePool::enqueueLoading(Voice* voice, std::string_view sample, int numFrames) noexcept
|
void sfz::FilePool::enqueueLoading(Voice* voice, std::string_view sample, int numFrames, unsigned ticket) noexcept
|
||||||
{
|
{
|
||||||
if (!loadingQueue.try_enqueue({ voice, sample, numFrames })) {
|
if (!loadingQueue.try_enqueue({ voice, sample, numFrames, ticket })) {
|
||||||
DBG("Problem enqueuing a file read for file " << sample);
|
DBG("Problem enqueuing a file read for file " << sample);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -113,6 +113,6 @@ void sfz::FilePool::loadingThread() noexcept
|
||||||
|
|
||||||
SndfileHandle sndFile(reinterpret_cast<const char*>(file.c_str()));
|
SndfileHandle sndFile(reinterpret_cast<const char*>(file.c_str()));
|
||||||
auto fileLoaded = std::make_unique<AudioBuffer<float>>(sndFile.channels(), fileToLoad.numFrames);
|
auto fileLoaded = std::make_unique<AudioBuffer<float>>(sndFile.channels(), fileToLoad.numFrames);
|
||||||
fileToLoad.voice->setFileData(readFromFile<float>(sndFile, fileToLoad.numFrames));
|
fileToLoad.voice->setFileData(readFromFile<float>(sndFile, fileToLoad.numFrames), fileToLoad.ticket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -57,13 +57,14 @@ public:
|
||||||
std::shared_ptr<AudioBuffer<float>> preloadedData;
|
std::shared_ptr<AudioBuffer<float>> preloadedData;
|
||||||
};
|
};
|
||||||
std::optional<FileInformation> getFileInformation(std::string_view filename) noexcept;
|
std::optional<FileInformation> getFileInformation(std::string_view filename) noexcept;
|
||||||
void enqueueLoading(Voice* voice, std::string_view sample, int numFrames) noexcept;
|
void enqueueLoading(Voice* voice, std::string_view sample, int numFrames, unsigned ticket) noexcept;
|
||||||
private:
|
private:
|
||||||
std::filesystem::path rootDirectory;
|
std::filesystem::path rootDirectory;
|
||||||
struct FileLoadingInformation {
|
struct FileLoadingInformation {
|
||||||
Voice* voice;
|
Voice* voice;
|
||||||
std::string_view sample;
|
std::string_view sample;
|
||||||
int numFrames;
|
int numFrames;
|
||||||
|
unsigned ticket;
|
||||||
};
|
};
|
||||||
|
|
||||||
moodycamel::BlockingReaderWriterQueue<FileLoadingInformation> loadingQueue;
|
moodycamel::BlockingReaderWriterQueue<FileLoadingInformation> loadingQueue;
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "Synth.h"
|
#include "Synth.h"
|
||||||
#include "ScopedFTZ.h"
|
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
|
#include "ScopedFTZ.h"
|
||||||
#include "StringViewHelpers.h"
|
#include "StringViewHelpers.h"
|
||||||
#include "absl/algorithm/container.h"
|
#include "absl/algorithm/container.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
@ -106,6 +106,7 @@ void sfz::Synth::clear()
|
||||||
numGroups = 0;
|
numGroups = 0;
|
||||||
numMasters = 0;
|
numMasters = 0;
|
||||||
numCurves = 0;
|
numCurves = 0;
|
||||||
|
fileTicket = -1;
|
||||||
defaultSwitch = std::nullopt;
|
defaultSwitch = std::nullopt;
|
||||||
for (auto& state : ccState)
|
for (auto& state : ccState)
|
||||||
state = 0;
|
state = 0;
|
||||||
|
|
@ -152,18 +153,14 @@ void sfz::Synth::handleControlOpcodes(const std::vector<Opcode>& members)
|
||||||
|
|
||||||
void addEndpointsToVelocityCurve(sfz::Region& region)
|
void addEndpointsToVelocityCurve(sfz::Region& region)
|
||||||
{
|
{
|
||||||
if (region.velocityPoints.size() > 0)
|
if (region.velocityPoints.size() > 0) {
|
||||||
{
|
|
||||||
absl::c_sort(region.velocityPoints, [](auto& lhs, auto& rhs) { return lhs.first < rhs.first; });
|
absl::c_sort(region.velocityPoints, [](auto& lhs, auto& rhs) { return lhs.first < rhs.first; });
|
||||||
if (region.ampVeltrack > 0)
|
if (region.ampVeltrack > 0) {
|
||||||
{
|
|
||||||
if (region.velocityPoints.back().first != sfz::Default::velocityRange.getEnd())
|
if (region.velocityPoints.back().first != sfz::Default::velocityRange.getEnd())
|
||||||
region.velocityPoints.push_back(std::make_pair<int, float>(127, 1.0f));
|
region.velocityPoints.push_back(std::make_pair<int, float>(127, 1.0f));
|
||||||
if (region.velocityPoints.front().first != sfz::Default::velocityRange.getStart())
|
if (region.velocityPoints.front().first != sfz::Default::velocityRange.getStart())
|
||||||
region.velocityPoints.insert(region.velocityPoints.begin(), std::make_pair<int, float>(0, 0.0f));
|
region.velocityPoints.insert(region.velocityPoints.begin(), std::make_pair<int, float>(0, 0.0f));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (region.velocityPoints.front().first != sfz::Default::velocityRange.getEnd())
|
if (region.velocityPoints.front().first != sfz::Default::velocityRange.getEnd())
|
||||||
region.velocityPoints.insert(region.velocityPoints.begin(), std::make_pair<int, float>(127, 0.0f));
|
region.velocityPoints.insert(region.velocityPoints.begin(), std::make_pair<int, float>(127, 0.0f));
|
||||||
if (region.velocityPoints.back().first != sfz::Default::velocityRange.getStart())
|
if (region.velocityPoints.back().first != sfz::Default::velocityRange.getStart())
|
||||||
|
|
@ -299,7 +296,10 @@ void sfz::Synth::noteOn(int delay, int channel, int noteNumber, uint8_t velocity
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
voice->startVoice(region.get(), delay, channel, noteNumber, velocity, Voice::TriggerType::NoteOn);
|
voice->startVoice(region.get(), delay, channel, noteNumber, velocity, Voice::TriggerType::NoteOn);
|
||||||
filePool.enqueueLoading(voice, region->sample, region->trueSampleEnd());
|
if (!region->isGenerator()) {
|
||||||
|
voice->expectFileData(fileTicket);
|
||||||
|
filePool.enqueueLoading(voice, region->sample, region->trueSampleEnd(), fileTicket++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -317,7 +317,10 @@ void sfz::Synth::noteOff(int delay, int channel, int noteNumber, uint8_t velocit
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
voice->startVoice(region.get(), delay, channel, noteNumber, velocity, Voice::TriggerType::NoteOff);
|
voice->startVoice(region.get(), delay, channel, noteNumber, velocity, Voice::TriggerType::NoteOff);
|
||||||
filePool.enqueueLoading(voice, region->sample, region->trueSampleEnd());
|
if (!region->isGenerator()) {
|
||||||
|
voice->expectFileData(fileTicket);
|
||||||
|
filePool.enqueueLoading(voice, region->sample, region->trueSampleEnd(), fileTicket++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -336,7 +339,10 @@ void sfz::Synth::cc(int delay, int channel, int ccNumber, uint8_t ccValue) noexc
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
voice->startVoice(region.get(), delay, channel, ccNumber, ccValue, Voice::TriggerType::CC);
|
voice->startVoice(region.get(), delay, channel, ccNumber, ccValue, Voice::TriggerType::CC);
|
||||||
filePool.enqueueLoading(voice, region->sample, region->trueSampleEnd());
|
if (!region->isGenerator()) {
|
||||||
|
voice->expectFileData(fileTicket);
|
||||||
|
filePool.enqueueLoading(voice, region->sample, region->trueSampleEnd(), fileTicket++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ private:
|
||||||
float sampleRate { config::defaultSampleRate };
|
float sampleRate { config::defaultSampleRate };
|
||||||
|
|
||||||
std::uniform_real_distribution<float> randNoteDistribution { 0, 1 };
|
std::uniform_real_distribution<float> randNoteDistribution { 0, 1 };
|
||||||
|
unsigned fileTicket { 1 };
|
||||||
|
|
||||||
LEAK_DETECTOR(Synth);
|
LEAK_DETECTOR(Synth);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -101,9 +101,11 @@ void sfz::Voice::prepareEGEnvelope(int delay, uint8_t velocity) noexcept
|
||||||
normalizePercents(region->amplitudeEG.getStart(ccState, velocity)));
|
normalizePercents(region->amplitudeEG.getStart(ccState, velocity)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Voice::setFileData(std::unique_ptr<AudioBuffer<float>> file) noexcept
|
void sfz::Voice::setFileData(std::unique_ptr<AudioBuffer<float>> file, unsigned ticket) noexcept
|
||||||
{
|
{
|
||||||
// DBG("File data set for sample " << region->sample);
|
if (ticket != this->ticket)
|
||||||
|
return;
|
||||||
|
|
||||||
fileData = std::move(file);
|
fileData = std::move(file);
|
||||||
dataReady.store(true);
|
dataReady.store(true);
|
||||||
}
|
}
|
||||||
|
|
@ -422,3 +424,8 @@ void sfz::Voice::garbageCollect() noexcept
|
||||||
if (state == State::idle && region == nullptr)
|
if (state == State::idle && region == nullptr)
|
||||||
fileData.reset();
|
fileData.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sfz::Voice::expectFileData(unsigned ticket)
|
||||||
|
{
|
||||||
|
this->ticket = ticket;
|
||||||
|
}
|
||||||
|
|
@ -47,7 +47,8 @@ public:
|
||||||
|
|
||||||
void startVoice(Region* region, int delay, int channel, int number, uint8_t value, TriggerType triggerType) noexcept;
|
void startVoice(Region* region, int delay, int channel, int number, uint8_t value, TriggerType triggerType) noexcept;
|
||||||
|
|
||||||
void setFileData(std::unique_ptr<AudioBuffer<float>> file) noexcept;
|
void expectFileData(unsigned ticket);
|
||||||
|
void setFileData(std::unique_ptr<AudioBuffer<float>> file, unsigned ticket) noexcept;
|
||||||
void registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity) noexcept;
|
void registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity) noexcept;
|
||||||
void registerCC(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept;
|
void registerCC(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept;
|
||||||
void registerPitchWheel(int delay, int channel, int pitch) noexcept;
|
void registerPitchWheel(int delay, int channel, int pitch) noexcept;
|
||||||
|
|
@ -102,6 +103,7 @@ private:
|
||||||
|
|
||||||
std::atomic<bool> dataReady { false };
|
std::atomic<bool> dataReady { false };
|
||||||
std::unique_ptr<AudioBuffer<float>> fileData { nullptr };
|
std::unique_ptr<AudioBuffer<float>> fileData { nullptr };
|
||||||
|
unsigned ticket { 0 };
|
||||||
|
|
||||||
Buffer<float> tempBuffer1;
|
Buffer<float> tempBuffer1;
|
||||||
Buffer<float> tempBuffer2;
|
Buffer<float> tempBuffer2;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue