Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Phaser effect to LMMS #5168

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7f1c954
Merge pull request #8 from LMMS/master
LostRobotMusic Jun 21, 2019
0bb50a8
Merge pull request #11 from LMMS/master
LostRobotMusic Aug 7, 2019
a332d47
Merge pull request #12 from LMMS/master
LostRobotMusic Aug 30, 2019
5f0aacc
Merge pull request #13 from LMMS/master
LostRobotMusic Sep 4, 2019
6f4afb1
Add Phaser effect, upgrade Flanger effect
LostRobotMusic Sep 4, 2019
b41a6a9
Resolve code/style reviews
LostRobotMusic Sep 4, 2019
b9d1b45
Resolve code/style reviews, don't calulate LFO rate every loop
LostRobotMusic Sep 4, 2019
9a8fdfa
Rename Phaser.cpp and Phaser.h to PhaserEffect.cpp and PhaserEffect.h
LostRobotMusic Sep 4, 2019
4e1ba1d
Remove unnecessary Phaser disconnection
LostRobotMusic Sep 5, 2019
b7dd6d1
Fix Phaser artwork LFO font
LostRobotMusic Sep 5, 2019
779d1b5
Merge branch 'master' into phaser
LostRobotMusic Nov 24, 2019
bd9ee92
Add Phaser to plugin list
LostRobotMusic Nov 24, 2019
8534cab
Add many enhancements for the Phaser effect
LostRobotMusic Feb 17, 2020
34221f3
Fix stuff
LostRobotMusic Feb 17, 2020
ed7c1b2
Fix stuff 2: Electric Boogaloo
LostRobotMusic Feb 17, 2020
b467652
Fix stuff 3: No joke here
LostRobotMusic Feb 17, 2020
47e6f6a
Resolve code and style reviews
LostRobotMusic Feb 26, 2020
185ce06
Resolve more code and style reviews
LostRobotMusic Apr 18, 2020
fbd62a6
Input follower range buff
LostRobotMusic May 17, 2020
81bbf89
Make LFO Rate logarithmic by default
LostRobotMusic May 17, 2020
df143d1
Remove RMS from input follower
LostRobotMusic Oct 26, 2020
c5ce560
Fix compilation complaints
LostRobotMusic Oct 26, 2020
6b97fb5
Major update
LostRobotMusic Dec 11, 2020
9e9a824
Fix stuffs
LostRobotMusic Dec 15, 2020
9cd0ecf
Fix more stuffs
LostRobotMusic Dec 15, 2020
801acf4
Add Input Follower enable button
LostRobotMusic Dec 16, 2020
3211fe6
Initialize QuadratureLfo's frequency and phase in constructor
LostRobotMusic Dec 16, 2020
ab2dee9
Why is it called oven when you of in the cold food of out hot eat the…
LostRobotMusic Jan 15, 2021
b4bac58
Revert one of the modes to its original naming, due to very high demand.
LostRobotMusic Feb 25, 2021
e597a2c
Fix merge conflicts with Flanger upgrade PR
LostRobotMusic Mar 25, 2021
f436816
Continue running Phaser while LFO is disabled
LostRobotMusic Mar 25, 2021
f679542
Fix inaccurate comment
LostRobotMusic Mar 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ IF("${PLUGIN_LIST}" STREQUAL "")
FreeBoy
patman
peak_controller_effect
Phaser
GigPlayer
ReverbSC
sf2_player
Expand Down
2 changes: 1 addition & 1 deletion plugins/Flanger/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
INCLUDE(BuildPlugin)

BUILD_PLUGIN(flanger FlangerEffect.cpp FlangerControls.cpp FlangerControlsDialog.cpp Noise.cpp QuadratureLfo.cpp MonoDelay.cpp MOCFILES FlangerControls.h FlangerControlsDialog.h EMBEDDED_RESOURCES artwork.png logo.png)
BUILD_PLUGIN(flanger FlangerEffect.cpp FlangerControls.cpp FlangerControlsDialog.cpp Noise.cpp MonoDelay.cpp MOCFILES FlangerControls.h FlangerControlsDialog.h EMBEDDED_RESOURCES artwork.png logo.png)
25 changes: 19 additions & 6 deletions plugins/Flanger/FlangerControls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,19 @@
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( "Seconds" ) ),
m_feedbackModel( 0.0 , 0.0 , 1.0 , 0.0001, this, tr( "Regen" ) ),
m_whiteNoiseAmountModel( 0.0 , 0.0 , 0.05 , 0.0001, this, tr( "Noise" ) ),
m_invertFeedbackModel ( false , this, tr( "Invert" ) )
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( "Seconds" ) ),
m_lfoPhaseModel( 180.0, 0.0, 360.0, 0.0001, this, tr( "Stereo Phase" ) ),
DomClark marked this conversation as resolved.
Show resolved Hide resolved
m_feedbackModel( 0.0, -1.0, 1.0, 0.0001, this, tr( "Regen" ) ),
m_whiteNoiseAmountModel( 0.0, 0.0, 0.05, 0.0001, this, tr( "Noise" ) ),
m_invertFeedbackModel ( false, this, tr( "Invert" ) )

