audacia/src/effects/BassBoost.cpp

291 lines
7.4 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
BassBoost.cpp
Effect programming:
Nasca Octavian Paul
UI programming:
Dominic Mazzoni (with the help of wxDesigner)
Vaughan Johnson (Preview)
*******************************************************************//**
\class EffectBassBoost
\brief An EffectSimpleMono
*//****************************************************************//**
\class BassBoostDialog
\brief Dialog for EffectBassBoost
*//*******************************************************************/
#include "../Audacity.h"
#include "BassBoost.h"
#include "../WaveTrack.h"
#include <wx/button.h>
#include <wx/msgdlg.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/valtext.h>
#include <math.h>
//
// EffectBassBoost
//
EffectBassBoost::EffectBassBoost()
{
frequency = 200;
dB_boost = 12;
}
wxString EffectBassBoost::GetEffectDescription() {
// Note: This is useful only after values have been set.
return wxString::Format(_("Applied effect: %s frequency = %.0f Hz, boost = %.0f dB"),
this->GetEffectName().c_str(), frequency, dB_boost);
}
bool EffectBassBoost::NewTrackSimpleMono()
{
//(re)initialise filter parameters
xn1=0;
xn2=0;
yn1=0;
yn2=0;
/* Compute coefficents of the biquand IIR filter */
omega = 2 * 3.141592653589 * frequency / mCurRate;
sn = sin(omega);
cs = cos(omega);
a = exp(log(10.0) * dB_boost / 40);
shape = float(1.0); /*Low Shelf filter's shape, if this is too large
or too small it will result an unstable filter */
beta = sqrt((a * a + 1) / shape - (pow((a - 1), 2)));
/* Coefficients */
b0 = a * ((a + 1) - (a - 1) * cs + beta * sn);
b1 = 2 * a * ((a - 1) - (a + 1) * cs);
b2 = a * ((a + 1) - (a - 1) * cs - beta * sn);
a0 = ((a + 1) + (a - 1) * cs + beta * sn);
a1 = -2 * ((a - 1) + (a + 1) * cs);
a2 = (a + 1) + (a - 1) * cs - beta * sn;
return true;
}
bool EffectBassBoost::PromptUser()
{
BassBoostDialog dlog(this, mParent);
dlog.freq = frequency;
dlog.boost = dB_boost;
dlog.TransferDataToWindow();
dlog.CentreOnParent();
dlog.ShowModal();
if (dlog.GetReturnCode() == wxID_CANCEL)
return false;
frequency = dlog.freq;
dB_boost = dlog.boost;
return true;
}
bool EffectBassBoost::TransferParameters( Shuttle & shuttle )
{
shuttle.TransferFloat(wxT("Boost"),dB_boost,0.0);
shuttle.TransferFloat(wxT("Freq"),frequency,0.0);
return true;
}
bool EffectBassBoost::ProcessSimpleMono(float *buffer, sampleCount len)
{
/* initialise the filter */
float out, in = 0;
for (int i = 0; i < len; i++) {
in = buffer[i];
out = (b0 * in + b1 * xn1 + b2 * xn2 - a1 * yn1 - a2 * yn2) / a0;
xn2 = xn1;
xn1 = in;
yn2 = yn1;
yn1 = out;
if (out < -1.0)
out = float(-1.0);
else if (out > 1.0)
out = float(1.0); //Prevents clipping
buffer[i] = out;
}
return true;
}
// WDR: class implementations
//----------------------------------------------------------------------------
// BassBoostDialog
//----------------------------------------------------------------------------
const static wxChar *numbers[] =
{
wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"),
wxT("5"), wxT("6"), wxT("7"), wxT("8"), wxT("9")
};
// Declare window functions
#define ID_FREQ_TEXT 10001
#define ID_FREQ_SLIDER 10002
#define ID_BOOST_TEXT 10003
#define ID_BOOST_SLIDER 10004
// Declare ranges
#define FREQ_MIN 1
#define FREQ_MAX 1000
#define BOOST_MIN 0
#define BOOST_MAX 36
BEGIN_EVENT_TABLE(BassBoostDialog, EffectDialog)
EVT_SLIDER(ID_FREQ_SLIDER, BassBoostDialog::OnFreqSlider)
EVT_SLIDER(ID_BOOST_SLIDER, BassBoostDialog::OnBoostSlider)
EVT_TEXT(ID_FREQ_TEXT, BassBoostDialog::OnFreqText)
EVT_TEXT(ID_BOOST_TEXT, BassBoostDialog::OnBoostText)
EVT_BUTTON(ID_EFFECT_PREVIEW, BassBoostDialog::OnPreview)
END_EVENT_TABLE()
BassBoostDialog::BassBoostDialog(EffectBassBoost *effect,
wxWindow * parent):
EffectDialog(parent, _("Bass Boost"), PROCESS_EFFECT),
mEffect(effect)
{
Init();
}
void BassBoostDialog::PopulateOrExchange(ShuttleGui & S)
{
wxTextValidator vld(wxFILTER_INCLUDE_CHAR_LIST);
vld.SetIncludes(wxArrayString(10, numbers));
S.StartHorizontalLay(wxCENTER, false);
{
S.AddTitle(_("by Nasca Octavian Paul"));
}
S.EndHorizontalLay();
S.StartHorizontalLay(wxCENTER, false);
{
// Add a little space
}
S.EndHorizontalLay();
S.StartMultiColumn(3, wxEXPAND);
S.SetStretchyCol(2);
{
// Frequency
mFreqT = S.Id(ID_FREQ_TEXT).AddTextBox(_("Frequency (Hz):"),
wxT(""),
10);
mFreqT->SetValidator(vld);
S.SetStyle(wxSL_HORIZONTAL);
mFreqS = S.Id(ID_FREQ_SLIDER).AddSlider(wxT(""),
0,
FREQ_MAX);
mFreqS->SetName(_("Frequency Hertz"));
mFreqS->SetRange(FREQ_MIN, FREQ_MAX);
// Boost
mBoostT = S.Id(ID_BOOST_TEXT).AddTextBox(_("Boost (dB):"),
wxT(""),
10);
mBoostT->SetValidator(vld);
S.SetStyle(wxSL_HORIZONTAL);
mBoostS = S.Id(ID_BOOST_SLIDER).AddSlider(wxT(""),
0,
BOOST_MAX);
mBoostS->SetName(_("Boost dB"));
mBoostS->SetRange(BOOST_MIN, BOOST_MAX);
}
S.EndMultiColumn();
return;
}
bool BassBoostDialog::TransferDataToWindow()
{
mBoostS->SetValue((int)boost);
mFreqS->SetValue((int)freq);
mBoostT->SetValue(wxString::Format(wxT("%d"), (int) boost));
mFreqT->SetValue(wxString::Format(wxT("%d"), (int) freq));
return true;
}
bool BassBoostDialog::TransferDataFromWindow()
{
boost = TrapLong(mBoostS->GetValue(), BOOST_MIN, BOOST_MAX);
freq = TrapLong(mFreqS->GetValue(), FREQ_MIN, FREQ_MAX);
return true;
}
// WDR: handler implementations for BassBoostDialog
void BassBoostDialog::OnBoostText(wxCommandEvent & event)
{
long val;
mBoostT->GetValue().ToLong(&val);
mBoostS->SetValue(TrapLong(val, BOOST_MIN, BOOST_MAX));
}
void BassBoostDialog::OnFreqText(wxCommandEvent & event)
{
long val;
mFreqT->GetValue().ToLong(&val);
mFreqS->SetValue(TrapLong(val, FREQ_MIN, FREQ_MAX));
}
void BassBoostDialog::OnBoostSlider(wxCommandEvent & event)
{
mBoostT->SetValue(wxString::Format(wxT("%d"), mBoostS->GetValue()));
}
void BassBoostDialog::OnFreqSlider(wxCommandEvent & event)
{
mFreqT->SetValue(wxString::Format(wxT("%d"), mFreqS->GetValue()));
}
void BassBoostDialog::OnPreview(wxCommandEvent & event)
{
TransferDataFromWindow();
mEffect->frequency = freq;
mEffect->dB_boost = boost;
mEffect->Preview();
}
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
// version control system. Please do not modify past this point.
//
// Local Variables:
// c-basic-offset: 3
// indent-tabs-mode: nil
// End:
//
// vim: et sts=3 sw=3
// arch-tag: 25dfd7cb-9e1b-4c8d-a188-ed406c2b51b7