Merge branch 'master' into sample-recording

This commit is contained in:
Rossmaxx
2024-07-15 16:46:37 +05:30
274 changed files with 3020 additions and 1890 deletions

View File

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

View File

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

View File

@@ -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 );
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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" ) );

View File

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

View File

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

View File

@@ -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" ) ),

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,9 @@
include(BuildPlugin)
build_plugin(granularpitchshifter
GranularPitchShifterEffect.cpp
GranularPitchShifterControls.cpp
GranularPitchShifterControlDialog.cpp
MOCFILES
GranularPitchShifterControls.h
GranularPitchShifterControlDialog.h
EMBEDDED_RESOURCES *.png)

View 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

View 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

View 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

View 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

View 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -125,7 +125,7 @@ public:
~OrganicInstrument() override;
void playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer ) override;
SampleFrame* _working_buffer ) override;
void deleteNotePluginData( NotePlayHandle * _n ) override;

View File

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

View File

@@ -60,7 +60,7 @@ public:
~PatmanInstrument() override;
void playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer ) override;
SampleFrame* _working_buffer ) override;
void deleteNotePluginData( NotePlayHandle * _n ) override;

View File

@@ -93,7 +93,7 @@ PeakControllerEffect::~PeakControllerEffect()
}
bool PeakControllerEffect::processAudioBuffer( sampleFrame * _buf,
bool PeakControllerEffect::processAudioBuffer( SampleFrame* _buf,
const fpp_t _frames )
{
PeakControllerEffectControls & c = m_peakControls;

View File

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

View File

@@ -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"))
{
}

View File

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

View File

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

View File

@@ -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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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