EQ update

filters before downsampling changed
ignore wet dry knob
scale lines on widget
filter type switch loading correctly
analyser code all move to one location
implment analyze button
remove redundant code
analyser display omprovments
This commit is contained in:
Dave French
2014-12-13 15:55:28 +00:00
parent a7831a7cca
commit 08821a7290
10 changed files with 646 additions and 515 deletions

View File

@@ -65,14 +65,15 @@ EqControls::EqControls( EqEffect *effect ) :
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( true, this , tr( "LP 12" ) ),
m_lp12Model( false, this , tr( "LP 12" ) ),
m_lp24Model( false, this , tr( "LP 24" ) ),
m_lp48Model( false, this , tr( "LP 48" ) ),
m_hp12Model( true, this , tr( "HP 12" ) ),
m_hp12Model( false, this , tr( "HP 12" ) ),
m_hp24Model( false, this , tr( "HP 24" ) ),
m_hp48Model( false, this , tr( "HP 48" ) ),
m_analyzeModel( true, this , tr( "Analyze enable" ) )
m_analyzeModel( true, this , tr( "Analyze enable" ) ),
m_lpTypeModel(0,0,2,this, tr( "low pass type") ) ,
m_hpTypeModel(0,0,2,this, tr( "high pass type") )
{
m_hpFeqModel.setScaleLogarithmic( true );
m_lowShelfFreqModel.setScaleLogarithmic( true );
@@ -92,6 +93,7 @@ EqControls::EqControls( EqEffect *effect ) :
m_para3PeakL = 0; m_para3PeakR = 0;
m_para4PeakL = 0; m_para4PeakR = 0;
m_highShelfPeakL = 0; m_highShelfPeakR = 0;
m_inProgress = false;
}
@@ -144,6 +146,9 @@ void EqControls::loadSettings( const QDomElement &_this )
m_hp24Model.loadSettings( _this , "HP24" );
m_hp48Model.loadSettings( _this , "HP48" );
m_analyzeModel.loadSettings( _this, "Analyzeenable");
m_lpTypeModel.loadSettings( _this, "LP" );
m_hpTypeModel.loadSettings( _this, "HP" );
}
@@ -197,5 +202,7 @@ void EqControls::saveSettings( QDomDocument &doc, QDomElement &parent )
m_hp48Model.saveSettings( doc, parent, "HP48" );
m_analyzeModel.saveSettings( doc, parent, "Analyzeenable");
m_lpTypeModel.saveSettings( doc, parent, "LP" );
m_hpTypeModel.saveSettings( doc, parent, "HP" );
}

View File

@@ -36,28 +36,28 @@ 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 39;
}
virtual EffectControlDialog* createView()
{
return new EqControlsDialog( this );
}
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 39;
}
virtual EffectControlDialog* createView()
{
return new EqControlsDialog( this );
}
float m_inPeakL;
float m_inPeakR;
float m_outPeakL;
float m_outPeakR;
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;
@@ -65,64 +65,69 @@ public:
float m_para4PeakL, m_para4PeakR;
float m_highShelfPeakL, m_highShelfPeakR;
FftBands m_inFftBands;
FftBands m_outFftBands;
EqAnalyser m_inFftBands;
EqAnalyser m_outFftBands;
bool m_inProgress;
private:
EqEffect* m_effect;
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_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_para1ResModel;
FloatModel m_para2ResModel;
FloatModel m_para3ResModel;
FloatModel m_para4ResModel;
FloatModel m_highShelfResModel;
FloatModel m_lpResModel;
FloatModel m_hpResModel;
FloatModel m_lowShelfResModel;
FloatModel m_para1ResModel;
FloatModel m_para2ResModel;
FloatModel m_para3ResModel;
FloatModel m_para4ResModel;
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;
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_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_lp12Model;
BoolModel m_lp24Model;
BoolModel m_lp48Model;
BoolModel m_hp12Model;
BoolModel m_hp24Model;
BoolModel m_hp48Model;
BoolModel m_hp12Model;
BoolModel m_hp24Model;
BoolModel m_hp48Model;
BoolModel m_analyzeModel;
BoolModel m_analyzeModel;
friend class EqControlsDialog;
friend class EqEffect;
IntModel m_lpTypeModel;
IntModel m_hpTypeModel;
friend class EqControlsDialog;
friend class EqEffect;
};

View File

