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 <numbers> 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 <numbers>

* 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 <messmer.dalton@gmail.com>

* Apply suggestions from code review

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

* 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 <messmer.dalton@gmail.com>

* Clean up fastRand() a little bit more

---------

Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
This commit is contained in:
Fawn
2025-02-13 11:15:08 -07:00
committed by GitHub
parent e615046d78
commit e328a136fc
47 changed files with 327 additions and 321 deletions

View File

@@ -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<double>( len ) / static_cast<double>( harm );
const double amp = -1.0 / static_cast<double>( harm );
//const double a2 = std::cos(om * harm * numbers::tau_v<float>);
s += amp * /*a2 **/ std::sin(static_cast<double>(ph * harm) / static_cast<double>(len) * numbers::tau_v<float>);
//const double a2 = std::cos(om * harm * 2 * pi_v<float>);
s += amp * /*a2 **/ std::sin(static_cast<double>(ph * harm) / static_cast<double>(len) * 2 * pi_v<float>);
harm++;
} while( hlen > 2.0 );
s_waveforms[static_cast<std::size_t>(BandLimitedWave::Waveform::BLSaw)].setSampleAt( i, ph, s );
@@ -145,8 +146,8 @@ void BandLimitedWave::generateWaves()
{
hlen = static_cast<double>( len ) / static_cast<double>( harm );
const double amp = 1.0 / static_cast<double>( harm );
//const double a2 = std::cos(om * harm * numbers::tau_v<float>);
s += amp * /*a2 **/ std::sin(static_cast<double>(ph * harm) / static_cast<double>(len) * numbers::tau_v<float>);
//const double a2 = std::cos(om * harm * 2 * pi_v<float>);
s += amp * /*a2 **/ std::sin(static_cast<double>(ph * harm) / static_cast<double>(len) * 2 * pi_v<float>);
harm += 2;
} while( hlen > 2.0 );
s_waveforms[static_cast<std::size_t>(BandLimitedWave::Waveform::BLSquare)].setSampleAt( i, ph, s );
@@ -186,9 +187,9 @@ void BandLimitedWave::generateWaves()
{
hlen = static_cast<double>( len ) / static_cast<double>( harm );
const double amp = 1.0 / static_cast<double>( harm * harm );
//const double a2 = std::cos(om * harm * numbers::tau_v<float>);
//const double a2 = std::cos(om * harm * 2 * pi_v<float>);
s += amp * /*a2 **/ std::sin((static_cast<double>(ph * harm) / static_cast<double>(len) +
((harm + 1) % 4 == 0 ? 0.5 : 0.0)) * numbers::tau_v<float>);
((harm + 1) % 4 == 0 ? 0.5 : 0.0)) * 2 * pi_v<float>);
harm += 2;
} while( hlen > 2.0 );
s_waveforms[static_cast<std::size_t>(BandLimitedWave::Waveform::BLTriangle)].setSampleAt( i, ph, s );

View File

