From a8b2c9dfa823fdc78051a200f33e3e801ab7dbfc Mon Sep 17 00:00:00 2001 From: paulfd Date: Thu, 29 Aug 2019 16:23:35 +0200 Subject: [PATCH] Noexcepts --- sources/FilePool.cpp | 6 +++--- sources/FilePool.h | 21 +++++--------------- sources/Region.cpp | 18 ++++++++++------- sources/Region.h | 12 +++++------ sources/Synth.cpp | 47 +++++++++++++++++++++++++++++++++++--------- sources/Synth.h | 38 +++++++++++++++++------------------ sources/Voice.cpp | 40 ++++++++++++++++++------------------- sources/Voice.h | 40 ++++++++++++++++++------------------- 8 files changed, 122 insertions(+), 100 deletions(-) diff --git a/sources/FilePool.cpp b/sources/FilePool.cpp index fe2af015..5ba1b218 100644 --- a/sources/FilePool.cpp +++ b/sources/FilePool.cpp @@ -19,7 +19,7 @@ void readFromFile(SndfileHandle& sndFile, int numFrames, StereoBuffer& output } } -std::optional sfz::FilePool::getFileInformation(std::string_view filename) +std::optional 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::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) { diff --git a/sources/FilePool.h b/sources/FilePool.h index f3adeebe..4e3e1e29 100644 --- a/sources/FilePool.h +++ b/sources/FilePool.h @@ -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> preloadedData; }; - std::optional getFileInformation(std::string_view filename); - void enqueueLoading(Voice* voice, std::string_view sample, int numFrames); - static void deleteAndTrackBuffers(StereoBuffer* buffer) - { - fileBuffers--; - delete buffer; - }; - static int getFileBuffers() - { - return fileBuffers.load(); - } - + std::optional 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 fileBuffers { 0 }; moodycamel::BlockingReaderWriterQueue loadingQueue; - void loadingThread(); + void loadingThread() noexcept; std::thread fileLoadingThread; bool quitThread { false }; absl::flat_hash_map>> preloadedData; diff --git a/sources/Region.cpp b/sources/Region.cpp index e17b0171..efdedf1d 100644 --- a/sources/Region.cpp +++ b/sources/Region.cpp @@ -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) diff --git a/sources/Region.h b/sources/Region.h index 8441de4d..97861944 100644 --- a/sources/Region.h +++ b/sources/Region.h @@ -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; diff --git a/sources/Synth.cpp b/sources/Synth.cpp index 4544ff84..74977931 100644 --- a/sources/Synth.cpp +++ b/sources/Synth.cpp @@ -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 buffer) +void sfz::Synth::renderBlock(StereoSpan buffer) noexcept { ScopedFTZ ftz; buffer.fill(0.0f); @@ -230,7 +230,7 @@ void sfz::Synth::renderBlock(StereoSpan 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(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 sfz::Synth::getUnknownOpcodes() const noexcept +{ + return unknownOpcodes; +} +size_t sfz::Synth::getNumPreloadedSamples() const noexcept +{ + return filePool.getNumPreloadedSamples(); } \ No newline at end of file diff --git a/sources/Synth.h b/sources/Synth.h index dae03f90..75f9d2ce 100644 --- a/sources/Synth.h +++ b/sources/Synth.h @@ -22,27 +22,27 @@ public: Synth(); bool loadSfzFile(const std::filesystem::path& file) final; - int getNumRegions() const noexcept { return static_cast(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 getUnknownOpcodes() const noexcept; + size_t getNumPreloadedSamples() const noexcept; - void setSamplesPerBlock(int samplesPerBlock); - void setSampleRate(float sampleRate); - void renderBlock(StereoSpan buffer); + void setSamplesPerBlock(int samplesPerBlock) noexcept; + void setSampleRate(float sampleRate) noexcept; + void renderBlock(StereoSpan 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& members) final; @@ -63,7 +63,7 @@ private: FilePool filePool; CCValueArray ccState; - Voice* findFreeVoice(); + Voice* findFreeVoice() noexcept; std::vector ccNames; std::optional defaultSwitch; std::set unknownOpcodes; diff --git a/sources/Voice.cpp b/sources/Voice.cpp index 3ed3cf4d..c46fb4e8 100644 --- a/sources/Voice.cpp +++ b/sources/Voice.cpp @@ -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(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> file) +void sfz::Voice::setFileData(std::unique_ptr> 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 buffer) +void sfz::Voice::renderBlock(StereoSpan buffer) noexcept { const auto numSamples = buffer.size(); ASSERT(static_cast(numSamples) <= samplesPerBlock); @@ -139,7 +139,7 @@ void sfz::Voice::renderBlock(StereoSpan buffer) reset(); } -void sfz::Voice::fillWithData(StereoSpan buffer) +void sfz::Voice::fillWithData(StereoSpan buffer) noexcept { auto source { [&]() { if (region->canUsePreloadedData() || !dataReady) @@ -195,7 +195,7 @@ void sfz::Voice::fillWithData(StereoSpan buffer) } } -void sfz::Voice::fillWithGenerator(StereoSpan buffer) +void sfz::Voice::fillWithGenerator(StereoSpan 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(); diff --git a/sources/Voice.h b/sources/Voice.h index 3ce66e38..81794388 100644 --- a/sources/Voice.h +++ b/sources/Voice.h @@ -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> 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> 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 buffer); + void renderBlock(StereoSpan 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 buffer); - void fillWithGenerator(StereoSpan buffer); - void prepareEGEnvelope(int delay, uint8_t velocity); + void fillWithData(StereoSpan buffer) noexcept; + void fillWithGenerator(StereoSpan buffer) noexcept; + void prepareEGEnvelope(int delay, uint8_t velocity) noexcept; Region* region { nullptr };