@@ -51,10 +51,10 @@ EqControlsDialog::EqControlsDialog(EqControls *controls) :
m_inSpec = new EqSpectrumView( &controls->m_inFftBands, this);
m_inSpec->move( 50, 5 );
m_inSpec->color = QColor( 200, 200, 100, 100 );
m_inSpec->color = QColor( 255, 0, 255, 80 );
m_outSpec = new EqSpectrumView( &controls->m_outFftBands, this);
m_outSpec->move( 50, 5 );
m_outSpec->color = QColor(100, 200, 200, 100);
m_outSpec->color = QColor(00, 255, 255, 80);
m_parameterWidget = new EqParameterWidget( this );
m_parameterWidget->move( 50, 5 );
@@ -134,31 +134,16 @@ EqControlsDialog::EqControlsDialog(EqControls *controls) :
m_lp48Box->setModel( &controls->m_lp48Model );
automatableButtonGroup *lpBtnGrp = new automatableButtonGroup(this,tr ( "lp grp" ) );
lpBtnGrp->addButton(m_lp12Box);
lpBtnGrp->addButton(m_lp24Box );
lpBtnGrp->addButton(m_lp48Box );
connect( m_lp12Box, SIGNAL( clicked() ), lpBtnGrp , SLOT( updateButtons() ) );
connect( m_lp24Box, SIGNAL( clicked() ), lpBtnGrp , SLOT( updateButtons() ) );
connect( m_lp48Box, SIGNAL( clicked() ), lpBtnGrp , SLOT( updateButtons() ) );
connect( &controls->m_lp12Model, SIGNAL( dataChanged() ), lpBtnGrp, SLOT( updateButtons() ) );
connect( &controls->m_lp24Model, SIGNAL( dataChanged() ), lpBtnGrp, SLOT( updateButtons() ) );
connect( &controls->m_lp48Model, SIGNAL( dataChanged() ), lpBtnGrp, SLOT( updateButtons() ) );
lpBtnGrp->addButton( m_lp12Box);
lpBtnGrp->addButton( m_lp24Box );
lpBtnGrp->addButton( m_lp48Box );
lpBtnGrp->setModel( &m_controls->m_lpTypeModel, false);
automatableButtonGroup *hpBtnGrp = new automatableButtonGroup( this, tr( "hp grp" ) );
hpBtnGrp->addButton(m_hp12Box );
hpBtnGrp->addButton(m_hp24Box );
hpBtnGrp->addButton(m_hp48Box );
connect( m_hp12Box, SIGNAL ( clicked() ), hpBtnGrp, SLOT( updateButtons() ) );
connect( m_hp24Box, SIGNAL ( clicked() ), hpBtnGrp, SLOT( updateButtons() ) );
connect( m_hp48Box, SIGNAL ( clicked() ), hpBtnGrp, SLOT( updateButtons() ) );
connect( &controls->m_hp12Model, SIGNAL( dataChanged() ), hpBtnGrp, SLOT( updateButtons() ) );
connect( &controls->m_hp24Model, SIGNAL( dataChanged() ), hpBtnGrp, SLOT( updateButtons() ) );
connect( &controls->m_hp48Model, SIGNAL( dataChanged() ), hpBtnGrp, SLOT( updateButtons() ) );
hpBtnGrp->addButton( m_hp12Box );
hpBtnGrp->addButton( m_hp24Box );
hpBtnGrp->addButton( m_hp48Box );
hpBtnGrp->setModel( &m_controls->m_hpTypeModel,false);
//Analize Box
m_analyzeBox = new LedCheckBox( tr( "Analyze" ), this );

View File

@@ -33,6 +33,7 @@
#include "MainWindow.h"
#include "qpushbutton.h"
#include "eqspectrumview.h"
#include "qlist.h"
class EqControls;
@@ -40,56 +41,56 @@ class EqControlsDialog : public EffectControlDialog
{
public:
EqControlsDialog( EqControls* controls );
virtual ~EqControlsDialog()
{
}
EqControlsDialog( EqControls* controls );
virtual ~EqControlsDialog()
{
}
EqBand * setBand(EqControls *controls);
EqBand * setBand(EqControls *controls);
private slots:
void updateVuMeters();
void updateVuMeters();
private:
EqControls * m_controls;
EqControls * m_controls;
Fader* m_inGainFader;
Fader* m_outGainFader;
Fader* m_gainFader;
Knob* m_resKnob;
Knob* m_freqKnob;
LedCheckBox* m_activeBox;
LedCheckBox* m_lp12Box;
LedCheckBox* m_lp24Box;
LedCheckBox* m_lp48Box;
LedCheckBox* m_hp12Box;
LedCheckBox* m_hp24Box;
LedCheckBox* m_hp48Box;
Fader* m_inGainFader;
Fader* m_outGainFader;
Fader* m_gainFader;
Knob* m_resKnob;
Knob* m_freqKnob;
LedCheckBox* m_activeBox;
LedCheckBox* m_lp12Box;
LedCheckBox* m_lp24Box;
LedCheckBox* m_lp48Box;
LedCheckBox* m_hp12Box;
LedCheckBox* m_hp24Box;
LedCheckBox* m_hp48Box;
LedCheckBox* m_analyzeBox;
LedCheckBox* m_analyzeBox;
EqParameterWidget* m_parameterWidget;
EqParameterWidget* m_parameterWidget;
EqSpectrumView* m_inSpec;
EqSpectrumView* m_outSpec;
virtual void mouseDoubleClickEvent(QMouseEvent *event);
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)
{
EqBand* filterModels = m_parameterWidget->getBandModels( index );
filterModels->active = active;
filterModels->freq = freq;
filterModels->res = res;
filterModels->color = color;
filterModels->gain = gain;
{
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;
return filterModels;
}
int m_originalHeight;
return filterModels;
}
int m_originalHeight;
};
#endif // EQCONTROLSDIALOG_H

