Use templates for common geometric constants (#7558)

* add templates for common geometric constants

* oops missed one

* LD_2PI -> LD_PI

i re-added the wrong constant ffs

* CamelCase names and also verify compilation without -DLMMS_MINIMAL

* C++20 stuff

Updated to account for `<numbers>` and C++20:
- Marked all `lmms_constants.h` constants with an exact equivalent in `<numbers>` as deprecated
- Removed all `lmms_constants.h` constants where no variant is currently in use
- Using `inline constexpr`
- Using `std::floating_point` concept instead of `typename`

* add lmms::numbers namespace

* Remove panning_constants.h

Moves the four constants in panning_constants.h into panning.h, then
removes panning.h.

* Use std::exp(n) instead of powf(numbers::e, n)

* Use C++ std math functions

Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>

* Use overloaded std math functions

An attempt to fix compiler warnings on some platforms

* Remove uses of __USE_XOPEN

And also update two functions I missed from the previous commit

* Missed a few

* Fix ANOTHER std math function use

Of course there's another one

---------

Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
This commit is contained in:
Fawn
2025-02-03 09:52:13 -07:00
committed by GitHub
parent fc125bc7ba
commit 9aa937d391
33 changed files with 127 additions and 189 deletions

View File

@@ -31,10 +31,6 @@
#ifndef LMMS_BASIC_FILTERS_H
#define LMMS_BASIC_FILTERS_H
#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif
#include <cmath>
#include <array>
@@ -74,21 +70,20 @@ public:
inline void setCoeffs( float freq )
{
// wc
const double wc = D_2PI * freq;
const double wc = numbers::tau * freq;
const double wc2 = wc * wc;
const double wc3 = wc2 * wc;
m_wc4 = wc2 * wc2;
// k
const double k = wc / tan( D_PI * freq / m_sampleRate );
const double k = wc / std::tan(numbers::pi * freq / m_sampleRate);
const double k2 = k * k;
const double k3 = k2 * k;
m_k4 = k2 * k2;
// a
static const double sqrt2 = sqrt( 2.0 );
const double sq_tmp1 = sqrt2 * wc3 * k;
const double sq_tmp2 = sqrt2 * wc * k3;
const double sq_tmp1 = numbers::sqrt2 * wc3 * k;
const double sq_tmp2 = numbers::sqrt2 * wc * k3;
m_a = 1.0 / ( 4.0 * wc2 * k2 + 2.0 * sq_tmp1 + m_k4 + 2.0 * sq_tmp2 + m_wc4 );
@@ -718,7 +713,7 @@ public:
{
_freq = std::clamp(_freq, 50.0f, 20000.0f);
const float sr = m_sampleRatio * 0.25f;
const float f = 1.0f / ( _freq * F_2PI );
const float f = 1.0f / (_freq * numbers::tau_v<float>);
m_rca = 1.0f - sr / ( f + sr );
m_rcb = 1.0f - m_rca;
@@ -751,8 +746,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 ) * F_2PI );
const float f1 = 1.0f / ( linearInterpolate( _f[vowel+0][1], _f[vowel+1][1], fract ) * F_2PI );
const float f0 = 1.0f / (linearInterpolate(_f[vowel+0][0], _f[vowel+1][0], fract) * numbers::tau_v<float>);
const float f1 = 1.0f / (linearInterpolate(_f[vowel+0][1], _f[vowel+1][1], fract) * numbers::tau_v<float>);
// samplerate coeff: depends on oversampling
const float sr = m_type == FilterType::FastFormant ? m_sampleRatio : m_sampleRatio * 0.25f;
@@ -774,7 +769,7 @@ public:
// (Empirical tunning)
m_p = ( 3.6f - 3.2f * f ) * f;
m_k = 2.0f * m_p - 1;
m_r = _q * powf( F_E, ( 1 - m_p ) * 1.386249f );
m_r = _q * std::exp((1 - m_p) * 1.386249f);
if( m_doubleFilter )
{
@@ -791,7 +786,7 @@ public:
m_p = ( 3.6f - 3.2f * f ) * f;
m_k = 2.0f * m_p - 1.0f;
m_r = _q * 0.1f * powf( F_E, ( 1 - m_p ) * 1.386249f );
m_r = _q * 0.1f * std::exp((1 - m_p) * 1.386249f);
return;
}
@@ -801,7 +796,7 @@ public:
m_type == FilterType::Highpass_SV ||
m_type == FilterType::Notch_SV )
{
const float f = sinf(std::max(minFreq(), _freq) * m_sampleRatio * F_PI);
const float f = std::sin(std::max(minFreq(), _freq) * m_sampleRatio * numbers::pi_v<float>);
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));
@@ -810,7 +805,7 @@ public:
// other filters
_freq = std::clamp(_freq, minFreq(), 20000.0f);
const float omega = F_2PI * _freq * m_sampleRatio;
const float omega = numbers::tau_v<float> * _freq * m_sampleRatio;
const float tsin = sinf( omega ) * 0.5f;
const float tcos = cosf( omega );

