From e328a136fc882672859e10ed7d67af60cb5bff8f Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 13 Feb 2025 11:15:08 -0700 Subject: [PATCH] Use C++20 std::numbers, std::lerp() (#7696) * use c++20 concepts and numbers for lmms_constants.h * replace lmms::numbers::sqrt2 with std::numbers::sqrt2 * replace lmms::numbers::e with std::numbers::e Also replace the only use of lmms::numbers::inv_e with a local constexpr instead * remove lmms::numbers::pi_half and lmms::numbers::pi_sqr They were only used in one or two places each * replace lmms::numbers::pi with std::numbers::pi * add #include to every file touched so far This is probably not needed for some of these files. I'll remove those later * Remove lmms::numbers Rest in peace lmms::numbers::tau, my beloved * Add missing #include * replace stray use of F_EPSILON with approximatelyEqual() * make many constants inline constexpr A lot of the remaining constants in lmms_constants.h are specific to SaProcessor. If they are only used there, shouldn't they be in SaProcessor.h? * ok then, it's allowed to be signed * remove #include "lmms_constants.h" for files that don't need it - And also move F_EPSILON into lmms_math.h - And also add an overload for fast_rand() to specify a higher and lower bound - And a bunch of other nonsense * ok then, it's allowed to be inferred * ok then, it can accept an integral * fix typo * appease msvc * appease msvc again * Replace linearInterpolate with std::lerp() As well as time travel to undo several foolish decisions and squash tiny commits together * Fix msvc constexpr warnings * Fix msvc float to double truncation warning * Apply two suggestions from code review Co-authored-by: Dalton Messmer * Apply suggestions from code review Co-authored-by: Dalton Messmer * fix silly mistake * Remove SlicerT's dependence on lmms_math.h * Allow more type inference on fastRand() and fastPow10f() * Apply suggestions from code review Co-authored-by: Dalton Messmer * Clean up fastRand() a little bit more --------- Co-authored-by: Dalton Messmer --- include/BandLimitedWave.h | 4 +- include/BasicFilters.h | 30 ++++--- include/ColorHelper.h | 10 ++- include/Delay.h | 14 +-- include/DspEffectLibrary.h | 5 +- include/Oscillator.h | 21 ++--- include/QuadratureLfo.h | 9 +- include/interpolation.h | 11 +-- include/lmms_constants.h | 90 +++++-------------- include/lmms_math.h | 78 +++++++++------- plugins/BitInvader/BitInvader.cpp | 7 +- plugins/Bitcrush/Bitcrush.cpp | 5 +- plugins/Compressor/Compressor.cpp | 19 ++-- .../Compressor/CompressorControlDialog.cpp | 16 +++- plugins/Delay/Lfo.cpp | 3 +- plugins/Delay/Lfo.h | 8 +- plugins/Dispersion/Dispersion.cpp | 2 +- .../DynamicsProcessor/DynamicsProcessor.cpp | 6 +- plugins/Eq/EqCurve.cpp | 16 ++-- plugins/Eq/EqFilter.h | 16 ++-- plugins/Eq/EqParameterWidget.cpp | 3 +- plugins/Eq/EqSpectrumView.cpp | 9 +- plugins/Flanger/FlangerEffect.cpp | 9 +- .../GranularPitchShifterEffect.cpp | 12 ++- .../GranularPitchShifterEffect.h | 15 ++-- plugins/Kicker/KickerOsc.h | 5 +- plugins/LOMM/LOMM.cpp | 13 +-- plugins/LOMM/LOMM.h | 1 - plugins/Monstro/Monstro.cpp | 12 ++- plugins/MultitapEcho/MultitapEcho.cpp | 1 + plugins/MultitapEcho/MultitapEcho.h | 2 +- plugins/Nes/Nes.cpp | 5 +- plugins/SlicerT/SlicerT.cpp | 4 +- plugins/Stk/Mallets/Mallets.cpp | 13 +-- plugins/Watsyn/Watsyn.cpp | 65 ++++++++------ plugins/WaveShaper/WaveShaper.cpp | 5 +- plugins/Xpressive/ExprSynth.cpp | 9 +- plugins/Xpressive/Xpressive.cpp | 5 +- src/core/BandLimitedWave.cpp | 13 +-- src/core/DrumSynth.cpp | 30 +++---- src/core/Effect.cpp | 4 +- src/core/Instrument.cpp | 7 +- src/core/NotePlayHandle.cpp | 2 +- src/core/Oscillator.cpp | 15 ++-- src/core/ValueBuffer.cpp | 7 +- src/core/fft_helpers.cpp | 9 +- src/gui/widgets/Knob.cpp | 3 +- 47 files changed, 327 insertions(+), 321 deletions(-) diff --git a/include/BandLimitedWave.h b/include/BandLimitedWave.h index 1c1a052ca..c70b8f6eb 100644 --- a/include/BandLimitedWave.h +++ b/include/BandLimitedWave.h @@ -156,11 +156,11 @@ public: t += 1; const sample_t s3 = s_waveforms[ static_cast(_wave) ].sampleAt( t, lookup ); const sample_t s4 = s_waveforms[ static_cast(_wave) ].sampleAt( t, ( lookup + 1 ) % tlen ); - const sample_t s34 = linearInterpolate( s3, s4, ip ); + const sample_t s34 = std::lerp(s3, s4, ip); const float ip2 = ( ( tlen - _wavelen ) / tlen - 0.5 ) * 2.0; - return linearInterpolate( s12, s34, ip2 ); + return std::lerp(s12, s34, ip2); */ }; diff --git a/include/BasicFilters.h b/include/BasicFilters.h index c4664009c..51d617480 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -31,12 +31,12 @@ #ifndef LMMS_BASIC_FILTERS_H #define LMMS_BASIC_FILTERS_H -#include +#include #include +#include +#include #include "lmms_basics.h" -#include "lmms_constants.h" -#include "interpolation.h" namespace lmms { @@ -69,21 +69,22 @@ public: inline void setCoeffs( float freq ) { + using namespace std::numbers; // wc - const double wc = numbers::tau * freq; + const double wc = 2 * pi * freq; const double wc2 = wc * wc; const double wc3 = wc2 * wc; m_wc4 = wc2 * wc2; // k - const double k = wc / std::tan(numbers::pi * freq / m_sampleRate); + const double k = wc / std::tan(pi * freq / m_sampleRate); const double k2 = k * k; const double k3 = k2 * k; m_k4 = k2 * k2; // a - const double sq_tmp1 = numbers::sqrt2 * wc3 * k; - const double sq_tmp2 = numbers::sqrt2 * wc * k3; + const double sq_tmp1 = sqrt2 * wc3 * k; + const double sq_tmp2 = sqrt2 * wc * k3; m_a = 1.0 / ( 4.0 * wc2 * k2 + 2.0 * sq_tmp1 + m_k4 + 2.0 * sq_tmp2 + m_wc4 ); @@ -206,7 +207,7 @@ public: inline float update( float s, ch_cnt_t ch ) { - if (std::abs(s) < 1.0e-10f && std::abs(m_z1[ch]) < 1.0e-10f) return 0.0f; + if (std::abs(s) < 1.0e-10f && std::abs(m_z1[ch]) < 1.0e-10f) { return 0.0f; } return m_z1[ch] = s * m_a0 + m_z1[ch] * m_b1; } @@ -375,7 +376,7 @@ public: for( int i = 0; i < 4; ++i ) { ip += 0.25f; - sample_t x = linearInterpolate( m_last[_chnl], _in0, ip ) - m_r * m_y3[_chnl]; + sample_t x = std::lerp(m_last[_chnl], _in0, ip) - m_r * m_y3[_chnl]; m_y1[_chnl] = std::clamp((x + m_oldx[_chnl]) * m_p - m_k * m_y1[_chnl], -10.0f, @@ -701,6 +702,7 @@ public: inline void calcFilterCoeffs( float _freq, float _q ) { + using namespace std::numbers; // temp coef vars _q = std::max(_q, minQ()); @@ -713,7 +715,7 @@ public: { _freq = std::clamp(_freq, 50.0f, 20000.0f); const float sr = m_sampleRatio * 0.25f; - const float f = 1.0f / (_freq * numbers::tau_v); + const float f = 1.0f / (_freq * 2 * pi_v); m_rca = 1.0f - sr / ( f + sr ); m_rcb = 1.0f - m_rca; @@ -746,8 +748,8 @@ public: const float fract = vowelf - vowel; // interpolate between formant frequencies - const float f0 = 1.0f / (linearInterpolate(_f[vowel+0][0], _f[vowel+1][0], fract) * numbers::tau_v); - const float f1 = 1.0f / (linearInterpolate(_f[vowel+0][1], _f[vowel+1][1], fract) * numbers::tau_v); + const float f0 = 1.f / (std::lerp(_f[vowel+0][0], _f[vowel+1][0], fract) * 2 * pi_v); + const float f1 = 1.f / (std::lerp(_f[vowel+0][1], _f[vowel+1][1], fract) * 2 * pi_v); // samplerate coeff: depends on oversampling const float sr = m_type == FilterType::FastFormant ? m_sampleRatio : m_sampleRatio * 0.25f; @@ -796,7 +798,7 @@ public: m_type == FilterType::Highpass_SV || m_type == FilterType::Notch_SV ) { - const float f = std::sin(std::max(minFreq(), _freq) * m_sampleRatio * numbers::pi_v); + const float f = std::sin(std::max(minFreq(), _freq) * m_sampleRatio * pi_v); m_svf1 = std::min(f, 0.825f); m_svf2 = std::min(f * 2.0f, 0.825f); m_svq = std::max(0.0001f, 2.0f - (_q * 0.1995f)); @@ -805,7 +807,7 @@ public: // other filters _freq = std::clamp(_freq, minFreq(), 20000.0f); - const float omega = numbers::tau_v * _freq * m_sampleRatio; + const float omega = 2 * pi_v * _freq * m_sampleRatio; const float tsin = std::sin(omega) * 0.5f; const float tcos = std::cos(omega); diff --git a/include/ColorHelper.h b/include/ColorHelper.h index 78f99b9e2..b313d9b46 100644 --- a/include/ColorHelper.h +++ b/include/ColorHelper.h @@ -24,6 +24,7 @@ #ifndef LMMS_GUI_COLOR_HELPER_H #define LMMS_GUI_COLOR_HELPER_H +#include #include namespace lmms::gui @@ -40,10 +41,11 @@ public: qreal br, bg, bb, ba; b.getRgbF(&br, &bg, &bb, &ba); - const float interH = lerp(ar, br, t); - const float interS = lerp(ag, bg, t); - const float interV = lerp(ab, bb, t); - const float interA = lerp(aa, ba, t); + const auto t2 = static_cast(t); + const float interH = std::lerp(ar, br, t2); + const float interS = std::lerp(ag, bg, t2); + const float interV = std::lerp(ab, bb, t2); + const float interA = std::lerp(aa, ba, t2); return QColor::fromRgbF(interH, interS, interV, interA); } diff --git a/include/Delay.h b/include/Delay.h index 71fbe1b00..8ead1c37b 100644 --- a/include/Delay.h +++ b/include/Delay.h @@ -26,9 +26,9 @@ #ifndef LMMS_DELAY_H #define LMMS_DELAY_H +#include + #include "lmms_basics.h" -#include "lmms_math.h" -#include "interpolation.h" namespace lmms { @@ -114,7 +114,7 @@ public: int readPos = m_position - m_delay; if( readPos < 0 ) { readPos += m_size; } - const double y = linearInterpolate( m_buffer[readPos][ch], m_buffer[( readPos + 1 ) % m_size][ch], m_fraction ); + const double y = std::lerp(m_buffer[readPos][ch], m_buffer[(readPos + 1) % m_size][ch], m_fraction); ++m_position %= m_size; @@ -185,7 +185,7 @@ class CombFeedfwd int readPos = m_position - m_delay; if( readPos < 0 ) { readPos += m_size; } - const double y = linearInterpolate( m_buffer[readPos][ch], m_buffer[( readPos + 1 ) % m_size][ch], m_fraction ) + in * m_gain; + const double y = std::lerp(m_buffer[readPos][ch], m_buffer[(readPos + 1) % m_size][ch], m_fraction) + in * m_gain; ++m_position %= m_size; @@ -262,8 +262,8 @@ class CombFeedbackDualtap int readPos2 = m_position - m_delay2; if( readPos2 < 0 ) { readPos2 += m_size; } - const double y = linearInterpolate( m_buffer[readPos1][ch], m_buffer[( readPos1 + 1 ) % m_size][ch], m_fraction1 ) + - linearInterpolate( m_buffer[readPos2][ch], m_buffer[( readPos2 + 1 ) % m_size][ch], m_fraction2 ); + const double y = std::lerp(m_buffer[readPos1][ch], m_buffer[(readPos1 + 1) % m_size][ch], m_fraction1) + + std::lerp(m_buffer[readPos2][ch], m_buffer[(readPos2 + 1) % m_size][ch], m_fraction2); ++m_position %= m_size; @@ -337,7 +337,7 @@ public: int readPos = m_position - m_delay; if( readPos < 0 ) { readPos += m_size; } - const double y = linearInterpolate( m_buffer[readPos][ch], m_buffer[( readPos + 1 ) % m_size][ch], m_fraction ) + in * -m_gain; + const double y = std::lerp(m_buffer[readPos][ch], m_buffer[(readPos + 1) % m_size][ch], m_fraction) + in * -m_gain; const double x = in + m_gain * y; ++m_position %= m_size; diff --git a/include/DspEffectLibrary.h b/include/DspEffectLibrary.h index 55afb69f7..656d5b1dd 100644 --- a/include/DspEffectLibrary.h +++ b/include/DspEffectLibrary.h @@ -25,8 +25,9 @@ #ifndef LMMS_DSPEFFECTLIBRARY_H #define LMMS_DSPEFFECTLIBRARY_H +#include + #include "lmms_math.h" -#include "lmms_constants.h" #include "lmms_basics.h" #include "SampleFrame.h" @@ -328,7 +329,7 @@ namespace lmms::DspEffectLibrary void nextSample( sample_t& inLeft, sample_t& inRight ) { - const float toRad = numbers::pi_v / 180; + constexpr float toRad = std::numbers::pi_v / 180.f; const sample_t tmp = inLeft; inLeft += inRight * std::sin(m_wideCoeff * toRad * .5f); inRight -= tmp * std::sin(m_wideCoeff * toRad * .5f); diff --git a/include/Oscillator.h b/include/Oscillator.h index 10fc64925..648fe3bb8 100644 --- a/include/Oscillator.h +++ b/include/Oscillator.h @@ -30,10 +30,10 @@ #include #include #include -#include "interpolation.h" +#include #include "Engine.h" -#include "lmms_constants.h" +#include "lmms_math.h" #include "lmmsconfig.h" #include "AudioEngine.h" #include "OscillatorConstants.h" @@ -114,7 +114,7 @@ public: // now follow the wave-shape-routines... static inline sample_t sinSample( const float _sample ) { - return std::sin(_sample * numbers::tau_v); + return std::sin(_sample * 2 * std::numbers::pi_v); } static inline sample_t triangleSample( const float _sample ) @@ -173,7 +173,7 @@ public: const auto frame = absFraction(sample) * frames; const auto f1 = static_cast(frame); - return linearInterpolate(buffer->data()[f1][0], buffer->data()[(f1 + 1) % frames][0], fraction(frame)); + return std::lerp(buffer->data()[f1][0], buffer->data()[(f1 + 1) % frames][0], fraction(frame)); } struct wtSampleControl { @@ -202,24 +202,25 @@ public: { assert(table != nullptr); wtSampleControl control = getWtSampleControl(sample); - return linearInterpolate(table[control.band][control.f1], - table[control.band][control.f2], fraction(control.frame)); + return std::lerp(table[control.band][control.f1], table[control.band][control.f2], fraction(control.frame)); } sample_t wtSample(const OscillatorConstants::waveform_t* table, const float sample) const { assert(table != nullptr); wtSampleControl control = getWtSampleControl(sample); - return linearInterpolate((*table)[control.band][control.f1], - (*table)[control.band][control.f2], fraction(control.frame)); + return std::lerp( + (*table)[control.band][control.f1], + (*table)[control.band][control.f2], + fraction(control.frame) + ); } inline sample_t wtSample(sample_t **table, const float sample) const { assert(table != nullptr); wtSampleControl control = getWtSampleControl(sample); - return linearInterpolate(table[control.band][control.f1], - table[control.band][control.f2], fraction(control.frame)); + return std::lerp(table[control.band][control.f1], table[control.band][control.f2], fraction(control.frame)); } static inline int waveTableBandFromFreq(float freq) diff --git a/include/QuadratureLfo.h b/include/QuadratureLfo.h index 72734a8b0..bece17c5a 100644 --- a/include/QuadratureLfo.h +++ b/include/QuadratureLfo.h @@ -25,7 +25,8 @@ #ifndef LMMS_QUADRATURE_LFO_H #define LMMS_QUADRATURE_LFO_H -#include "lmms_math.h" +#include +#include namespace lmms { @@ -37,7 +38,7 @@ public: QuadratureLfo( int sampleRate ) : m_frequency(0), m_phase(0), - m_offset(numbers::pi_half) + m_offset(std::numbers::pi * 0.5) { setSampleRate(sampleRate); } @@ -64,7 +65,7 @@ public: inline void setSampleRate ( int samplerate ) { m_samplerate = samplerate; - m_twoPiOverSr = numbers::tau_v / samplerate; + m_twoPiOverSr = 2 * std::numbers::pi_v / samplerate; m_increment = m_frequency * m_twoPiOverSr; } @@ -80,7 +81,7 @@ public: *l = std::sin(m_phase); *r = std::sin(m_phase + m_offset); m_phase += m_increment; - while (m_phase >= numbers::tau) { m_phase -= numbers::tau; } + m_phase = std::fmod(m_phase, 2 * std::numbers::pi); } private: diff --git a/include/interpolation.h b/include/interpolation.h index de9a94480..83e24e5ae 100644 --- a/include/interpolation.h +++ b/include/interpolation.h @@ -26,8 +26,7 @@ #define LMMS_INTERPOLATION_H #include -#include "lmms_constants.h" -#include "lmms_math.h" +#include namespace lmms { @@ -78,17 +77,11 @@ inline float cubicInterpolate( float v0, float v1, float v2, float v3, float x ) inline float cosinusInterpolate( float v0, float v1, float x ) { - const float f = (1.0f - std::cos(x * numbers::pi_v)) * 0.5f; + const float f = (1.0f - std::cos(x * std::numbers::pi_v)) * 0.5f; return f * (v1 - v0) + v0; } -inline float linearInterpolate( float v0, float v1, float x ) -{ - return x * (v1 - v0) + v0; -} - - inline float optimalInterpolate( float v0, float v1, float x ) { const float z = x - 0.5f; diff --git a/include/lmms_constants.h b/include/lmms_constants.h index 6ac0fac77..782e6849d 100644 --- a/include/lmms_constants.h +++ b/include/lmms_constants.h @@ -25,65 +25,20 @@ #ifndef LMMS_CONSTANTS_H #define LMMS_CONSTANTS_H -// #include -// #include - -namespace lmms::numbers -{ - -//TODO C++20: Use std::floating_point instead of typename -//TODO C++20: Use std::numbers::pi_v instead of literal value -template -inline constexpr T pi_v = T(3.14159265358979323846264338327950288419716939937510); -inline constexpr double pi = pi_v; - -//TODO C++20: Use std::floating_point instead of typename -template -inline constexpr T tau_v = T(pi_v * 2.0); -inline constexpr double tau = tau_v; - -//TODO C++20: Use std::floating_point instead of typename -template -inline constexpr T pi_half_v = T(pi_v / 2.0); -inline constexpr double pi_half = pi_half_v; - -//TODO C++20: Use std::floating_point instead of typename -template -inline constexpr T pi_sqr_v = T(pi_v * pi_v); -inline constexpr double pi_sqr = pi_sqr_v; - -//TODO C++20: Use std::floating_point instead of typename -//TODO C++20: Use std::numbers::e_v instead of literal value -template -inline constexpr T e_v = T(2.71828182845904523536028747135266249775724709369995); -inline constexpr double e = e_v; - -//TODO C++20: Use std::floating_point instead of typename -template -inline constexpr T inv_e_v = T(1.0 / e_v); -inline constexpr double inv_e = e_v; - -//TODO C++20: Use std::floating_point instead of typename -//TODO C++20: Use std::numbers::sqrt2_v instead of literal value -//TODO C++26: Remove since std::sqrt(2.0) is constexpr -template -inline constexpr T sqrt2_v = T(1.41421356237309504880168872420969807856967187537695); -inline constexpr double sqrt2 = sqrt2_v; - -} - namespace lmms { -constexpr float F_EPSILON = 1.0e-10f; // 10^-10 +// Prefer using `approximatelyEqual()` from lmms_math.h rather than +// using this directly +inline constexpr float F_EPSILON = 1.0e-10f; // 10^-10 // Microtuner -constexpr unsigned int MaxScaleCount = 10; //!< number of scales per project -constexpr unsigned int MaxKeymapCount = 10; //!< number of keyboard mappings per project +inline constexpr unsigned MaxScaleCount = 10; //!< number of scales per project +inline constexpr unsigned MaxKeymapCount = 10; //!< number of keyboard mappings per project // Frequency ranges (in Hz). // Arbitrary low limit for logarithmic frequency scale; >1 Hz. -constexpr int LOWEST_LOG_FREQ = 5; +inline constexpr auto LOWEST_LOG_FREQ = 5; // Full range is defined by LOWEST_LOG_FREQ and current sample rate. enum class FrequencyRange @@ -95,14 +50,14 @@ enum class FrequencyRange High }; -constexpr int FRANGE_AUDIBLE_START = 20; -constexpr int FRANGE_AUDIBLE_END = 20000; -constexpr int FRANGE_BASS_START = 20; -constexpr int FRANGE_BASS_END = 300; -constexpr int FRANGE_MIDS_START = 200; -constexpr int FRANGE_MIDS_END = 5000; -constexpr int FRANGE_HIGH_START = 4000; -constexpr int FRANGE_HIGH_END = 20000; +inline constexpr auto FRANGE_AUDIBLE_START = 20; +inline constexpr auto FRANGE_AUDIBLE_END = 20000; +inline constexpr auto FRANGE_BASS_START = 20; +inline constexpr auto FRANGE_BASS_END = 300; +inline constexpr auto FRANGE_MIDS_START = 200; +inline constexpr auto FRANGE_MIDS_END = 5000; +inline constexpr auto FRANGE_HIGH_START = 4000; +inline constexpr auto FRANGE_HIGH_END = 20000; // Amplitude ranges (in dBFS). // Reference: full scale sine wave (-1.0 to 1.0) is 0 dB. @@ -115,15 +70,14 @@ enum class AmplitudeRange Silent }; -constexpr int ARANGE_EXTENDED_START = -80; -constexpr int ARANGE_EXTENDED_END = 20; -constexpr int ARANGE_AUDIBLE_START = -50; -constexpr int ARANGE_AUDIBLE_END = 0; -constexpr int ARANGE_LOUD_START = -30; -constexpr int ARANGE_LOUD_END = 0; -constexpr int ARANGE_SILENT_START = -60; -constexpr int ARANGE_SILENT_END = -10; - +inline constexpr auto ARANGE_EXTENDED_START = -80; +inline constexpr auto ARANGE_EXTENDED_END = 20; +inline constexpr auto ARANGE_AUDIBLE_START = -50; +inline constexpr auto ARANGE_AUDIBLE_END = 0; +inline constexpr auto ARANGE_LOUD_START = -30; +inline constexpr auto ARANGE_LOUD_END = 0; +inline constexpr auto ARANGE_SILENT_START = -60; +inline constexpr auto ARANGE_SILENT_END = -10; } // namespace lmms diff --git a/include/lmms_math.h b/include/lmms_math.h index be58e6805..1d3de249d 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -31,18 +31,22 @@ #include #include #include +#include +#include -#include "lmms_constants.h" #include "lmmsconfig.h" +#include "lmms_constants.h" namespace lmms { -inline bool approximatelyEqual(float x, float y) +// TODO C++23: Make constexpr since std::abs() will be constexpr +inline bool approximatelyEqual(float x, float y) noexcept { - return x == y ? true : std::abs(x - y) < F_EPSILON; + return x == y || std::abs(x - y) < F_EPSILON; } +// TODO C++23: Make constexpr since std::trunc() will be constexpr /*! * @brief Returns the fractional part of a float, a value between -1.0f and 1.0f. * @@ -52,11 +56,13 @@ inline bool approximatelyEqual(float x, float y) * Note that if the return value is used as a phase of an oscillator, that the oscillator must support * negative phases. */ -inline float fraction(const float x) +inline auto fraction(std::floating_point auto x) noexcept { return x - std::trunc(x); } + +// TODO C++23: Make constexpr since std::floor() will be constexpr /*! * @brief Returns the wrapped fractional part of a float, a value between 0.0f and 1.0f. * @@ -67,25 +73,30 @@ inline float fraction(const float x) * If the result is interpreted as a phase of an oscillator, it makes that negative phases are * converted to positive phases. */ -inline float absFraction(const float x) +inline auto absFraction(std::floating_point auto x) noexcept { return x - std::floor(x); } - -constexpr float FAST_RAND_RATIO = 1.0f / 32767; -inline int fast_rand() +inline auto fastRand() noexcept { static unsigned long next = 1; next = next * 1103515245 + 12345; - return( (unsigned)( next / 65536 ) % 32768 ); + return next / 65536 % 32768; } -inline float fastRandf(float range) +template +inline auto fastRand(T range) noexcept { - return fast_rand() * range * FAST_RAND_RATIO; + constexpr T FAST_RAND_RATIO = static_cast(1.0 / 32767); + return fastRand() * range * FAST_RAND_RATIO; } +template +inline auto fastRand(T from, T to) noexcept +{ + return from + fastRand(to - from); +} //! Round `value` to `where` depending on step size template @@ -112,10 +123,11 @@ inline double fastPow(double a, double b) } -//! returns 1.0f if val >= 0.0f, -1.0 else -inline float sign(float val) +//! returns +1 if val >= 0, else -1 +template +constexpr T sign(T val) noexcept { - return val >= 0.0f ? 1.0f : -1.0f; + return val >= 0 ? 1 : -1; } @@ -136,14 +148,15 @@ inline float signedPowf(float v, float e) //! Value should be within [0,1] inline float logToLinearScale(float min, float max, float value) { + using namespace std::numbers; if (min < 0) { const float mmax = std::max(std::abs(min), std::abs(max)); const float val = value * (max - min) + min; - float result = signedPowf(val / mmax, numbers::e_v) * mmax; + float result = signedPowf(val / mmax, e_v) * mmax; return std::isnan(result) ? 0 : result; } - float result = std::pow(value, numbers::e_v) * (max - min) + min; + float result = std::pow(value, e_v) * (max - min) + min; return std::isnan(result) ? 0 : result; } @@ -151,26 +164,37 @@ inline float logToLinearScale(float min, float max, float value) //! @brief Scales value from logarithmic to linear. Value should be in min-max range. inline float linearToLogScale(float min, float max, float value) { + constexpr auto inv_e = static_cast(1.0 / std::numbers::e); const float valueLimited = std::clamp(value, min, max); const float val = (valueLimited - min) / (max - min); if (min < 0) { const float mmax = std::max(std::abs(min), std::abs(max)); - float result = signedPowf(valueLimited / mmax, numbers::inv_e_v) * mmax; + float result = signedPowf(valueLimited / mmax, inv_e) * mmax; return std::isnan(result) ? 0 : result; } - float result = std::pow(val, numbers::inv_e_v) * (max - min) + min; + float result = std::pow(val, inv_e) * (max - min) + min; return std::isnan(result) ? 0 : result; } -inline float fastPow10f(float x) +// TODO C++26: Make constexpr since std::exp() will be constexpr +template +inline auto fastPow10f(T x) { - return std::exp(2.302585092994046f * x); + return std::exp(std::numbers::ln10_v * x); } -inline float fastLog10f(float x) +// TODO C++26: Make constexpr since std::exp() will be constexpr +inline auto fastPow10f(std::integral auto x) { - return std::log(x) * 0.4342944819032518f; + return std::exp(std::numbers::ln10_v * x); +} + +// TODO C++26: Make constexpr since std::log() will be constexpr +inline auto fastLog10f(float x) +{ + constexpr auto inv_ln10 = static_cast(1.0 / std::numbers::ln10); + return std::log(x) * inv_ln10; } //! @brief Converts linear amplitude (>0-1.0) to dBFS scale. @@ -209,16 +233,8 @@ inline float safeDbfsToAmp(float dbfs) } - -//! Returns the linear interpolation of the two values -template -constexpr T lerp(T a, T b, F t) -{ - return (1. - t) * a + t * b; -} - +// TODO C++20: use std::formatted_size // @brief Calculate number of digits which LcdSpinBox would show for a given number -// @note Once we upgrade to C++20, we could probably use std::formatted_size inline int numDigitsAsInt(float f) { // use rounding: diff --git a/plugins/BitInvader/BitInvader.cpp b/plugins/BitInvader/BitInvader.cpp index 2f31449c7..dcd24e8e9 100644 --- a/plugins/BitInvader/BitInvader.cpp +++ b/plugins/BitInvader/BitInvader.cpp @@ -22,7 +22,7 @@ * */ - +#include #include #include "BitInvader.h" @@ -36,10 +36,9 @@ #include "NotePlayHandle.h" #include "PixmapButton.h" #include "Song.h" -#include "interpolation.h" +#include "lmms_math.h" #include "embed.h" - #include "plugin_export.h" namespace lmms @@ -121,7 +120,7 @@ sample_t BSynth::nextStringSample( float sample_length ) } const auto nextIndex = currentIndex < sample_length - 1 ? currentIndex + 1 : 0; - return linearInterpolate(sample_shape[currentIndex], sample_shape[nextIndex], fraction(currentRealIndex)); + return std::lerp(sample_shape[currentIndex], sample_shape[nextIndex], fraction(currentRealIndex)); } /*********************************************************************** diff --git a/plugins/Bitcrush/Bitcrush.cpp b/plugins/Bitcrush/Bitcrush.cpp index 7b9e8f8ef..624cdd90b 100644 --- a/plugins/Bitcrush/Bitcrush.cpp +++ b/plugins/Bitcrush/Bitcrush.cpp @@ -24,6 +24,7 @@ */ #include "Bitcrush.h" +#include "lmms_math.h" #include "embed.h" #include "plugin_export.h" @@ -97,7 +98,7 @@ inline float BitcrushEffect::depthCrush( float in ) inline float BitcrushEffect::noise( float amt ) { - return fastRandf( amt * 2.0f ) - amt; + return fastRand(-amt, +amt); } Effect::ProcessStatus BitcrushEffect::processImpl(SampleFrame* buf, const fpp_t frames) @@ -248,4 +249,4 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* parent, void* data ) } -} // namespace lmms \ No newline at end of file +} // namespace lmms diff --git a/plugins/Compressor/Compressor.cpp b/plugins/Compressor/Compressor.cpp index 06d4f1d0d..a6f6c79dc 100755 --- a/plugins/Compressor/Compressor.cpp +++ b/plugins/Compressor/Compressor.cpp @@ -24,8 +24,10 @@ #include "Compressor.h" +#include +#include + #include "embed.h" -#include "interpolation.h" #include "lmms_math.h" #include "plugin_export.h" @@ -209,18 +211,19 @@ void CompressorEffect::redrawKnee() void CompressorEffect::calcTiltCoeffs() { + using namespace std::numbers; m_tiltVal = m_compressorControls.m_tiltModel.value(); - const float amp = 6.f / std::log(2.f); + constexpr float amp = 6.f / ln2_v; - const float gfactor = 5; + constexpr float gfactor = 5; const float g1 = m_tiltVal > 0 ? -gfactor * m_tiltVal : -m_tiltVal; const float g2 = m_tiltVal > 0 ? m_tiltVal : gfactor * m_tiltVal; m_lgain = std::exp(g1 / amp) - 1; m_hgain = std::exp(g2 / amp) - 1; - const float omega = numbers::tau_v * m_compressorControls.m_tiltFreqModel.value(); + const float omega = 2 * pi_v * m_compressorControls.m_tiltFreqModel.value(); const float n = 1 / (m_sampleRate * 3 + omega); m_a0 = 2 * omega * n; m_b1 = (m_sampleRate * 3 - omega) * n; @@ -402,21 +405,21 @@ Effect::ProcessStatus CompressorEffect::processImpl(SampleFrame* buf, const fpp_ if (blend <= 1)// Blend to minimum volume { const float temp1 = qMin(m_gainResult[0], m_gainResult[1]); - m_gainResult[0] = linearInterpolate(m_gainResult[0], temp1, blend); - m_gainResult[1] = linearInterpolate(m_gainResult[1], temp1, blend); + m_gainResult[0] = std::lerp(m_gainResult[0], temp1, blend); + m_gainResult[1] = std::lerp(m_gainResult[1], temp1, blend); } else if (blend <= 2)// Blend to average volume { const float temp1 = qMin(m_gainResult[0], m_gainResult[1]); const float temp2 = (m_gainResult[0] + m_gainResult[1]) * 0.5f; - m_gainResult[0] = linearInterpolate(temp1, temp2, blend - 1); + m_gainResult[0] = std::lerp(temp1, temp2, blend - 1); m_gainResult[1] = m_gainResult[0]; } else// Blend to maximum volume { const float temp1 = (m_gainResult[0] + m_gainResult[1]) * 0.5f; const float temp2 = qMax(m_gainResult[0], m_gainResult[1]); - m_gainResult[0] = linearInterpolate(temp1, temp2, blend - 2); + m_gainResult[0] = std::lerp(temp1, temp2, blend - 2); m_gainResult[1] = m_gainResult[0]; } } diff --git a/plugins/Compressor/CompressorControlDialog.cpp b/plugins/Compressor/CompressorControlDialog.cpp index d7350ba59..2622fbc2b 100755 --- a/plugins/Compressor/CompressorControlDialog.cpp +++ b/plugins/Compressor/CompressorControlDialog.cpp @@ -26,6 +26,7 @@ #include "CompressorControlDialog.h" #include "CompressorControls.h" +#include #include #include #include @@ -34,7 +35,6 @@ #include "embed.h" #include "../Eq/EqFader.h" #include "GuiApplication.h" -#include "interpolation.h" #include "Knob.h" #include "MainWindow.h" #include "PixmapButton.h" @@ -437,7 +437,11 @@ void CompressorControlDialog::drawVisPixmap() m_p.setPen(QPen(m_inVolAreaColor, 1)); for (int i = 0; i < m_compPixelMovement; ++i) { - const int temp = linearInterpolate(m_lastPoint, m_yPoint, float(i) / float(m_compPixelMovement)); + const int temp = std::lerp( + m_lastPoint, + m_yPoint, + static_cast(i) / static_cast(m_compPixelMovement) + ); m_p.drawLine(m_windowSizeX-m_compPixelMovement+i, temp, m_windowSizeX-m_compPixelMovement+i, m_windowSizeY); } @@ -449,7 +453,11 @@ void CompressorControlDialog::drawVisPixmap() m_p.setPen(QPen(m_outVolAreaColor, 1)); for (int i = 0; i < m_compPixelMovement; ++i) { - const int temp = linearInterpolate(m_lastPoint+m_lastGainPoint, m_yPoint+m_yGainPoint, float(i) / float(m_compPixelMovement)); + const int temp = std::lerp( + m_lastPoint + m_lastGainPoint, + m_yPoint + m_yGainPoint, + static_cast(i) / static_cast(m_compPixelMovement) + ); m_p.drawLine(m_windowSizeX-m_compPixelMovement+i, temp, m_windowSizeX-m_compPixelMovement+i, m_windowSizeY); } @@ -512,7 +520,7 @@ void CompressorControlDialog::redrawKnee() // Draw knee curve using many straight lines. for (int i = 0; i < COMP_KNEE_LINES; ++i) { - newPoint[0] = linearInterpolate(kneePoint1, kneePoint2X, (i + 1) / (float)COMP_KNEE_LINES); + newPoint[0] = std::lerp(kneePoint1, kneePoint2X, (i + 1) / static_cast(COMP_KNEE_LINES)); const float temp = newPoint[0] - thresholdVal + kneeVal; newPoint[1] = (newPoint[0] + (actualRatio - 1) * temp * temp / (4 * kneeVal)); diff --git a/plugins/Delay/Lfo.cpp b/plugins/Delay/Lfo.cpp index e4e002b79..ce5903baa 100644 --- a/plugins/Delay/Lfo.cpp +++ b/plugins/Delay/Lfo.cpp @@ -25,6 +25,7 @@ #include "Lfo.h" #include +#include namespace lmms { @@ -33,7 +34,7 @@ namespace lmms Lfo::Lfo( int samplerate ) { m_samplerate = samplerate; - m_twoPiOverSr = numbers::tau_v / samplerate; + m_twoPiOverSr = 2 * std::numbers::pi_v / samplerate; } diff --git a/plugins/Delay/Lfo.h b/plugins/Delay/Lfo.h index 8f69412ea..f3fc22cf7 100644 --- a/plugins/Delay/Lfo.h +++ b/plugins/Delay/Lfo.h @@ -25,8 +25,8 @@ #ifndef LFO_H #define LFO_H -#include "lmms_constants.h" - +#include +#include namespace lmms { @@ -50,7 +50,7 @@ public: m_frequency = frequency; m_increment = m_frequency * m_twoPiOverSr; - if (m_phase >= numbers::tau_v) { m_phase -= numbers::tau_v; } + m_phase = std::fmod(m_phase, 2 * std::numbers::pi_v); } @@ -59,7 +59,7 @@ public: inline void setSampleRate ( int samplerate ) { m_samplerate = samplerate; - m_twoPiOverSr = numbers::tau_v / samplerate; + m_twoPiOverSr = 2 * std::numbers::pi_v / samplerate; m_increment = m_frequency * m_twoPiOverSr; } diff --git a/plugins/Dispersion/Dispersion.cpp b/plugins/Dispersion/Dispersion.cpp index 624c161e6..52dd60136 100644 --- a/plugins/Dispersion/Dispersion.cpp +++ b/plugins/Dispersion/Dispersion.cpp @@ -70,7 +70,7 @@ Effect::ProcessStatus DispersionEffect::processImpl(SampleFrame* buf, const fpp_ const bool dc = m_dispersionControls.m_dcModel.value(); // All-pass coefficient calculation - const float w0 = (numbers::tau_v / m_sampleRate) * freq; + const float w0 = (2 * std::numbers::pi_v / m_sampleRate) * freq; const float a0 = 1 + (std::sin(w0) / (reso * 2.f)); float apCoeff1 = (1 - (a0 - 1)) / a0; float apCoeff2 = (-2 * std::cos(w0)) / a0; diff --git a/plugins/DynamicsProcessor/DynamicsProcessor.cpp b/plugins/DynamicsProcessor/DynamicsProcessor.cpp index 752e63e23..4f8db97ce 100644 --- a/plugins/DynamicsProcessor/DynamicsProcessor.cpp +++ b/plugins/DynamicsProcessor/DynamicsProcessor.cpp @@ -25,8 +25,10 @@ #include "DynamicsProcessor.h" + +#include + #include "lmms_math.h" -#include "interpolation.h" #include "RmsHelper.h" #include "embed.h" @@ -189,7 +191,7 @@ Effect::ProcessStatus DynProcEffect::processImpl(SampleFrame* buf, const fpp_t f { float gain; if (lookup < 1) { gain = frac * samples[0]; } - else if (lookup < 200) { gain = linearInterpolate(samples[lookup - 1], samples[lookup], frac); } + else if (lookup < 200) { gain = std::lerp(samples[lookup - 1], samples[lookup], frac); } else { gain = samples[199]; } s[i] *= gain; diff --git a/plugins/Eq/EqCurve.cpp b/plugins/Eq/EqCurve.cpp index a0654054b..c07b98dd3 100644 --- a/plugins/Eq/EqCurve.cpp +++ b/plugins/Eq/EqCurve.cpp @@ -31,7 +31,6 @@ #include "embed.h" #include "Engine.h" #include "FontHelper.h" -#include "lmms_constants.h" #include "lmms_math.h" @@ -200,13 +199,14 @@ bool EqHandle::mousePressed() const float EqHandle::getPeakCurve( float x ) { + using namespace std::numbers; double freqZ = xPixelToFreq( EqHandle::x(), m_width ); - double w0 = numbers::tau * freqZ / Engine::audioEngine()->outputSampleRate(); + double w0 = 2 * pi * freqZ / Engine::audioEngine()->outputSampleRate(); double c = std::cos(w0); double s = std::sin(w0); double Q = getResonance(); double A = fastPow10f(yPixelToGain(EqHandle::y(), m_heigth, m_pixelsPerUnitHeight) / 40); - double alpha = s * std::sinh(std::log(2.0) / 2 * Q * w0 / std::sin(w0)); + double alpha = s * std::sinh(ln2 / 2 * Q * w0 / std::sin(w0)); //calc coefficents double b0 = 1 + alpha * A; @@ -237,7 +237,7 @@ float EqHandle::getPeakCurve( float x ) float EqHandle::getHighShelfCurve( float x ) { double freqZ = xPixelToFreq( EqHandle::x(), m_width ); - double w0 = numbers::tau * freqZ / Engine::audioEngine()->outputSampleRate(); + double w0 = 2 * std::numbers::pi * freqZ / Engine::audioEngine()->outputSampleRate(); double c = std::cos(w0); double s = std::sin(w0); double A = fastPow10f(yPixelToGain(EqHandle::y(), m_heigth, m_pixelsPerUnitHeight) * 0.025); @@ -272,7 +272,7 @@ float EqHandle::getHighShelfCurve( float x ) float EqHandle::getLowShelfCurve( float x ) { double freqZ = xPixelToFreq( EqHandle::x(), m_width ); - double w0 = numbers::tau * freqZ / Engine::audioEngine()->outputSampleRate(); + double w0 = 2 * std::numbers::pi * freqZ / Engine::audioEngine()->outputSampleRate(); double c = std::cos(w0); double s = std::sin(w0); double A = fastPow10f(yPixelToGain(EqHandle::y(), m_heigth, m_pixelsPerUnitHeight) / 40); @@ -307,7 +307,7 @@ float EqHandle::getLowShelfCurve( float x ) float EqHandle::getLowCutCurve( float x ) { double freqZ = xPixelToFreq( EqHandle::x(), m_width ); - double w0 = numbers::tau * freqZ / Engine::audioEngine()->outputSampleRate(); + double w0 = 2 * std::numbers::pi * freqZ / Engine::audioEngine()->outputSampleRate(); double c = std::cos(w0); double s = std::sin(w0); double resonance = getResonance(); @@ -349,7 +349,7 @@ float EqHandle::getLowCutCurve( float x ) float EqHandle::getHighCutCurve( float x ) { double freqZ = xPixelToFreq( EqHandle::x(), m_width ); - double w0 = numbers::tau * freqZ / Engine::audioEngine()->outputSampleRate(); + double w0 = 2 * std::numbers::pi * freqZ / Engine::audioEngine()->outputSampleRate(); double c = std::cos(w0); double s = std::sin(w0); double resonance = getResonance(); @@ -522,7 +522,7 @@ void EqHandle::setlp48() double EqHandle::calculateGain(const double freq, const double a1, const double a2, const double b0, const double b1, const double b2 ) { - const double w = std::sin(numbers::pi * freq / Engine::audioEngine()->outputSampleRate()); + const double w = std::sin(std::numbers::pi * freq / Engine::audioEngine()->outputSampleRate()); const double PHI = w * w * 4; auto bb = b0 + b1 + b2; diff --git a/plugins/Eq/EqFilter.h b/plugins/Eq/EqFilter.h index c5685dd88..a6e7d558a 100644 --- a/plugins/Eq/EqFilter.h +++ b/plugins/Eq/EqFilter.h @@ -25,13 +25,14 @@ #ifndef EQFILTER_H #define EQFILTER_H +#include + #include "BasicFilters.h" #include "lmms_math.h" namespace lmms { - /// /// \brief The EqFilter class. /// A wrapper for the StereoBiQuad class, giving it freq, res, and gain controls. @@ -185,7 +186,7 @@ public : { // calc intermediate - float w0 = numbers::tau_v * m_freq / m_sampleRate; + float w0 = 2 * std::numbers::pi_v * m_freq / m_sampleRate; float c = std::cos(w0); float s = std::sin(w0); float alpha = s / ( 2 * m_res ); @@ -228,7 +229,7 @@ public : { // calc intermediate - float w0 = numbers::tau_v * m_freq / m_sampleRate; + float w0 = 2 * std::numbers::pi_v * m_freq / m_sampleRate; float c = std::cos(w0); float s = std::sin(w0); float alpha = s / ( 2 * m_res ); @@ -268,12 +269,13 @@ public: void calcCoefficents() override { + using namespace std::numbers; // calc intermediate - float w0 = numbers::tau_v * m_freq / m_sampleRate; + float w0 = 2 * pi_v * m_freq / m_sampleRate; float c = std::cos(w0); float s = std::sin(w0); float A = fastPow10f(m_gain * 0.025); - float alpha = s * std::sinh(std::log(2.f) / 2 * m_bw * w0 / std::sin(w0)); + float alpha = s * std::sinh(ln2 / 2 * m_bw * w0 / std::sin(w0)); //calc coefficents float b0 = 1 + alpha * A; @@ -332,7 +334,7 @@ public : { // calc intermediate - float w0 = numbers::tau_v * m_freq / m_sampleRate; + float w0 = 2 * std::numbers::pi_v * m_freq / m_sampleRate; float c = std::cos(w0); float s = std::sin(w0); float A = fastPow10f(m_gain * 0.025); @@ -369,7 +371,7 @@ public : { // calc intermediate - float w0 = numbers::tau_v * m_freq / m_sampleRate; + float w0 = 2 * std::numbers::pi_v * m_freq / m_sampleRate; float c = std::cos(w0); float s = std::sin(w0); float A = fastPow10f(m_gain * 0.025); diff --git a/plugins/Eq/EqParameterWidget.cpp b/plugins/Eq/EqParameterWidget.cpp index ceccb669f..a7c75b70d 100644 --- a/plugins/Eq/EqParameterWidget.cpp +++ b/plugins/Eq/EqParameterWidget.cpp @@ -35,7 +35,6 @@ #include "AutomatableModel.h" #include "EqCurve.h" #include "EqParameterWidget.h" -#include "lmms_constants.h" namespace lmms::gui @@ -239,4 +238,4 @@ EqBand::EqBand() : } -} // namespace lmms::gui \ No newline at end of file +} // namespace lmms::gui diff --git a/plugins/Eq/EqSpectrumView.cpp b/plugins/Eq/EqSpectrumView.cpp index 7dc398bfb..5441df287 100644 --- a/plugins/Eq/EqSpectrumView.cpp +++ b/plugins/Eq/EqSpectrumView.cpp @@ -23,6 +23,7 @@ #include "EqSpectrumView.h" #include +#include #include #include @@ -31,7 +32,6 @@ #include "EqCurve.h" #include "GuiApplication.h" #include "MainWindow.h" -#include "lmms_constants.h" namespace lmms { @@ -43,6 +43,7 @@ EqAnalyser::EqAnalyser() : m_sampleRate ( 1 ), m_active ( true ) { + using namespace std::numbers; m_inProgress=false; m_specBuf = ( fftwf_complex * ) fftwf_malloc( ( FFT_BUFFER_SIZE + 1 ) * sizeof( fftwf_complex ) ); m_fftPlan = fftwf_plan_dft_r2c_1d( FFT_BUFFER_SIZE*2, m_buffer, m_specBuf, FFTW_MEASURE ); @@ -56,9 +57,9 @@ EqAnalyser::EqAnalyser() : for (auto i = std::size_t{0}; i < FFT_BUFFER_SIZE; i++) { - m_fftWindow[i] = (a0 - a1 * std::cos(2 * numbers::pi_v * i / ((float)FFT_BUFFER_SIZE - 1.0)) - + a2 * std::cos(4 * numbers::pi_v * i / ((float)FFT_BUFFER_SIZE - 1.0)) - - a3 * std::cos(6 * numbers::pi_v * i / ((float)FFT_BUFFER_SIZE - 1.0))); + m_fftWindow[i] = a0 - a1 * std::cos(2 * pi_v * i / static_cast(FFT_BUFFER_SIZE - 1.0)) + + a2 * std::cos(4 * pi_v * i / static_cast(FFT_BUFFER_SIZE - 1.0)) + - a3 * std::cos(6 * pi_v * i / static_cast(FFT_BUFFER_SIZE - 1.0)); } clear(); } diff --git a/plugins/Flanger/FlangerEffect.cpp b/plugins/Flanger/FlangerEffect.cpp index 9aa765ff4..2072156f5 100644 --- a/plugins/Flanger/FlangerEffect.cpp +++ b/plugins/Flanger/FlangerEffect.cpp @@ -23,6 +23,9 @@ */ #include "FlangerEffect.h" + +#include + #include "Engine.h" #include "MonoDelay.h" #include "QuadratureLfo.h" @@ -94,7 +97,7 @@ Effect::ProcessStatus FlangerEffect::processImpl(SampleFrame* buf, const fpp_t f float amplitude = m_flangerControls.m_lfoAmountModel.value() * Engine::audioEngine()->outputSampleRate(); bool invertFeedback = m_flangerControls.m_invertFeedbackModel.value(); m_lfo->setFrequency( 1.0/m_flangerControls.m_lfoFrequencyModel.value() ); - m_lfo->setOffset(m_flangerControls.m_lfoPhaseModel.value() / 180 * numbers::pi); + m_lfo->setOffset(m_flangerControls.m_lfoPhaseModel.value() / 180 * std::numbers::pi); m_lDelay->setFeedback( m_flangerControls.m_feedbackModel.value() ); m_rDelay->setFeedback( m_flangerControls.m_feedbackModel.value() ); auto dryS = std::array{}; @@ -103,8 +106,8 @@ Effect::ProcessStatus FlangerEffect::processImpl(SampleFrame* buf, const fpp_t f float leftLfo; float rightLfo; - buf[f][0] += (fastRandf(2.0f) - 1.0f) * noise; - buf[f][1] += (fastRandf(2.0f) - 1.0f) * noise; + buf[f][0] += fastRand(-1.f, +1.f) * noise; + buf[f][1] += fastRand(-1.f, +1.f) * noise; dryS[0] = buf[f][0]; dryS[1] = buf[f][1]; m_lfo->tick(&leftLfo, &rightLfo); diff --git a/plugins/GranularPitchShifter/GranularPitchShifterEffect.cpp b/plugins/GranularPitchShifter/GranularPitchShifterEffect.cpp index 2a48f0e3c..f59030105 100755 --- a/plugins/GranularPitchShifter/GranularPitchShifterEffect.cpp +++ b/plugins/GranularPitchShifter/GranularPitchShifterEffect.cpp @@ -26,6 +26,7 @@ #include #include "embed.h" +#include "lmms_math.h" #include "plugin_export.h" @@ -155,18 +156,15 @@ Effect::ProcessStatus GranularPitchShifterEffect::processImpl(SampleFrame* buf, if (++m_timeSinceLastGrain >= m_nextWaitRandomization * waitMult) { m_timeSinceLastGrain = 0; - double randThing = fast_rand() * static_cast(FAST_RAND_RATIO) * 2. - 1.; + auto randThing = fastRand(-1.0, +1.0); m_nextWaitRandomization = std::exp2(randThing * twitch); double grainSpeed = 1. / std::exp2(randThing * jitter); std::array sprayResult = {0, 0}; if (spray > 0) { - sprayResult[0] = fast_rand() * FAST_RAND_RATIO * spray * m_sampleRate; - sprayResult[1] = linearInterpolate( - sprayResult[0], - fast_rand() * FAST_RAND_RATIO * spray * m_sampleRate, - spraySpread); + sprayResult[0] = fastRand(spray * m_sampleRate); + sprayResult[1] = std::lerp(sprayResult[0], fastRand(spray * m_sampleRate), spraySpread); } std::array readPoint; @@ -271,7 +269,7 @@ void GranularPitchShifterEffect::changeSampleRate() m_grainCount = 0; m_grains.reserve(8);// arbitrary - m_dcCoeff = std::exp(-numbers::tau_v * DcRemovalHz / m_sampleRate); + m_dcCoeff = std::exp(-2 * std::numbers::pi_v * DcRemovalHz / m_sampleRate); const double pitch = m_granularpitchshifterControls.m_pitchModel.value() * (1. / 12.); const double pitchSpread = m_granularpitchshifterControls.m_pitchSpreadModel.value() * (1. / 24.); diff --git a/plugins/GranularPitchShifter/GranularPitchShifterEffect.h b/plugins/GranularPitchShifter/GranularPitchShifterEffect.h index d844b852f..4b4eb55b2 100755 --- a/plugins/GranularPitchShifter/GranularPitchShifterEffect.h +++ b/plugins/GranularPitchShifter/GranularPitchShifterEffect.h @@ -25,6 +25,8 @@ #ifndef LMMS_GRANULAR_PITCH_SHIFTER_EFFECT_H #define LMMS_GRANULAR_PITCH_SHIFTER_EFFECT_H +#include + #include "Effect.h" #include "GranularPitchShifterControls.h" @@ -118,12 +120,13 @@ private: void setCoefs(float sampleRate, float cutoff) { - const float g = std::tan(numbers::pi_v * cutoff / sampleRate); - const float ginv = g / (1.f + g * (g + numbers::sqrt2_v)); - m_g1 = ginv; - m_g2 = 2.f * (g + numbers::sqrt2_v) * ginv; - m_g3 = g * ginv; - m_g4 = 2.f * ginv; + using namespace std::numbers; + const float g = std::tan(pi_v * cutoff / sampleRate); + const float ginv = g / (1.f + g * (g + sqrt2_v)); + m_g1 = ginv; + m_g2 = 2 * (g + sqrt2_v) * ginv; + m_g3 = g * ginv; + m_g4 = 2 * ginv; } float process(float input) diff --git a/plugins/Kicker/KickerOsc.h b/plugins/Kicker/KickerOsc.h index adcceaefe..6cac39134 100644 --- a/plugins/Kicker/KickerOsc.h +++ b/plugins/Kicker/KickerOsc.h @@ -26,11 +26,12 @@ #ifndef KICKER_OSC_H #define KICKER_OSC_H +#include + #include "DspEffectLibrary.h" #include "Oscillator.h" #include "lmms_math.h" -#include "interpolation.h" namespace lmms { @@ -72,7 +73,7 @@ public: // update distortion envelope if necessary if( m_hasDistEnv && m_counter < m_length ) { - float thres = linearInterpolate( m_distStart, m_distEnd, m_counter / m_length ); + float thres = std::lerp(m_distStart, m_distEnd, m_counter / m_length); m_FX.leftFX().setThreshold( thres ); m_FX.rightFX().setThreshold( thres ); } diff --git a/plugins/LOMM/LOMM.cpp b/plugins/LOMM/LOMM.cpp index 32c77e3db..aafbfcf41 100644 --- a/plugins/LOMM/LOMM.cpp +++ b/plugins/LOMM/LOMM.cpp @@ -24,6 +24,7 @@ #include "LOMM.h" +#include "lmms_math.h" #include "embed.h" #include "plugin_export.h" @@ -312,11 +313,11 @@ Effect::ProcessStatus LOMMEffect::processImpl(SampleFrame* buf, const fpp_t fram { if (downward * depth <= 1) { - aboveGain = linearInterpolate(yDbfs, aboveGain, downward * depth); + aboveGain = std::lerp(yDbfs, aboveGain, downward * depth); } else { - aboveGain = linearInterpolate(aboveGain, aThresh[j], downward * depth - 1); + aboveGain = std::lerp(aboveGain, aThresh[j], downward * depth - 1); } } @@ -338,11 +339,11 @@ Effect::ProcessStatus LOMMEffect::processImpl(SampleFrame* buf, const fpp_t fram { if (upward * depth <= 1) { - belowGain = linearInterpolate(yDbfs, belowGain, upward * depth); + belowGain = std::lerp(yDbfs, belowGain, upward * depth); } else { - belowGain = linearInterpolate(belowGain, bThresh[j], upward * depth - 1); + belowGain = std::lerp(belowGain, bThresh[j], upward * depth - 1); } } @@ -396,12 +397,12 @@ Effect::ProcessStatus LOMMEffect::processImpl(SampleFrame* buf, const fpp_t fram bands[j][i] *= outBandVol[j]; - bands[j][i] = linearInterpolate(bandsDry[j][i], bands[j][i], mix); + bands[j][i] = std::lerp(bandsDry[j][i], bands[j][i], mix); } s[i] = bands[0][i] + bands[1][i] + bands[2][i]; - s[i] *= linearInterpolate(1.f, outVol, mix * (depthScaling ? depth : 1)); + s[i] *= std::lerp(1.f, outVol, mix * (depthScaling ? depth : 1)); } // Convert mid/side back to left/right. diff --git a/plugins/LOMM/LOMM.h b/plugins/LOMM/LOMM.h index 36aa12dea..c0d2155c3 100644 --- a/plugins/LOMM/LOMM.h +++ b/plugins/LOMM/LOMM.h @@ -30,7 +30,6 @@ #include "Effect.h" #include "BasicFilters.h" -#include "lmms_math.h" namespace lmms { diff --git a/plugins/Monstro/Monstro.cpp b/plugins/Monstro/Monstro.cpp index 367ef7f71..57d423bca 100644 --- a/plugins/Monstro/Monstro.cpp +++ b/plugins/Monstro/Monstro.cpp @@ -22,11 +22,10 @@ * */ +#include "Monstro.h" #include -#include "Monstro.h" - #include "ComboBox.h" #include "Engine.h" #include "InstrumentTrack.h" @@ -34,7 +33,6 @@ #include "interpolation.h" #include "embed.h" - #include "plugin_export.h" namespace lmms @@ -625,8 +623,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, SampleFrame* _buf ) sub = qBound( 0.0f, sub, 1.0f ); } - sample_t O3L = linearInterpolate( O3AL, O3BL, sub ); - sample_t O3R = linearInterpolate( O3AR, O3BR, sub ); + sample_t O3L = std::lerp(O3AL, O3BL, sub); + sample_t O3R = std::lerp(O3AR, O3BR, sub); // modulate volume O3L *= o3lv; @@ -665,8 +663,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, SampleFrame* _buf ) sample_t L = O1L + O3L + ( omod == MOD_MIX ? O2L : 0.0f ); sample_t R = O1R + O3R + ( omod == MOD_MIX ? O2R : 0.0f ); - _buf[f][0] = linearInterpolate( L, m_l_last, m_parent->m_integrator ); - _buf[f][1] = linearInterpolate( R, m_r_last, m_parent->m_integrator ); + _buf[f][0] = std::lerp(L, m_l_last, m_parent->m_integrator); + _buf[f][1] = std::lerp(R, m_r_last, m_parent->m_integrator); m_l_last = L; m_r_last = R; diff --git a/plugins/MultitapEcho/MultitapEcho.cpp b/plugins/MultitapEcho/MultitapEcho.cpp index 96a828dcc..3d92e5ae8 100644 --- a/plugins/MultitapEcho/MultitapEcho.cpp +++ b/plugins/MultitapEcho/MultitapEcho.cpp @@ -26,6 +26,7 @@ #include "MultitapEcho.h" #include "embed.h" #include "lmms_basics.h" +#include "lmms_math.h" #include "plugin_export.h" namespace lmms diff --git a/plugins/MultitapEcho/MultitapEcho.h b/plugins/MultitapEcho/MultitapEcho.h index 63d6ac5d6..a7ed0c2c4 100644 --- a/plugins/MultitapEcho/MultitapEcho.h +++ b/plugins/MultitapEcho/MultitapEcho.h @@ -54,7 +54,7 @@ private: inline void setFilterFreq( float fc, StereoOnePole & f ) { - const float b1 = std::exp(-numbers::tau_v * fc); + const float b1 = std::exp(-2 * std::numbers::pi_v * fc); f.setCoeffs( 1.0f - b1, b1 ); } diff --git a/plugins/Nes/Nes.cpp b/plugins/Nes/Nes.cpp index d91130ef1..9fbb46db1 100644 --- a/plugins/Nes/Nes.cpp +++ b/plugins/Nes/Nes.cpp @@ -29,7 +29,6 @@ #include "AudioEngine.h" #include "Engine.h" #include "InstrumentTrack.h" -#include "interpolation.h" #include "Knob.h" #include "Oscillator.h" @@ -398,7 +397,7 @@ void NesObject::renderOutput( SampleFrame* buf, fpp_t frames ) pin1 = pin1 * 2.0f - 1.0f; // simple first order iir filter, to simulate the frequency response falloff in nes analog audio output - pin1 = linearInterpolate( pin1, m_12Last, m_nsf ); + pin1 = std::lerp(pin1, m_12Last, m_nsf); m_12Last = pin1; // compensate DC offset @@ -416,7 +415,7 @@ void NesObject::renderOutput( SampleFrame* buf, fpp_t frames ) pin2 = pin2 * 2.0f - 1.0f; // simple first order iir filter, to simulate the frequency response falloff in nes analog audio output - pin2 = linearInterpolate( pin2, m_34Last, m_nsf ); + pin2 = std::lerp(pin2, m_34Last, m_nsf); m_34Last = pin2; // compensate DC offset diff --git a/plugins/SlicerT/SlicerT.cpp b/plugins/SlicerT/SlicerT.cpp index e510e8cb9..ef533cd1a 100644 --- a/plugins/SlicerT/SlicerT.cpp +++ b/plugins/SlicerT/SlicerT.cpp @@ -34,7 +34,7 @@ #include "SampleLoader.h" #include "Song.h" #include "embed.h" -#include "lmms_constants.h" +#include "interpolation.h" #include "plugin_export.h" namespace lmms { @@ -183,7 +183,7 @@ void SlicerT::findSlices() for (auto i = std::size_t{0}; i < singleChannel.size(); i++) { singleChannel[i] /= maxMag; - if (sign(lastValue) != sign(singleChannel[i])) + if ((lastValue >= 0) != (singleChannel[i] >= 0)) { zeroCrossings.push_back(i); lastValue = singleChannel[i]; diff --git a/plugins/Stk/Mallets/Mallets.cpp b/plugins/Stk/Mallets/Mallets.cpp index 00ddbf422..fecb15a76 100644 --- a/plugins/Stk/Mallets/Mallets.cpp +++ b/plugins/Stk/Mallets/Mallets.cpp @@ -41,6 +41,7 @@ #include "InstrumentTrack.h" #include "embed.h" +#include "lmms_math.h" #include "plugin_export.h" namespace lmms @@ -305,26 +306,26 @@ void MalletsInstrument::playNote( NotePlayHandle * _n, if (p < 9) { - hardness += random * (static_cast(fast_rand() % 128) - 64.0); + hardness += random * fastRand(-64.f, +64.f); hardness = std::clamp(hardness, 0.0f, 128.0f); - position += random * (static_cast(fast_rand() % 64) - 32.0); + position += random * fastRand(-32.f, +32.f); position = std::clamp(position, 0.0f, 64.0f); } else if (p == 9) { - modulator += random * (static_cast(fast_rand() % 128) - 64.0); + modulator += random * fastRand(-64.f, +64.f); modulator = std::clamp(modulator, 0.0f, 128.0f); - crossfade += random * (static_cast(fast_rand() % 128) - 64.0); + crossfade += random * fastRand(-64.f, +64.f); crossfade = std::clamp(crossfade, 0.0f, 128.0f); } else { - pressure += random * (static_cast(fast_rand() % 128) - 64.0); + pressure += random * fastRand(-64.f, +64.f); pressure = std::clamp(pressure, 0.0f, 128.0f); - speed += random * (static_cast(fast_rand() % 128) - 64.0); + speed += random * fastRand(-64.f, +64.f); speed = std::clamp(speed, 0.0f, 128.0f); } diff --git a/plugins/Watsyn/Watsyn.cpp b/plugins/Watsyn/Watsyn.cpp index 6ce1beced..272ba5d46 100644 --- a/plugins/Watsyn/Watsyn.cpp +++ b/plugins/Watsyn/Watsyn.cpp @@ -32,7 +32,6 @@ #include "PixmapButton.h" #include "Song.h" #include "lmms_math.h" -#include "interpolation.h" #include "embed.h" #include "plugin_export.h" @@ -122,12 +121,16 @@ void WatsynObject::renderOutput( fpp_t _frames ) ///////////// A-series ///////////////// // A2 - sample_t A2_L = linearInterpolate( m_A2wave[ static_cast( m_lphase[A2_OSC] ) ], - m_A2wave[ static_cast( m_lphase[A2_OSC] + 1 ) % WAVELEN ], - fraction( m_lphase[A2_OSC] ) ) * m_parent->m_lvol[A2_OSC]; - sample_t A2_R = linearInterpolate( m_A2wave[ static_cast( m_rphase[A2_OSC] ) ], - m_A2wave[ static_cast( m_rphase[A2_OSC] + 1 ) % WAVELEN ], - fraction( m_rphase[A2_OSC] ) ) * m_parent->m_rvol[A2_OSC]; + sample_t A2_L = m_parent->m_lvol[A2_OSC] * std::lerp( + m_A2wave[static_cast(m_lphase[A2_OSC])], + m_A2wave[static_cast(m_lphase[A2_OSC] + 1) % WAVELEN], + fraction(m_lphase[A2_OSC]) + ); + sample_t A2_R = m_parent->m_rvol[A2_OSC] * std::lerp( + m_A2wave[static_cast(m_rphase[A2_OSC])], + m_A2wave[static_cast(m_rphase[A2_OSC] + 1) % WAVELEN], + fraction(m_rphase[A2_OSC]) + ); // if phase mod, add to phases if( m_amod == MOD_PM ) @@ -138,22 +141,30 @@ void WatsynObject::renderOutput( fpp_t _frames ) if( A1_rphase < 0 ) A1_rphase += WAVELEN; } // A1 - sample_t A1_L = linearInterpolate( m_A1wave[ static_cast( A1_lphase ) ], - m_A1wave[ static_cast( A1_lphase + 1 ) % WAVELEN ], - fraction( A1_lphase ) ) * m_parent->m_lvol[A1_OSC]; - sample_t A1_R = linearInterpolate( m_A1wave[ static_cast( A1_rphase ) ], - m_A1wave[ static_cast( A1_rphase + 1 ) % WAVELEN ], - fraction( A1_rphase ) ) * m_parent->m_rvol[A1_OSC]; + sample_t A1_L = m_parent->m_lvol[A1_OSC] * std::lerp( + m_A1wave[static_cast(A1_lphase)], + m_A1wave[static_cast(A1_lphase + 1) % WAVELEN], + fraction(A1_lphase) + ); + sample_t A1_R = m_parent->m_rvol[A1_OSC] * std::lerp( + m_A1wave[static_cast(A1_rphase)], + m_A1wave[static_cast(A1_rphase + 1) % WAVELEN], + fraction(A1_rphase) + ); ///////////// B-series ///////////////// // B2 - sample_t B2_L = linearInterpolate( m_B2wave[ static_cast( m_lphase[B2_OSC] ) ], - m_B2wave[ static_cast( m_lphase[B2_OSC] + 1 ) % WAVELEN ], - fraction( m_lphase[B2_OSC] ) ) * m_parent->m_lvol[B2_OSC]; - sample_t B2_R = linearInterpolate( m_B2wave[ static_cast( m_rphase[B2_OSC] ) ], - m_B2wave[ static_cast( m_rphase[B2_OSC] + 1 ) % WAVELEN ], - fraction( m_rphase[B2_OSC] ) ) * m_parent->m_rvol[B2_OSC]; + sample_t B2_L = m_parent->m_lvol[B2_OSC] * std::lerp( + m_B2wave[static_cast(m_lphase[B2_OSC])], + m_B2wave[static_cast(m_lphase[B2_OSC] + 1) % WAVELEN], + fraction(m_lphase[B2_OSC]) + ); + sample_t B2_R = m_parent->m_rvol[B2_OSC] * std::lerp( + m_B2wave[static_cast(m_rphase[B2_OSC])], + m_B2wave[static_cast(m_rphase[B2_OSC] + 1) % WAVELEN], + fraction(m_rphase[B2_OSC]) + ); // if crosstalk active, add a1 const float xt = m_parent->m_xtalk.value(); @@ -172,12 +183,16 @@ void WatsynObject::renderOutput( fpp_t _frames ) if( B1_rphase < 0 ) B1_rphase += WAVELEN; } // B1 - sample_t B1_L = linearInterpolate( m_B1wave[ static_cast( B1_lphase ) % WAVELEN ], - m_B1wave[ static_cast( B1_lphase + 1 ) % WAVELEN ], - fraction( B1_lphase ) ) * m_parent->m_lvol[B1_OSC]; - sample_t B1_R = linearInterpolate( m_B1wave[ static_cast( B1_rphase ) % WAVELEN ], - m_B1wave[ static_cast( B1_rphase + 1 ) % WAVELEN ], - fraction( B1_rphase ) ) * m_parent->m_rvol[B1_OSC]; + sample_t B1_L = m_parent->m_lvol[B1_OSC] * std::lerp( + m_B1wave[static_cast(B1_lphase) % WAVELEN], + m_B1wave[static_cast(B1_lphase + 1) % WAVELEN], + fraction(B1_lphase) + ); + sample_t B1_R = m_parent->m_rvol[B1_OSC] * std::lerp( + m_B1wave[static_cast(B1_rphase) % WAVELEN], + m_B1wave[static_cast(B1_rphase + 1) % WAVELEN], + fraction(B1_rphase) + ); // A-series modulation) diff --git a/plugins/WaveShaper/WaveShaper.cpp b/plugins/WaveShaper/WaveShaper.cpp index f21a2dff7..4915e40af 100644 --- a/plugins/WaveShaper/WaveShaper.cpp +++ b/plugins/WaveShaper/WaveShaper.cpp @@ -27,7 +27,6 @@ #include "WaveShaper.h" #include "lmms_math.h" #include "embed.h" -#include "interpolation.h" #include "plugin_export.h" @@ -116,9 +115,7 @@ Effect::ProcessStatus WaveShaperEffect::processImpl(SampleFrame* buf, const fpp_ } else if( lookup < 200 ) { - s[i] = linearInterpolate( samples[ lookup - 1 ], - samples[ lookup ], frac ) - * posneg; + s[i] = std::lerp(samples[lookup - 1], samples[lookup], frac) * posneg; } else { diff --git a/plugins/Xpressive/ExprSynth.cpp b/plugins/Xpressive/ExprSynth.cpp index 715bf453c..347bb6d80 100644 --- a/plugins/Xpressive/ExprSynth.cpp +++ b/plugins/Xpressive/ExprSynth.cpp @@ -29,9 +29,8 @@ #include #include #include +#include - -#include "interpolation.h" #include "lmms_math.h" #include "NotePlayHandle.h" #include "SampleFrame.h" @@ -220,7 +219,7 @@ struct WaveValueFunctionInterpolate : public exprtk::ifunction const T x = positiveFraction(index) * m_size; const int ix = (int)x; const float xfrc = fraction(x); - return linearInterpolate(m_vec[ix], m_vec[(ix + 1) % m_size], xfrc); + return std::lerp(m_vec[ix], m_vec[(ix + 1) % m_size], xfrc); } const T *m_vec; const std::size_t m_size; @@ -413,7 +412,7 @@ struct sin_wave static inline float process(float x) { x = positiveFraction(x); - return std::sin(x * numbers::tau_v); + return std::sin(x * 2 * std::numbers::pi_v); } }; static freefunc1 sin_wave_func; @@ -535,7 +534,7 @@ ExprFront::ExprFront(const char * expr, int last_func_samples) m_data->m_expression_string = expr; m_data->m_symbol_table.add_pi(); - m_data->m_symbol_table.add_constant("e", numbers::e_v); + m_data->m_symbol_table.add_constant("e", std::numbers::e_v); m_data->m_symbol_table.add_constant("seed", SimpleRandom::generator() & max_float_integer_mask); diff --git a/plugins/Xpressive/Xpressive.cpp b/plugins/Xpressive/Xpressive.cpp index 6e3a91343..37dcb16fa 100644 --- a/plugins/Xpressive/Xpressive.cpp +++ b/plugins/Xpressive/Xpressive.cpp @@ -40,8 +40,6 @@ #include "Song.h" #include "base64.h" -#include "lmms_constants.h" - #include "embed.h" #include "ExprSynth.h" @@ -252,7 +250,8 @@ void Xpressive::smooth(float smoothness,const graphModel * in,graphModel * out) const int guass_size = (int)(smoothness * 5) | 1; const int guass_center = guass_size/2; const float delta = smoothness; - const float a = 1.0f / (std::sqrt(numbers::tau_v) * delta); + constexpr float inv_sqrt2pi = std::numbers::inv_sqrtpi_v / std::numbers::sqrt2_v; + const float a = inv_sqrt2pi / delta; auto const guassian = new float[guass_size]; float sum = 0.0f; float temp = 0.0f; diff --git a/src/core/BandLimitedWave.cpp b/src/core/BandLimitedWave.cpp index 2eb6d5eb0..50b386786 100644 --- a/src/core/BandLimitedWave.cpp +++ b/src/core/BandLimitedWave.cpp @@ -64,6 +64,7 @@ QDataStream& operator>> ( QDataStream &in, WaveMipMap &waveMipMap ) void BandLimitedWave::generateWaves() { + using namespace std::numbers; // don't generate if they already exist if( s_wavesGenerated ) return; @@ -103,8 +104,8 @@ void BandLimitedWave::generateWaves() { hlen = static_cast( len ) / static_cast( harm ); const double amp = -1.0 / static_cast( harm ); - //const double a2 = std::cos(om * harm * numbers::tau_v); - s += amp * /*a2 **/ std::sin(static_cast(ph * harm) / static_cast(len) * numbers::tau_v); + //const double a2 = std::cos(om * harm * 2 * pi_v); + s += amp * /*a2 **/ std::sin(static_cast(ph * harm) / static_cast(len) * 2 * pi_v); harm++; } while( hlen > 2.0 ); s_waveforms[static_cast(BandLimitedWave::Waveform::BLSaw)].setSampleAt( i, ph, s ); @@ -145,8 +146,8 @@ void BandLimitedWave::generateWaves() { hlen = static_cast( len ) / static_cast( harm ); const double amp = 1.0 / static_cast( harm ); - //const double a2 = std::cos(om * harm * numbers::tau_v); - s += amp * /*a2 **/ std::sin(static_cast(ph * harm) / static_cast(len) * numbers::tau_v); + //const double a2 = std::cos(om * harm * 2 * pi_v); + s += amp * /*a2 **/ std::sin(static_cast(ph * harm) / static_cast(len) * 2 * pi_v); harm += 2; } while( hlen > 2.0 ); s_waveforms[static_cast(BandLimitedWave::Waveform::BLSquare)].setSampleAt( i, ph, s ); @@ -186,9 +187,9 @@ void BandLimitedWave::generateWaves() { hlen = static_cast( len ) / static_cast( harm ); const double amp = 1.0 / static_cast( harm * harm ); - //const double a2 = std::cos(om * harm * numbers::tau_v); + //const double a2 = std::cos(om * harm * 2 * pi_v); s += amp * /*a2 **/ std::sin((static_cast(ph * harm) / static_cast(len) + - ((harm + 1) % 4 == 0 ? 0.5 : 0.0)) * numbers::tau_v); + ((harm + 1) % 4 == 0 ? 0.5 : 0.0)) * 2 * pi_v); harm += 2; } while( hlen > 2.0 ); s_waveforms[static_cast(BandLimitedWave::Waveform::BLTriangle)].setSampleAt( i, ph, s ); diff --git a/src/core/DrumSynth.cpp b/src/core/DrumSynth.cpp index 85c2a1d17..e54476a19 100644 --- a/src/core/DrumSynth.cpp +++ b/src/core/DrumSynth.cpp @@ -176,8 +176,7 @@ float DrumSynth::waveform(float ph, int form) // sine^2 if (form == 1) { return std::abs(2.f * std::sin(0.5f * ph)) - 1.f; } // sawtooth with range [0, 1], used to generate triangle, sawtooth, and square - auto ph_tau = ph / numbers::tau_v; - auto saw01 = ph_tau - std::floor(ph_tau); + auto saw01 = absFraction(ph / (2 * std::numbers::pi_v)); // triangle if (form == 2) { return 1.f - 4.f * std::abs(saw01 - 0.5f); } // sawtooth @@ -304,6 +303,7 @@ float DrumSynth::GetPrivateProfileFloat(const char* sec, const char* key, float int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sample_rate_t Fs) { + using namespace std::numbers; // input file char sec[32]; char ver[32]; @@ -429,12 +429,12 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa sliLev[0] = GetPrivateProfileInt(sec, "Level", 128, dsfile); TL = static_cast(sliLev[0] * sliLev[0]) * mem_t; GetEnv(1, sec, "Envelope", dsfile); - F1 = MasterTune * numbers::tau_v * GetPrivateProfileFloat(sec, "F1", 200.0, dsfile) / Fs; + F1 = MasterTune * 2 * pi_v * GetPrivateProfileFloat(sec, "F1", 200.0, dsfile) / Fs; if (std::abs(F1) < 0.001f) { F1 = 0.001f; // to prevent overtone ratio div0 } - F2 = MasterTune * numbers::tau_v * GetPrivateProfileFloat(sec, "F2", 120.0, dsfile) / Fs; + F2 = MasterTune * 2 * pi_v * GetPrivateProfileFloat(sec, "F2", 120.0, dsfile) / Fs; TDroopRate = GetPrivateProfileFloat(sec, "Droop", 0.f, dsfile); if (TDroopRate > 0.f) { @@ -460,8 +460,8 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa GetEnv(3, sec, "Envelope1", dsfile); GetEnv(4, sec, "Envelope2", dsfile); OMode = GetPrivateProfileInt(sec, "Method", 2, dsfile); - OF1 = MasterTune * numbers::tau_v * GetPrivateProfileFloat(sec, "F1", 200.0, dsfile) / Fs; - OF2 = MasterTune * numbers::tau_v * GetPrivateProfileFloat(sec, "F2", 120.0, dsfile) / Fs; + OF1 = MasterTune * 2 * pi_v * GetPrivateProfileFloat(sec, "F1", 200.0, dsfile) / Fs; + OF2 = MasterTune * 2 * pi_v * GetPrivateProfileFloat(sec, "F2", 120.0, dsfile) / Fs; OW1 = GetPrivateProfileInt(sec, "Wave1", 0, dsfile); OW2 = GetPrivateProfileInt(sec, "Wave2", 0, dsfile); OBal2 = static_cast(GetPrivateProfileInt(sec, "Param", 50, dsfile)); @@ -489,8 +489,8 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa OcQ = OcA * OcA; OcF = (1.8f - 0.7f * OcQ) * 0.92f; // multiply by env 2 OcA *= 1.0f + 4.0f * OBal1; // level is a compromise! - Ocf1 = numbers::tau_v / OF1; - Ocf2 = numbers::tau_v / OF2; + Ocf1 = 2 * pi_v / OF1; + Ocf2 = 2 * pi_v / OF2; for (i = 0; i < 6; i++) { Oc[i][0] = Oc[i][1] = Ocf1 + (Ocf2 - Ocf1) * 0.2f * static_cast(i); @@ -502,8 +502,8 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa BON = chkOn[3]; sliLev[3] = GetPrivateProfileInt(sec, "Level", 128, dsfile); BL = static_cast(sliLev[3] * sliLev[3]) * mem_b; - BF = MasterTune * numbers::tau_v * GetPrivateProfileFloat(sec, "F", 1000.0, dsfile) / Fs; - BPhi = numbers::tau_v / 8.f; + BF = MasterTune * 2 * pi_v * GetPrivateProfileFloat(sec, "F", 1000.0, dsfile) / Fs; + BPhi = pi_v / 4.f; GetEnv(5, sec, "Envelope", dsfile); BFStep = GetPrivateProfileInt(sec, "dF", 50, dsfile); BQ = static_cast(BFStep); @@ -515,8 +515,8 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa BON2 = chkOn[4]; sliLev[4] = GetPrivateProfileInt(sec, "Level", 128, dsfile); BL2 = static_cast(sliLev[4] * sliLev[4]) * mem_b; - BF2 = MasterTune * numbers::tau_v * GetPrivateProfileFloat(sec, "F", 1000.0, dsfile) / Fs; - BPhi2 = numbers::tau_v / 8.f; + BF2 = MasterTune * 2 * pi_v * GetPrivateProfileFloat(sec, "F", 1000.0, dsfile) / Fs; + BPhi2 = pi_v / 4.f; GetEnv(6, sec, "Envelope", dsfile); BFStep2 = GetPrivateProfileInt(sec, "dF", 50, dsfile); BQ2 = static_cast(BFStep2); @@ -662,7 +662,7 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa UpdateEnv(1, t); } Tphi = Tphi + phi[totmp]; - DF[totmp] += TL * envData[1][ENV] * std::sin(std::fmod(Tphi, numbers::tau_v)); // overflow? + DF[totmp] += TL * envData[1][ENV] * std::sin(Tphi); // overflow? } if (t >= envData[1][MAX]) { @@ -695,7 +695,7 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa } BPhi = BPhi + BF + BQ * BdF; botmp = t - tpos; - DF[botmp] = DF[botmp] + std::cos(std::fmod(BPhi, numbers::tau_v)) * envData[5][ENV] * BL; + DF[botmp] = DF[botmp] + std::cos(BPhi) * envData[5][ENV] * BL; } if (t >= envData[5][MAX]) { @@ -721,7 +721,7 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa } BPhi2 = BPhi2 + BF2 + BQ2 * BdF2; botmp = t - tpos; - DF[botmp] = DF[botmp] + std::cos(std::fmod(BPhi2, numbers::tau_v)) * envData[6][ENV] * BL2; + DF[botmp] = DF[botmp] + std::cos(BPhi2) * envData[6][ENV] * BL2; } if (t >= envData[6][MAX]) { diff --git a/src/core/Effect.cpp b/src/core/Effect.cpp index 1fb0b71b5..83df28b24 100644 --- a/src/core/Effect.cpp +++ b/src/core/Effect.cpp @@ -32,7 +32,7 @@ #include "ConfigManager.h" #include "SampleFrame.h" -#include "lmms_constants.h" +#include "lmms_math.h" namespace lmms { @@ -190,7 +190,7 @@ void Effect::checkGate(double outSum) // Check whether we need to continue processing input. Restart the // counter if the threshold has been exceeded. - if (outSum - gate() <= F_EPSILON) + if (approximatelyEqual(outSum, gate())) { incrementBufferCount(); if( bufferCount() > timeout() ) diff --git a/src/core/Instrument.cpp b/src/core/Instrument.cpp index fca3549f1..cae16dee8 100644 --- a/src/core/Instrument.cpp +++ b/src/core/Instrument.cpp @@ -25,12 +25,11 @@ #include "Instrument.h" #include +#include #include "DummyInstrument.h" #include "InstrumentTrack.h" #include "lmms_basics.h" -#include "lmms_constants.h" - namespace lmms { @@ -152,7 +151,7 @@ void Instrument::applyFadeIn(SampleFrame* buf, NotePlayHandle * n) { for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch) { - buf[offset + f][ch] *= 0.5 - 0.5 * std::cos(numbers::pi_v * (float) f / (float) n->m_fadeInLength); + buf[offset + f][ch] *= 0.5 - 0.5 * std::cos(std::numbers::pi_v * static_cast(f) / static_cast(n->m_fadeInLength)); } } } @@ -168,7 +167,7 @@ void Instrument::applyFadeIn(SampleFrame* buf, NotePlayHandle * n) for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch) { float currentLength = n->m_fadeInLength * (1.0f - (float) f / frames) + new_length * ((float) f / frames); - buf[f][ch] *= 0.5 - 0.5 * std::cos(numbers::pi_v * (float) (total + f) / currentLength); + buf[f][ch] *= 0.5 - 0.5 * std::cos(std::numbers::pi_v * static_cast(total + f) / currentLength); if (total + f >= currentLength) { n->m_fadeInLength = currentLength; diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index e2aa02ddc..326e63eaf 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -26,12 +26,12 @@ #include "NotePlayHandle.h" #include "AudioEngine.h" -#include "BasicFilters.h" #include "DetuningHelper.h" #include "InstrumentSoundShaping.h" #include "InstrumentTrack.h" #include "Instrument.h" #include "Song.h" +#include "lmms_math.h" namespace lmms { diff --git a/src/core/Oscillator.cpp b/src/core/Oscillator.cpp index 82d6dfe81..5b48ddf3e 100644 --- a/src/core/Oscillator.cpp +++ b/src/core/Oscillator.cpp @@ -29,6 +29,7 @@ #if !defined(__MINGW32__) && !defined(__MINGW64__) #include #endif +#include #include "BufferManager.h" #include "Engine.h" @@ -118,6 +119,7 @@ void Oscillator::update(SampleFrame* ab, const fpp_t frames, const ch_cnt_t chnl void Oscillator::generateSawWaveTable(int bands, sample_t* table, int firstBand) { + using namespace std::numbers; // sawtooth wave contain both even and odd harmonics // hence sinewaves are added for all bands // https://en.wikipedia.org/wiki/Sawtooth_wave @@ -127,7 +129,7 @@ void Oscillator::generateSawWaveTable(int bands, sample_t* table, int firstBand) const float imod = (i - OscillatorConstants::WAVETABLE_LENGTH / 2.f) / OscillatorConstants::WAVETABLE_LENGTH; for (int n = firstBand; n <= bands; n++) { - table[i] += (n % 2 ? 1.0f : -1.0f) / n * std::sin(numbers::tau_v * n * imod) / numbers::pi_half_v; + table[i] += (n % 2 ? 1.0f : -1.0f) / n * std::sin(2 * pi_v * n * imod) / (pi_v * 0.5f); } } } @@ -135,6 +137,8 @@ void Oscillator::generateSawWaveTable(int bands, sample_t* table, int firstBand) void Oscillator::generateTriangleWaveTable(int bands, sample_t* table, int firstBand) { + using namespace std::numbers; + constexpr float pi_sqr = pi_v * pi_v; // triangle waves contain only odd harmonics // hence sinewaves are added for alternate bands // https://en.wikipedia.org/wiki/Triangle_wave @@ -142,8 +146,8 @@ void Oscillator::generateTriangleWaveTable(int bands, sample_t* table, int first { for (int n = firstBand | 1; n <= bands; n += 2) { - table[i] += (n & 2 ? -1.0f : 1.0f) / (n * n) * - std::sin(numbers::tau_v * n * i / (float)OscillatorConstants::WAVETABLE_LENGTH) / (numbers::pi_sqr_v / 8.0f); + table[i] += (n & 2 ? -1.0f : 1.0f) / (n * n) + * std::sin(2 * pi_v * n * i / (float)OscillatorConstants::WAVETABLE_LENGTH) / (pi_sqr / 8.f); } } } @@ -151,6 +155,7 @@ void Oscillator::generateTriangleWaveTable(int bands, sample_t* table, int first void Oscillator::generateSquareWaveTable(int bands, sample_t* table, int firstBand) { + using namespace std::numbers; // square waves only contain odd harmonics, // at diffrent levels when compared to triangle waves // https://en.wikipedia.org/wiki/Square_wave @@ -159,8 +164,8 @@ void Oscillator::generateSquareWaveTable(int bands, sample_t* table, int firstBa for (int n = firstBand | 1; n <= bands; n += 2) { table[i] += (1.0f / n) - * std::sin(numbers::tau_v * i * n / OscillatorConstants::WAVETABLE_LENGTH) - / (numbers::pi_v / 4); + * std::sin(2 * pi_v * i * n / OscillatorConstants::WAVETABLE_LENGTH) + / (pi_v / 4.f); } } } diff --git a/src/core/ValueBuffer.cpp b/src/core/ValueBuffer.cpp index 01003dc3b..b77464023 100644 --- a/src/core/ValueBuffer.cpp +++ b/src/core/ValueBuffer.cpp @@ -1,6 +1,7 @@ #include "ValueBuffer.h" -#include "interpolation.h" +#include +#include namespace lmms { @@ -38,9 +39,7 @@ int ValueBuffer::length() const void ValueBuffer::interpolate(float start, float end_) { float i = 0; - std::generate(begin(), end(), [&]() { - return linearInterpolate( start, end_, i++ / length()); - }); + std::generate(begin(), end(), [&]() { return std::lerp(start, end_, i++ / length()); }); } diff --git a/src/core/fft_helpers.cpp b/src/core/fft_helpers.cpp index 2af0829fb..e4fd87aeb 100644 --- a/src/core/fft_helpers.cpp +++ b/src/core/fft_helpers.cpp @@ -27,7 +27,7 @@ #include "fft_helpers.h" #include -#include "lmms_constants.h" +#include namespace lmms { @@ -104,6 +104,7 @@ int notEmpty(const std::vector &spectrum) */ int precomputeWindow(float *window, unsigned int length, FFTWindow type, bool normalized) { + using namespace std::numbers; if (window == nullptr) {return -1;} float gain = 0; @@ -144,9 +145,9 @@ int precomputeWindow(float *window, unsigned int length, FFTWindow type, bool no // common computation for cosine-sum based windows for (unsigned int i = 0; i < length; i++) { - window[i] = (a0 - a1 * std::cos(2 * numbers::pi_v * i / ((float)length - 1.0)) - + a2 * std::cos(4 * numbers::pi_v * i / ((float)length - 1.0)) - - a3 * std::cos(6 * numbers::pi_v * i / ((float)length - 1.0))); + window[i] = (a0 - a1 * std::cos(2 * pi_v * i / (static_cast(length) - 1.0)) + + a2 * std::cos(4 * pi_v * i / (static_cast(length) - 1.0)) + - a3 * std::cos(6 * pi_v * i / (static_cast(length) - 1.0))); gain += window[i]; } diff --git a/src/gui/widgets/Knob.cpp b/src/gui/widgets/Knob.cpp index 7aa676953..25d2e3e3f 100644 --- a/src/gui/widgets/Knob.cpp +++ b/src/gui/widgets/Knob.cpp @@ -25,6 +25,7 @@ #include "Knob.h" #include +#include #include "lmms_math.h" #include "DeprecationHelper.h" @@ -312,7 +313,7 @@ void Knob::setTextColor( const QColor & c ) QLineF Knob::calculateLine( const QPointF & _mid, float _radius, float _innerRadius ) const { - const float rarc = m_angle * numbers::pi_v / 180.0; + const float rarc = m_angle * std::numbers::pi_v / 180.0; const float ca = std::cos(rarc); const float sa = -std::sin(rarc);