View File

@@ -59,14 +59,12 @@ EqEffect::EqEffect(Model *parent, const Plugin::Descriptor::SubPluginFeatures::K
Effect( &eq_plugin_descriptor, parent, key ),
m_eqControls( this )
{
m_dFilterCount = 10;
m_downsampleFilters = new EqLp12Filter[m_dFilterCount];
m_dFilterCount = 20;
m_downsampleFilters = new EqLinkwitzRiley[m_dFilterCount];
for( int i = 0; i < m_dFilterCount; i++)
{
m_downsampleFilters[i].setFrequency(22000);
m_downsampleFilters[i].setQ(0.85);
m_downsampleFilters[i].setGain(0);
m_downsampleFilters[i].setSampleRate(Engine::mixer()->processingSampleRate() * 2 );
m_downsampleFilters[i].setFrequency(21500);
m_downsampleFilters[i].setSR(Engine::mixer()->processingSampleRate() * 2 );
}
m_upBuf = 0;
}
@@ -88,15 +86,21 @@ bool EqEffect::processAudioBuffer(sampleFrame *buf, const fpp_t frames)
{
return( false );
}
m_eqControls.m_inProgress = true;
double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float outGain = m_eqControls.m_outGainModel.value();
const int sampleRate = Engine::mixer()->processingSampleRate() * 2;
sample_t dryS[2];
sampleFrame m_inPeak;
sampleFrame m_inPeak = { 0, 0 };
if(m_eqControls.m_analyzeModel.value() )
{
m_eqControls.m_inFftBands.analyze( buf, frames );
}
else
{
m_eqControls.m_inFftBands.clear();
}
analyze( buf, frames, &m_eqControls.m_inFftBands) ;
//TODO UPSAMPLE
upsample( buf, frames );
@@ -214,7 +218,7 @@ bool EqEffect::processAudioBuffer(sampleFrame *buf, const fpp_t frames)
}
}
sampleFrame outPeak;
sampleFrame outPeak = { 0, 0 };
gain( m_upBuf , m_upBufFrames, 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[0] : m_eqControls.m_outPeakR;
@@ -229,14 +233,20 @@ bool EqEffect::processAudioBuffer(sampleFrame *buf, const fpp_t frames)
for( fpp_t f = 0; f < frames; ++f )
{
buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] );
buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] );
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
checkGate( outSum / frames );
analyze( buf, frames, &m_eqControls.m_outFftBands) ;
setBandPeaks( &m_eqControls.m_outFftBands , (int)(sampleRate * 0.5));
if(m_eqControls.m_analyzeModel.value() )
{
m_eqControls.m_outFftBands.analyze( buf, frames );
}
else
{
m_eqControls.m_outFftBands.clear();
}
setBandPeaks( &m_eqControls.m_outFftBands , (int)(sampleRate * 0.5));
m_eqControls.m_inProgress = false;
return isRunning();
}
@@ -259,8 +269,8 @@ void EqEffect::gain(sampleFrame *buf, const fpp_t frames, float scale, sampleFra
{
peak[0][1] = fabs( buf[f][0] );
}
}
}
}
sampleFrame m_lastUpFrame;
@@ -288,54 +298,60 @@ void EqEffect::upsample(sampleFrame *buf, const fpp_t frames)
m_lastUpFrame[1] = buf[f][1];
}
}
}
void EqEffect::downSample(sampleFrame *buf, const fpp_t frames)
{
for( int f = 0, f2 = 0; f < frames; ++f, f2 += 2 )
{
buf[f][0] = m_upBuf[f2][0];
buf[f][1] = m_upBuf[f2][1];
buf[f][0] = m_upBuf[f2+1][0];
buf[f][1] = m_upBuf[f2+1][1];
}
}
void EqEffect::analyze(sampleFrame *buf, const fpp_t frames, FftBands* fft)
void EqEffect::analyze(sampleFrame *buf, const fpp_t frames, EqAnalyser* fft)
{
const int FFT_BUFFER_SIZE = 2048;
fpp_t f = 0;
if( frames > FFT_BUFFER_SIZE )
if(m_eqControls.m_analyzeModel.value() )
{
const int FFT_BUFFER_SIZE = 2048;
fpp_t f = 0;
if( frames > FFT_BUFFER_SIZE )
{
fft->m_framesFilledUp = 0;
f = frames - FFT_BUFFER_SIZE;
}
// meger channels
for( ; f < frames; ++f )
{
fft->m_buffer[fft->m_framesFilledUp] =
( buf[f][0] + buf[f][1] ) * 0.5;
++fft->m_framesFilledUp;
}
if( fft->m_framesFilledUp < FFT_BUFFER_SIZE )
{
return;
}
fft->m_sr = Engine::mixer()->processingSampleRate();
const int LOWEST_FREQ = 0;
const int HIGHEST_FREQ = fft->m_sr / 2;
fftwf_execute( fft->m_fftPlan );
absspec( fft->m_specBuf, fft->m_absSpecBuf, FFT_BUFFER_SIZE+1 );
compressbands( fft->m_absSpecBuf, fft->m_bands, FFT_BUFFER_SIZE+1,
MAX_BANDS,
(int)(LOWEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(fft->m_sr /2)),
(int)(HIGHEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(fft->m_sr /2)));
fft->m_energy = maximum( fft->m_bands, MAX_BANDS ) / maximum( fft->m_buffer, FFT_BUFFER_SIZE );
fft->m_framesFilledUp = 0;
f = frames - FFT_BUFFER_SIZE;
}
// meger channels
for( ; f < frames; ++f )
{
fft->m_buffer[fft->m_framesFilledUp] =
( buf[f][0] + buf[f][1] ) * 0.5;
++fft->m_framesFilledUp;
}
if( fft->m_framesFilledUp < FFT_BUFFER_SIZE )
{
return;
}
fft->m_sr = Engine::mixer()->processingSampleRate();
const int LOWEST_FREQ = 0;
const int HIGHEST_FREQ = fft->m_sr / 2;
fftwf_execute( fft->m_fftPlan );
absspec( fft->m_specBuf, fft->m_absSpecBuf, FFT_BUFFER_SIZE+1 );
compressbands( fft->m_absSpecBuf, fft->m_bands, FFT_BUFFER_SIZE+1,
MAX_BANDS,
(int)(LOWEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(fft->m_sr /2)),
(int)(HIGHEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(fft->m_sr /2)));
fft->m_energy = maximum( fft->m_bands, MAX_BANDS ) / maximum( fft->m_buffer, FFT_BUFFER_SIZE );
fft->m_framesFilledUp = 0;
}
float EqEffect::peakBand(float minF, float maxF, FftBands *fft, int sr)
float EqEffect::peakBand(float minF, float maxF, EqAnalyser *fft, int sr)
{
float peak = -60;
float * b = fft->m_bands;
@@ -351,7 +367,7 @@ float EqEffect::peakBand(float minF, float maxF, FftBands *fft, int sr)
return (peak+100)/100;
}
void EqEffect::setBandPeaks(FftBands *fft, int samplerate )
void EqEffect::setBandPeaks(EqAnalyser *fft, int samplerate )
{
m_eqControls.m_lowShelfPeakR = m_eqControls.m_lowShelfPeakL =
peakBand( 0,
@@ -399,4 +415,4 @@ Plugin * PLUGIN_EXPORT lmms_plugin_main( Model* parent, void* data )
return new EqEffect( parent , static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>( data ) );
}
}}
}