{
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( changedSampleRate() ) );
connect( Engine::getSong(), SIGNAL( playbackStateChanged() ), this, SLOT( changedPlaybackState() ) );

connect( &m_lfoPhaseModel, SIGNAL( dataChanged() ), this, SLOT( updatePhase() ) );
}


Expand All @@ -54,6 +57,7 @@ void FlangerControls::loadSettings( const QDomElement &_this )
m_delayTimeModel.loadSettings( _this, "DelayTimeSamples" );
m_lfoFrequencyModel.loadSettings( _this, "LfoFrequency" );
m_lfoAmountModel.loadSettings( _this, "LfoAmount" );
m_lfoPhaseModel.loadSettings( _this, "LfoPhase" );
m_feedbackModel.loadSettings( _this, "Feedback" );
m_whiteNoiseAmountModel.loadSettings( _this, "WhiteNoise" );
m_invertFeedbackModel.loadSettings( _this, "Invert" );
Expand All @@ -68,6 +72,7 @@ void FlangerControls::saveSettings( QDomDocument &doc, QDomElement &parent )
m_delayTimeModel.saveSettings( doc , parent, "DelayTimeSamples" );
m_lfoFrequencyModel.saveSettings( doc, parent , "LfoFrequency" );
m_lfoAmountModel.saveSettings( doc, parent , "LfoAmount" );
m_lfoPhaseModel.saveSettings( doc, parent , "LfoPhase" );
m_feedbackModel.saveSettings( doc, parent, "Feedback" ) ;
m_whiteNoiseAmountModel.saveSettings( doc, parent , "WhiteNoise" ) ;
m_invertFeedbackModel.saveSettings( doc, parent, "Invert" );
Expand All @@ -88,3 +93,11 @@ void FlangerControls::changedPlaybackState()
{
m_effect->restartLFO();
}




void FlangerControls::updatePhase()
{
m_effect->m_lfo->setOffset(m_lfoPhaseModel.value() / 180 * D_PI);
LostRobotMusic marked this conversation as resolved.
Show resolved Hide resolved
}
4 changes: 3 additions & 1 deletion plugins/Flanger/FlangerControls.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class FlangerControls : public EffectControls
}
virtual int controlCount()
{
return 5;
return 7;
}
virtual EffectControlDialog* createView()
{
Expand All @@ -58,12 +58,14 @@ class FlangerControls : public EffectControls
private slots:
void changedSampleRate();
void changedPlaybackState();
void updatePhase();

private:
FlangerEffect* m_effect;
FloatModel m_delayTimeModel;
TempoSyncKnobModel m_lfoFrequencyModel;
FloatModel m_lfoAmountModel;
FloatModel m_lfoPhaseModel;
FloatModel m_feedbackModel;
FloatModel m_whiteNoiseAmountModel;
BoolModel m_invertFeedbackModel;
Expand Down
13 changes: 10 additions & 3 deletions plugins/Flanger/FlangerControlsDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ FlangerControlsDialog::FlangerControlsDialog( FlangerControls *controls ) :
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
setPalette( pal );
setFixedSize( 195, 75 );
setFixedSize( 233, 75 );

Knob* delayKnob = new Knob( knobBright_26, this );
delayKnob->move( 10,10 );
Expand All @@ -61,15 +61,22 @@ FlangerControlsDialog::FlangerControlsDialog( FlangerControls *controls ) :
lfoAmtKnob->setLabel( tr( "AMNT" ) );
lfoAmtKnob->setHintText( tr( "Amount:" ) , "" );

Knob * lfoPhaseKnob = new Knob( knobBright_26, this );
lfoPhaseKnob->move( 123,10 );
lfoPhaseKnob->setVolumeKnob( false );
lfoPhaseKnob->setModel( &controls->m_lfoPhaseModel );
lfoPhaseKnob->setLabel( tr( "PHASE" ) );
lfoPhaseKnob->setHintText( tr( "Phase:" ) , "" );

Knob * feedbackKnob = new Knob( knobBright_26, this );
feedbackKnob->move( 122,10 );
feedbackKnob->move( 160,10 );
feedbackKnob->setVolumeKnob( true) ;
feedbackKnob->setModel( &controls->m_feedbackModel );
feedbackKnob->setLabel( tr( "FDBK" ) );
feedbackKnob->setHintText( tr( "Feedback amount:" ) , "" );

Knob * whiteNoiseKnob = new Knob( knobBright_26, this );
whiteNoiseKnob->move( 156,10 );
whiteNoiseKnob->move( 196,10 );
whiteNoiseKnob->setVolumeKnob( true) ;
whiteNoiseKnob->setModel( &controls->m_whiteNoiseAmountModel );
whiteNoiseKnob->setLabel( tr( "NOISE" ) );
Expand Down
2 changes: 2 additions & 0 deletions plugins/Flanger/FlangerEffect.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class FlangerEffect : public Effect
QuadratureLfo* m_lfo;
Noise* m_noise;

friend class FlangerControls;

};

#endif // FLANGEREFFECT_H
31 changes: 22 additions & 9 deletions plugins/Flanger/QuadratureLfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,51 +30,64 @@
class QuadratureLfo
{
public:
QuadratureLfo( int sampleRate );
QuadratureLfo( int sampleRate )
{
setSampleRate(sampleRate);
}
~QuadratureLfo()
{
}

inline void setFrequency( double frequency )
{
if( frequency < 0 || frequency > ( m_samplerate / 2.0 ) || frequency == m_frequency )
if( frequency < 0 || frequency > m_samplerate / 2.0 || frequency == m_frequency )
{
return;
}
m_frequency = frequency;
m_increment = m_frequency * m_twoPiOverSr;

if( m_phase >= F_2PI )
if( m_phase >= D_2PI )
{
m_phase -= F_2PI;
m_phase -= D_2PI;
}
}




inline void restart()
{
m_phase = 0;
}




inline void setSampleRate ( int samplerate )
{
m_samplerate = samplerate;
m_twoPiOverSr = F_2PI / samplerate;
m_increment = m_frequency * m_twoPiOverSr;
}

void tick( float *s, float *c );

inline void setOffset( double offsetVal )
{
m_offset = offsetVal;
}


void tick( float *l, float *r )
{
*l = sinf( m_phase );
*r = sinf( m_phase + m_offset );
m_phase += m_increment;

}

private:
double m_frequency;
double m_phase;
double m_increment;
double m_twoPiOverSr;
double m_offset = D_PI;
int m_samplerate;

};
Expand Down
3 changes: 3 additions & 0 deletions plugins/Phaser/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
INCLUDE(BuildPlugin)

BUILD_PLUGIN(phaser PhaserEffect.cpp PhaserControls.cpp PhaserControlDialog.cpp MOCFILES PhaserControls.h PhaserControlDialog.h ../Eq/EqFader.h EMBEDDED_RESOURCES artwork.png logo.png cutoffDotLeft.png cutoffDotRight.png)
157 changes: 157 additions & 0 deletions plugins/Phaser/PhaserControlDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* PhaserControlDialog.cpp
*
* Copyright (c) 2019 Lost Robot <r94231@gmail.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 <QLayout>

#include "PhaserEffect.h"
#include "PhaserControlDialog.h"
#include "PhaserControls.h"
#include "embed.h"
#include "LedCheckbox.h"
#include "TempoSyncKnob.h"
#include "../Eq/EqFader.h"
#include "lmms_math.h"


const int PHA_DOT_SLIDER_LENGTH = 338;
const float PHA_MIN_FREQ = 20;
const float PHA_MAX_FREQ = 20000;
DomClark marked this conversation as resolved.
Show resolved Hide resolved


