From ed2536b5cec57c588280017016a0d206ae56e128 Mon Sep 17 00:00:00 2001 From: paulfd Date: Sat, 21 Sep 2019 01:05:43 +0200 Subject: [PATCH 1/9] Math helpers stay with static --- sfizz/MathHelpers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sfizz/MathHelpers.h b/sfizz/MathHelpers.h index b4b1a953..0e3d074e 100644 --- a/sfizz/MathHelpers.h +++ b/sfizz/MathHelpers.h @@ -60,8 +60,8 @@ inline constexpr Type mag2db(Type in) } namespace Random { -static SFZ_INLINE std::random_device randomDevice; -static SFZ_INLINE std::mt19937 randomGenerator { randomDevice() }; + static SFZ_INLINE std::random_device randomDevice; + static SFZ_INLINE std::mt19937 randomGenerator { randomDevice() }; } // namespace Random inline float midiNoteFrequency(const int noteNumber) From 144916bd39a98d6e8b50228c527bccfec32829f3 Mon Sep 17 00:00:00 2001 From: paulfd Date: Sat, 21 Sep 2019 01:06:01 +0200 Subject: [PATCH 2/9] Corrected a bug in the one pole filter --- sfizz/OnePoleFilter.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sfizz/OnePoleFilter.h b/sfizz/OnePoleFilter.h index 14d080ac..d7d1aad6 100644 --- a/sfizz/OnePoleFilter.h +++ b/sfizz/OnePoleFilter.h @@ -89,6 +89,9 @@ public: while (in < sentinel) { setGain(*g); oneLowpass(in, out); + in++; + out++; + g++; } return size; } @@ -103,6 +106,9 @@ public: while (in < sentinel) { setGain(*g); oneLowpass(in, out); + in++; + out++; + g++; } return size; } From 32865b5841ad5e936318cca3d494326136def061 Mon Sep 17 00:00:00 2001 From: paulfd Date: Sat, 21 Sep 2019 01:06:47 +0200 Subject: [PATCH 3/9] Regexes get their own file --- sfizz/Parser.cpp | 2 ++ sfizz/Parser.h | 11 +---------- tests/RegexT.cpp | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/sfizz/Parser.cpp b/sfizz/Parser.cpp index e5b18ab4..307c0664 100644 --- a/sfizz/Parser.cpp +++ b/sfizz/Parser.cpp @@ -26,7 +26,9 @@ #include "StringViewHelpers.h" #include "absl/strings/str_join.h" #include "absl/strings/str_cat.h" +#include "Regexes.h" #include +#include #include using svregex_iterator = std::regex_iterator; diff --git a/sfizz/Parser.h b/sfizz/Parser.h index 7c300a25..481b6eb0 100644 --- a/sfizz/Parser.h +++ b/sfizz/Parser.h @@ -25,20 +25,11 @@ #include "Opcode.h" #include "compat/filesystem.h" #include -#include #include -#include +#include "absl/strings/string_view.h" #include namespace sfz { -namespace Regexes { - SFZ_INLINE static std::regex includes { R"V(#include\s*"(.*?)".*$)V", std::regex::optimize }; - SFZ_INLINE static std::regex defines { R"(#define\s*(\$[a-zA-Z0-9]+)\s+([a-zA-Z0-9]+)(?=\s|$))", std::regex::optimize }; - SFZ_INLINE static std::regex headers { R"(<(.*?)>(.*?)(?=<|$))", std::regex::optimize }; - SFZ_INLINE static std::regex members { R"(([a-zA-Z0-9_]+)=([a-zA-Z0-9-_#.&\/\s\\\(\),\*]+)(?![a-zA-Z0-9_]*=))", std::regex::optimize }; - SFZ_INLINE static std::regex opcodeParameters { R"(([a-zA-Z0-9_]+?)([0-9]+)$)", std::regex::optimize }; -} - class Parser { public: virtual bool loadSfzFile(const std::filesystem::path& file); diff --git a/tests/RegexT.cpp b/tests/RegexT.cpp index 50c79a06..836c7637 100644 --- a/tests/RegexT.cpp +++ b/tests/RegexT.cpp @@ -21,7 +21,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "Parser.h" +#include "Regexes.h" #include "catch2/catch.hpp" using namespace Catch::literals; From d4a11782337afaff4836fc21fd2be63132aa282c Mon Sep 17 00:00:00 2001 From: paulfd Date: Sat, 21 Sep 2019 01:07:53 +0200 Subject: [PATCH 4/9] ccState and the midiState globals become a single private member of the Synth object; read-only references are loaded on creation into the regions and voice. --- sfizz/MidiState.h | 15 +++-- sfizz/Region.cpp | 2 +- sfizz/Region.h | 5 +- sfizz/SfzHelpers.h | 2 +- sfizz/Synth.cpp | 16 ++--- sfizz/Synth.h | 3 +- sfizz/Voice.cpp | 32 +++++----- sfizz/Voice.h | 5 +- tests/RegionActivationT.cpp | 4 +- tests/RegionCrossfadesT.cpp | 117 ++++++++++++++++++++---------------- tests/RegionT.cpp | 12 ++-- tests/RegionTriggersT.cpp | 7 ++- 12 files changed, 127 insertions(+), 93 deletions(-) diff --git a/sfizz/MidiState.h b/sfizz/MidiState.h index fd575529..b6725533 100644 --- a/sfizz/MidiState.h +++ b/sfizz/MidiState.h @@ -1,10 +1,13 @@ +#pragma once #include #include +#include "SfzHelpers.h" #include "compat/utils.h" + namespace sfz { - SFZ_INLINE std::array noteOnTimes { }; - SFZ_INLINE std::array lastNoteVelocities { }; +struct MidiState +{ inline void noteOn(int noteNumber, uint8_t velocity) { if (noteNumber >= 0 && noteNumber < 128) { @@ -13,7 +16,7 @@ namespace sfz } } - inline float getNoteDuration(int noteNumber) + inline float getNoteDuration(int noteNumber) const { if (noteNumber >= 0 && noteNumber < 128) { const auto noteOffTime = std::chrono::steady_clock::now(); @@ -24,11 +27,15 @@ namespace sfz return 0.0f; } - inline uint8_t getNoteVelocity(int noteNumber) + inline uint8_t getNoteVelocity(int noteNumber) const { if (noteNumber >= 0 && noteNumber < 128) return lastNoteVelocities[noteNumber]; return 0; } + std::array noteOnTimes { }; + std::array lastNoteVelocities { }; + CCValueArray cc; +}; } diff --git a/sfizz/Region.cpp b/sfizz/Region.cpp index e6126be5..39ae614f 100644 --- a/sfizz/Region.cpp +++ b/sfizz/Region.cpp @@ -635,7 +635,7 @@ float sfz::Region::getBaseVolumedB(int noteNumber) noexcept { auto baseVolumedB = volume + volumeDistribution(Random::randomGenerator); if (trigger == SfzTrigger::release || trigger == SfzTrigger::release_key) - baseVolumedB -= rtDecay * getNoteDuration(noteNumber); + baseVolumedB -= rtDecay * midiState.getNoteDuration(noteNumber); return baseVolumedB; } diff --git a/sfizz/Region.h b/sfizz/Region.h index 61a9a6e1..f4173460 100644 --- a/sfizz/Region.h +++ b/sfizz/Region.h @@ -28,6 +28,7 @@ #include "EGDescription.h" #include "Opcode.h" #include "AudioBuffer.h" +#include "MidiState.h" #include #include #include @@ -36,7 +37,8 @@ namespace sfz { struct Region { - Region() + Region(const MidiState& midiState) + : midiState(midiState) { ccSwitched.set(); } @@ -154,6 +156,7 @@ struct Region { double sampleRate { config::defaultSampleRate }; std::shared_ptr> preloadedData { nullptr }; private: + const MidiState& midiState; bool keySwitched { true }; bool previousKeySwitched { true }; bool sequenceSwitched { true }; diff --git a/sfizz/SfzHelpers.h b/sfizz/SfzHelpers.h index 10151814..87df290f 100644 --- a/sfizz/SfzHelpers.h +++ b/sfizz/SfzHelpers.h @@ -44,7 +44,7 @@ inline constexpr float centsFactor(T cents, T centsPerOctave = 1200) template inline constexpr float normalizeCC(T ccValue) { - static_assert(std::is_integral::value); + static_assert(std::is_integral::value, "Requires an integral T"); return static_cast(std::min(std::max(ccValue, static_cast(0)), static_cast(127))) / 127.0f; } diff --git a/sfizz/Synth.cpp b/sfizz/Synth.cpp index 87a647c2..4f9875bc 100644 --- a/sfizz/Synth.cpp +++ b/sfizz/Synth.cpp @@ -37,7 +37,7 @@ using namespace std::literals; sfz::Synth::Synth() { for (int i = 0; i < config::numVoices; ++i) - voices.push_back(std::make_unique(ccState)); + voices.push_back(std::make_unique(midiState)); voiceViewArray.reserve(config::numVoices); } @@ -83,7 +83,7 @@ void sfz::Synth::callback(absl::string_view header, const std::vector& m void sfz::Synth::buildRegion(const std::vector& regionOpcodes) { - auto lastRegion = std::make_unique(); + auto lastRegion = std::make_unique(midiState); auto parseOpcodes = [&](const auto& opcodes) { for (auto& opcode : opcodes) { @@ -114,7 +114,7 @@ void sfz::Synth::clear() numCurves = 0; fileTicket = -1; defaultSwitch = absl::nullopt; - for (auto& state : ccState) + for (auto& state : midiState.cc) state = 0; ccNames.clear(); globalOpcodes.clear(); @@ -142,7 +142,7 @@ void sfz::Synth::handleControlOpcodes(const std::vector& members) case hash("Set_cc"): [[fallthrough]]; case hash("set_cc"): if (member.parameter && Default::ccRange.containsWithEnd(*member.parameter)) - setValueFromOpcode(member, ccState[*member.parameter], Default::ccRange); + setValueFromOpcode(member, midiState.cc[*member.parameter], Default::ccRange); break; case hash("Label_cc"): [[fallthrough]]; case hash("label_cc"): @@ -230,7 +230,7 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename) // Defaults for (int ccIndex = 1; ccIndex < 128; ccIndex++) - region->registerCC(region->channelRange.getStart(), ccIndex, ccState[ccIndex]); + region->registerCC(region->channelRange.getStart(), ccIndex, midiState.cc[ccIndex]); if (defaultSwitch) { region->registerNoteOn(region->channelRange.getStart(), *defaultSwitch, 127, 1.0); @@ -333,7 +333,7 @@ void sfz::Synth::noteOn(int delay, int channel, int noteNumber, uint8_t velocity ASSERT(noteNumber < 128); ASSERT(noteNumber >= 0); - sfz::noteOn(noteNumber, velocity); + midiState.noteOn(noteNumber, velocity); auto randValue = randNoteDistribution(Random::randomGenerator); for (auto& region : noteActivationLists[noteNumber]) { @@ -361,7 +361,7 @@ void sfz::Synth::noteOff(int delay, int channel, int noteNumber, uint8_t velocit ASSERT(noteNumber < 128); ASSERT(noteNumber >= 0); - auto replacedVelocity = velocity == 0 ? sfz::getNoteVelocity(noteNumber) : velocity; + auto replacedVelocity = velocity == 0 ? midiState.getNoteVelocity(noteNumber) : velocity; auto randValue = randNoteDistribution(Random::randomGenerator); for (auto& voice : voices) voice->registerNoteOff(delay, channel, noteNumber, replacedVelocity); @@ -389,7 +389,7 @@ void sfz::Synth::cc(int delay, int channel, int ccNumber, uint8_t ccValue) noexc for (auto& voice : voices) voice->registerCC(delay, channel, ccNumber, ccValue); - ccState[ccNumber] = ccValue; + midiState.cc[ccNumber] = ccValue; for (auto& region : ccActivationLists[ccNumber]) { if (region->registerCC(channel, ccNumber, ccValue)) { diff --git a/sfizz/Synth.h b/sfizz/Synth.h index 80f45343..763415e4 100644 --- a/sfizz/Synth.h +++ b/sfizz/Synth.h @@ -26,6 +26,7 @@ #include "Parser.h" #include "Region.h" #include "LeakDetector.h" +#include "MidiState.h" #include "AudioSpan.h" #include "absl/types/span.h" #include @@ -80,7 +81,7 @@ private: std::vector groupOpcodes; FilePool filePool; - CCValueArray ccState; + MidiState midiState; Voice* findFreeVoice() noexcept; std::vector ccNames; absl::optional defaultSwitch; diff --git a/sfizz/Voice.cpp b/sfizz/Voice.cpp index 5aef90ff..8beee826 100644 --- a/sfizz/Voice.cpp +++ b/sfizz/Voice.cpp @@ -31,8 +31,8 @@ #include "absl/algorithm/container.h" #include -sfz::Voice::Voice(const CCValueArray& ccState) - : ccState(ccState) +sfz::Voice::Voice(const MidiState& midiState) + : midiState(midiState) { } @@ -59,39 +59,39 @@ void sfz::Voice::startVoice(Region* region, int delay, int channel, int number, auto volumedB { baseVolumedB }; if (region->volumeCC) - volumedB += normalizeCC(ccState[region->volumeCC->first]) * region->volumeCC->second; + volumedB += normalizeCC(midiState.cc[region->volumeCC->first]) * region->volumeCC->second; volumeEnvelope.reset(db2mag(volumedB)); // DBG("Base volume: " << baseVolumedB << " dB - with modifier: " << volumedB << " dB"); baseGain = region->getBaseGain(); - baseGain *= region->getCrossfadeGain(ccState); + baseGain *= region->getCrossfadeGain(midiState.cc); if (triggerType != TriggerType::CC) baseGain *= region->getNoteGain(number, value); float gain { baseGain }; if (region->amplitudeCC) - gain *= normalizeCC(ccState[region->amplitudeCC->first]) * normalizePercents(region->amplitudeCC->second); + gain *= normalizeCC(midiState.cc[region->amplitudeCC->first]) * normalizePercents(region->amplitudeCC->second); amplitudeEnvelope.reset(gain); // DBG("Base gain: " << baseGain << " - with modifier: " << gain); basePan = normalizeNegativePercents(region->pan); auto pan { basePan }; if (region->panCC) - pan += normalizeCC(ccState[region->panCC->first]) * normalizeNegativePercents(region->panCC->second); + pan += normalizeCC(midiState.cc[region->panCC->first]) * normalizeNegativePercents(region->panCC->second); panEnvelope.reset(pan); // DBG("Base pan: " << basePan << " - with modifier: " << pan); basePosition = normalizeNegativePercents(region->position); auto position { basePosition }; if (region->positionCC) - position += normalizeCC(ccState[region->positionCC->first]) * normalizeNegativePercents(region->positionCC->second); + position += normalizeCC(midiState.cc[region->positionCC->first]) * normalizeNegativePercents(region->positionCC->second); positionEnvelope.reset(position); // DBG("Base position: " << basePosition << " - with modifier: " << position); baseWidth = normalizeNegativePercents(region->width); auto width { baseWidth }; if (region->widthCC) - width += normalizeCC(ccState[region->widthCC->first]) * normalizeNegativePercents(region->widthCC->second); + width += normalizeCC(midiState.cc[region->widthCC->first]) * normalizeNegativePercents(region->widthCC->second); widthEnvelope.reset(width); // DBG("Base width: " << baseWidth << " - with modifier: " << width); @@ -109,13 +109,13 @@ void sfz::Voice::prepareEGEnvelope(int delay, uint8_t velocity) noexcept }; egEnvelope.reset( - secondsToSamples(region->amplitudeEG.getAttack(ccState, velocity)), - secondsToSamples(region->amplitudeEG.getRelease(ccState, velocity)), - normalizePercents(region->amplitudeEG.getSustain(ccState, velocity)), - delay + secondsToSamples(region->amplitudeEG.getDelay(ccState, velocity)), - secondsToSamples(region->amplitudeEG.getDecay(ccState, velocity)), - secondsToSamples(region->amplitudeEG.getHold(ccState, velocity)), - normalizePercents(region->amplitudeEG.getStart(ccState, velocity))); + secondsToSamples(region->amplitudeEG.getAttack(midiState.cc, velocity)), + secondsToSamples(region->amplitudeEG.getRelease(midiState.cc, velocity)), + normalizePercents(region->amplitudeEG.getSustain(midiState.cc, velocity)), + delay + secondsToSamples(region->amplitudeEG.getDelay(midiState.cc, velocity)), + secondsToSamples(region->amplitudeEG.getDecay(midiState.cc, velocity)), + secondsToSamples(region->amplitudeEG.getHold(midiState.cc, velocity)), + normalizePercents(region->amplitudeEG.getStart(midiState.cc, velocity))); } void sfz::Voice::setFileData(std::shared_ptr> file, unsigned ticket) noexcept @@ -154,7 +154,7 @@ void sfz::Voice::registerNoteOff(int delay, int channel, int noteNumber, uint8_t if (region->loopMode == SfzLoopMode::one_shot) return; - if (!region->checkSustain || ccState[config::sustainCC] < config::halfCCThreshold) + if (!region->checkSustain || midiState.cc[config::sustainCC] < config::halfCCThreshold) release(delay); } } diff --git a/sfizz/Voice.h b/sfizz/Voice.h index 5ed9cd14..ae58b756 100644 --- a/sfizz/Voice.h +++ b/sfizz/Voice.h @@ -28,6 +28,7 @@ #include "HistoricalBuffer.h" #include "Region.h" #include "AudioBuffer.h" +#include "MidiState.h" #include "AudioSpan.h" #include "LeakDetector.h" #include @@ -38,7 +39,7 @@ namespace sfz { class Voice { public: Voice() = delete; - Voice(const CCValueArray& ccState); + Voice(const MidiState& midiState); enum class TriggerType { NoteOn, NoteOff, @@ -124,7 +125,7 @@ private: int samplesPerBlock { config::defaultSamplesPerBlock }; float sampleRate { config::defaultSampleRate }; - const CCValueArray& ccState; + const MidiState& midiState; ADSREnvelope egEnvelope; LinearEnvelope volumeEnvelope; // dB events but the envelope output is linear gain LinearEnvelope amplitudeEnvelope; // linear events diff --git a/tests/RegionActivationT.cpp b/tests/RegionActivationT.cpp index 34e3d8b4..259cd399 100644 --- a/tests/RegionActivationT.cpp +++ b/tests/RegionActivationT.cpp @@ -27,7 +27,9 @@ using namespace Catch::literals; TEST_CASE("Region activation", "Region tests") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; + region.parseOpcode({ "sample", "*sine" }); SECTION("Basic state") { diff --git a/tests/RegionCrossfadesT.cpp b/tests/RegionCrossfadesT.cpp index e933c661..eec5597c 100644 --- a/tests/RegionCrossfadesT.cpp +++ b/tests/RegionCrossfadesT.cpp @@ -32,7 +32,8 @@ using namespace Catch::literals; TEST_CASE("[Region] Crossfade in on key") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_lokey", "1" }); region.parseOpcode({ "xfin_hikey", "3" }); @@ -43,7 +44,8 @@ TEST_CASE("[Region] Crossfade in on key") TEST_CASE("[Region] Crossfade in on key - 2") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_lokey", "1" }); region.parseOpcode({ "xfin_hikey", "5" }); @@ -57,7 +59,8 @@ TEST_CASE("[Region] Crossfade in on key - 2") TEST_CASE("[Region] Crossfade in on key - gain") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_lokey", "1" }); region.parseOpcode({ "xfin_hikey", "5" }); @@ -71,7 +74,8 @@ TEST_CASE("[Region] Crossfade in on key - gain") TEST_CASE("[Region] Crossfade out on key") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_lokey", "51" }); region.parseOpcode({ "xfout_hikey", "55" }); @@ -86,7 +90,8 @@ TEST_CASE("[Region] Crossfade out on key") TEST_CASE("[Region] Crossfade out on key - gain") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_lokey", "51" }); region.parseOpcode({ "xfout_hikey", "55" }); @@ -102,7 +107,8 @@ TEST_CASE("[Region] Crossfade out on key - gain") TEST_CASE("[Region] Crossfade in on velocity") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_lovel", "20" }); region.parseOpcode({ "xfin_hivel", "24" }); @@ -118,7 +124,8 @@ TEST_CASE("[Region] Crossfade in on velocity") TEST_CASE("[Region] Crossfade in on vel - gain") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_lovel", "20" }); region.parseOpcode({ "xfin_hivel", "24" }); @@ -135,7 +142,8 @@ TEST_CASE("[Region] Crossfade in on vel - gain") TEST_CASE("[Region] Crossfade out on vel") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_lovel", "51" }); region.parseOpcode({ "xfout_hivel", "55" }); @@ -151,7 +159,8 @@ TEST_CASE("[Region] Crossfade out on vel") TEST_CASE("[Region] Crossfade out on vel - gain") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_lovel", "51" }); region.parseOpcode({ "xfout_hivel", "55" }); @@ -168,76 +177,77 @@ TEST_CASE("[Region] Crossfade out on vel - gain") TEST_CASE("[Region] Crossfade in on CC") { - sfz::Region region {}; - sfz::CCValueArray ccState; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_locc24", "20" }); region.parseOpcode({ "xfin_hicc24", "24" }); region.parseOpcode({ "amp_veltrack", "0" }); - ccState[24] = 19; REQUIRE( region.getCrossfadeGain(ccState) == 0.0_a ); - ccState[24] = 20; REQUIRE( region.getCrossfadeGain(ccState) == 0.0_a ); - ccState[24] = 21; REQUIRE( region.getCrossfadeGain(ccState) == 0.5_a ); - ccState[24] = 22; REQUIRE( region.getCrossfadeGain(ccState) == 0.70711_a ); - ccState[24] = 23; REQUIRE( region.getCrossfadeGain(ccState) == 0.86603_a ); - ccState[24] = 24; REQUIRE( region.getCrossfadeGain(ccState) == 1.0_a ); - ccState[24] = 25; REQUIRE( region.getCrossfadeGain(ccState) == 1.0_a ); + midiState.cc[24] = 19; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.0_a ); + midiState.cc[24] = 20; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.0_a ); + midiState.cc[24] = 21; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.5_a ); + midiState.cc[24] = 22; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.70711_a ); + midiState.cc[24] = 23; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.86603_a ); + midiState.cc[24] = 24; REQUIRE( region.getCrossfadeGain(midiState.cc) == 1.0_a ); + midiState.cc[24] = 25; REQUIRE( region.getCrossfadeGain(midiState.cc) == 1.0_a ); } TEST_CASE("[Region] Crossfade in on CC - gain") { - sfz::Region region {}; - sfz::CCValueArray ccState; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfin_locc24", "20" }); region.parseOpcode({ "xfin_hicc24", "24" }); region.parseOpcode({ "amp_veltrack", "0" }); region.parseOpcode({ "xf_cccurve", "gain" }); - ccState[24] = 19; REQUIRE( region.getCrossfadeGain(ccState) == 0.0_a ); - ccState[24] = 20; REQUIRE( region.getCrossfadeGain(ccState) == 0.0_a ); - ccState[24] = 21; REQUIRE( region.getCrossfadeGain(ccState) == 0.25_a ); - ccState[24] = 22; REQUIRE( region.getCrossfadeGain(ccState) == 0.5_a ); - ccState[24] = 23; REQUIRE( region.getCrossfadeGain(ccState) == 0.75_a ); - ccState[24] = 24; REQUIRE( region.getCrossfadeGain(ccState) == 1.0_a ); - ccState[24] = 25; REQUIRE( region.getCrossfadeGain(ccState) == 1.0_a ); + midiState.cc[24] = 19; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.0_a ); + midiState.cc[24] = 20; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.0_a ); + midiState.cc[24] = 21; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.25_a ); + midiState.cc[24] = 22; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.5_a ); + midiState.cc[24] = 23; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.75_a ); + midiState.cc[24] = 24; REQUIRE( region.getCrossfadeGain(midiState.cc) == 1.0_a ); + midiState.cc[24] = 25; REQUIRE( region.getCrossfadeGain(midiState.cc) == 1.0_a ); } TEST_CASE("[Region] Crossfade out on CC") { - sfz::Region region {}; - sfz::CCValueArray ccState; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_locc24", "20" }); region.parseOpcode({ "xfout_hicc24", "24" }); region.parseOpcode({ "amp_veltrack", "0" }); - ccState[24] = 19; REQUIRE( region.getCrossfadeGain(ccState) == 1.0_a ); - ccState[24] = 20; REQUIRE( region.getCrossfadeGain(ccState) == 1.0_a ); - ccState[24] = 21; REQUIRE( region.getCrossfadeGain(ccState) == 0.86603_a ); - ccState[24] = 22; REQUIRE( region.getCrossfadeGain(ccState) == 0.70711_a ); - ccState[24] = 23; REQUIRE( region.getCrossfadeGain(ccState) == 0.5_a ); - ccState[24] = 24; REQUIRE( region.getCrossfadeGain(ccState) == 0.0_a ); - ccState[24] = 25; REQUIRE( region.getCrossfadeGain(ccState) == 0.0_a ); + midiState.cc[24] = 19; REQUIRE( region.getCrossfadeGain(midiState.cc) == 1.0_a ); + midiState.cc[24] = 20; REQUIRE( region.getCrossfadeGain(midiState.cc) == 1.0_a ); + midiState.cc[24] = 21; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.86603_a ); + midiState.cc[24] = 22; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.70711_a ); + midiState.cc[24] = 23; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.5_a ); + midiState.cc[24] = 24; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.0_a ); + midiState.cc[24] = 25; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.0_a ); } TEST_CASE("[Region] Crossfade out on CC - gain") { - sfz::Region region {}; - sfz::CCValueArray ccState; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "xfout_locc24", "20" }); region.parseOpcode({ "xfout_hicc24", "24" }); region.parseOpcode({ "amp_veltrack", "0" }); region.parseOpcode({ "xf_cccurve", "gain" }); - ccState[24] = 19; REQUIRE( region.getCrossfadeGain(ccState) == 1.0_a ); - ccState[24] = 20; REQUIRE( region.getCrossfadeGain(ccState) == 1.0_a ); - ccState[24] = 21; REQUIRE( region.getCrossfadeGain(ccState) == 0.75_a ); - ccState[24] = 22; REQUIRE( region.getCrossfadeGain(ccState) == 0.5_a ); - ccState[24] = 23; REQUIRE( region.getCrossfadeGain(ccState) == 0.25_a ); - ccState[24] = 24; REQUIRE( region.getCrossfadeGain(ccState) == 0.0_a ); - ccState[24] = 25; REQUIRE( region.getCrossfadeGain(ccState) == 0.0_a ); + midiState.cc[24] = 19; REQUIRE( region.getCrossfadeGain(midiState.cc) == 1.0_a ); + midiState.cc[24] = 20; REQUIRE( region.getCrossfadeGain(midiState.cc) == 1.0_a ); + midiState.cc[24] = 21; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.75_a ); + midiState.cc[24] = 22; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.5_a ); + midiState.cc[24] = 23; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.25_a ); + midiState.cc[24] = 24; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.0_a ); + midiState.cc[24] = 25; REQUIRE( region.getCrossfadeGain(midiState.cc) == 0.0_a ); } TEST_CASE("[Region] Velocity bug for extreme values - veltrack at 0") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "amp_veltrack", "0" }); REQUIRE( region.getNoteGain(64, 127) == 1.0_a ); @@ -247,7 +257,8 @@ TEST_CASE("[Region] Velocity bug for extreme values - veltrack at 0") TEST_CASE("[Region] Velocity bug for extreme values - positive veltrack") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "amp_veltrack", "100" }); REQUIRE( region.getNoteGain(64, 127) == 1.0_a ); @@ -256,7 +267,8 @@ TEST_CASE("[Region] Velocity bug for extreme values - positive veltrack") TEST_CASE("[Region] Velocity bug for extreme values - negative veltrack") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "amp_veltrack", "-100" }); REQUIRE( region.getNoteGain(64, 127) == Approx(0.0).margin(0.0001) ); @@ -265,19 +277,20 @@ TEST_CASE("[Region] Velocity bug for extreme values - negative veltrack") TEST_CASE("[Region] rt_decay") { - sfz::Region region {}; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); region.parseOpcode({ "trigger", "release" }); region.parseOpcode({ "rt_decay", "10" }); - sfz::noteOn(64, 64); + midiState.noteOn(64, 64); std::this_thread::sleep_for(std::chrono::milliseconds(100)); REQUIRE( region.getBaseVolumedB(64) == Approx(sfz::Default::volume - 1.0f).margin(0.1) ); region.parseOpcode({ "rt_decay", "20" }); - sfz::noteOn(64, 64); + midiState.noteOn(64, 64); std::this_thread::sleep_for(std::chrono::milliseconds(100)); REQUIRE( region.getBaseVolumedB(64) == Approx(sfz::Default::volume - 2.0f).margin(0.1) ); region.parseOpcode({ "trigger", "attack" }); - sfz::noteOn(64, 64); + midiState.noteOn(64, 64); std::this_thread::sleep_for(std::chrono::milliseconds(100)); REQUIRE( region.getBaseVolumedB(64) == Approx(sfz::Default::volume).margin(0.1) ); } \ No newline at end of file diff --git a/tests/RegionT.cpp b/tests/RegionT.cpp index 0f52cc79..ab9f8cdd 100644 --- a/tests/RegionT.cpp +++ b/tests/RegionT.cpp @@ -21,13 +21,16 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "MidiState.h" #include "Region.h" #include "catch2/catch.hpp" using namespace Catch::literals; TEST_CASE("[Region] Parsing opcodes") { - sfz::Region region; + sfz::MidiState midiState; + sfz::Region region { midiState }; + SECTION("sample") { REQUIRE(region.sample == ""); @@ -168,10 +171,10 @@ TEST_CASE("[Region] Parsing opcodes") REQUIRE(!region.offBy); region.parseOpcode({ "off_by", "5" }); REQUIRE(region.offBy); - REQUIRE(region.offBy == 5); + REQUIRE(*region.offBy == 5); region.parseOpcode({ "off_by", "-1" }); REQUIRE(region.offBy); - REQUIRE(region.offBy == 0); + REQUIRE(*region.offBy == 0); } SECTION("off_mode") @@ -1036,7 +1039,8 @@ TEST_CASE("[Region] Parsing opcodes") // Specific region bugs TEST_CASE("[Region] Non-conforming floating point values in integer opcodes") { - sfz::Region region; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "offset", "2014.5" }); REQUIRE(region.offset == 2014); region.parseOpcode({ "pitch_keytrack", "-2.1" }); diff --git a/tests/RegionTriggersT.cpp b/tests/RegionTriggersT.cpp index a9ffa9e9..21d773f6 100644 --- a/tests/RegionTriggersT.cpp +++ b/tests/RegionTriggersT.cpp @@ -27,7 +27,9 @@ using namespace Catch::literals; TEST_CASE("Basic triggers", "Region triggers") { - sfz::Region region; + sfz::MidiState midiState; + sfz::Region region { midiState }; + region.parseOpcode({ "sample", "*sine" }); SECTION("key") { @@ -136,7 +138,8 @@ TEST_CASE("Basic triggers", "Region triggers") TEST_CASE("Legato triggers", "Region triggers") { - sfz::Region region; + sfz::MidiState midiState; + sfz::Region region { midiState }; region.parseOpcode({ "sample", "*sine" }); SECTION("First note playing") { From 94851d3adff93850d6f82f5778659c55ccf21bbb Mon Sep 17 00:00:00 2001 From: paulfd Date: Sat, 21 Sep 2019 01:08:12 +0200 Subject: [PATCH 5/9] Added the regexes headers --- sfizz/Regexes.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 sfizz/Regexes.h diff --git a/sfizz/Regexes.h b/sfizz/Regexes.h new file mode 100644 index 00000000..de323bb5 --- /dev/null +++ b/sfizz/Regexes.h @@ -0,0 +1,13 @@ +#include + +namespace sfz +{ +namespace Regexes +{ + static std::regex includes { R"V(#include\s*"(.*?)".*$)V", std::regex::optimize }; + static std::regex defines { R"(#define\s*(\$[a-zA-Z0-9]+)\s+([a-zA-Z0-9]+)(?=\s|$))", std::regex::optimize }; + static std::regex headers { R"(<(.*?)>(.*?)(?=<|$))", std::regex::optimize }; + static std::regex members { R"(([a-zA-Z0-9_]+)=([a-zA-Z0-9-_#.&\/\s\\\(\),\*]+)(?![a-zA-Z0-9_]*=))", std::regex::optimize }; + static std::regex opcodeParameters { R"(([a-zA-Z0-9_]+?)([0-9]+)$)", std::regex::optimize }; +} +} \ No newline at end of file From 20c0aeb8dd284585446adabe221580cd8b7bbc22 Mon Sep 17 00:00:00 2001 From: paulfd Date: Sat, 21 Sep 2019 01:22:52 +0200 Subject: [PATCH 6/9] Corrected a bug in the one pole filter with variable gain --- sfizz/OnePoleFilter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sfizz/OnePoleFilter.h b/sfizz/OnePoleFilter.h index d7d1aad6..58f1d9dc 100644 --- a/sfizz/OnePoleFilter.h +++ b/sfizz/OnePoleFilter.h @@ -105,7 +105,7 @@ public: auto sentinel = in + size; while (in < sentinel) { setGain(*g); - oneLowpass(in, out); + oneHighpass(in, out); in++; out++; g++; From a456256b002f32a1ebca36210c357061758fcfc6 Mon Sep 17 00:00:00 2001 From: paulfd Date: Sat, 21 Sep 2019 10:57:21 +0200 Subject: [PATCH 7/9] Added a message for the static_assert --- sfizz/LinearEnvelope.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sfizz/LinearEnvelope.h b/sfizz/LinearEnvelope.h index e246629f..ae9b5927 100644 --- a/sfizz/LinearEnvelope.h +++ b/sfizz/LinearEnvelope.h @@ -44,7 +44,7 @@ public: void getBlock(absl::Span output); private: std::function function { [](Type input) { return input; } }; - static_assert(std::is_arithmetic::value); + static_assert(std::is_arithmetic::value, "Type should be arithmetic"); std::vector> events; int maxCapacity { config::defaultSamplesPerBlock }; Type currentValue { 0.0 }; From 41010019e31fc9a8af3f6f65dd3fad59de5a8e57 Mon Sep 17 00:00:00 2001 From: paulfd Date: Sat, 21 Sep 2019 11:16:23 +0200 Subject: [PATCH 8/9] Cleanups --- benchmarks/BM_ADSR.cpp | 4 ++-- sfizz/Synth.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/benchmarks/BM_ADSR.cpp b/benchmarks/BM_ADSR.cpp index b54dd720..0125507f 100644 --- a/benchmarks/BM_ADSR.cpp +++ b/benchmarks/BM_ADSR.cpp @@ -49,7 +49,7 @@ static void Point(benchmark::State& state) { out = envelope.getNextValue(); benchmark::DoNotOptimize(output); } - state.counters["Per block"] = benchmark::Counter(envelopeSize / state.range(0), benchmark::Counter::kIsIterationInvariantRate | benchmark::Counter::kInvert); + state.counters["Per block"] = benchmark::Counter(envelopeSize / state.range(0), benchmark::Counter::kIsIterationInvariantRate); } static void Block(benchmark::State& state) { @@ -63,7 +63,7 @@ static void Block(benchmark::State& state) { benchmark::DoNotOptimize(output); } - state.counters["Per block"] = benchmark::Counter(envelopeSize / state.range(0), benchmark::Counter::kIsIterationInvariantRate | benchmark::Counter::kInvert); + state.counters["Per block"] = benchmark::Counter(envelopeSize / state.range(0), benchmark::Counter::kIsIterationInvariantRate); } BENCHMARK(Point)->RangeMultiplier(2)->Range((2<<6), (2<<11)); diff --git a/sfizz/Synth.cpp b/sfizz/Synth.cpp index a8f5a1ec..81453549 100644 --- a/sfizz/Synth.cpp +++ b/sfizz/Synth.cpp @@ -356,6 +356,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 [[maybe_unused]]) noexcept { ASSERT(noteNumber < 128); ASSERT(noteNumber >= 0); From 105c459a4abbc4f491c2e2905c99d3b7a7f51b69 Mon Sep 17 00:00:00 2001 From: paulfd Date: Sat, 21 Sep 2019 13:01:50 +0200 Subject: [PATCH 9/9] cleanups --- CMakeLists.txt | 5 +- benchmarks/BM_OPF_high_vs_low.cpp | 46 +++-------- benchmarks/BM_pointerIterationOrOffsets.cpp | 2 +- clients/sfzprint.cpp | 3 +- external/abseil-cpp | 2 +- external/benchmark | 2 +- sfizz/CMakeLists.txt | 47 ++++++++++-- sfizz/FilePool.cpp | 8 +- sfizz/FilePool.h | 4 +- sfizz/Parser.cpp | 8 +- sfizz/Parser.h | 10 +-- sfizz/Synth.cpp | 6 +- sfizz/Synth.h | 3 +- sfizz/compat/filesystem.h | 25 +++--- tests/FilesT.cpp | 48 ++++++------ tests/OnePoleFilterT.cpp | 84 ++++++++++----------- 16 files changed, 156 insertions(+), 147 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94a039d5..434bb819 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,11 +9,10 @@ set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) # To override the policy in abseil and ben set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT ANDROID) + set(USE_LIBCPP ON CACHE BOOL "Use libc++ with clang") add_compile_options(-stdlib=libc++) # Presumably need the above for linking too, maybe other options missing as well - add_link_options(-stdlib=libc++) # New command on CMake master, not in 3.12 release -else() - add_link_options(-lstdc++fs) + add_link_options(-lc++abi) # New command on CMake master, not in 3.12 release endif() if (UNIX) diff --git a/benchmarks/BM_OPF_high_vs_low.cpp b/benchmarks/BM_OPF_high_vs_low.cpp index db23bd92..5a67d73f 100644 --- a/benchmarks/BM_OPF_high_vs_low.cpp +++ b/benchmarks/BM_OPF_high_vs_low.cpp @@ -41,13 +41,14 @@ void lowpass(absl::Span input, absl::Span lowpass, float gai float state = 0.0f; float intermediate; const auto G = gain / (1 - gain); - for (auto [in, out] = std::make_pair(input.begin(), lowpass.begin()); - in < input.end() && out < lowpass.end(); - in++, out++) - { + auto in = input.begin(); + auto out = lowpass.begin(); + while (in < input.end()) { intermediate = G * (*in - state); *out = intermediate + state; state = *out + intermediate; + in++; + out++; } } @@ -56,32 +57,23 @@ void highpass(absl::Span input, absl::Span highpass, float g float state = 0.0f; float intermediate; const auto G = gain / (1 - gain); - for (auto [in, out] = std::make_pair(input.begin(), highpass.begin()); - in < input.end() && out < highpass.end(); - in++, out++) - { + auto in = input.begin(); + auto out = highpass.begin(); + while (in < input.end()) { intermediate = G * (*in - state); *out = *in - intermediate - state; state += 2*intermediate; + in++; + out++; } } -void highpass_foreach(absl::Span input, absl::Span highpass, float gain) -{ - lowpass(input, highpass, gain); - for (auto [in, out] = std::make_pair(input.begin(), highpass.begin()); - in < input.end() && out < highpass.end(); - in++, out++) - *out = *in - *out; -} - void highpass_raw(absl::Span input, absl::Span highpass, float gain) { lowpass(input, highpass, gain); auto in = input.data(); auto out = highpass.data(); - while (in < input.end() && out < highpass.end()) - { + while (in < input.end()) { *out = *in - *out; out++; in++; @@ -144,21 +136,6 @@ static void High(benchmark::State& state) { highpass(input, absl::MakeSpan(output), filterGain); } -static void High_ForEach(benchmark::State& state) { - std::vector input(state.range(0)); - std::vector output(state.range(0)); - std::random_device rd { }; - std::mt19937 gen { rd() }; - - std::normal_distribution dist { }; - std::generate(input.begin(), input.end(), [&]() { - return dist(gen); - }); - - for (auto _ : state) - highpass_foreach(input, absl::MakeSpan(output), filterGain); -} - static void High_Raw(benchmark::State& state) { std::vector input(state.range(0)); std::vector output(state.range(0)); @@ -192,7 +169,6 @@ static void High_SSE(benchmark::State& state) { BENCHMARK(Low)->RangeMultiplier(2)->Range((2<<5), (2<<10)); BENCHMARK(High)->RangeMultiplier(2)->Range((2<<5), (2<<10)); -BENCHMARK(High_ForEach)->RangeMultiplier(2)->Range((2<<5), (2<<10)); BENCHMARK(High_Raw)->RangeMultiplier(2)->Range((2<<5), (2<<10)); BENCHMARK(High_SSE)->RangeMultiplier(2)->Range((2<<5), (2<<10)); BENCHMARK_MAIN(); \ No newline at end of file diff --git a/benchmarks/BM_pointerIterationOrOffsets.cpp b/benchmarks/BM_pointerIterationOrOffsets.cpp index be2ce371..23b10fc0 100644 --- a/benchmarks/BM_pointerIterationOrOffsets.cpp +++ b/benchmarks/BM_pointerIterationOrOffsets.cpp @@ -27,7 +27,7 @@ #include "../sfizz/SIMDHelpers.h" #include "absl/types/span.h" -inline constexpr int bigNumber { 2399132 }; +constexpr int bigNumber { 2399132 }; class IterOffset : public benchmark::Fixture { public: diff --git a/clients/sfzprint.cpp b/clients/sfzprint.cpp index 91ab76ff..caae4036 100644 --- a/clients/sfzprint.cpp +++ b/clients/sfzprint.cpp @@ -74,8 +74,7 @@ int main(int argc, char** argv) std::cout << '\n'; PrintingParser parser; - std::filesystem::path filename { filesToParse[0] }; - parser.loadSfzFile(filename); + parser.loadSfzFile(filesToParse[0]); std::cout << "==========" << '\n'; std::cout << "Total:" << '\n'; std::cout << "\tMasters: " << parser.getNumMasters() << '\n'; diff --git a/external/abseil-cpp b/external/abseil-cpp index aa844899..ac78ffc3 160000 --- a/external/abseil-cpp +++ b/external/abseil-cpp @@ -1 +1 @@ -Subproject commit aa844899c937bde5d2b24f276b59997e5b668bde +Subproject commit ac78ffc3bc0a8b295cab9a03817760fd460df2a1 diff --git a/external/benchmark b/external/benchmark index 090faecb..bf4f2ea0 160000 --- a/external/benchmark +++ b/external/benchmark @@ -1 +1 @@ -Subproject commit 090faecb454fbd6e6e17a75ef8146acb037118d4 +Subproject commit bf4f2ea0bd1180b34718ac26eb79b170a4f6290e diff --git a/sfizz/CMakeLists.txt b/sfizz/CMakeLists.txt index aa12a72f..58d4e0c5 100644 --- a/sfizz/CMakeLists.txt +++ b/sfizz/CMakeLists.txt @@ -36,24 +36,59 @@ endif() set(SFIZZ_SOURCES ${SFIZZ_SOURCES} ${SFIZZ_SIMD_SOURCES}) +# include(CheckCXXSourceCompiles) +# check_cxx_source_compiles(" +# #include + +# int main(int argc, char** argv) +# { +# std::filesystem::path p; +# return 0; +# } +# " HAVE_STD_FILESYSTEM) + +check_include_file_cxx("filesystem" HAVE_STD_FILESYSTEM) +if (HAVE_STD_FILESYSTEM) + # if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0) + # add_compile_options(-DUSE_STD_FILESYSTEM) + # endif() + if (WIN32) + add_compile_options(/DUSE_STD_FILESYSTEM) + endif() +endif() + + add_library(sfizz_parser STATIC) target_sources(sfizz_parser PRIVATE Parser.cpp Opcode.cpp) target_include_directories(sfizz_parser PUBLIC .) -if(UNIX) - target_link_libraries(sfizz_parser PUBLIC stdc++fs) - # target_compile_options(sfizz_parser PUBLIC -fno-rtti -fno-exceptions) -endif(UNIX) target_link_libraries(sfizz_parser PRIVATE absl::strings) +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT ANDROID) + target_link_libraries(sfizz_parser PUBLIC c++fs) +endif() + +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_link_libraries(sfizz_parser PUBLIC stdc++fs) +endif() + + add_library(sfizz STATIC ${SFIZZ_SOURCES}) target_link_libraries(sfizz PRIVATE sfizz_parser) target_include_directories(sfizz PUBLIC .) find_package(Threads REQUIRED) target_link_libraries(sfizz PRIVATE Threads::Threads) if(UNIX) - target_link_libraries(sfizz PUBLIC stdc++fs atomic) - # target_compile_options(sfizz PUBLIC -fno-rtti -fno-exceptions) + target_link_libraries(sfizz PUBLIC atomic) endif(UNIX) + +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT ANDROID) + target_link_libraries(sfizz PUBLIC c++fs) +endif() + +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_link_libraries(sfizz PUBLIC stdc++fs) +endif() + target_link_libraries(sfizz PUBLIC absl::strings) target_link_libraries(sfizz PRIVATE sndfile absl::flat_hash_map) diff --git a/sfizz/FilePool.cpp b/sfizz/FilePool.cpp index 0e1c31a2..dacf704b 100644 --- a/sfizz/FilePool.cpp +++ b/sfizz/FilePool.cpp @@ -50,8 +50,8 @@ std::unique_ptr> readFromFile(SndfileHandle& sndFile, int numFram absl::optional sfz::FilePool::getFileInformation(const std::string& filename, uint32_t offset) noexcept { - std::filesystem::path file { rootDirectory / filename }; - if (!std::filesystem::exists(file)) + fs::path file { rootDirectory / filename }; + if (!fs::exists(file)) return {}; SndfileHandle sndFile(reinterpret_cast(file.c_str())); @@ -128,8 +128,8 @@ void sfz::FilePool::loadingThread() noexcept } DBG("Background loading of: " << *fileToLoad.sample); - std::filesystem::path file { rootDirectory / *fileToLoad.sample }; - if (!std::filesystem::exists(file)) { + fs::path file { rootDirectory / *fileToLoad.sample }; + if (!fs::exists(file)) { DBG("Background thread: no file " << *fileToLoad.sample << " exists."); continue; } diff --git a/sfizz/FilePool.h b/sfizz/FilePool.h index fb30c353..4c25250b 100644 --- a/sfizz/FilePool.h +++ b/sfizz/FilePool.h @@ -46,7 +46,7 @@ public: fileLoadingThread.join(); garbageCollectionThread.join(); } - void setRootDirectory(const std::filesystem::path& directory) noexcept { rootDirectory = directory; } + void setRootDirectory(const fs::path& directory) noexcept { rootDirectory = directory; } size_t getNumPreloadedSamples() const noexcept { return preloadedData.size(); } struct FileInformation { @@ -60,7 +60,7 @@ public: void enqueueLoading(Voice* voice, const std::string* sample, int numFrames, unsigned ticket) noexcept; void clear(); private: - std::filesystem::path rootDirectory; + fs::path rootDirectory; struct FileLoadingInformation { Voice* voice; const std::string* sample; diff --git a/sfizz/Parser.cpp b/sfizz/Parser.cpp index 307c0664..d007a205 100644 --- a/sfizz/Parser.cpp +++ b/sfizz/Parser.cpp @@ -41,10 +41,10 @@ void removeCommentOnLine(absl::string_view& line) line.remove_suffix(line.size() - position); } -bool sfz::Parser::loadSfzFile(const std::filesystem::path& file) +bool sfz::Parser::loadSfzFile(const fs::path& file) { const auto sfzFile = file.is_absolute() ? file : rootDirectory / file; - if (!std::filesystem::exists(sfzFile)) + if (!fs::exists(sfzFile)) return false; rootDirectory = file.parent_path(); @@ -81,7 +81,7 @@ bool sfz::Parser::loadSfzFile(const std::filesystem::path& file) return true; } -void sfz::Parser::readSfzFile(const std::filesystem::path& fileName, std::vector& lines) noexcept +void sfz::Parser::readSfzFile(const fs::path& fileName, std::vector& lines) noexcept { std::ifstream fileStream(fileName.c_str()); if (!fileStream) @@ -107,7 +107,7 @@ void sfz::Parser::readSfzFile(const std::filesystem::path& fileName, std::vector std::replace(includePath.begin(), includePath.end(), '\\', '/'); const auto newFile = rootDirectory / includePath; auto alreadyIncluded = std::find(includedFiles.begin(), includedFiles.end(), newFile); - if (std::filesystem::exists(newFile)) { + if (fs::exists(newFile)) { if (alreadyIncluded == includedFiles.end()) { includedFiles.push_back(newFile); readSfzFile(newFile, lines); diff --git a/sfizz/Parser.h b/sfizz/Parser.h index 481b6eb0..25d2307a 100644 --- a/sfizz/Parser.h +++ b/sfizz/Parser.h @@ -32,20 +32,20 @@ namespace sfz { class Parser { public: - virtual bool loadSfzFile(const std::filesystem::path& file); + virtual bool loadSfzFile(const fs::path& file); const std::map& getDefines() const noexcept { return defines; } - const std::vector& getIncludedFiles() const noexcept { return includedFiles; } + const std::vector& getIncludedFiles() const noexcept { return includedFiles; } void disableRecursiveIncludeGuard() { recursiveIncludeGuard = false; } void enableRecursiveIncludeGuard() { recursiveIncludeGuard = true; } protected: virtual void callback(absl::string_view header, const std::vector& members) = 0; - std::filesystem::path rootDirectory { std::filesystem::current_path() }; + fs::path rootDirectory { fs::current_path() }; private: bool recursiveIncludeGuard { false }; std::map defines; - std::vector includedFiles; + std::vector includedFiles; std::string aggregatedContent {}; - void readSfzFile(const std::filesystem::path& fileName, std::vector& lines) noexcept; + void readSfzFile(const fs::path& fileName, std::vector& lines) noexcept; }; } // namespace sfz diff --git a/sfizz/Synth.cpp b/sfizz/Synth.cpp index 81453549..3cc03336 100644 --- a/sfizz/Synth.cpp +++ b/sfizz/Synth.cpp @@ -152,8 +152,8 @@ void sfz::Synth::handleControlOpcodes(const std::vector& members) case hash("Default_path"): [[fallthrough]]; case hash("default_path"): { auto stringPath = std::string(member.value.begin(), member.value.end()); - auto newPath = std::filesystem::path(stringPath); - if (std::filesystem::exists(newPath)) + auto newPath = fs::path(stringPath); + if (fs::exists(newPath)) rootDirectory = newPath; break; } @@ -182,7 +182,7 @@ void addEndpointsToVelocityCurve(sfz::Region& region) } } -bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename) +bool sfz::Synth::loadSfzFile(const fs::path& filename) { canEnterCallback = false; while (inCallback) { diff --git a/sfizz/Synth.h b/sfizz/Synth.h index 763415e4..24fd9604 100644 --- a/sfizz/Synth.h +++ b/sfizz/Synth.h @@ -40,8 +40,7 @@ namespace sfz { class Synth : public Parser { public: Synth(); - - bool loadSfzFile(const std::filesystem::path& file) final; + bool loadSfzFile(const fs::path& file) final; int getNumRegions() const noexcept; int getNumGroups() const noexcept; int getNumMasters() const noexcept; diff --git a/sfizz/compat/filesystem.h b/sfizz/compat/filesystem.h index 6b040bf7..38f13894 100644 --- a/sfizz/compat/filesystem.h +++ b/sfizz/compat/filesystem.h @@ -1,15 +1,16 @@ #pragma once - -#ifdef __cplusplus - #if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) - #include - #elif (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) - #warning std::experimental::filesystem in use - #include - namespace std { - namespace filesystem = std::experimental::filesystem; - } - #endif +#ifdef USE_STD_FILESYSTEM + #warning FS + #include + namespace fs = std::filesystem; #else - #error no filesystem support + #warning EXPFS + #include + namespace fs = std::experimental::filesystem; #endif + +// #if __cplusplus < 201703L +// #warning EXPFSNS +// #else +// #warning FSNS +// #endif \ No newline at end of file diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp index 7462a3f6..d8c9177d 100644 --- a/tests/FilesT.cpp +++ b/tests/FilesT.cpp @@ -23,13 +23,13 @@ #include "Synth.h" #include "catch2/catch.hpp" -#include +#include "../sfizz/compat/filesystem.h" using namespace Catch::literals; TEST_CASE("[Files] Single region (regions_one.sfz)") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Regions/regions_one.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Regions/regions_one.sfz"); REQUIRE(synth.getNumRegions() == 1); REQUIRE(synth.getRegionView(0)->sample == "dummy.wav"); } @@ -38,7 +38,7 @@ TEST_CASE("[Files] Single region (regions_one.sfz)") TEST_CASE("[Files] Multiple regions (regions_many.sfz)") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Regions/regions_many.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Regions/regions_many.sfz"); REQUIRE(synth.getNumRegions() == 3); REQUIRE(synth.getRegionView(0)->sample == "dummy.wav"); REQUIRE(synth.getRegionView(1)->sample == "dummy.1.wav"); @@ -48,7 +48,7 @@ TEST_CASE("[Files] Multiple regions (regions_many.sfz)") TEST_CASE("[Files] Basic opcodes (regions_opcodes.sfz)") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Regions/regions_opcodes.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Regions/regions_opcodes.sfz"); REQUIRE(synth.getNumRegions() == 1); REQUIRE(synth.getRegionView(0)->channelRange == Range(2, 14)); } @@ -56,7 +56,7 @@ TEST_CASE("[Files] Basic opcodes (regions_opcodes.sfz)") TEST_CASE("[Files] Underscore opcodes (underscore_opcodes.sfz)") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Regions/underscore_opcodes.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Regions/underscore_opcodes.sfz"); REQUIRE(synth.getNumRegions() == 1); REQUIRE(synth.getRegionView(0)->loopMode == SfzLoopMode::loop_sustain); } @@ -64,7 +64,7 @@ TEST_CASE("[Files] Underscore opcodes (underscore_opcodes.sfz)") TEST_CASE("[Files] Local include") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Includes/root_local.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/root_local.sfz"); REQUIRE(synth.getNumRegions() == 1); REQUIRE(synth.getRegionView(0)->sample == "dummy.wav"); } @@ -72,7 +72,7 @@ TEST_CASE("[Files] Local include") TEST_CASE("[Files] Multiple includes") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Includes/multiple_includes.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/multiple_includes.sfz"); REQUIRE(synth.getNumRegions() == 2); REQUIRE(synth.getRegionView(0)->sample == "dummy.wav"); REQUIRE(synth.getRegionView(1)->sample == "dummy2.wav"); @@ -81,7 +81,7 @@ TEST_CASE("[Files] Multiple includes") TEST_CASE("[Files] Multiple includes with comments") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Includes/multiple_includes_with_comments.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/multiple_includes_with_comments.sfz"); REQUIRE(synth.getNumRegions() == 2); REQUIRE(synth.getRegionView(0)->sample == "dummy.wav"); REQUIRE(synth.getRegionView(1)->sample == "dummy2.wav"); @@ -90,7 +90,7 @@ TEST_CASE("[Files] Multiple includes with comments") TEST_CASE("[Files] Subdir include") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Includes/root_subdir.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/root_subdir.sfz"); REQUIRE(synth.getNumRegions() == 1); REQUIRE(synth.getRegionView(0)->sample == "dummy_subdir.wav"); } @@ -98,7 +98,7 @@ TEST_CASE("[Files] Subdir include") TEST_CASE("[Files] Subdir include Win") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Includes/root_subdir_win.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/root_subdir_win.sfz"); REQUIRE(synth.getNumRegions() == 1); REQUIRE(synth.getRegionView(0)->sample == "dummy_subdir.wav"); } @@ -107,7 +107,7 @@ TEST_CASE("[Files] Recursive include (with include guard)") { sfz::Synth synth; synth.enableRecursiveIncludeGuard(); - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Includes/root_recursive.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/root_recursive.sfz"); REQUIRE(synth.getNumRegions() == 2); REQUIRE(synth.getRegionView(0)->sample == "dummy_recursive2.wav"); REQUIRE(synth.getRegionView(1)->sample == "dummy_recursive1.wav"); @@ -117,7 +117,7 @@ TEST_CASE("[Files] Include loops (with include guard)") { sfz::Synth synth; synth.enableRecursiveIncludeGuard(); - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/Includes/root_loop.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/root_loop.sfz"); REQUIRE(synth.getNumRegions() == 2); REQUIRE(synth.getRegionView(0)->sample == "dummy_loop2.wav"); REQUIRE(synth.getRegionView(1)->sample == "dummy_loop1.wav"); @@ -126,7 +126,7 @@ TEST_CASE("[Files] Include loops (with include guard)") TEST_CASE("[Files] Define test") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/defines.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/defines.sfz"); REQUIRE(synth.getNumRegions() == 3); REQUIRE(synth.getRegionView(0)->keyRange == Range(36, 36)); REQUIRE(synth.getRegionView(1)->keyRange == Range(38, 38)); @@ -136,7 +136,7 @@ TEST_CASE("[Files] Define test") TEST_CASE("[Files] Group from AVL") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/groups_avl.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/groups_avl.sfz"); REQUIRE(synth.getNumRegions() == 5); for (int i = 0; i < synth.getNumRegions(); ++i) { REQUIRE(synth.getRegionView(i)->volume == 6.0f); @@ -152,7 +152,7 @@ TEST_CASE("[Files] Group from AVL") TEST_CASE("[Files] Full hierarchy") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/basic_hierarchy.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/basic_hierarchy.sfz"); REQUIRE(synth.getNumRegions() == 8); for (int i = 0; i < synth.getNumRegions(); ++i) { REQUIRE(synth.getRegionView(i)->width == 40.0f); @@ -193,9 +193,9 @@ TEST_CASE("[Files] Full hierarchy") TEST_CASE("[Files] Reloading files") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/basic_hierarchy.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/basic_hierarchy.sfz"); REQUIRE(synth.getNumRegions() == 8); - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/basic_hierarchy.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/basic_hierarchy.sfz"); REQUIRE(synth.getNumRegions() == 8); } @@ -203,7 +203,7 @@ TEST_CASE("[Files] Full hierarchy with antislashes") { { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/basic_hierarchy.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/basic_hierarchy.sfz"); REQUIRE(synth.getNumRegions() == 8); REQUIRE(synth.getRegionView(0)->sample == "Regions/dummy.wav"); REQUIRE(synth.getRegionView(1)->sample == "Regions/dummy.1.wav"); @@ -217,7 +217,7 @@ TEST_CASE("[Files] Full hierarchy with antislashes") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/basic_hierarchy_antislash.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/basic_hierarchy_antislash.sfz"); REQUIRE(synth.getNumRegions() == 8); REQUIRE(synth.getRegionView(0)->sample == "Regions/dummy.wav"); REQUIRE(synth.getRegionView(1)->sample == "Regions/dummy.1.wav"); @@ -233,7 +233,7 @@ TEST_CASE("[Files] Full hierarchy with antislashes") TEST_CASE("[Files] Pizz basic") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/SpecificBugs/MeatBassPizz/Programs/pizz.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/SpecificBugs/MeatBassPizz/Programs/pizz.sfz"); REQUIRE(synth.getNumRegions() == 4); for (int i = 0; i < synth.getNumRegions(); ++i) { REQUIRE(synth.getRegionView(i)->keyRange == Range(12, 22)); @@ -254,7 +254,7 @@ TEST_CASE("[Files] Pizz basic") TEST_CASE("[Files] Channels (channels.sfz)") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/channels.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/channels.sfz"); REQUIRE(synth.getNumRegions() == 2); REQUIRE(synth.getRegionView(0)->sample == "mono_sample.wav"); REQUIRE(!synth.getRegionView(0)->isStereo()); @@ -265,7 +265,7 @@ TEST_CASE("[Files] Channels (channels.sfz)") TEST_CASE("[Files] sw_default") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/sw_default.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/sw_default.sfz"); REQUIRE( synth.getNumRegions() == 4 ); REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); REQUIRE( synth.getRegionView(1)->isSwitchedOn() ); @@ -276,7 +276,7 @@ TEST_CASE("[Files] sw_default") TEST_CASE("[Files] sw_default and playing with switches") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/sw_default.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/sw_default.sfz"); REQUIRE( synth.getNumRegions() == 4 ); REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); REQUIRE( synth.getRegionView(1)->isSwitchedOn() ); @@ -306,7 +306,7 @@ TEST_CASE("[Files] sw_default and playing with switches") TEST_CASE("[Files] wrong (overlapping) replacement for defines") { sfz::Synth synth; - synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/SpecificBugs/wrong-replacements.sfz"); + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/SpecificBugs/wrong-replacements.sfz"); REQUIRE( synth.getNumRegions() == 3 ); REQUIRE( synth.getRegionView(0)->keyRange.getStart() == 52 ); REQUIRE( synth.getRegionView(0)->keyRange.getEnd() == 52 ); diff --git a/tests/OnePoleFilterT.cpp b/tests/OnePoleFilterT.cpp index 14cadcaf..c33000e5 100644 --- a/tests/OnePoleFilterT.cpp +++ b/tests/OnePoleFilterT.cpp @@ -46,7 +46,7 @@ inline bool approxEqual(const std::vector& lhs, const std::vector& r } template -void testLowpass(const std::filesystem::path& inputNumpyFile, const std::filesystem::path& outputNumpyFile, Type gain) +void testLowpass(const fs::path& inputNumpyFile, const fs::path& outputNumpyFile, Type gain) { const auto input = cnpy::npy_load(inputNumpyFile.string()); REQUIRE(input.word_size == 8); @@ -81,7 +81,7 @@ void testLowpass(const std::filesystem::path& inputNumpyFile, const std::filesys } template -void testHighpass(const std::filesystem::path& inputNumpyFile, const std::filesystem::path& outputNumpyFile, Type gain) +void testHighpass(const fs::path& inputNumpyFile, const fs::path& outputNumpyFile, Type gain) { const auto input = cnpy::npy_load(inputNumpyFile.string()); REQUIRE(input.word_size == 8); @@ -118,95 +118,95 @@ void testHighpass(const std::filesystem::path& inputNumpyFile, const std::filesy TEST_CASE("[OnePoleFilter] Lowpass Float") { testLowpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy", 0.1f); testLowpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy", 0.3f); testLowpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy", 0.5f); testLowpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy", 0.7f); testLowpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy", 0.9f); } TEST_CASE("[OnePoleFilter] Lowpass Double") { testLowpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy", 0.1f); testLowpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy", 0.3f); testLowpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy", 0.5f); testLowpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy", 0.7f); testLowpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy", 0.9f); } TEST_CASE("[OnePoleFilter] Highpass Float") { testHighpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy", 0.1f); testHighpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy", 0.3f); testHighpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy", 0.5f); testHighpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy", 0.7f); testHighpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy", 0.9f); } TEST_CASE("[OnePoleFilter] Highpass Double") { testHighpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy", 0.1f); testHighpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy", 0.3f); testHighpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy", 0.5f); testHighpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy", 0.7f); testHighpass( - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", + fs::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy", 0.9f); }