View File

@@ -66,7 +66,7 @@ private:
EqLp12Filter m_lp24;
EqLp12Filter m_lp480;
EqLp12Filter m_lp481;
EqLp12Filter* m_downsampleFilters;
EqLinkwitzRiley* m_downsampleFilters;
int m_dFilterCount;
sampleFrame* m_upBuf;
fpp_t m_upBufFrames;
@@ -74,15 +74,15 @@ private:
// const static int MAX_BANDS = 249;
void upsample( sampleFrame *buf, const fpp_t frames );
void downSample( sampleFrame *buf, const fpp_t frames );
void analyze( sampleFrame *buf, const fpp_t frames, FftBands* fft );
float peakBand(float minF, float maxF,FftBands*, int);
void analyze( sampleFrame *buf, const fpp_t frames, EqAnalyser* fft );
float peakBand(float minF, float maxF,EqAnalyser*, int);
inline float bandToFreq ( int index , int sampleRate )
{
return index * sampleRate / (MAX_BANDS * 2);
}
void setBandPeaks( FftBands *fft , int);
void setBandPeaks( EqAnalyser *fft , int);
// float m_bands[MAX_BANDS];
// float m_energy;

View File

@@ -47,14 +47,6 @@ public:
m_lPeak = lPeak;
m_rPeak = rPeak;
connect( Engine::mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( updateVuMeters() ) );
m_text = 0;
QList<TextFloat*> tfs = Engine::mainWindow()->findChildren<TextFloat*>();
m_text = tfs.last();
if(m_text)
{
printf("found text float\n");
}
connect(model , SIGNAL (dataChanged()) , this, SLOT (updateText () ));
m_model = model;
}
@@ -95,16 +87,12 @@ private slots:
update();
}
void updateText()
{
m_text->setText(QString()+m_model->value());
}
private:
float* m_lPeak;
float* m_rPeak;
TextFloat* m_text;
FloatModel* m_model;
};

