Merge branch 'master' into sample-recording
This commit is contained in:
@@ -57,7 +57,7 @@ AmplifierEffect::AmplifierEffect(Model* parent, const Descriptor::SubPluginFeatu
|
||||
}
|
||||
|
||||
|
||||
bool AmplifierEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
|
||||
bool AmplifierEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
|
||||
{
|
||||
if (!isEnabled() || !isRunning()) { return false ; }
|
||||
|
||||
@@ -80,14 +80,14 @@ bool AmplifierEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
|
||||
const float panLeft = std::min(1.0f, 1.0f - pan);
|
||||
const float panRight = std::min(1.0f, 1.0f + pan);
|
||||
|
||||
auto s = std::array{buf[f][0], buf[f][1]};
|
||||
auto& currentFrame = buf[f];
|
||||
|
||||
s[0] *= volume * left * panLeft;
|
||||
s[1] *= volume * right * panRight;
|
||||
const auto s = currentFrame * SampleFrame(left * panLeft, right * panRight) * volume;
|
||||
|
||||
buf[f][0] = d * buf[f][0] + w * s[0];
|
||||
buf[f][1] = d * buf[f][1] + w * s[1];
|
||||
outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1];
|
||||
// Dry/wet mix
|
||||
currentFrame = currentFrame * d + s * w;
|
||||
|
||||
outSum += currentFrame.sumOfSquaredAmplitudes();
|
||||
}
|
||||
|
||||
checkGate(outSum / frames);
|
||||
|
||||
@@ -37,7 +37,7 @@ class AmplifierEffect : public Effect
|
||||
public:
|
||||
AmplifierEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
|
||||
~AmplifierEffect() override = default;
|
||||
bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override;
|
||||
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
|
||||
@@ -105,7 +105,7 @@ AudioFileProcessor::AudioFileProcessor( InstrumentTrack * _instrument_track ) :
|
||||
|
||||
|
||||
void AudioFileProcessor::playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer )
|
||||
SampleFrame* _working_buffer )
|
||||
{
|
||||
const fpp_t frames = _n->framesLeftForCurrentPeriod();
|
||||
const f_cnt_t offset = _n->noteOffset();
|
||||
@@ -165,7 +165,7 @@ void AudioFileProcessor::playNote( NotePlayHandle * _n,
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( _working_buffer, 0, ( frames + offset ) * sizeof( sampleFrame ) );
|
||||
zeroSampleFrames(_working_buffer, frames + offset);
|
||||
emit isPlaying( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
AudioFileProcessor( InstrumentTrack * _instrument_track );
|
||||
|
||||
void playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer ) override;
|
||||
SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
void saveSettings(QDomDocument& doc, QDomElement& elem) override;
|
||||
|
||||
@@ -69,7 +69,7 @@ BassBoosterEffect::BassBoosterEffect( Model* parent, const Descriptor::SubPlugin
|
||||
|
||||
|
||||
|
||||
bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
bool BassBoosterEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
@@ -91,23 +91,19 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
const float d = dryLevel();
|
||||
const float w = wetLevel();
|
||||
|
||||
for( fpp_t f = 0; f < frames; ++f )
|
||||
for (fpp_t f = 0; f < frames; ++f)
|
||||
{
|
||||
float gain = const_gain;
|
||||
if (gainBuffer) {
|
||||
//process period using sample exact data
|
||||
gain = gainBuffer->value( f );
|
||||
}
|
||||
//float gain = gainBuffer ? gainBuffer[f] : gain;
|
||||
m_bbFX.leftFX().setGain( gain );
|
||||
m_bbFX.rightFX().setGain( gain);
|
||||
auto& currentFrame = buf[f];
|
||||
|
||||
auto s = std::array{buf[f][0], buf[f][1]};
|
||||
m_bbFX.nextSample( s[0], s[1] );
|
||||
// Process copy of current sample frame
|
||||
m_bbFX.setGain(gainBuffer ? gainBuffer->value(f) : const_gain);
|
||||
auto s = currentFrame;
|
||||
m_bbFX.nextSample(s);
|
||||
|
||||
buf[f][0] = d * buf[f][0] + w * s[0];
|
||||
buf[f][1] = d * buf[f][1] + w * s[1];
|
||||
outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1];
|
||||
// Dry/wet mix
|
||||
currentFrame = currentFrame * d + s * w;
|
||||
|
||||
outSum += currentFrame.sumOfSquaredAmplitudes();
|
||||
}
|
||||
|
||||
checkGate( outSum / frames );
|
||||
|
||||
@@ -38,7 +38,7 @@ class BassBoosterEffect : public Effect
|
||||
public:
|
||||
BassBoosterEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
|
||||
~BassBoosterEffect() override = default;
|
||||
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
|
||||
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
|
||||
@@ -256,7 +256,7 @@ QString BitInvader::nodeName() const
|
||||
|
||||
|
||||
void BitInvader::playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer )
|
||||
SampleFrame* _working_buffer )
|
||||
{
|
||||
if (!_n->m_pluginData)
|
||||
{
|
||||
@@ -274,11 +274,7 @@ void BitInvader::playNote( NotePlayHandle * _n,
|
||||
auto ps = static_cast<BSynth*>(_n->m_pluginData);
|
||||
for( fpp_t frame = offset; frame < frames + offset; ++frame )
|
||||
{
|
||||
const sample_t cur = ps->nextStringSample( m_graph.length() );
|
||||
for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
_working_buffer[frame][chnl] = cur;
|
||||
}
|
||||
_working_buffer[frame] = SampleFrame(ps->nextStringSample(m_graph.length()));
|
||||
}
|
||||
|
||||
applyRelease( _working_buffer, _n );
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
~BitInvader() override = default;
|
||||
|
||||
void playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer ) override;
|
||||
SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ BitcrushEffect::BitcrushEffect( Model * parent, const Descriptor::SubPluginFeatu
|
||||
m_sampleRate( Engine::audioEngine()->outputSampleRate() ),
|
||||
m_filter( m_sampleRate )
|
||||
{
|
||||
m_buffer = new sampleFrame[Engine::audioEngine()->framesPerPeriod() * OS_RATE];
|
||||
m_buffer = new SampleFrame[Engine::audioEngine()->framesPerPeriod() * OS_RATE];
|
||||
m_filter.setLowpass( m_sampleRate * ( CUTOFF_RATIO * OS_RATIO ) );
|
||||
m_needsUpdate = true;
|
||||
|
||||
@@ -100,7 +100,7 @@ inline float BitcrushEffect::noise( float amt )
|
||||
return fastRandf( amt * 2.0f ) - amt;
|
||||
}
|
||||
|
||||
bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
bool BitcrushEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
|
||||
@@ -41,7 +41,7 @@ class BitcrushEffect : public Effect
|
||||
public:
|
||||
BitcrushEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
|
||||
~BitcrushEffect() override;
|
||||
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
|
||||
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
@@ -55,7 +55,7 @@ private:
|
||||
|
||||
BitcrushControls m_controls;
|
||||
|
||||
sampleFrame * m_buffer;
|
||||
SampleFrame* m_buffer;
|
||||
float m_sampleRate;
|
||||
StereoLinkwitzRiley m_filter;
|
||||
|
||||
|
||||
@@ -495,11 +495,11 @@ void CarlaInstrument::loadSettings(const QDomElement& elem)
|
||||
#endif
|
||||
}
|
||||
|
||||
void CarlaInstrument::play(sampleFrame* workingBuffer)
|
||||
void CarlaInstrument::play(SampleFrame* workingBuffer)
|
||||
{
|
||||
const uint bufsize = Engine::audioEngine()->framesPerPeriod();
|
||||
|
||||
std::memset(workingBuffer, 0, sizeof(sample_t)*bufsize*DEFAULT_CHANNELS);
|
||||
zeroSampleFrames(workingBuffer, bufsize);
|
||||
|
||||
if (fHandle == nullptr)
|
||||
{
|
||||
|
||||
@@ -81,7 +81,7 @@ class CarlaParamFloatModel : public FloatModel
|
||||
{
|
||||
public:
|
||||
CarlaParamFloatModel(Model * parent):
|
||||
FloatModel(0.0, 0.0, 1.0, 0.001, parent, "Unused"),
|
||||
FloatModel(0.f, 0.f, 1.f, 0.001f, parent, "Unused"),
|
||||
m_isOutput(false),
|
||||
m_isEnabled(false)
|
||||
{
|
||||
@@ -193,7 +193,7 @@ public:
|
||||
QString nodeName() const override;
|
||||
void saveSettings(QDomDocument& doc, QDomElement& parent) override;
|
||||
void loadSettings(const QDomElement& elem) override;
|
||||
void play(sampleFrame* workingBuffer) override;
|
||||
void play(SampleFrame* workingBuffer) override;
|
||||
bool handleMidiEvent(const MidiEvent& event, const TimePos& time, f_cnt_t offset) override;
|
||||
gui::PluginView* instantiateView(QWidget* parent) override;
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ void CompressorEffect::calcMix()
|
||||
|
||||
|
||||
|
||||
bool CompressorEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
|
||||
bool CompressorEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
|
||||
{
|
||||
if (!isEnabled() || !isRunning())
|
||||
{
|
||||
@@ -590,6 +590,9 @@ void CompressorEffect::changeSampleRate()
|
||||
calcInGain();
|
||||
calcTiltCoeffs();
|
||||
calcMix();
|
||||
|
||||
calcAutoAttack();
|
||||
calcAutoRelease();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace lmms
|
||||
{
|
||||
|
||||
|
||||
constexpr float COMP_LOG = -2.2;
|
||||
constexpr float COMP_LOG = -2.2f;
|
||||
|
||||
class CompressorEffect : public Effect
|
||||
{
|
||||
@@ -43,7 +43,7 @@ class CompressorEffect : public Effect
|
||||
public:
|
||||
CompressorEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
|
||||
~CompressorEffect() override = default;
|
||||
bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override;
|
||||
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
@@ -105,7 +105,7 @@ private:
|
||||
|
||||
float m_coeffPrecalc;
|
||||
|
||||
sampleFrame m_maxLookaheadVal;
|
||||
SampleFrame m_maxLookaheadVal;
|
||||
|
||||
int m_maxLookaheadTimer[2] = {1, 1};
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ class QLabel;
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
constexpr float COMP_NOISE_FLOOR = 0.000001;// -120 dbFs
|
||||
constexpr float COMP_NOISE_FLOOR = 0.000001f;// -120 dbFs
|
||||
|
||||
class CompressorControls;
|
||||
|
||||
|
||||
@@ -64,9 +64,9 @@ CrossoverEQEffect::CrossoverEQEffect( Model* parent, const Descriptor::SubPlugin
|
||||
m_hp4( m_sampleRate ),
|
||||
m_needsUpdate( true )
|
||||
{
|
||||
m_tmp2 = new sampleFrame[Engine::audioEngine()->framesPerPeriod()];
|
||||
m_tmp1 = new sampleFrame[Engine::audioEngine()->framesPerPeriod()];
|
||||
m_work = new sampleFrame[Engine::audioEngine()->framesPerPeriod()];
|
||||
m_tmp2 = new SampleFrame[Engine::audioEngine()->framesPerPeriod()];
|
||||
m_tmp1 = new SampleFrame[Engine::audioEngine()->framesPerPeriod()];
|
||||
m_work = new SampleFrame[Engine::audioEngine()->framesPerPeriod()];
|
||||
}
|
||||
|
||||
CrossoverEQEffect::~CrossoverEQEffect()
|
||||
@@ -89,7 +89,7 @@ void CrossoverEQEffect::sampleRateChanged()
|
||||
}
|
||||
|
||||
|
||||
bool CrossoverEQEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
bool CrossoverEQEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
@@ -139,7 +139,7 @@ bool CrossoverEQEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
|
||||
|
||||
m_needsUpdate = false;
|
||||
|
||||
memset( m_work, 0, sizeof( sampleFrame ) * frames );
|
||||
zeroSampleFrames(m_work, frames);
|
||||
|
||||
// run temp bands
|
||||
for( int f = 0; f < frames; ++f )
|
||||
|
||||
@@ -40,7 +40,7 @@ class CrossoverEQEffect : public Effect
|
||||
public:
|
||||
CrossoverEQEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
|
||||
~CrossoverEQEffect() override;
|
||||
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
|
||||
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
@@ -69,9 +69,9 @@ private:
|
||||
StereoLinkwitzRiley m_hp3;
|
||||
StereoLinkwitzRiley m_hp4;
|
||||
|
||||
sampleFrame * m_tmp1;
|
||||
sampleFrame * m_tmp2;
|
||||
sampleFrame * m_work;
|
||||
SampleFrame* m_tmp1;
|
||||
SampleFrame* m_tmp2;
|
||||
SampleFrame* m_work;
|
||||
|
||||
bool m_needsUpdate;
|
||||
|
||||
|
||||
@@ -34,11 +34,11 @@ namespace lmms
|
||||
DelayControls::DelayControls( DelayEffect* effect ):
|
||||
EffectControls( effect ),
|
||||
m_effect ( effect ),
|
||||
m_delayTimeModel( 0.5, 0.01, 5.0, 0.0001, 5000.0, this, tr( "Delay samples" )) ,
|
||||
m_feedbackModel(0.0f,0.0f,1.0f,0.01f,this,tr( "Feedback" ) ),
|
||||
m_lfoTimeModel(2.0, 0.01, 5.0, 0.0001, 20000.0, this, tr( "LFO frequency" ) ),
|
||||
m_lfoAmountModel(0.0, 0.0, 0.5, 0.0001, 2000.0, this, tr ( "LFO amount" ) ),
|
||||
m_outGainModel( 0.0, -60.0, 20.0, 0.01, this, tr( "Output gain" ) )
|
||||
m_delayTimeModel(0.5f, 0.01f, 5.f, 0.0001f, 5000.f, this, tr("Delay samples")) ,
|
||||
m_feedbackModel(0.0f, 0.0f, 1.0f, 0.01f, this, tr("Feedback")),
|
||||
m_lfoTimeModel(2.f, 0.01f, 5.f, 0.0001f, 20000.f, this, tr("LFO frequency")),
|
||||
m_lfoAmountModel(0.f, 0.f, 0.5f, 0.0001f, 2000.f, this, tr("LFO amount")),
|
||||
m_outGainModel(0.f, -60.f, 20.f, 0.01f, this, tr("Output gain"))
|
||||
{
|
||||
connect( Engine::audioEngine(), SIGNAL( sampleRateChanged() ), this, SLOT( changeSampleRate() ) );
|
||||
m_outPeakL = 0.0;
|
||||
@@ -77,4 +77,4 @@ void DelayControls::changeSampleRate()
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
} // namespace lmms
|
||||
|
||||
@@ -81,7 +81,7 @@ DelayEffect::~DelayEffect()
|
||||
|
||||
|
||||
|
||||
bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
bool DelayEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
@@ -91,9 +91,8 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
const float sr = Engine::audioEngine()->outputSampleRate();
|
||||
const float d = dryLevel();
|
||||
const float w = wetLevel();
|
||||
auto dryS = std::array<sample_t, 2>{};
|
||||
float lPeak = 0.0;
|
||||
float rPeak = 0.0;
|
||||
|
||||
SampleFrame peak;
|
||||
float length = m_delayControls.m_delayTimeModel.value();
|
||||
float amplitude = m_delayControls.m_lfoAmountModel.value() * sr;
|
||||
float lfoTime = 1.0 / m_delayControls.m_lfoTimeModel.value();
|
||||
@@ -116,26 +115,28 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
m_outGain = dbfsToAmp( m_delayControls.m_outGainModel.value() );
|
||||
}
|
||||
|
||||
for( fpp_t f = 0; f < frames; ++f )
|
||||
for (fpp_t f = 0; f < frames; ++f)
|
||||
{
|
||||
dryS[0] = buf[f][0];
|
||||
dryS[1] = buf[f][1];
|
||||
auto& currentFrame = buf[f];
|
||||
const auto dryS = currentFrame;
|
||||
|
||||
// Prepare delay for current sample
|
||||
m_delay->setFeedback( *feedbackPtr );
|
||||
m_lfo->setFrequency( *lfoTimePtr );
|
||||
m_currentLength = static_cast<int>(*lengthPtr * Engine::audioEngine()->outputSampleRate());
|
||||
m_delay->setLength( m_currentLength + ( *amplitudePtr * ( float )m_lfo->tick() ) );
|
||||
m_delay->tick( buf[f] );
|
||||
|
||||
buf[f][0] *= m_outGain;
|
||||
buf[f][1] *= m_outGain;
|
||||
// Process the wet signal
|
||||
m_delay->tick( currentFrame );
|
||||
currentFrame *= m_outGain;
|
||||
|
||||
lPeak = buf[f][0] > lPeak ? buf[f][0] : lPeak;
|
||||
rPeak = buf[f][1] > rPeak ? buf[f][1] : rPeak;
|
||||
// Calculate peak of wet signal
|
||||
peak = peak.absMax(currentFrame);
|
||||
|
||||
buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] );
|
||||
buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] );
|
||||
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
|
||||
// Dry/wet mix
|
||||
currentFrame = dryS * d + currentFrame * w;
|
||||
|
||||
outSum += currentFrame.sumOfSquaredAmplitudes();
|
||||
|
||||
lengthPtr += lengthInc;
|
||||
amplitudePtr += amplitudeInc;
|
||||
@@ -143,8 +144,8 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
feedbackPtr += feedbackInc;
|
||||
}
|
||||
checkGate( outSum / frames );
|
||||
m_delayControls.m_outPeakL = lPeak;
|
||||
m_delayControls.m_outPeakR = rPeak;
|
||||
m_delayControls.m_outPeakL = peak.left();
|
||||
m_delayControls.m_outPeakR = peak.right();
|
||||
|
||||
return isRunning();
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class DelayEffect : public Effect
|
||||
public:
|
||||
DelayEffect(Model* parent , const Descriptor::SubPluginFeatures::Key* key );
|
||||
~DelayEffect() override;
|
||||
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
|
||||
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
|
||||
EffectControls* controls() override
|
||||
{
|
||||
return &m_delayControls;
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
*/
|
||||
|
||||
#include "StereoDelay.h"
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "SampleFrame.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
@@ -32,9 +34,9 @@ namespace lmms
|
||||
StereoDelay::StereoDelay( int maxTime, int sampleRate )
|
||||
{
|
||||
m_buffer = 0;
|
||||
m_maxTime = maxTime;
|
||||
m_maxTime = static_cast<float>(maxTime);
|
||||
m_maxLength = maxTime * sampleRate;
|
||||
m_length = m_maxLength;
|
||||
m_length = static_cast<float>(m_maxLength);
|
||||
|
||||
m_writeIndex = 0;
|
||||
m_feedback = 0.0f;
|
||||
@@ -55,10 +57,10 @@ StereoDelay::~StereoDelay()
|
||||
|
||||
|
||||
|
||||
void StereoDelay::tick( sampleFrame& frame )
|
||||
void StereoDelay::tick( SampleFrame& frame )
|
||||
{
|
||||
m_writeIndex = ( m_writeIndex + 1 ) % ( int )m_maxLength;
|
||||
int readIndex = m_writeIndex - m_length;
|
||||
int readIndex = m_writeIndex - static_cast<int>(m_length);
|
||||
if (readIndex < 0 ) { readIndex += m_maxLength; }
|
||||
float lOut = m_buffer[ readIndex ][ 0 ];
|
||||
float rOut = m_buffer[ readIndex ] [1 ];
|
||||
@@ -81,7 +83,7 @@ void StereoDelay::setSampleRate( int sampleRate )
|
||||
}
|
||||
|
||||
int bufferSize = ( int )( sampleRate * m_maxTime );
|
||||
m_buffer = new sampleFrame[bufferSize];
|
||||
m_buffer = new SampleFrame[bufferSize];
|
||||
for( int i = 0 ; i < bufferSize ; i++)
|
||||
{
|
||||
m_buffer[i][0] = 0.0;
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class SampleFrame;
|
||||
|
||||
class StereoDelay
|
||||
{
|
||||
public:
|
||||
@@ -49,11 +51,11 @@ public:
|
||||
m_feedback = feedback;
|
||||
}
|
||||
|
||||
void tick( sampleFrame& frame );
|
||||
void tick( SampleFrame& frame );
|
||||
void setSampleRate( int sampleRate );
|
||||
|
||||
private:
|
||||
sampleFrame* m_buffer;
|
||||
SampleFrame* m_buffer;
|
||||
int m_maxLength;
|
||||
float m_length;
|
||||
int m_writeIndex;
|
||||
|
||||
@@ -58,7 +58,7 @@ DispersionEffect::DispersionEffect(Model* parent, const Descriptor::SubPluginFea
|
||||
}
|
||||
|
||||
|
||||
bool DispersionEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
|
||||
bool DispersionEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
|
||||
{
|
||||
if (!isEnabled() || !isRunning())
|
||||
{
|
||||
|
||||
@@ -41,7 +41,7 @@ class DispersionEffect : public Effect
|
||||
public:
|
||||
DispersionEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
|
||||
~DispersionEffect() override = default;
|
||||
bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override;
|
||||
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
|
||||
@@ -35,9 +35,9 @@ DispersionControls::DispersionControls(DispersionEffect* effect) :
|
||||
EffectControls(effect),
|
||||
m_effect(effect),
|
||||
m_amountModel(0, 0, MAX_DISPERSION_FILTERS, this, tr("Amount")),
|
||||
m_freqModel(200, 20, 20000, 0.001, this, tr("Frequency")),
|
||||
m_resoModel(0.707, 0.01, 8, 0.0001, this, tr("Resonance")),
|
||||
m_feedbackModel(0.f, -1.f, 1.f, 0.0001, this, tr("Feedback")),
|
||||
m_freqModel(200, 20, 20000, 0.001f, this, tr("Frequency")),
|
||||
m_resoModel(0.707f, 0.01f, 8, 0.0001f, this, tr("Resonance")),
|
||||
m_feedbackModel(0.f, -1.f, 1.f, 0.0001f, this, tr("Feedback")),
|
||||
m_dcModel(false, this, tr("DC Offset Removal"))
|
||||
{
|
||||
m_freqModel.setScaleLogarithmic(true);
|
||||
|
||||
@@ -77,7 +77,7 @@ DualFilterEffect::~DualFilterEffect()
|
||||
|
||||
|
||||
|
||||
bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
bool DualFilterEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ class DualFilterEffect : public Effect
|
||||
public:
|
||||
DualFilterEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
|
||||
~DualFilterEffect() override;
|
||||
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
|
||||
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ DualFilterControls::DualFilterControls( DualFilterEffect* effect ) :
|
||||
m_enabled1Model( true, this, tr( "Filter 1 enabled" ) ),
|
||||
m_filter1Model( this, tr( "Filter 1 type" ) ),
|
||||
m_cut1Model( 7000.0f, 1.0f, 20000.0f, 1.0f, this, tr( "Cutoff frequency 1" ) ),
|
||||
m_res1Model( 0.5, BasicFilters<>::minQ(), 10.0, 0.01, this, tr( "Q/Resonance 1" ) ),
|
||||
m_res1Model(0.5f, BasicFilters<>::minQ(), 10.f, 0.01f, this, tr("Q/Resonance 1")),
|
||||
m_gain1Model( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Gain 1" ) ),
|
||||
|
||||
m_mixModel( 0.0f, -1.0f, 1.0f, 0.01f, this, tr( "Mix" ) ),
|
||||
@@ -51,7 +51,7 @@ DualFilterControls::DualFilterControls( DualFilterEffect* effect ) :
|
||||
m_enabled2Model( true, this, tr( "Filter 2 enabled" ) ),
|
||||
m_filter2Model( this, tr( "Filter 2 type" ) ),
|
||||
m_cut2Model( 7000.0f, 1.0f, 20000.0f, 1.0f, this, tr( "Cutoff frequency 2" ) ),
|
||||
m_res2Model( 0.5, BasicFilters<>::minQ(), 10.0, 0.01, this, tr( "Q/Resonance 2" ) ),
|
||||
m_res2Model(0.5f, BasicFilters<>::minQ(), 10.f, 0.01f, this, tr("Q/Resonance 2")),
|
||||
m_gain2Model( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Gain 2" ) )
|
||||
{
|
||||
m_filter1Model.addItem( tr( "Low-pass" ), std::make_unique<PixmapLoader>( "filter_lp" ) );
|
||||
|
||||
@@ -91,7 +91,7 @@ inline void DynProcEffect::calcRelease()
|
||||
}
|
||||
|
||||
|
||||
bool DynProcEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
bool DynProcEffect::processAudioBuffer( SampleFrame* _buf,
|
||||
const fpp_t _frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
DynProcEffect( Model * _parent,
|
||||
const Descriptor::SubPluginFeatures::Key * _key );
|
||||
~DynProcEffect() override;
|
||||
bool processAudioBuffer( sampleFrame * _buf,
|
||||
bool processAudioBuffer( SampleFrame* _buf,
|
||||
const fpp_t _frames ) override;
|
||||
|
||||
EffectControls * controls() override
|
||||
|
||||
@@ -37,30 +37,30 @@ namespace lmms
|
||||
EqControls::EqControls( EqEffect *effect ) :
|
||||
EffectControls( effect ),
|
||||
m_effect( effect ),
|
||||
m_inGainModel( 0.0, -60.0, 20.0, 0.01, this, tr( "Input gain") ),
|
||||
m_outGainModel( -.0, -60.0, 20.0, 0.01, this, tr( "Output gain" ) ),
|
||||
m_lowShelfGainModel( 0.0 , -18, 18, 0.001, this, tr( "Low-shelf gain" ) ),
|
||||
m_para1GainModel( 0.0 , -18, 18, 0.001, this, tr( "Peak 1 gain" ) ),
|
||||
m_para2GainModel( 0.0 , -18, 18, 0.001, this, tr( "Peak 2 gain" ) ),
|
||||
m_para3GainModel( 0.0 , -18, 18, 0.001, this, tr( "Peak 3 gain" ) ),
|
||||
m_para4GainModel( 0.0 , -18, 18, 0.001, this, tr( "Peak 4 gain" ) ),
|
||||
m_highShelfGainModel( 0.0 , -18, 18, 0.001, this, tr( "High-shelf gain" ) ),
|
||||
m_hpResModel( 0.707,0.003, 10.0 , 0.001, this, tr( "HP res" ) ),
|
||||
m_lowShelfResModel( 0.707, 0.55, 10.0 , 0.001, this , tr( "Low-shelf res" ) ),
|
||||
m_para1BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 1 BW" ) ),
|
||||
m_para2BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 2 BW" ) ),
|
||||
m_para3BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 3 BW" ) ),
|
||||
m_para4BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 4 BW" ) ),
|
||||
m_highShelfResModel( 0.707, 0.55, 10.0 , 0.001, this , tr( "High-shelf res" ) ),
|
||||
m_lpResModel( 0.707,0.003, 10.0 , 0.001, this , tr( "LP res" ) ),
|
||||
m_hpFeqModel( 31.0, 20.0, 20000, 0.001, this , tr( "HP freq" ) ),
|
||||
m_lowShelfFreqModel( 80.0, 20.0, 20000, 0.001, this , tr( "Low-shelf freq" ) ),
|
||||
m_para1FreqModel( 120.0, 20.0, 20000, 0.001, this , tr( "Peak 1 freq" ) ),
|
||||
m_para2FreqModel( 250.0, 20.0, 20000, 0.001, this, tr( "Peak 2 freq" ) ),
|
||||
m_para3FreqModel( 2000.0, 20.0, 20000, 0.001, this , tr( "Peak 3 freq" ) ),
|
||||
m_para4FreqModel( 4000.0, 20.0, 20000, 0.001, this , tr( "Peak 4 freq" ) ),
|
||||
m_highShelfFreqModel( 12000.0, 20.0, 20000, 0.001, this , tr( "High-shelf freq" ) ),
|
||||
m_lpFreqModel( 18000.0, 20.0, 20000, 0.001, this , tr( "LP freq" ) ),
|
||||
m_inGainModel(0.f, -60.f, 20.f, 0.01f, this, tr("Input gain")),
|
||||
m_outGainModel(-0.f, -60.f, 20.f, 0.01f, this, tr("Output gain")),
|
||||
m_lowShelfGainModel( 0.f, -18, 18, 0.001f, this, tr("Low-shelf gain")),
|
||||
m_para1GainModel(0.f, -18, 18, 0.001f, this, tr("Peak 1 gain")),
|
||||
m_para2GainModel(0.f, -18, 18, 0.001f, this, tr("Peak 2 gain")),
|
||||
m_para3GainModel(0.f, -18, 18, 0.001f, this, tr("Peak 3 gain")),
|
||||
m_para4GainModel(0.f, -18, 18, 0.001f, this, tr("Peak 4 gain")),
|
||||
m_highShelfGainModel(0.f, -18, 18, 0.001f, this, tr("High-shelf gain")),
|
||||
m_hpResModel(0.707f,0.003f, 10.f, 0.001f, this, tr("HP res")),
|
||||
m_lowShelfResModel(0.707f, 0.55f, 10.f, 0.001f, this, tr("Low-shelf res")),
|
||||
m_para1BwModel(0.3f, 0.1f, 4, 0.001f, this, tr("Peak 1 BW")),
|
||||
m_para2BwModel(0.3f, 0.1f, 4, 0.001f, this, tr("Peak 2 BW")),
|
||||
m_para3BwModel(0.3f, 0.1f, 4, 0.001f, this, tr("Peak 3 BW")),
|
||||
m_para4BwModel(0.3f, 0.1f, 4, 0.001f, this, tr("Peak 4 BW")),
|
||||
m_highShelfResModel(0.707f, 0.55f, 10.f, 0.001f, this, tr("High-shelf res")),
|
||||
m_lpResModel(0.707f,0.003f, 10.f, 0.001f, this, tr("LP res")),
|
||||
m_hpFeqModel(31.f, 20.f, 20000, 0.001f, this, tr("HP freq")),
|
||||
m_lowShelfFreqModel(80.f, 20.f, 20000, 0.001f, this, tr("Low-shelf freq")),
|
||||
m_para1FreqModel(120.f, 20.f, 20000, 0.001f, this, tr("Peak 1 freq")),
|
||||
m_para2FreqModel(250.f, 20.f, 20000, 0.001f, this, tr("Peak 2 freq")),
|
||||
m_para3FreqModel(2000.f, 20.f, 20000, 0.001f, this, tr("Peak 3 freq")),
|
||||
m_para4FreqModel(4000.f, 20.f, 20000, 0.001f, this, tr("Peak 4 freq")),
|
||||
m_highShelfFreqModel(12000.f, 20.f, 20000, 0.001f, this, tr("High-shelf freq")),
|
||||
m_lpFreqModel(18000.f, 20.f, 20000, 0.001f, this, tr("LP freq")),
|
||||
m_hpActiveModel( false, this , tr( "HP active" ) ),
|
||||
m_lowShelfActiveModel( false, this , tr( "Low-shelf active" ) ),
|
||||
m_para1ActiveModel( false, this , tr( "Peak 1 active" ) ),
|
||||
|
||||
@@ -581,17 +581,8 @@ void EqHandle::wheelEvent( QGraphicsSceneWheelEvent *wevent )
|
||||
|
||||
if( wevent->orientation() == Qt::Vertical )
|
||||
{
|
||||
m_resonance = m_resonance + ( numSteps );
|
||||
m_resonance = std::clamp(m_resonance + numSteps, 0.1f, highestBandwich);
|
||||
|
||||
if( m_resonance < 0.1 )
|
||||
{
|
||||
m_resonance = 0.1;
|
||||
}
|
||||
|
||||
if( m_resonance > highestBandwich )
|
||||
{
|
||||
m_resonance = highestBandwich;
|
||||
}
|
||||
emit positionChanged();
|
||||
}
|
||||
wevent->accept();
|
||||
|
||||
@@ -64,7 +64,7 @@ EqEffect::EqEffect( Model *parent, const Plugin::Descriptor::SubPluginFeatures::
|
||||
|
||||
|
||||
|
||||
bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
|
||||
bool EqEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
const int sampleRate = Engine::audioEngine()->outputSampleRate();
|
||||
|
||||
@@ -157,7 +157,7 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
|
||||
}
|
||||
|
||||
const float outGain = m_outGain;
|
||||
sampleFrame m_inPeak = { 0, 0 };
|
||||
SampleFrame m_inPeak = { 0, 0 };
|
||||
|
||||
if(m_eqControls.m_analyseInModel.value( true ) && outSum > 0 && m_eqControls.isViewVisible() )
|
||||
{
|
||||
@@ -263,7 +263,7 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
|
||||
|
||||
}
|
||||
|
||||
sampleFrame outPeak = { 0, 0 };
|
||||
SampleFrame outPeak = { 0, 0 };
|
||||
gain( buf, frames, outGain, &outPeak );
|
||||
m_eqControls.m_outPeakL = m_eqControls.m_outPeakL < outPeak[0] ? outPeak[0] : m_eqControls.m_outPeakL;
|
||||
m_eqControls.m_outPeakR = m_eqControls.m_outPeakR < outPeak[1] ? outPeak[1] : m_eqControls.m_outPeakR;
|
||||
|
||||
@@ -40,12 +40,12 @@ class EqEffect : public Effect
|
||||
public:
|
||||
EqEffect( Model * parent , const Descriptor::SubPluginFeatures::Key * key );
|
||||
~EqEffect() override = default;
|
||||
bool processAudioBuffer( sampleFrame * buf, const fpp_t frames ) override;
|
||||
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
|
||||
EffectControls * controls() override
|
||||
{
|
||||
return &m_eqControls;
|
||||
}
|
||||
inline void gain( sampleFrame * buf, const fpp_t frames, float scale, sampleFrame * peak )
|
||||
inline void gain( SampleFrame* buf, const fpp_t frames, float scale, SampleFrame* peak )
|
||||
{
|
||||
peak[0][0] = 0.0f; peak[0][1] = 0.0f;
|
||||
for( fpp_t f = 0; f < frames; ++f )
|
||||
|
||||
@@ -67,7 +67,7 @@ private slots:
|
||||
{
|
||||
const float opl = getPeak_L();
|
||||
const float opr = getPeak_R();
|
||||
const float fallOff = 1.07;
|
||||
const float fallOff = 1.07f;
|
||||
if( *m_lPeak > opl )
|
||||
{
|
||||
setPeak_L( *m_lPeak );
|
||||
|
||||
@@ -432,7 +432,7 @@ public:
|
||||
|
||||
|
||||
|
||||
virtual void processBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
virtual void processBuffer( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
for ( fpp_t f = 0 ; f < frames ; ++f)
|
||||
{
|
||||
|
||||
@@ -49,10 +49,10 @@ EqAnalyser::EqAnalyser() :
|
||||
|
||||
//initialize Blackman-Harris window, constants taken from
|
||||
//https://en.wikipedia.org/wiki/Window_function#A_list_of_window_functions
|
||||
const float a0 = 0.35875;
|
||||
const float a1 = 0.48829;
|
||||
const float a2 = 0.14128;
|
||||
const float a3 = 0.01168;
|
||||
const float a0 = 0.35875f;
|
||||
const float a1 = 0.48829f;
|
||||
const float a2 = 0.14128f;
|
||||
const float a3 = 0.01168f;
|
||||
|
||||
for (int i = 0; i < FFT_BUFFER_SIZE; i++)
|
||||
{
|
||||
@@ -75,7 +75,7 @@ EqAnalyser::~EqAnalyser()
|
||||
|
||||
|
||||
|
||||
void EqAnalyser::analyze( sampleFrame *buf, const fpp_t frames )
|
||||
void EqAnalyser::analyze( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
//only analyse if the view is visible
|
||||
if ( m_active )
|
||||
@@ -230,7 +230,7 @@ void EqSpectrumView::paintEvent(QPaintEvent *event)
|
||||
float *bands = m_analyser->m_bands;
|
||||
m_path.moveTo( 0, height() );
|
||||
m_peakSum = 0;
|
||||
const float fallOff = 1.07;
|
||||
const float fallOff = 1.07f;
|
||||
for( int x = 0; x < MAX_BANDS; ++x, ++bands )
|
||||
{
|
||||
float peak = *bands != 0. ? (fh * 2.0 / 3.0 * (20. * log10(*bands / energy) - LOWER_Y) / (-LOWER_Y)) : 0.;
|
||||
@@ -305,4 +305,4 @@ void EqSpectrumView::periodicalUpdate()
|
||||
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
} // namespace lmms
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class SampleFrame;
|
||||
|
||||
const int MAX_BANDS = 2048;
|
||||
class EqAnalyser
|
||||
@@ -44,7 +45,7 @@ public:
|
||||
bool getInProgress();
|
||||
void clear();
|
||||
|
||||
void analyze( sampleFrame *buf, const fpp_t frames );
|
||||
void analyze( SampleFrame* buf, const fpp_t frames );
|
||||
|
||||
float getEnergy() const;
|
||||
int getSampleRate() const;
|
||||
|
||||
@@ -36,12 +36,12 @@ namespace lmms
|
||||
FlangerControls::FlangerControls( FlangerEffect *effect ) :
|
||||
EffectControls ( effect ),
|
||||
m_effect ( effect ),
|
||||
m_delayTimeModel(0.001, 0.0001, 0.050, 0.0001, this, tr( "Delay samples" ) ),
|
||||
m_lfoFrequencyModel( 0.25, 0.01, 60, 0.0001, 60000.0, this, tr( "LFO frequency" ) ),
|
||||
m_lfoAmountModel( 0.0, 0.0, 0.0025, 0.0001, this, tr( "Amount" ) ),
|
||||
m_lfoPhaseModel( 90.0, 0.0, 360.0, 0.0001, this, tr( "Stereo phase" ) ),
|
||||
m_feedbackModel( 0.0, -1.0, 1.0, 0.0001, this, tr( "Feedback" ) ),
|
||||
m_whiteNoiseAmountModel( 0.0, 0.0, 0.05, 0.0001, this, tr( "Noise" ) ),
|
||||
m_delayTimeModel(0.001f, 0.0001f, 0.050f, 0.0001f, this, tr("Delay samples")),
|
||||
m_lfoFrequencyModel(0.25f, 0.01f, 60, 0.0001f, 60000.f, this, tr("LFO frequency")),
|
||||
m_lfoAmountModel(0.f, 0.f, 0.0025f, 0.0001f, this, tr("Amount")),
|
||||
m_lfoPhaseModel(90.f, 0.f, 360.f, 0.0001f, this, tr("Stereo phase")),
|
||||
m_feedbackModel(0.f, -1.f, 1.f, 0.0001f, this, tr("Feedback")),
|
||||
m_whiteNoiseAmountModel(0.f, 0.f, 0.05f, 0.0001f, this, tr("Noise")),
|
||||
m_invertFeedbackModel ( false, this, tr( "Invert" ) )
|
||||
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ FlangerEffect::~FlangerEffect()
|
||||
|
||||
|
||||
|
||||
bool FlangerEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
|
||||
bool FlangerEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ class FlangerEffect : public Effect
|
||||
public:
|
||||
FlangerEffect( Model* parent , const Descriptor::SubPluginFeatures::Key* key );
|
||||
~FlangerEffect() override;
|
||||
bool processAudioBuffer( sampleFrame *buf, const fpp_t frames ) override;
|
||||
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
|
||||
EffectControls* controls() override
|
||||
{
|
||||
return &m_flangerControls;
|
||||
|
||||
@@ -32,9 +32,9 @@ namespace lmms
|
||||
MonoDelay::MonoDelay( int maxTime , int sampleRate )
|
||||
{
|
||||
m_buffer = 0;
|
||||
m_maxTime = maxTime;
|
||||
m_maxTime = static_cast<float>(maxTime);
|
||||
m_maxLength = maxTime * sampleRate;
|
||||
m_length = m_maxLength;
|
||||
m_length = static_cast<float>(m_maxLength);
|
||||
|
||||
m_writeIndex = 0;
|
||||
m_feedback = 0.0f;
|
||||
@@ -57,7 +57,7 @@ MonoDelay::~MonoDelay()
|
||||
void MonoDelay::tick( sample_t* sample )
|
||||
{
|
||||
m_writeIndex = ( m_writeIndex + 1 ) % ( int )m_maxLength;
|
||||
int readIndex = m_writeIndex - m_length;
|
||||
int readIndex = m_writeIndex - static_cast<int>(m_length);
|
||||
if (readIndex < 0 ) { readIndex += m_maxLength; }
|
||||
float out = m_buffer[ readIndex ];
|
||||
m_buffer[ m_writeIndex ] = *sample + ( out * m_feedback );
|
||||
|
||||
@@ -228,7 +228,7 @@ float FreeBoyInstrument::desiredReleaseTimeMs() const
|
||||
|
||||
|
||||
|
||||
void FreeBoyInstrument::playNote(NotePlayHandle* nph, sampleFrame* workingBuffer)
|
||||
void FreeBoyInstrument::playNote(NotePlayHandle* nph, SampleFrame* workingBuffer)
|
||||
{
|
||||
const f_cnt_t tfp = nph->totalFramesPlayed();
|
||||
const int samplerate = Engine::audioEngine()->outputSampleRate();
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
FreeBoyInstrument( InstrumentTrack * _instrument_track );
|
||||
~FreeBoyInstrument() override = default;
|
||||
|
||||
void playNote(NotePlayHandle* nph, sampleFrame* workingBuffer) override;
|
||||
void playNote(NotePlayHandle* nph, SampleFrame* workingBuffer) override;
|
||||
void deleteNotePluginData(NotePlayHandle* nph) override;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
|
||||
@@ -289,7 +289,7 @@ QString GigInstrument::getCurrentPatchName()
|
||||
|
||||
|
||||
// A key has been pressed
|
||||
void GigInstrument::playNote( NotePlayHandle * _n, sampleFrame * )
|
||||
void GigInstrument::playNote( NotePlayHandle * _n, SampleFrame* )
|
||||
{
|
||||
const float LOG440 = 2.643452676f;
|
||||
|
||||
@@ -320,7 +320,7 @@ void GigInstrument::playNote( NotePlayHandle * _n, sampleFrame * )
|
||||
|
||||
// Process the notes and output a certain number of frames (e.g. 256, set in
|
||||
// the preferences)
|
||||
void GigInstrument::play( sampleFrame * _working_buffer )
|
||||
void GigInstrument::play( SampleFrame* _working_buffer )
|
||||
{
|
||||
const fpp_t frames = Engine::audioEngine()->framesPerPeriod();
|
||||
const int rate = Engine::audioEngine()->outputSampleRate();
|
||||
@@ -441,7 +441,7 @@ void GigInstrument::play( sampleFrame * _working_buffer )
|
||||
}
|
||||
|
||||
// Load this note's data
|
||||
sampleFrame sampleData[samples];
|
||||
SampleFrame sampleData[samples];
|
||||
loadSample(sample, sampleData, samples);
|
||||
|
||||
// Apply ADSR using a copy so if we don't use these samples when
|
||||
@@ -458,7 +458,7 @@ void GigInstrument::play( sampleFrame * _working_buffer )
|
||||
// Output the data resampling if needed
|
||||
if( resample == true )
|
||||
{
|
||||
sampleFrame convertBuf[frames];
|
||||
SampleFrame convertBuf[frames];
|
||||
|
||||
// Only output if resampling is successful (note that "used" is output)
|
||||
if (sample.convertSampleRate(*sampleData, *convertBuf, samples, frames, freq_factor, used))
|
||||
@@ -499,7 +499,7 @@ void GigInstrument::play( sampleFrame * _working_buffer )
|
||||
|
||||
|
||||
|
||||
void GigInstrument::loadSample( GigSample& sample, sampleFrame* sampleData, f_cnt_t samples )
|
||||
void GigInstrument::loadSample( GigSample& sample, SampleFrame* sampleData, f_cnt_t samples )
|
||||
{
|
||||
if( sampleData == nullptr || samples < 1 )
|
||||
{
|
||||
@@ -1182,7 +1182,7 @@ void GigSample::updateSampleRate()
|
||||
|
||||
|
||||
|
||||
bool GigSample::convertSampleRate( sampleFrame & oldBuf, sampleFrame & newBuf,
|
||||
bool GigSample::convertSampleRate( SampleFrame & oldBuf, SampleFrame & newBuf,
|
||||
f_cnt_t oldSize, f_cnt_t newSize, float freq_factor, f_cnt_t& used )
|
||||
{
|
||||
if( srcState == nullptr )
|
||||
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
|
||||
// Needed since libsamplerate stores data internally between calls
|
||||
void updateSampleRate();
|
||||
bool convertSampleRate( sampleFrame & oldBuf, sampleFrame & newBuf,
|
||||
bool convertSampleRate( SampleFrame & oldBuf, SampleFrame & newBuf,
|
||||
f_cnt_t oldSize, f_cnt_t newSize, float freq_factor, f_cnt_t& used );
|
||||
|
||||
gig::Sample * sample;
|
||||
@@ -243,10 +243,10 @@ public:
|
||||
GigInstrument( InstrumentTrack * _instrument_track );
|
||||
~GigInstrument() override;
|
||||
|
||||
void play( sampleFrame * _working_buffer ) override;
|
||||
void play( SampleFrame* _working_buffer ) override;
|
||||
|
||||
void playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer ) override;
|
||||
SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
|
||||
@@ -312,7 +312,7 @@ private:
|
||||
Dimension getDimensions( gig::Region * pRegion, int velocity, bool release );
|
||||
|
||||
// Load sample data from the Gig file, looping the sample where needed
|
||||
void loadSample( GigSample& sample, sampleFrame* sampleData, f_cnt_t samples );
|
||||
void loadSample( GigSample& sample, SampleFrame* sampleData, f_cnt_t samples );
|
||||
f_cnt_t getLoopedIndex( f_cnt_t index, f_cnt_t startf, f_cnt_t endf ) const;
|
||||
f_cnt_t getPingPongIndex( f_cnt_t index, f_cnt_t startf, f_cnt_t endf ) const;
|
||||
|
||||
|
||||
9
plugins/GranularPitchShifter/CMakeLists.txt
Executable file
9
plugins/GranularPitchShifter/CMakeLists.txt
Executable file
@@ -0,0 +1,9 @@
|
||||
include(BuildPlugin)
|
||||
build_plugin(granularpitchshifter
|
||||
GranularPitchShifterEffect.cpp
|
||||
GranularPitchShifterControls.cpp
|
||||
GranularPitchShifterControlDialog.cpp
|
||||
MOCFILES
|
||||
GranularPitchShifterControls.h
|
||||
GranularPitchShifterControlDialog.h
|
||||
EMBEDDED_RESOURCES *.png)
|
||||
158
plugins/GranularPitchShifter/GranularPitchShifterControlDialog.cpp
Executable file
158
plugins/GranularPitchShifter/GranularPitchShifterControlDialog.cpp
Executable file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* GranularPitchShifterControlDialog.cpp
|
||||
*
|
||||
* Copyright (c) 2024 Lost Robot <r94231/at/gmail/dot/com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GranularPitchShifterControlDialog.h"
|
||||
#include "GranularPitchShifterControls.h"
|
||||
#include "embed.h"
|
||||
#include "LcdFloatSpinBox.h"
|
||||
#include "Knob.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "gui_templates.h"
|
||||
#include "PixmapButton.h"
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
GranularPitchShifterControlDialog::GranularPitchShifterControlDialog(GranularPitchShifterControls* controls) :
|
||||
EffectControlDialog(controls)
|
||||
{
|
||||
setAutoFillBackground(true);
|
||||
QPalette pal;
|
||||
pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork"));
|
||||
setPalette(pal);
|
||||
setFixedSize(305, 180);
|
||||
|
||||
auto makeKnob = [this](KnobType style, int x, int y, const QString& hintText, const QString& unit, FloatModel* model)
|
||||
{
|
||||
Knob* newKnob = new Knob(style, this);
|
||||
newKnob->move(x, y);
|
||||
newKnob->setModel(model);
|
||||
newKnob->setHintText(hintText, unit);
|
||||
return newKnob;
|
||||
};
|
||||
|
||||
makeKnob(KnobType::Bright26, 19, 78, tr("Grain Size:"), " Hz", &controls->m_sizeModel);
|
||||
makeKnob(KnobType::Bright26, 116, 10, tr("Spray:"), " seconds", &controls->m_sprayModel);
|
||||
makeKnob(KnobType::Bright26, 158, 10, tr("Jitter:"), " octaves", &controls->m_jitterModel);
|
||||
makeKnob(KnobType::Bright26, 200, 10, tr("Twitch:"), " octaves", &controls->m_twitchModel);
|
||||
makeKnob(KnobType::Bright26, 188, 60, tr("Spray Stereo Spread:"), "", &controls->m_spraySpreadModel);
|
||||
makeKnob(KnobType::Bright26, 135, 110, tr("Grain Shape:"), "", &controls->m_shapeModel);
|
||||
makeKnob(KnobType::Bright26, 188, 110, tr("Fade Length:"), "", &controls->m_fadeLengthModel);
|
||||
makeKnob(KnobType::Bright26, 258, 45, tr("Feedback:"), "", &controls->m_feedbackModel);
|
||||
makeKnob(KnobType::Bright26, 258, 92, tr("Minimum Allowed Latency:"), " seconds", &controls->m_minLatencyModel);
|
||||
makeKnob(KnobType::Small17, 66, 157, tr("Density:"), "x", &controls->m_densityModel);
|
||||
makeKnob(KnobType::Small17, 8, 157, tr("Glide:"), " seconds", &controls->m_glideModel);
|
||||
|
||||
LcdFloatSpinBox* pitchBox = new LcdFloatSpinBox(3, 2, "11green", tr("Pitch"), this);
|
||||
pitchBox->move(15, 41);
|
||||
pitchBox->setModel(&controls->m_pitchModel);
|
||||
pitchBox->setToolTip(tr("Pitch"));
|
||||
pitchBox->setSeamless(true, true);
|
||||
|
||||
LcdFloatSpinBox* pitchSpreadBox = new LcdFloatSpinBox(3, 2, "11green", tr("Pitch Stereo Spread"), this);
|
||||
pitchSpreadBox->move(133, 66);
|
||||
pitchSpreadBox->setModel(&controls->m_pitchSpreadModel);
|
||||
pitchSpreadBox->setToolTip(tr("Pitch Stereo Spread"));
|
||||
pitchSpreadBox->setSeamless(true, true);
|
||||
|
||||
QPushButton button("Show Help", this);
|
||||
connect(&button, &QPushButton::clicked, this, &GranularPitchShifterControlDialog::showHelpWindow);
|
||||
|
||||
PixmapButton* m_helpBtn = new PixmapButton(this, nullptr);
|
||||
m_helpBtn->move(278, 159);
|
||||
m_helpBtn->setActiveGraphic(PLUGIN_NAME::getIconPixmap("help_active"));
|
||||
m_helpBtn->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("help_inactive"));
|
||||
m_helpBtn->setToolTip(tr("Open help window"));
|
||||
connect(m_helpBtn, SIGNAL(clicked()), this, SLOT(showHelpWindow()));
|
||||
|
||||
PixmapButton* prefilterButton = new PixmapButton(this, tr("Prefilter"));
|
||||
prefilterButton->move(8, 133);
|
||||
prefilterButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("prefilter_active"));
|
||||
prefilterButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("prefilter_inactive"));
|
||||
prefilterButton->setCheckable(true);
|
||||
prefilterButton->setModel(&controls->m_prefilterModel);
|
||||
prefilterButton->setToolTip(tr("Prefilter"));
|
||||
|
||||
ComboBox* rangeBox = new ComboBox(this);
|
||||
rangeBox->setGeometry(189, 155, 80, 22);
|
||||
rangeBox->setModel(&controls->m_rangeModel);
|
||||
controls->updateRange();
|
||||
}
|
||||
|
||||
void GranularPitchShifterControlDialog::showHelpWindow() {
|
||||
GranularPitchShifterHelpView::getInstance()->close();
|
||||
GranularPitchShifterHelpView::getInstance()->show();
|
||||
}
|
||||
|
||||
|
||||
QString GranularPitchShifterHelpView::s_helpText=
|
||||
"<div style='text-align: center;'>"
|
||||
"<b>Granular Pitch Shifter</b><br><br>"
|
||||
"Plugin by Lost Robot<br>"
|
||||
"GUI by thismoon<br>"
|
||||
"</div>"
|
||||
"<h3>Grain:</h3>"
|
||||
"<b>Pitch</b> - The amount of pitch shifting to perform, in 12EDO semitones.<br>"
|
||||
"<b>Size</b> - The length of each grain, in Hz. By default, new grains will be created at double this rate. <br>In most cases, you'll want this to be set to higher frequencies when shifting the pitch upward, and vice-versa. <br>"
|
||||
"<br><h3>Random:</h3>"
|
||||
"<b>Spray</b> - The amount of randomization for the playback position of each grain, in seconds. <br>This does not change when the grain plays, but rather what audio the grain is pulling from. <br>For example, a value of 0.5 seconds will allow each grain to play back audio from up to half of a second ago.<br>It's oftentimes recommended to use at least a small amount of Spray, as this will break up the periodicity in the grains, which is usually the main artifact caused by a granular pitch shifter. <br>This will also make the grains uncorrelated with each other, guaranteeing that a grain Shape value of 2 will always be optimal.<br>"
|
||||
"<b>Jitter</b> - The amount of randomization for the pitch of each grain, in octaves.<br> This does not impact how often grains are created.<br>"
|
||||
"<b>Twitch</b> - The amount of randomization for how often new grains are created, in octaves. <br>Jitter and Twitch both use the same random numbers, so if they're at the same value, then the grain creation timings will be changed exactly proportionally to their change in pitch.<br>"
|
||||
"<br><h3>Stereo:</h3>"
|
||||
"<b>Pitch</b> - The total distance in pitch between both stereo channels, in 12EDO semitones.<br> Half of the amount of pitch shifting shown will be applied to the right channel, and the opposite to the left channel.<br>"
|
||||
"<b>Spray</b> - The allowed distance between each channel's randomized position with the Spray feature in the Random category. <br>A value of 1 makes the Spray values in each channel entirely unlinked."
|
||||
"<br><h3>Shape:</h3>"
|
||||
"<b>Shape</b> - The shape of each grain's fades. In most cases, 2 is the optimal value, providing equal-power fades. <br>However, when the plugin is performing minimal pitch shifting and has most of its parameters at default, a value of 1 may be more optimal, providing equal-gain fades. <br>All fades are designed for 50% grain overlap.<br>"
|
||||
"<b>Fade</b> - The length of the grain fades. A value of 1 provides the cleanest fades, causing those fades to reach across the entire grain. <br>Values below 1 make the fade artifacts more audible, but those fades will only apply to the outer edges of each grain. <br>A value of 0 will result in clicking sounds due to the fades no longer being present.<br>"
|
||||
"<br><h3>Delay:</h3>"
|
||||
"<b>Feedback</b> - The amount of feedback for the pitch shifter.<br> This feeds a portion of the pitch shifter output back into the input buffer. Large values can be dangerous.<br>"
|
||||
"<b>Latency</b> - The minimum amount of latency the pitch shifter will have.<br> This granular pitch shifter dynamically changes its latency to be at the minimum possible amount depending on your settings. <br>If you'd like for this latency to be more predictable, you may increase the value of this parameter until the latency no longer changes. <br>This parameter may also be used to be set the minimum amount of delay for the feedback.<br>A larger latency amount can remove subtle fluttering artifacts that may result from automating the pitch shifting amount at high speeds."
|
||||
"<br><h3>Miscellaneous:</h3>"
|
||||
"<b>Prefilter</b> - Enables a 12 dB lowpass filter prior to the pitch shifting which automatically adjusts its cutoff to drastically reduce any resulting aliasing.<br>"
|
||||
"<b>Density</b> - The multiplier for how often grains are spawned. <br>This will increase the grain overlap above 50%. <br>It will create painful piercing sounds if you don't make use of any of the knobs in the Random category. <br>Otherwise, you can get some interesting effects similar to unison or a stationary Paulstretch. <br>Note that this knob uses by far the most CPU out of any parameter in this plugin when increased.<br>"
|
||||
"<b>Glide</b> - The length of interpolation for the amount of pitch shifting.<br> A small amount of glide is very effective for cleaning up many of the artifacts that may result from changing the pitch shift amount over time. <br>"
|
||||
"<b>Range</b> - The length of the pitch shifter's internal ring buffer.<br> Changing this will change the minimum and maximum values for some of the other parameters, which are listed in each of the options.<br> Increase it if you need parameter values that aren't supported with the minimum buffer length. Otherwise, it's best to leave it at its minimum value.<br>"
|
||||
;
|
||||
|
||||
GranularPitchShifterHelpView::GranularPitchShifterHelpView():QTextEdit(s_helpText)
|
||||
{
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5,12,0))
|
||||
// Bug workaround: https://codereview.qt-project.org/c/qt/qtbase/+/225348
|
||||
using ::operator|;
|
||||
#endif
|
||||
setWindowTitle("Granular Pitch Shifter Help");
|
||||
setTextInteractionFlags(Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
|
||||
getGUI()->mainWindow()->addWindowedWidget(this);
|
||||
parentWidget()->setAttribute(Qt::WA_DeleteOnClose, false);
|
||||
parentWidget()->setWindowIcon(PLUGIN_NAME::getIconPixmap("logo"));
|
||||
|
||||
// No maximize button
|
||||
Qt::WindowFlags flags = parentWidget()->windowFlags();
|
||||
flags &= ~Qt::WindowMaximizeButtonHint;
|
||||
parentWidget()->setWindowFlags(flags);
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
75
plugins/GranularPitchShifter/GranularPitchShifterControlDialog.h
Executable file
75
plugins/GranularPitchShifter/GranularPitchShifterControlDialog.h
Executable file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* GranularPitchShifterControlDialog.h
|
||||
*
|
||||
* Copyright (c) 2024 Lost Robot <r94231/at/gmail/dot/com>
|
||||
*
|
||||
* 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_GRANULAR_PITCH_SHIFTER_CONTROLS_H
|
||||
#define LMMS_GRANULAR_PITCH_SHIFTER_CONTROLS_H
|
||||
|
||||
#include "EffectControlDialog.h"
|
||||
|
||||
#include <QTextEdit>
|
||||
#include "ComboBox.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class GranularPitchShifterControls;
|
||||
class FloatModel;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class Knob;
|
||||
|
||||
class GranularPitchShifterControlDialog : public EffectControlDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GranularPitchShifterControlDialog(GranularPitchShifterControls* controls);
|
||||
~GranularPitchShifterControlDialog() override = default;
|
||||
public slots:
|
||||
void showHelpWindow();
|
||||
};
|
||||
|
||||
class GranularPitchShifterHelpView : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static GranularPitchShifterHelpView* getInstance()
|
||||
{
|
||||
static GranularPitchShifterHelpView instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
private:
|
||||
GranularPitchShifterHelpView();
|
||||
static QString s_helpText;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GRANULAR_PITCH_SHIFTER_CONTROLS_H
|
||||
149
plugins/GranularPitchShifter/GranularPitchShifterControls.cpp
Executable file
149
plugins/GranularPitchShifter/GranularPitchShifterControls.cpp
Executable file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* GranularPitchShifterControls.cpp
|
||||
*
|
||||
* Copyright (c) 2024 Lost Robot <r94231/at/gmail/dot/com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QDomElement>
|
||||
|
||||
#include "GranularPitchShifterControls.h"
|
||||
#include "GranularPitchShifterEffect.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
GranularPitchShifterControls::GranularPitchShifterControls(GranularPitchShifterEffect* effect) :
|
||||
EffectControls(effect),
|
||||
m_effect(effect),
|
||||
m_pitchModel(1.f, -48.f, 24.f, 0.01f, this, tr("Pitch")),
|
||||
m_sizeModel(10.f, 2.f, 1000.f, 0.001f, this, tr("Grain Size")),
|
||||
m_sprayModel(0.005f, 0.f, 0.5f, 0.0001f, this, tr("Spray")),
|
||||
m_jitterModel(0.f, 0.f, 1.f, 0.0001f, this, tr("Jitter")),
|
||||
m_twitchModel(0.f, 0.f, 1.f, 0.0001f, this, tr("Twitch")),
|
||||
m_pitchSpreadModel(0.f, -24.f, 24.f, 0.01f, this, tr("Pitch Stereo Spread")),
|
||||
m_spraySpreadModel(0.f, 0.f, 1.f, 0.0001f, this, tr("Spray Stereo")),
|
||||
m_shapeModel(2.f, 1.f, 2.f, 0.0001f, this, tr("Shape")),
|
||||
m_fadeLengthModel(1.f, 0.001f, 1.f, 0.00001f, this, tr("Fade Length")),
|
||||
m_feedbackModel(0.f, 0.f, 1.f, 0.00001f, this, tr("Feedback")),
|
||||
m_minLatencyModel(0.01f, 0.f, 1.f, 0.00001f, this, tr("Minimum Allowed Latency")),
|
||||
m_prefilterModel(true, this, tr("Prefilter")),
|
||||
m_densityModel(1.f, 1.f, 16.f, 0.0001f, this, tr("Density")),
|
||||
m_glideModel(0.01f, 0.f, 1.f, 0.0001f, this, tr("Glide")),
|
||||
m_rangeModel(this, tr("Ring Buffer Length"))
|
||||
{
|
||||
m_sizeModel.setScaleLogarithmic(true);
|
||||
m_sprayModel.setScaleLogarithmic(true);
|
||||
m_spraySpreadModel.setScaleLogarithmic(true);
|
||||
m_minLatencyModel.setScaleLogarithmic(true);
|
||||
m_densityModel.setScaleLogarithmic(true);
|
||||
m_glideModel.setScaleLogarithmic(true);
|
||||
|
||||
m_rangeModel.addItem(tr("5 Seconds"));
|
||||
m_rangeModel.addItem(tr("10 Seconds (Size)"));
|
||||
m_rangeModel.addItem(tr("40 Seconds (Size and Pitch)"));
|
||||
m_rangeModel.addItem(tr("40 Seconds (Size and Spray and Jitter)"));
|
||||
m_rangeModel.addItem(tr("120 Seconds (All of the above)"));
|
||||
|
||||
connect(&m_rangeModel, &ComboBoxModel::dataChanged, this, &GranularPitchShifterControls::updateRange);
|
||||
}
|
||||
|
||||
void GranularPitchShifterControls::updateRange()
|
||||
{
|
||||
switch (m_rangeModel.value())
|
||||
{
|
||||
case 0:// 5 seconds
|
||||
m_sizeModel.setRange(4.f, 1000.f, 0.001f);
|
||||
m_pitchModel.setRange(-48.f, 24.f, 0.01f);
|
||||
m_sprayModel.setRange(0.f, 0.5f, 0.0001f);
|
||||
m_jitterModel.setRange(0.f, 1.f, 0.0001f);
|
||||
break;
|
||||
case 1:// 10 seconds (size)
|
||||
m_sizeModel.setRange(2.f, 1000.f, 0.001f);
|
||||
m_pitchModel.setRange(-48.f, 24.f, 0.01f);
|
||||
m_sprayModel.setRange(0.f, 0.5f, 0.0001f);
|
||||
m_jitterModel.setRange(0.f, 1.f, 0.0001f);
|
||||
break;
|
||||
case 2:// 40 seconds (size and pitch)
|
||||
m_sizeModel.setRange(2.f, 1000.f, 0.001f);
|
||||
m_pitchModel.setRange(-48.f, 48.f, 0.01f);
|
||||
m_sprayModel.setRange(0.f, 0.5f, 0.0001f);
|
||||
m_jitterModel.setRange(0.f, 1.f, 0.0001f);
|
||||
break;
|
||||
case 3:// 40 seconds (size and spray and jitter)
|
||||
m_sizeModel.setRange(2.f, 1000.f, 0.001f);
|
||||
m_pitchModel.setRange(-48.f, 24.f, 0.01f);
|
||||
m_sprayModel.setRange(0.f, 20.f, 0.0001f);
|
||||
m_jitterModel.setRange(0.f, 2.f, 0.0001f);
|
||||
break;
|
||||
case 4:// 120 seconds (all of the above)
|
||||
m_sizeModel.setRange(2.f, 1000.f, 0.001f);
|
||||
m_pitchModel.setRange(-48.f, 48.f, 0.01f);
|
||||
m_sprayModel.setRange(0.f, 40.f, 0.0001f);
|
||||
m_jitterModel.setRange(0.f, 2.f, 0.0001f);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_effect->sampleRateNeedsUpdate();
|
||||
}
|
||||
|
||||
void GranularPitchShifterControls::loadSettings(const QDomElement& parent)
|
||||
{
|
||||
// must be loaded first so the ranges are set properly
|
||||
m_rangeModel.loadSettings(parent, "range");
|
||||
|
||||
m_pitchModel.loadSettings(parent, "pitch");
|
||||
m_sizeModel.loadSettings(parent, "size");
|
||||
m_sprayModel.loadSettings(parent, "spray");
|
||||
m_jitterModel.loadSettings(parent, "jitter");
|
||||
m_twitchModel.loadSettings(parent, "twitch");
|
||||
m_pitchSpreadModel.loadSettings(parent, "pitchSpread");
|
||||
m_spraySpreadModel.loadSettings(parent, "spraySpread");
|
||||
m_shapeModel.loadSettings(parent, "shape");
|
||||
m_fadeLengthModel.loadSettings(parent, "fadeLength");
|
||||
m_feedbackModel.loadSettings(parent, "feedback");
|
||||
m_minLatencyModel.loadSettings(parent, "minLatency");
|
||||
m_prefilterModel.loadSettings(parent, "prefilter");
|
||||
m_densityModel.loadSettings(parent, "density");
|
||||
m_glideModel.loadSettings(parent, "glide");
|
||||
}
|
||||
|
||||
void GranularPitchShifterControls::saveSettings(QDomDocument& doc, QDomElement& parent)
|
||||
{
|
||||
m_rangeModel.saveSettings(doc, parent, "range");
|
||||
m_pitchModel.saveSettings(doc, parent, "pitch");
|
||||
m_sizeModel.saveSettings(doc, parent, "size");
|
||||
m_sprayModel.saveSettings(doc, parent, "spray");
|
||||
m_jitterModel.saveSettings(doc, parent, "jitter");
|
||||
m_twitchModel.saveSettings(doc, parent, "twitch");
|
||||
m_pitchSpreadModel.saveSettings(doc, parent, "pitchSpread");
|
||||
m_spraySpreadModel.saveSettings(doc, parent, "spraySpread");
|
||||
m_shapeModel.saveSettings(doc, parent, "shape");
|
||||
m_fadeLengthModel.saveSettings(doc, parent, "fadeLength");
|
||||
m_feedbackModel.saveSettings(doc, parent, "feedback");
|
||||
m_minLatencyModel.saveSettings(doc, parent, "minLatency");
|
||||
m_prefilterModel.saveSettings(doc, parent, "prefilter");
|
||||
m_densityModel.saveSettings(doc, parent, "density");
|
||||
m_glideModel.saveSettings(doc, parent, "glide");
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
87
plugins/GranularPitchShifter/GranularPitchShifterControls.h
Executable file
87
plugins/GranularPitchShifter/GranularPitchShifterControls.h
Executable file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* GranularPitchShifterControls.h
|
||||
*
|
||||
* Copyright (c) 2024 Lost Robot <r94231/at/gmail/dot/com>
|
||||
*
|
||||
* 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_GRANULAR_PITCH_SHIFTER_CONTROL_DIALOG_H
|
||||
#define LMMS_GRANULAR_PITCH_SHIFTER_CONTROL_DIALOG_H
|
||||
|
||||
#include "EffectControls.h"
|
||||
#include "GranularPitchShifterControlDialog.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class GranularPitchShifterEffect;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class GranularPitchShifterControlDialog;
|
||||
}
|
||||
|
||||
class GranularPitchShifterControls : public EffectControls
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GranularPitchShifterControls(GranularPitchShifterEffect* effect);
|
||||
~GranularPitchShifterControls() override = default;
|
||||
|
||||
void saveSettings(QDomDocument& doc, QDomElement& parent) override;
|
||||
void loadSettings(const QDomElement& parent) override;
|
||||
inline QString nodeName() const override
|
||||
{
|
||||
return "GranularPitchShifterControls";
|
||||
}
|
||||
gui::EffectControlDialog* createView() override
|
||||
{
|
||||
return new gui::GranularPitchShifterControlDialog(this);
|
||||
}
|
||||
int controlCount() override { return 4; }
|
||||
|
||||
public slots:
|
||||
void updateRange();
|
||||
|
||||
private:
|
||||
GranularPitchShifterEffect* m_effect;
|
||||
FloatModel m_pitchModel;
|
||||
FloatModel m_sizeModel;
|
||||
FloatModel m_sprayModel;
|
||||
FloatModel m_jitterModel;
|
||||
FloatModel m_twitchModel;
|
||||
FloatModel m_pitchSpreadModel;
|
||||
FloatModel m_spraySpreadModel;
|
||||
FloatModel m_shapeModel;
|
||||
FloatModel m_fadeLengthModel;
|
||||
FloatModel m_feedbackModel;
|
||||
FloatModel m_minLatencyModel;
|
||||
BoolModel m_prefilterModel;
|
||||
FloatModel m_densityModel;
|
||||
FloatModel m_glideModel;
|
||||
ComboBoxModel m_rangeModel;
|
||||
|
||||
friend class gui::GranularPitchShifterControlDialog;
|
||||
friend class GranularPitchShifterEffect;
|
||||
};
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GRANULAR_PITCH_SHIFTER_CONTROL_DIALOG_H
|
||||
296
plugins/GranularPitchShifter/GranularPitchShifterEffect.cpp
Executable file
296
plugins/GranularPitchShifter/GranularPitchShifterEffect.cpp
Executable file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* GranularPitchShifter.cpp
|
||||
*
|
||||
* Copyright (c) 2024 Lost Robot <r94231/at/gmail/dot/com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GranularPitchShifterEffect.h"
|
||||
|
||||
#include <cmath>
|
||||
#include "embed.h"
|
||||
#include "plugin_export.h"
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
extern "C"
|
||||
{
|
||||
Plugin::Descriptor PLUGIN_EXPORT granularpitchshifter_plugin_descriptor =
|
||||
{
|
||||
LMMS_STRINGIFY(PLUGIN_NAME),
|
||||
"Granular Pitch Shifter",
|
||||
QT_TRANSLATE_NOOP("PluginBrowser", "Granular pitch shifter"),
|
||||
"Lost Robot <r94231/at/gmail/dot/com>",
|
||||
0x0100,
|
||||
Plugin::Type::Effect,
|
||||
new PluginPixmapLoader("logo"),
|
||||
nullptr,
|
||||
nullptr,
|
||||
} ;
|
||||
}
|
||||
|
||||
|
||||
GranularPitchShifterEffect::GranularPitchShifterEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key) :
|
||||
Effect(&granularpitchshifter_plugin_descriptor, parent, key),
|
||||
m_granularpitchshifterControls(this),
|
||||
m_prefilter({PrefilterLowpass(), PrefilterLowpass()})
|
||||
{
|
||||
autoQuitModel()->setValue(autoQuitModel()->maxValue());
|
||||
|
||||
changeSampleRate();
|
||||
}
|
||||
|
||||
|
||||
bool GranularPitchShifterEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
|
||||
{
|
||||
if (!isEnabled() || !isRunning()) { return false; }
|
||||
|
||||
const float d = dryLevel();
|
||||
const float w = wetLevel();
|
||||
|
||||
const ValueBuffer* pitchBuf = m_granularpitchshifterControls.m_pitchModel.valueBuffer();
|
||||
const ValueBuffer* pitchSpreadBuf = m_granularpitchshifterControls.m_pitchSpreadModel.valueBuffer();
|
||||
|
||||
const float size = m_granularpitchshifterControls.m_sizeModel.value();
|
||||
const float shape = m_granularpitchshifterControls.m_shapeModel.value();
|
||||
const float jitter = m_granularpitchshifterControls.m_jitterModel.value();
|
||||
const float twitch = m_granularpitchshifterControls.m_twitchModel.value();
|
||||
const float spray = m_granularpitchshifterControls.m_sprayModel.value();
|
||||
const float spraySpread = m_granularpitchshifterControls.m_spraySpreadModel.value();
|
||||
const float density = m_granularpitchshifterControls.m_densityModel.value();
|
||||
const float glide = m_granularpitchshifterControls.m_glideModel.value();
|
||||
const int minLatency = m_granularpitchshifterControls.m_minLatencyModel.value() * m_sampleRate;
|
||||
const float densityInvRoot = std::sqrt(1.f / density);
|
||||
const float feedback = m_granularpitchshifterControls.m_feedbackModel.value();
|
||||
const float fadeLength = 1.f / m_granularpitchshifterControls.m_fadeLengthModel.value();
|
||||
const bool prefilter = m_granularpitchshifterControls.m_prefilterModel.value();
|
||||
|
||||
if (glide != m_oldGlide)
|
||||
{
|
||||
m_oldGlide = glide;
|
||||
m_glideCoef = glide > 0 ? std::exp(-1 / (glide * m_sampleRate)) : 0;
|
||||
}
|
||||
|
||||
const float shapeK = cosWindowApproxK(shape);
|
||||
const int sizeSamples = m_sampleRate / size;
|
||||
const float waitMult = sizeSamples / (density * 2);
|
||||
|
||||
for (fpp_t f = 0; f < frames; ++f)
|
||||
{
|
||||
const double pitch = (pitchBuf ? pitchBuf->value(f) : m_granularpitchshifterControls.m_pitchModel.value()) * (1. / 12.);
|
||||
const double pitchSpread = (pitchSpreadBuf ? pitchSpreadBuf->value(f) : m_granularpitchshifterControls.m_pitchSpreadModel.value()) * (1. / 24.);
|
||||
|
||||
// interpolate pitch depending on glide
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
double targetVal = pitch + pitchSpread * (i ? 1. : -1.);
|
||||
|
||||
if (targetVal == m_truePitch[i]) { continue; }
|
||||
m_updatePitches = true;
|
||||
|
||||
m_truePitch[i] = m_glideCoef * m_truePitch[i] + (1. - m_glideCoef) * targetVal;
|
||||
// we crudely lock the pitch to the target value once it gets close enough, so we can save on CPU
|
||||
if (std::abs(targetVal - m_truePitch[i]) < GlideSnagRadius) { m_truePitch[i] = targetVal; }
|
||||
}
|
||||
|
||||
// this stuff is computationally expensive, so we should only do it when necessary
|
||||
if (m_updatePitches)
|
||||
{
|
||||
m_updatePitches = false;
|
||||
|
||||
std::array<double, 2> speed = {
|
||||
std::exp2(m_truePitch[0]),
|
||||
std::exp2(m_truePitch[1])
|
||||
};
|
||||
std::array<double, 2> ratio = {
|
||||
speed[0] / m_speed[0],
|
||||
speed[1] / m_speed[1]
|
||||
};
|
||||
|
||||
for (int i = 0; i < m_grainCount; ++i)
|
||||
{
|
||||
for (int j = 0; j < 2; ++j)
|
||||
{
|
||||
m_grains[i].grainSpeed[j] *= ratio[j];
|
||||
|
||||
// we unfortunately need to do extra stuff to ensure these don't shoot past the write index...
|
||||
if (m_grains[i].grainSpeed[j] > 1)
|
||||
{
|
||||
double distance = m_writePoint - m_grains[i].readPoint[j] - SafetyLatency;
|
||||
if (distance <= 0) { distance += m_ringBufLength; }
|
||||
double grainSpeedRequired = ((m_grains[i].grainSpeed[j] - 1.) / distance) * (1. - m_grains[i].phase);
|
||||
m_grains[i].phaseSpeed[j] = std::max(m_grains[i].phaseSpeed[j], grainSpeedRequired);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_speed[0] = speed[0];
|
||||
m_speed[1] = speed[1];
|
||||
|
||||
// prevent aliasing by lowpassing frequencies that the pitch shifting would push above nyquist
|
||||
m_prefilter[0].setCoefs(m_sampleRate, std::min(m_nyquist / static_cast<float>(speed[0]), m_nyquist) * PrefilterBandwidth);
|
||||
m_prefilter[1].setCoefs(m_sampleRate, std::min(m_nyquist / static_cast<float>(speed[1]), m_nyquist) * PrefilterBandwidth);
|
||||
}
|
||||
|
||||
std::array<float, 2> s = {0, 0};
|
||||
std::array<float, 2> filtered = {buf[f][0], buf[f][1]};
|
||||
|
||||
// spawn a new grain if it's time
|
||||
if (++m_timeSinceLastGrain >= m_nextWaitRandomization * waitMult)
|
||||
{
|
||||
m_timeSinceLastGrain = 0;
|
||||
double randThing = (fast_rand()/static_cast<double>(FAST_RAND_MAX) * 2. - 1.);
|
||||
m_nextWaitRandomization = std::exp2(randThing * twitch);
|
||||
double grainSpeed = 1. / std::exp2(randThing * jitter);
|
||||
|
||||
std::array<float, 2> sprayResult = {0, 0};
|
||||
if (spray > 0)
|
||||
{
|
||||
sprayResult[0] = (fast_rand() / static_cast<float>(FAST_RAND_MAX)) * spray * m_sampleRate;
|
||||
sprayResult[1] = linearInterpolate(
|
||||
sprayResult[0],
|
||||
(fast_rand() / static_cast<float>(FAST_RAND_MAX)) * spray * m_sampleRate,
|
||||
spraySpread);
|
||||
}
|
||||
|
||||
std::array<int, 2> readPoint;
|
||||
int latency = std::max(static_cast<int>(std::max(sizeSamples * (std::max(m_speed[0], m_speed[1]) * grainSpeed - 1.), 0.) + SafetyLatency), minLatency);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
readPoint[i] = m_writePoint - latency - sprayResult[i];
|
||||
if (readPoint[i] < 0) { readPoint[i] += m_ringBufLength; }
|
||||
}
|
||||
const double phaseInc = 1. / sizeSamples;
|
||||
m_grains.push_back(Grain(grainSpeed * m_speed[0], grainSpeed * m_speed[1], phaseInc, phaseInc, readPoint[0], readPoint[1]));
|
||||
++m_grainCount;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_grainCount; ++i)
|
||||
{
|
||||
m_grains[i].phase += std::max(m_grains[i].phaseSpeed[0], m_grains[i].phaseSpeed[1]);
|
||||
if (m_grains[i].phase >= 1)
|
||||
{
|
||||
// grain is done, delete it
|
||||
std::swap(m_grains[i], m_grains[m_grainCount-1]);
|
||||
m_grains.pop_back();
|
||||
--i;
|
||||
--m_grainCount;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_grains[i].readPoint[0] += m_grains[i].grainSpeed[0];
|
||||
m_grains[i].readPoint[1] += m_grains[i].grainSpeed[1];
|
||||
if (m_grains[i].readPoint[0] >= m_ringBufLength) { m_grains[i].readPoint[0] -= m_ringBufLength; }
|
||||
if (m_grains[i].readPoint[1] >= m_ringBufLength) { m_grains[i].readPoint[1] -= m_ringBufLength; }
|
||||
|
||||
const float fadePos = std::clamp((-std::abs(-2.f * static_cast<float>(m_grains[i].phase) + 1.f) + 0.5f) * fadeLength + 0.5f, 0.f, 1.f);
|
||||
const float windowVal = cosHalfWindowApprox(fadePos, shapeK);
|
||||
s[0] += getHermiteSample(m_grains[i].readPoint[0], 0) * windowVal;
|
||||
s[1] += getHermiteSample(m_grains[i].readPoint[1], 1) * windowVal;
|
||||
}
|
||||
|
||||
// note that adding two signals together, when uncorrelated, results in a signal power multiplication of sqrt(2), not 2
|
||||
s[0] *= densityInvRoot;
|
||||
s[1] *= densityInvRoot;
|
||||
|
||||
// 1-pole highpass for DC offset removal, to make feedback safer
|
||||
s[0] -= (m_dcVal[0] = (1.f - m_dcCoeff) * s[0] + m_dcCoeff * m_dcVal[0]);
|
||||
s[1] -= (m_dcVal[1] = (1.f - m_dcCoeff) * s[1] + m_dcCoeff * m_dcVal[1]);
|
||||
|
||||
// cheap safety saturator to protect against infinite feedback
|
||||
if (feedback > 0)
|
||||
{
|
||||
s[0] = safetySaturate(s[0]);
|
||||
s[1] = safetySaturate(s[1]);
|
||||
}
|
||||
|
||||
if (++m_writePoint >= m_ringBufLength)
|
||||
{
|
||||
m_writePoint = 0;
|
||||
}
|
||||
if (prefilter)
|
||||
{
|
||||
filtered[0] = m_prefilter[0].process(filtered[0]);
|
||||
filtered[1] = m_prefilter[1].process(filtered[1]);
|
||||
}
|
||||
|
||||
m_ringBuf[m_writePoint][0] = filtered[0] + s[0] * feedback;
|
||||
m_ringBuf[m_writePoint][1] = filtered[1] + s[1] * feedback;
|
||||
|
||||
buf[f][0] = d * buf[f][0] + w * s[0];
|
||||
buf[f][1] = d * buf[f][1] + w * s[1];
|
||||
}
|
||||
|
||||
if (m_sampleRateNeedsUpdate)
|
||||
{
|
||||
m_sampleRateNeedsUpdate = false;
|
||||
changeSampleRate();
|
||||
}
|
||||
|
||||
return isRunning();
|
||||
}
|
||||
|
||||
void GranularPitchShifterEffect::changeSampleRate()
|
||||
{
|
||||
const int range = m_granularpitchshifterControls.m_rangeModel.value();
|
||||
const float ringBufLength = RangeSeconds[range];
|
||||
|
||||
m_sampleRate = Engine::audioEngine()->outputSampleRate();
|
||||
m_nyquist = m_sampleRate / 2;
|
||||
|
||||
m_ringBufLength = m_sampleRate * ringBufLength;
|
||||
m_ringBuf.resize(m_ringBufLength);
|
||||
for (size_t i = 0; i < m_ringBufLength; ++i)
|
||||
{
|
||||
m_ringBuf[i][0] = 0;
|
||||
m_ringBuf[i][1] = 0;
|
||||
}
|
||||
m_writePoint = 0;
|
||||
|
||||
m_oldGlide = -1;
|
||||
|
||||
m_updatePitches = true;
|
||||
|
||||
m_grains.clear();
|
||||
m_grainCount = 0;
|
||||
m_grains.reserve(8);// arbitrary
|
||||
|
||||
m_dcCoeff = std::exp(-2.0 * F_PI * DcRemovalHz / m_sampleRate);
|
||||
|
||||
const double pitch = m_granularpitchshifterControls.m_pitchModel.value() * (1. / 12.);
|
||||
const double pitchSpread = m_granularpitchshifterControls.m_pitchSpreadModel.value() * (1. / 24.);
|
||||
m_truePitch[0] = pitch - pitchSpread;
|
||||
m_truePitch[1] = pitch + pitchSpread;
|
||||
m_speed[0] = std::exp2(m_truePitch[0]);
|
||||
m_speed[1] = std::exp2(m_truePitch[1]);
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// necessary for getting instance out of shared lib
|
||||
PLUGIN_EXPORT Plugin* lmms_plugin_main(Model* parent, void* data)
|
||||
{
|
||||
return new GranularPitchShifterEffect(parent, static_cast<const Plugin::Descriptor::SubPluginFeatures::Key*>(data));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace lmms
|
||||
185
plugins/GranularPitchShifter/GranularPitchShifterEffect.h
Executable file
185
plugins/GranularPitchShifter/GranularPitchShifterEffect.h
Executable file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* GranularPitchShifter.h
|
||||
*
|
||||
* Copyright (c) 2024 Lost Robot <r94231/at/gmail/dot/com>
|
||||
*
|
||||
* 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_GRANULAR_PITCH_SHIFTER_EFFECT_H
|
||||
#define LMMS_GRANULAR_PITCH_SHIFTER_EFFECT_H
|
||||
|
||||
#include "Effect.h"
|
||||
#include "GranularPitchShifterControls.h"
|
||||
|
||||
#include "BasicFilters.h"
|
||||
#include "interpolation.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
constexpr float PrefilterBandwidth = 0.96f;// 96% of nyquist
|
||||
constexpr double GlideSnagRadius = 0.001;
|
||||
constexpr int SafetyLatency = 3;
|
||||
constexpr float RangeSeconds[5] = {5, 10, 40, 40, 120};
|
||||
constexpr float DcRemovalHz = 7.f;
|
||||
constexpr float SatuSafeVol = 16.f;
|
||||
constexpr float SatuStrength = 0.001f;
|
||||
|
||||
|
||||
class GranularPitchShifterEffect : public Effect
|
||||
{
|
||||
public:
|
||||
GranularPitchShifterEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
|
||||
~GranularPitchShifterEffect() override = default;
|
||||
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
return &m_granularpitchshifterControls;
|
||||
}
|
||||
|
||||
// double index and fraction are required for good quality
|
||||
float getHermiteSample(double index, int ch)
|
||||
{
|
||||
const int index_floor = static_cast<int>(index);
|
||||
const double fraction = index - index_floor;
|
||||
|
||||
float v0, v1, v2, v3;
|
||||
|
||||
if (index_floor == 0) { v0 = m_ringBuf[m_ringBuf.size() - 1][ch]; }
|
||||
else { v0 = m_ringBuf[index_floor - 1][ch]; }
|
||||
|
||||
v1 = m_ringBuf[index_floor][ch];
|
||||
|
||||
if(index_floor >= m_ringBuf.size() - 2)
|
||||
{
|
||||
v2 = m_ringBuf[(index_floor + 1) % m_ringBuf.size()][ch];
|
||||
v3 = m_ringBuf[(index_floor + 2) % m_ringBuf.size()][ch];
|
||||
}
|
||||
else
|
||||
{
|
||||
v2 = m_ringBuf[index_floor + 1][ch];
|
||||
v3 = m_ringBuf[index_floor + 2][ch];
|
||||
}
|
||||
|
||||
return hermiteInterpolate(v0, v1, v2, v3, static_cast<float>(fraction));
|
||||
}
|
||||
|
||||
// adapted from signalsmith's crossfade approximation:
|
||||
// https://signalsmith-audio.co.uk/writing/2021/cheap-energy-crossfade
|
||||
float cosHalfWindowApprox(float x, float k)
|
||||
{
|
||||
float A = x * (1 - x);
|
||||
float B = A * (1 + k * A);
|
||||
float C = (B + x);
|
||||
return C * C;
|
||||
}
|
||||
// 1-2 fades between equal-gain and equal-power
|
||||
float cosWindowApproxK(float p)
|
||||
{
|
||||
return -6.0026608f + p * (6.8773512f - 1.5838104f * p);
|
||||
}
|
||||
|
||||
// designed to use minimal CPU if the input isn't loud
|
||||
float safetySaturate(float input)
|
||||
{
|
||||
float absInput = std::abs(input);
|
||||
return absInput <= SatuSafeVol ? input :
|
||||
std::copysign((absInput - SatuSafeVol) / (1 + (absInput - SatuSafeVol) * SatuStrength) + SatuSafeVol, input);
|
||||
}
|
||||
|
||||
void sampleRateNeedsUpdate() { m_sampleRateNeedsUpdate = true; }
|
||||
|
||||
void changeSampleRate();
|
||||
|
||||
private:
|
||||
struct PrefilterLowpass
|
||||
{
|
||||
float m_v0z = 0.f, m_v1 = 0.f, m_v2 = 0.f;
|
||||
float m_g1, m_g2, m_g3, m_g4;
|
||||
|
||||
void setCoefs(float sampleRate, float cutoff)
|
||||
{
|
||||
const float g = std::tan(F_PI * cutoff / sampleRate);
|
||||
const float ginv = g / (1.f + g * (g + F_SQRT_2));
|
||||
m_g1 = ginv;
|
||||
m_g2 = 2.f * (g + F_SQRT_2) * ginv;
|
||||
m_g3 = g * ginv;
|
||||
m_g4 = 2.f * ginv;
|
||||
}
|
||||
|
||||
float process(float input)
|
||||
{
|
||||
const float v1z = m_v1;
|
||||
const float v3 = input + m_v0z - 2.f * m_v2;
|
||||
m_v1 += m_g1 * v3 - m_g2 * v1z;
|
||||
m_v2 += m_g3 * v3 + m_g4 * v1z;
|
||||
m_v0z = input;
|
||||
return m_v2;
|
||||
}
|
||||
};
|
||||
|
||||
struct Grain
|
||||
{
|
||||
Grain(double grainSpeedL, double grainSpeedR, double phaseSpeedL, double phaseSpeedR, double readPointL, double readPointR) :
|
||||
readPoint{readPointL, readPointR},
|
||||
phaseSpeed{phaseSpeedL, phaseSpeedR},
|
||||
grainSpeed{grainSpeedL, grainSpeedR},
|
||||
phase{0}
|
||||
{}
|
||||
std::array<double, 2> readPoint;
|
||||
std::array<double, 2> phaseSpeed;
|
||||
std::array<double, 2> grainSpeed;
|
||||
double phase;
|
||||
};
|
||||
|
||||
GranularPitchShifterControls m_granularpitchshifterControls;
|
||||
|
||||
std::vector<std::array<float, 2>> m_ringBuf;
|
||||
std::vector<Grain> m_grains;
|
||||
|
||||
std::array<PrefilterLowpass, 2> m_prefilter;
|
||||
std::array<double, 2> m_speed = {1, 1};
|
||||
std::array<double, 2> m_truePitch = {0, 0};
|
||||
std::array<float, 2> m_dcVal = {0, 0};
|
||||
|
||||
float m_sampleRate;
|
||||
float m_nyquist;
|
||||
float m_nextWaitRandomization = 1;
|
||||
float m_dcCoeff;
|
||||
|
||||
int m_ringBufLength = 0;
|
||||
int m_writePoint = 0;
|
||||
int m_grainCount = 0;
|
||||
int m_timeSinceLastGrain = 999999999;
|
||||
|
||||
double m_oldGlide = -1;
|
||||
double m_glideCoef = 0;
|
||||
|
||||
bool m_sampleRateNeedsUpdate = false;
|
||||
bool m_updatePitches = true;
|
||||
|
||||
friend class GranularPitchShifterControls;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_GRANULAR_PITCH_SHIFTER_EFFECT_H
|
||||
BIN
plugins/GranularPitchShifter/artwork.png
Executable file
BIN
plugins/GranularPitchShifter/artwork.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
BIN
plugins/GranularPitchShifter/help_active.png
Executable file
BIN
plugins/GranularPitchShifter/help_active.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
BIN
plugins/GranularPitchShifter/help_inactive.png
Normal file
BIN
plugins/GranularPitchShifter/help_inactive.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
BIN
plugins/GranularPitchShifter/logo.png
Executable file
BIN
plugins/GranularPitchShifter/logo.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 774 B |
BIN
plugins/GranularPitchShifter/prefilter_active.png
Executable file
BIN
plugins/GranularPitchShifter/prefilter_active.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 805 B |
BIN
plugins/GranularPitchShifter/prefilter_inactive.png
Executable file
BIN
plugins/GranularPitchShifter/prefilter_inactive.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 890 B |
@@ -156,7 +156,7 @@ using DistFX = DspEffectLibrary::Distortion;
|
||||
using SweepOsc = KickerOsc<DspEffectLibrary::MonoToStereoAdaptor<DistFX>>;
|
||||
|
||||
void KickerInstrument::playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer )
|
||||
SampleFrame* _working_buffer )
|
||||
{
|
||||
const fpp_t frames = _n->framesLeftForCurrentPeriod();
|
||||
const f_cnt_t offset = _n->noteOffset();
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
~KickerInstrument() override = default;
|
||||
|
||||
void playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer ) override;
|
||||
SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
void saveSettings(QDomDocument& doc, QDomElement& elem) override;
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
|
||||
virtual ~KickerOsc() = default;
|
||||
|
||||
void update( sampleFrame* buf, const fpp_t frames, const float sampleRate )
|
||||
void update( SampleFrame* buf, const fpp_t frames, const float sampleRate )
|
||||
{
|
||||
for( fpp_t frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
|
||||
@@ -57,21 +57,17 @@ LOMMEffect::LOMMEffect(Model* parent, const Descriptor::SubPluginFeatures::Key*
|
||||
m_hp2(m_sampleRate),
|
||||
m_ap(m_sampleRate),
|
||||
m_needsUpdate(true),
|
||||
m_coeffPrecalc(-0.05),
|
||||
m_crestTimeConst(0.999),
|
||||
m_coeffPrecalc(-0.05f),
|
||||
m_crestTimeConst(0.999f),
|
||||
m_lookWrite(0),
|
||||
m_lookBufLength(2)
|
||||
{
|
||||
autoQuitModel()->setValue(autoQuitModel()->maxValue());
|
||||
|
||||
m_yL[0][0] = m_yL[0][1] = LOMM_MIN_FLOOR;
|
||||
m_yL[1][0] = m_yL[1][1] = LOMM_MIN_FLOOR;
|
||||
m_yL[2][0] = m_yL[2][1] = LOMM_MIN_FLOOR;
|
||||
|
||||
m_ap.setFilterType(BasicFilters<2>::FilterType::AllPass);
|
||||
|
||||
connect(Engine::audioEngine(), SIGNAL(sampleRateChanged()), this, SLOT(changeSampleRate()));
|
||||
emit changeSampleRate();
|
||||
changeSampleRate();
|
||||
}
|
||||
|
||||
void LOMMEffect::changeSampleRate()
|
||||
@@ -97,10 +93,15 @@ void LOMMEffect::changeSampleRate()
|
||||
m_scLookBuf[j][i].resize(m_lookBufLength, LOMM_MIN_FLOOR);
|
||||
}
|
||||
}
|
||||
|
||||
std::fill(m_yL.begin(), m_yL.end(), std::array<float, 2>{LOMM_MIN_FLOOR, LOMM_MIN_FLOOR});
|
||||
m_rms = m_gainResult = m_displayIn = m_displayOut = m_prevOut = m_yL;
|
||||
m_crestPeakVal[0] = m_crestPeakVal[1] = LOMM_MIN_FLOOR;
|
||||
m_crestRmsVal = m_crestFactorVal = m_crestPeakVal;
|
||||
}
|
||||
|
||||
|
||||
bool LOMMEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
|
||||
bool LOMMEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
|
||||
{
|
||||
if (!isEnabled() || !isRunning())
|
||||
{
|
||||
@@ -111,7 +112,7 @@ bool LOMMEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
|
||||
{
|
||||
m_lp1.setLowpass(m_lommControls.m_split1Model.value());
|
||||
m_hp1.setHighpass(m_lommControls.m_split1Model.value());
|
||||
m_ap.calcFilterCoeffs(m_lommControls.m_split1Model.value(), 0.70710678118);
|
||||
m_ap.calcFilterCoeffs(m_lommControls.m_split1Model.value(), 0.70710678118f);
|
||||
}
|
||||
if (m_needsUpdate || m_lommControls.m_split2Model.isValueChanged())
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
constexpr inline float LOMM_MIN_FLOOR = 0.00012589;// -72 dBFS
|
||||
constexpr inline float LOMM_MIN_FLOOR = 0.00012589f;// -72 dBFS
|
||||
constexpr inline float LOMM_MAX_LOOKAHEAD = 20.f;
|
||||
constexpr inline float LOMM_AUTO_TIME_ADJUST = 5.f;
|
||||
|
||||
@@ -45,7 +45,7 @@ class LOMMEffect : public Effect
|
||||
public:
|
||||
LOMMEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
|
||||
~LOMMEffect() override = default;
|
||||
bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override;
|
||||
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
|
||||
@@ -35,55 +35,55 @@ namespace lmms
|
||||
LOMMControls::LOMMControls(LOMMEffect* effect) :
|
||||
EffectControls(effect),
|
||||
m_effect(effect),
|
||||
m_depthModel(0.4, 0, 1, 0.00001, this, tr("Depth")),
|
||||
m_timeModel(1, 0, 10, 0.00001, this, tr("Time")),
|
||||
m_inVolModel(0, -48, 48, 0.00001, this, tr("Input Volume")),
|
||||
m_outVolModel(8, -48, 48, 0.00001, this, tr("Output Volume")),
|
||||
m_upwardModel(1, 0, 2, 0.00001, this, tr("Upward Depth")),
|
||||
m_downwardModel(1, 0, 2, 0.00001, this, tr("Downward Depth")),
|
||||
m_split1Model(2500, 20, 20000, 0.01, this, tr("High/Mid Split")),
|
||||
m_split2Model(88.3, 20, 20000, 0.01, this, tr("Mid/Low Split")),
|
||||
m_depthModel(0.4f, 0, 1, 0.00001f, this, tr("Depth")),
|
||||
m_timeModel(1, 0, 10, 0.00001f, this, tr("Time")),
|
||||
m_inVolModel(0, -48, 48, 0.00001f, this, tr("Input Volume")),
|
||||
m_outVolModel(8, -48, 48, 0.00001f, this, tr("Output Volume")),
|
||||
m_upwardModel(1, 0, 2, 0.00001f, this, tr("Upward Depth")),
|
||||
m_downwardModel(1, 0, 2, 0.00001f, this, tr("Downward Depth")),
|
||||
m_split1Model(2500, 20, 20000, 0.01f, this, tr("High/Mid Split")),
|
||||
m_split2Model(88.3f, 20, 20000, 0.01f, this, tr("Mid/Low Split")),
|
||||
m_split1EnabledModel(true, this, tr("Enable High/Mid Split")),
|
||||
m_split2EnabledModel(true, this, tr("Enable Mid/Low Split")),
|
||||
m_band1EnabledModel(true, this, tr("Enable High Band")),
|
||||
m_band2EnabledModel(true, this, tr("Enable Mid Band")),
|
||||
m_band3EnabledModel(true, this, tr("Enable Low Band")),
|
||||
m_inHighModel(0, -48, 48, 0.00001, this, tr("High Input Volume")),
|
||||
m_inMidModel(0, -48, 48, 0.00001, this, tr("Mid Input Volume")),
|
||||
m_inLowModel(0, -48, 48, 0.00001, this, tr("Low Input Volume")),
|
||||
m_outHighModel(4.6, -48, 48, 0.00001, this, tr("High Output Volume")),
|
||||
m_outMidModel(0.0, -48, 48, 0.00001, this, tr("Mid Output Volume")),
|
||||
m_outLowModel(4.6, -48, 48, 0.00001, this, tr("Low Output Volume")),
|
||||
m_aThreshHModel(-30.3, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001, this, tr("Above Threshold High")),
|
||||
m_aThreshMModel(-25.0, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001, this, tr("Above Threshold Mid")),
|
||||
m_aThreshLModel(-28.6, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001, this, tr("Above Threshold Low")),
|
||||
m_aRatioHModel(99.99, 1, 99.99, 0.01, this, tr("Above Ratio High")),
|
||||
m_aRatioMModel(66.7, 1, 99.99, 0.01, this, tr("Above Ratio Mid")),
|
||||
m_aRatioLModel(66.7, 1, 99.99, 0.01, this, tr("Above Ratio Low")),
|
||||
m_bThreshHModel(-35.6, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001, this, tr("Below Threshold High")),
|
||||
m_bThreshMModel(-36.6, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001, this, tr("Below Threshold Mid")),
|
||||
m_bThreshLModel(-35.6, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001, this, tr("Below Threshold Low")),
|
||||
m_bRatioHModel(4.17, 1, 99.99, 0.01, this, tr("Below Ratio High")),
|
||||
m_bRatioMModel(4.17, 1, 99.99, 0.01, this, tr("Below Ratio Mid")),
|
||||
m_bRatioLModel(4.17, 1, 99.99, 0.01, this, tr("Below Ratio Low")),
|
||||
m_atkHModel(13.5, 0, 1000, 0.001, this, tr("Attack High")),
|
||||
m_atkMModel(22.4, 0, 1000, 0.001, this, tr("Attack Mid")),
|
||||
m_atkLModel(47.8, 0, 1000, 0.001, this, tr("Attack Low")),
|
||||
m_relHModel(132, 0, 1000, 0.001, this, tr("Release High")),
|
||||
m_relMModel(282, 0, 1000, 0.001, this, tr("Release Mid")),
|
||||
m_relLModel(282, 0, 1000, 0.001, this, tr("Release Low")),
|
||||
m_rmsTimeModel(10, 0, 500, 0.001, this, tr("RMS Time")),
|
||||
m_kneeModel(6, 0, 36, 0.00001, this, tr("Knee")),
|
||||
m_rangeModel(36, 0, 96, 0.00001, this, tr("Range")),
|
||||
m_balanceModel(0, -18, 18, 0.00001, this, tr("Balance")),
|
||||
m_inHighModel(0, -48, 48, 0.00001f, this, tr("High Input Volume")),
|
||||
m_inMidModel(0, -48, 48, 0.00001f, this, tr("Mid Input Volume")),
|
||||
m_inLowModel(0, -48, 48, 0.00001f, this, tr("Low Input Volume")),
|
||||
m_outHighModel(4.6f, -48, 48, 0.00001f, this, tr("High Output Volume")),
|
||||
m_outMidModel(0.f, -48, 48, 0.00001f, this, tr("Mid Output Volume")),
|
||||
m_outLowModel(4.6f, -48, 48, 0.00001f, this, tr("Low Output Volume")),
|
||||
m_aThreshHModel(-30.3f, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001f, this, tr("Above Threshold High")),
|
||||
m_aThreshMModel(-25.f, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001f, this, tr("Above Threshold Mid")),
|
||||
m_aThreshLModel(-28.6f, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001f, this, tr("Above Threshold Low")),
|
||||
m_aRatioHModel(99.99f, 1, 99.99f, 0.01f, this, tr("Above Ratio High")),
|
||||
m_aRatioMModel(66.7f, 1, 99.99f, 0.01f, this, tr("Above Ratio Mid")),
|
||||
m_aRatioLModel(66.7f, 1, 99.99f, 0.01f, this, tr("Above Ratio Low")),
|
||||
m_bThreshHModel(-35.6f, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001f, this, tr("Below Threshold High")),
|
||||
m_bThreshMModel(-36.6f, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001f, this, tr("Below Threshold Mid")),
|
||||
m_bThreshLModel(-35.6f, LOMM_DISPLAY_MIN, LOMM_DISPLAY_MAX, 0.001f, this, tr("Below Threshold Low")),
|
||||
m_bRatioHModel(4.17f, 1, 99.99f, 0.01f, this, tr("Below Ratio High")),
|
||||
m_bRatioMModel(4.17f, 1, 99.99f, 0.01f, this, tr("Below Ratio Mid")),
|
||||
m_bRatioLModel(4.17f, 1, 99.99f, 0.01f, this, tr("Below Ratio Low")),
|
||||
m_atkHModel(13.5f, 0, 1000, 0.001f, this, tr("Attack High")),
|
||||
m_atkMModel(22.4f, 0, 1000, 0.001f, this, tr("Attack Mid")),
|
||||
m_atkLModel(47.8f, 0, 1000, 0.001f, this, tr("Attack Low")),
|
||||
m_relHModel(132, 0, 1000, 0.001f, this, tr("Release High")),
|
||||
m_relMModel(282, 0, 1000, 0.001f, this, tr("Release Mid")),
|
||||
m_relLModel(282, 0, 1000, 0.001f, this, tr("Release Low")),
|
||||
m_rmsTimeModel(10, 0, 500, 0.001f, this, tr("RMS Time")),
|
||||
m_kneeModel(6, 0, 36, 0.00001f, this, tr("Knee")),
|
||||
m_rangeModel(36, 0, 96, 0.00001f, this, tr("Range")),
|
||||
m_balanceModel(0, -18, 18, 0.00001f, this, tr("Balance")),
|
||||
m_depthScalingModel(true, this, tr("Scale output volume with Depth")),
|
||||
m_stereoLinkModel(false, this, tr("Stereo Link")),
|
||||
m_autoTimeModel(0, 0, 1, 0.00001, this, tr("Auto Time")),
|
||||
m_mixModel(1, 0, 1, 0.00001, this, tr("Mix")),
|
||||
m_autoTimeModel(0, 0, 1, 0.00001f, this, tr("Auto Time")),
|
||||
m_mixModel(1, 0, 1, 0.00001f, this, tr("Mix")),
|
||||
m_feedbackModel(false, this, tr("Feedback")),
|
||||
m_midsideModel(false, this, tr("Mid/Side")),
|
||||
m_lookaheadEnableModel(false, this, tr("Lookahead")),
|
||||
m_lookaheadModel(0.f, 0.f, LOMM_MAX_LOOKAHEAD, 0.01, this, tr("Lookahead Length")),
|
||||
m_lookaheadModel(0.f, 0.f, LOMM_MAX_LOOKAHEAD, 0.01f, this, tr("Lookahead Length")),
|
||||
m_lowSideUpwardSuppressModel(false, this, tr("Suppress upward compression for side band"))
|
||||
{
|
||||
auto models = {&m_timeModel, &m_inVolModel, &m_outVolModel, &m_inHighModel, &m_inMidModel,
|
||||
|
||||
@@ -129,7 +129,7 @@ void LadspaEffect::changeSampleRate()
|
||||
|
||||
|
||||
|
||||
bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
bool LadspaEffect::processAudioBuffer( SampleFrame* _buf,
|
||||
const fpp_t _frames )
|
||||
{
|
||||
m_pluginMutex.lock();
|
||||
@@ -140,13 +140,13 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
}
|
||||
|
||||
int frames = _frames;
|
||||
sampleFrame * o_buf = nullptr;
|
||||
QVarLengthArray<sample_t> sBuf(_frames * DEFAULT_CHANNELS);
|
||||
SampleFrame* o_buf = nullptr;
|
||||
QVarLengthArray<SampleFrame> sBuf(_frames);
|
||||
|
||||
if( m_maxSampleRate < Engine::audioEngine()->outputSampleRate() )
|
||||
{
|
||||
o_buf = _buf;
|
||||
_buf = reinterpret_cast<sampleFrame*>(sBuf.data());
|
||||
_buf = sBuf.data();
|
||||
sampleDown( o_buf, _buf, m_maxSampleRate );
|
||||
frames = _frames * m_maxSampleRate /
|
||||
Engine::audioEngine()->outputSampleRate();
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
const Descriptor::SubPluginFeatures::Key * _key );
|
||||
~LadspaEffect() override;
|
||||
|
||||
bool processAudioBuffer( sampleFrame * _buf,
|
||||
bool processAudioBuffer( SampleFrame* _buf,
|
||||
const fpp_t _frames ) override;
|
||||
|
||||
void setControl( int _control, LADSPA_Data _data );
|
||||
|
||||
@@ -209,7 +209,7 @@ Lb302Filter3Pole::Lb302Filter3Pole(Lb302FilterKnobState *p_fs) :
|
||||
void Lb302Filter3Pole::recalc()
|
||||
{
|
||||
// DO NOT CALL BASE CLASS
|
||||
vcf_e0 = 0.000001;
|
||||
vcf_e0 = 0.000001f;
|
||||
vcf_e1 = 1.0;
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ Lb302Synth::Lb302Synth( InstrumentTrack * _instrumentTrack ) :
|
||||
accentToggle( false, this, tr( "Accent" ) ),
|
||||
deadToggle( false, this, tr( "Dead" ) ),
|
||||
db24Toggle( false, this, tr( "24dB/oct Filter" ) ),
|
||||
vca_attack(1.0 - 0.96406088),
|
||||
vca_attack(1.f - 0.96406088f),
|
||||
vca_a0(0.5),
|
||||
vca_a(0.),
|
||||
vca_mode(VcaMode::NeverPlayed)
|
||||
@@ -462,7 +462,7 @@ inline float GET_INC(float freq) {
|
||||
return freq/Engine::audioEngine()->outputSampleRate(); // TODO: Use actual sampling rate.
|
||||
}
|
||||
|
||||
int Lb302Synth::process(sampleFrame *outbuf, const int size)
|
||||
int Lb302Synth::process(SampleFrame* outbuf, const int size)
|
||||
{
|
||||
const float sampleRatio = 44100.f / Engine::audioEngine()->outputSampleRate();
|
||||
|
||||
@@ -732,7 +732,7 @@ void Lb302Synth::initSlide()
|
||||
}
|
||||
|
||||
|
||||
void Lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer )
|
||||
void Lb302Synth::playNote( NotePlayHandle * _n, SampleFrame* _working_buffer )
|
||||
{
|
||||
if( _n->isMasterNote() || ( _n->hasParent() && _n->isReleased() ) )
|
||||
{
|
||||
@@ -791,7 +791,7 @@ void Lb302Synth::processNote( NotePlayHandle * _n )
|
||||
|
||||
|
||||
|
||||
void Lb302Synth::play( sampleFrame * _working_buffer )
|
||||
void Lb302Synth::play( SampleFrame* _working_buffer )
|
||||
{
|
||||
m_notesMutex.lock();
|
||||
while( ! m_notes.isEmpty() )
|
||||
|
||||
@@ -152,9 +152,9 @@ public:
|
||||
Lb302Synth( InstrumentTrack * _instrument_track );
|
||||
~Lb302Synth() override;
|
||||
|
||||
void play( sampleFrame * _working_buffer ) override;
|
||||
void play( SampleFrame* _working_buffer ) override;
|
||||
void playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer ) override;
|
||||
SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ private:
|
||||
|
||||
void recalcFilter();
|
||||
|
||||
int process(sampleFrame *outbuf, const int size);
|
||||
int process(SampleFrame* outbuf, const int size);
|
||||
|
||||
friend class gui::Lb302SynthView;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ Lv2Effect::Lv2Effect(Model* parent, const Descriptor::SubPluginFeatures::Key *ke
|
||||
|
||||
|
||||
|
||||
bool Lv2Effect::processAudioBuffer(sampleFrame *buf, const fpp_t frames)
|
||||
bool Lv2Effect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
|
||||
{
|
||||
if (!isEnabled() || !isRunning()) { return false; }
|
||||
Q_ASSERT(frames <= static_cast<fpp_t>(m_tmpOutputSmps.size()));
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
*/
|
||||
Lv2Effect(Model* parent, const Descriptor::SubPluginFeatures::Key* _key);
|
||||
|
||||
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
|
||||
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
|
||||
EffectControls* controls() override { return &m_controls; }
|
||||
|
||||
Lv2FxControls* lv2Controls() { return &m_controls; }
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
|
||||
private:
|
||||
Lv2FxControls m_controls;
|
||||
std::vector<sampleFrame> m_tmpOutputSmps;
|
||||
std::vector<SampleFrame> m_tmpOutputSmps;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ bool Lv2Instrument::handleMidiEvent(
|
||||
|
||||
// not yet working
|
||||
#ifndef LV2_INSTRUMENT_USE_MIDI
|
||||
void Lv2Instrument::playNote(NotePlayHandle *nph, sampleFrame *)
|
||||
void Lv2Instrument::playNote(NotePlayHandle *nph, SampleFrame*)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@@ -185,7 +185,7 @@ void Lv2Instrument::playNote(NotePlayHandle *nph, sampleFrame *)
|
||||
|
||||
|
||||
|
||||
void Lv2Instrument::play(sampleFrame *buf)
|
||||
void Lv2Instrument::play(SampleFrame* buf)
|
||||
{
|
||||
copyModelsFromLmms();
|
||||
|
||||
|
||||
@@ -77,9 +77,9 @@ public:
|
||||
bool handleMidiEvent(const MidiEvent &event,
|
||||
const TimePos &time = TimePos(), f_cnt_t offset = 0) override;
|
||||
#else
|
||||
void playNote(NotePlayHandle *nph, sampleFrame *) override;
|
||||
void playNote(NotePlayHandle *nph, SampleFrame*) override;
|
||||
#endif
|
||||
void play(sampleFrame *buf) override;
|
||||
void play(SampleFrame* buf) override;
|
||||
|
||||
/*
|
||||
misc
|
||||
|
||||
@@ -110,7 +110,7 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph ) :
|
||||
}
|
||||
|
||||
|
||||
void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf )
|
||||
void MonstroSynth::renderOutput( fpp_t _frames, SampleFrame* _buf )
|
||||
{
|
||||
float modtmp; // temp variable for freq modulation
|
||||
// macros for modulating with env/lfos
|
||||
@@ -514,7 +514,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf )
|
||||
}
|
||||
|
||||
sample_t O2R = 0.;
|
||||
if (len_r != 0.)
|
||||
if (pd_r != 0.)
|
||||
{
|
||||
len_r = BandLimitedWave::pdToLen(pd_r);
|
||||
if (m_counter2r > 0)
|
||||
@@ -865,31 +865,31 @@ inline sample_t MonstroSynth::calcSlope( int slope, sample_t s )
|
||||
MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) :
|
||||
Instrument( _instrument_track, &monstro_plugin_descriptor ),
|
||||
|
||||
m_osc1Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 1 volume" ) ),
|
||||
m_osc1Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 1 panning" ) ),
|
||||
m_osc1Vol(33.f, 0.f, 200.f, 0.1f, this, tr("Osc 1 volume")),
|
||||
m_osc1Pan(0.f, -100.f, 100.f, 0.1f, this, tr("Osc 1 panning")),
|
||||
m_osc1Crs( 0.0, -24.0, 24.0, 1.0, this, tr( "Osc 1 coarse detune" ) ),
|
||||
m_osc1Ftl( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 1 fine detune left" ) ),
|
||||
m_osc1Ftr( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 1 fine detune right" ) ),
|
||||
m_osc1Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 1 stereo phase offset" ) ),
|
||||
m_osc1Pw( 50.0, PW_MIN, PW_MAX, 0.01, this, tr( "Osc 1 pulse width" ) ),
|
||||
m_osc1Spo(0.f, -180.f, 180.f, 0.1f, this, tr("Osc 1 stereo phase offset")),
|
||||
m_osc1Pw(50.f, PW_MIN, PW_MAX, 0.01f, this, tr("Osc 1 pulse width")),
|
||||
m_osc1SSR( false, this, tr( "Osc 1 sync send on rise" ) ),
|
||||
m_osc1SSF( false, this, tr( "Osc 1 sync send on fall" ) ),
|
||||
|
||||
m_osc2Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 2 volume" ) ),
|
||||
m_osc2Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 2 panning" ) ),
|
||||
m_osc2Vol(33.f, 0.f, 200.f, 0.1f, this, tr("Osc 2 volume")),
|
||||
m_osc2Pan(0.f, -100.f, 100.f, 0.1f, this, tr("Osc 2 panning")),
|
||||
m_osc2Crs( 0.0, -24.0, 24.0, 1.0, this, tr( "Osc 2 coarse detune" ) ),
|
||||
m_osc2Ftl( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 2 fine detune left" ) ),
|
||||
m_osc2Ftr( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 2 fine detune right" ) ),
|
||||
m_osc2Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 2 stereo phase offset" ) ),
|
||||
m_osc2Spo(0.f, -180.f, 180.f, 0.1f, this, tr("Osc 2 stereo phase offset")),
|
||||
m_osc2Wave( this, tr( "Osc 2 waveform" ) ),
|
||||
m_osc2SyncH( false, this, tr( "Osc 2 sync hard" ) ),
|
||||
m_osc2SyncR( false, this, tr( "Osc 2 sync reverse" ) ),
|
||||
|
||||
m_osc3Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 3 volume" ) ),
|
||||
m_osc3Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 3 panning" ) ),
|
||||
m_osc3Vol(33.f, 0.f, 200.f, 0.1f, this, tr("Osc 3 volume")),
|
||||
m_osc3Pan(0.f, -100.f, 100.f, 0.1f, this, tr("Osc 3 panning")),
|
||||
m_osc3Crs( 0.0, -24.0, 24.0, 1.0, this, tr( "Osc 3 coarse detune" ) ),
|
||||
m_osc3Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 3 Stereo phase offset" ) ),
|
||||
m_osc3Sub( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 3 sub-oscillator mix" ) ),
|
||||
m_osc3Spo(0.f, -180.f, 180.f, 0.1f, this, tr("Osc 3 Stereo phase offset")),
|
||||
m_osc3Sub(0.f, -100.f, 100.f, 0.1f, this, tr("Osc 3 sub-oscillator mix")),
|
||||
m_osc3Wave1( this, tr( "Osc 3 waveform 1" ) ),
|
||||
m_osc3Wave2( this, tr( "Osc 3 waveform 2" ) ),
|
||||
m_osc3SyncH( false, this, tr( "Osc 3 sync hard" ) ),
|
||||
@@ -897,13 +897,13 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) :
|
||||
|
||||
m_lfo1Wave( this, tr( "LFO 1 waveform" ) ),
|
||||
m_lfo1Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "LFO 1 attack" ) ),
|
||||
m_lfo1Rate( 1.0f, 0.1, 10000.0, 0.1, 10000.0f, this, tr( "LFO 1 rate" ) ),
|
||||
m_lfo1Phs( 0.0, -180.0, 180.0, 0.1, this, tr( "LFO 1 phase" ) ),
|
||||
m_lfo1Rate(1.0f, 0.1f, 10000.f, 0.1f, 10000.0f, this, tr("LFO 1 rate")),
|
||||
m_lfo1Phs(0.f, -180.f, 180.f, 0.1f, this, tr("LFO 1 phase")),
|
||||
|
||||
m_lfo2Wave( this, tr( "LFO 2 waveform" ) ),
|
||||
m_lfo2Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "LFO 2 attack" ) ),
|
||||
m_lfo2Rate( 1.0f, 0.1, 10000.0, 0.1, 10000.0f, this, tr( "LFO 2 rate" ) ),
|
||||
m_lfo2Phs( 0.0, -180.0, 180.0, 0.1, this, tr( "LFO 2 phase" ) ),
|
||||
m_lfo2Rate(1.0f, 0.1f, 10000.f, 0.1f, 10000.0f, this, tr("LFO 2 rate")),
|
||||
m_lfo2Phs(0.0, -180.f, 180.f, 0.1f, this, tr("LFO 2 phase")),
|
||||
|
||||
m_env1Pre( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 1 pre-delay" ) ),
|
||||
m_env1Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 1 attack" ) ),
|
||||
@@ -1062,7 +1062,7 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) :
|
||||
|
||||
|
||||
void MonstroInstrument::playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer )
|
||||
SampleFrame* _working_buffer )
|
||||
{
|
||||
const fpp_t frames = _n->framesLeftForCurrentPeriod();
|
||||
const f_cnt_t offset = _n->noteOffset();
|
||||
|
||||
@@ -177,7 +177,7 @@ public:
|
||||
MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph );
|
||||
virtual ~MonstroSynth() = default;
|
||||
|
||||
void renderOutput( fpp_t _frames, sampleFrame * _buf );
|
||||
void renderOutput( fpp_t _frames, SampleFrame* _buf );
|
||||
|
||||
private:
|
||||
|
||||
@@ -357,7 +357,7 @@ public:
|
||||
~MonstroInstrument() override = default;
|
||||
|
||||
void playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer ) override;
|
||||
SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
void saveSettings( QDomDocument & _doc,
|
||||
|
||||
@@ -58,7 +58,7 @@ MultitapEchoEffect::MultitapEchoEffect( Model* parent, const Descriptor::SubPlug
|
||||
m_sampleRate( Engine::audioEngine()->outputSampleRate() ),
|
||||
m_sampleRatio( 1.0f / m_sampleRate )
|
||||
{
|
||||
m_work = new sampleFrame[Engine::audioEngine()->framesPerPeriod()];
|
||||
m_work = new SampleFrame[Engine::audioEngine()->framesPerPeriod()];
|
||||
m_buffer.reset();
|
||||
m_stages = static_cast<int>( m_controls.m_stages.value() );
|
||||
updateFilters( 0, 19 );
|
||||
@@ -83,7 +83,7 @@ void MultitapEchoEffect::updateFilters( int begin, int end )
|
||||
}
|
||||
|
||||
|
||||
void MultitapEchoEffect::runFilter( sampleFrame * dst, sampleFrame * src, StereoOnePole & filter, const fpp_t frames )
|
||||
void MultitapEchoEffect::runFilter( SampleFrame* dst, SampleFrame* src, StereoOnePole & filter, const fpp_t frames )
|
||||
{
|
||||
for( int f = 0; f < frames; ++f )
|
||||
{
|
||||
@@ -93,7 +93,7 @@ void MultitapEchoEffect::runFilter( sampleFrame * dst, sampleFrame * src, Stereo
|
||||
}
|
||||
|
||||
|
||||
bool MultitapEchoEffect::processAudioBuffer( sampleFrame * buf, const fpp_t frames )
|
||||
bool MultitapEchoEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ class MultitapEchoEffect : public Effect
|
||||
public:
|
||||
MultitapEchoEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
|
||||
~MultitapEchoEffect() override;
|
||||
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
|
||||
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
|
||||
private:
|
||||
void updateFilters( int begin, int end );
|
||||
void runFilter( sampleFrame * dst, sampleFrame * src, StereoOnePole & filter, const fpp_t frames );
|
||||
void runFilter( SampleFrame* dst, SampleFrame* src, StereoOnePole & filter, const fpp_t frames );
|
||||
|
||||
inline void setFilterFreq( float fc, StereoOnePole & f )
|
||||
{
|
||||
@@ -70,7 +70,7 @@ private:
|
||||
float m_sampleRate;
|
||||
float m_sampleRatio;
|
||||
|
||||
sampleFrame * m_work;
|
||||
SampleFrame* m_work;
|
||||
|
||||
friend class MultitapEchoControls;
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ NesObject::NesObject( NesInstrument * nes, const sample_rate_t samplerate, NoteP
|
||||
}
|
||||
|
||||
|
||||
void NesObject::renderOutput( sampleFrame * buf, fpp_t frames )
|
||||
void NesObject::renderOutput( SampleFrame* buf, fpp_t frames )
|
||||
{
|
||||
////////////////////////////////
|
||||
// //
|
||||
@@ -545,7 +545,7 @@ NesInstrument::NesInstrument( InstrumentTrack * instrumentTrack ) :
|
||||
|
||||
|
||||
|
||||
void NesInstrument::playNote( NotePlayHandle * n, sampleFrame * workingBuffer )
|
||||
void NesInstrument::playNote( NotePlayHandle * n, SampleFrame* workingBuffer )
|
||||
{
|
||||
const fpp_t frames = n->framesLeftForCurrentPeriod();
|
||||
const f_cnt_t offset = n->noteOffset();
|
||||
|
||||
@@ -60,22 +60,22 @@ namespace lmms
|
||||
{
|
||||
|
||||
|
||||
const float NES_SIMPLE_FILTER = 1.0 / 20.0; // simulate nes analog audio output
|
||||
const float NES_SIMPLE_FILTER = 1.f / 20.f; // simulate nes analog audio output
|
||||
const float NFB = 895000.0f;
|
||||
const float NOISE_FREQS[16] =
|
||||
{ NFB/5, NFB/9, NFB/17, NFB/33, NFB/65, NFB/97, NFB/129, NFB/161, NFB/193, NFB/255, NFB/381, NFB/509, NFB/763, NFB/1017, NFB/2035, NFB/4069 };
|
||||
const uint16_t LFSR_INIT = 1;
|
||||
const float DUTY_CYCLE[4] = { 0.125, 0.25, 0.5, 0.75 };
|
||||
const float DITHER_AMP = 1.0 / 60.0;
|
||||
const float DITHER_AMP = 1.f / 60.f;
|
||||
const float MIN_FREQ = 10.0;
|
||||
const int TRIANGLE_WAVETABLE[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
|
||||
|
||||
const float NES_DIST = 0.9f; // simulate the slight nonlinear distortion in nes audio output
|
||||
|
||||
const float NES_MIXING_12 = 1.0 / 20.0;
|
||||
const float NES_MIXING_34 = 1.0 / 12.0;
|
||||
const float NES_MIXING_ALL = 1.0 / ( NES_MIXING_12 + NES_MIXING_34 ); // constants to simulate the hardwired mixing values for nes channels
|
||||
const float NES_MIXING_12 = 1.f / 20.f;
|
||||
const float NES_MIXING_34 = 1.f / 12.f;
|
||||
const float NES_MIXING_ALL = 1.f / (NES_MIXING_12 + NES_MIXING_34); // constants to simulate the hardwired mixing values for nes channels
|
||||
|
||||
const int MIN_WLEN = 4;
|
||||
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
NesObject( NesInstrument * nes, const sample_rate_t samplerate, NotePlayHandle * nph );
|
||||
virtual ~NesObject() = default;
|
||||
|
||||
void renderOutput( sampleFrame * buf, fpp_t frames );
|
||||
void renderOutput( SampleFrame* buf, fpp_t frames );
|
||||
void updateVibrato( float * freq );
|
||||
void updatePitch();
|
||||
|
||||
@@ -212,7 +212,7 @@ public:
|
||||
~NesInstrument() override = default;
|
||||
|
||||
void playNote( NotePlayHandle * n,
|
||||
sampleFrame * workingBuffer ) override;
|
||||
SampleFrame* workingBuffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * n ) override;
|
||||
|
||||
|
||||
|
||||
@@ -390,7 +390,7 @@ gui::PluginView* OpulenzInstrument::instantiateView( QWidget * _parent )
|
||||
}
|
||||
|
||||
|
||||
void OpulenzInstrument::play( sampleFrame * _working_buffer )
|
||||
void OpulenzInstrument::play( SampleFrame* _working_buffer )
|
||||
{
|
||||
emulatorMutex.lock();
|
||||
theEmulator->update(renderbuffer, frameCount);
|
||||
@@ -770,15 +770,15 @@ void OpulenzInstrumentView::updateKnobHints()
|
||||
// Envelope times in ms: t[0] = 0, t[n] = ( 1<<n ) * X, X = 0.11597 for A, 0.6311 for D/R
|
||||
// Here some rounding has been applied.
|
||||
const auto attack_times = std::array<float, 16>{
|
||||
0.0, 0.2, 0.4, 0.9, 1.8, 3.7, 7.4,
|
||||
15.0, 30.0, 60.0, 120.0, 240.0, 480.0,
|
||||
950.0, 1900.0, 3800.0
|
||||
0.f, 0.2f, 0.4f, 0.9f, 1.8f, 3.7f, 7.4f,
|
||||
15.f, 30.f, 60.f, 120.f, 240.f, 480.f,
|
||||
950.f, 1900.f, 3800.f
|
||||
};
|
||||
|
||||
const auto dr_times = std::array<float, 16>{
|
||||
0.0, 1.2, 2.5, 5.0, 10.0, 20.0, 40.0,
|
||||
80.0, 160.0, 320.0, 640.0, 1300.0, 2600.0,
|
||||
5200.0, 10000.0, 20000.0
|
||||
0.f, 1.2f, 2.5f, 5.f, 10.f, 20.f, 40.f,
|
||||
80.f, 160.f, 320.f, 640.f, 1300.f, 2600.f,
|
||||
5200.f, 10000.f, 20000.f
|
||||
};
|
||||
|
||||
const auto fmultipliers = std::array<int, 16>{
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
gui::PluginView* instantiateView( QWidget * _parent ) override;
|
||||
|
||||
bool handleMidiEvent( const MidiEvent& event, const TimePos& time, f_cnt_t offset = 0 ) override;
|
||||
void play( sampleFrame * _working_buffer ) override;
|
||||
void play( SampleFrame* _working_buffer ) override;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
|
||||
@@ -221,7 +221,7 @@ QString OrganicInstrument::nodeName() const
|
||||
|
||||
|
||||
void OrganicInstrument::playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer )
|
||||
SampleFrame* _working_buffer )
|
||||
{
|
||||
const fpp_t frames = _n->framesLeftForCurrentPeriod();
|
||||
const f_cnt_t offset = _n->noteOffset();
|
||||
|
||||
@@ -125,7 +125,7 @@ public:
|
||||
~OrganicInstrument() override;
|
||||
|
||||
void playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer ) override;
|
||||
SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ QString PatmanInstrument::nodeName() const
|
||||
|
||||
|
||||
void PatmanInstrument::playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer )
|
||||
SampleFrame* _working_buffer )
|
||||
{
|
||||
if( m_patchFile == "" )
|
||||
{
|
||||
@@ -160,7 +160,7 @@ void PatmanInstrument::playNote( NotePlayHandle * _n,
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( _working_buffer, 0, ( frames + offset ) * sizeof( sampleFrame ) );
|
||||
zeroSampleFrames(_working_buffer, frames + offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ PatmanInstrument::LoadError PatmanInstrument::loadPatch(
|
||||
}
|
||||
}
|
||||
|
||||
auto data = new sampleFrame[frames];
|
||||
auto data = new SampleFrame[frames];
|
||||
|
||||
for( f_cnt_t frame = 0; frame < frames; ++frame )
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
~PatmanInstrument() override;
|
||||
|
||||
void playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer ) override;
|
||||
SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ PeakControllerEffect::~PeakControllerEffect()
|
||||
}
|
||||
|
||||
|
||||
bool PeakControllerEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
bool PeakControllerEffect::processAudioBuffer( SampleFrame* _buf,
|
||||
const fpp_t _frames )
|
||||
{
|
||||
PeakControllerEffectControls & c = m_peakControls;
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
PeakControllerEffect( Model * parent,
|
||||
const Descriptor::SubPluginFeatures::Key * _key );
|
||||
~PeakControllerEffect() override;
|
||||
bool processAudioBuffer( sampleFrame * _buf,
|
||||
bool processAudioBuffer( SampleFrame* _buf,
|
||||
const fpp_t _frames ) override;
|
||||
|
||||
EffectControls * controls() override
|
||||
|
||||
@@ -38,14 +38,14 @@ PeakControllerEffectControls::
|
||||
PeakControllerEffectControls( PeakControllerEffect * _eff ) :
|
||||
EffectControls( _eff ),
|
||||
m_effect( _eff ),
|
||||
m_baseModel( 0.5, 0.0, 1.0, 0.001, this, tr( "Base value" ) ),
|
||||
m_amountModel( 1.0, -1.0, 1.0, 0.005, this, tr( "Modulation amount" ) ),
|
||||
m_attackModel( 0, 0, 0.999, 0.001, this, tr( "Attack" ) ),
|
||||
m_decayModel( 0, 0, 0.999, 0.001, this, tr( "Release" ) ),
|
||||
m_tresholdModel( 0, 0, 1.0, 0.001, this, tr( "Treshold" ) ),
|
||||
m_baseModel(0.5f, 0.f, 1.f, 0.001f, this, tr("Base value")),
|
||||
m_amountModel(1.f, -1.f, 1.f, 0.005f, this, tr("Modulation amount")),
|
||||
m_attackModel(0, 0, 0.999f, 0.001f, this, tr("Attack")),
|
||||
m_decayModel(0, 0, 0.999f, 0.001f, this, tr("Release")),
|
||||
m_tresholdModel(0, 0, 1.f, 0.001f, this, tr("Treshold")),
|
||||
m_muteModel( false, this, tr( "Mute output" ) ),
|
||||
m_absModel( true, this, tr("Absolute value") ),
|
||||
m_amountMultModel( 1.0, 0, 32, 0.2, this, tr("Amount multiplicator") )
|
||||
m_amountMultModel(1.f, 0, 32, 0.2f, this, tr("Amount multiplicator"))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ ReverbSCEffect::~ReverbSCEffect()
|
||||
sp_destroy(&sp);
|
||||
}
|
||||
|
||||
bool ReverbSCEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
|
||||
bool ReverbSCEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
|
||||
@@ -45,7 +45,7 @@ class ReverbSCEffect : public Effect
|
||||
public:
|
||||
ReverbSCEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
|
||||
~ReverbSCEffect() override;
|
||||
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
|
||||
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
|
||||
|
||||
EffectControls* controls() override
|
||||
{
|
||||
|
||||
@@ -33,7 +33,7 @@ int sp_dcblock_init(sp_data *sp, sp_dcblock *p, int oversampling )
|
||||
p->inputs = 0.0;
|
||||
p->gain = pow( 0.99, 1.0f / oversampling );
|
||||
if (p->gain == 0.0 || p->gain>=1.0 || p->gain<=-1.0)
|
||||
p->gain = 0.99;
|
||||
p->gain = 0.99f;
|
||||
return SP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "base.h"
|
||||
#include "revsc.h"
|
||||
|
||||
#define DEFAULT_SRATE 44100.0
|
||||
#define DEFAULT_SRATE 44100.f
|
||||
#define MIN_SRATE 5000.0
|
||||
#define MAX_SRATE 1000000.0
|
||||
#define MAX_PITCHMOD 20.0
|
||||
@@ -34,20 +34,20 @@
|
||||
/* reverbParams[n][3] = random seed (0 - 32767) */
|
||||
|
||||
static const SPFLOAT reverbParams[8][4] = {
|
||||
{ (2473.0 / DEFAULT_SRATE), 0.0010, 3.100, 1966.0 },
|
||||
{ (2767.0 / DEFAULT_SRATE), 0.0011, 3.500, 29491.0 },
|
||||
{ (3217.0 / DEFAULT_SRATE), 0.0017, 1.110, 22937.0 },
|
||||
{ (3557.0 / DEFAULT_SRATE), 0.0006, 3.973, 9830.0 },
|
||||
{ (3907.0 / DEFAULT_SRATE), 0.0010, 2.341, 20643.0 },
|
||||
{ (4127.0 / DEFAULT_SRATE), 0.0011, 1.897, 22937.0 },
|
||||
{ (2143.0 / DEFAULT_SRATE), 0.0017, 0.891, 29491.0 },
|
||||
{ (1933.0 / DEFAULT_SRATE), 0.0006, 3.221, 14417.0 }
|
||||
{ (2473.f / DEFAULT_SRATE), 0.0010f, 3.100f, 1966.f },
|
||||
{ (2767.f / DEFAULT_SRATE), 0.0011f, 3.500f, 29491.f },
|
||||
{ (3217.f / DEFAULT_SRATE), 0.0017f, 1.110f, 22937.f },
|
||||
{ (3557.f / DEFAULT_SRATE), 0.0006f, 3.973f, 9830.f },
|
||||
{ (3907.f / DEFAULT_SRATE), 0.0010f, 2.341f, 20643.f },
|
||||
{ (4127.f / DEFAULT_SRATE), 0.0011f, 1.897f, 22937.f },
|
||||
{ (2143.f / DEFAULT_SRATE), 0.0017f, 0.891f, 29491.f },
|
||||
{ (1933.f / DEFAULT_SRATE), 0.0006f, 3.221f, 14417.f }
|
||||
};
|
||||
|
||||
static int delay_line_max_samples(SPFLOAT sr, SPFLOAT iPitchMod, int n);
|
||||
static int init_delay_line(sp_revsc *p, sp_revsc_dl *lp, int n);
|
||||
static int delay_line_bytes_alloc(SPFLOAT sr, SPFLOAT iPitchMod, int n);
|
||||
static const SPFLOAT outputGain = 0.35;
|
||||
static const SPFLOAT outputGain = 0.35f;
|
||||
static const SPFLOAT jpScale = 0.25;
|
||||
int sp_revsc_create(sp_revsc **p){
|
||||
*p = malloc(sizeof(sp_revsc));
|
||||
@@ -56,9 +56,9 @@ int sp_revsc_create(sp_revsc **p){
|
||||
|
||||
int sp_revsc_init(sp_data *sp, sp_revsc *p)
|
||||
{
|
||||
p->iSampleRate = sp->sr;
|
||||
p->sampleRate = sp->sr;
|
||||
p->feedback = 0.97;
|
||||
p->iSampleRate = (float) sp->sr;
|
||||
p->sampleRate = (float) sp->sr;
|
||||
p->feedback = 0.97f;
|
||||
p->lpfreq = 10000;
|
||||
p->iPitchMod = 1;
|
||||
p->iSkipInit = 0;
|
||||
@@ -67,14 +67,14 @@ int sp_revsc_init(sp_data *sp, sp_revsc *p)
|
||||
p->initDone = 1;
|
||||
int i, nBytes = 0;
|
||||
for(i = 0; i < 8; i++){
|
||||
nBytes += delay_line_bytes_alloc(sp->sr, 1, i);
|
||||
nBytes += delay_line_bytes_alloc((float) sp->sr, 1, i);
|
||||
}
|
||||
sp_auxdata_alloc(&p->aux, nBytes);
|
||||
nBytes = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
p->delayLines[i].buf = (SPFLOAT*) (((char*) p->aux.ptr) + nBytes);
|
||||
init_delay_line(p, &p->delayLines[i], i);
|
||||
nBytes += delay_line_bytes_alloc(sp->sr, 1, i);
|
||||
nBytes += delay_line_bytes_alloc((float) sp->sr, 1, i);
|
||||
}
|
||||
|
||||
return SP_OK;
|
||||
@@ -217,7 +217,7 @@ int sp_revsc_compute(sp_data *sp, sp_revsc *p, SPFLOAT *in1, SPFLOAT *in2, SPFLO
|
||||
|
||||
/* calculate interpolation coefficients */
|
||||
|
||||
a2 = frac * frac; a2 -= 1.0; a2 *= (1.0 / 6.0);
|
||||
a2 = frac * frac; a2 -= 1.0; a2 *= (1.f / 6.f);
|
||||
a1 = frac; a1 += 1.0; a1 *= 0.5; am1 = a1 - 1.0;
|
||||
a0 = 3.0 * a2; a1 -= a0; am1 -= a2; a0 -= frac;
|
||||
|
||||
|
||||
@@ -136,14 +136,14 @@ Sf2Instrument::Sf2Instrument( InstrumentTrack * _instrument_track ) :
|
||||
m_gain( 1.0f, 0.0f, 5.0f, 0.01f, this, tr( "Gain" ) ),
|
||||
m_reverbOn( false, this, tr( "Reverb" ) ),
|
||||
m_reverbRoomSize( FLUID_REVERB_DEFAULT_ROOMSIZE, 0, 1.0, 0.01f, this, tr( "Reverb room size" ) ),
|
||||
m_reverbDamping( FLUID_REVERB_DEFAULT_DAMP, 0, 1.0, 0.01, this, tr( "Reverb damping" ) ),
|
||||
m_reverbDamping(FLUID_REVERB_DEFAULT_DAMP, 0, 1.f, 0.01f, this, tr("Reverb damping")),
|
||||
m_reverbWidth( FLUID_REVERB_DEFAULT_WIDTH, 0, 1.0, 0.01f, this, tr( "Reverb width" ) ),
|
||||
m_reverbLevel( FLUID_REVERB_DEFAULT_LEVEL, 0, 1.0, 0.01f, this, tr( "Reverb level" ) ),
|
||||
m_chorusOn( false, this, tr( "Chorus" ) ),
|
||||
m_chorusNum( FLUID_CHORUS_DEFAULT_N, 0, 10.0, 1.0, this, tr( "Chorus voices" ) ),
|
||||
m_chorusLevel( FLUID_CHORUS_DEFAULT_LEVEL, 0, 10.0, 0.01, this, tr( "Chorus level" ) ),
|
||||
m_chorusSpeed( FLUID_CHORUS_DEFAULT_SPEED, 0.29, 5.0, 0.01, this, tr( "Chorus speed" ) ),
|
||||
m_chorusDepth( FLUID_CHORUS_DEFAULT_DEPTH, 0, 46.0, 0.05, this, tr( "Chorus depth" ) )
|
||||
m_chorusLevel(FLUID_CHORUS_DEFAULT_LEVEL, 0, 10.f, 0.01f, this, tr("Chorus level")),
|
||||
m_chorusSpeed(FLUID_CHORUS_DEFAULT_SPEED, 0.29f, 5.f, 0.01f, this, tr("Chorus speed")),
|
||||
m_chorusDepth(FLUID_CHORUS_DEFAULT_DEPTH, 0, 46.f, 0.05f, this, tr("Chorus depth"))
|
||||
{
|
||||
|
||||
|
||||
@@ -647,7 +647,7 @@ void Sf2Instrument::reloadSynth()
|
||||
|
||||
|
||||
|
||||
void Sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * )
|
||||
void Sf2Instrument::playNote( NotePlayHandle * _n, SampleFrame* )
|
||||
{
|
||||
if( _n->isMasterNote() || ( _n->hasParent() && _n->isReleased() ) )
|
||||
{
|
||||
@@ -782,7 +782,7 @@ void Sf2Instrument::noteOff( Sf2PluginData * n )
|
||||
}
|
||||
|
||||
|
||||
void Sf2Instrument::play( sampleFrame * _working_buffer )
|
||||
void Sf2Instrument::play( SampleFrame* _working_buffer )
|
||||
{
|
||||
const fpp_t frames = Engine::audioEngine()->framesPerPeriod();
|
||||
|
||||
@@ -868,7 +868,7 @@ void Sf2Instrument::play( sampleFrame * _working_buffer )
|
||||
}
|
||||
|
||||
|
||||
void Sf2Instrument::renderFrames( f_cnt_t frames, sampleFrame * buf )
|
||||
void Sf2Instrument::renderFrames( f_cnt_t frames, SampleFrame* buf )
|
||||
{
|
||||
m_synthMutex.lock();
|
||||
fluid_synth_get_gain(m_synth); // This flushes voice updates as a side effect
|
||||
@@ -877,9 +877,9 @@ void Sf2Instrument::renderFrames( f_cnt_t frames, sampleFrame * buf )
|
||||
{
|
||||
const fpp_t f = frames * m_internalSampleRate / Engine::audioEngine()->outputSampleRate();
|
||||
#ifdef __GNUC__
|
||||
sampleFrame tmp[f];
|
||||
SampleFrame tmp[f];
|
||||
#else
|
||||
sampleFrame * tmp = new sampleFrame[f];
|
||||
SampleFrame* tmp = new SampleFrame[f];
|
||||
#endif
|
||||
fluid_synth_write_float( m_synth, f, tmp, 0, 2, tmp, 1, 2 );
|
||||
|
||||
|
||||
@@ -64,10 +64,10 @@ public:
|
||||
Sf2Instrument( InstrumentTrack * _instrument_track );
|
||||
~Sf2Instrument() override;
|
||||
|
||||
void play( sampleFrame * _working_buffer ) override;
|
||||
void play( SampleFrame* _working_buffer ) override;
|
||||
|
||||
void playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer ) override;
|
||||
SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ private:
|
||||
void freeFont();
|
||||
void noteOn( Sf2PluginData * n );
|
||||
void noteOff( Sf2PluginData * n );
|
||||
void renderFrames( f_cnt_t frames, sampleFrame * buf );
|
||||
void renderFrames( f_cnt_t frames, SampleFrame* buf );
|
||||
|
||||
friend class gui::Sf2InstrumentView;
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ void SfxrSynth::resetSample( bool restart )
|
||||
|
||||
|
||||
|
||||
void SfxrSynth::update( sampleFrame * buffer, const int32_t frameNum )
|
||||
void SfxrSynth::update( SampleFrame* buffer, const int32_t frameNum )
|
||||
{
|
||||
for(int i=0;i<frameNum;i++)
|
||||
{
|
||||
@@ -442,7 +442,7 @@ QString SfxrInstrument::nodeName() const
|
||||
|
||||
|
||||
|
||||
void SfxrInstrument::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer )
|
||||
void SfxrInstrument::playNote( NotePlayHandle * _n, SampleFrame* _working_buffer )
|
||||
{
|
||||
float currentSampleRate = Engine::audioEngine()->outputSampleRate();
|
||||
|
||||
@@ -454,7 +454,7 @@ void SfxrInstrument::playNote( NotePlayHandle * _n, sampleFrame * _working_buffe
|
||||
}
|
||||
else if( static_cast<SfxrSynth*>(_n->m_pluginData)->isPlaying() == false )
|
||||
{
|
||||
memset(_working_buffer + offset, 0, sizeof(sampleFrame) * frameNum);
|
||||
zeroSampleFrames(_working_buffer + offset, frameNum);
|
||||
_n->noteOff();
|
||||
return;
|
||||
}
|
||||
@@ -467,7 +467,7 @@ void SfxrInstrument::playNote( NotePlayHandle * _n, sampleFrame * _working_buffe
|
||||
// debug code
|
||||
// qDebug( "pFN %d", pitchedFrameNum );
|
||||
|
||||
auto pitchedBuffer = new sampleFrame[pitchedFrameNum];
|
||||
auto pitchedBuffer = new SampleFrame[pitchedFrameNum];
|
||||
static_cast<SfxrSynth*>(_n->m_pluginData)->update( pitchedBuffer, pitchedFrameNum );
|
||||
for( fpp_t i=0; i<frameNum; i++ )
|
||||
{
|
||||
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
virtual ~SfxrSynth() = default;
|
||||
|
||||
void resetSample( bool restart );
|
||||
void update( sampleFrame * buffer, const int32_t frameNum );
|
||||
void update( SampleFrame* buffer, const int32_t frameNum );
|
||||
|
||||
bool isPlaying() const;
|
||||
|
||||
@@ -135,7 +135,7 @@ class SfxrZeroToOneFloatModel : public FloatModel
|
||||
{
|
||||
public:
|
||||
SfxrZeroToOneFloatModel( float val, Model * parent, const QString& displayName ):
|
||||
FloatModel( val, 0.0, 1.0, 0.001, parent, displayName )
|
||||
FloatModel(val, 0.f, 1.f, 0.001f, parent, displayName)
|
||||
{
|
||||
}
|
||||
/* purpose: prevent the initial value of the model from being changed */
|
||||
@@ -156,7 +156,7 @@ class SfxrNegPosOneFloatModel : public FloatModel
|
||||
{
|
||||
public:
|
||||
SfxrNegPosOneFloatModel(float val, Model * parent, const QString& displayName ):
|
||||
FloatModel( val, -1.0, 1.0, 0.001, parent, displayName )
|
||||
FloatModel(val, -1.f, 1.f, 0.001f, parent, displayName)
|
||||
{
|
||||
}
|
||||
/* purpose: prevent the initial value of the model from being changed */
|
||||
@@ -177,7 +177,7 @@ public:
|
||||
SfxrInstrument(InstrumentTrack * _instrument_track );
|
||||
~SfxrInstrument() override = default;
|
||||
|
||||
void playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) override;
|
||||
void playNote( NotePlayHandle * _n, SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
void saveSettings( QDomDocument & _doc,
|
||||
|
||||
@@ -286,7 +286,7 @@ static int sid_fillbuffer(unsigned char* sidreg, reSID::SID *sid, int tdelta, sh
|
||||
|
||||
|
||||
void SidInstrument::playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer )
|
||||
SampleFrame* _working_buffer )
|
||||
{
|
||||
const int clockrate = C64_PAL_CYCLES_PER_SEC;
|
||||
const int samplerate = Engine::audioEngine()->outputSampleRate();
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
~SidInstrument() override = default;
|
||||
|
||||
void playNote( NotePlayHandle * _n,
|
||||
sampleFrame * _working_buffer ) override;
|
||||
SampleFrame* _working_buffer ) override;
|
||||
void deleteNotePluginData( NotePlayHandle * _n ) override;
|
||||
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ SlicerT::SlicerT(InstrumentTrack* instrumentTrack)
|
||||
m_sliceSnap.setValue(0);
|
||||
}
|
||||
|
||||
void SlicerT::playNote(NotePlayHandle* handle, sampleFrame* workingBuffer)
|
||||
void SlicerT::playNote(NotePlayHandle* handle, SampleFrame* workingBuffer)
|
||||
{
|
||||
if (m_originalSample.sampleSize() <= 1) { return; }
|
||||
|
||||
@@ -197,7 +197,7 @@ void SlicerT::findSlices()
|
||||
|
||||
int lastPoint = -minDist - 1; // to always store 0 first
|
||||
float spectralFlux = 0;
|
||||
float prevFlux = 1E-10; // small value, no divison by zero
|
||||
float prevFlux = 1E-10f; // small value, no divison by zero
|
||||
|
||||
for (int i = 0; i < singleChannel.size() - windowSize; i += windowSize)
|
||||
{
|
||||
@@ -227,7 +227,7 @@ void SlicerT::findSlices()
|
||||
}
|
||||
|
||||
prevFlux = spectralFlux;
|
||||
spectralFlux = 1E-10; // again for no divison by zero
|
||||
spectralFlux = 1E-10f; // again for no divison by zero
|
||||
}
|
||||
|
||||
m_slicePoints.push_back(m_originalSample.sampleSize());
|
||||
|
||||
@@ -75,7 +75,7 @@ signals:
|
||||
public:
|
||||
SlicerT(InstrumentTrack* instrumentTrack);
|
||||
|
||||
void playNote(NotePlayHandle* handle, sampleFrame* workingBuffer) override;
|
||||
void playNote(NotePlayHandle* handle, SampleFrame* workingBuffer) override;
|
||||
void deleteNotePluginData(NotePlayHandle* handle) override;
|
||||
|
||||
void saveSettings(QDomDocument& document, QDomElement& element) override;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user