From 004afb6d8ab62f91786eb9dc561864e046b098e3 Mon Sep 17 00:00:00 2001 From: paulfd Date: Fri, 30 Aug 2019 13:05:07 +0200 Subject: [PATCH] Reorganized the helpers to make more sense --- CMakeLists.txt | 1 + sources/ADSREnvelope.cpp | 1 - sources/ADSREnvelope.h | 2 +- sources/Buffer.h | 2 +- sources/CCMap.h | 2 +- sources/Debug.h | 48 ++++++++ sources/EGDescription.h | 1 + sources/FilePool.cpp | 2 + sources/FilePool.h | 2 +- sources/Helpers.h | 231 ------------------------------------ sources/LeakDetector.h | 72 +++++++++++ sources/LinearEnvelope.cpp | 2 +- sources/LinearEnvelope.h | 2 +- sources/MathHelpers.h | 76 ++++++++++++ sources/OnePoleFilter.h | 2 +- sources/Opcode.cpp | 1 + sources/Opcode.h | 2 +- sources/Parser.cpp | 2 +- sources/Region.cpp | 3 +- sources/Region.h | 1 + sources/SIMDDummy.cpp | 1 - sources/SIMDHelpers.h | 3 +- sources/SIMDSSE.cpp | 1 - sources/ScopedFTZ.cpp | 54 +++++++++ sources/ScopedFTZ.h | 31 +++++ sources/SfzHelpers.cpp | 171 ++++++++++++++++++++++++++ sources/SfzHelpers.h | 2 +- sources/StereoBuffer.h | 3 +- sources/StereoSpan.h | 2 +- sources/StringViewHelpers.h | 63 ++++++++++ sources/Synth.cpp | 4 +- sources/Synth.h | 9 +- sources/Voice.cpp | 1 + sources/Voice.h | 1 + tests/HelpersT.cpp | 2 +- 35 files changed, 546 insertions(+), 257 deletions(-) create mode 100644 sources/Debug.h delete mode 100644 sources/Helpers.h create mode 100644 sources/LeakDetector.h create mode 100644 sources/MathHelpers.h create mode 100644 sources/ScopedFTZ.cpp create mode 100644 sources/ScopedFTZ.h create mode 100644 sources/SfzHelpers.cpp create mode 100644 sources/StringViewHelpers.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 02fa357e..644ed5b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,7 @@ set(COMMON_SOURCES sources/FilePool.cpp sources/Region.cpp sources/Voice.cpp + sources/ScopedFTZ.cpp sources/SfzHelpers.cpp sources/FloatEnvelopes.cpp sources/Parser.cpp diff --git a/sources/ADSREnvelope.cpp b/sources/ADSREnvelope.cpp index 15a10010..905fe40e 100644 --- a/sources/ADSREnvelope.cpp +++ b/sources/ADSREnvelope.cpp @@ -23,7 +23,6 @@ #include "ADSREnvelope.h" #include "Globals.h" -#include "Helpers.h" #include "SIMDHelpers.h" #include diff --git a/sources/ADSREnvelope.h b/sources/ADSREnvelope.h index b271233d..f9cf9ec2 100644 --- a/sources/ADSREnvelope.h +++ b/sources/ADSREnvelope.h @@ -22,7 +22,7 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once -#include "Helpers.h" +#include "LeakDetector.h" #include namespace sfz { diff --git a/sources/Buffer.h b/sources/Buffer.h index 3f77d1c8..d6fc1482 100644 --- a/sources/Buffer.h +++ b/sources/Buffer.h @@ -23,7 +23,7 @@ #pragma once #include "Globals.h" -#include "Helpers.h" +#include "LeakDetector.h" #include #include #include diff --git a/sources/CCMap.h b/sources/CCMap.h index 3ebaed25..6da0940f 100644 --- a/sources/CCMap.h +++ b/sources/CCMap.h @@ -22,7 +22,7 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once -#include "Helpers.h" +#include "LeakDetector.h" #include namespace sfz { diff --git a/sources/Debug.h b/sources/Debug.h new file mode 100644 index 00000000..34e22a6e --- /dev/null +++ b/sources/Debug.h @@ -0,0 +1,48 @@ +#pragma once + +#ifndef NDEBUG +#include +// These trap into the signal library rather than your own sourcecode +// #include +// #define ASSERTFALSE { ::kill(0, SIGTRAP); } +// #define ASSERTFALSE { raise(SIGTRAP); } +#if (__linux__ || __unix__) + +// Break in source code +#if (__x86_64__ || __i386__) +#define ASSERTFALSE \ + { \ + __asm__("int3"); \ + } +#elif (__arm__ || __aarch64__) +#define ASSERTFALSE \ + { \ + __builtin_trap(); \ + } +#endif + +#elif (_WIN32 || _WIN64) +#pragma intrinsic(__debugbreak) +#define ASSERTFALSE \ + { \ + __debugbreak(); \ + } +#else +#define ASSERTFALSE +#endif + +// Assert stuff +#define ASSERT(expression) \ + if (!(expression)) \ + ASSERTFALSE + +// Debug message +#define DBG(ostream) std::cerr << ostream << '\n' + +#else // NDEBUG + +#define ASSERTFALSE +#define ASSERT(expression) +#define DBG(ostream) + +#endif \ No newline at end of file diff --git a/sources/EGDescription.h b/sources/EGDescription.h index 4178f06f..8170af8f 100644 --- a/sources/EGDescription.h +++ b/sources/EGDescription.h @@ -24,6 +24,7 @@ #pragma once #include "Globals.h" #include "Defaults.h" +#include "LeakDetector.h" #include "SfzHelpers.h" #include diff --git a/sources/FilePool.cpp b/sources/FilePool.cpp index a9ac8821..49991738 100644 --- a/sources/FilePool.cpp +++ b/sources/FilePool.cpp @@ -23,8 +23,10 @@ #include "FilePool.h" #include "Globals.h" +#include "Debug.h" #include "absl/types/span.h" #include +#include using namespace std::chrono_literals; template diff --git a/sources/FilePool.h b/sources/FilePool.h index 97f40e8d..bb4912b6 100644 --- a/sources/FilePool.h +++ b/sources/FilePool.h @@ -23,13 +23,13 @@ #pragma once #include "Defaults.h" +#include "LeakDetector.h" #include "StereoBuffer.h" #include "Voice.h" #include "readerwriterqueue.h" #include #include #include -#include #include #include diff --git a/sources/Helpers.h b/sources/Helpers.h deleted file mode 100644 index 73da79bc..00000000 --- a/sources/Helpers.h +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) 2019, Paul Ferrand -// All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: - -// 1. Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. - -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once -#include -#include -#include -#include - -#ifdef HAVE_X86INTRIN_H -#include -#endif - -#ifdef HAVE_INTRIN_H -#include -#endif - -inline void trimInPlace(std::string_view& s) -{ - const auto leftPosition = s.find_first_not_of(" \r\t\n\f\v"); - if (leftPosition != s.npos) { - s.remove_prefix(leftPosition); - const auto rightPosition = s.find_last_not_of(" \r\t\n\f\v"); - s.remove_suffix(s.size() - rightPosition - 1); - } else { - s.remove_suffix(s.size()); - } -} - -inline std::string_view trim(std::string_view s) -{ - const auto leftPosition = s.find_first_not_of(" \r\t\n\f\v"); - if (leftPosition != s.npos) { - s.remove_prefix(leftPosition); - const auto rightPosition = s.find_last_not_of(" \r\t\n\f\v"); - s.remove_suffix(s.size() - rightPosition - 1); - } else { - s.remove_suffix(s.size()); - } - return s; -} - -inline constexpr uint64_t Fnv1aBasis = 0x811C9DC5; -inline constexpr uint64_t Fnv1aPrime = 0x01000193; - -inline constexpr uint64_t hash(std::string_view s, uint64_t h = Fnv1aBasis) -{ - if (s.length() > 0) - return hash( { s.data() + 1, s.length() - 1 }, (h ^ s.front()) * Fnv1aPrime ); - - return h; -} - -template -inline constexpr T min(T op1, T op2) { return std::min(op1, op2); } -template -inline constexpr T min(T op1, T op2, T op3) { return std::min(op1, std::min(op2, op3)); } -template -inline constexpr T min(T op1, T op2, T op3, T op4) { return std::min(op1, std::min(op2, std::min(op3, op4))); } - -#ifndef NDEBUG -#if __linux__ || __unix__ -// These trap into the signal library rather than your own sourcecode -// #define ASSERTFALSE { ::kill(0, SIGTRAP); } -// #define ASSERTFALSE { raise(SIGTRAP); } -#define ASSERTFALSE \ - { \ - __asm__("int3"); \ - } -#elif _WIN32 || _WIN64 -#pragma intrinsic(__debugbreak) -#define ASSERTFALSE \ - { \ - __debugbreak(); \ - } -#else -#define ASSERTFALSE \ - { \ - __asm int 3; \ - } -#endif -#define ASSERT(expression) \ - if (!(expression)) \ - ASSERTFALSE -#include -#define DBG(ostream) std::cerr << ostream << '\n' -#else -#define ASSERTFALSE -#define ASSERT(expression) -#define DBG(ostream) -#endif - -template -inline constexpr Type db2pow(Type in) -{ - return std::pow(static_cast(10.0), in * static_cast(0.1)); -} - -template -inline constexpr Type pow2db(Type in) -{ - return static_cast(10.0) * std::log10(in); -} - -template -inline constexpr Type db2mag(Type in) -{ - return std::pow(static_cast(10.0), in * static_cast(0.05)); -} - -template -inline constexpr Type mag2db(Type in) -{ - return static_cast(20.0) * std::log10(in); -} - -namespace Random { -static inline std::random_device randomDevice; -static inline std::mt19937 randomGenerator { randomDevice() }; -} // namespace Random - -inline float midiNoteFrequency(const int noteNumber) -{ - return 440.0f * std::pow(2.0f, (noteNumber - 69) / 12.0f); -} - -template -constexpr Type pi { 3.141592653589793238462643383279502884 }; -template -constexpr Type twoPi { 2 * pi }; -template -constexpr Type piTwo { pi / 2 }; - -#include -template -class LeakDetector { -public: - LeakDetector() - { - objectCounter.count++; - } - LeakDetector(const LeakDetector&) - { - objectCounter.count++; - } - ~LeakDetector() - { - objectCounter.count--; - if (objectCounter.count.load() < 0) { - DBG("Deleted a dangling pointer for class " << Owner::getClassName()); - // Deleted a dangling pointer! - ASSERTFALSE; - } - } - -private: - struct ObjectCounter { - ObjectCounter() = default; - ~ObjectCounter() - { - if (auto residualCount = count.load() > 0) { - DBG("Leaked " << residualCount << " instance(s) of class " << Owner::getClassName()); - // Leaked ojects - ASSERTFALSE; - } - }; - std::atomic count { 0 }; - }; - static inline ObjectCounter objectCounter; -}; - -#ifndef NDEBUG -#define LEAK_DETECTOR(Class) \ - friend class LeakDetector; \ - static const char* getClassName() { return #Class; } \ - LeakDetector leakDetector; -#else -#define LEAK_DETECTOR(Class) -#endif - -class ScopedFTZ { - -public: - ScopedFTZ() - { -#if (HAVE_X86INTRIN_H || HAVE_INTRIN_H) - unsigned mask = _MM_DENORMALS_ZERO_MASK | _MM_FLUSH_ZERO_MASK; - registerState = _mm_getcsr(); - _mm_setcsr((registerState & (~mask)) | mask); -#elif HAVE_ARM_NEON_H - intptr_t mask = (1 << 24); - asm volatile("vmrs %0, fpscr" - : "=r"(registerState)); - asm volatile("vmsr fpscr, %0" - : - : "ri"((registerState & (~mask)) | mask)); -#endif - } - ~ScopedFTZ() - { -#if (HAVE_X86INTRIN_H || HAVE_INTRIN_H) - _mm_setcsr(registerState); -#elif HAVE_ARM_NEON_H - asm volatile("vmsr %0, fpscr" - : "=r"(registerState)); -#endif - } - -private: - unsigned registerState; -}; \ No newline at end of file diff --git a/sources/LeakDetector.h b/sources/LeakDetector.h new file mode 100644 index 00000000..948c374a --- /dev/null +++ b/sources/LeakDetector.h @@ -0,0 +1,72 @@ +// Copyright (c) 2019, Paul Ferrand +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: + +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once +#include +#include "Debug.h" + +template +class LeakDetector { +public: + LeakDetector() + { + objectCounter.count++; + } + LeakDetector(const LeakDetector&) + { + objectCounter.count++; + } + ~LeakDetector() + { + objectCounter.count--; + if (objectCounter.count.load() < 0) { + DBG("Deleted a dangling pointer for class " << Owner::getClassName()); + // Deleted a dangling pointer! + ASSERTFALSE; + } + } + +private: + struct ObjectCounter { + ObjectCounter() = default; + ~ObjectCounter() + { + if (auto residualCount = count.load() > 0) { + DBG("Leaked " << residualCount << " instance(s) of class " << Owner::getClassName()); + // Leaked ojects + ASSERTFALSE; + } + }; + std::atomic count { 0 }; + }; + static inline ObjectCounter objectCounter; +}; + +#ifndef NDEBUG +#define LEAK_DETECTOR(Class) \ + friend class LeakDetector; \ + static const char* getClassName() { return #Class; } \ + LeakDetector leakDetector; +#else +#define LEAK_DETECTOR(Class) +#endif \ No newline at end of file diff --git a/sources/LinearEnvelope.cpp b/sources/LinearEnvelope.cpp index 01194580..2584a866 100644 --- a/sources/LinearEnvelope.cpp +++ b/sources/LinearEnvelope.cpp @@ -22,8 +22,8 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "LinearEnvelope.h" -#include "Helpers.h" #include "SIMDHelpers.h" +#include "MathHelpers.h" #include namespace sfz { diff --git a/sources/LinearEnvelope.h b/sources/LinearEnvelope.h index 3056b431..2e646821 100644 --- a/sources/LinearEnvelope.h +++ b/sources/LinearEnvelope.h @@ -23,7 +23,7 @@ #pragma once #include "Globals.h" -#include "Helpers.h" +#include "LeakDetector.h" #include #include #include diff --git a/sources/MathHelpers.h b/sources/MathHelpers.h new file mode 100644 index 00000000..93e11bec --- /dev/null +++ b/sources/MathHelpers.h @@ -0,0 +1,76 @@ +// Copyright (c) 2019, Paul Ferrand +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: + +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once +#include +#include +#include + +template +inline constexpr T min(T op1, T op2) { return std::min(op1, op2); } +template +inline constexpr T min(T op1, T op2, T op3) { return std::min(op1, std::min(op2, op3)); } +template +inline constexpr T min(T op1, T op2, T op3, T op4) { return std::min(op1, std::min(op2, std::min(op3, op4))); } + + +template +inline constexpr Type db2pow(Type in) +{ + return std::pow(static_cast(10.0), in * static_cast(0.1)); +} + +template +inline constexpr Type pow2db(Type in) +{ + return static_cast(10.0) * std::log10(in); +} + +template +inline constexpr Type db2mag(Type in) +{ + return std::pow(static_cast(10.0), in * static_cast(0.05)); +} + +template +inline constexpr Type mag2db(Type in) +{ + return static_cast(20.0) * std::log10(in); +} + +namespace Random { +static inline std::random_device randomDevice; +static inline std::mt19937 randomGenerator { randomDevice() }; +} // namespace Random + +inline float midiNoteFrequency(const int noteNumber) +{ + return 440.0f * std::pow(2.0f, (noteNumber - 69) / 12.0f); +} + +template +constexpr Type pi { 3.141592653589793238462643383279502884 }; +template +constexpr Type twoPi { 2 * pi }; +template +constexpr Type piTwo { pi / 2 }; \ No newline at end of file diff --git a/sources/OnePoleFilter.h b/sources/OnePoleFilter.h index 1346c5de..49db81de 100644 --- a/sources/OnePoleFilter.h +++ b/sources/OnePoleFilter.h @@ -23,7 +23,7 @@ #pragma once #include "Globals.h" -#include "Helpers.h" +#include "MathHelpers.h" #include #include diff --git a/sources/Opcode.cpp b/sources/Opcode.cpp index 4f1f8b73..a52203fd 100644 --- a/sources/Opcode.cpp +++ b/sources/Opcode.cpp @@ -22,6 +22,7 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Opcode.h" +#include "StringViewHelpers.h" sfz::Opcode::Opcode(std::string_view inputOpcode, std::string_view inputValue) : opcode(inputOpcode) diff --git a/sources/Opcode.h b/sources/Opcode.h index 2c0344a7..d587471b 100644 --- a/sources/Opcode.h +++ b/sources/Opcode.h @@ -23,7 +23,7 @@ #pragma once #include "Defaults.h" -#include "Helpers.h" +#include "LeakDetector.h" #include "Range.h" #include "SfzHelpers.h" #include diff --git a/sources/Parser.cpp b/sources/Parser.cpp index 2857373d..2ec2bbf9 100644 --- a/sources/Parser.cpp +++ b/sources/Parser.cpp @@ -23,7 +23,7 @@ #include "Parser.h" #include "Globals.h" -#include "Helpers.h" +#include "StringViewHelpers.h" #include "absl/strings/str_join.h" #include #include diff --git a/sources/Region.cpp b/sources/Region.cpp index 06cb7c7a..67e11e2b 100644 --- a/sources/Region.cpp +++ b/sources/Region.cpp @@ -22,7 +22,8 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Region.h" -#include "Helpers.h" +#include "Debug.h" +#include "StringViewHelpers.h" #include "absl/strings/str_replace.h" #include diff --git a/sources/Region.h b/sources/Region.h index 4f9cdde6..567364b7 100644 --- a/sources/Region.h +++ b/sources/Region.h @@ -23,6 +23,7 @@ #pragma once #include "CCMap.h" +#include "LeakDetector.h" #include "Defaults.h" #include "EGDescription.h" #include "Opcode.h" diff --git a/sources/SIMDDummy.cpp b/sources/SIMDDummy.cpp index 05f4a8db..979b2ae7 100644 --- a/sources/SIMDDummy.cpp +++ b/sources/SIMDDummy.cpp @@ -21,7 +21,6 @@ // (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 "Helpers.h" #include "SIMDHelpers.h" template <> diff --git a/sources/SIMDHelpers.h b/sources/SIMDHelpers.h index 16559416..169bbda4 100644 --- a/sources/SIMDHelpers.h +++ b/sources/SIMDHelpers.h @@ -23,7 +23,8 @@ #pragma once #include "Globals.h" -#include "Helpers.h" +#include "Debug.h" +#include "MathHelpers.h" #include #include #include diff --git a/sources/SIMDSSE.cpp b/sources/SIMDSSE.cpp index 6e4b9f6a..1eaf054f 100644 --- a/sources/SIMDSSE.cpp +++ b/sources/SIMDSSE.cpp @@ -21,7 +21,6 @@ // (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 "Helpers.h" #include "SIMDHelpers.h" #if HAVE_X86INTRIN_H diff --git a/sources/ScopedFTZ.cpp b/sources/ScopedFTZ.cpp new file mode 100644 index 00000000..fb871f06 --- /dev/null +++ b/sources/ScopedFTZ.cpp @@ -0,0 +1,54 @@ +// Copyright (c) 2019, Paul Ferrand +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: + +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 "ScopedFTZ.h" +#if (HAVE_X86INTRIN_H) +#include +#elif (HAVE_INTRIN_H) +#include +#elif (HAVE_ARM_NEON_H) +#include "arm_neon.h" +#endif + + +ScopedFTZ::ScopedFTZ() +{ +#if (HAVE_X86INTRIN_H || HAVE_INTRIN_H) + unsigned mask = _MM_DENORMALS_ZERO_MASK | _MM_FLUSH_ZERO_MASK; + registerState = _mm_getcsr(); + _mm_setcsr((registerState & (~mask)) | mask); +#elif HAVE_ARM_NEON_H + intptr_t mask = (1 << 24); + asm volatile("vmrs %0, fpscr" : "=r"(registerState)); + asm volatile("vmsr fpscr, %0" : : "ri"((registerState & (~mask)) | mask)); +#endif +} + +ScopedFTZ::~ScopedFTZ() +{ +#if (HAVE_X86INTRIN_H || HAVE_INTRIN_H) + _mm_setcsr(registerState); +#elif HAVE_ARM_NEON_H + asm volatile("vmsr %0, fpscr" : : "ri"(registerState)); +#endif +} \ No newline at end of file diff --git a/sources/ScopedFTZ.h b/sources/ScopedFTZ.h new file mode 100644 index 00000000..4590c540 --- /dev/null +++ b/sources/ScopedFTZ.h @@ -0,0 +1,31 @@ +// Copyright (c) 2019, Paul Ferrand +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: + +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +class ScopedFTZ { + +public: + ScopedFTZ(); + ~ScopedFTZ(); +private: + unsigned registerState; +}; \ No newline at end of file diff --git a/sources/SfzHelpers.cpp b/sources/SfzHelpers.cpp new file mode 100644 index 00000000..2a08b833 --- /dev/null +++ b/sources/SfzHelpers.cpp @@ -0,0 +1,171 @@ +// Copyright (c) 2019, Paul Ferrand +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: + +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 "SfzHelpers.h" +#include "StringViewHelpers.h" + +std::optional sfz::readNoteValue(const std::string_view& value) +{ + switch(hash(value)) + { + case hash("c-1"): case hash("C-1"): return (uint8_t) 0; + case hash("c#-1"): case hash("C#-1"): return (uint8_t) 1; + case hash("d-1"): case hash("D-1"): return (uint8_t) 2; + case hash("d#-1"): case hash("D#-1"): return (uint8_t) 3; + case hash("e-1"): case hash("E-1"): return (uint8_t) 4; + case hash("f-1"): case hash("F-1"): return (uint8_t) 5; + case hash("f#-1"): case hash("F#-1"): return (uint8_t) 6; + case hash("g-1"): case hash("G-1"): return (uint8_t) 7; + case hash("g#-1"): case hash("G#-1"): return (uint8_t) 8; + case hash("a-1"): case hash("A-1"): return (uint8_t) 9; + case hash("a#-1"): case hash("A#-1"): return (uint8_t) 10; + case hash("b-1"): case hash("B-1"): return (uint8_t) 11; + + case hash("c0"): case hash("C0"): return (uint8_t) 12; + case hash("c#0"): case hash("C#0"): return (uint8_t) 13; + case hash("d0"): case hash("D0"): return (uint8_t) 14; + case hash("d#0"): case hash("D#0"): return (uint8_t) 15; + case hash("e0"): case hash("E0"): return (uint8_t) 16; + case hash("f0"): case hash("F0"): return (uint8_t) 17; + case hash("f#0"): case hash("F#0"): return (uint8_t) 18; + case hash("g0"): case hash("G0"): return (uint8_t) 19; + case hash("g#0"): case hash("G#0"): return (uint8_t) 20; + case hash("a0"): case hash("A0"): return (uint8_t) 21; + case hash("a#0"): case hash("A#0"): return (uint8_t) 22; + case hash("b0"): case hash("B0"): return (uint8_t) 23; + + case hash("c1"): case hash("C1"): return (uint8_t) 24; + case hash("c#1"): case hash("C#1"): return (uint8_t) 25; + case hash("d1"): case hash("D1"): return (uint8_t) 26; + case hash("d#1"): case hash("D#1"): return (uint8_t) 27; + case hash("e1"): case hash("E1"): return (uint8_t) 28; + case hash("f1"): case hash("F1"): return (uint8_t) 29; + case hash("f#1"): case hash("F#1"): return (uint8_t) 30; + case hash("g1"): case hash("G1"): return (uint8_t) 31; + case hash("g#1"): case hash("G#1"): return (uint8_t) 32; + case hash("a1"): case hash("A1"): return (uint8_t) 33; + case hash("a#1"): case hash("A#1"): return (uint8_t) 34; + case hash("b1"): case hash("B1"): return (uint8_t) 35; + + case hash("c2"): case hash("C2"): return (uint8_t) 36; + case hash("c#2"): case hash("C#2"): return (uint8_t) 37; + case hash("d2"): case hash("D2"): return (uint8_t) 38; + case hash("d#2"): case hash("D#2"): return (uint8_t) 39; + case hash("e2"): case hash("E2"): return (uint8_t) 40; + case hash("f2"): case hash("F2"): return (uint8_t) 41; + case hash("f#2"): case hash("F#2"): return (uint8_t) 42; + case hash("g2"): case hash("G2"): return (uint8_t) 43; + case hash("g#2"): case hash("G#2"): return (uint8_t) 44; + case hash("a2"): case hash("A2"): return (uint8_t) 45; + case hash("a#2"): case hash("A#2"): return (uint8_t) 46; + case hash("b2"): case hash("B2"): return (uint8_t) 47; + + case hash("c3"): case hash("C3"): return (uint8_t) 48; + case hash("c#3"): case hash("C#3"): return (uint8_t) 49; + case hash("d3"): case hash("D3"): return (uint8_t) 50; + case hash("d#3"): case hash("D#3"): return (uint8_t) 51; + case hash("e3"): case hash("E3"): return (uint8_t) 52; + case hash("f3"): case hash("F3"): return (uint8_t) 53; + case hash("f#3"): case hash("F#3"): return (uint8_t) 54; + case hash("g3"): case hash("G3"): return (uint8_t) 55; + case hash("g#3"): case hash("G#3"): return (uint8_t) 56; + case hash("a3"): case hash("A3"): return (uint8_t) 57; + case hash("a#3"): case hash("A#3"): return (uint8_t) 58; + case hash("b3"): case hash("B3"): return (uint8_t) 59; + + case hash("c4"): case hash("C4"): return (uint8_t) 60; + case hash("c#4"): case hash("C#4"): return (uint8_t) 61; + case hash("d4"): case hash("D4"): return (uint8_t) 62; + case hash("d#4"): case hash("D#4"): return (uint8_t) 63; + case hash("e4"): case hash("E4"): return (uint8_t) 64; + case hash("f4"): case hash("F4"): return (uint8_t) 65; + case hash("f#4"): case hash("F#4"): return (uint8_t) 66; + case hash("g4"): case hash("G4"): return (uint8_t) 67; + case hash("g#4"): case hash("G#4"): return (uint8_t) 68; + case hash("a4"): case hash("A4"): return (uint8_t) 69; + case hash("a#4"): case hash("A#4"): return (uint8_t) 70; + case hash("b4"): case hash("B4"): return (uint8_t) 71; + + case hash("c5"): case hash("C5"): return (uint8_t) 72; + case hash("c#5"): case hash("C#5"): return (uint8_t) 73; + case hash("d5"): case hash("D5"): return (uint8_t) 74; + case hash("d#5"): case hash("D#5"): return (uint8_t) 75; + case hash("e5"): case hash("E5"): return (uint8_t) 76; + case hash("f5"): case hash("F5"): return (uint8_t) 77; + case hash("f#5"): case hash("F#5"): return (uint8_t) 78; + case hash("g5"): case hash("G5"): return (uint8_t) 79; + case hash("g#5"): case hash("G#5"): return (uint8_t) 80; + case hash("a5"): case hash("A5"): return (uint8_t) 81; + case hash("a#5"): case hash("A#5"): return (uint8_t) 82; + case hash("b5"): case hash("B5"): return (uint8_t) 83; + + case hash("c6"): case hash("C6"): return (uint8_t) 84; + case hash("c#6"): case hash("C#6"): return (uint8_t) 85; + case hash("d6"): case hash("D6"): return (uint8_t) 86; + case hash("d#6"): case hash("D#6"): return (uint8_t) 87; + case hash("e6"): case hash("E6"): return (uint8_t) 88; + case hash("f6"): case hash("F6"): return (uint8_t) 89; + case hash("f#6"): case hash("F#6"): return (uint8_t) 90; + case hash("g6"): case hash("G6"): return (uint8_t) 91; + case hash("g#6"): case hash("G#6"): return (uint8_t) 92; + case hash("a6"): case hash("A6"): return (uint8_t) 93; + case hash("a#6"): case hash("A#6"): return (uint8_t) 94; + case hash("b6"): case hash("B6"): return (uint8_t) 95; + + case hash("c7"): case hash("C7"): return (uint8_t) 96; + case hash("c#7"): case hash("C#7"): return (uint8_t) 97; + case hash("d7"): case hash("D7"): return (uint8_t) 98; + case hash("d#7"): case hash("D#7"): return (uint8_t) 99; + case hash("e7"): case hash("E7"): return (uint8_t) 100; + case hash("f7"): case hash("F7"): return (uint8_t) 101; + case hash("f#7"): case hash("F#7"): return (uint8_t) 102; + case hash("g7"): case hash("G7"): return (uint8_t) 103; + case hash("g#7"): case hash("G#7"): return (uint8_t) 104; + case hash("a7"): case hash("A7"): return (uint8_t) 105; + case hash("a#7"): case hash("A#7"): return (uint8_t) 106; + case hash("b7"): case hash("B7"): return (uint8_t) 107; + + case hash("c8"): case hash("C8"): return (uint8_t) 108; + case hash("c#8"): case hash("C#8"): return (uint8_t) 109; + case hash("d8"): case hash("D8"): return (uint8_t) 110; + case hash("d#8"): case hash("D#8"): return (uint8_t) 111; + case hash("e8"): case hash("E8"): return (uint8_t) 112; + case hash("f8"): case hash("F8"): return (uint8_t) 113; + case hash("f#8"): case hash("F#8"): return (uint8_t) 114; + case hash("g8"): case hash("G8"): return (uint8_t) 115; + case hash("g#8"): case hash("G#8"): return (uint8_t) 116; + case hash("a8"): case hash("A8"): return (uint8_t) 117; + case hash("a#8"): case hash("A#8"): return (uint8_t) 118; + case hash("b8"): case hash("B8"): return (uint8_t) 119; + + case hash("c9"): case hash("C9"): return (uint8_t) 120; + case hash("c#9"): case hash("C#9"): return (uint8_t) 121; + case hash("d9"): case hash("D9"): return (uint8_t) 122; + case hash("d#9"): case hash("D#9"): return (uint8_t) 123; + case hash("e9"): case hash("E9"): return (uint8_t) 124; + case hash("f9"): case hash("F9"): return (uint8_t) 125; + case hash("f#9"): case hash("F#9"): return (uint8_t) 126; + case hash("g9"): case hash("G9"): return (uint8_t) 127; + default: return {}; + } +} diff --git a/sources/SfzHelpers.h b/sources/SfzHelpers.h index 3ac89d77..1cc4ea41 100644 --- a/sources/SfzHelpers.h +++ b/sources/SfzHelpers.h @@ -26,7 +26,6 @@ #include #include #include -#include "Helpers.h" namespace sfz { @@ -63,5 +62,6 @@ inline float ccSwitchedValue(const CCValueArray& ccValues, const std::optional readNoteValue(const std::string_view& value); + } // namespace sfz diff --git a/sources/StereoBuffer.h b/sources/StereoBuffer.h index 418a22ae..15211a89 100644 --- a/sources/StereoBuffer.h +++ b/sources/StereoBuffer.h @@ -24,7 +24,8 @@ #pragma once #include "Buffer.h" #include "Globals.h" -#include "Helpers.h" +#include "Debug.h" +#include "LeakDetector.h" #include "SIMDHelpers.h" #include #include diff --git a/sources/StereoSpan.h b/sources/StereoSpan.h index 9f56a805..377a9c35 100644 --- a/sources/StereoSpan.h +++ b/sources/StereoSpan.h @@ -22,7 +22,7 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once -#include "Helpers.h" +#include "LeakDetector.h" #include "SIMDHelpers.h" #include "StereoBuffer.h" #include diff --git a/sources/StringViewHelpers.h b/sources/StringViewHelpers.h new file mode 100644 index 00000000..039f4c3f --- /dev/null +++ b/sources/StringViewHelpers.h @@ -0,0 +1,63 @@ +// Copyright (c) 2019, Paul Ferrand +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: + +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once +#include + +inline void trimInPlace(std::string_view& s) +{ + const auto leftPosition = s.find_first_not_of(" \r\t\n\f\v"); + if (leftPosition != s.npos) { + s.remove_prefix(leftPosition); + const auto rightPosition = s.find_last_not_of(" \r\t\n\f\v"); + s.remove_suffix(s.size() - rightPosition - 1); + } else { + s.remove_suffix(s.size()); + } +} + +inline std::string_view trim(std::string_view s) +{ + const auto leftPosition = s.find_first_not_of(" \r\t\n\f\v"); + if (leftPosition != s.npos) { + s.remove_prefix(leftPosition); + const auto rightPosition = s.find_last_not_of(" \r\t\n\f\v"); + s.remove_suffix(s.size() - rightPosition - 1); + } else { + s.remove_suffix(s.size()); + } + return s; +} + +inline constexpr uint64_t Fnv1aBasis = 0x811C9DC5; +inline constexpr uint64_t Fnv1aPrime = 0x01000193; + +inline constexpr uint64_t hash(std::string_view s, uint64_t h = Fnv1aBasis) +{ + if (s.length() > 0) + return hash( { s.data() + 1, s.length() - 1 }, (h ^ s.front()) * Fnv1aPrime ); + + return h; +} + + diff --git a/sources/Synth.cpp b/sources/Synth.cpp index 2d922e38..79f9c751 100644 --- a/sources/Synth.cpp +++ b/sources/Synth.cpp @@ -22,7 +22,9 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Synth.h" -#include "Helpers.h" +#include "ScopedFTZ.h" +#include "Debug.h" +#include "StringViewHelpers.h" #include "absl/algorithm/container.h" #include #include diff --git a/sources/Synth.h b/sources/Synth.h index 9a595fac..05c685c5 100644 --- a/sources/Synth.h +++ b/sources/Synth.h @@ -25,18 +25,14 @@ #include "FilePool.h" #include "Parser.h" #include "Region.h" -#include "SfzHelpers.h" -#include "Helpers.h" +#include "LeakDetector.h" #include "StereoSpan.h" #include "absl/types/span.h" -#include #include #include #include #include -#include #include -using namespace std::literals; namespace sfz { @@ -99,8 +95,7 @@ private: StereoBuffer tempBuffer { config::defaultSamplesPerBlock }; int samplesPerBlock { config::defaultSamplesPerBlock }; float sampleRate { config::defaultSampleRate }; - std::random_device rd {}; - std::mt19937 randomGenerator { rd() }; + std::uniform_real_distribution randNoteDistribution { 0, 1 }; LEAK_DETECTOR(Synth); diff --git a/sources/Voice.cpp b/sources/Voice.cpp index 3907dd7b..10404d60 100644 --- a/sources/Voice.cpp +++ b/sources/Voice.cpp @@ -21,6 +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 "Voice.h" #include "Voice.h" #include "SIMDHelpers.h" #include "SfzHelpers.h" diff --git a/sources/Voice.h b/sources/Voice.h index 5524acb2..24ce30af 100644 --- a/sources/Voice.h +++ b/sources/Voice.h @@ -27,6 +27,7 @@ #include "Region.h" #include "StereoBuffer.h" #include "StereoSpan.h" +#include "LeakDetector.h" #include #include diff --git a/tests/HelpersT.cpp b/tests/HelpersT.cpp index 2c678abd..51e628e3 100644 --- a/tests/HelpersT.cpp +++ b/tests/HelpersT.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 "../sources/Helpers.h" +#include "../sources/StringViewHelpers.h" #include "catch2/catch.hpp" #include using namespace Catch::literals;