Merge pull request #3 from LMMS/master

Merge from master, for updated LR4 filters
This commit is contained in:
Dave
2014-12-15 12:50:49 +00:00
15 changed files with 728 additions and 37 deletions

View File

@@ -64,6 +64,7 @@ public:
for( int i = 0; i < CHANNELS; ++i )
{
m_z1[i] = m_z2[i] = m_z3[i] = m_z4[i] = 0.0f;
m_y1[i] = m_y2[i] = m_y3[i] = m_y4[i] = 0.0f;
}
}
@@ -75,69 +76,89 @@ public:
inline void setCoeffs( float freq )
{
// wc
const float wc = F_2PI * freq / m_sampleRate;
const float wc2 = wc * wc;
const float wc3 = wc2 * wc;
const double wc = D_2PI * freq;
const double wc2 = wc * wc;
const double wc3 = wc2 * wc;
m_wc4 = wc2 * wc2;
// k
const float k = wc / tan( wc * 0.5 );
const float k2 = k * k;
const float k3 = k2 * k;
const double k = wc / tan( D_PI * freq / m_sampleRate );
const double k2 = k * k;
const double k3 = k2 * k;
m_k4 = k2 * k2;
// a
static const double sqrt2 = sqrt( 2.0 );
const float sq_tmp1 = sqrt2 * wc3 * k;
const float sq_tmp2 = sqrt2 * wc * k3;
m_a = 1.0f / ( 4.0f * wc2 * k2 + 2.0f * sq_tmp1 + m_k4 + 2.0f * sq_tmp2 + m_wc4 );
const double sq_tmp1 = sqrt2 * wc3 * k;
const double sq_tmp2 = sqrt2 * wc * k3;
m_a = 1.0 / ( 4.0 * wc2 * k2 + 2.0 * sq_tmp1 + m_k4 + 2.0 * sq_tmp2 + m_wc4 );
// b
m_b1 = ( 4.0f * ( m_wc4 + sq_tmp1 - m_k4 - sq_tmp2 ) ) * m_a;
m_b2 = ( 6.0f * m_wc4 - 8.0f * wc2 * k2 + 6.0f * m_k4 ) * m_a;
m_b3 = ( 4.0f * ( m_wc4 - sq_tmp1 + sq_tmp2 - m_k4 ) ) * m_a;
m_b4 = ( m_k4 - 2.0f * sq_tmp1 + m_wc4 - 2.0f * sq_tmp2 + 4.0f * wc2 * k2 ) * m_a;
m_b1 = ( 4.0 * ( m_wc4 + sq_tmp1 - m_k4 - sq_tmp2 ) ) * m_a;
m_b2 = ( 6.0 * m_wc4 - 8.0 * wc2 * k2 + 6.0 * m_k4 ) * m_a;
m_b3 = ( 4.0 * ( m_wc4 - sq_tmp1 + sq_tmp2 - m_k4 ) ) * m_a;
m_b4 = ( m_k4 - 2.0 * sq_tmp1 + m_wc4 - 2.0 * sq_tmp2 + 4.0 * wc2 * k2 ) * m_a;
}
inline void setLowpass( float freq )
{
setCoeffs( freq );
m_a0 = m_wc4 * m_a;
m_a1 = 4.0f * m_a0;
m_a2 = 6.0f * m_a0;
m_a1 = 4.0 * m_a0;
m_a2 = 6.0 * m_a0;
}
inline void setHighpass( float freq )
{
setCoeffs( freq );
m_a0 = m_k4 * m_a;
m_a1 = 4.0f * m_a0;
m_a2 = 6.0f * m_a0;
m_a1 = -4.0 * m_a0;
m_a2 = 6.0 * m_a0;
}
inline float update( float in, ch_cnt_t ch )
{
const float a0in = m_a0 * in;
const float a1in = m_a1 * in;
const float out = m_z1[ch] + a0in;
const double y = m_a0 * in + ( m_z1[ch] * m_a1 ) + ( m_z2[ch] * m_a2 ) +
( m_z3[ch] * m_a1 ) + ( m_z4[ch] * m_a0 ) -
( m_y1[ch] * m_b1 ) - ( m_y2[ch] * m_b2 ) -
( m_y3[ch] * m_b3 ) - ( m_y4[ch] * m_b4 );
m_z4[ch] = m_z3[ch];
m_z3[ch] = m_z2[ch];
m_z2[ch] = m_z1[ch];
m_z1[ch] = in;
m_z1[ch] = a1in + m_z2[ch] - ( m_b1 * out );
m_z2[ch] = ( m_a2 * in ) + m_z3[ch] - ( m_b2 * out );
m_z3[ch] = a1in + m_z4[ch] - ( m_b3 * out );
m_z4[ch] = a0in - ( m_b4 * out );
m_y4[ch] = m_y3[ch];
m_y3[ch] = m_y2[ch];
m_y2[ch] = m_y1[ch];
m_y1[ch] = y;
return out;
return y;
// for some reason converting to direct form 2 doesn't seem to work for this filter
/* const double x = in - ( m_z1[ch] * m_b1 ) - ( m_z2[ch] * m_b2 ) -
( m_z3[ch] * m_b3 ) - ( m_z4[ch] * m_b4 );
m_z4[ch] = m_z3[ch];
m_z3[ch] = m_z2[ch];
m_z2[ch] = m_z1[ch];
m_z1[ch] = x;
return ( m_a0 * x ) + ( m_z1[ch] * m_a1 ) + ( m_z2[ch] * m_a2 ) +
( m_z3[ch] * m_a1 ) + ( m_z4[ch] * m_a0 );*/
}
private:
float m_sampleRate;
float m_wc4;
float m_k4;
float m_a, m_a0, m_a1, m_a2;
float m_b1, m_b2, m_b3, m_b4;
double m_wc4;
double m_k4;
double m_a, m_a0, m_a1, m_a2;
double m_b1, m_b2, m_b3, m_b4;
typedef float frame[CHANNELS];
typedef double frame[CHANNELS];
frame m_z1, m_z2, m_z3, m_z4;
frame m_y1, m_y2, m_y3, m_y4;
};
typedef LinkwitzRiley<2> StereoLinkwitzRiley;