View File

@@ -38,74 +38,74 @@
class EqFilter : public StereoBiQuad
{
public:
EqFilter()
{
EqFilter()
{
}
}
virtual inline void setSampleRate( int sampleRate )
{
if( sampleRate != m_sampleRate )
{
m_sampleRate = sampleRate;
calcCoefficents();
}
}
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 setFrequency( float freq ){
if ( freq != m_freq )
{
m_freq = freq;
calcCoefficents();
}
}
virtual void setQ( float res )
{
if ( res != m_res )
{
m_res = res;
calcCoefficents();
}
}
virtual void setQ( float res )
{
if ( res != m_res )
{
m_res = res;
calcCoefficents();
}
}
virtual void setGain( float gain )
{
if ( gain != m_gain )
{
m_gain = gain;
calcCoefficents();
}
}
virtual void setGain( float gain )
{
if ( gain != m_gain )
{
m_gain = gain;
calcCoefficents();
}
}
///
/// \brief processBuffer
/// \param buf Audio Buffer
/// \param frames Count of sampleFrames in Audio Buffer
///
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);
}
}
///
/// \brief processBuffer
/// \param buf Audio Buffer
/// \param frames Count of sampleFrames in Audio Buffer
///
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:
///
/// \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 );
///
/// \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 );
}
}
float m_sampleRate;
float m_freq;
float m_res;
float m_gain;
float m_sampleRate;
float m_freq;
float m_res;
float m_gain;
};
@@ -118,38 +118,38 @@ protected:
class EqHp12Filter : public EqFilter
{
public :
virtual void calcCoefficents()
{
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 );
// 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
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;
//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;
//normalise
b0 /= a0;
b1 /= a0;
b2 /= a0;
a1 /= a0;
a2 /= a0;
a0 = 1;
a0 = 1;
setCoeffs( a1, a2, b0, b1, b2 );
setCoeffs( a1, a2, b0, b1, b2 );
}
}
};
@@ -161,36 +161,36 @@ public :
class EqLp12Filter : public EqFilter
{
public :
virtual void calcCoefficents()
{
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 );
// 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
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;
//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;
//normalise
b0 /= a0;
b1 /= a0;
b2 /= a0;
a1 /= a0;
a2 /= a0;
a0 = 1;
a0 = 1;
setCoeffs( a1, a2, b0, b1, b2 );
}
setCoeffs( a1, a2, b0, b1, b2 );
}
};
@@ -205,108 +205,156 @@ 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 / ( 2 * m_res );
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 a0, a1, a2, b0, b1, b2; // coeffs to calculate
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;
//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;
//normalise
b0 /= a0;
b1 /= a0;
b2 /= a0;
a1 /= a0;
a2 /= a0;
a0 = 1;
setCoeffs( a1, a2, b0, b1, b2 );
}
setCoeffs( a1, a2, b0, b1, b2 );
}
};
class EqLowShelfFilter : public EqFilter
{
public :
virtual void calcCoefficents()
{
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;
// 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
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;
//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;
//normalise
b0 /= a0;
b1 /= a0;
b2 /= a0;
a1 /= a0;
a2 /= a0;
a0 = 1;
a0 = 1;
setCoeffs( a1, a2, b0, b1, b2 );
setCoeffs( a1, a2, b0, b1, b2 );
}
}
};
class EqHighShelfFilter : public EqFilter
{
public :
virtual void calcCoefficents()
{
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;
// 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
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)
{
}
virtual inline void setSR( int sampleRate )
{
if( sampleRate != m_sr )
{
m_sr = sampleRate;
setLowpass(m_freq);
setSampleRate( sampleRate );
}
}
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;
//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 );
}
};

View File

