Improve lmms::fastRand() and use it instead of std::rand() (#7741)

This commit is contained in:
Fawn
2026-01-15 17:12:04 -07:00
committed by GitHub
parent b390fa414a
commit 5e3a67c9d1
23 changed files with 433 additions and 468 deletions

View File

@@ -162,7 +162,7 @@ public:
static inline sample_t noiseSample( const float )
{
return 1.0f - rand() * 2.0f / static_cast<float>(RAND_MAX);
return fastRandInc(-1.f, 1.f);
}
static sample_t userWaveSample(const SampleBuffer* buffer, const float sample)

View File

@@ -43,6 +43,7 @@
namespace lmms
{
// TODO C++23: Make constexpr since std::abs() will be constexpr
inline bool approximatelyEqual(float x, float y) noexcept
{
@@ -81,26 +82,112 @@ inline auto absFraction(std::floating_point auto x) noexcept
return x - std::floor(x);
}
inline auto fastRand() noexcept
//! @brief Returns a pseudorandom integer within [0, 32768).
//! @returns A pseudorandom integer greater than or equal to 0 and less than 32767.
inline int fastRand() noexcept
{
static unsigned long next = 1;
next = next * 1103515245 + 12345;
return next / 65536 % 32768;
thread_local unsigned long s_next = 1;
s_next = s_next * 1103515245 + 12345;
return s_next / 65536 % 32768;
}
//! @brief Returns a pseudorandom number within [0, @p upper) (exclusive upper bound).
//! @returns A pseudorandom number greater than or equal to 0 and less @p upper.
template<std::floating_point T>
inline auto fastRand(T range) noexcept
inline T fastRand(T upper) noexcept
{
constexpr T FAST_RAND_RATIO = static_cast<T>(1.0 / 32767);
return fastRand() * range * FAST_RAND_RATIO;
constexpr auto FAST_RAND_RATIO = static_cast<T>(1.0 / 32768);
return fastRand() * upper * FAST_RAND_RATIO;
}
template<std::floating_point T>
inline auto fastRand(T from, T to) noexcept
//! @brief Returns a pseudorandom integer within [0, @p upper) (exclusive upper bound).
//! @p upper may be negative, in which case the output range is (@p upper, 0].
//! @returns A pseudorandom integer greater than or equal to 0 and less than @p upper.
template<std::integral T>
inline T fastRand(T upper) noexcept
{
return from + fastRand(to - from);
constexpr float FAST_RAND_RATIO = 1.f / 32768;
return static_cast<T>(fastRand() * static_cast<float>(upper) * FAST_RAND_RATIO);
}
//! @brief Returns a pseudorandom integer within [@p from, @p to) (exclusive upper bound).
//! @returns A pseudorandom integer greater than or equal to @p from and less than @p to.
template<typename T> requires std::is_arithmetic_v<T>
inline auto fastRand(T from, T to) noexcept { return from + fastRand(to - from); }
//! @brief Returns a pseudorandom number within [0, @p upper] (inclusive upper bound).
//! @returns A pseudorandom number greater than or equal to 0 and less than or equal to @p upper.
template<std::floating_point T>
inline T fastRandInc(T upper) noexcept
{
constexpr auto FAST_RAND_RATIO = static_cast<T>(1.0 / 32767);
return fastRand() * upper * FAST_RAND_RATIO;
}
//! @brief Returns a pseudorandom integer within [0, @p upper] (inclusive upper bound).
//! @returns A pseudorandom integer greater than or equal to 0 and less than or equal to @p upper.
template<std::unsigned_integral T>
inline T fastRandInc(T upper) noexcept
{
// The integer specialization of this function is kind of weird, but it is
// necessary to prevent massive bias away from the maximum value.
// FAST_RAND_RATIO here is 1 greater than normal, so when multiplied by, it
// will result in a random float within [0, @p upper) instead of the usual
// [0, @p upper].
constexpr float FAST_RAND_RATIO = 1.f / 32768;
// Since the random float will be in a range that does not include @upper
// due to the above ratio, increase the upper bound by 1.
// All values greater than @p upper get rounded down to @p upper, making the
// chance of returning a value of @p upper the same as any other of the
// possible values.
// No need to copysign() unlike the signed_integral overload, since it will always be positive
return static_cast<T>(fastRand() * (upper + 1.f) * FAST_RAND_RATIO);
}
//! @brief Returns a pseudorandom integer within [0, @p upper] (inclusive upper bound).
//! @p upper may be negative, in which case the output range is [@p upper, 0].
//! @returns A pseudorandom integer greater than or equal to 0 and less than or equal to @p upper.
template<std::signed_integral T>
inline T fastRandInc(T upper) noexcept
{
// The integer specialization of this function is kind of weird, but it is
// necessary to prevent massive bias away from the maximum value.
// FAST_RAND_RATIO here is 1 greater than normal, so when multiplied by, it
// will result in a random float within [0, @p upper) instead of the usual
// [0, @p upper].
constexpr float FAST_RAND_RATIO = 1.f / 32768;
// Since the random float will be in a range that does not include @upper
// due to the above ratio, increase the magnitude of the upper bound by 1.
// All values greater than @p upper get rounded down to @p upper, making the
// chance of returning a value of @p upper the same as any other of the
// possible values.
// HACK: Even on -O3, without this static_cast, it will convert @p upper to float twice for some reason
const auto fupper = static_cast<float>(upper);
const float r = fupper + std::copysign(1.f, fupper);
// Always round towards 0 (implicit truncation occurs during static_cast).
return static_cast<T>(fastRand() * r * FAST_RAND_RATIO);
}
//! @brief Returns a pseudorandom integer within [@p from, @p to] (inclusive upper bound).
//! This function does not require the parameters to be in the proper order.
//! fastRand(a, b) behaves identically to fastRand(b, a).
//! @returns A pseudorandom integer greater than or equal to @p from and less than or equal to @p to.
template<typename T> requires std::is_arithmetic_v<T>
inline auto fastRandInc(T from, T to) noexcept { return from + fastRandInc(to - from); }
//! @brief Returns true one in @p chance times at random.
inline bool oneIn(unsigned chance) noexcept { return 0 == (fastRand() % chance); }
//! Round `value` to `where` depending on step size
template<class T>
static void roundAt(T& value, const T& where, const T& stepSize)
@@ -180,26 +267,26 @@ inline float linearToLogScale(float min, float max, float value)
return std::isnan(result) ? 0 : result;
}
// TODO C++26: Make constexpr since std::exp() will be constexpr
template<std::floating_point T>
template<typename T> requires std::is_arithmetic_v<T>
inline auto fastPow10f(T x)
{
return std::exp(std::numbers::ln10_v<T> * x);
using F_T = std::conditional_t<std::is_floating_point_v<T>, T, float>;
return std::exp(std::numbers::ln10_v<F_T> * x);
}
// TODO C++26: Make constexpr since std::exp() will be constexpr
inline auto fastPow10f(std::integral auto x)
{
return std::exp(std::numbers::ln10_v<float> * x);
}
// TODO C++26: Make constexpr since std::log() will be constexpr
inline auto fastLog10f(float x)
template<typename T> requires std::is_arithmetic_v<T>
inline auto fastLog10f(T x)
{
constexpr auto inv_ln10 = static_cast<float>(1.0 / std::numbers::ln10);
using F_T = std::conditional_t<std::is_floating_point_v<T>, T, float>;
constexpr auto inv_ln10 = static_cast<F_T>(1.0 / std::numbers::ln10);
return std::log(x) * inv_ln10;
}
//! @brief Converts linear amplitude (>0-1.0) to dBFS scale.
//! @param amp Linear amplitude, where 1.0 = 0dBFS. ** Must be larger than zero! **
//! @return Amplitude in dBFS.

View File

@@ -98,7 +98,7 @@ inline float BitcrushEffect::depthCrush( float in )
inline float BitcrushEffect::noise( float amt )
{
return fastRand(-amt, +amt);
return fastRandInc(-amt, +amt);
}
Effect::ProcessStatus BitcrushEffect::processImpl(SampleFrame* buf, const fpp_t frames)

View File

@@ -106,8 +106,8 @@ Effect::ProcessStatus FlangerEffect::processImpl(SampleFrame* buf, const fpp_t f
float leftLfo;
float rightLfo;
buf[f][0] += fastRand(-1.f, +1.f) * noise;
buf[f][1] += fastRand(-1.f, +1.f) * noise;
buf[f][0] += fastRandInc(-1.f, 1.f) * noise;
buf[f][1] += fastRandInc(-1.f, 1.f) * noise;
dryS[0] = buf[f][0];
dryS[1] = buf[f][1];
m_lfo->tick(&leftLfo, &rightLfo);

View File

@@ -156,7 +156,7 @@ Effect::ProcessStatus GranularPitchShifterEffect::processImpl(SampleFrame* buf,
if (++m_timeSinceLastGrain >= m_nextWaitRandomization * waitMult)
{
m_timeSinceLastGrain = 0;
auto randThing = fastRand<double>(-1.0, +1.0);
auto randThing = fastRandInc<double>(-1.0, +1.0);
m_nextWaitRandomization = std::exp2(randThing * twitch);
double grainSpeed = 1. / std::exp2(randThing * jitter);

View File

@@ -33,7 +33,7 @@
#include "NotePlayHandle.h"
#include "Oscillator.h"
#include "PixmapButton.h"
#include "lmms_math.h"
#include "embed.h"
#include "plugin_export.h"
@@ -231,71 +231,63 @@ void OrganicInstrument::playNote( NotePlayHandle * _n,
auto oscs_l = std::array<Oscillator*, NUM_OSCILLATORS>{};
auto oscs_r = std::array<Oscillator*, NUM_OSCILLATORS>{};
_n->m_pluginData = new oscPtr;
auto newOsc = new oscPtr;
_n->m_pluginData = newOsc;
for( int i = m_numOscillators - 1; i >= 0; --i )
for (int i = m_numOscillators - 1; i >= 0; --i)
{
static_cast<oscPtr *>( _n->m_pluginData )->phaseOffsetLeft[i]
= rand() / (static_cast<float>(RAND_MAX) + 1.0f);
static_cast<oscPtr *>( _n->m_pluginData )->phaseOffsetRight[i]
= rand() / (static_cast<float>(RAND_MAX) + 1.0f);
newOsc->phaseOffsetLeft[i] = fastRand(1.f);
newOsc->phaseOffsetRight[i] = fastRand(1.f);
// initialise ocillators
if( i == m_numOscillators - 1 )
if (i == m_numOscillators - 1)
{
// create left oscillator
oscs_l[i] = new Oscillator(
&m_osc[i]->m_waveShape,
&m_modulationAlgo,
_n->frequency(),
m_osc[i]->m_detuningLeft,
static_cast<oscPtr *>( _n->m_pluginData )->phaseOffsetLeft[i],
m_osc[i]->m_volumeLeft );
&m_osc[i]->m_waveShape,
&m_modulationAlgo,
_n->frequency(),
m_osc[i]->m_detuningLeft,
newOsc->phaseOffsetLeft[i],
m_osc[i]->m_volumeLeft);
// create right oscillator
oscs_r[i] = new Oscillator(
&m_osc[i]->m_waveShape,
&m_modulationAlgo,
_n->frequency(),
m_osc[i]->m_detuningRight,
static_cast<oscPtr *>( _n->m_pluginData )->phaseOffsetRight[i],
m_osc[i]->m_volumeRight );
&m_osc[i]->m_waveShape,
&m_modulationAlgo,
_n->frequency(),
m_osc[i]->m_detuningRight,
newOsc->phaseOffsetRight[i],
m_osc[i]->m_volumeRight);
}
else
{
// create left oscillator
oscs_l[i] = new Oscillator(
&m_osc[i]->m_waveShape,
&m_modulationAlgo,
_n->frequency(),
m_osc[i]->m_detuningLeft,
static_cast<oscPtr *>( _n->m_pluginData )->phaseOffsetLeft[i],
m_osc[i]->m_volumeLeft,
oscs_l[i + 1] );
&m_osc[i]->m_waveShape,
&m_modulationAlgo,
_n->frequency(),
m_osc[i]->m_detuningLeft,
newOsc->phaseOffsetLeft[i],
m_osc[i]->m_volumeLeft,
oscs_l[i + 1]);
// create right oscillator
oscs_r[i] = new Oscillator(
&m_osc[i]->m_waveShape,
&m_modulationAlgo,
_n->frequency(),
m_osc[i]->m_detuningRight,
static_cast<oscPtr *>( _n->m_pluginData )->phaseOffsetRight[i],
m_osc[i]->m_volumeRight,
oscs_r[i + 1] );
&m_osc[i]->m_waveShape,
&m_modulationAlgo,
_n->frequency(),
m_osc[i]->m_detuningRight,
newOsc->phaseOffsetRight[i],
m_osc[i]->m_volumeRight,
oscs_r[i + 1]);
}
}
static_cast<oscPtr *>( _n->m_pluginData )->oscLeft = oscs_l[0];
static_cast<oscPtr *>( _n->m_pluginData )->oscRight = oscs_r[0];
newOsc->oscLeft = oscs_l[0];
newOsc->oscRight = oscs_r[0];
}
Oscillator * osc_l = static_cast<oscPtr *>( _n->m_pluginData )->oscLeft;
Oscillator * osc_r = static_cast<oscPtr *>( _n->m_pluginData)->oscRight;
osc_l->update( _working_buffer + offset, frames, 0 );
osc_r->update( _working_buffer + offset, frames, 1 );
auto osc = static_cast<oscPtr*>(_n->m_pluginData);
osc->oscLeft->update(_working_buffer + offset, frames, 0);
osc->oscRight->update(_working_buffer + offset, frames, 1);
// -- fx section --
@@ -346,27 +338,18 @@ float inline OrganicInstrument::waveshape(float in, float amount)
}
void OrganicInstrument::randomiseSettings()
{
for( int i = 0; i < m_numOscillators; i++ )
for (auto i = 0; i < m_numOscillators; ++i)
{
m_osc[i]->m_volModel.setValue( intRand( 0, 100 ) );
m_osc[i]->m_detuneModel.setValue( intRand( -5, 5 ) );
m_osc[i]->m_panModel.setValue( 0 );
m_osc[i]->m_oscModel.setValue( intRand( 0, 5 ) );
m_osc[i]->m_volModel.setValue(fastRandInc(100));
m_osc[i]->m_detuneModel.setValue(fastRandInc(-5, 5));
m_osc[i]->m_panModel.setValue(0);
m_osc[i]->m_oscModel.setValue(fastRandInc(5));
}
}
void OrganicInstrument::updateAllDetuning()
{
for( int i = 0; i < m_numOscillators; ++i )
@@ -376,17 +359,6 @@ void OrganicInstrument::updateAllDetuning()
}
int OrganicInstrument::intRand( int min, int max )
{
// int randn = min+int((max-min)*rand()/(RAND_MAX + 1.0));
// cout << randn << endl;
int randn = ( rand() % (max - min) ) + min;
return( randn );
}
gui::PluginView * OrganicInstrument::instantiateView( QWidget * _parent )
{
return( new gui::OrganicInstrumentView( this, _parent ) );

View File

@@ -133,8 +133,6 @@ public:
QString nodeName() const override;
int intRand( int min, int max );
static float * s_harmonics;
public slots:

View File

@@ -66,7 +66,7 @@ PeakControllerEffect::PeakControllerEffect(
Model * _parent,
const Descriptor::SubPluginFeatures::Key * _key ) :
Effect( &peakcontrollereffect_plugin_descriptor, _parent, _key ),
m_effectId( rand() ),
m_effectId(fastRand()),
m_peakControls( this ),
m_lastSample( 0 ),
m_autoController( nullptr )

View File

@@ -29,6 +29,7 @@
#include "PeakControllerEffectControls.h"
#include "PeakControllerEffect.h"
#include "Song.h"
#include "lmms_math.h"
namespace lmms
{
@@ -81,7 +82,7 @@ void PeakControllerEffectControls::loadSettings( const QDomElement & _this )
else
{
// TODO: Fix possible collision
m_effect->m_effectId = rand();
m_effect->m_effectId = fastRand();
}
}

View File

@@ -90,10 +90,10 @@ Effect::ProcessStatus ReverbSCEffect::processImpl(SampleFrame* buf, const fpp_t
{
auto s = std::array{buf[f][0], buf[f][1]};
const auto inGain = static_cast<SPFLOAT>(fastPow10f(
(inGainBuf ? inGainBuf->values()[f] : m_reverbSCControls.m_inputGainModel.value()) / 20.f));
const auto outGain = static_cast<SPFLOAT>(fastPow10f(
(outGainBuf ? outGainBuf->values()[f] : m_reverbSCControls.m_outputGainModel.value()) / 20.f));
const auto inGain = fastPow10f<SPFLOAT>(
(inGainBuf ? inGainBuf->values()[f] : m_reverbSCControls.m_inputGainModel.value()) / 20.f);
const auto outGain = fastPow10f<SPFLOAT>(
(outGainBuf ? outGainBuf->values()[f] : m_reverbSCControls.m_outputGainModel.value()) / 20.f);
s[0] *= inGain;
s[1] *= inGain;

View File

@@ -23,23 +23,13 @@
* Boston, MA 02110-1301 USA.
*/
#include "Sfxr.h"
#include <cstdlib>
#include <ctime>
#define rnd(n) (rand()%(n+1))
#define PI 3.14159265f
float frnd(float range)
{
return (float)rnd(10000)/10000*range;
}
#include <cmath>
#include <QDomElement>
#include "Sfxr.h"
#include "AudioEngine.h"
#include "Engine.h"
#include "InstrumentTrack.h"
@@ -47,9 +37,8 @@ float frnd(float range)
#include "NotePlayHandle.h"
#include "PixmapButton.h"
#include "MidiEvent.h"
#include "lmms_math.h"
#include "embed.h"
#include "plugin_export.h"
namespace lmms
@@ -145,7 +134,7 @@ void SfxrSynth::resetSample( bool restart )
phaser_buffer.fill(0.0f);
for (auto& noiseSample : noise_buffer)
{
noiseSample = frnd(2.0f) - 1.0f;
noiseSample = fastRandInc(-1.f, 1.f);
}
rep_time=0;
@@ -239,12 +228,14 @@ void SfxrSynth::update( SampleFrame* buffer, const int32_t frameNum )
if(phase>=period)
{
// phase=0;
phase%=period;
if(s->m_waveFormModel.value()==3)
for (auto& noiseSample : noise_buffer)
phase %= period;
if (s->m_waveFormModel.value() == 3)
{
for (auto& noiseSample : noise_buffer)
{
noiseSample = frnd(2.0f) - 1.0f;
noiseSample = fastRandInc(-1.f, 1.f);
}
}
}
// base waveform
float fp=(float)phase/period;
@@ -260,7 +251,7 @@ void SfxrSynth::update( SampleFrame* buffer, const int32_t frameNum )
sample=1.0f-fp*2;
break;
case 2: // sine
sample=(float)sin(fp*2*PI);
sample = std::sin(fp * 2.f * std::numbers::pi_v<float>);
break;
case 3: // noise
sample=noise_buffer[phase*32/period];
@@ -593,7 +584,6 @@ SfxrInstrumentView::SfxrInstrumentView( Instrument * _instrument,
QWidget * _parent ) :
InstrumentViewFixedSize( _instrument, _parent )
{
srand(time(nullptr));
setAutoFillBackground( true );
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
@@ -745,359 +735,307 @@ void SfxrInstrumentView::modelChanged()
}
void SfxrInstrumentView::genPickup()
{
auto s = castModel<SfxrInstrument>();
s->resetModels();
s->m_startFreqModel.setValue( 0.4f+frnd(0.5f) );
s->m_attModel.setValue( 0.0f );
s->m_holdModel.setValue( frnd(0.1f) );
s->m_decModel.setValue( 0.1f+frnd(0.4f) );
s->m_susModel.setValue( 0.3f+frnd(0.3f) );
s->m_startFreqModel.setValue(fastRandInc(0.4f, 0.9f));
s->m_attModel.setValue(0.f);
s->m_holdModel.setValue(fastRandInc(0.1f));
s->m_decModel.setValue(fastRandInc(0.1f, 0.5f));
s->m_susModel.setValue(fastRandInc(0.3f, 0.6f));
if(rnd(1))
if (oneIn(2))
{
s->m_changeSpeedModel.setValue( 0.5f+frnd(0.2f) );
s->m_changeAmtModel.setValue( 0.2f+frnd(0.4f) );
s->m_changeSpeedModel.setValue(fastRandInc(0.5f, 0.7f));
s->m_changeAmtModel.setValue(fastRandInc(0.2f, 0.6f));
}
}
void SfxrInstrumentView::genLaser()
{
auto s = castModel<SfxrInstrument>();
s->resetModels();
s->m_waveFormModel.setValue( rnd(2) );
if(s->m_waveFormModel.value()==2 && rnd(1))
s->m_waveFormModel.setValue( rnd(1) );
s->m_waveFormModel.setValue(fastRandInc(2));
if (s->m_waveFormModel.value() == 2 && oneIn(2)) { s->m_waveFormModel.setValue(fastRand() & 1); }
s->m_startFreqModel.setValue(fastRandInc(0.5f, 1.f));
s->m_minFreqModel.setValue(std::max(0.2f, s->m_startFreqModel.value() - fastRandInc(0.2f, 0.8f)));
s->m_slideModel.setValue(fastRandInc(-0.15f, -0.35f));
s->m_startFreqModel.setValue( 0.5f+frnd(0.5f) );
s->m_minFreqModel.setValue( s->m_startFreqModel.value()-0.2f-frnd(0.6f) );
if(s->m_minFreqModel.value()<0.2f)
if (oneIn(3))
{
s->m_minFreqModel.setValue(0.2f);
s->m_startFreqModel.setValue(fastRandInc(0.3f, 0.9f));
s->m_minFreqModel.setValue(fastRandInc(0.1f));
s->m_slideModel.setValue(fastRandInc(-0.65f,-0.35f));
}
s->m_slideModel.setValue( -0.15f-frnd(0.2f) );
if(rnd(2)==0)
if (oneIn(2))
{
s->m_startFreqModel.setValue( 0.3f+frnd(0.6f) );
s->m_minFreqModel.setValue( frnd(0.1f) );
s->m_slideModel.setValue( -0.35f-frnd(0.3f) );
}
if(rnd(1))
{
s->m_sqrDutyModel.setValue( frnd(0.5f) );
s->m_sqrSweepModel.setValue( 0.2f );
s->m_sqrDutyModel.setValue(fastRandInc(0.5f));
s->m_sqrSweepModel.setValue(0.2f);
}
else
{
s->m_sqrDutyModel.setValue( 0.4f+frnd(0.5f) );
s->m_sqrSweepModel.setValue( -frnd(0.7f) );
s->m_sqrDutyModel.setValue(fastRandInc(0.4f, 0.9f));
s->m_sqrSweepModel.setValue(fastRandInc(-0.7f));
}
s->m_attModel.setValue( 0.0f );
s->m_holdModel.setValue( 0.1f+frnd(0.2f) );
s->m_decModel.setValue( frnd(0.4f) );
s->m_attModel.setValue(0.f);
s->m_holdModel.setValue(fastRandInc(0.1f, 0.3f));
s->m_decModel.setValue(fastRandInc(0.4f));
if(rnd(1))
if (oneIn(2)) { s->m_susModel.setValue(fastRandInc(0.3f)); }
if (oneIn(3))
{
s->m_susModel.setValue( frnd(0.3f) );
s->m_phaserOffsetModel.setValue(fastRandInc(0.2f));
s->m_phaserSweepModel.setValue(fastRandInc(-0.2f));
}
if(rnd(2)==0)
{
s->m_phaserOffsetModel.setValue( frnd(0.2f) );
s->m_phaserSweepModel.setValue( -frnd(0.2f) );
}
if(rnd(1))
s->m_hpFilCutModel.setValue( frnd(0.3f) );
if (oneIn(2)) { s->m_hpFilCutModel.setValue(fastRandInc(0.3f)); }
}
void SfxrInstrumentView::genExplosion()
{
auto s = castModel<SfxrInstrument>();
s->resetModels();
s->m_waveFormModel.setValue( 3 );
s->m_waveFormModel.setValue(3);
if(rnd(1))
if (oneIn(2))
{
s->m_startFreqModel.setValue( 0.1f+frnd(0.4f) );
s->m_slideModel.setValue( -0.1f+frnd(0.4f) );
s->m_startFreqModel.setValue(fastRandInc(0.1f, 0.5f));
s->m_slideModel.setValue(fastRandInc(-0.1f, 0.3f));
}
else
{
s->m_startFreqModel.setValue( 0.2f+frnd(0.7f) );
s->m_slideModel.setValue( -0.2f-frnd(0.2f) );
s->m_startFreqModel.setValue(fastRandInc(0.2f, 0.9f));
s->m_slideModel.setValue(fastRandInc(-0.4f, -0.2f));
}
s->m_startFreqModel.setValue( s->m_startFreqModel.value()*s->m_startFreqModel.value() );
s->m_startFreqModel.setValue(s->m_startFreqModel.value() * s->m_startFreqModel.value());
if(rnd(4)==0)
if (oneIn(5)) { s->m_slideModel.setValue(0.0f); }
if (oneIn(3)) { s->m_repeatSpeedModel.setValue(fastRandInc(0.3f, 0.8f)); }
s->m_attModel.setValue(0.f);
s->m_holdModel.setValue(fastRandInc(0.1f, 0.4f));
s->m_decModel.setValue(0.5f);
if (oneIn(2))
{
s->m_slideModel.setValue( 0.0f );
s->m_phaserOffsetModel.setValue(fastRandInc(-0.3f, 0.6f));
s->m_phaserSweepModel.setValue(fastRandInc(-0.3f));
}
s->m_susModel.setValue(fastRandInc(0.2f, 0.8f));
if (oneIn(2))
{
s->m_vibDepthModel.setValue(fastRandInc(0.7f));
s->m_vibSpeedModel.setValue(fastRandInc(0.6f));
}
if(rnd(2)==0)
if (oneIn(3))
{
s->m_repeatSpeedModel.setValue( 0.3f+frnd(0.5f) );
s->m_changeSpeedModel.setValue(fastRandInc(0.6f, 0.9f));
s->m_changeAmtModel.setValue(fastRandInc(-0.8f, 0.8f));
}
s->m_attModel.setValue( 0.0f );
s->m_holdModel.setValue( 0.1f+frnd(0.3f) );
s->m_decModel.setValue( 0.5f );
if(rnd(1)==0)
{
s->m_phaserOffsetModel.setValue( -0.3f+frnd(0.9f) );
s->m_phaserSweepModel.setValue( -frnd(0.3f) );
}
s->m_susModel.setValue( 0.2f+frnd(0.6f) );
if(rnd(1))
{
s->m_vibDepthModel.setValue( frnd(0.7f) );
s->m_vibSpeedModel.setValue( frnd(0.6f) );
}
if(rnd(2)==0)
{
s->m_changeSpeedModel.setValue( 0.6f+frnd(0.3f) );
s->m_changeAmtModel.setValue( 0.8f-frnd(1.6f) );
}
}
void SfxrInstrumentView::genPowerup()
{
auto s = castModel<SfxrInstrument>();
s->resetModels();
if(rnd(1))
s->m_waveFormModel.setValue( 1 );
else
s->m_sqrDutyModel.setValue( frnd(0.6f) );
if(rnd(1))
if (oneIn(2)) { s->m_waveFormModel.setValue(1); }
else { s->m_sqrDutyModel.setValue(fastRandInc(0.6f)); }
if (oneIn(2))
{
s->m_startFreqModel.setValue( 0.2f+frnd(0.3f) );
s->m_slideModel.setValue( 0.1f+frnd(0.4f) );
s->m_repeatSpeedModel.setValue( 0.4f+frnd(0.4f) );
s->m_startFreqModel.setValue(fastRandInc(0.2f, 0.5f));
s->m_slideModel.setValue(fastRandInc(0.1f, 0.5f));
s->m_repeatSpeedModel.setValue(fastRandInc(0.4f, 0.8f));
}
else
{
s->m_startFreqModel.setValue( 0.2f+frnd(0.3f) );
s->m_slideModel.setValue( 0.05f+frnd(0.2f) );
if(rnd(1))
s->m_startFreqModel.setValue(fastRandInc(0.2f, 0.5f));
s->m_slideModel.setValue(fastRandInc(0.05f, 0.25f));
if (oneIn(2))
{
s->m_vibDepthModel.setValue( frnd(0.7f) );
s->m_vibSpeedModel.setValue( frnd(0.6f) );
s->m_vibDepthModel.setValue(fastRandInc(0.7f));
s->m_vibSpeedModel.setValue(fastRandInc(0.6f));
}
}
s->m_attModel.setValue( 0.0f );
s->m_holdModel.setValue( frnd(0.4f) );
s->m_decModel.setValue( 0.1f+frnd(0.4f) );
s->m_attModel.setValue(0.0f);
s->m_holdModel.setValue(fastRandInc(0.4f));
s->m_decModel.setValue(fastRandInc(0.1f, 0.5f));
}
void SfxrInstrumentView::genHit()
{
auto s = castModel<SfxrInstrument>();
s->resetModels();
s->m_waveFormModel.setValue( rnd(2) );
if(s->m_waveFormModel.value()==2)
{
s->m_waveFormModel.setValue( 3 );
}
if(s->m_waveFormModel.value()==0)
{
s->m_sqrDutyModel.setValue( frnd(0.6f) );
}
s->m_waveFormModel.setValue(fastRandInc(2));
if (s->m_waveFormModel.value() == 2) { s->m_waveFormModel.setValue(3); }
if (s->m_waveFormModel.value() == 0) { s->m_sqrDutyModel.setValue(fastRandInc(0.6f)); }
s->m_startFreqModel.setValue( 0.2f+frnd(0.6f) );
s->m_slideModel.setValue( -0.3f-frnd(0.4f) );
s->m_attModel.setValue( 0.0f );
s->m_holdModel.setValue( frnd(0.1f) );
s->m_decModel.setValue( 0.1f+frnd(0.2f) );
if(rnd(1))
{
s->m_hpFilCutModel.setValue( frnd(0.3f) );
}
s->m_startFreqModel.setValue(fastRandInc(0.2f, 0.8f));
s->m_slideModel.setValue(fastRandInc(-0.7f, -0.3f));
s->m_attModel.setValue(0.f);
s->m_holdModel.setValue(fastRandInc(0.1f));
s->m_decModel.setValue(fastRandInc(0.1f, 0.3f));
if (oneIn(2)) { s->m_hpFilCutModel.setValue(fastRandInc(0.3f)); }
}
void SfxrInstrumentView::genJump()
{
auto s = castModel<SfxrInstrument>();
s->resetModels();
s->m_waveFormModel.setValue( 0 );
s->m_sqrDutyModel.setValue( frnd(0.6f) );
s->m_waveFormModel.setValue(0);
s->m_sqrDutyModel.setValue(fastRandInc(0.6f));
s->m_startFreqModel.setValue( 0.3f+frnd(0.3f) );
s->m_slideModel.setValue( 0.1f+frnd(0.2f) );
s->m_startFreqModel.setValue(fastRandInc(0.3f, 0.6f));
s->m_slideModel.setValue(fastRandInc(0.1f, 0.3f));
s->m_attModel.setValue( 0.0f );
s->m_holdModel.setValue( 0.1f+frnd(0.3f) );
s->m_decModel.setValue( 0.1f+frnd(0.2f) );
if(rnd(1))
{
s->m_hpFilCutModel.setValue( frnd(0.3f) );
}
if(rnd(1))
{
s->m_lpFilCutModel.setValue( 1.0f-frnd(0.6f) );
}
s->m_attModel.setValue(0.0f);
s->m_holdModel.setValue(fastRandInc(0.1f, 0.4f));
s->m_decModel.setValue(fastRandInc(0.1f, 0.3f));
if (oneIn(2)) { s->m_hpFilCutModel.setValue(fastRandInc(0.3f)); }
if (oneIn(2)) { s->m_lpFilCutModel.setValue(fastRandInc(0.4f, 1.f)); }
}
void SfxrInstrumentView::genBlip()
{
auto s = castModel<SfxrInstrument>();
s->resetModels();
s->m_waveFormModel.setValue( rnd(1) );
if( s->m_waveFormModel.value()==0 )
{
s->m_sqrDutyModel.setValue( frnd(0.6f) );
}
s->m_waveFormModel.setValue(fastRand() & 1);
if (s->m_waveFormModel.value() == 0) { s->m_sqrDutyModel.setValue(fastRandInc(0.6f)); }
s->m_startFreqModel.setValue( 0.2f+frnd(0.4f) );
s->m_attModel.setValue( 0.0f );
s->m_holdModel.setValue( 0.1f+frnd(0.1f) );
s->m_decModel.setValue( frnd(0.2f) );
s->m_hpFilCutModel.setValue( 0.1f );
s->m_startFreqModel.setValue(fastRandInc(0.2f, 0.6f));
s->m_attModel.setValue(0.f);
s->m_holdModel.setValue(fastRandInc(0.1f, 0.2f));
s->m_decModel.setValue(fastRandInc(0.2f));
s->m_hpFilCutModel.setValue(0.1f);
}
namespace
{
// HACK This expands pow_hack<3>(5) to (5 * 5 * 5) to avoid actual pow()
template <unsigned N> constexpr auto pow_hack(float x) { return x * pow_hack<N - 1>(x); }
template <> constexpr auto pow_hack<1>(float x) { return x; }
}
void SfxrInstrumentView::randomize()
{
auto s = castModel<SfxrInstrument>();
s->m_startFreqModel.setValue(std::pow(frnd(2.0f) - 1.0f, 2.0f));
if(rnd(1))
s->m_startFreqModel.setValue(pow_hack<2>(fastRandInc(-1.f, 1.f)));
if (oneIn(2))
{
s->m_startFreqModel.setValue(std::pow(frnd(2.0f) - 1.0f, 3.0f) + 0.5f);
}
s->m_minFreqModel.setValue( 0.0f );
s->m_slideModel.setValue(std::pow(frnd(2.0f) - 1.0f, 5.0f));
if( s->m_startFreqModel.value()>0.7f && s->m_slideModel.value()>0.2f )
{
s->m_slideModel.setValue( -s->m_slideModel.value() );
}
if( s->m_startFreqModel.value()<0.2f && s->m_slideModel.value()<-0.05f )
{
s->m_slideModel.setValue( -s->m_slideModel.value() );
}
s->m_dSlideModel.setValue(std::pow(frnd(2.0f) - 1.0f, 3.0f));
s->m_sqrDutyModel.setValue( frnd(2.0f)-1.0f );
s->m_sqrSweepModel.setValue(std::pow(frnd(2.0f) - 1.0f, 3.0f));
s->m_vibDepthModel.setValue(std::pow(frnd(2.0f) - 1.0f, 3.0f));
s->m_vibSpeedModel.setValue( frnd(2.0f)-1.0f );
//s->m_vibDelayModel.setValue( frnd(2.0f)-1.0f );
s->m_attModel.setValue(std::pow(frnd(2.0f) - 1.0f, 3.0f));
s->m_holdModel.setValue(std::pow(frnd(2.0f) - 1.0f, 2.0f));
s->m_decModel.setValue( frnd(2.0f)-1.0f );
s->m_susModel.setValue(std::pow(frnd(0.8f), 2.0f));
if(s->m_attModel.value()+s->m_holdModel.value()+s->m_decModel.value()<0.2f)
{
s->m_holdModel.setValue( s->m_holdModel.value()+0.2f+frnd(0.3f) );
s->m_decModel.setValue( s->m_decModel.value()+0.2f+frnd(0.3f) );
s->m_startFreqModel.setValue(pow_hack<3>(fastRandInc(-1.f, 1.f)) + 0.5f);
}
s->m_lpFilResoModel.setValue( frnd(2.0f)-1.0f );
s->m_lpFilCutModel.setValue(1.0f - std::pow(frnd(1.0f), 3.0f));
s->m_lpFilCutSweepModel.setValue(std::pow(frnd(2.0f) - 1.0f, 3.0f));
if(s->m_lpFilCutModel.value()<0.1f && s->m_lpFilCutSweepModel.value()<-0.05f)
s->m_minFreqModel.setValue(0.0f);
s->m_slideModel.setValue(pow_hack<5>(fastRandInc(-1.f, 1.f)));
if (s->m_startFreqModel.value() > 0.7f && s->m_slideModel.value() > 0.2f)
{
s->m_lpFilCutSweepModel.setValue( -s->m_lpFilCutSweepModel.value() );
s->m_slideModel.setValue(-s->m_slideModel.value());
}
s->m_hpFilCutModel.setValue(std::pow(frnd(1.0f), 5.0f));
s->m_hpFilCutSweepModel.setValue(std::pow(frnd(2.0f) - 1.0f, 5.0f));
s->m_phaserOffsetModel.setValue(std::pow(frnd(2.0f) - 1.0f, 3.0f));
s->m_phaserSweepModel.setValue(std::pow(frnd(2.0f) - 1.0f, 3.0f));
if (s->m_startFreqModel.value() < 0.2f && s->m_slideModel.value() < -0.05f)
{
s->m_slideModel.setValue(-s->m_slideModel.value());
}
s->m_repeatSpeedModel.setValue( frnd(2.0f)-1.0f );
s->m_dSlideModel.setValue(pow_hack<3>(fastRandInc(-1.f, 1.f)));
s->m_changeSpeedModel.setValue( frnd(2.0f)-1.0f );
s->m_changeAmtModel.setValue( frnd(2.0f)-1.0f );
s->m_sqrDutyModel.setValue(fastRandInc(-1.f, 1.f));
s->m_sqrSweepModel.setValue(pow_hack<3>(fastRandInc(-1.f, 1.f)));
s->m_vibDepthModel.setValue(pow_hack<3>(fastRandInc(-1.f, 1.f)));
s->m_vibSpeedModel.setValue(fastRandInc(-1.f, 1.f));
//s->m_vibDelayModel.setValue(fastRand(-1.f, 1.f));
s->m_attModel.setValue(pow_hack<3>(fastRandInc(-1.f, 1.f)));
s->m_holdModel.setValue(pow_hack<2>(fastRandInc(-1.f, 1.f)));
s->m_decModel.setValue(fastRandInc(-1.f, 1.f));
s->m_susModel.setValue(pow_hack<2>(fastRandInc(0.8f)));
if (s->m_attModel.value() + s->m_holdModel.value() + s->m_decModel.value() < 0.2f)
{
s->m_holdModel.setValue(s->m_holdModel.value() + fastRandInc(0.2f, 0.5f));
s->m_decModel.setValue(s->m_decModel.value() + fastRandInc(0.2f, 0.5f));
}
s->m_lpFilResoModel.setValue(fastRandInc(-1.f, 1.f));
s->m_lpFilCutModel.setValue(1.0f - pow_hack<3>(fastRandInc(1.f)));
s->m_lpFilCutSweepModel.setValue(pow_hack<3>(fastRandInc(-1.f, 1.f)));
if (s->m_lpFilCutModel.value() < 0.1f && s->m_lpFilCutSweepModel.value() < -0.05f)
{
s->m_lpFilCutSweepModel.setValue(-s->m_lpFilCutSweepModel.value());
}
s->m_hpFilCutModel.setValue(pow_hack<5>(fastRandInc(1.f)));
s->m_hpFilCutSweepModel.setValue(pow_hack<5>(fastRandInc(-1.f, 1.f)));
s->m_phaserOffsetModel.setValue(pow_hack<3>(fastRandInc(-1.f, 1.f)));
s->m_phaserSweepModel.setValue(pow_hack<3>(fastRandInc(-1.f, 1.f)));
s->m_repeatSpeedModel.setValue(fastRandInc(-1.f, 1.f));
s->m_changeSpeedModel.setValue(fastRandInc(-1.f, 1.f));
s->m_changeAmtModel.setValue(fastRandInc(-1.f, 1.f));
}
void SfxrInstrumentView::mutate()
{
auto s = castModel<SfxrInstrument>();
if(rnd(1)) s->m_startFreqModel.setValue( s->m_startFreqModel.value()+frnd(0.1f)-0.05f );
// if(rnd(1)) s->m_minFreqModel.setValue( s->m_minFreqModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_slideModel.setValue( s->m_slideModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_dSlideModel.setValue( s->m_dSlideModel.value()+frnd(0.1f)-0.05f );
if (oneIn(2)) { s->m_startFreqModel.setValue(s->m_startFreqModel.value() + fastRandInc(-0.05f, 0.05f)); }
// if (oneIn(2)) { s->m_minFreqModel.setValue(s->m_minFreqModel.value() + fastRand(-0.05f, 0.05f))); }
if (oneIn(2)) { s->m_slideModel.setValue( s->m_slideModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_dSlideModel.setValue( s->m_dSlideModel.value() + fastRandInc(-0.05f, 0.05f)); }
if(rnd(1)) s->m_sqrDutyModel.setValue( s->m_sqrDutyModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_sqrSweepModel.setValue( s->m_sqrSweepModel.value()+frnd(0.1f)-0.05f );
if (oneIn(2)) { s->m_sqrDutyModel.setValue( s->m_sqrDutyModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_sqrSweepModel.setValue( s->m_sqrSweepModel.value() + fastRandInc(-0.05f, 0.05f)); }
if(rnd(1)) s->m_vibDepthModel.setValue( s->m_vibDepthModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_vibSpeedModel.setValue( s->m_vibSpeedModel.value()+frnd(0.1f)-0.05f );
// if(rnd(1)) s->m_vibDelayModel.setValue( s->m_vibDelayModel.value()+frnd(0.1f)-0.05f );
if (oneIn(2)) { s->m_vibDepthModel.setValue( s->m_vibDepthModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_vibSpeedModel.setValue( s->m_vibSpeedModel.value() + fastRandInc(-0.05f, 0.05f)); }
// if (oneIn(2)) { s->m_vibDelayModel.setValue( s->m_vibDelayModel.value() + fastRand(-0.05f, 0.05f))); }
if(rnd(1)) s->m_attModel.setValue( s->m_attModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_holdModel.setValue( s->m_holdModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_decModel.setValue( s->m_decModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_susModel.setValue( s->m_susModel.value()+frnd(0.1f)-0.05f );
if (oneIn(2)) { s->m_attModel.setValue( s->m_attModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_holdModel.setValue( s->m_holdModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_decModel.setValue( s->m_decModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_susModel.setValue( s->m_susModel.value() + fastRandInc(-0.05f, 0.05f)); }
if(rnd(1)) s->m_lpFilResoModel.setValue( s->m_lpFilResoModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_lpFilCutModel.setValue( s->m_lpFilCutModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_lpFilCutSweepModel.setValue( s->m_lpFilCutSweepModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_hpFilCutModel.setValue( s->m_hpFilCutModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_hpFilCutSweepModel.setValue( s->m_hpFilCutSweepModel.value()+frnd(0.1f)-0.05f );
if (oneIn(2)) { s->m_lpFilResoModel.setValue( s->m_lpFilResoModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_lpFilCutModel.setValue( s->m_lpFilCutModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_lpFilCutSweepModel.setValue( s->m_lpFilCutSweepModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_hpFilCutModel.setValue( s->m_hpFilCutModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_hpFilCutSweepModel.setValue( s->m_hpFilCutSweepModel.value() + fastRandInc(-0.05f, 0.05f)); }
if(rnd(1)) s->m_phaserOffsetModel.setValue( s->m_phaserOffsetModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_phaserSweepModel.setValue( s->m_phaserSweepModel.value()+frnd(0.1f)-0.05f );
if (oneIn(2)) { s->m_phaserOffsetModel.setValue( s->m_phaserOffsetModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_phaserSweepModel.setValue( s->m_phaserSweepModel.value() + fastRandInc(-0.05f, 0.05f)); }
if(rnd(1)) s->m_repeatSpeedModel.setValue( s->m_repeatSpeedModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_changeSpeedModel.setValue( s->m_changeSpeedModel.value()+frnd(0.1f)-0.05f );
if(rnd(1)) s->m_changeAmtModel.setValue( s->m_changeAmtModel.value()+frnd(0.1f)-0.05f );
if (oneIn(2)) { s->m_repeatSpeedModel.setValue( s->m_repeatSpeedModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_changeSpeedModel.setValue( s->m_changeSpeedModel.value() + fastRandInc(-0.05f, 0.05f)); }
if (oneIn(2)) { s->m_changeAmtModel.setValue( s->m_changeAmtModel.value() + fastRandInc(-0.05f, 0.05f)); }
}
void SfxrInstrumentView::previewSound()
{
auto s = castModel<SfxrInstrument>();

View File

@@ -23,13 +23,12 @@
*
*/
#include <sid.h>
#include <cmath>
#include <cstdio>
#include <sid.h>
#include "SidInstrument.h"
#include "AudioEngine.h"
#include "Engine.h"
@@ -37,20 +36,21 @@
#include "Knob.h"
#include "NotePlayHandle.h"
#include "PixmapButton.h"
#include "lmms_math.h"
#include "embed.h"
#include "plugin_export.h"
namespace
{
inline constexpr auto C64_PAL_CYCLES_PER_SEC = 985248;
inline constexpr auto NUMSIDREGS = 0x19;
inline constexpr auto SIDWRITEDELAY = 9; // lda $xxxx,x 4 cycles, sta $d400,x 5 cycles
inline constexpr auto SIDWAVEDELAY = 4; // and $xxxx,x 4 cycles extra
}
namespace lmms
{
#define C64_PAL_CYCLES_PER_SEC 985248
#define NUMSIDREGS 0x19
#define SIDWRITEDELAY 9 // lda $xxxx,x 4 cycles, sta $d400,x 5 cycles
#define SIDWAVEDELAY 4 // and $xxxx,x 4 cycles extra
auto sidorder = std::array<unsigned char, 25>
{0x15,0x16,0x18,0x17,
0x05,0x06,0x02,0x03,0x00,0x01,0x04,
@@ -238,56 +238,49 @@ float SidInstrument::desiredReleaseTimeMs() const
static int sid_fillbuffer(unsigned char* sidreg, reSID::SID *sid, int tdelta, short *ptr, int samples)
{
int total = 0;
// customly added
int residdelay = 0;
int total = 0;
int badline = fastRand(NUMSIDREGS);
int residdelay = 0; // customly added
int badline = rand() % NUMSIDREGS;
for (int c = 0; c < NUMSIDREGS; ++c)
{
unsigned char o = sidorder[c];
for (int c = 0; c < NUMSIDREGS; c++)
{
unsigned char o = sidorder[c];
// Extra delay for loading the waveform (and mt_chngate,x)
if (o == 4 || o == 11 || o == 18)
{
auto dt = SIDWAVEDELAY;
const int result = sid->clock(dt, ptr, samples);
total += result;
ptr += result;
samples -= result;
tdelta -= SIDWAVEDELAY;
}
// Extra delay for loading the waveform (and mt_chngate,x)
if ((o == 4) || (o == 11) || (o == 18))
{
int tdelta2 = SIDWAVEDELAY;
int result = sid->clock(tdelta2, ptr, samples);
total += result;
ptr += result;
samples -= result;
tdelta -= SIDWAVEDELAY;
}
// Possible random badline delay once per writing
if (badline == c && residdelay)
{
auto dt = residdelay;
const int result = sid->clock(dt, ptr, samples);
total += result;
ptr += result;
samples -= result;
tdelta -= residdelay;
}
// Possible random badline delay once per writing
if ((badline == c) && (residdelay))
{
int tdelta2 = residdelay;
int result = sid->clock(tdelta2, ptr, samples);
total += result;
ptr += result;
samples -= result;
tdelta -= residdelay;
}
sid->write(o, sidreg[o]);
sid->write(o, sidreg[o]);
int tdelta2 = SIDWRITEDELAY;
int result = sid->clock(tdelta2, ptr, samples);
total += result;
ptr += result;
samples -= result;
tdelta -= SIDWRITEDELAY;
}
int result = sid->clock(tdelta, ptr, samples);
total += result;
return total;
auto dt = SIDWRITEDELAY;
const int result = sid->clock(dt, ptr, samples);
total += result;
ptr += result;
samples -= result;
tdelta -= SIDWRITEDELAY;
}
return total + sid->clock(tdelta, ptr, samples);
}
void SidInstrument::playNote( NotePlayHandle * _n,
SampleFrame* _working_buffer )
{

View File

@@ -729,17 +729,18 @@ std::vector<std::pair<float, std::string>> SaSpectrumView::makeLogAmpTics(int lo
// Base zoom level on selected range and how close is the current height
// to the sizeHint() (denser scale for bigger window).
if ((high - low) < 20 * ((float)height() / sizeHint().height()))
const float heightScale = static_cast<float>(height()) / sizeHint().height();
if ((high - low) < 20 * heightScale)
{
increment = fastPow10f(0.3f); // 3 dB steps when really zoomed in
increment = fastPow10f(0.3); // 3 dB steps when really zoomed in
}
else if (high - low < 45 * ((float)height() / sizeHint().height()))
else if ((high - low) < 45 * heightScale)
{
increment = fastPow10f(0.6f); // 6 dB steps when sufficiently zoomed in
increment = fastPow10f(0.6); // 6 dB steps when sufficiently zoomed in
}
else
{
increment = 10; // 10 dB steps otherwise
increment = 10.0; // 10 dB steps otherwise
}
// Generate n dB increments, start checking at -90 dB. Limits are tweaked

View File

@@ -307,26 +307,26 @@ void MalletsInstrument::playNote( NotePlayHandle * _n,
if (p < 9)
{
hardness += random * fastRand(-64.f, +64.f);
hardness += random * fastRandInc(-64.f, 64.f);
hardness = std::clamp(hardness, 0.0f, 128.0f);
position += random * fastRand(-32.f, +32.f);
position += random * fastRandInc(-32.f, 32.f);
position = std::clamp(position, 0.0f, 64.0f);
}
else if (p == 9)
{
modulator += random * fastRand(-64.f, +64.f);
modulator += random * fastRandInc(-64.f, 64.f);
modulator = std::clamp(modulator, 0.0f, 128.0f);
crossfade += random * fastRand(-64.f, +64.f);
crossfade += random * fastRandInc(-64.f, 64.f);
crossfade = std::clamp(crossfade, 0.0f, 128.0f);
}
else
{
pressure += random * fastRand(-64.f, +64.f);
pressure += random * fastRandInc(-64.f, 64.f);
pressure = std::clamp(pressure, 0.0f, 128.0f);
speed += random * fastRand(-64.f, +64.f);
speed += random * fastRandInc(-64.f, 64.f);
speed = std::clamp(speed, 0.0f, 128.0f);
}

View File

@@ -40,7 +40,7 @@ VibratingString::VibratingString(float pitch, float pick, float pickup, const fl
m_oversample{2 * oversample / static_cast<int>(sampleRate / Engine::audioEngine()->baseSampleRate())},
m_randomize{randomize},
m_stringLoss{1.0f - stringLoss},
m_choice{static_cast<int>(m_oversample * static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX))},
m_choice(fastRandInc(m_oversample)),
m_state{0.1f},
m_outsamp{std::make_unique<sample_t[]>(m_oversample)}
{
@@ -78,9 +78,7 @@ std::unique_ptr<VibratingString::DelayLine> VibratingString::initDelayLine(int l
dl->data = std::make_unique<sample_t[]>(len);
for (int i = 0; i < dl->length; ++i)
{
float r = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
float offset = (m_randomize / 2.0f - m_randomize) * r;
dl->data[i] = offset;
dl->data[i] = fastRandInc(m_randomize / 2.0f - m_randomize);
}
}
else

View File

@@ -29,6 +29,7 @@
#include <cstdlib>
#include "LmmsTypes.h"
#include "lmms_math.h"
namespace lmms
{
@@ -103,19 +104,16 @@ private:
*/
void setDelayLine(DelayLine* dl, int pick, const float* values, int len, float scale, bool state)
{
const auto randAmt = m_randomize / 2.f - m_randomize;
if (!state)
{
for (int i = 0; i < pick; ++i)
{
float r = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
float offset = (m_randomize / 2.0f - m_randomize) * r;
dl->data[i] = scale * values[dl->length - i - 1] + offset;
dl->data[i] = scale * values[dl->length - i - 1] + fastRandInc(randAmt);
}
for (int i = pick; i < dl->length; ++i)
{
float r = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
float offset = (m_randomize / 2.0f - m_randomize) * r;
dl->data[i] = scale * values[i - pick] + offset;
dl->data[i] = scale * values[i - pick] + fastRandInc(randAmt);
}
}
else
@@ -124,18 +122,14 @@ private:
{
for (int i = pick; i < dl->length; ++i)
{
float r = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
float offset = (m_randomize / 2.0f - m_randomize) * r;
dl->data[i] = scale * values[i - pick] + offset;
dl->data[i] = scale * values[i - pick] + fastRandInc(randAmt);
}
}
else
{
for (int i = 0; i < len; ++i)
{
float r = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
float offset = (m_randomize / 2.0f - m_randomize) * r;
dl->data[i+pick] = scale * values[i] + offset;
dl->data[i+pick] = scale * values[i] + fastRandInc(randAmt);
}
}
}

View File

@@ -294,8 +294,6 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa
long Length, tpos = 0, tplus, totmp, t, i, j;
float x[3] = {0.f, 0.f, 0.f};
float MasterTune;
constexpr float randmax = 1.f / static_cast<float>(RAND_MAX);
constexpr float randmax2 = 2.f / static_cast<float>(RAND_MAX);
int MainFilter, HighPass;
long NON, NT, TON, DiON, TDroop = 0, DStep;
@@ -366,7 +364,7 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa
timestretch *= Fs / 44100.f;
DGain = 1.0f; // leave this here!
DGain = fastPow10f(0.05 * GetPrivateProfileFloat(sec, "Level", 0, dsfile));
DGain = fastPow10f(0.05f * GetPrivateProfileFloat(sec, "Level", 0, dsfile));
MasterTune = GetPrivateProfileFloat(sec, "Tuning", 0.0, dsfile);
MasterTune = std::pow(1.0594631f, MasterTune + mem_tune);
@@ -399,9 +397,6 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa
g = NL;
}
// if(GetPrivateProfileInt(sec,"FixedSeq",0,dsfile)!=0)
// srand(1); //fixed random sequence
// read tone parameters
std::strcpy(sec, "Tone");
chkOn[0] = GetPrivateProfileInt(sec, "On", 0, dsfile);
@@ -520,7 +515,7 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa
DAtten = DGain * static_cast<short>(LoudestEnv());
clippoint = DAtten > 32700 ? 32700 : static_cast<short>(DAtten);
DAtten = std::exp2(2.0 * GetPrivateProfileInt(sec, "Bits", 0, dsfile));
DGain = DAtten * DGain * fastPow10f(0.05 * GetPrivateProfileInt(sec, "Clipping", 0, dsfile));
DGain = DAtten * DGain * fastPow10f(0.05f * GetPrivateProfileInt(sec, "Clipping", 0, dsfile));
}
// prepare envelopes
@@ -596,7 +591,7 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa
}
x[2] = x[1];
x[1] = x[0];
x[0] = (randmax2 * static_cast<float>(rand())) - 1.f;
x[0] = fastRandInc(-1.f, 1.f);
TT = a * x[0] + b * x[1] + c * x[2] + d * TT;
DF[t - tpos] = TT * g * envData[2][ENV];
}
@@ -671,7 +666,7 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa
}
if ((t % BFStep) == 0)
{
BdF = randmax * static_cast<float>(rand()) - 0.5f;
BdF = fastRandInc(-0.5f, 0.5f);
}
BPhi = BPhi + BF + BQ * BdF;
botmp = t - tpos;
@@ -697,7 +692,7 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sa
}
if ((t % BFStep2) == 0)
{
BdF2 = randmax * static_cast<float>(rand()) - 0.5f;
BdF2 = fastRandInc(-0.5f, 0.5f);
}
BPhi2 = BPhi2 + BF2 + BQ2 * BdF2;
botmp = t - tpos;

View File

@@ -28,6 +28,7 @@
#include "embed.h"
#include "Engine.h"
#include "InstrumentTrack.h"
#include "lmms_math.h"
#include "PresetPreviewPlayHandle.h"
#include <vector>
@@ -414,28 +415,20 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
frames_processed += remaining_frames_for_cur_arp;
// Skip notes randomly
if( m_arpSkipModel.value() )
if (m_arpSkipModel.value() && fastRandInc(100.f) <= m_arpSkipModel.value())
{
if (100 * static_cast<float>(rand()) / (static_cast<float>(RAND_MAX) + 1.0f) < m_arpSkipModel.value())
{
// update counters
frames_processed += arp_frames;
cur_frame += arp_frames;
continue;
}
frames_processed += arp_frames;
cur_frame += arp_frames;
continue;
}
auto dir = static_cast<ArpDirection>(m_arpDirectionModel.value());
// Miss notes randomly. We intercept int dir and abuse it
// after need. :)
if( m_arpMissModel.value() )
if (m_arpMissModel.value() && fastRandInc(100.f) <= m_arpMissModel.value())
{
if (100 * static_cast<float>(rand()) / (static_cast<float>(RAND_MAX) + 1.0f) < m_arpMissModel.value())
{
dir = ArpDirection::Random;
}
dir = ArpDirection::Random;
}
int cur_arp_idx = 0;
@@ -461,7 +454,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
else if( dir == ArpDirection::Random )
{
// just pick a random chord-index
cur_arp_idx = static_cast<int>(range * static_cast<float>(rand()) / static_cast<float>(RAND_MAX));
cur_arp_idx = fastRandInc(range);
}
// Divide cur_arp_idx with wanted repeats. The repeat feature will not affect random notes.

View File

@@ -189,7 +189,7 @@ PeakController * PeakController::getControllerBySetting(const QDomElement & _thi
int effectId = _this.attribute( "effectId" ).toInt();
//Backward compatibility for bug in <= 0.4.15 . For >= 1.0.0 ,
//foundCount should always be 1 because m_effectId is initialized with rand()
//foundCount should always be 1 because m_effectId is initialized with fastRand()
int foundCount = 0;
if( m_buggedFile == false )
{

View File

@@ -28,6 +28,7 @@
#include "ProjectJournal.h"
#include "Engine.h"
#include "JournallingObject.h"
#include "lmms_math.h"
#include "Song.h"
#include "AutomationClip.h"
@@ -135,24 +136,15 @@ void ProjectJournal::addJournalCheckPoint( JournallingObject *jo )
}
jo_id_t ProjectJournal::allocID( JournallingObject * _obj )
jo_id_t ProjectJournal::allocID(JournallingObject* obj)
{
jo_id_t id;
for( jo_id_t tid = rand(); m_joIDs.contains( id = tid % EO_ID_MSB
| EO_ID_MSB ); tid++ )
{
}
m_joIDs[id] = _obj;
//printf("new id: %d\n", id );
for (jo_id_t tid = fastRand(); m_joIDs.contains(id = tid % EO_ID_MSB | EO_ID_MSB); tid++) {}
m_joIDs[id] = obj;
return id;
}
void ProjectJournal::reallocID( const jo_id_t _id, JournallingObject * _obj )
{
//printf("realloc %d %d\n", _id, _obj );

View File

@@ -46,6 +46,7 @@
#include "GuiApplication.h"
#include "Knob.h"
#include "LcdWidget.h"
#include "lmms_math.h"
#include "Mixer.h"
#include "MixerView.h"
#include "PeakIndicator.h"
@@ -322,7 +323,7 @@ void MixerChannelView::selectColor()
void MixerChannelView::randomizeColor()
{
auto channel = mixerChannel();
channel->setColor(ColorChooser::getPalette(ColorChooser::Palette::Mixer)[rand() % 48]);
channel->setColor(ColorChooser::getPalette(ColorChooser::Palette::Mixer)[fastRand(48)]);
Engine::getSong()->setModified();
update();
}

View File

@@ -40,6 +40,7 @@
#include "embed.h"
#include "GuiApplication.h"
#include "KeyboardShortcuts.h"
#include "lmms_math.h"
#include "MidiClipView.h"
#include "PatternClip.h"
#include "PatternStore.h"
@@ -353,7 +354,7 @@ void ClipView::selectColor()
void ClipView::randomizeColor()
{
setColor(ColorChooser::getPalette(ColorChooser::Palette::Mixer)[std::rand() % 48]);
setColor(ColorChooser::getPalette(ColorChooser::Palette::Mixer)[fastRand(48)]);
}
void ClipView::resetColor()

View File

@@ -41,6 +41,7 @@
#include "embed.h"
#include "Engine.h"
#include "InstrumentTrackView.h"
#include "lmms_math.h"
#include "KeyboardShortcuts.h"
#include "Song.h"
#include "StringPairDrag.h"
@@ -270,7 +271,7 @@ void TrackOperationsWidget::resetTrackColor()
void TrackOperationsWidget::randomizeTrackColor()
{
QColor buffer = ColorChooser::getPalette( ColorChooser::Palette::Track )[ rand() % 48 ];
QColor buffer = ColorChooser::getPalette(ColorChooser::Palette::Track)[fastRand(48)];
auto track = m_trackView->getTrack();
track->addJournalCheckPoint();
track->setColor(buffer);