View File

@@ -103,7 +103,7 @@ private:
float fRange = m_model->maxValue() - m_model->minValue();
float realVal = m_model->value() - m_model->minValue();
return height() - ( ( height() - ( *s_knob ).height() ) * ( realVal / fRange ) );
return height() - ( ( height() - m_knob->height() ) * ( realVal / fRange ) );
}
FloatModel * m_model;

View File

@@ -6,6 +6,7 @@ ADD_SUBDIRECTORY(Bitcrush)
ADD_SUBDIRECTORY(carlabase)
ADD_SUBDIRECTORY(carlapatchbay)
ADD_SUBDIRECTORY(carlarack)
ADD_SUBDIRECTORY(CrossoverEQ)
ADD_SUBDIRECTORY(delay)
ADD_SUBDIRECTORY(DualFilter)
ADD_SUBDIRECTORY(dynamics_processor)

View File

@@ -0,0 +1,3 @@
INCLUDE(BuildPlugin)
BUILD_PLUGIN(crossovereq CrossoverEQ.cpp CrossoverEQControls.cpp CrossoverEQControlDialog.cpp MOCFILES CrossoverEQControls.h CrossoverEQControlDialog.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")

View File

@@ -0,0 +1,219 @@
/*
* CrossoverEQ.cpp - A native 4-band Crossover Equalizer
* good for simulating tonestacks or simple peakless (flat-band) equalization
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - http://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 "CrossoverEQ.h"
#include "lmms_math.h"
#include "embed.cpp"
extern "C"
{
Plugin::Descriptor PLUGIN_EXPORT crossovereq_plugin_descriptor =
{
STRINGIFY( PLUGIN_NAME ),
"Crossover Equalizer",
QT_TRANSLATE_NOOP( "pluginBrowser", "A 4-band Crossover Equalizer" ),
"Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>",
0x0100,
Plugin::Effect,
new PluginPixmapLoader( "logo" ),
NULL,
NULL
};
}
CrossoverEQEffect::CrossoverEQEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ) :
Effect( &crossovereq_plugin_descriptor, parent, key ),
m_controls( this ),
m_sampleRate( Engine::mixer()->processingSampleRate() ),
m_lp1( m_sampleRate ),
m_lp2( m_sampleRate ),
m_lp3( m_sampleRate ),
m_hp2( m_sampleRate ),
m_hp3( m_sampleRate ),
m_hp4( m_sampleRate ),
m_needsUpdate( true )
{
m_tmp1 = MM_ALLOC( sampleFrame, Engine::mixer()->framesPerPeriod() );
m_tmp2 = MM_ALLOC( sampleFrame, Engine::mixer()->framesPerPeriod() );
m_work = MM_ALLOC( sampleFrame, Engine::mixer()->framesPerPeriod() );
}
CrossoverEQEffect::~CrossoverEQEffect()
{
MM_FREE( m_tmp1 );
MM_FREE( m_tmp2 );
MM_FREE( m_work );
}
void CrossoverEQEffect::sampleRateChanged()
{
m_sampleRate = Engine::mixer()->processingSampleRate();
m_lp1.setSampleRate( m_sampleRate );
m_lp2.setSampleRate( m_sampleRate );
m_lp3.setSampleRate( m_sampleRate );
m_hp2.setSampleRate( m_sampleRate );
m_hp3.setSampleRate( m_sampleRate );
m_hp4.setSampleRate( m_sampleRate );
m_needsUpdate = true;
}
bool CrossoverEQEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{
return( false );
}
// filters update
if( m_needsUpdate || m_controls.m_xover12.isValueChanged() )
{
m_lp1.setLowpass( m_controls.m_xover12.value() );
m_lp1.clearHistory();
m_hp2.setHighpass( m_controls.m_xover12.value() );
m_hp2.clearHistory();
}
if( m_needsUpdate || m_controls.m_xover23.isValueChanged() )
{
m_lp2.setLowpass( m_controls.m_xover23.value() );
m_lp2.clearHistory();
m_hp3.setHighpass( m_controls.m_xover23.value() );
m_hp3.clearHistory();
}
if( m_needsUpdate || m_controls.m_xover34.isValueChanged() )
{
m_lp3.setLowpass( m_controls.m_xover34.value() );
m_lp3.clearHistory();
m_hp4.setHighpass( m_controls.m_xover34.value() );
m_hp4.clearHistory();
}
// gain values update
if( m_needsUpdate || m_controls.m_gain1.isValueChanged() )
{
m_gain1 = dbvToAmp( m_controls.m_gain1.value() );
}
if( m_needsUpdate || m_controls.m_gain2.isValueChanged() )
{
m_gain2 = dbvToAmp( m_controls.m_gain2.value() );
}
if( m_needsUpdate || m_controls.m_gain3.isValueChanged() )
{
m_gain3 = dbvToAmp( m_controls.m_gain3.value() );
}
if( m_needsUpdate || m_controls.m_gain4.isValueChanged() )
{
m_gain4 = dbvToAmp( m_controls.m_gain4.value() );
}
// mute values update
const bool mute1 = m_controls.m_mute1.value();
const bool mute2 = m_controls.m_mute2.value();
const bool mute3 = m_controls.m_mute3.value();
const bool mute4 = m_controls.m_mute4.value();
m_needsUpdate = false;
memset( m_work, 0, sizeof( sampleFrame ) * frames );
// run temp bands
for( int f = 0; f < frames; ++f )
{
m_tmp1[f][0] = m_lp2.update( buf[f][0], 0 );
m_tmp1[f][1] = m_lp2.update( buf[f][1], 1 );
m_tmp2[f][0] = m_hp3.update( buf[f][0], 0 );
m_tmp2[f][1] = m_hp3.update( buf[f][1], 1 );
}
// run band 1
if( ! mute1 )
{
for( int f = 0; f < frames; ++f )
{
m_work[f][0] += m_lp1.update( m_tmp1[f][0], 0 ) * m_gain1;
m_work[f][1] += m_lp1.update( m_tmp1[f][1], 1 ) * m_gain1;
}
}
// run band 2
if( ! mute2 )
{
for( int f = 0; f < frames; ++f )
{
m_work[f][0] += m_hp2.update( m_tmp1[f][0], 0 ) * m_gain2;
m_work[f][1] += m_hp2.update( m_tmp1[f][1], 1 ) * m_gain2;
}
}
// run band 3
if( ! mute3 )
{
for( int f = 0; f < frames; ++f )
{
m_work[f][0] += m_lp3.update( m_tmp2[f][0], 0 ) * m_gain3;
m_work[f][1] += m_lp3.update( m_tmp2[f][1], 1 ) * m_gain3;
}
}
// run band 4
if( ! mute4 )
{
for( int f = 0; f < frames; ++f )
{
m_work[f][0] += m_hp4.update( m_tmp2[f][0], 0 ) * m_gain4;
m_work[f][1] += m_hp4.update( m_tmp2[f][1], 1 ) * m_gain4;
}
}
const float d = dryLevel();
const float w = wetLevel();
double outSum = 0.0;
for( int f = 0; f < frames; ++f )
{
buf[f][0] = d * buf[f][0] + w * m_work[f][0];
buf[f][1] = d * buf[f][1] + w * m_work[f][1];
outSum = buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1];
}
checkGate( outSum );
return isRunning();
}
extern "C"
{
// necessary for getting instance out of shared lib
Plugin * PLUGIN_EXPORT lmms_plugin_main( Model* parent, void* data )
{
return new CrossoverEQEffect( parent, static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>( data ) );
}
}

View File

@@ -0,0 +1,77 @@
/*
* CrossoverEQ.h - A native 4-band Crossover Equalizer
* good for simulating tonestacks or simple peakless (flat-band) equalization
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - http://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 CROSSOVEREQ_H
#define CROSSOVEREQ_H
#include "Effect.h"
#include "CrossoverEQControls.h"
#include "ValueBuffer.h"
#include "lmms_math.h"
#include "BasicFilters.h"
class CrossoverEQEffect : public Effect
{
public:
CrossoverEQEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
virtual ~CrossoverEQEffect();
virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames );
virtual EffectControls* controls()
{
return &m_controls;
}
private:
CrossoverEQControls m_controls;
void sampleRateChanged();
float m_sampleRate;
float m_gain1;
float m_gain2;
float m_gain3;
float m_gain4;
StereoLinkwitzRiley m_lp1;
StereoLinkwitzRiley m_lp2;
StereoLinkwitzRiley m_lp3;
StereoLinkwitzRiley m_hp2;
StereoLinkwitzRiley m_hp3;
StereoLinkwitzRiley m_hp4;
sampleFrame * m_tmp1;
sampleFrame * m_tmp2;
sampleFrame * m_work;
bool m_needsUpdate;
friend class CrossoverEQControls;
};
#endif

View File

@@ -0,0 +1,115 @@
/*
* CrossoverEQControlDialog.cpp - A native 4-band Crossover Equalizer
* good for simulating tonestacks or simple peakless (flat-band) equalization
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - http://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#include <QLayout>
#include <QLabel>
#include "CrossoverEQControlDialog.h"
#include "CrossoverEQControls.h"
#include "embed.h"
#include "ToolTip.h"
#include "LedCheckbox.h"
#include "Knob.h"
#include "Fader.h"
CrossoverEQControlDialog::CrossoverEQControlDialog( CrossoverEQControls * controls ) :
EffectControlDialog( controls )
{
setAutoFillBackground( true );
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
setPalette( pal );
setFixedSize( 167, 188 );
// knobs
Knob * xover12 = new Knob( knobBright_26, this );
xover12->move( 29, 15 );
xover12->setModel( & controls->m_xover12 );
xover12->setLabel( "1/2" );
xover12->setHintText( tr( "Band 1/2 Crossover:" ), " Hz" );
Knob * xover23 = new Knob( knobBright_26, this );
xover23->move( 69, 15 );
xover23->setModel( & controls->m_xover23 );
xover23->setLabel( "2/3" );
xover23->setHintText( tr( "Band 2/3 Crossover:" ), " Hz" );
Knob * xover34 = new Knob( knobBright_26, this );
xover34->move( 109, 15 );
xover34->setModel( & controls->m_xover34 );
xover34->setLabel( "3/4" );
xover34->setHintText( tr( "Band 3/4 Crossover:" ), " Hz" );
m_fader_bg = QPixmap( PLUGIN_NAME::getIconPixmap( "fader_bg" ) );
m_fader_empty = QPixmap( PLUGIN_NAME::getIconPixmap( "fader_empty" ) );
m_fader_knob = QPixmap( PLUGIN_NAME::getIconPixmap( "fader_knob2" ) );
// faders
Fader * gain1 = new Fader( &controls->m_gain1, "Band 1 Gain", this,
&m_fader_bg, &m_fader_empty, &m_fader_knob );
gain1->move( 7, 56 );
gain1->setDisplayConversion( false );
gain1->setHintText( tr( "Band 1 Gain:" ), " dBV" );
Fader * gain2 = new Fader( &controls->m_gain2, "Band 2 Gain", this,
&m_fader_bg, &m_fader_empty, &m_fader_knob );
gain2->move( 47, 56 );
gain2->setDisplayConversion( false );
gain2->setHintText( tr( "Band 2 Gain:" ), " dBV" );
Fader * gain3 = new Fader( &controls->m_gain3, "Band 3 Gain", this,
&m_fader_bg, &m_fader_empty, &m_fader_knob );
gain3->move( 87, 56 );
gain3->setDisplayConversion( false );
gain3->setHintText( tr( "Band 3 Gain:" ), " dBV" );
Fader * gain4 = new Fader( &controls->m_gain4, "Band 4 Gain", this,
&m_fader_bg, &m_fader_empty, &m_fader_knob );
gain4->move( 127, 56 );
gain4->setDisplayConversion( false );
gain4->setHintText( tr( "Band 4 Gain:" ), " dBV" );
// leds
LedCheckBox * mute1 = new LedCheckBox( "M", this, tr( "Band 1 Mute" ), LedCheckBox::Red );
mute1->move( 11, 158 );
mute1->setModel( & controls->m_mute1 );
ToolTip::add( mute1, tr( "Mute Band 1" ) );
LedCheckBox * mute2 = new LedCheckBox( "M", this, tr( "Band 2 Mute" ), LedCheckBox::Red );
mute2->move( 51, 158 );
mute2->setModel( & controls->m_mute2 );
ToolTip::add( mute2, tr( "Mute Band 2" ) );
LedCheckBox * mute3 = new LedCheckBox( "M", this, tr( "Band 3 Mute" ), LedCheckBox::Red );
mute3->move( 91, 158 );
mute3->setModel( & controls->m_mute3 );
ToolTip::add( mute3, tr( "Mute Band 3" ) );
LedCheckBox * mute4 = new LedCheckBox( "M", this, tr( "Band 4 Mute" ), LedCheckBox::Red );
mute4->move( 131, 158 );
mute4->setModel( & controls->m_mute4 );
ToolTip::add( mute4, tr( "Mute Band 4" ) );
}

View File

@@ -0,0 +1,50 @@
/*
* CrossoverEQControlDialog.h - A native 4-band Crossover Equalizer
* good for simulating tonestacks or simple peakless (flat-band) equalization
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - http://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 CROSSOVEREQ_CONTROL_DIALOG_H
#define CROSSOVEREQ_CONTROL_DIALOG_H
#include <QPixmap>
#include "EffectControlDialog.h"
class CrossoverEQControls;
class CrossoverEQControlDialog : public EffectControlDialog
{
Q_OBJECT
public:
CrossoverEQControlDialog( CrossoverEQControls * controls );
virtual ~CrossoverEQControlDialog()
{
}
private:
QPixmap m_fader_bg;
QPixmap m_fader_empty;
QPixmap m_fader_knob;
};
#endif

View File

@@ -0,0 +1,116 @@
/*
* CrossoverEQControls.cpp - A native 4-band Crossover Equalizer
* good for simulating tonestacks or simple peakless (flat-band) equalization
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - http://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 "CrossoverEQControls.h"
#include "CrossoverEQ.h"
CrossoverEQControls::CrossoverEQControls( CrossoverEQEffect * eff ) :
EffectControls( eff ),
m_effect( eff ),
m_xover12( 125.f, 50.f, 10000.f, 1.0f, this, "Band 1/2 Crossover" ),
m_xover23( 1250.f, 50.f, 20000.f, 1.0f, this, "Band 2/3 Crossover" ),
m_xover34( 5000.f, 50.f, 20000.f, 1.0f, this, "Band 3/4 Crossover" ),
m_gain1( 0.f, -60.f, 30.f, 0.1f, this, "Band 1 Gain" ),
m_gain2( 0.f, -60.f, 30.f, 0.1f, this, "Band 2 Gain" ),
m_gain3( 0.f, -60.f, 30.f, 0.1f, this, "Band 3 Gain" ),
m_gain4( 0.f, -60.f, 30.f, 0.1f, this, "Band 4 Gain" ),
m_mute1( false, this, "Mute Band 1" ),
m_mute2( false, this, "Mute Band 2" ),
m_mute3( false, this, "Mute Band 3" ),
m_mute4( false, this, "Mute Band 4" )
{
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) );
connect( &m_xover12, SIGNAL( dataChanged() ), this, SLOT( xover12Changed() ) );
connect( &m_xover23, SIGNAL( dataChanged() ), this, SLOT( xover23Changed() ) );
connect( &m_xover34, SIGNAL( dataChanged() ), this, SLOT( xover34Changed() ) );
m_xover12.setScaleLogarithmic( true );
m_xover23.setScaleLogarithmic( true );
m_xover34.setScaleLogarithmic( true );
}
void CrossoverEQControls::saveSettings( QDomDocument & doc, QDomElement & elem )
{
m_xover12.saveSettings( doc, elem, "xover12" );
m_xover23.saveSettings( doc, elem, "xover23" );
m_xover34.saveSettings( doc, elem, "xover34" );
m_gain1.saveSettings( doc, elem, "gain1" );
m_gain2.saveSettings( doc, elem, "gain2" );
m_gain3.saveSettings( doc, elem, "gain3" );
m_gain4.saveSettings( doc, elem, "gain4" );
m_mute1.saveSettings( doc, elem, "mute1" );
m_mute2.saveSettings( doc, elem, "mute2" );
m_mute3.saveSettings( doc, elem, "mute3" );
m_mute4.saveSettings( doc, elem, "mute4" );
}
void CrossoverEQControls::loadSettings( const QDomElement & elem )
{
m_xover12.loadSettings( elem, "xover12" );
m_xover23.loadSettings( elem, "xover23" );
m_xover34.loadSettings( elem, "xover34" );
m_gain1.loadSettings( elem, "gain1" );
m_gain2.loadSettings( elem, "gain2" );
m_gain3.loadSettings( elem, "gain3" );
m_gain4.loadSettings( elem, "gain4" );
m_mute1.loadSettings( elem, "mute1" );
m_mute2.loadSettings( elem, "mute2" );
m_mute3.loadSettings( elem, "mute3" );
m_mute4.loadSettings( elem, "mute4" );
m_effect->m_needsUpdate = true;
}
void CrossoverEQControls::xover12Changed()
{
float v = m_xover12.value();
if( m_xover23.value() < v ) { m_xover23.setValue( v ); }
if( m_xover34.value() < v ) { m_xover34.setValue( v ); }
}
void CrossoverEQControls::xover23Changed()
{
float v = m_xover23.value();
if( m_xover12.value() > v ) { m_xover12.setValue( v ); }
if( m_xover34.value() < v ) { m_xover34.setValue( v ); }
}
void CrossoverEQControls::xover34Changed()
{
float v = m_xover34.value();
if( m_xover12.value() > v ) { m_xover12.setValue( v ); }
if( m_xover23.value() > v ) { m_xover23.setValue( v ); }
}
void CrossoverEQControls::sampleRateChanged()
{
m_effect->sampleRateChanged();
}

View File

@@ -0,0 +1,86 @@
/*
* CrossoverEQControls.h - A native 4-band Crossover Equalizer
* good for simulating tonestacks or simple peakless (flat-band) equalization
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - http://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 CROSSOVEREQ_CONTROLS_H
#define CROSSOVEREQ_CONTROLS_H
#include "EffectControls.h"
#include "CrossoverEQControlDialog.h"
class CrossoverEQEffect;
class CrossoverEQControls : public EffectControls
{
Q_OBJECT
public:
CrossoverEQControls( CrossoverEQEffect * eff );
virtual ~CrossoverEQControls() {}
virtual void saveSettings( QDomDocument & doc, QDomElement & elem );
virtual void loadSettings( const QDomElement & elem );
inline virtual QString nodeName() const
{
return( "crossoevereqcontrols" );
}
virtual int controlCount()
{
return( 11 );
}
virtual EffectControlDialog * createView()
{
return( new CrossoverEQControlDialog( this ) );
}
private slots:
void xover12Changed();
void xover23Changed();
void xover34Changed();
void sampleRateChanged();
private:
CrossoverEQEffect * m_effect;
FloatModel m_xover12;
FloatModel m_xover23;
FloatModel m_xover34;
FloatModel m_gain1;
FloatModel m_gain2;
FloatModel m_gain3;
FloatModel m_gain4;
BoolModel m_mute1;
BoolModel m_mute2;
BoolModel m_mute3;
BoolModel m_mute4;
friend class CrossoverEQControlDialog;
friend class CrossoverEQEffect;
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 B

View File

@@ -170,7 +170,7 @@ void Fader::mouseMoveEvent( QMouseEvent *mouseEvent )
{
int dy = m_moveStartPoint - mouseEvent->globalY();
float delta = dy * ( m_model->maxValue() - m_model->minValue() ) / (float) ( height() - ( *s_knob ).height() );
float delta = dy * ( m_model->maxValue() - m_model->minValue() ) / (float) ( height() - ( *m_knob ).height() );
model()->setValue( m_startValue + delta );
@@ -186,7 +186,7 @@ void Fader::mousePressEvent( QMouseEvent* mouseEvent )
if( mouseEvent->button() == Qt::LeftButton &&
! ( mouseEvent->modifiers() & Qt::ControlModifier ) )
{
if( mouseEvent->y() >= knobPosY() - ( *s_knob ).height() && mouseEvent->y() < knobPosY() )
if( mouseEvent->y() >= knobPosY() - ( *m_knob ).height() && mouseEvent->y() < knobPosY() )
{
updateTextFloat();
s_textFloat->show();
@@ -346,13 +346,16 @@ void Fader::paintEvent( QPaintEvent * ev)
// background
painter.drawPixmap( ev->rect(), *m_back, ev->rect() );
// peak leds
//float fRange = abs( m_fMaxPeak ) + abs( m_fMinPeak );
int height = m_back->height();
int width = m_back->width() / 2;
int center = m_back->width() - width;
int peak_L = calculateDisplayPeak( m_fPeakValue_L - m_fMinPeak );
int persistentPeak_L = qMax<int>( 3, calculateDisplayPeak( m_persistentPeak_L - m_fMinPeak ) );
painter.drawPixmap( QRect( 0, peak_L, 11, 116 - peak_L ), *m_leds, QRect( 0, peak_L, 11, 116 - peak_L ) );
painter.drawPixmap( QRect( 0, peak_L, width, height - peak_L ), *m_leds, QRect( 0, peak_L, width, height - peak_L ) );
if( m_persistentPeak_L > 0.05 )
{
@@ -363,7 +366,7 @@ void Fader::paintEvent( QPaintEvent * ev)
int peak_R = calculateDisplayPeak( m_fPeakValue_R - m_fMinPeak );
int persistentPeak_R = qMax<int>( 3, calculateDisplayPeak( m_persistentPeak_R - m_fMinPeak ) );
painter.drawPixmap( QRect( 11, peak_R, 11, 116 - peak_R ), *m_leds, QRect( 11, peak_R, 11, 116 - peak_R ) );
painter.drawPixmap( QRect( center, peak_R, width, height - peak_R ), *m_leds, QRect( center, peak_R, width, height - peak_R ) );
if( m_persistentPeak_R > 0.05 )
{
@@ -373,7 +376,7 @@ void Fader::paintEvent( QPaintEvent * ev)
}
// knob
painter.drawPixmap( 0, knobPosY() - ( *m_knob ).height(), *s_knob );
painter.drawPixmap( 0, knobPosY() - m_knob->height(), *m_knob );
}