@@ -31,19 +31,22 @@
#include "QMouseEvent"
EqParameterWidget::EqParameterWidget( QWidget *parent ) :
QWidget( parent ),
m_bands ( 0 ),
m_selectedBand ( 0 )
QWidget( parent ),
m_bands ( 0 ),
m_selectedBand ( 0 )
{
m_bands = new EqBand[8];
resize( 250, 116 );
connect( Engine::mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( update() ) );
float totalLength = log10( 21000 );
m_pixelsPerUnitWidth = width( ) / totalLength ;
m_bands = new EqBand[8];
resize( 250, 116 );
// connect( Engine::mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( update() ) );
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(200);
float totalLength = log10( 21000 );
m_pixelsPerUnitWidth = width( ) / totalLength ;
float totalHeight = 80;
m_pixelsPerUnitHeight = (height() - 4) / ( totalHeight );
m_scale = 1.5;
m_pixelsPerOctave = freqToXPixel( 10000 ) - freqToXPixel( 5000 );
m_pixelsPerUnitHeight = (height() - 4) / ( totalHeight );
m_scale = 1.5;
m_pixelsPerOctave = freqToXPixel( 10000 ) - freqToXPixel( 5000 );
}
@@ -78,39 +81,39 @@ void EqParameterWidget::paintEvent( QPaintEvent *event )
//draw 0dB line
painter.drawLine(0, gainToYPixel( 0 ) , width(), gainToYPixel( 0 ) );
for( int i = 0 ; i < bandCount() ; i++ )
{
for( int i = 0 ; i < bandCount() ; i++ )
{
m_bands[i].color.setAlpha(m_bands[i].active->value() ? activeAplha() : inactiveAlpha());
m_bands[i].color.setAlpha(m_bands[i].active->value() ? activeAplha() : inactiveAlpha());
painter.setPen( QPen( m_bands[i].color, 10, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) );
float x = freqToXPixel( m_bands[i].freq->value() );
float y = height() * 0.5;
float gain = 1;
if( m_bands[i].gain )
{
gain = m_bands[i].gain->value();
}
float x = freqToXPixel( m_bands[i].freq->value() );
float y = height() * 0.5;
float gain = 1;
if( m_bands[i].gain )
{
gain = m_bands[i].gain->value();
}
y = gainToYPixel( gain );
float bw = m_bands[i].freq->value() / m_bands[i].res->value();
m_bands[i].x = x; m_bands[i].y = y;
painter.drawPoint( x, y );
float bw = m_bands[i].freq->value() / m_bands[i].res->value();
m_bands[i].x = x; m_bands[i].y = y;
painter.drawPoint( x, y );
painter.setPen( QPen( m_bands[i].color, 3, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin ) );
if(i == 0 || i == bandCount() - 1 ){
painter.drawLine(x, y, x, y - (m_bands[i].res->value() * 4 ) );
}
else
{
painter.drawLine(freqToXPixel(m_bands[i].freq->value()-(bw * 0.5)),y,freqToXPixel(m_bands[i].freq->value()+(bw * 0.5)),y);
}
}
//Draw color band
int sectionLength = width() / bandCount();
for( int i = 0; i < bandCount(); i++)
{
m_bands[i].color.setAlpha( 255 );
painter.setPen( QPen( m_bands[i].color, 3, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) );
painter.drawLine(sectionLength * i , 1, sectionLength * (i+1) , 1);
}
if(i == 0 || i == bandCount() - 1 ){
painter.drawLine(x, y, x, y - (m_bands[i].res->value() * 4 ) );
}
else
{
painter.drawLine(freqToXPixel(m_bands[i].freq->value()-(bw * 0.5)),y,freqToXPixel(m_bands[i].freq->value()+(bw * 0.5)),y);
}
}
//Draw color band
int sectionLength = width() / bandCount();
for( int i = 0; i < bandCount(); i++)
{
m_bands[i].color.setAlpha( 255 );
painter.setPen( QPen( m_bands[i].color, 3, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) );
painter.drawLine(sectionLength * i , 1, sectionLength * (i+1) , 1);
}
}
@@ -118,11 +121,11 @@ void EqParameterWidget::paintEvent( QPaintEvent *event )
void EqParameterWidget::mousePressEvent( QMouseEvent *event )
{
m_oldX = event->x(); m_oldY = event->y();
m_selectedBand = selectNearestHandle( event->x(), event->y() );
m_mouseAction = none;
if ( event->button() == Qt::LeftButton ) m_mouseAction = drag;
if ( event->button() == Qt::RightButton ) m_mouseAction = res;
m_oldX = event->x(); m_oldY = event->y();
m_selectedBand = selectNearestHandle( event->x(), event->y() );
m_mouseAction = none;
if ( event->button() == Qt::LeftButton ) m_mouseAction = drag;
if ( event->button() == Qt::RightButton ) m_mouseAction = res;
}
@@ -130,8 +133,8 @@ void EqParameterWidget::mousePressEvent( QMouseEvent *event )
void EqParameterWidget::mouseReleaseEvent( QMouseEvent *event )
{
m_selectedBand = 0;
m_mouseAction = none;
m_selectedBand = 0;
m_mouseAction = none;
}
@@ -139,26 +142,26 @@ void EqParameterWidget::mouseReleaseEvent( QMouseEvent *event )
void EqParameterWidget::mouseMoveEvent( QMouseEvent *event )
{
int deltaX = event->x() - m_oldX;
int deltaR = event->y() - m_oldY;
m_oldX = event->x(); m_oldY = event->y();
if(m_selectedBand && m_selectedBand->active->value() )
{
switch ( m_mouseAction ) {
case none :
break;
case drag:
if( m_selectedBand->freq ) m_selectedBand->freq->setValue( xPixelToFreq( m_oldX ) );
if( m_selectedBand->gain )m_selectedBand->gain->setValue( yPixelToGain( m_oldY ) );
break;
case res:
if( m_selectedBand->res )m_selectedBand->res->incValue( deltaX * resPixelMultiplyer() );
if( m_selectedBand->res )m_selectedBand->res->incValue( (-deltaR) * resPixelMultiplyer() );
break;
default:
break;
}
}
int deltaX = event->x() - m_oldX;
int deltaR = event->y() - m_oldY;
m_oldX = event->x(); m_oldY = event->y();
if(m_selectedBand && m_selectedBand->active->value() )
{
switch ( m_mouseAction ) {
case none :
break;
case drag:
if( m_selectedBand->freq ) m_selectedBand->freq->setValue( xPixelToFreq( m_oldX ) );
if( m_selectedBand->gain )m_selectedBand->gain->setValue( yPixelToGain( m_oldY ) );
break;
case res:
if( m_selectedBand->res )m_selectedBand->res->incValue( deltaX * resPixelMultiplyer() );
if( m_selectedBand->res )m_selectedBand->res->incValue( (-deltaR) * resPixelMultiplyer() );
break;
default:
break;
}
}
}
@@ -166,11 +169,11 @@ void EqParameterWidget::mouseMoveEvent( QMouseEvent *event )
void EqParameterWidget::mouseDoubleClickEvent( QMouseEvent *event )
{
EqBand* selected = selectNearestHandle( event->x() , event->y() );
if( selected )
{
selected->active->setValue( selected->active->value() ? 0 : 1 );
}
EqBand* selected = selectNearestHandle( event->x() , event->y() );
if( selected )
{
selected->active->setValue( selected->active->value() ? 0 : 1 );
}
}
@@ -178,39 +181,39 @@ void EqParameterWidget::mouseDoubleClickEvent( QMouseEvent *event )
EqBand* EqParameterWidget::selectNearestHandle( const int x, const int y )
{
EqBand* selectedModel = 0;
float* distanceToHandles = new float[bandCount()];
//calc distance to each handle
for( int i = 0 ; i < bandCount() ; i++)
{
int xOffset = m_bands[i].x - x;
int yOffset = m_bands[i].y - y;
distanceToHandles[i] = fabs(sqrt((xOffset * xOffset ) + ( yOffset * yOffset ) ) );
}
//select band
int shortestBand = 0;
for (int i = 1 ; i < bandCount() ; i++ )
{
if ( distanceToHandles [i] < distanceToHandles[shortestBand] ){
shortestBand = i;
}
}
if(distanceToHandles[shortestBand] < maxDistanceFromHandle() )
{
selectedModel = &m_bands[shortestBand];
}
delete distanceToHandles;
return selectedModel;
EqBand* selectedModel = 0;
float* distanceToHandles = new float[bandCount()];
//calc distance to each handle
for( int i = 0 ; i < bandCount() ; i++)
{
int xOffset = m_bands[i].x - x;
int yOffset = m_bands[i].y - y;
distanceToHandles[i] = fabs(sqrt((xOffset * xOffset ) + ( yOffset * yOffset ) ) );
}
//select band
int shortestBand = 0;
for (int i = 1 ; i < bandCount() ; i++ )
{
if ( distanceToHandles [i] < distanceToHandles[shortestBand] ){
shortestBand = i;
}
}
if(distanceToHandles[shortestBand] < maxDistanceFromHandle() )
{
selectedModel = &m_bands[shortestBand];
}
delete distanceToHandles;
return selectedModel;
}
EqBand::EqBand() :
gain ( 0 ),
res ( 0 ),
freq ( 0 ),
color ( QColor( 255, 255, 255 ) ),
name ( QString( "" ) )
gain ( 0 ),
res ( 0 ),
freq ( 0 ),
color ( QColor( 255, 255, 255 ) ),
name ( QString( "" ) )
{
}