View File

@@ -328,7 +328,7 @@ namespace lmms::DspEffectLibrary
void nextSample( sample_t& inLeft, sample_t& inRight )
{
const float toRad = F_PI / 180;
const float toRad = numbers::pi_v<float> / 180;
const sample_t tmp = inLeft;
inLeft += inRight * sinf( m_wideCoeff * ( .5 * toRad ) );
inRight -= tmp * sinf( m_wideCoeff * ( .5 * toRad ) );

View File

@@ -27,7 +27,7 @@
#include <cstdlib>
#include "Midi.h"
#include "panning_constants.h"
#include "panning.h"
#include "volume.h"
namespace lmms

View File

@@ -114,7 +114,7 @@ public:
// now follow the wave-shape-routines...
static inline sample_t sinSample( const float _sample )
{
return sinf( _sample * F_2PI );
return std::sin(_sample * numbers::tau_v<float>);
}
static inline sample_t triangleSample( const float _sample )

View File

@@ -37,7 +37,7 @@ public:
QuadratureLfo( int sampleRate ) :
m_frequency(0),
m_phase(0),
m_offset(D_PI / 2)
m_offset(numbers::pi_half)
{
setSampleRate(sampleRate);
}
@@ -64,7 +64,7 @@ public:
inline void setSampleRate ( int samplerate )
{
m_samplerate = samplerate;
m_twoPiOverSr = F_2PI / samplerate;
m_twoPiOverSr = numbers::tau_v<float> / samplerate;
m_increment = m_frequency * m_twoPiOverSr;
}
@@ -81,10 +81,7 @@ public:
*r = sinf( m_phase + m_offset );
m_phase += m_increment;
while (m_phase >= D_2PI)
{
m_phase -= D_2PI;
}
while (m_phase >= numbers::tau) { m_phase -= numbers::tau; }
}
private:

View File

@@ -25,10 +25,6 @@
#ifndef LMMS_INTERPOLATION_H
#define LMMS_INTERPOLATION_H
#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif
#include <cmath>
#include "lmms_constants.h"
#include "lmms_math.h"
@@ -82,7 +78,7 @@ 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 - cosf( x * F_PI ) ) * 0.5f;
const float f = (1.0f - std::cos(x * numbers::pi_v<float>)) * 0.5f;
return f * (v1 - v0) + v0;
}

View File