@@ -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<float>;
auto saw01 = ph_tau - std::floor(ph_tau);
auto saw01 = absFraction(ph / (2 * std::numbers::pi_v<float>));
// 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<float>(sliLev[0] * sliLev[0]) * mem_t;
GetEnv(1, sec, "Envelope", dsfile);
F1 = MasterTune * numbers::tau_v<float> * GetPrivateProfileFloat(sec, "F1", 200.0, dsfile) / Fs;
F1 = MasterTune * 2 * pi_v<float> * 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<float> * GetPrivateProfileFloat(sec, "F2", 120.0, dsfile) / Fs;
F2 = MasterTune * 2 * pi_v<float> * 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<float> * GetPrivateProfileFloat(sec, "F1", 200.0, dsfile) / Fs;
OF2 = MasterTune * numbers::tau_v<float> * GetPrivateProfileFloat(sec, "F2", 120.0, dsfile) / Fs;
OF1 = MasterTune * 2 * pi_v<float> * GetPrivateProfileFloat(sec, "F1", 200.0, dsfile) / Fs;
OF2 = MasterTune * 2 * pi_v<float> * GetPrivateProfileFloat(sec, "F2", 120.0, dsfile) / Fs;
OW1 = GetPrivateProfileInt(sec, "Wave1", 0, dsfile);
OW2 = GetPrivateProfileInt(sec, "Wave2", 0, dsfile);
OBal2 = static_cast<float>(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<float> / OF1;
Ocf2 = numbers::tau_v<float> / OF2;
Ocf1 = 2 * pi_v<float> / OF1;
Ocf2 = 2 * pi_v<float> / OF2;
for (i = 0; i < 6; i++)
{
Oc[i][0] = Oc[i][1] = Ocf1 + (Ocf2 - Ocf1) * 0.2f * static_cast<float>(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<float>(sliLev[3] * sliLev[3]) * mem_b;
BF = MasterTune * numbers::tau_v<float> * GetPrivateProfileFloat(sec, "F", 1000.0, dsfile) / Fs;
BPhi = numbers::tau_v<float> / 8.f;
BF = MasterTune * 2 * pi_v<float> * GetPrivateProfileFloat(sec, "F", 1000.0, dsfile) / Fs;
BPhi = pi_v<float> / 4.f;
GetEnv(5, sec, "Envelope", dsfile);
BFStep = GetPrivateProfileInt(sec, "dF", 50, dsfile);
BQ = static_cast<float>(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<float>(sliLev[4] * sliLev[4]) * mem_b;
BF2 = MasterTune * numbers::tau_v<float> * GetPrivateProfileFloat(sec, "F", 1000.0, dsfile) / Fs;
BPhi2 = numbers::tau_v<float> / 8.f;
BF2 = MasterTune * 2 * pi_v<float> * GetPrivateProfileFloat(sec, "F", 1000.0, dsfile) / Fs;
BPhi2 = pi_v<float> / 4.f;
GetEnv(6, sec, "Envelope", dsfile);
BFStep2 = GetPrivateProfileInt(sec, "dF", 50, dsfile);
BQ2 = static_cast<float>(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<float>)); // 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<float>)) * 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<float>)) * envData[6][ENV] * BL2;
DF[botmp] = DF[botmp] + std::cos(BPhi2) * envData[6][ENV] * BL2;
}
if (t >= envData[6][MAX])
{

View File

@@ -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() )

View File

@@ -25,12 +25,11 @@
#include "Instrument.h"
#include <cmath>
#include <numbers>
#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> * (float) f / (float) n->m_fadeInLength);
buf[offset + f][ch] *= 0.5 - 0.5 * std::cos(std::numbers::pi_v<float> * static_cast<float>(f) / static_cast<float>(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> * (float) (total + f) / currentLength);
buf[f][ch] *= 0.5 - 0.5 * std::cos(std::numbers::pi_v<float> * static_cast<float>(total + f) / currentLength);
if (total + f >= currentLength)
{
n->m_fadeInLength = currentLength;

View File

@@ -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
{

View File

@@ -29,6 +29,7 @@
#if !defined(__MINGW32__) && !defined(__MINGW64__)
#include <thread>
#endif
#include <numbers>
#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<float> * n * imod) / numbers::pi_half_v<float>;
table[i] += (n % 2 ? 1.0f : -1.0f) / n * std::sin(2 * pi_v<float> * n * imod) / (pi_v<float> * 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<float> * pi_v<float>;
// 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<float> * n * i / (float)OscillatorConstants::WAVETABLE_LENGTH) / (numbers::pi_sqr_v<float> / 8.0f);
table[i] += (n & 2 ? -1.0f : 1.0f) / (n * n)
* std::sin(2 * pi_v<float> * 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<float> * i * n / OscillatorConstants::WAVETABLE_LENGTH)
/ (numbers::pi_v<float> / 4);
* std::sin(2 * pi_v<float> * i * n / OscillatorConstants::WAVETABLE_LENGTH)
/ (pi_v<float> / 4.f);
}
}
}

View File

@@ -1,6 +1,7 @@
#include "ValueBuffer.h"
#include "interpolation.h"
#include <algorithm>
#include <cmath>
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()); });
}

View File

@@ -27,7 +27,7 @@
#include "fft_helpers.h"
#include <cmath>
#include "lmms_constants.h"
#include <numbers>
namespace lmms
{
@@ -104,6 +104,7 @@ int notEmpty(const std::vector<float> &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<float> * i / ((float)length - 1.0))
+ a2 * std::cos(4 * numbers::pi_v<float> * i / ((float)length - 1.0))
- a3 * std::cos(6 * numbers::pi_v<float> * i / ((float)length - 1.0)));
window[i] = (a0 - a1 * std::cos(2 * pi_v<float> * i / (static_cast<float>(length) - 1.0))
+ a2 * std::cos(4 * pi_v<float> * i / (static_cast<float>(length) - 1.0))
- a3 * std::cos(6 * pi_v<float> * i / (static_cast<float>(length) - 1.0)));
gain += window[i];
}

View File

@@ -25,6 +25,7 @@
#include "Knob.h"
#include <QPainter>
#include <numbers>
#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<float> / 180.0;
const float rarc = m_angle * std::numbers::pi_v<float> / 180.0;
const float ca = std::cos(rarc);
const float sa = -std::sin(rarc);