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:
paulfd 2019-09-07 17:23:13 +02:00
parent dd08115dc4
commit 32efd60ec9
6 changed files with 36 additions and 19 deletions

View file

@ -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);
} }
} }

View file

@ -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;

View file

@ -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++);
}
} }
} }
} }

View file

@ -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);
}; };

View file

@ -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;
}

View file

@ -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;