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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -113,6 +113,6 @@ void sfz::FilePool::loadingThread() noexcept
|
|||
|
||||
SndfileHandle sndFile(reinterpret_cast<const char*>(file.c_str()));
|
||||
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::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:
|
||||
std::filesystem::path rootDirectory;
|
||||
struct FileLoadingInformation {
|
||||
Voice* voice;
|
||||
std::string_view sample;
|
||||
int numFrames;
|
||||
unsigned ticket;
|
||||
};
|
||||
|
||||
moodycamel::BlockingReaderWriterQueue<FileLoadingInformation> loadingQueue;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@
|
|||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "Synth.h"
|
||||
#include "ScopedFTZ.h"
|
||||
#include "Debug.h"
|
||||
#include "ScopedFTZ.h"
|
||||
#include "StringViewHelpers.h"
|
||||
#include "absl/algorithm/container.h"
|
||||
#include <algorithm>
|
||||
|
|
@ -106,6 +106,7 @@ void sfz::Synth::clear()
|
|||
numGroups = 0;
|
||||
numMasters = 0;
|
||||
numCurves = 0;
|
||||
fileTicket = -1;
|
||||
defaultSwitch = std::nullopt;
|
||||
for (auto& state : ccState)
|
||||
state = 0;
|
||||
|
|
@ -152,23 +153,19 @@ void sfz::Synth::handleControlOpcodes(const std::vector<Opcode>& members)
|
|||
|
||||
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; });
|
||||
if (region.ampVeltrack > 0)
|
||||
{
|
||||
if (region.ampVeltrack > 0) {
|
||||
if (region.velocityPoints.back().first != sfz::Default::velocityRange.getEnd())
|
||||
region.velocityPoints.push_back(std::make_pair<int, float>(127, 1.0f));
|
||||
if (region.velocityPoints.front().first != sfz::Default::velocityRange.getStart())
|
||||
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())
|
||||
region.velocityPoints.insert(region.velocityPoints.begin(), std::make_pair<int, float>(127, 0.0f));
|
||||
if (region.velocityPoints.back().first != sfz::Default::velocityRange.getStart())
|
||||
region.velocityPoints.push_back(std::make_pair<int, float>(0, 1.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -299,7 +296,10 @@ void sfz::Synth::noteOn(int delay, int channel, int noteNumber, uint8_t velocity
|
|||
continue;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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 };
|
||||
|
||||
std::uniform_real_distribution<float> randNoteDistribution { 0, 1 };
|
||||
unsigned fileTicket { 1 };
|
||||
|
||||
LEAK_DETECTOR(Synth);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -101,9 +101,11 @@ void sfz::Voice::prepareEGEnvelope(int delay, uint8_t velocity) noexcept
|
|||
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);
|
||||
dataReady.store(true);
|
||||
}
|
||||
|
|
@ -422,3 +424,8 @@ void sfz::Voice::garbageCollect() noexcept
|
|||
if (state == State::idle && region == nullptr)
|
||||
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 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 registerCC(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept;
|
||||
void registerPitchWheel(int delay, int channel, int pitch) noexcept;
|
||||
|
|
@ -102,6 +103,7 @@ private:
|
|||
|
||||
std::atomic<bool> dataReady { false };
|
||||
std::unique_ptr<AudioBuffer<float>> fileData { nullptr };
|
||||
unsigned ticket { 0 };
|
||||
|
||||
Buffer<float> tempBuffer1;
|
||||
Buffer<float> tempBuffer2;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue