code:
/*
 * eqcontrols.cpp - defination of EqControls class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 "EqControls.h"

#include <QtXml/QDomElement>

#include "EqControlsDialog.h"
#include "EqEffect.h"

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( 1.4,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( 1.4, 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_hpActiveModel( false, this , tr( "HP active" ) ),
	m_lowShelfActiveModel( false, this , tr( "Low-shelf active" ) ),
	m_para1ActiveModel( false, this , tr( "Peak 1 active" ) ),
	m_para2ActiveModel( false, this , tr( "Peak 2 active" ) ),
	m_para3ActiveModel( false, this , tr( "Peak 3 active" ) ),
	m_para4ActiveModel( false, this , tr( "Peak 4 active" ) ),
	m_highShelfActiveModel( false, this , tr( "High-shelf active" ) ),
	m_lpActiveModel( false, this , tr( "LP active" ) ),
	m_lp12Model( false, this , tr( "LP 12" ) ),
	m_lp24Model( false, this , tr( "LP 24" ) ),
	m_lp48Model( false, this , tr( "LP 48" ) ),
	m_hp12Model( false, this , tr( "HP 12" ) ),
	m_hp24Model( false, this , tr( "HP 24" ) ),
	m_hp48Model( false, this , tr( "HP 48" ) ),
	m_lpTypeModel( 0,0,2, this, tr( "Low-pass type" ) ) ,
	m_hpTypeModel( 0,0,2, this, tr( "High-pass type" ) ),
	m_analyseInModel( true, this , tr( "Analyse IN" ) ),
	m_analyseOutModel( true, this, tr( "Analyse OUT" ) )
{
	m_hpFeqModel.setScaleLogarithmic( true );
	m_lowShelfFreqModel.setScaleLogarithmic( true );
	m_para1FreqModel.setScaleLogarithmic( true );
	m_para2FreqModel.setScaleLogarithmic( true );
	m_para3FreqModel.setScaleLogarithmic( true );
	m_para4FreqModel.setScaleLogarithmic( true );
	m_highShelfFreqModel.setScaleLogarithmic( true );
	m_lpFreqModel.setScaleLogarithmic( true );
	m_para1GainModel.setScaleLogarithmic( true );
	m_inPeakL = 0;
	m_inPeakR = 0;
	m_outPeakL = 0;
	m_outPeakR = 0;
	m_lowShelfPeakL = 0; m_lowShelfPeakR = 0;
	m_para1PeakL = 0; m_para1PeakR = 0;
	m_para2PeakL = 0; m_para2PeakR = 0;
	m_para3PeakL = 0; m_para3PeakR = 0;
	m_para4PeakL = 0; m_para4PeakR = 0;
	m_highShelfPeakL = 0; m_highShelfPeakR = 0;
	m_inProgress = false;
	m_inGainModel.setScaleLogarithmic( true );
}

void EqControls::loadSettings( const QDomElement &_this )
{
	m_inGainModel.loadSettings( _this, "Inputgain" );
	m_outGainModel.loadSettings( _this, "Outputgain" );
	m_lowShelfGainModel.loadSettings( _this , "Lowshelfgain" );
	m_para1GainModel.loadSettings( _this, "Peak1gain" );
	m_para2GainModel.loadSettings( _this, "Peak2gain" );
	m_para3GainModel.loadSettings( _this, "Peak3gain" );
	m_para4GainModel.loadSettings( _this, "Peak4gain" );
	m_highShelfGainModel.loadSettings( _this , "HighShelfgain" );
	m_hpResModel.loadSettings( _this ,"HPres" );
	m_lowShelfResModel.loadSettings( _this, "LowShelfres" );
	m_para1BwModel.loadSettings( _this ,"Peak1bw" );
	m_para2BwModel.loadSettings( _this ,"Peak2bw" );
	m_para3BwModel.loadSettings( _this ,"Peak3bw" );
	m_para4BwModel.loadSettings( _this ,"Peak4bw" );
	m_highShelfResModel.loadSettings( _this, "HighShelfres" );
	m_lpResModel.loadSettings( _this, "LPres" );
	m_hpFeqModel.loadSettings( _this, "HPfreq" );
	m_lowShelfFreqModel.loadSettings( _this, "LowShelffreq" );
	m_para1FreqModel.loadSettings( _this, "Peak1freq" );
	m_para2FreqModel.loadSettings( _this, "Peak2freq" );
	m_para3FreqModel.loadSettings( _this, "Peak3freq" );
	m_para4FreqModel.loadSettings( _this, "Peak4freq" );
	m_highShelfFreqModel.loadSettings( _this, "Highshelffreq" );
	m_lpFreqModel.loadSettings( _this, "LPfreq" );
	m_hpActiveModel.loadSettings( _this, "HPactive" );
	m_lowShelfActiveModel.loadSettings( _this, "Lowshelfactive" );
	m_para1ActiveModel.loadSettings( _this, "Peak1active" );
	m_para2ActiveModel.loadSettings( _this, "Peak2active" );
	m_para3ActiveModel.loadSettings( _this, "Peak3active" );
	m_para4ActiveModel.loadSettings( _this, "Peak4active" );
	m_highShelfActiveModel.loadSettings( _this, "Highshelfactive" );
	m_lpActiveModel.loadSettings( _this, "LPactive" );
	m_lp12Model.loadSettings( _this , "LP12" );
	m_lp24Model.loadSettings( _this , "LP24" );
	m_lp48Model.loadSettings( _this , "LP48" );
	m_hp12Model.loadSettings( _this , "HP12" );
	m_hp24Model.loadSettings( _this , "HP24" );
	m_hp48Model.loadSettings( _this , "HP48" );
	m_lpTypeModel.loadSettings( _this, "LP" );
	m_hpTypeModel.loadSettings( _this, "HP" );
	m_analyseInModel.loadSettings( _this, "AnalyseIn" );
	m_analyseOutModel.loadSettings( _this, "AnalyseOut" );
}

EffectControlDialog*EqControls::createView()
{
	return new EqControlsDialog( this );
}

void EqControls::saveSettings( QDomDocument &doc, QDomElement &parent )
{
	m_inGainModel.saveSettings( doc, parent, "Inputgain" );
	m_outGainModel.saveSettings( doc, parent, "Outputgain");
	m_lowShelfGainModel.saveSettings( doc, parent , "Lowshelfgain" );
	m_para1GainModel.saveSettings( doc, parent, "Peak1gain" );
	m_para2GainModel.saveSettings( doc, parent, "Peak2gain" );
	m_para3GainModel.saveSettings( doc, parent, "Peak3gain" );
	m_para4GainModel.saveSettings( doc, parent, "Peak4gain" );
	m_highShelfGainModel.saveSettings( doc, parent, "HighShelfgain" );
	m_hpResModel.saveSettings( doc, parent ,"HPres" );
	m_lowShelfResModel.saveSettings( doc, parent, "LowShelfres" );
	m_para1BwModel.saveSettings( doc, parent,"Peak1bw" );
	m_para2BwModel.saveSettings( doc, parent,"Peak2bw" );
	m_para3BwModel.saveSettings( doc, parent,"Peak3bw" );
	m_para4BwModel.saveSettings( doc, parent,"Peak4bw" );
	m_highShelfResModel.saveSettings( doc, parent, "HighShelfres" );
	m_lpResModel.saveSettings( doc, parent, "LPres" );
	m_hpFeqModel.saveSettings( doc, parent, "HPfreq" );
	m_lowShelfFreqModel.saveSettings( doc, parent, "LowShelffreq" );
	m_para1FreqModel.saveSettings( doc, parent, "Peak1freq" );
	m_para2FreqModel.saveSettings( doc, parent, "Peak2freq" );
	m_para3FreqModel.saveSettings( doc, parent, "Peak3freq" );
	m_para4FreqModel.saveSettings( doc, parent, "Peak4freq" );
	m_highShelfFreqModel.saveSettings( doc, parent, "Highshelffreq" );
	m_lpFreqModel.saveSettings( doc, parent, "LPfreq" );
	m_hpActiveModel.saveSettings( doc, parent, "HPactive" );
	m_lowShelfActiveModel.saveSettings( doc, parent, "Lowshelfactive" );
	m_para1ActiveModel.saveSettings( doc, parent, "Peak1active" );
	m_para2ActiveModel.saveSettings( doc, parent, "Peak2active" );
	m_para3ActiveModel.saveSettings( doc, parent, "Peak3active" );
	m_para4ActiveModel.saveSettings( doc, parent, "Peak4active" );
	m_highShelfActiveModel.saveSettings( doc, parent, "Highshelfactive" );
	m_lpActiveModel.saveSettings( doc, parent, "LPactive" );
	m_lp12Model.saveSettings( doc, parent, "LP12" );
	m_lp24Model.saveSettings( doc, parent, "LP24" );
	m_lp48Model.saveSettings( doc, parent, "LP48" );
	m_hp12Model.saveSettings( doc, parent, "HP12" );
	m_hp24Model.saveSettings( doc, parent, "HP24" );
	m_hp48Model.saveSettings( doc, parent, "HP48" );
	m_lpTypeModel.saveSettings( doc, parent, "LP" );
	m_hpTypeModel.saveSettings( doc, parent, "HP" );
	m_analyseInModel.saveSettings( doc, parent, "AnalyseIn" );
	m_analyseOutModel.saveSettings( doc, parent, "AnalyseOut" );
}


code:
/*
 * eqcontrols.h - defination of EqControls class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 EQCONTROLS_H
#define EQCONTROLS_H

#include "EffectControls.h"
#include "EqSpectrumView.h"

class EqEffect;

class EqControls : public EffectControls
{
	Q_OBJECT
public:
	explicit EqControls( EqEffect* effect );
	virtual ~EqControls()
	{
	}

	virtual void saveSettings ( QDomDocument& doc, QDomElement& parent );

	virtual void loadSettings ( const QDomElement &_this );

	inline virtual QString nodeName() const
	{
		return "Eq";
	}

	virtual int controlCount()
	{
		return 42;
	}

	virtual EffectControlDialog* createView();

	float m_inPeakL;
	float m_inPeakR;
	float m_outPeakL;
	float m_outPeakR;
	float m_lowShelfPeakL, m_lowShelfPeakR;
	float m_para1PeakL, m_para1PeakR;
	float m_para2PeakL, m_para2PeakR;
	float m_para3PeakL, m_para3PeakR;
	float m_para4PeakL, m_para4PeakR;
	float m_highShelfPeakL, m_highShelfPeakR;

	EqAnalyser m_inFftBands;
	EqAnalyser m_outFftBands;

	bool m_inProgress;
	bool visable();

private:
	EqEffect *m_effect;

	FloatModel m_inGainModel;
	FloatModel m_outGainModel;
	FloatModel m_lowShelfGainModel;
	FloatModel m_para1GainModel;
	FloatModel m_para2GainModel;
	FloatModel m_para3GainModel;
	FloatModel m_para4GainModel;
	FloatModel m_highShelfGainModel;

	FloatModel m_hpResModel;
	FloatModel m_lowShelfResModel;
	FloatModel m_para1BwModel;
	FloatModel m_para2BwModel;
	FloatModel m_para3BwModel;
	FloatModel m_para4BwModel;
	FloatModel m_highShelfResModel;
	FloatModel m_lpResModel;

	FloatModel m_hpFeqModel;
	FloatModel m_lowShelfFreqModel;
	FloatModel m_para1FreqModel;
	FloatModel m_para2FreqModel;
	FloatModel m_para3FreqModel;
	FloatModel m_para4FreqModel;
	FloatModel m_highShelfFreqModel;
	FloatModel m_lpFreqModel;

	BoolModel m_hpActiveModel;
	BoolModel m_lowShelfActiveModel;
	BoolModel m_para1ActiveModel;
	BoolModel m_para2ActiveModel;
	BoolModel m_para3ActiveModel;
	BoolModel m_para4ActiveModel;
	BoolModel m_highShelfActiveModel;
	BoolModel m_lpActiveModel;

	BoolModel m_lp12Model;
	BoolModel m_lp24Model;
	BoolModel m_lp48Model;

	BoolModel m_hp12Model;
	BoolModel m_hp24Model;
	BoolModel m_hp48Model;

	IntModel m_lpTypeModel;
	IntModel m_hpTypeModel;

	BoolModel m_analyseInModel;
	BoolModel m_analyseOutModel;

	friend class EqControlsDialog;
	friend class EqEffect;
};
#endif // EQCONTROLS_H

repo_name: CYBERDEViL/LMMS

license: mit


code:
/*
 * eqcontrolsdialog.cpp - defination of EqControlsDialog class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 "EqControlsDialog.h"

#include <QGraphicsView>
#include <QLayout>
#include <QWidget>

#include "AutomatableButton.h"
#include "embed.h"
#include "Engine.h"
#include "Knob.h"
#include "Fader.h"
#include "LedCheckbox.h"
#include "PixmapButton.h"

#include "EqControls.h"
#include "EqFader.h"
#include "EqParameterWidget.h"
#include "EqSpectrumView.h"

EqControlsDialog::EqControlsDialog( EqControls *controls ) :
	EffectControlDialog( controls ),
	m_controls( controls )
{
	setAutoFillBackground( true );
	QPalette pal;
	pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
	setPalette( pal );
	setFixedSize( 500, 500 );

	EqSpectrumView * inSpec = new EqSpectrumView( &controls->m_inFftBands, this );
	inSpec->move( 26, 17 );
	inSpec->setColor( QColor( 77, 101, 242, 150 ) );

	EqSpectrumView * outSpec = new EqSpectrumView( &controls->m_outFftBands, this );
	outSpec->setColor( QColor( 0, 255, 239, 150 ) );
	outSpec->move( 26, 17 );

	m_parameterWidget = new EqParameterWidget( this , controls );
	m_parameterWidget->move( 26, 17 );

	setBand( 0, &controls->m_hpActiveModel, &controls->m_hpFeqModel, &controls->m_hpResModel, 0, QColor(255 ,255, 255), tr( "HP" ) ,0,0, &controls->m_hp12Model, &controls->m_hp24Model, &controls->m_hp48Model,0,0,0);
	setBand( 1, &controls->m_lowShelfActiveModel, &controls->m_lowShelfFreqModel, &controls->m_lowShelfResModel, &controls->m_lowShelfGainModel, QColor(255 ,255, 255), tr( "Low-shelf" ), &controls->m_lowShelfPeakL , &controls->m_lowShelfPeakR,0,0,0,0,0,0 );
	setBand( 2, &controls->m_para1ActiveModel, &controls->m_para1FreqModel, &controls->m_para1BwModel, &controls->m_para1GainModel, QColor(255 ,255, 255), tr( "Peak 1" ), &controls->m_para1PeakL, &controls->m_para1PeakR,0,0,0,0,0,0 );
	setBand( 3, &controls->m_para2ActiveModel, &controls->m_para2FreqModel, &controls->m_para2BwModel, &controls->m_para2GainModel, QColor(255 ,255, 255), tr( "Peak 2" ), &controls->m_para2PeakL, &controls->m_para2PeakR,0,0,0,0,0,0 );
	setBand( 4, &controls->m_para3ActiveModel, &controls->m_para3FreqModel, &controls->m_para3BwModel, &controls->m_para3GainModel, QColor(255 ,255, 255), tr( "Peak 3" ), &controls->m_para3PeakL, &controls->m_para3PeakR,0,0,0,0,0,0 );
	setBand( 5, &controls->m_para4ActiveModel, &controls->m_para4FreqModel, &controls->m_para4BwModel, &controls->m_para4GainModel, QColor(255 ,255, 255), tr( "Peak 4" ), &controls->m_para4PeakL, &controls->m_para4PeakR,0,0,0,0,0,0 );
	setBand( 6, &controls->m_highShelfActiveModel, &controls->m_highShelfFreqModel, &controls->m_highShelfResModel, &controls->m_highShelfGainModel, QColor(255 ,255, 255), tr( "High-shelf" ), &controls->m_highShelfPeakL, &controls->m_highShelfPeakR,0,0,0,0,0,0 );
	setBand( 7, &controls->m_lpActiveModel, &controls->m_lpFreqModel, &controls->m_lpResModel, 0, QColor(255 ,255, 255), tr( "LP" ) ,0,0,0,0,0, &controls->m_lp12Model, &controls->m_lp24Model, &controls->m_lp48Model);

	QPixmap * faderBg = new QPixmap( PLUGIN_NAME::getIconPixmap( "faderback" ) );
	QPixmap * faderLeds = new QPixmap( PLUGIN_NAME::getIconPixmap( "faderleds" ) );
	QPixmap * faderKnob = new QPixmap( PLUGIN_NAME::getIconPixmap( "faderknob" ) );

	EqFader * GainFaderIn = new EqFader( &controls->m_inGainModel, tr( "Input gain" ), this, faderBg, faderLeds, faderKnob, &controls->m_inPeakL, &controls->m_inPeakR );
	GainFaderIn->move( 23, 295 );
	GainFaderIn->setDisplayConversion( false );
	GainFaderIn->setHintText( tr( "Gain" ), "dBv");

	EqFader * GainFaderOut = new EqFader( &controls->m_outGainModel, tr( "Output gain" ), this, faderBg, faderLeds, faderKnob, &controls->m_outPeakL, &controls->m_outPeakR );
	GainFaderOut->move( 453, 295);
	GainFaderOut->setDisplayConversion( false );
	GainFaderOut->setHintText( tr( "Gain" ), "dBv" );

	// Gain Fader for each Filter exepts the pass filter
	int distance = 126;
	for( int i = 1; i < m_parameterWidget->bandCount() - 1; i++ )
	{
		EqFader * gainFader = new EqFader( m_parameterWidget->getBandModels( i )->gain, tr( "" ), this, faderBg, faderLeds, faderKnob, m_parameterWidget->getBandModels( i )->peakL, m_parameterWidget->getBandModels( i )->peakR );
		gainFader->move( distance, 295 );
		distance += 44;
		gainFader->setMinimumHeight(80);
		gainFader->resize(gainFader->width() , 80);
		gainFader->setDisplayConversion( false );
		gainFader->setHintText( tr( "Gain") , "dB");
	}

	//Control Button and Knobs for each Band
	distance = 81;
	for( int i = 0; i < m_parameterWidget->bandCount() ; i++ )
	{
		Knob * resKnob = new Knob( knobBright_26, this );
		resKnob->move( distance, 440 );
		resKnob->setVolumeKnob(false);
		resKnob->setModel( m_parameterWidget->getBandModels( i )->res );
		if(i > 1 && i < 6) { resKnob->setHintText( tr( "Bandwidth: " ) , tr( " Octave" ) ); }
		else { resKnob->setHintText( tr( "Resonance : " ) , "" ); }

		Knob * freqKnob = new Knob( knobBright_26, this );
		freqKnob->move( distance, 396 );
		freqKnob->setVolumeKnob( false );
		freqKnob->setModel( m_parameterWidget->getBandModels( i )->freq );
		freqKnob->setHintText( tr( "Frequency:" ), "Hz" );

		// adds the Number Active buttons
		PixmapButton * activeButton = new PixmapButton( this, NULL );
		activeButton->setCheckable(true);
		activeButton->setModel( m_parameterWidget->getBandModels( i )->active );

		QString iconActiveFileName = "bandLabel" + QString::number(i+1);
		QString iconInactiveFileName = "bandLabel" + QString::number(i+1) + "off";
		activeButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap( iconActiveFileName.toLatin1() ) );
		activeButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( iconInactiveFileName.toLatin1() ) );
		activeButton->move( distance - 2, 276 );
		activeButton->setModel( m_parameterWidget->getBandModels( i )->active );

		// Connects the knobs, Faders and buttons with the curve graphic
		QObject::connect( m_parameterWidget->getBandModels( i )->freq , SIGNAL( dataChanged() ), m_parameterWidget, SLOT ( updateHandle() ) );
		if ( m_parameterWidget->getBandModels( i )->gain ) QObject::connect( m_parameterWidget->getBandModels( i )->gain, SIGNAL( dataChanged() ), m_parameterWidget, SLOT ( updateHandle() ));
		QObject::connect( m_parameterWidget->getBandModels( i )->res, SIGNAL( dataChanged() ), m_parameterWidget , SLOT ( updateHandle() ) );
		QObject::connect( m_parameterWidget->getBandModels( i )->active, SIGNAL( dataChanged() ), m_parameterWidget , SLOT ( updateHandle() ) );

		m_parameterWidget->changeHandle( i );
		distance += 44;
	}

	// adds the buttons for Spectrum analyser on/off
	LedCheckBox * inSpecButton = new LedCheckBox( this );
	inSpecButton->setCheckable(true);
	inSpecButton->setModel( &controls->m_analyseInModel );
	inSpecButton->move( 172, 240 );
	LedCheckBox * outSpecButton = new LedCheckBox( this );
	outSpecButton->setCheckable(true);
	outSpecButton->setModel( &controls->m_analyseOutModel );
	outSpecButton->move( 302, 240 );

	//hp filter type
	PixmapButton * hp12Button = new PixmapButton( this , NULL );
	hp12Button->setModel( m_parameterWidget->getBandModels( 0 )->hp12 );
	hp12Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "12dB" ) );
	hp12Button->setInactiveGraphic(  PLUGIN_NAME::getIconPixmap( "12dBoff" ) );
	hp12Button->move( 79, 298 );
	PixmapButton * hp24Button = new PixmapButton( this , NULL );
	hp24Button->setModel(m_parameterWidget->getBandModels( 0 )->hp24 );
	hp24Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "24dB" ) );
	hp24Button->setInactiveGraphic(  PLUGIN_NAME::getIconPixmap( "24dBoff" ) );

	hp24Button->move( 79 , 328 );
	PixmapButton * hp48Button = new PixmapButton( this , NULL );
	hp48Button->setModel( m_parameterWidget->getBandModels(0)->hp48 );
	hp48Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "48dB" ) );
	hp48Button->setInactiveGraphic(  PLUGIN_NAME::getIconPixmap( "48dBoff" ) );

	hp48Button->move( 79, 358 );
	//LP filter type
	PixmapButton * lp12Button = new PixmapButton( this , NULL );
	lp12Button->setModel( m_parameterWidget->getBandModels( 7 )->lp12 );
	lp12Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "12dB" ) );
	lp12Button->setInactiveGraphic(  PLUGIN_NAME::getIconPixmap( "12dBoff" ) );

	lp12Button->move( 387, 298 );
	PixmapButton * lp24Button = new PixmapButton( this , NULL );
	lp24Button->setModel( m_parameterWidget->getBandModels( 7 )->lp24 );
	lp24Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "24dB" ) );
	lp24Button->setInactiveGraphic(  PLUGIN_NAME::getIconPixmap( "24dBoff" ) );

	lp24Button->move( 387, 328 );

	PixmapButton * lp48Button = new PixmapButton( this , NULL );
	lp48Button->setModel( m_parameterWidget->getBandModels( 7 )->lp48 );
	lp48Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "48dB" ) );
	lp48Button->setInactiveGraphic(  PLUGIN_NAME::getIconPixmap( "48dBoff" ) );

	lp48Button->move( 387, 358 );
	// the curve has to change its appearance
	QObject::connect( m_parameterWidget->getBandModels( 0 )->hp12 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateHandle()));
	QObject::connect( m_parameterWidget->getBandModels( 0 )->hp24 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateHandle()));
	QObject::connect( m_parameterWidget->getBandModels( 0 )->hp48 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateHandle()));

	QObject::connect( m_parameterWidget->getBandModels( 7 )->lp12 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateHandle()));
	QObject::connect( m_parameterWidget->getBandModels( 7 )->lp24 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateHandle()));
	QObject::connect( m_parameterWidget->getBandModels( 7 )->lp48 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateHandle()));

	automatableButtonGroup *lpBtnGrp = new automatableButtonGroup( this, tr( "LP group" ) );
	lpBtnGrp->addButton( lp12Button );
	lpBtnGrp->addButton( lp24Button );
	lpBtnGrp->addButton( lp48Button );
	lpBtnGrp->setModel( &m_controls->m_lpTypeModel, false);

	automatableButtonGroup *hpBtnGrp = new automatableButtonGroup( this, tr( "HP group" ) );
	hpBtnGrp->addButton( hp12Button );
	hpBtnGrp->addButton( hp24Button );
	hpBtnGrp->addButton( hp48Button );
	hpBtnGrp->setModel( &m_controls->m_hpTypeModel,false);
}

void EqControlsDialog::mouseDoubleClickEvent(QMouseEvent *event)
{
	m_originalHeight = parentWidget()->height() == 283 ? m_originalHeight : parentWidget()->height() ;
	parentWidget()->setFixedHeight( parentWidget()->height() == m_originalHeight ? 283 : m_originalHeight  );
	update();
}

EqBand* EqControlsDialog::setBand(int index, BoolModel* active, FloatModel* freq, FloatModel* res, FloatModel* gain, QColor color, QString name, float* peakL, float* peakR, BoolModel* hp12, BoolModel* hp24, BoolModel* hp48, BoolModel* lp12, BoolModel* lp24, BoolModel* lp48)
{
	EqBand *filterModels = m_parameterWidget->getBandModels( index );
	filterModels->active = active;
	filterModels->freq = freq;
	filterModels->res = res;
	filterModels->color = color;
	filterModels->gain = gain;
	filterModels->peakL = peakL;
	filterModels->peakR = peakR;
	filterModels->hp12 = hp12;
	filterModels->hp24 = hp24;
	filterModels->hp48 = hp48;
	filterModels->lp12 = lp12;
	filterModels->lp24 = lp24;
	filterModels->lp48 = lp48;
	return filterModels;
}


code:
/*
 * eqcontrolsdialog.h - defination of EqControlsDialog class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 EQCONTROLSDIALOG_H
#define EQCONTROLSDIALOG_H

#include <QLabel>
#include <QPushButton>

#include "EffectControlDialog.h"

class BoolModel;
class FloatModel;

class EqControls;
class EqBand;
class EqParameterWidget;

class EqControlsDialog : public EffectControlDialog
{
	Q_OBJECT
public:
	EqControlsDialog( EqControls * controls );
	virtual ~EqControlsDialog()
	{
	}

	EqBand * setBand( EqControls * controls );

private:
	EqControls * m_controls;
	EqParameterWidget * m_parameterWidget;

	virtual void mouseDoubleClickEvent(QMouseEvent *event);

	EqBand *setBand( int index, BoolModel *active, FloatModel *freq, FloatModel *res, FloatModel *gain, QColor color, QString name, float *peakL, float *peakR, BoolModel *hp12, BoolModel *hp24, BoolModel *hp48, BoolModel *lp12, BoolModel *lp24, BoolModel *lp48 );

	int m_originalHeight;
};

#endif // EQCONTROLSDIALOG_H


code:
/*
 * EqCurve.cpp - declaration of EqCurve and EqHandle classes.
 *
 * Copyright (c) 2015 Steffen Baranowsky <BaraMGB/at/freenet/dot/de>
 *
 * 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 "EqCurve.h"

#include "Effect.h"
#include "embed.h"
#include "lmms_math.h"

EqHandle::EqHandle( int num, int x, int y ):
	m_numb( num ),
	m_width( x ),
	m_heigth( y ),
	m_mousePressed( false ),
	m_active( false )
{
	setFlag( ItemIsMovable );
	setFlag( ItemSendsGeometryChanges );
	setAcceptHoverEvents( true );
	float totalHeight = 36;
	m_pixelsPerUnitHeight = ( m_heigth ) / ( totalHeight );
	setMouseHover( false );
}

QRectF EqHandle::boundingRect() const
{
	return QRectF( - m_circlePixmap.width() / 2, - m_circlePixmap.height() / 2, m_circlePixmap.width(), m_circlePixmap.height() );
}

float EqHandle::freqToXPixel( float freq , int w )
{
	float min = log10f( 20 );
	float max = log10f( 20000 );
	float range = max - min;
	return ( log10f( freq ) - min ) / range * w;
}

float EqHandle::xPixelToFreq( float x , int w )
{
	float min = log10f( 20 );
	float max = log10f( 20000 );
	float range = max - min;
	return powf( 10 , x * ( range / w ) + min );
}

float EqHandle::gainToYPixel(float gain , int h, float pixelPerUnitHeight )
{
	return h * 0.5 - gain * pixelPerUnitHeight;
}

float EqHandle::yPixelToGain(float y , int h, float pixelPerUnitHeight )
{
	return ( ( h * 0.5 ) - y ) / pixelPerUnitHeight;
}

void EqHandle::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
	painter->setRenderHint( QPainter::Antialiasing, true );
	if ( m_mousePressed )
	{
		emit positionChanged();
	}

	// graphics for the handles
	loadPixmap();
	painter->drawPixmap( - ( m_circlePixmap.width() / 2 ) - 1 , - ( m_circlePixmap.height() / 2 ), m_circlePixmap );

	// on mouse hover draw an info box and change the pixmap of the handle
	if ( isMouseHover() )
	{
		// keeps the info box in view
		float rectX = -40;
		float rectY = -40;
		if ( EqHandle::y() < 40 )
		{
			rectY = rectY + 40 - EqHandle::y();
		}
		if ( EqHandle::x() < 40 )
		{
			rectX = rectX + 40 - EqHandle::x();
		}
		if ( EqHandle::x() > m_width - 40 )
		{
			rectX = rectX - ( 40 - ( m_width - EqHandle::x() ) );
		}
		QPixmap hover = PLUGIN_NAME::getIconPixmap( "handlehover" );
		painter->drawPixmap( - ( hover.width() / 2) - 1, - ( hover.height() / 2 ), hover );
		QRectF textRect = QRectF ( rectX, rectY, 80, 30 );
		QRectF textRect2 = QRectF ( rectX+1, rectY+1, 80, 30 );
		QString freq = QString::number( xPixelToFreq( EqHandle::x(), m_width ) );
		QString res;
		if ( getType() != para )
		{
			res = tr( "Reso: ") + QString::number( getResonance() );
		}
		else
		{
			res = tr( "BW: " ) +  QString::number( getResonance() );
		}

		QFont painterFont = painter->font();
		painterFont.setPointSizeF( painterFont.pointSizeF() * 0.7 );
		painter->setFont( painterFont );
		painter->setPen( Qt::black );
		painter->drawRect( textRect );
		painter->fillRect( textRect, QBrush( QColor( 6, 106, 43, 180 ) ) );

		painter->setPen ( QColor( 0, 0, 0 ) );
		painter->drawText( textRect2, Qt::AlignCenter,
						   QString( tr( "Freq: " ) + freq + "\n" + res ) );
		painter->setPen( QColor( 255, 255, 255 ) );
		painter->drawText( textRect, Qt::AlignCenter,
						   QString( tr( "Freq: " ) + freq + "\n" + res ) );
	}
}

QPainterPath EqHandle::getCurvePath()
{
	QPainterPath path;
	float y = m_heigth * 0.5;
	for ( float x = 0 ; x < m_width; x++ )
	{
		if ( m_type == highpass ) y = getLowCutCurve( x );
		if ( m_type == lowshelf ) y = getLowShelfCurve( x );
		if ( m_type == para ) y = getPeakCurve( x );
		if ( m_type == highshelf ) y = getHighShelfCurve( x );
		if ( m_type == lowpass ) y = getHighCutCurve( x );
		if ( x == 0 ) path.moveTo( x, y ); // sets the begin of Path
		path.lineTo( x, y );
	}
	return path;
}

void EqHandle::loadPixmap()
{
	QString fileName = "handle" + QString::number(m_numb+1);
	if ( !isActiveHandle() ) { fileName = fileName + "inactive"; }
	m_circlePixmap = PLUGIN_NAME::getIconPixmap( fileName.toLatin1() );
}

bool EqHandle::mousePressed() const
{
	return m_mousePressed;
}

float EqHandle::getPeakCurve( float x )
{
	double freqZ = xPixelToFreq( EqHandle::x(), m_width );
	const int SR = Engine::mixer()->processingSampleRate();
	double w0 = 2 * LD_PI * freqZ / SR ;
	double c = cosf( w0 );
	double s = sinf( w0 );
	double Q = getResonance();
	double A =  pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 40 );
	double alpha = s * sinh( log( 2 ) / 2 * Q * w0 / sinf( w0 ) );
	double a0, a1, a2, b0, b1, b2; // coeffs to calculate

	//calc coefficents
	b0 =   1 + alpha * A;
	b1 =  -2 * c;
	b2 =   1 - alpha * A;
	a0 =   1 + alpha / A;
	a1 =  -2 * c;
	a2 =   1 - alpha / A;

	//normalise
	b0 /= a0;
	b1 /= a0;
	b2 /= a0;
	a1 /= a0;
	a2 /= a0;
	a0 = 1;

	double freq = xPixelToFreq( x, m_width );
	double gain = calculateGain( freq, a1, a2, b0, b1, b2 );
	float y = gainToYPixel( gain, m_heigth, m_pixelsPerUnitHeight );

	return y;
}

float EqHandle::getHighShelfCurve( float x )
{
	double freqZ = xPixelToFreq( EqHandle::x(), m_width );
	const int SR = Engine::mixer()->processingSampleRate();
	double w0 = 2 * LD_PI * freqZ / SR;
	double c = cosf( w0 );
	double s = sinf( w0 );
	double A =  pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) * 0.025 );
	double beta = sqrt( A ) / m_resonance;
	double a0, a1, a2, b0, b1, b2; // coeffs to calculate

	//calc coefficents
	b0 = A * ( ( A + 1 ) + ( A - 1 ) * c + beta * s);
	b1 = -2 * A * ( ( A - 1 ) + ( A + 1 ) * c );
	b2 = A * ( ( A + 1 ) + ( A - 1 ) * c - beta * s);
	a0 = ( A + 1 ) - ( A - 1 ) * c + beta * s;
	a1 = 2 * ( ( A - 1 ) - ( A + 1 ) * c );
	a2 = ( A + 1 ) - ( A - 1 ) * c - beta * s;
	//normalise
	b0 /= a0;
	b1 /= a0;
	b2 /= a0;
	a1 /= a0;
	a2 /= a0;
	a0 = 1;

	double freq = xPixelToFreq( x, m_width );
	double gain = calculateGain( freq, a1, a2, b0, b1, b2 );
	float y = gainToYPixel( gain, m_heigth, m_pixelsPerUnitHeight );

	return y;
}

float EqHandle::getLowShelfCurve( float x )
{
	double freqZ = xPixelToFreq( EqHandle::x(), m_width );
	const int SR = Engine::mixer()->processingSampleRate();
	double w0 = 2 * LD_PI * freqZ / SR ;
	double c = cosf( w0 );
	double s = sinf( w0 );
	double A =  pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 40 );
	double beta = sqrt( A ) / m_resonance;
	double a0, a1, a2, b0, b1, b2; // coeffs to calculate

	//calc coefficents
	b0 = A * ( ( A + 1 ) - ( A - 1 ) * c + beta * s );
	b1 = 2  * A * ( ( A - 1 ) - ( A + 1 ) * c ) ;
	b2 = A * ( ( A + 1 ) - ( A - 1 ) * c - beta * s);
	a0 = ( A + 1 ) + ( A - 1 ) * c + beta * s;
	a1 = -2 * ( ( A - 1 ) + ( A + 1 ) * c );
	a2 = ( A + 1 ) + ( A - 1) * c - beta * s;

	//normalise
	b0 /= a0;
	b1 /= a0;
	b2 /= a0;
	a1 /= a0;
	a2 /= a0;
	a0 = 1;

	double freq = xPixelToFreq( x, m_width );
	double gain = calculateGain( freq, a1, a2, b0, b1, b2 );
	float y = gainToYPixel( gain, m_heigth, m_pixelsPerUnitHeight );

	return y;
}

float EqHandle::getLowCutCurve( float x )
{
	double freqZ = xPixelToFreq( EqHandle::x(), m_width );
	const int SR = Engine::mixer()->processingSampleRate();
	double w0 = 2 * LD_PI * freqZ / SR ;
	double c = cosf( w0 );
	double s = sinf( w0 );
	double resonance = getResonance();
	double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 20);
	double alpha = s / 2 * sqrt ( ( A +1/A ) * ( 1 / resonance -1 ) +2 );
	double a0, a1, a2, b0, b1, b2; // coeffs to calculate

	b0 = ( 1 + c ) * 0.5;
	b1 = ( -( 1 + c ) );
	b2 = ( 1 + c ) * 0.5;
	a0 = 1 + alpha;
	a1 = ( -2 * c );
	a2 = 1 - alpha;
	//normalise
	b0 /= a0;
	b1 /= a0;
	b2 /= a0;
	a1 /= a0;
	a2 /= a0;
	a0 = 1;

	double freq = xPixelToFreq( x, m_width );
	double gain = calculateGain( freq, a1, a2, b0, b1, b2 );
	if ( m_hp24 )
	{
		gain = gain * 2;
	}
	if ( m_hp48 )
	{
		gain = gain * 3;
	}
	float y = gainToYPixel( gain, m_heigth, m_pixelsPerUnitHeight );

	return y;
}

float EqHandle::getHighCutCurve( float x )
{
	double freqZ = xPixelToFreq( EqHandle::x(), m_width );
	const int SR = Engine::mixer()->processingSampleRate();
	double w0 = 2 * LD_PI * freqZ / SR ;
	double c = cosf( w0 );
	double s = sinf( w0 );
	double resonance = getResonance();
	double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 20 );
	double alpha = s / 2 * sqrt ( ( A + 1 / A ) * ( 1 / resonance -1 ) +2 );
	double a0, a1, a2, b0, b1, b2; // coeffs to calculate

	b0 = ( 1 - c ) * 0.5;
	b1 = 1 - c;
	b2 = ( 1 - c ) * 0.5;
	a0 = 1 + alpha;
	a1 = -2 * c;
	a2 = 1 - alpha;
	//normalise
	b0 /= a0;
	b1 /= a0;
	b2 /= a0;
	a1 /= a0;
	a2 /= a0;
	a0 = 1;

	double freq = xPixelToFreq( x, m_width );
	double gain = calculateGain( freq, a1, a2, b0, b1, b2 );
	if ( m_lp24 )
	{
		gain = gain * 2;
	}
	if ( m_lp48 )
	{
		gain = gain * 3;
	}
	float y = gainToYPixel( gain, m_heigth, m_pixelsPerUnitHeight );

	return y;
}

float EqHandle::getResonance()
{
	return m_resonance;
}

int EqHandle::getNum()
{
	return m_numb;
}

void EqHandle::setType( int t )
{
	EqHandle::m_type = t;
}

void EqHandle::setResonance( float r )
{
	EqHandle::m_resonance = r;
}

bool EqHandle::isMouseHover()
{
	return m_mouseHover;
}

void EqHandle::setMouseHover( bool d )
{
	m_mouseHover = d;
}

int EqHandle::getType()
{
	return m_type;
}

bool EqHandle::isActiveHandle()
{
	return m_active;
}

void EqHandle::setHandleActive( bool a )
{
	EqHandle::m_active = a;
}

void EqHandle::sethp12()
{
	m_hp12 = true;
	m_hp24 = false;
	m_hp48 = false;
}

void EqHandle::sethp24()
{
	m_hp12 = false;
	m_hp24 = true;
	m_hp48 = false;
}

void EqHandle::sethp48()
{
	m_hp12 = false;
	m_hp24 = false;
	m_hp48 = true;
}

void EqHandle::setlp12()
{
	m_lp12 = true;
	m_lp24 = false;
	m_lp48 = false;
}

void EqHandle::setlp24()
{
	m_lp12 = false;
	m_lp24 = true;
	m_lp48 = false;
}

void EqHandle::setlp48()
{
	m_lp12 = false;
	m_lp24 = false;
	m_lp48 = true;
}

double EqHandle::calculateGain(const double freq, const double a1, const double a2, const double b0, const double b1, const double b2 )
{
	const int SR = Engine::mixer()->processingSampleRate();

	const double w = 2 * LD_PI * freq / SR ;
	const double PHI = pow( sin( w / 2 ), 2 ) * 4;

	double gain = 10 * log10( pow( b0 + b1 + b2 , 2 ) + ( b0 * b2 * PHI - ( b1 * ( b0 + b2 )
				+ 4 * b0 * b2 ) ) * PHI ) - 10 * log10( pow( 1 + a1 + a2, 2 )
				+ ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI );
	return gain;
}

void EqHandle::mousePressEvent( QGraphicsSceneMouseEvent *event )
{
	if( event->button() == Qt::LeftButton )
	{
		m_mousePressed = true;
		QGraphicsItem::mousePressEvent( event );
	}
}

void EqHandle::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
{
	if( event->button() == Qt::LeftButton )
	{
		m_mousePressed = false;
		QGraphicsItem::mouseReleaseEvent( event );
	}
}

void EqHandle::wheelEvent( QGraphicsSceneWheelEvent *wevent )
{
	float highestBandwich;
	if( m_type != para )
	{
		highestBandwich = 10;
	}
	else
	{
		highestBandwich = 4;
	}

	int numDegrees = wevent->delta() / 120;
	float numSteps = 0;
	if( wevent->modifiers() == Qt::ControlModifier )
	{
		numSteps = numDegrees * 0.01;
	}
	else
	{
		 numSteps = numDegrees * 0.15;
	}

	if( wevent->orientation() == Qt::Vertical )
	{
		m_resonance = m_resonance + ( numSteps );

		if( m_resonance < 0.1 )
		{
			m_resonance = 0.1;
		}

		if( m_resonance > highestBandwich )
		{
			m_resonance = highestBandwich;
		}
		emit positionChanged();
	}
	wevent->accept();
}

void EqHandle::hoverEnterEvent( QGraphicsSceneHoverEvent *hevent )
{
	setMouseHover( true );
}

void EqHandle::hoverLeaveEvent( QGraphicsSceneHoverEvent *hevent )
{
	setMouseHover( false );
}

QVariant EqHandle::itemChange( QGraphicsItem::GraphicsItemChange change, const QVariant &value )
{
	if( change == ItemPositionChange )
	{
		// pass filter don't move in y direction
		if ( m_type == highpass || m_type == lowpass )
		{
			float newX = value.toPointF().x();
			if( newX < 0 )
			{
				newX = 0;
			}
			if( newX > m_width )
			{
				newX = m_width;
			}
			return QPointF(newX, m_heigth/2);
		}
	}

	QPointF newPos = value.toPointF();
	QRectF rect = QRectF( 0, 0, m_width, m_heigth );
	if( !rect.contains( newPos ) )
	{
		// Keep the item inside the scene rect.
		newPos.setX( qMin( rect.right(), qMax( newPos.x(), rect.left() ) ) );
		newPos.setY( qMin( rect.bottom(), qMax( newPos.y(), rect.top() ) ) );
		return newPos;
	}
	return QGraphicsItem::itemChange( change, value );
}

// ----------------------------------------------------------------------
//
// Class EqCurve
//
// Every Handle calculates its own curve.
// But EqCurve generates an average curve.
//
// ----------------------------------------------------------------------

EqCurve::EqCurve( QList<EqHandle*> *handle, int x, int y ) :
	m_handle( handle ),
	m_width( x ),
	m_heigth( y ),
	m_alpha( 0 ),
	m_modelChanged( false )
{
}

QRectF EqCurve::boundingRect() const
{
	return QRect( 0, 0, m_width, m_heigth );
}

void EqCurve::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
	painter->setRenderHint( QPainter::Antialiasing, true );
	if( m_modelChanged )
	{
		setModelChanged( false );
		//counts the active bands
		int activeHandles=0;
		for ( int thatHandle = 0; thatHandle<m_handle->count(); thatHandle++ )
		{
			if ( m_handle->at(thatHandle)->isActiveHandle() == true )
			{
				activeHandles++;
			}
		}
		//Computes the main curve
		//if a band is active the curve will be computed by averaging the curves of each band
		QMap<float,float> mainCurve;
		for ( int thatHandle = 0; thatHandle<m_handle->count(); thatHandle++ )
		{
			if ( m_handle->at(thatHandle)->isActiveHandle() == true )
			{
				for ( int x = 0; x < m_width ; x=x+1 )
				{
					if ( m_handle->at( thatHandle )->getType() == highpass )
					{
						mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getLowCutCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) );
					}
					if ( m_handle->at(thatHandle)->getType() == lowshelf )
					{
						mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getLowShelfCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) );
					}
					if ( m_handle->at( thatHandle )->getType() == para )
					{
						mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getPeakCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) );
					}
					if ( m_handle->at( thatHandle )->getType() == highshelf )
					{
						mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getHighShelfCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) );
					}
					if ( m_handle->at(thatHandle)->getType() == lowpass )
					{
						mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getHighCutCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) );
					}
				}
			}
		}
		//compute a QPainterPath
		m_curve = QPainterPath();
		for ( int x = 0; x < m_width ; x++ )
		{
			mainCurve[x] = ( ( mainCurve[x] / activeHandles ) ) - ( m_heigth/2 );
			if ( x==0 )
			{
				m_curve.moveTo( x, mainCurve[x] );
			}
			m_curve.lineTo( x, mainCurve[x] );
		}
		//we cache the curve painting in a pixmap for saving cpu
		QPixmap cacheMap( boundingRect().size().toSize() );
		cacheMap.fill( QColor( 0, 0, 0, 0 ) );
		QPainter cachePainter( &cacheMap );
		cachePainter.setRenderHint( QPainter::Antialiasing, true );
		QPen pen;
		pen.setWidth( 2 );
		pen.setColor( Qt::white );
		cachePainter.setPen( pen );
		cachePainter.drawPath( m_curve );
		cachePainter.end();

		m_curvePixmapCache.fill( QColor( 0, 0, 0, 0 ) );
		m_curvePixmapCache.swap( cacheMap );
	}
	//we paint our cached curve pixmap
	painter->drawPixmap( 0, 0, m_width, m_heigth, m_curvePixmapCache );
	// if mouse hover a handle, m_alpha counts up slow for blend in the filled EQ curve
	// todo: a smarter way of this "if-monster"
	QColor curveColor;
	if( m_handle->at( 0 )->isMouseHover()
		 || m_handle->at( 1 )->isMouseHover()
		 || m_handle->at( 2 )->isMouseHover()
		 || m_handle->at( 3 )->isMouseHover()
		 || m_handle->at( 4 )->isMouseHover()
		 || m_handle->at( 5 )->isMouseHover()
		 || m_handle->at( 6 )->isMouseHover()
		 || m_handle->at( 7 )->isMouseHover()
		 )
	{
		if ( m_alpha < 40 )
		{
			m_alpha = m_alpha + 10;
		}
	}
	else
	{
		if ( m_alpha > 0 )
		{
			m_alpha = m_alpha - 10;
		}
	}
	//draw on mouse hover the curve of hovered filter in different colors
	for ( int i = 0; i < m_handle->count(); i++ )
	{
		if ( m_handle->at(i)->isMouseHover() )
		{
			curveColor = QColor( qRgba( 6, 106, 43, 242 ));
			QPen pen ( curveColor);
			pen.setWidth( 2 );
			painter->setPen( pen );
			painter->drawPath( m_handle->at( i )->getCurvePath() );
		}
	}
	//draw on mouse hover the EQ curve filled. with m_alpha it blends in and out smooth
	QPainterPath cPath;
	cPath.addPath( m_curve );
	cPath.lineTo( cPath.currentPosition().x(), m_heigth );
	cPath.lineTo( cPath.elementAt( 0 ).x  , m_heigth );
	painter->fillPath( cPath, QBrush ( QColor( 255,255,255, m_alpha ) ) );
}

void EqCurve::setModelChanged( bool mc )
{
	m_modelChanged = mc;
}


code:
/*
 * EqCurve.h - defination of EqCurve and EqHandle classes.
 *
* Copyright (c) 2015 Steffen Baranowsky <BaraMGB/at/freenet/dot/de>
 *
 * 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 EQCURVE_H
#define EQCURVE_H

#include <QGraphicsItem>
#include <QPainter>
#include <QGraphicsSceneWheelEvent>
#include "lmms_math.h"
#include "AutomatableModelView.h"

enum{
	highpass=1,
	lowshelf,
	para,
	highshelf,
	lowpass
};

// implements the Eq_Handle to control a band
class EqHandle : public QGraphicsObject
{
	Q_OBJECT
public:
	EqHandle( int num, int x, int y );

	static float freqToXPixel( float freq, int w );
	static float xPixelToFreq( float x , int w );
	static float gainToYPixel( float gain, int h, float pixelPerUnitHeight );
	static float yPixelToGain( float y, int h, float pixelPerUnitHeight );

	QRectF boundingRect() const;
	QPainterPath getCurvePath();
	float getPeakCurve( float x );
	float getHighShelfCurve( float x );
	float getLowShelfCurve( float x );
	float getLowCutCurve( float x );
	float getHighCutCurve( float x );
	float getResonance();
	int getNum();
	int getType();
	void setType( int t );
	void setResonance( float r );
	bool isMouseHover();
	void setMouseHover( bool d );
	bool isActiveHandle();
	void setHandleActive( bool a );
	bool mousePressed() const;
	void sethp12();
	void sethp24();
	void sethp48();
	void setlp12();
	void setlp24();
	void setlp48();

signals:
	void positionChanged();

protected:
	void mousePressEvent( QGraphicsSceneMouseEvent *event );
	void mouseReleaseEvent( QGraphicsSceneMouseEvent *event );
	void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
	void wheelEvent( QGraphicsSceneWheelEvent *wevent );
	void hoverEnterEvent( QGraphicsSceneHoverEvent *hevent );
	void hoverLeaveEvent( QGraphicsSceneHoverEvent *hevent );
	QVariant itemChange( GraphicsItemChange change, const QVariant &value );

private:
	double calculateGain( const double freq, const double a1, const double a2, const double b0, const double b1, const double b2 );
	void loadPixmap();
	float m_pixelsPerUnitWidth;
	float m_pixelsPerUnitHeight;
	float m_scale;
	bool m_hp12;
	bool m_hp24;
	bool m_hp48;
	bool m_lp12;
	bool m_lp24;
	bool m_lp48;
	bool m_mouseHover;
	int m_type, m_numb;
	float m_width, m_heigth;
	float m_resonance;
	bool m_mousePressed;
	bool m_active;
	QPixmap m_circlePixmap;
};

class EqCurve : public QGraphicsObject
{
	Q_OBJECT
public:
	EqCurve( QList<EqHandle*> *handle, int x, int y );
	QRectF boundingRect() const;
	void setModelChanged(bool mc);

protected:
	void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );

private:
	QList<EqHandle*> *m_handle;
	QPainterPath m_curve;
	QPixmap m_curvePixmapCache;
	int m_width, m_heigth;
	int m_alpha;
	bool m_modelChanged;
	float m_pixelsPerUnitHeight;
	float m_scale;
};

#endif // EQCURVE_H


code:
/*
 * eqeffect.cpp - defination of EqEffect class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 "EqEffect.h"

#include "Engine.h"
#include "EqFader.h"
#include "interpolation.h"
#include "lmms_math.h"

#include "embed.h"
#include "plugin_export.h"

extern "C"
{

Plugin::Descriptor PLUGIN_EXPORT eq_plugin_descriptor =
{
	STRINGIFY( PLUGIN_NAME ),
	"Equalizer",
	QT_TRANSLATE_NOOP( "PluginBrowser", "A native eq plugin" ),
	"Dave French <contact/dot/dave/dot/french3/at/googlemail/dot/com>",
	0x0100,
	Plugin::Effect,
	new PluginPixmapLoader("logo"),
	NULL,
	NULL
} ;

}

EqEffect::EqEffect( Model *parent, const Plugin::Descriptor::SubPluginFeatures::Key *key) :
	Effect( &eq_plugin_descriptor, parent, key ),
	m_eqControls( this ),
	m_inGain( 1.0 ),
	m_outGain( 1.0 )
{
}

EqEffect::~EqEffect()
{
}

bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
{
	const int sampleRate = Engine::mixer()->processingSampleRate();

	//wet/dry controls
	const float dry = dryLevel();
	const float wet = wetLevel();
	sample_t dryS[2];
	// setup sample exact controls
	float hpRes = m_eqControls.m_hpResModel.value();
	float lowShelfRes = m_eqControls.m_lowShelfResModel.value();
	float para1Bw = m_eqControls.m_para1BwModel.value();
	float para2Bw = m_eqControls.m_para2BwModel.value();
	float para3Bw = m_eqControls.m_para3BwModel.value();
	float para4Bw = m_eqControls.m_para4BwModel.value();
	float highShelfRes = m_eqControls.m_highShelfResModel.value();
	float lpRes = m_eqControls.m_lpResModel.value();

	float hpFreq = m_eqControls.m_hpFeqModel.value();
	float lowShelfFreq = m_eqControls.m_lowShelfFreqModel.value();
	float para1Freq = m_eqControls.m_para1FreqModel.value();
	float para2Freq = m_eqControls.m_para2FreqModel.value();
	float para3Freq = m_eqControls.m_para3FreqModel.value();
	float para4Freq = m_eqControls.m_para4FreqModel.value();
	float highShelfFreq = m_eqControls.m_highShelfFreqModel.value();
	float lpFreq = m_eqControls.m_lpFreqModel.value();

	bool hpActive = m_eqControls.m_hpActiveModel.value();
	bool hp24Active = m_eqControls.m_hp24Model.value();
	bool hp48Active = m_eqControls.m_hp48Model.value();
	bool lowShelfActive = m_eqControls.m_lowShelfActiveModel.value();
	bool para1Active = m_eqControls.m_para1ActiveModel.value();
	bool para2Active = m_eqControls.m_para2ActiveModel.value();
	bool para3Active = m_eqControls.m_para3ActiveModel.value();
	bool para4Active = m_eqControls.m_para4ActiveModel.value();
	bool highShelfActive = m_eqControls.m_highShelfActiveModel.value();
	bool lpActive = m_eqControls.m_lpActiveModel.value();
	bool lp24Active = m_eqControls.m_lp24Model.value();
	bool lp48Active = m_eqControls.m_lp48Model.value();

	float lowShelfGain = m_eqControls.m_lowShelfGainModel.value();
	float para1Gain = m_eqControls.m_para1GainModel.value();
	float para2Gain = m_eqControls.m_para2GainModel.value();
	float para3Gain = m_eqControls.m_para3GainModel.value();
	float para4Gain = m_eqControls.m_para4GainModel.value();
	float highShelfGain = m_eqControls.m_highShelfGainModel.value();

	//set all filter parameters once per frame, EqFilter handles
	//smooth xfading, reducing pops clicks and dc bias offsets

	m_hp12.setParameters( sampleRate, hpFreq, hpRes, 1 );
	m_hp24.setParameters( sampleRate, hpFreq, hpRes, 1 );
	m_hp480.setParameters( sampleRate, hpFreq, hpRes, 1 );
	m_hp481.setParameters( sampleRate, hpFreq, hpRes, 1 );
	m_lowShelf.setParameters( sampleRate, lowShelfFreq, lowShelfRes, lowShelfGain );
	m_para1.setParameters( sampleRate, para1Freq, para1Bw, para1Gain );
	m_para2.setParameters( sampleRate, para2Freq, para2Bw, para2Gain );
	m_para3.setParameters( sampleRate, para3Freq, para3Bw, para3Gain );
	m_para4.setParameters( sampleRate, para4Freq, para4Bw, para4Gain );
	m_highShelf.setParameters( sampleRate, highShelfFreq, highShelfRes, highShelfGain );
	m_lp12.setParameters( sampleRate, lpFreq, lpRes, 1 );
	m_lp24.setParameters( sampleRate, lpFreq, lpRes, 1 );
	m_lp480.setParameters( sampleRate, lpFreq, lpRes, 1 );
	m_lp481.setParameters( sampleRate, lpFreq, lpRes, 1 );

	if( !isEnabled() || !isRunning () )
	{
		return( false );
	}

	if( m_eqControls.m_outGainModel.isValueChanged() )
	{
		m_outGain = dbfsToAmp(m_eqControls.m_outGainModel.value());
	}

	if( m_eqControls.m_inGainModel.isValueChanged() )
	{
		m_inGain = dbfsToAmp(m_eqControls.m_inGainModel.value());
	}

	m_eqControls.m_inProgress = true;
	double outSum = 0.0;

	for( fpp_t f = 0; f < frames; ++f )
	{
		outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
	}

	const float outGain =  m_outGain;
	sampleFrame m_inPeak = { 0, 0 };

	if(m_eqControls.m_analyseInModel.value( true ) &&  outSum > 0 && m_eqControls.isViewVisible()  )
	{
		m_eqControls.m_inFftBands.analyze( buf, frames );
	}
	else
	{
		m_eqControls.m_inFftBands.clear();
	}

	gain( buf, frames, m_inGain, &m_inPeak );
	m_eqControls.m_inPeakL = m_eqControls.m_inPeakL < m_inPeak[0] ? m_inPeak[0] : m_eqControls.m_inPeakL;
	m_eqControls.m_inPeakR = m_eqControls.m_inPeakR < m_inPeak[1] ? m_inPeak[1] : m_eqControls.m_inPeakR;

	float periodProgress = 0.0f; // percentage of period processed
	for( fpp_t f = 0; f < frames; ++f)
	{
		periodProgress = (float)f / (float)(frames-1);
		//wet dry buffer
		dryS[0] = buf[f][0];
		dryS[1] = buf[f][1];
		if( hpActive )
		{
			buf[f][0] = m_hp12.update( buf[f][0], 0, periodProgress );
			buf[f][1] = m_hp12.update( buf[f][1], 1, periodProgress );

			if( hp24Active || hp48Active )
			{
				buf[f][0] = m_hp24.update( buf[f][0], 0, periodProgress );
				buf[f][1] = m_hp24.update( buf[f][1], 1, periodProgress );
			}

			if( hp48Active )
			{
				buf[f][0] = m_hp480.update( buf[f][0], 0, periodProgress );
				buf[f][1] = m_hp480.update( buf[f][1], 1, periodProgress );

				buf[f][0] = m_hp481.update( buf[f][0], 0, periodProgress );
				buf[f][1] = m_hp481.update( buf[f][1], 1, periodProgress );
			}
		}

		if( lowShelfActive )
		{
			buf[f][0] = m_lowShelf.update( buf[f][0], 0, periodProgress );
			buf[f][1] = m_lowShelf.update( buf[f][1], 1, periodProgress );
		}

		if( para1Active )
		{
			buf[f][0] = m_para1.update( buf[f][0], 0, periodProgress );
			buf[f][1] = m_para1.update( buf[f][1], 1, periodProgress );
		}

		if( para2Active )
		{
			buf[f][0] = m_para2.update( buf[f][0], 0, periodProgress );
			buf[f][1] = m_para2.update( buf[f][1], 1, periodProgress );
		}

		if( para3Active )
		{
			buf[f][0] = m_para3.update( buf[f][0], 0, periodProgress );
			buf[f][1] = m_para3.update( buf[f][1], 1, periodProgress );
		}

		if( para4Active )
		{
			buf[f][0] = m_para4.update( buf[f][0], 0, periodProgress );
			buf[f][1] = m_para4.update( buf[f][1], 1, periodProgress );
		}

		if( highShelfActive )
		{
			buf[f][0] = m_highShelf.update( buf[f][0], 0, periodProgress );
			buf[f][1] = m_highShelf.update( buf[f][1], 1, periodProgress );
		}

		if( lpActive ){
			buf[f][0] = m_lp12.update( buf[f][0], 0, periodProgress );
			buf[f][1] = m_lp12.update( buf[f][1], 1, periodProgress );

			if( lp24Active || lp48Active )
			{
				buf[f][0] = m_lp24.update( buf[f][0], 0, periodProgress );
				buf[f][1] = m_lp24.update( buf[f][1], 1, periodProgress );
			}

			if( lp48Active )
			{
				buf[f][0] = m_lp480.update( buf[f][0], 0, periodProgress );
				buf[f][1] = m_lp480.update( buf[f][1], 1, periodProgress );

				buf[f][0] = m_lp481.update( buf[f][0], 0, periodProgress );
				buf[f][1] = m_lp481.update( buf[f][1], 1, periodProgress );
			}
		}

		//apply wet / dry levels
		buf[f][1] = ( dry * dryS[1] ) + ( wet * buf[f][1] );
		buf[f][0] = ( dry * dryS[0] ) + ( wet * buf[f][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;

	checkGate( outSum / frames );

	if(m_eqControls.m_analyseOutModel.value( true ) && outSum > 0 && m_eqControls.isViewVisible() )
	{
		m_eqControls.m_outFftBands.analyze( buf, frames );
		setBandPeaks( &m_eqControls.m_outFftBands , ( int )( sampleRate ) );
	}
	else
	{
		m_eqControls.m_outFftBands.clear();
	}

	m_eqControls.m_inProgress = false;
	return isRunning();
}

float EqEffect::peakBand( float minF, float maxF, EqAnalyser *fft, int sr )
{
	float peak = -60;
	float *b = fft->m_bands;
	float h = 0;
	for( int x = 0; x < MAX_BANDS; x++, b++ )
	{
		if( bandToFreq( x ,sr) >= minF && bandToFreq( x,sr ) <= maxF )
		{
			h = 20 * ( log10( *b / fft->getEnergy() ) );
			peak = h > peak ? h : peak;
		}
	}

	return ( peak + 60 ) / 100;
}

void EqEffect::setBandPeaks( EqAnalyser *fft, int samplerate )
{
	m_eqControls.m_lowShelfPeakR = m_eqControls.m_lowShelfPeakL =
			peakBand( m_eqControls.m_lowShelfFreqModel.value()
					  * ( 1 - m_eqControls.m_lowShelfResModel.value() * 0.5 ),
					  m_eqControls.m_lowShelfFreqModel.value(),
					  fft , samplerate );

	m_eqControls.m_para1PeakL = m_eqControls.m_para1PeakR =
			peakBand( m_eqControls.m_para1FreqModel.value()
					  * ( 1 - m_eqControls.m_para1BwModel.value() * 0.5 ),
					  m_eqControls.m_para1FreqModel.value()
					  * ( 1 + m_eqControls.m_para1BwModel.value() * 0.5 ),
					  fft , samplerate );

	m_eqControls.m_para2PeakL = m_eqControls.m_para2PeakR =
			peakBand( m_eqControls.m_para2FreqModel.value()
					  * ( 1 - m_eqControls.m_para2BwModel.value() * 0.5 ),
					  m_eqControls.m_para2FreqModel.value()
					  * ( 1 + m_eqControls.m_para2BwModel.value() * 0.5 ),
					  fft , samplerate );

	m_eqControls.m_para3PeakL = m_eqControls.m_para3PeakR =
			peakBand( m_eqControls.m_para3FreqModel.value()
					  * ( 1 - m_eqControls.m_para3BwModel.value() * 0.5 ),
					  m_eqControls.m_para3FreqModel.value()
					  * ( 1 + m_eqControls.m_para3BwModel.value() * 0.5 ),
					  fft , samplerate );

	m_eqControls.m_para4PeakL = m_eqControls.m_para4PeakR =
			peakBand( m_eqControls.m_para4FreqModel.value()
					  * ( 1 - m_eqControls.m_para4BwModel.value() * 0.5 ),
					  m_eqControls.m_para4FreqModel.value()
					  * ( 1 + m_eqControls.m_para4BwModel.value() * 0.5 ),
					  fft , samplerate );

	m_eqControls.m_highShelfPeakL = m_eqControls.m_highShelfPeakR =
			peakBand( m_eqControls.m_highShelfFreqModel.value(),
					  m_eqControls.m_highShelfFreqModel.value()
					  * ( 1 + m_eqControls.m_highShelfResModel.value() * 0.5 ),
					  fft, samplerate );
}

extern "C"
{

//needed for getting plugin out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* parent, void* data )
{
	return new EqEffect( parent , static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>( data ) );
}

}


code:
/* eqeffect.h - defination of EqEffect class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 EQEFFECT_H
#define EQEFFECT_H

#include "BasicFilters.h"
#include "Effect.h"
#include "EqControls.h"
#include "EqFilter.h"
#include "lmms_math.h"

class EqEffect : public Effect
{
public:
	EqEffect( Model * parent , const Descriptor::SubPluginFeatures::Key * key );
	virtual ~EqEffect();
	virtual bool processAudioBuffer( sampleFrame * buf, const fpp_t frames );
	virtual EffectControls * controls()
	{
		return &m_eqControls;
	}
	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 )
		{
			buf[f][0] *= scale;
			buf[f][1] *= scale;

			if( fabs( buf[f][0] ) > peak[0][0] )
			{
				peak[0][0] = fabs( buf[f][0] );
			}
			if( fabs( buf[f][1] ) > peak[0][1] )
			{
				peak[0][1] = fabs( buf[f][0] );
			}

		}
	}

private:
	EqControls m_eqControls;

	EqHp12Filter m_hp12;
	EqHp12Filter m_hp24;
	EqHp12Filter m_hp480;
	EqHp12Filter m_hp481;

	EqLowShelfFilter m_lowShelf;

	EqPeakFilter m_para1;
	EqPeakFilter m_para2;
	EqPeakFilter m_para3;
	EqPeakFilter m_para4;

	EqHighShelfFilter m_highShelf;

	EqLp12Filter m_lp12;
	EqLp12Filter m_lp24;
	EqLp12Filter m_lp480;
	EqLp12Filter m_lp481;

	float m_inGain;
	float m_outGain;

	float peakBand( float minF, float maxF, EqAnalyser *, int );

	inline float bandToFreq ( int index , int sampleRate )
	{
		return index * sampleRate / ( MAX_BANDS * 2 );
	}

	void setBandPeaks( EqAnalyser * fft , int );
};

#endif // EQEFFECT_H


code:
/* eqfader.h - defination of EqFader class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 EQFADER_H
#define EQFADER_H
#include <QList>
#include <QWidget>

#include "EffectControls.h"
#include "Fader.h"
#include "GuiApplication.h"
#include "MainWindow.h"
#include "TextFloat.h"

class EqFader : public Fader
{

public:
	Q_OBJECT
public:
	EqFader( FloatModel * model, const QString & name, QWidget * parent, QPixmap * backg, QPixmap * leds, QPixmap * knobpi,  float* lPeak, float* rPeak ) :
		Fader( model, name, parent, backg, leds, knobpi )
	{
		setMinimumSize( 23, 80 );
		setMaximumSize( 23, 80 );
		resize( 23, 80 );
		m_lPeak = lPeak;
		m_rPeak = rPeak;
		connect( gui->mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( updateVuMeters() ) );
		m_model = model;
		setPeak_L( 0 );
		setPeak_R( 0 );
	}

	EqFader( FloatModel * model, const QString & name, QWidget * parent,  float* lPeak, float* rPeak ) :
		Fader( model, name, parent )
	{
		setMinimumSize( 23, 116 );
		setMaximumSize( 23, 116 );
		resize( 23, 116 );
		m_lPeak = lPeak;
		m_rPeak = rPeak;
		connect( gui->mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( updateVuMeters() ) );
		m_model = model;
		setPeak_L( 0 );
		setPeak_R( 0 );
	}

	~EqFader()
	{
	}

private slots:

	void updateVuMeters()
	{
		const float opl = getPeak_L();
		const float opr = getPeak_R();
		const float fallOff = 1.07;
		if( *m_lPeak > opl )
		{
			setPeak_L( *m_lPeak );
			*m_lPeak = 0;
		}
		else
		{
			setPeak_L( opl/fallOff );
		}

		if( *m_rPeak > opr )
		{
			setPeak_R( *m_rPeak );
			*m_rPeak = 0;
		}
		else
		{
			setPeak_R( opr/fallOff );
		}
		update();
	}

private:
	float* m_lPeak;
	float* m_rPeak;
	FloatModel* m_model;

};
#endif // EQFADER_H


code:
/*
 * eqfilter.cpp - defination of EqFilterclass.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 EQFILTER_H
#define EQFILTER_H

#include "BasicFilters.h"
#include "lmms_math.h"

///
/// \brief The EqFilter class.
/// A wrapper for the StereoBiQuad class, giving it freq, res, and gain controls.
/// Used on a per channel per frame basis with recalculation of coefficents
/// upon parameter changes. The intention is to use this as a bass class, children override
/// the calcCoefficents() function, providing the coefficents a1, a2, b0, b1, b2.
///
class EqFilter
{
public:
	EqFilter() :
		m_sampleRate(0),
		m_freq(0),
		m_res(0),
		m_gain(0),
		m_bw(0)
	{

	}

	virtual inline void setSampleRate( int sampleRate )
	{
		if( sampleRate != m_sampleRate )
		{
			m_sampleRate = sampleRate;
			calcCoefficents();
		}
	}

	virtual inline void setFrequency( float freq ){
		if ( freq != m_freq )
		{
			m_freq = freq;
			calcCoefficents();
		}
	}

	virtual inline void setQ( float res )
	{
		if ( res != m_res )
		{
			m_res = res;
			calcCoefficents();
		}
	}

	virtual inline void setGain( float gain )
	{
		if ( gain != m_gain )
		{
			m_gain = gain;
			calcCoefficents();
		}
	}

	virtual inline void setParameters( float sampleRate, float freq, float res, float gain )
	{
		bool hasChanged = ( sampleRate != m_sampleRate ||
		                    freq != m_freq ||
		                    res != m_res ||
		                    gain != m_gain );
		if ( hasChanged )
		{
			m_sampleRate = sampleRate;
			m_freq = freq;
			m_res = res;
			m_gain = gain;
			calcCoefficents();
		}
	}

	///
	/// \brief update
	/// filters using two BiQuads, then crossfades,
	///  depending on on percentage of period processes
	/// \param in
	/// \param ch
	/// \param frameProgress percentage of frame processed
	/// \return
	///
	inline float update( float in, ch_cnt_t ch, float frameProgress)
	{
		float initailF =  m_biQuadFrameInitial.update( in, ch );
		float targetF = m_biQuadFrameTarget.update( in, ch );

		if(frameProgress > 0.99999 )
		{
			m_biQuadFrameInitial= m_biQuadFrameTarget;
		}

		return (1.0f-frameProgress) * initailF + frameProgress * targetF;

	}

protected:
	///
	/// \brief calcCoefficents
	///  Override this in child classes to provide the coefficents, based on
	///  Freq, Res and Gain
	virtual void calcCoefficents(){
		setCoeffs( 0, 0, 0, 0, 0 );

	}

	inline void setCoeffs( float a1, float a2, float b0, float b1, float b2 )
	{
		m_biQuadFrameTarget.setCoeffs( a1, a2, b0, b1, b2 );
	}

	float m_sampleRate;
	float m_freq;
	float m_res;
	float m_gain;
	float m_bw;
	StereoBiQuad m_biQuadFrameInitial;
	StereoBiQuad m_biQuadFrameTarget;
};

///
/// \brief The EqHp12Filter class
/// A 2 pole High Pass Filter
/// Coefficent calculations from http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
class EqHp12Filter : public EqFilter
{
public :
	virtual void calcCoefficents()
	{

		// calc intermediate
		float w0 = F_2PI * m_freq / m_sampleRate;
		float c = cosf( w0 );
		float s = sinf( w0 );
		float alpha = s / ( 2 * m_res );

		float a0, a1, a2, b0, b1, b2; // coeffs to calculate

		//calc coefficents
		b0 = ( 1 + c ) * 0.5;
		b1 = ( -( 1 + c ) );
		b2 = ( 1 + c ) * 0.5;
		a0 = 1 + alpha;
		a1 = ( -2 * c );
		a2 = 1 - alpha;

		//normalise
		b0 /= a0;
		b1 /= a0;
		b2 /= a0;
		a1 /= a0;
		a2 /= a0;

		a0 = 1;

		setCoeffs( a1, a2, b0, b1, b2 );

	}
};

///
/// \brief The EqLp12Filter class.
/// A 2 pole low pass filter
/// Coefficent calculations from http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
///
class EqLp12Filter : public EqFilter
{
public :
	virtual void calcCoefficents()
	{

		// calc intermediate
		float w0 = F_2PI * m_freq / m_sampleRate;
		float c = cosf( w0 );
		float s = sinf( w0 );
		float alpha = s / ( 2 * m_res );

		float a0, a1, a2, b0, b1, b2; // coeffs to calculate

		//calc coefficents
		b0 = ( 1 - c ) * 0.5;
		b1 = 1 - c;
		b2 = ( 1 - c ) * 0.5;
		a0 = 1 + alpha;
		a1 = -2 * c;
		a2 = 1 - alpha;

		//normalise
		b0 /= a0;
		b1 /= a0;
		b2 /= a0;
		a1 /= a0;
		a2 /= a0;

		a0 = 1;

		setCoeffs( a1, a2, b0, b1, b2 );
	}
};

///
/// \brief The EqPeakFilter class
/// A Peak Filter
/// Coefficent calculations from http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
///
class EqPeakFilter : public EqFilter
{
public:

	virtual void calcCoefficents()
	{
		// calc intermediate
		float w0 = F_2PI * m_freq / m_sampleRate;
		float c = cosf( w0 );
		float s = sinf( w0 );
		float A =  pow( 10, m_gain * 0.025);
		float alpha = s * sinh( log( 2 ) / 2 * m_bw * w0 / sinf(w0) );

		float a0, a1, a2, b0, b1, b2; // coeffs to calculate

		//calc coefficents
		b0 =   1 + alpha*A;
		b1 =  -2*c;
		b2 =   1 - alpha*A;
		a0 =   1 + alpha/A;
		a1 =  -2*c;
		a2 =   1 - alpha/A;

		//normalise
		b0 /= a0;
		b1 /= a0;
		b2 /= a0;
		a1 /= a0;
		a2 /= a0;
		a0 = 1;

		setCoeffs( a1, a2, b0, b1, b2 );
	}

	virtual inline void setParameters( float sampleRate, float freq, float bw, float gain )
	{
		bool hasChanged = false;
		if( sampleRate != m_sampleRate )
		{
			m_sampleRate = sampleRate;
			hasChanged = true;
		}
		if ( freq != m_freq )
		{
			m_freq = freq;
			hasChanged = true;
		}
		if ( bw != m_bw )
		{
			m_bw = bw;
			hasChanged = true;
		}
		if ( gain != m_gain )
		{
			m_gain = gain;
			hasChanged = true;
		}

		if ( hasChanged ) { calcCoefficents(); }
	}
};

class EqLowShelfFilter : public EqFilter
{
public :
	virtual void calcCoefficents()
	{

		// calc intermediate
		float w0 = F_2PI * m_freq / m_sampleRate;
		float c = cosf( w0 );
		float s = sinf( w0 );
		float A =  pow( 10, m_gain * 0.025);
		//        float alpha = s / ( 2 * m_res );
		float beta = sqrt( A ) / m_res;

		float a0, a1, a2, b0, b1, b2; // coeffs to calculate

		//calc coefficents
		b0 = A * ( ( A+1 ) - ( A-1 ) * c + beta * s );
		b1 = 2  * A * ( ( A - 1 ) - ( A + 1 ) * c) ;
		b2 = A * ( ( A + 1 ) - ( A - 1 ) * c - beta * s);
		a0 = ( A + 1 ) + ( A - 1 ) * c + beta * s;
		a1 = -2 * ( ( A - 1 ) + ( A + 1 ) * c );
		a2 = ( A + 1 ) + ( A - 1) * c - beta * s;

		//normalise
		b0 /= a0;
		b1 /= a0;
		b2 /= a0;
		a1 /= a0;
		a2 /= a0;

		a0 = 1;

		setCoeffs( a1, a2, b0, b1, b2 );

	}
};

class EqHighShelfFilter : public EqFilter
{
public :
	virtual void calcCoefficents()
	{

		// calc intermediate
		float w0 = F_2PI * m_freq / m_sampleRate;
		float c = cosf( w0 );
		float s = sinf( w0 );
		float A =  pow( 10, m_gain * 0.025 );
		float beta = sqrt( A ) / m_res;

		float a0, a1, a2, b0, b1, b2; // coeffs to calculate

		//calc coefficents
		b0 = A *( ( A +1 ) + ( A - 1 ) * c + beta * s);
		b1 = -2 * A * ( ( A - 1 ) + ( A + 1 ) * c );
		b2 = A * ( ( A + 1 ) + ( A - 1 ) * c - beta * s);
		a0 = ( A + 1 ) - ( A - 1 ) * c + beta * s;
		a1 = 2 * ( ( A - 1 ) - ( A + 1 ) * c );
		a2 = ( A + 1) - ( A - 1 ) * c - beta * s;
		//normalise
		b0 /= a0;
		b1 /= a0;
		b2 /= a0;
		a1 /= a0;
		a2 /= a0;
		a0 = 1;

		setCoeffs( a1, a2, b0, b1, b2 );
	}
};

class EqLinkwitzRiley : public StereoLinkwitzRiley
{
public:
	EqLinkwitzRiley() :
		StereoLinkwitzRiley( 44100),
		m_freq(0 ),
		m_sr( 1 )
	{
	}

	virtual inline void setSR( int sampleRate )
	{
		if( sampleRate != m_sr )
		{
			m_sr = sampleRate;
			setSampleRate( sampleRate );
			setLowpass(m_freq);
		}
	}

	virtual inline void setFrequency( float freq ){
		if ( freq != m_freq )
		{
			m_freq = freq;
			setLowpass(m_freq);
		}
	}

	virtual void processBuffer( sampleFrame* buf, const fpp_t frames )
	{
		for ( fpp_t f = 0 ; f < frames ; ++f)
		{
			buf[f][0] = update( buf[f][0] , 0);
			buf[f][1] = update( buf[f][1] , 1);
		}
	}
protected:

	float m_freq;
	int m_sr;

};

#endif // EQFILTER_H


code:
/*
 * eqparameterwidget.cpp - defination of EqParameterWidget class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
 * Copyright (c) 2015 Steffen Baranowsky <BaraMGB/at/freenet/dot/de>
 *
 * 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 "EqParameterWidget.h"

#include <QGraphicsScene>
#include <QGraphicsView>
#include <QMouseEvent>
#include <QWidget>

#include "EqControls.h"
#include "lmms_math.h"

EqParameterWidget::EqParameterWidget( QWidget *parent, EqControls * controls ) :
	QWidget( parent ),
	m_displayWidth ( 450 ),
	m_displayHeigth ( 200 ),
	m_controls ( controls )

{
	m_bands = new EqBand[8];
	resize( m_displayWidth, m_displayHeigth );
	float totalHeight = 36; // gain range from -18 to +18
	m_pixelsPerUnitHeight = m_displayHeigth / totalHeight;
	m_pixelsPerOctave = EqHandle::freqToXPixel( 10000, m_displayWidth ) - EqHandle::freqToXPixel( 5000, m_displayWidth );

	//GraphicsScene and GraphicsView stuff
	QGraphicsScene *scene = new QGraphicsScene();
	scene->setSceneRect( 0, 0, m_displayWidth, m_displayHeigth );
	QGraphicsView *view = new QGraphicsView( this );
	view->setStyleSheet( "border-style: none; background: transparent;" );
	view->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
	view->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
	view->setScene( scene );

	//adds the handles
	m_handleList = new QList<EqHandle*>;
	for ( int i = 0; i < bandCount(); i++ )
	{
		m_handle = new EqHandle ( i, m_displayWidth, m_displayHeigth );
		m_handleList->append( m_handle );
		m_handle->setZValue( 1 );
		scene->addItem( m_handle );
	}

	//adds the curve widget
	m_eqcurve = new EqCurve( m_handleList, m_displayWidth, m_displayHeigth );
	scene->addItem( m_eqcurve );
	for ( int i = 0; i < bandCount(); i++ )
	{
		// if the data of handle position has changed update the models
		QObject::connect( m_handleList->at( i ) ,SIGNAL( positionChanged() ), this ,SLOT( updateModels() ) );
	}
}

EqParameterWidget::~EqParameterWidget()
{
	if( m_bands )
	{
		delete[] m_bands;
		m_bands = 0;
	}
}

EqBand *EqParameterWidget::getBandModels( int i )
{
	return &m_bands[i];
}

void EqParameterWidget::updateHandle()
{
	m_eqcurve->setModelChanged( true );
	for( int i = 0 ; i < bandCount(); i++ )
	{
		if ( !m_handleList->at( i )->mousePressed() ) //prevents a short circuit between handle and data model
		{
			//sets the band on active if a fader or a knob is moved
			bool hover = false; // prevents an action if handle is moved
			for ( int j = 0; j < bandCount(); j++ )
			{
				if ( m_handleList->at(j)->isMouseHover() )
				{
					hover = true;
				}
			}
			if ( !hover )
			{
				if ( sender() == m_bands[i].gain ) m_bands[i].active->setValue( true );
				if ( sender() == m_bands[i].freq ) m_bands[i].active->setValue( true );
				if ( sender() == m_bands[i].res ) m_bands[i].active->setValue( true );
			}
			changeHandle( i );
		}
		else
		{
			m_handleList->at( i )->setHandleActive( m_bands[i].active->value() );
		}
	}
	if ( m_bands[0].hp12->value() ) m_handleList->at( 0 )->sethp12();
	if ( m_bands[0].hp24->value() ) m_handleList->at( 0 )->sethp24();
	if ( m_bands[0].hp48->value() ) m_handleList->at( 0 )->sethp48();
	if ( m_bands[7].lp12->value() ) m_handleList->at( 7 )->setlp12();
	if ( m_bands[7].lp24->value() ) m_handleList->at( 7 )->setlp24();
	if ( m_bands[7].lp48->value() ) m_handleList->at( 7 )->setlp48();
}

void EqParameterWidget::changeHandle( int i )
{
	//fill x, y, and bw with data from model
	float x = EqHandle::freqToXPixel( m_bands[i].freq->value(), m_displayWidth );
	float y = m_handleList->at( i )->y();
	//for pass filters there is no gain model
	if( m_bands[i].gain )
	{
		float gain = m_bands[i].gain->value();
		y = EqHandle::gainToYPixel( gain, m_displayHeigth, m_pixelsPerUnitHeight );
	}
	float bw = m_bands[i].res->value();

	// set the handle position, filter type for each handle
	switch ( i )
	{
	case 0 :
		m_handleList->at( i )->setType( highpass );
		m_handleList->at( i )->setPos( x, m_displayHeigth / 2 );
		break;
	case 1:
		m_handleList->at( i )->setType( lowshelf );
		m_handleList->at( i )->setPos( x, y );
		break;
	case 2:
		m_handleList->at( i )->setType( para );
		m_handleList->at( i )->setPos( x, y );
		break;
	case 3:
		m_handleList->at( i )->setType( para );
		m_handleList->at( i )->setPos( x, y );
		break;
	case 4:
		m_handleList->at( i )->setType( para );
		m_handleList->at( i )->setPos( x, y );
		break;
	case 5:
		m_handleList->at( i )->setType( para );
		m_handleList->at( i )->setPos( x, y );
		break;
	case 6:
		m_handleList->at( i )->setType( highshelf );
		m_handleList->at( i )->setPos( x, y );
		break;
	case 7:
		m_handleList->at( i )->setType( lowpass );
		m_handleList->at( i )->setPos( QPointF( x, m_displayHeigth / 2 ) );
		break;
	}

	// set resonance/bandwidth for each handle
	if ( m_handleList->at( i )->getResonance() != bw )
	{
		m_handleList->at( i )->setResonance( bw );
	}

	// and the active status
	m_handleList->at( i )->setHandleActive( m_bands[i].active->value() );
	m_handleList->at( i )->update();
	m_eqcurve->update();
}

//this is called if a handle is moved
void EqParameterWidget::updateModels()
{
	for ( int i=0 ; i < bandCount(); i++ )
	{
		m_bands[i].freq->setValue( EqHandle::xPixelToFreq( m_handleList->at( i )->x(), m_displayWidth ) );

		if( m_bands[i].gain )
		{
			m_bands[i].gain->setValue( EqHandle::yPixelToGain( m_handleList->at(i)->y(), m_displayHeigth, m_pixelsPerUnitHeight ) );
		}

		m_bands[i].res->setValue( m_handleList->at( i )->getResonance() );
		//identifies the handle which is moved and set the band active
		if ( sender() == m_handleList->at( i ) )
		{
			m_bands[i].active->setValue( true );
		}
	}
	m_eqcurve->update();
}

EqBand::EqBand() :
	gain ( 0 ),
	res ( 0 ),
	freq ( 0 ),
	color ( QColor( 255, 255, 255 ) ),
	x( 0 ),
	y( 0 ),
	name ( QString( "" ) ),
	peakL( 0 ),
	peakR( 0 )
{
}


code:
/*
 * eqparameterwidget.cpp - defination of EqParameterWidget class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
* Copyright (c) 2015 Steffen Baranowsky <BaraMGB/at/freenet/dot/de>
 *
 * 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 EQPARAMETERWIDGET_H
#define EQPARAMETERWIDGET_H

#include <QWidget>

#include "EffectControls.h"
#include "EqCurve.h"
#include "TextFloat.h"

class EqControls;

class EqBand
{
public :
	EqBand();
	FloatModel *gain;
	FloatModel *res;
	FloatModel *freq;
	BoolModel *active;
	BoolModel *hp12;
	BoolModel *hp24;
	BoolModel *hp48;
	BoolModel *lp12;
	BoolModel *lp24;
	BoolModel *lp48;
	QColor color;
	int x;
	int y;
	QString name;
	float *peakL;
	float *peakR;
};

class EqParameterWidget : public QWidget
{
	Q_OBJECT
public:
	explicit EqParameterWidget( QWidget *parent = 0, EqControls * controls = 0 );
	~EqParameterWidget();
	QList<EqHandle*> *m_handleList;

	const int bandCount()
	{
		return 8;
	}

	EqBand* getBandModels( int i );
	void changeHandle( int i );

private:
	float m_pixelsPerUnitWidth;
	float m_pixelsPerUnitHeight;
	float m_pixelsPerOctave;
	float m_scale;
	int m_displayWidth, m_displayHeigth;
	EqControls *m_controls;
	EqBand *m_bands;
	EqHandle *m_handle;
	EqCurve *m_eqcurve;

private slots:
	void updateModels();
	void updateHandle();
};
#endif // EQPARAMETERWIDGET_H


code:
/* eqspectrumview.cpp - implementation of EqSpectrumView class.
*
* Copyright (c) 2014-2017, David French <dave/dot/french3/at/googlemail/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 "EqSpectrumView.h"

#include "Engine.h"
#include "EqCurve.h"
#include "GuiApplication.h"
#include "MainWindow.h"
#include "Mixer.h"

EqAnalyser::EqAnalyser() :
	m_framesFilledUp ( 0 ),
	m_energy ( 0 ),
	m_sampleRate ( 1 ),
	m_active ( true )
{
	m_inProgress=false;
	m_specBuf = ( fftwf_complex * ) fftwf_malloc( ( FFT_BUFFER_SIZE + 1 ) * sizeof( fftwf_complex ) );
	m_fftPlan = fftwf_plan_dft_r2c_1d( FFT_BUFFER_SIZE*2, m_buffer, m_specBuf, FFTW_MEASURE );

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

	for (int i = 0; i < FFT_BUFFER_SIZE; i++)
	{
		m_fftWindow[i] = (a0 - a1 * cos(2 * F_PI * i / ((float)FFT_BUFFER_SIZE - 1.0))
								+ a2 * cos(4 * F_PI * i / ((float)FFT_BUFFER_SIZE - 1.0))
								- a3 * cos(6 * F_PI * i / ((float)FFT_BUFFER_SIZE - 1.0)));
	}
	clear();
}

EqAnalyser::~EqAnalyser()
{
	fftwf_destroy_plan( m_fftPlan );
	fftwf_free( m_specBuf );
}

void EqAnalyser::analyze( sampleFrame *buf, const fpp_t frames )
{
	//only analyse if the view is visible
	if ( m_active )
	{
		m_inProgress=true;
		const int FFT_BUFFER_SIZE = 2048;
		fpp_t f = 0;
		if( frames > FFT_BUFFER_SIZE )
		{
			m_framesFilledUp = 0;
			f = frames - FFT_BUFFER_SIZE;
		}
		// meger channels
		for( ; f < frames; ++f )
		{
			m_buffer[m_framesFilledUp] =
					( buf[f][0] + buf[f][1] ) * 0.5;
			++m_framesFilledUp;
		}

		if( m_framesFilledUp < FFT_BUFFER_SIZE )
		{
			m_inProgress = false;
			return;
		}

		m_sampleRate = Engine::mixer()->processingSampleRate();
		const int LOWEST_FREQ = 0;
		const int HIGHEST_FREQ = m_sampleRate / 2;

		//apply FFT window
		for( int i = 0; i < FFT_BUFFER_SIZE; i++ )
		{
			m_buffer[i] = m_buffer[i] * m_fftWindow[i];
		}

		fftwf_execute( m_fftPlan );
		absspec( m_specBuf, m_absSpecBuf, FFT_BUFFER_SIZE+1 );

		compressbands( m_absSpecBuf, m_bands, FFT_BUFFER_SIZE+1,
					   MAX_BANDS,
					   ( int )( LOWEST_FREQ * ( FFT_BUFFER_SIZE + 1 ) / ( float )( m_sampleRate / 2 ) ),
					   ( int )( HIGHEST_FREQ * ( FFT_BUFFER_SIZE +  1) / ( float )( m_sampleRate / 2 ) ) );
		m_energy = maximum( m_bands, MAX_BANDS ) / maximum( m_buffer, FFT_BUFFER_SIZE );

		m_framesFilledUp = 0;
		m_inProgress = false;
		m_active = false;
	}
}

float EqAnalyser::getEnergy() const
{
	return m_energy;
}

int EqAnalyser::getSampleRate() const
{
	return m_sampleRate;
}

bool EqAnalyser::getActive() const
{
	return m_active;
}

void EqAnalyser::setActive(bool active)
{
	m_active = active;
}

bool EqAnalyser::getInProgress()
{
	return m_inProgress;
}

void EqAnalyser::clear()
{
	m_framesFilledUp = 0;
	m_energy = 0;
	memset( m_buffer, 0, sizeof( m_buffer ) );
	memset( m_bands, 0, sizeof( m_bands ) );
}

EqSpectrumView::EqSpectrumView(EqAnalyser *b, QWidget *_parent) :
	QWidget( _parent ),
	m_analyser( b ),
	m_periodicalUpdate( false )
{
	setFixedSize( 450, 200 );
	connect( gui->mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( periodicalUpdate() ) );
	setAttribute( Qt::WA_TranslucentBackground, true );
	m_skipBands = MAX_BANDS * 0.5;
	float totalLength = log10( 20000 );
	m_pixelsPerUnitWidth = width( ) / totalLength ;
	m_scale = 1.5;
	m_color = QColor( 255, 255, 255, 255 );
	for ( int i = 0 ; i < MAX_BANDS ; i++ )
	{
		m_bandHeight.append( 0 );
	}
}

void EqSpectrumView::paintEvent(QPaintEvent *event)
{
	const float energy =  m_analyser->getEnergy();
	if( energy <= 0 && m_peakSum <= 0 )
	{
		//dont draw anything
		return;
	}

	const int fh = height();
	const int LOWER_Y = -36;	// dB
	QPainter painter( this );
	painter.setPen( QPen( m_color, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) );
	painter.setRenderHint(QPainter::Antialiasing, true);

	if( m_analyser->getInProgress() || m_periodicalUpdate == false )
	{
		//only paint the cached path
		painter.fillPath( m_path, QBrush( m_color ) );
		return;
	}

	m_periodicalUpdate = false;
	//Now we calculate the path
	m_path = QPainterPath();
	float *bands = m_analyser->m_bands;
	float peak;
	m_path.moveTo( 0, height() );
	m_peakSum = 0;
	const float fallOff = 1.07;
	for( int x = 0; x < MAX_BANDS; ++x, ++bands )
	{
		peak = ( fh * 2.0 / 3.0 * ( 20 * ( log10( *bands / energy ) ) - LOWER_Y ) / ( - LOWER_Y ) );
		if( peak < 0 )
		{
			peak = 0;
		}
		else if( peak >= fh )
		{
			continue;
		}

		if ( peak > m_bandHeight[x] )
		{
			m_bandHeight[x] = peak;
		}
		else
		{
			m_bandHeight[x] = m_bandHeight[x] / fallOff;
		}

		if( m_bandHeight[x] < 0 )
		{
			m_bandHeight[x] = 0;
		}

		m_path.lineTo( EqHandle::freqToXPixel( bandToFreq( x ), width() ), fh - m_bandHeight[x] );
		m_peakSum += m_bandHeight[x];
	}

	m_path.lineTo( width(), height() );
	m_path.closeSubpath();
	painter.fillPath( m_path, QBrush( m_color ) );
	painter.drawPath( m_path );
}

QColor EqSpectrumView::getColor() const
{
	return m_color;
}

void EqSpectrumView::setColor( const QColor &value )
{
	m_color = value;
}

float EqSpectrumView::bandToFreq( int index )
{
	return index * m_analyser->getSampleRate() / ( MAX_BANDS * 2 );
}

void EqSpectrumView::periodicalUpdate()
{
	m_periodicalUpdate = true;
	m_analyser->setActive( isVisible() );
	update();
}


code:
/* eqspectrumview.h - defination of EqSpectrumView class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 EQSPECTRUMVIEW_H
#define EQSPECTRUMVIEW_H

#include <QPainter>
#include <QPainterPath>
#include <QWidget>

#include "fft_helpers.h"
#include "lmms_basics.h"
#include "lmms_math.h"

const int MAX_BANDS = 2048;
class EqAnalyser
{
public:
	EqAnalyser();
	virtual ~EqAnalyser();

	float m_bands[MAX_BANDS];
	bool getInProgress();
	void clear();

	void analyze( sampleFrame *buf, const fpp_t frames );

	float getEnergy() const;
	int getSampleRate() const;
	bool getActive() const;

	void setActive(bool active);

private:
	fftwf_plan m_fftPlan;
	fftwf_complex * m_specBuf;
	float m_absSpecBuf[FFT_BUFFER_SIZE+1];
	float m_buffer[FFT_BUFFER_SIZE*2];
	int m_framesFilledUp;
	float m_energy;
	int m_sampleRate;
	bool m_active;
	bool m_inProgress;
	float m_fftWindow[FFT_BUFFER_SIZE];
};

class EqSpectrumView : public QWidget
{
	Q_OBJECT
public:
	explicit EqSpectrumView( EqAnalyser *b, QWidget *_parent = 0 );
	virtual ~EqSpectrumView()
	{
	}

	QColor getColor() const;
	void setColor( const QColor &value );

protected:
	virtual void paintEvent( QPaintEvent *event );

private slots:
	void periodicalUpdate();

private:
	QColor m_color;
	EqAnalyser *m_analyser;
	QPainterPath m_path;
	float m_peakSum;
	float m_pixelsPerUnitWidth;
	float m_scale;
	int m_skipBands;
	bool m_periodicalUpdate;
	QList<float> m_bandHeight;

	float bandToFreq ( int index );
};
#endif // EQSPECTRUMVIEW_H


code:
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)


code:
/*
 * flangercontrols.cpp - defination of FlangerControls class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 <QtXml/QDomElement>

#include "FlangerControls.h"
#include "FlangerEffect.h"
#include "Engine.h"
#include "Song.h"

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

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

void FlangerControls::loadSettings( const QDomElement &_this )
{
	m_delayTimeModel.loadSettings( _this, "DelayTimeSamples" );
	m_lfoFrequencyModel.loadSettings( _this, "LfoFrequency" );
	m_lfoAmountModel.loadSettings( _this, "LfoAmount" );
	m_feedbackModel.loadSettings( _this, "Feedback" );
	m_whiteNoiseAmountModel.loadSettings( _this, "WhiteNoise" );
	m_invertFeedbackModel.loadSettings( _this, "Invert" );

}

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_feedbackModel.saveSettings( doc, parent, "Feedback" ) ;
	m_whiteNoiseAmountModel.saveSettings( doc, parent , "WhiteNoise" ) ;
	m_invertFeedbackModel.saveSettings( doc, parent, "Invert" );
}

void FlangerControls::changedSampleRate()
{
	m_effect->changeSampleRate();
}

void FlangerControls::changedPlaybackState()
{
	m_effect->restartLFO();
}


code:
/*
 * flangercontrols.h - defination of StereoDelay class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 FLANGERCONTROLS_H
#define FLANGERCONTROLS_H

#include "EffectControls.h"
#include "Knob.h"
#include "FlangerControlsDialog.h"

class FlangerEffect;

class FlangerControls : public EffectControls
{
	Q_OBJECT
public:
	FlangerControls( FlangerEffect* effect );
	virtual ~FlangerControls()
	{
	}
	virtual void saveSettings ( QDomDocument& doc, QDomElement& parent );
	virtual void loadSettings ( const QDomElement &_this );
	inline virtual QString nodeName() const
	{
		return "Flanger";
	}
	virtual int controlCount()
	{
		return 5;
	}
	virtual EffectControlDialog* createView()
	{
		return new FlangerControlsDialog( this );
	}

private slots:
	void changedSampleRate();
	void changedPlaybackState();

private:
	FlangerEffect* m_effect;
	FloatModel m_delayTimeModel;
	TempoSyncKnobModel m_lfoFrequencyModel;
	FloatModel m_lfoAmountModel;
	FloatModel m_feedbackModel;
	FloatModel m_whiteNoiseAmountModel;
	BoolModel m_invertFeedbackModel;

	friend class FlangerControlsDialog;
	friend class FlangerEffect;

};

#endif // FLANGERCONTROLS_H


code:
/*
 * flangercontrolsdialog.cpp - defination of FlangerControlsDialog class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 "FlangerControlsDialog.h"
#include "FlangerControls.h"
#include "embed.h"
#include "LedCheckbox.h"
#include "TempoSyncKnob.h"

FlangerControlsDialog::FlangerControlsDialog( FlangerControls *controls ) :
	EffectControlDialog( controls )
{
	setAutoFillBackground( true );
	QPalette pal;
	pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
	setPalette( pal );
	setFixedSize( 195, 75 );

	Knob* delayKnob = new Knob( knobBright_26, this );
	delayKnob->move( 10,10 );
	delayKnob->setVolumeKnob( false );
	delayKnob->setModel( &controls->m_delayTimeModel );
	delayKnob->setLabel( tr( "DELAY" ) );
	delayKnob->setHintText( tr( "Delay time:" ) + " ", "s" );

	TempoSyncKnob * lfoFreqKnob = new TempoSyncKnob( knobBright_26, this );
	lfoFreqKnob->move( 48,10 );
	lfoFreqKnob->setVolumeKnob( false );
	lfoFreqKnob->setModel( &controls->m_lfoFrequencyModel );
	lfoFreqKnob->setLabel( tr( "RATE" ) );
	lfoFreqKnob->setHintText( tr( "Period:" ) , " Sec" );

	Knob * lfoAmtKnob = new Knob( knobBright_26, this );
	lfoAmtKnob->move( 85,10 );
	lfoAmtKnob->setVolumeKnob( false );
	lfoAmtKnob->setModel( &controls->m_lfoAmountModel );
	lfoAmtKnob->setLabel( tr( "AMNT" ) );
	lfoAmtKnob->setHintText( tr( "Amount:" ) , "" );

	Knob * feedbackKnob = new Knob( knobBright_26, this );
	feedbackKnob->move( 122,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->setVolumeKnob( true) ;
	whiteNoiseKnob->setModel( &controls->m_whiteNoiseAmountModel );
	whiteNoiseKnob->setLabel( tr( "NOISE" ) );
	whiteNoiseKnob->setHintText( tr( "White noise amount:" ) , "" );

	LedCheckBox * invertCb = new LedCheckBox( tr( "Invert" ), this );
	invertCb->move( 10,53 );

}


code:
/*
 * flangercontrolsdialog.h - defination of FlangerControlsDialog class.
 *
 * Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/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 FLANGERCONTROLSDIALOG_H
#define FLANGERCONTROLSDIALOG_H

#include "EffectControlDialog.h"

class FlangerControls;

class FlangerControlsDialog : public EffectControlDialog
{
	Q_OBJECT
public:
	FlangerControlsDialog( FlangerControls* controls );
	virtual ~FlangerControlsDialog()
	{
	}
};

#endif // FLANGERCONTROLSDIALOG_H