Noexcepts

This commit is contained in:
paulfd 2019-08-29 16:23:35 +02:00
parent bfa85b131d
commit a8b2c9dfa8
8 changed files with 122 additions and 100 deletions

View file

@ -19,7 +19,7 @@ void readFromFile(SndfileHandle& sndFile, int numFrames, StereoBuffer<T>& output
}
}
std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(std::string_view filename)
std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(std::string_view filename) noexcept
{
std::filesystem::path file { rootDirectory / filename };
if (!std::filesystem::exists(file))
@ -60,14 +60,14 @@ std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(
return returnedValue;
}
void sfz::FilePool::enqueueLoading(Voice* voice, std::string_view sample, int numFrames)
void sfz::FilePool::enqueueLoading(Voice* voice, std::string_view sample, int numFrames) noexcept
{
if (!loadingQueue.try_enqueue({ voice, sample, numFrames })) {
DBG("Problem enqueuing a file read for file " << sample);
}
}
void sfz::FilePool::loadingThread()
void sfz::FilePool::loadingThread() noexcept
{
FileLoadingInformation fileToLoad {};
while (!quitThread) {

View file

@ -23,8 +23,8 @@ public:
quitThread = true;
fileLoadingThread.join();
}
void setRootDirectory(const std::filesystem::path& directory) { rootDirectory = directory; }
size_t getNumPreloadedSamples() { return preloadedData.size(); }
void setRootDirectory(const std::filesystem::path& directory) noexcept { rootDirectory = directory; }
size_t getNumPreloadedSamples() const noexcept { return preloadedData.size(); }
struct FileInformation {
uint32_t end { Default::sampleEndRange.getEnd() };
@ -33,18 +33,8 @@ public:
double sampleRate { config::defaultSampleRate };
std::shared_ptr<StereoBuffer<float>> preloadedData;
};
std::optional<FileInformation> getFileInformation(std::string_view filename);
void enqueueLoading(Voice* voice, std::string_view sample, int numFrames);
static void deleteAndTrackBuffers(StereoBuffer<float>* buffer)
{
fileBuffers--;
delete buffer;
};
static int getFileBuffers()
{
return fileBuffers.load();
}
std::optional<FileInformation> getFileInformation(std::string_view filename) noexcept;
void enqueueLoading(Voice* voice, std::string_view sample, int numFrames) noexcept;
private:
std::filesystem::path rootDirectory;
struct FileLoadingInformation {
@ -53,9 +43,8 @@ private:
int numFrames;
};
inline static std::atomic<int> fileBuffers { 0 };
moodycamel::BlockingReaderWriterQueue<FileLoadingInformation> loadingQueue;
void loadingThread();
void loadingThread() noexcept;
std::thread fileLoadingThread;
bool quitThread { false };
absl::flat_hash_map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;

View file

@ -403,12 +403,12 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
return true;
}
bool sfz::Region::isSwitchedOn() const noexcept
bool sfz::Region::isSwitchedOn() const noexcept
{
return keySwitched && previousKeySwitched && sequenceSwitched && pitchSwitched && bpmSwitched && aftertouchSwitched && allCCSwitched;
}
bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue)
bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue) noexcept
{
const bool chanOk = channelRange.containsWithEnd(channel);
if (!chanOk)
@ -468,7 +468,7 @@ bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity,
return keyOk && velOk && chanOk && randOk && (attackTrigger || firstLegatoNote || notFirstLegatoNote);
}
bool sfz::Region::registerNoteOff(int channel, int noteNumber, uint8_t velocity [[maybe_unused]], float randValue)
bool sfz::Region::registerNoteOff(int channel, int noteNumber, uint8_t velocity [[maybe_unused]], float randValue) noexcept
{
const bool chanOk = channelRange.containsWithEnd(channel);
if (!chanOk)
@ -496,7 +496,7 @@ bool sfz::Region::registerNoteOff(int channel, int noteNumber, uint8_t velocity
return keyOk && chanOk && randOk && releaseTrigger;
}
bool sfz::Region::registerCC(int channel, int ccNumber, uint8_t ccValue)
bool sfz::Region::registerCC(int channel, int ccNumber, uint8_t ccValue) noexcept
{
if (!channelRange.containsWithEnd(channel))
return false;
@ -517,7 +517,7 @@ bool sfz::Region::registerCC(int channel, int ccNumber, uint8_t ccValue)
return false;
}
void sfz::Region::registerPitchWheel(int channel, int pitch)
void sfz::Region::registerPitchWheel(int channel, int pitch) noexcept
{
if (!channelRange.containsWithEnd(channel))
return;
@ -528,7 +528,7 @@ void sfz::Region::registerPitchWheel(int channel, int pitch)
pitchSwitched = false;
}
void sfz::Region::registerAftertouch(int channel, uint8_t aftertouch)
void sfz::Region::registerAftertouch(int channel, uint8_t aftertouch) noexcept
{
if (!channelRange.containsWithEnd(channel))
return;
@ -539,7 +539,7 @@ void sfz::Region::registerAftertouch(int channel, uint8_t aftertouch)
aftertouchSwitched = false;
}
void sfz::Region::registerTempo(float secondsPerQuarter)
void sfz::Region::registerTempo(float secondsPerQuarter) noexcept
{
const float bpm = 60.0f / secondsPerQuarter;
if (bpmRange.containsWithEnd(bpm))
@ -557,16 +557,19 @@ float sfz::Region::getBasePitchVariation(int noteNumber, uint8_t velocity) noexc
pitchVariationInCents += pitchDistribution(Random::randomGenerator); // random pitch changes
return centsFactor(pitchVariationInCents);
}
float sfz::Region::getBaseGain() noexcept
{
float baseGaindB { volume };
baseGaindB += gainDistribution(Random::randomGenerator);
return db2mag(baseGaindB);
}
uint32_t sfz::Region::getOffset() noexcept
{
return offset + offsetDistribution(Random::randomGenerator);
}
uint32_t sfz::Region::getDelay() noexcept
{
return delay + delayDistribution(Random::randomGenerator);
@ -576,6 +579,7 @@ uint32_t sfz::Region::trueSampleEnd() const noexcept
{
return min(sampleEnd, loopRange.getEnd());
}
bool sfz::Region::canUsePreloadedData() const noexcept
{
if (preloadedData == nullptr)

View file

@ -23,12 +23,12 @@ struct Region {
bool isGenerator() const noexcept { return sample.size() > 0 ? sample[0] == '*' : false; }
bool shouldLoop() const noexcept { return (loopMode == SfzLoopMode::loop_continuous || loopMode == SfzLoopMode::loop_sustain); }
bool isSwitchedOn() const noexcept;
bool registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue);
bool registerNoteOff(int channel, int noteNumber, uint8_t velocity, float randValue);
bool registerCC(int channel, int ccNumber, uint8_t ccValue);
void registerPitchWheel(int channel, int pitch);
void registerAftertouch(int channel, uint8_t aftertouch);
void registerTempo(float secondsPerQuarter);
bool registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue) noexcept;
bool registerNoteOff(int channel, int noteNumber, uint8_t velocity, float randValue) noexcept;
bool registerCC(int channel, int ccNumber, uint8_t ccValue) noexcept;
void registerPitchWheel(int channel, int pitch) noexcept;
void registerAftertouch(int channel, uint8_t aftertouch) noexcept;
void registerTempo(float secondsPerQuarter) noexcept;
bool isStereo() const noexcept;
float getBasePitchVariation(int noteNumber, uint8_t velocity) noexcept;
float getBaseGain() noexcept;

View file

@ -176,7 +176,7 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename)
return parserReturned;
}
sfz::Voice* sfz::Synth::findFreeVoice()
sfz::Voice* sfz::Synth::findFreeVoice() noexcept
{
auto freeVoice = absl::c_find_if(voices, [](const auto& voice) { return voice->isFree(); });
if (freeVoice == voices.end()) {
@ -186,7 +186,7 @@ sfz::Voice* sfz::Synth::findFreeVoice()
return freeVoice->get();
}
void sfz::Synth::getNumActiveVoices() const
void sfz::Synth::getNumActiveVoices() const noexcept
{
auto activeVoices { 0 };
for (const auto& voice : voices) {
@ -195,14 +195,14 @@ void sfz::Synth::getNumActiveVoices() const
}
}
void sfz::Synth::garbageCollect()
void sfz::Synth::garbageCollect() noexcept
{
for (auto& voice : voices) {
voice->garbageCollect();
}
}
void sfz::Synth::setSamplesPerBlock(int samplesPerBlock)
void sfz::Synth::setSamplesPerBlock(int samplesPerBlock) noexcept
{
DBG("[Synth] Samples per block set to " << samplesPerBlock);
this->samplesPerBlock = samplesPerBlock;
@ -211,7 +211,7 @@ void sfz::Synth::setSamplesPerBlock(int samplesPerBlock)
voice->setSamplesPerBlock(samplesPerBlock);
}
void sfz::Synth::setSampleRate(float sampleRate)
void sfz::Synth::setSampleRate(float sampleRate) noexcept
{
DBG("[Synth] Sample rate set to " << sampleRate);
this->sampleRate = sampleRate;
@ -219,7 +219,7 @@ void sfz::Synth::setSampleRate(float sampleRate)
voice->setSampleRate(sampleRate);
}
void sfz::Synth::renderBlock(StereoSpan<float> buffer)
void sfz::Synth::renderBlock(StereoSpan<float> buffer) noexcept
{
ScopedFTZ ftz;
buffer.fill(0.0f);
@ -230,7 +230,7 @@ void sfz::Synth::renderBlock(StereoSpan<float> buffer)
}
}
void sfz::Synth::noteOn(int delay, int channel, int noteNumber, uint8_t velocity)
void sfz::Synth::noteOn(int delay, int channel, int noteNumber, uint8_t velocity) noexcept
{
auto randValue = randNoteDistribution(Random::randomGenerator);
@ -251,7 +251,7 @@ void sfz::Synth::noteOn(int delay, int channel, int noteNumber, uint8_t velocity
}
}
void sfz::Synth::noteOff(int delay, int channel, int noteNumber, uint8_t velocity)
void sfz::Synth::noteOff(int delay, int channel, int noteNumber, uint8_t velocity) noexcept
{
auto randValue = randNoteDistribution(Random::randomGenerator);
for (auto& voice : voices)
@ -269,7 +269,7 @@ void sfz::Synth::noteOff(int delay, int channel, int noteNumber, uint8_t velocit
}
}
void sfz::Synth::cc(int delay, int channel, int ccNumber, uint8_t ccValue)
void sfz::Synth::cc(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept
{
for (auto& voice : voices)
voice->registerCC(delay, channel, ccNumber, ccValue);
@ -286,4 +286,33 @@ void sfz::Synth::cc(int delay, int channel, int ccNumber, uint8_t ccValue)
filePool.enqueueLoading(voice, region->sample, region->trueSampleEnd());
}
}
}
int sfz::Synth::getNumRegions() const noexcept
{
return static_cast<int>(regions.size());
}
int sfz::Synth::getNumGroups() const noexcept
{
return numGroups;
}
int sfz::Synth::getNumMasters() const noexcept
{
return numMasters;
}
int sfz::Synth::getNumCurves() const noexcept
{
return numCurves;
}
const sfz::Region* sfz::Synth::getRegionView(int idx) const noexcept
{
return (size_t)idx < regions.size() ? regions[idx].get() : nullptr;
}
std::set<std::string_view> sfz::Synth::getUnknownOpcodes() const noexcept
{
return unknownOpcodes;
}
size_t sfz::Synth::getNumPreloadedSamples() const noexcept
{
return filePool.getNumPreloadedSamples();
}