@@ -25,36 +25,54 @@
#ifndef LMMS_CONSTANTS_H
#define LMMS_CONSTANTS_H
namespace lmms
// #include <numbers>
// #include <concepts>
namespace lmms::numbers
{
//TODO C++20: Use std::floating_point instead of typename
//TODO C++20: Use std::numbers::pi_v<T> instead of literal value
template<typename T>
inline constexpr T pi_v = T(3.14159265358979323846264338327950288419716939937510);
inline constexpr double pi = pi_v<double>;
constexpr long double LD_PI = 3.14159265358979323846264338327950288419716939937510;
constexpr long double LD_2PI = LD_PI * 2.0;
constexpr long double LD_PI_2 = LD_PI * 0.5;
constexpr long double LD_PI_R = 1.0 / LD_PI;
constexpr long double LD_PI_SQR = LD_PI * LD_PI;
constexpr long double LD_E = 2.71828182845904523536028747135266249775724709369995;
constexpr long double LD_E_R = 1.0 / LD_E;
constexpr long double LD_SQRT_2 = 1.41421356237309504880168872420969807856967187537695;
//TODO C++20: Use std::floating_point instead of typename
template<typename T>
inline constexpr T tau_v = T(pi_v<T> * 2.0);
inline constexpr double tau = tau_v<double>;
constexpr double D_PI = (double) LD_PI;
constexpr double D_2PI = (double) LD_2PI;
constexpr double D_PI_2 = (double) LD_PI_2;
constexpr double D_PI_R = (double) LD_PI_R;
constexpr double D_PI_SQR = (double) LD_PI_SQR;
constexpr double D_E = (double) LD_E;
constexpr double D_E_R = (double) LD_E_R;
constexpr double D_SQRT_2 = (double) LD_SQRT_2;
//TODO C++20: Use std::floating_point instead of typename
template<typename T>
inline constexpr T pi_half_v = T(pi_v<T> / 2.0);
inline constexpr double pi_half = pi_half_v<double>;
constexpr float F_PI = (float) LD_PI;
constexpr float F_2PI = (float) LD_2PI;
constexpr float F_PI_2 = (float) LD_PI_2;
constexpr float F_PI_R = (float) LD_PI_R;
constexpr float F_PI_SQR = (float) LD_PI_SQR;
constexpr float F_E = (float) LD_E;
constexpr float F_E_R = (float) LD_E_R;
constexpr float F_SQRT_2 = (float) LD_SQRT_2;
//TODO C++20: Use std::floating_point instead of typename
template<typename T>
inline constexpr T pi_sqr_v = T(pi_v<T> * pi_v<T>);
inline constexpr double pi_sqr = pi_sqr_v<double>;
//TODO C++20: Use std::floating_point instead of typename
//TODO C++20: Use std::numbers::e_v<T> instead of literal value
template<typename T>
inline constexpr T e_v = T(2.71828182845904523536028747135266249775724709369995);
inline constexpr double e = e_v<double>;
//TODO C++20: Use std::floating_point instead of typename
template<typename T>
inline constexpr T inv_e_v = T(1.0 / e_v<T>);
inline constexpr double inv_e = e_v<double>;
//TODO C++20: Use std::floating_point instead of typename
//TODO C++20: Use std::numbers::sqrt2_v<T> instead of literal value
template<typename T>
inline constexpr T sqrt2_v = T(1.41421356237309504880168872420969807856967187537695);
inline constexpr double sqrt2 = sqrt2_v<double>;
}
namespace lmms
{
constexpr float F_EPSILON = 1.0e-10f; // 10^-10

View File

@@ -136,32 +136,31 @@ inline float signedPowf(float v, float e)
//! Value should be within [0,1]
inline float logToLinearScale(float min, float max, float value)
{
if( min < 0 )
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, F_E ) * mmax;
return std::isnan( result ) ? 0 : result;
const float val = value * (max - min) + min;
float result = signedPowf(val / mmax, numbers::e_v<float>) * mmax;
return std::isnan(result) ? 0 : result;
}
float result = powf( value, F_E ) * ( max - min ) + min;
return std::isnan( result ) ? 0 : result;
float result = std::pow(value, numbers::e_v<float>) * (max - min) + min;
return std::isnan(result) ? 0 : result;
}
//! @brief Scales value from logarithmic to linear. Value should be in min-max range.
inline float linearToLogScale(float min, float max, float value)
{
static const float EXP = 1.0f / F_E;
const float valueLimited = std::clamp(value, min, max);
const float val = ( valueLimited - min ) / ( max - min );
if( min < 0 )
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, EXP ) * mmax;
return std::isnan( result ) ? 0 : result;
float result = signedPowf(valueLimited / mmax, numbers::inv_e_v<float>) * mmax;
return std::isnan(result) ? 0 : result;
}
float result = powf( val, EXP ) * ( max - min ) + min;
return std::isnan( result ) ? 0 : result;
float result = std::pow(val, numbers::inv_e_v<float>) * (max - min) + min;
return std::isnan(result) ? 0 : result;
}
inline float fastPow10f(float x)

View File

@@ -27,7 +27,6 @@
#define LMMS_PANNING_H
#include "lmms_basics.h"
#include "panning_constants.h"
#include "Midi.h"
#include "volume.h"
@@ -36,6 +35,10 @@
namespace lmms
{
inline constexpr panning_t PanningRight = 100;
inline constexpr panning_t PanningLeft = -PanningRight;
inline constexpr panning_t PanningCenter = 0;
inline constexpr panning_t DefaultPanning = PanningCenter;
inline StereoVolumeVector panningToVolumeVector( panning_t _p,
float _scale = 1.0f )

View File

@@ -1,41 +0,0 @@
/*
* panning_constants.h - declaration of some constants, concerning the
* panning of a note
*
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef LMMS_PANNING_CONSTANTS_H
#define LMMS_PANNING_CONSTANTS_H
namespace lmms
{
constexpr panning_t PanningRight = ( 0 + 100 );
constexpr panning_t PanningLeft = - PanningRight;
constexpr panning_t PanningCenter = 0;
constexpr panning_t DefaultPanning = PanningCenter;
} // namespace lmms
#endif // LMMS_PANNING_CONSTANTS_H