PhaserControlDialog::PhaserControlDialog(PhaserControls* controls) :
EffectControlDialog(controls)
{
m_controls = controls;
DomClark marked this conversation as resolved.
Show resolved Hide resolved

setAutoFillBackground(true);
QPalette pal;
pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork"));
setPalette(pal);
setFixedSize(371, 155);

Knob * cutoffKnob = new Knob(knobBright_26, this);
cutoffKnob -> move(65, 13);
cutoffKnob->setModel(&controls->m_cutoffModel);
cutoffKnob->setHintText(tr("Cutoff:"), " Hz");

Knob * resonanceKnob = new Knob(knobBright_26, this);
resonanceKnob -> move(103, 13);
resonanceKnob->setModel(&controls->m_resonanceModel);
resonanceKnob->setHintText(tr("Resonance:"), "");

Knob * feedbackKnob = new Knob(knobBright_26, this);
feedbackKnob -> move(159, 13);
feedbackKnob->setModel(&controls->m_feedbackModel);
feedbackKnob->setHintText(tr("Feedback:"), "%");

LcdSpinBox * m_orderBox = new LcdSpinBox(2, this, "Order");
m_orderBox->setModel(&controls->m_orderModel);
m_orderBox->move(245, 17);

Knob * delayKnob = new Knob(knobBright_26, this);
delayKnob -> move(197, 13);
delayKnob->setModel(&controls->m_delayModel);
delayKnob->setHintText(tr("Delay:"), " samples");

TempoSyncKnob * rateKnob = new TempoSyncKnob(knobBright_26, this);
rateKnob -> move(104, 84);
rateKnob->setModel(&controls->m_rateModel);
rateKnob->setHintText(tr("Rate:"), " Sec");

Knob * amountKnob = new Knob(knobBright_26, this);
amountKnob -> move(66, 84);
amountKnob->setModel(&controls->m_amountModel);
amountKnob->setHintText(tr("Amount:"), " octaves");

Knob * phaseKnob = new Knob(knobBright_26, this);
phaseKnob -> move(142, 84);
phaseKnob->setModel(&controls->m_phaseModel);
phaseKnob->setHintText(tr("Phase:"), " degrees");

Knob * wetDryKnob = new Knob(knobBright_26, this);
wetDryKnob -> move(285, 13);
wetDryKnob->setModel(&controls->m_wetDryModel);
wetDryKnob->setHintText(tr("Wet/Dry:"), "");

Knob * inFollowKnob = new Knob(knobBright_26, this);
inFollowKnob -> move(203, 84);
inFollowKnob->setModel(&controls->m_inFollowModel);
inFollowKnob->setHintText(tr("Input Following:"), " octaves");

Knob * attackKnob = new Knob(knobBright_26, this);
attackKnob -> move(241, 84);
attackKnob->setModel(&controls->m_attackModel);
attackKnob->setHintText(tr("Attack:"), " ms");

Knob * releaseKnob = new Knob(knobBright_26, this);
releaseKnob -> move(279, 84);
releaseKnob->setModel(&controls->m_releaseModel);
releaseKnob->setHintText(tr("Release:"), " ms");

QPixmap m_cutoffDotLeftImg = PLUGIN_NAME::getIconPixmap("cutoffDotLeft");
m_cutoffDotLeftLabel = new QLabel(this);
m_cutoffDotLeftLabel->setPixmap(m_cutoffDotLeftImg);
m_cutoffDotLeftLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
m_cutoffDotLeftLabel->move(182, 139);

QPixmap m_cutoffDotRightImg = PLUGIN_NAME::getIconPixmap("cutoffDotRight");
m_cutoffDotRightLabel = new QLabel(this);
m_cutoffDotRightLabel->setPixmap(m_cutoffDotRightImg);
m_cutoffDotRightLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
m_cutoffDotRightLabel->move(182, 139);

LedCheckBox * enableLFO = new LedCheckBox("", this, tr("Enable LFO"), LedCheckBox::Green);
enableLFO->setModel(&controls->m_enableLFOModel);
enableLFO->move(160, 63);

EqFader * outFader = new EqFader(&controls->m_outGainModel,tr("Output gain"),
this, &controls->m_outPeakL, &controls->m_outPeakR);
outFader->setMinimumHeight(84);
outFader->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
outFader->resize(23, 84);
outFader->move(336, 33);
outFader->setDisplayConversion(false);
outFader->setHintText(tr("Gain"), "dBFS");

EqFader * inFader = new EqFader(&controls->m_inGainModel,tr("Input gain"),
this, &controls->m_inPeakL, &controls->m_inPeakR);
inFader->setMinimumHeight(84);
inFader->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
inFader->resize(23, 84);
inFader->move(13, 33);
inFader->setDisplayConversion(false);
inFader->setHintText(tr("Gain"), "dBFS");

connect( gui->mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( updateSliders() ) );
}


void PhaserControlDialog::updateSliders()
{
// Magic. Do not touch.
m_cutoffDotLeftLabel->move((int((log2(model()->m_effect->m_realCutoff[0]) - log2(PHA_MIN_FREQ)) /
log2(PHA_MAX_FREQ / PHA_MIN_FREQ) * PHA_DOT_SLIDER_LENGTH)) + 12, 139);
m_cutoffDotRightLabel->move((int((log2(model()->m_effect->m_realCutoff[1]) - log2(PHA_MIN_FREQ)) /
log2(PHA_MAX_FREQ / PHA_MIN_FREQ) * PHA_DOT_SLIDER_LENGTH)) + 12, 139);
}
Loading