View File

@@ -1,3 +1,26 @@
/* eqspectrumview.h - defination of EqSpectrumView class.
*
* Copyright (c) 2014 David French <dave/dot/french3/at/googlemail/dot/com>
*
* 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 EQSPECTRUMVIEW_H
#define EQSPECTRUMVIEW_H
@@ -5,11 +28,12 @@
//#include "eqeffect.h"
#include "qwidget.h"
#include "fft_helpers.h"
#include "Engine.h"
const int MAX_BANDS = 512;
const int MAX_BANDS = 2048;
class FftBands
class EqAnalyser
{
public:
@@ -24,15 +48,76 @@ public:
float m_energy;
int m_sr;
FftBands() :
m_framesFilledUp( 0 ),
m_energy( 0 )
{
memset( m_buffer, 0, sizeof( m_buffer ) );
EqAnalyser()
{
m_inProgress=false;
clear();
}
bool getInProgress()
{
return m_inProgress;
}
void clear()
{
m_framesFilledUp = 0;
m_energy = 0;
memset( m_buffer, 0, sizeof( m_buffer ) );
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 );
}
void analyze(sampleFrame *buf, const fpp_t frames )
{
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_sr = Engine::mixer()->processingSampleRate();
const int LOWEST_FREQ = 0;
const int HIGHEST_FREQ = m_sr / 2;
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_sr /2)),
(int)(HIGHEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(m_sr /2)));
m_energy = maximum( m_bands, MAX_BANDS ) / maximum( m_buffer, FFT_BUFFER_SIZE );
m_framesFilledUp = 0;
m_inProgress = false;
}
private:
bool m_inProgress;
};
@@ -40,12 +125,15 @@ class EqSpectrumView : public QWidget
{
public:
explicit EqSpectrumView( FftBands * b, QWidget * _parent = 0) :
explicit EqSpectrumView( EqAnalyser * b, QWidget * _parent = 0) :
QWidget( _parent ),
m_sa( b )
{
setFixedSize( 250, 116 );
connect( Engine::mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( update() ) );
// connect( Engine::mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( update() ) );
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(2000);
setAttribute( Qt::WA_TranslucentBackground, true );
m_skipBands = MAX_BANDS * 0.5;
float totalLength = log10( 21000);
@@ -59,47 +147,37 @@ public:
{
}
QColor color;
FftBands *m_sa;
int m_lastY;
EqAnalyser *m_sa;
QPainterPath pp;
virtual void paintEvent( QPaintEvent* event )
{
const int fh = height();
const int LOWER_Y = -96; // dB
int m_lastY = height();
const int LOWER_Y = -60; // dB
QPainter p( this );
p.setPen( QPen( color, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) );
//draw grid lines
int y33 = (int)( fh * 2.0 / 3.0 * (20*(log10( 0.33 ) ) - LOWER_Y ) / (-LOWER_Y ) );
p.drawLine(0, y33, width(), y33);
const float e = m_sa->m_energy;
if( e <= 0 )
{
//dont draw anything
return;
}
if(m_sa->getInProgress() ){
p.fillPath( pp ,QBrush( color ) );
return;
}
pp = QPainterPath();
float * b = m_sa->m_bands;
int h;
bool linX = true;
if( linX )
pp.moveTo( 0,height() );
for( int x = 0; x < MAX_BANDS; ++x, ++b )
{
for( int x = 0; x < MAX_BANDS; ++x, ++b )
{
h = (int)( fh * 2.0 / 3.0 * (20*(log10( *b / e ) ) - LOWER_Y ) / (-LOWER_Y ) );
if( h < 0 ) h = 0; else if( h >= fh ) continue;
p.drawLine(freqToXPixel(bandToFreq(x -1 ) ),m_lastY, freqToXPixel(bandToFreq(x ) ), fh-h );
m_lastY = fh-h;
}
}
else
{
for( int x = 0; x < 31; ++x, ++b )
{
h = (int)( fh * 2.0 / 3.0 * (20*(log10( *b / e ) ) - LOWER_Y ) / (-LOWER_Y ) );
if( h < 0 ) h = 0; else if( h >= fh ) continue; else h = ( h / 3 ) * 3;
p.drawPoint(x * 8, fh-h );
}
h = (int)( fh * 2.0 / 3.0 * (20*(log10( *b / e ) ) - LOWER_Y ) / (-LOWER_Y ) );
if( h < 0 ) h = 0; else if( h >= fh ) continue;
pp.lineTo( freqToXPixel(bandToFreq(x ) ), fh-h );
}
pp.lineTo(width(), height() );
pp.closeSubpath();
p.fillPath( pp ,QBrush( color ) );
}