View file

@ -22,27 +22,27 @@ public:
Synth();
bool loadSfzFile(const std::filesystem::path& file) final;
int getNumRegions() const noexcept { return static_cast<int>(regions.size()); }
int getNumGroups() const noexcept { return numGroups; }
int getNumMasters() const noexcept { return numMasters; }
int getNumCurves() const noexcept { return numCurves; }
const Region* getRegionView(int idx) const noexcept { return (size_t)idx < regions.size() ? regions[idx].get() : nullptr; }
auto getUnknownOpcodes() { return unknownOpcodes; }
size_t getNumPreloadedSamples() { return filePool.getNumPreloadedSamples(); }
int getNumRegions() const noexcept;
int getNumGroups() const noexcept;
int getNumMasters() const noexcept;
int getNumCurves() const noexcept;
const Region* getRegionView(int idx) const noexcept;
std::set<std::string_view> getUnknownOpcodes() const noexcept;
size_t getNumPreloadedSamples() const noexcept;
void setSamplesPerBlock(int samplesPerBlock);
void setSampleRate(float sampleRate);
void renderBlock(StereoSpan<float> buffer);
void setSamplesPerBlock(int samplesPerBlock) noexcept;
void setSampleRate(float sampleRate) noexcept;
void renderBlock(StereoSpan<float> buffer) noexcept;
void noteOn(int delay, int channel, int noteNumber, uint8_t velocity);
void noteOff(int delay, int channel, int noteNumber, uint8_t velocity);
void cc(int delay, int channel, int ccNumber, uint8_t ccValue);
void pitchWheel(int delay, int channel, int pitch);
void aftertouch(int delay, int channel, uint8_t aftertouch);
void tempo(int delay, float secondsPerQuarter);
void noteOn(int delay, int channel, int noteNumber, uint8_t velocity) noexcept;
void noteOff(int delay, int channel, int noteNumber, uint8_t velocity) noexcept;
void cc(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept;
void pitchWheel(int delay, int channel, int pitch) noexcept;
void aftertouch(int delay, int channel, uint8_t aftertouch) noexcept;
void tempo(int delay, float secondsPerQuarter) noexcept;
void getNumActiveVoices() const;
void garbageCollect();
void getNumActiveVoices() const noexcept;
void garbageCollect() noexcept;
protected:
void callback(std::string_view header, const std::vector<Opcode>& members) final;
@ -63,7 +63,7 @@ private:
FilePool filePool;
CCValueArray ccState;
Voice* findFreeVoice();
Voice* findFreeVoice() noexcept;
std::vector<CCNamePair> ccNames;
std::optional<uint8_t> defaultSwitch;
std::set<std::string_view> unknownOpcodes;

View file

@ -7,7 +7,7 @@ sfz::Voice::Voice(const CCValueArray& ccState)
{
}
void sfz::Voice::startVoice(Region* region, int delay, int channel, int number, uint8_t value, sfz::Voice::TriggerType triggerType)
void sfz::Voice::startVoice(Region* region, int delay, int channel, int number, uint8_t value, sfz::Voice::TriggerType triggerType) noexcept
{
this->triggerType = triggerType;
triggerNumber = number;
@ -32,7 +32,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int channel, int number,
prepareEGEnvelope(delay, value);
}
void sfz::Voice::prepareEGEnvelope(int delay, uint8_t velocity)
void sfz::Voice::prepareEGEnvelope(int delay, uint8_t velocity) noexcept
{
auto secondsToSamples = [this](auto timeInSeconds) {
return static_cast<int>(timeInSeconds * sampleRate);
@ -48,18 +48,18 @@ void sfz::Voice::prepareEGEnvelope(int delay, uint8_t velocity)
normalizePercents(region->amplitudeEG.getStart(ccState, velocity)));
}
void sfz::Voice::setFileData(std::unique_ptr<StereoBuffer<float>> file)
void sfz::Voice::setFileData(std::unique_ptr<StereoBuffer<float>> file) noexcept
{
fileData = std::move(file);
dataReady.store(true);
}
bool sfz::Voice::isFree() const
bool sfz::Voice::isFree() const noexcept
{
return (region == nullptr);
}
void sfz::Voice::registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity [[maybe_unused]])
void sfz::Voice::registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity [[maybe_unused]]) noexcept
{
if (region == nullptr)
return;
@ -78,33 +78,33 @@ void sfz::Voice::registerNoteOff(int delay, int channel, int noteNumber, uint8_t
}
}
void sfz::Voice::registerCC(int delay, int channel [[maybe_unused]], int ccNumber, uint8_t ccValue)
void sfz::Voice::registerCC(int delay, int channel [[maybe_unused]], int ccNumber, uint8_t ccValue) noexcept
{
if (ccNumber == 64 && noteIsOff && ccValue < 63)
egEnvelope.startRelease(delay);
}
void sfz::Voice::registerPitchWheel(int delay [[maybe_unused]], int channel [[maybe_unused]], int pitch [[maybe_unused]])
void sfz::Voice::registerPitchWheel(int delay [[maybe_unused]], int channel [[maybe_unused]], int pitch [[maybe_unused]]) noexcept
{
}
void sfz::Voice::registerAftertouch(int delay [[maybe_unused]], int channel [[maybe_unused]], uint8_t aftertouch [[maybe_unused]])
void sfz::Voice::registerAftertouch(int delay [[maybe_unused]], int channel [[maybe_unused]], uint8_t aftertouch [[maybe_unused]]) noexcept
{
}
void sfz::Voice::registerTempo(int delay [[maybe_unused]], float secondsPerQuarter [[maybe_unused]])
void sfz::Voice::registerTempo(int delay [[maybe_unused]], float secondsPerQuarter [[maybe_unused]]) noexcept
{
}
void sfz::Voice::setSampleRate(float sampleRate)
void sfz::Voice::setSampleRate(float sampleRate) noexcept
{
this->sampleRate = sampleRate;
}
void sfz::Voice::setSamplesPerBlock(int samplesPerBlock)
void sfz::Voice::setSamplesPerBlock(int samplesPerBlock) noexcept
{
this->samplesPerBlock = samplesPerBlock;
tempBuffer1.resize(samplesPerBlock);
@ -115,7 +115,7 @@ void sfz::Voice::setSamplesPerBlock(int samplesPerBlock)
indexSpan = absl::MakeSpan(indexBuffer);
}
void sfz::Voice::renderBlock(StereoSpan<float> buffer)
void sfz::Voice::renderBlock(StereoSpan<float> buffer) noexcept
{
const auto numSamples = buffer.size();
ASSERT(static_cast<int>(numSamples) <= samplesPerBlock);
@ -139,7 +139,7 @@ void sfz::Voice::renderBlock(StereoSpan<float> buffer)
reset();
}
void sfz::Voice::fillWithData(StereoSpan<float> buffer)
void sfz::Voice::fillWithData(StereoSpan<float> buffer) noexcept
{
auto source { [&]() {
if (region->canUsePreloadedData() || !dataReady)
@ -195,7 +195,7 @@ void sfz::Voice::fillWithData(StereoSpan<float> buffer)
}
}
void sfz::Voice::fillWithGenerator(StereoSpan<float> buffer)
void sfz::Voice::fillWithGenerator(StereoSpan<float> buffer) noexcept
{
if (region->sample != "*sine")
return;
@ -219,27 +219,27 @@ bool sfz::Voice::checkOffGroup(int delay [[maybe_unused]], uint32_t group) noexc
return false;
}
int sfz::Voice::getTriggerNumber() const
int sfz::Voice::getTriggerNumber() const noexcept
{
return triggerNumber;
}
int sfz::Voice::getTriggerChannel() const
int sfz::Voice::getTriggerChannel() const noexcept
{
return triggerNumber;
}
uint8_t sfz::Voice::getTriggerValue() const
uint8_t sfz::Voice::getTriggerValue() const noexcept
{
return triggerNumber;
}
sfz::Voice::TriggerType sfz::Voice::getTriggerType() const
sfz::Voice::TriggerType sfz::Voice::getTriggerType() const noexcept
{
return triggerType;
}
void sfz::Voice::reset()
void sfz::Voice::reset() noexcept
{
dataReady.store(false);
state = State::idle;
@ -252,7 +252,7 @@ void sfz::Voice::reset()
noteIsOff = false;
}
void sfz::Voice::garbageCollect()
void sfz::Voice::garbageCollect() noexcept
{
if (state == State::idle && region == nullptr)
fileData.reset();

View file

@ -17,33 +17,33 @@ public:
NoteOff,
CC
};
void setSampleRate(float sampleRate);
void setSamplesPerBlock(int samplesPerBlock);
void setSampleRate(float sampleRate) noexcept;
void setSamplesPerBlock(int samplesPerBlock) noexcept;
void startVoice(Region* region, int delay, int channel, int number, uint8_t value, TriggerType triggerType);
void startVoice(Region* region, int delay, int channel, int number, uint8_t value, TriggerType triggerType) noexcept;
void setFileData(std::unique_ptr<StereoBuffer<float>> file);
void registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity);
void registerCC(int delay, int channel, int ccNumber, uint8_t ccValue);
void registerPitchWheel(int delay, int channel, int pitch);
void registerAftertouch(int delay, int channel, uint8_t aftertouch);
void registerTempo(int delay, float secondsPerQuarter);
void setFileData(std::unique_ptr<StereoBuffer<float>> file) 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;
void registerAftertouch(int delay, int channel, uint8_t aftertouch) noexcept;
void registerTempo(int delay, float secondsPerQuarter) noexcept;
bool checkOffGroup(int delay [[maybe_unused]], uint32_t group) noexcept;
void renderBlock(StereoSpan<float> buffer);
void renderBlock(StereoSpan<float> buffer) noexcept;
bool isFree() const;
int getTriggerNumber() const;
int getTriggerChannel() const;
uint8_t getTriggerValue() const;
TriggerType getTriggerType() const;
bool isFree() const noexcept;
int getTriggerNumber() const noexcept;
int getTriggerChannel() const noexcept;
uint8_t getTriggerValue() const noexcept;
TriggerType getTriggerType() const noexcept;
void reset();
void garbageCollect();
void reset() noexcept;
void garbageCollect() noexcept;
private:
void fillWithData(StereoSpan<float> buffer);
void fillWithGenerator(StereoSpan<float> buffer);
void prepareEGEnvelope(int delay, uint8_t velocity);
void fillWithData(StereoSpan<float> buffer) noexcept;
void fillWithGenerator(StereoSpan<float> buffer) noexcept;
void prepareEGEnvelope(int delay, uint8_t velocity) noexcept;
Region* region { nullptr };