769 lines
24 KiB
C++
769 lines
24 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
AvcCompressor.cpp
|
|
|
|
Vincent A. Busam
|
|
|
|
*******************************************************************//**
|
|
|
|
\class EffectAvcCompressor
|
|
\brief An unused Effect (we use EffectCompressor instead) derived
|
|
from EffectSimplePairedTwoTrackBase
|
|
|
|
*//****************************************************************//**
|
|
|
|
\class iAVCBufferList
|
|
\brief An unused class used by EffectAvcCompressor.
|
|
|
|
*//****************************************************************//**
|
|
|
|
\class AvcCompressorDialog
|
|
\brief An unused class used by unused effect, EffectAvcCompressor.
|
|
|
|
*//*******************************************************************/
|
|
/* TODO List:
|
|
|
|
1. Add graph shows curve specified by grid, keep it up to date,
|
|
allow setting of grid points by moving points in grid.
|
|
2. Better help
|
|
3. Radio button selection so Adjustment Settings can be times instead
|
|
of samples.
|
|
4. Radio button selection so Amplification Settings can be db instead
|
|
of raw values.
|
|
5. Save settings by name
|
|
6. Remove "help" text in window when Audacity help available.
|
|
|
|
*/
|
|
|
|
#include <math.h>
|
|
|
|
#include <wx/defs.h>
|
|
#include <wx/msgdlg.h>
|
|
#include <wx/textdlg.h>
|
|
#include <wx/dcmemory.h>
|
|
|
|
#include "../WaveTrack.h"
|
|
#include "../Envelope.h"
|
|
#include "../widgets/Ruler.h"
|
|
#include "../Prefs.h"
|
|
|
|
// Including the following cpp file is quite unorthodox, but it gives the opportunity to
|
|
// use iAVC's capability of generating inline code for the important methods. We
|
|
// can't trust compilers to generated inline code, even when the inline keyword is
|
|
// used.
|
|
#ifdef _WINDOWS // kludge for Audacity since we don't really have MS Windows
|
|
#define max(a,b) ( (a<b)?b:a )
|
|
#endif
|
|
|
|
//!!!!!!!!!!!!!!!!!!!!!!!!! I M P O R T A N T !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
// IMPORTANT: This define determines if iAVC generates in line code.
|
|
//#define IAVC_INLINE // use inline code for get and put of samples
|
|
|
|
#include "AvcCompressor.h"
|
|
|
|
#include "../../lib-src/iAVC/iAVCsamples.h"
|
|
#include "../../lib-src/iAVC/iAVC.cpp"
|
|
|
|
#define ADJWIN_DEFAULT DEFAULT_ADJUSTER_WINDOW_SIZE
|
|
#define ADJWIN_MIN 1000
|
|
#define ADJWIN_MAX 10000
|
|
|
|
#define DELAY_DEFAULT DEFAULT_MINIMUM_SAMPLES_BEFORE_SWITCH
|
|
#define DELAY_MIN 0
|
|
#define DELAY_MAX 5000
|
|
|
|
#define CHANGE_DEFAULT DEFAULT_MINIMUM_SAMPLES_BEFORE_SWITCH
|
|
#define CHANGE_MIN 1000
|
|
#define CHANGE_MAX 5000
|
|
|
|
#define MINPCT_DEFAULT DEFAULT_MAX_PCT_CHANGE_AT_ONCE
|
|
#define MINPCT_MIN 5
|
|
#define MINPCT_MAX 50
|
|
|
|
EffectAvcCompressor::EffectAvcCompressor():
|
|
mpBufferList ( NULL ),
|
|
mpBufferPrevious ( NULL ),
|
|
mnDelay ( 0 ),
|
|
mpDialog ( NULL )
|
|
{
|
|
}
|
|
|
|
EffectAvcCompressor::~EffectAvcCompressor()
|
|
{
|
|
if ( mpDialog != NULL )
|
|
delete mpDialog;
|
|
}
|
|
|
|
wxString EffectAvcCompressor::GetEffectDescription() {
|
|
return "Applied effect: AVC"; // XXX: temporary
|
|
|
|
// Note: This is useful only after values have been set.
|
|
|
|
// FIX-ME: Compile error (cannot pass wxString to Format).
|
|
//return wxString::Format(_("Applied effect: %s"),
|
|
// this->GetEffectDescription());
|
|
|
|
//old
|
|
//return wxString::Format("Applied effect: %s change window = %d samples",
|
|
//(const char *)(this->GetEffectName()), mnChangeWindow);
|
|
}
|
|
|
|
inline
|
|
void EffectAvcCompressor::OutputSample ( IAVCSAMPLETYPE left, IAVCSAMPLETYPE right )
|
|
{
|
|
if ( mpBufferList->mnNext >= mpBufferList->mnLen )
|
|
{ // have filled up this buffer, move to next
|
|
iAVCBufferList * pOld = mpBufferList;
|
|
mpBufferList = mpBufferList->mpNext;
|
|
delete pOld;
|
|
}
|
|
if ( mpBufferList == NULL )
|
|
return;
|
|
|
|
// set the output sample values
|
|
((IAVCSAMPLETYPE*)mpBufferList->mpLeftBuffer)[mpBufferList->mnNext] = left;
|
|
if ( mpBufferList->mpRightBuffer )
|
|
((IAVCSAMPLETYPE*)mpBufferList->mpRightBuffer)[mpBufferList->mnNext] = right;
|
|
|
|
++mpBufferList->mnNext;
|
|
}
|
|
|
|
|
|
bool EffectAvcCompressor::PromptUser()
|
|
{
|
|
if ( mpDialog == NULL ) // reuse dialog so we keep user changes to values
|
|
mpDialog = new AvcCompressorDialog(mParent, -1, wxT("Automatic Volume Control"));
|
|
|
|
mpDialog->CentreOnParent();
|
|
mpDialog->ShowModal();
|
|
|
|
if (!mpDialog->GetReturnCode())
|
|
return false;
|
|
|
|
mAutoVolCtrl.Reset(); // reset control before setting values
|
|
|
|
// Set parameters for iAVC class
|
|
unsigned short int *nTransform = new unsigned short int [ MULTIPLY_PCT_ARRAY_SIZE ];
|
|
mnChangeWindow=mpDialog->GetChangeWindow();
|
|
mpDialog->GetTransformArray(nTransform);
|
|
|
|
if ( mAutoVolCtrl.SetSampleWindowSize(mpDialog->GetAdjusterWindow()+mnChangeWindow,
|
|
mpDialog->GetAdjusterWindow(),
|
|
0) == false ||
|
|
mAutoVolCtrl.SetMinSamplesBeforeSwitch(mnChangeWindow) == false ) {
|
|
wxMessageBox("Error setting parameters for automatic volume control.");
|
|
return false;
|
|
}
|
|
mAutoVolCtrl.SetMaxPctChangeAtOnce(mpDialog->GetMinimumPercent());
|
|
mAutoVolCtrl.SetMultipliers(nTransform);
|
|
mAutoVolCtrl.SetNumberTracks(mnTracks);
|
|
mnDelay = mpDialog->GetDelay();
|
|
|
|
delete [] nTransform;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool EffectAvcCompressor::TransferParameters( Shuttle & shuttle )
|
|
{
|
|
wxASSERT( false );// Not yet implemented.
|
|
// shuttle.TransferInt("",,0);
|
|
return true;
|
|
}
|
|
|
|
bool EffectAvcCompressor::Init() // invoked before PromptUser
|
|
{
|
|
if ( EffectSimplePairedTwoTrack<IAVCSAMPLETYPE,AVCCOMPSAMPLETYPE>::Init() == false )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool EffectAvcCompressor::ProcessSimplePairedTwoTrack(/*IAVCSAMPLETYPE*/ void *bufferLeft,
|
|
/*IAVCSAMPLETYPE*/ void *bufferRight, // may be 0
|
|
sampleCount len)
|
|
{
|
|
// build new iAVCBufferList node
|
|
iAVCBufferList * pBufferNode = new iAVCBufferList;
|
|
if ( mpBufferPrevious != NULL )
|
|
mpBufferPrevious->mpNext = pBufferNode; // link to end of list
|
|
else
|
|
mpBufferList = pBufferNode; // have first node in list
|
|
mpBufferPrevious = pBufferNode; // this node now the last added to list
|
|
pBufferNode->mpNext = NULL;
|
|
pBufferNode->mpLeftBuffer = bufferLeft;
|
|
pBufferNode->mpRightBuffer = bufferRight;
|
|
pBufferNode->mnLen = len;
|
|
pBufferNode->mnNext = 0;
|
|
|
|
// process samples in these buffer(s)
|
|
IAVCSAMPLETYPE* typedBufferLeft = (IAVCSAMPLETYPE*)bufferLeft;
|
|
IAVCSAMPLETYPE* typedBufferRight = (IAVCSAMPLETYPE*)bufferRight;
|
|
sampleCount i;
|
|
IAVCSAMPLETYPE left;
|
|
IAVCSAMPLETYPE right = 0;
|
|
|
|
for ( i = 0 ; i < len ; ++i ) {
|
|
left = typedBufferLeft[i];
|
|
if ( typedBufferRight )
|
|
right = typedBufferRight[i];
|
|
#ifdef IAVC_INLINE
|
|
// use inline SetNextSample()
|
|
#define IAVC_SETNEXTSAMPLE
|
|
#include "../../lib-src/iAVC/iAVC.cpp"
|
|
#undef IAVC_SETNEXTSAMPLE
|
|
// use inline GetNextSample()
|
|
if ( mnDelay <= 0 )
|
|
{ // get a value only if past desired delay
|
|
#define IAVC_GETNEXTSAMPLE
|
|
#include "../../lib-src/iAVC/iAVC.cpp"
|
|
#undef IAVC_SETNEXTSAMPLE
|
|
}
|
|
#else
|
|
// call SetNextSample() and GetNextSample()
|
|
mAutoVolCtrl.SetNextSample(left, right);
|
|
if ( mnDelay <= 0 )
|
|
{ // get a value only if past desired delay
|
|
mAutoVolCtrl.GetNextSample(left, right);
|
|
}
|
|
#endif
|
|
if ( mnDelay <= 0 )
|
|
{ // get a value only if past desired delay
|
|
OutputSample ( left, right );
|
|
typedBufferLeft[i] = left;
|
|
if ( typedBufferRight )
|
|
typedBufferRight[i] = right;
|
|
}
|
|
else
|
|
{ // count down the delay amount
|
|
--mnDelay;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void EffectAvcCompressor::End()
|
|
{
|
|
IAVCSAMPLETYPE left;
|
|
IAVCSAMPLETYPE right = 0;
|
|
|
|
// We now need to output any samples still waiting because
|
|
while ( mpBufferList != NULL )
|
|
{
|
|
#ifdef IAVC_INLINE
|
|
// use inline GetNextSample()
|
|
#define IAVC_GETNEXTSAMPLE
|
|
#include "../../lib-src/iAVC/iAVC.cpp"
|
|
#undef IAVC_SETNEXTSAMPLE
|
|
#else
|
|
// call GetNextSample()
|
|
mAutoVolCtrl.GetNextSample(left, right);
|
|
#endif
|
|
|
|
OutputSample ( left, right );
|
|
}
|
|
mpBufferPrevious = NULL;
|
|
|
|
EffectSimplePairedTwoTrack<IAVCSAMPLETYPE,AVCCOMPSAMPLETYPE>::End();
|
|
}
|
|
|
|
// WDR: class implementations
|
|
|
|
//----------------------------------------------------------------------------
|
|
// AvcCompressorDialog
|
|
//----------------------------------------------------------------------------
|
|
|
|
#define PREF_ADJWIN "/Effect/AVC/user1/adjwin"
|
|
#define PREF_DELAY "/Effect/AVC/user1/delay"
|
|
#define PREF_CHANGE "/Effect/AVC/user1/change"
|
|
#define PREF_MINPCT "/Effect/AVC/user1/minpct"
|
|
#define PREF_ENABLE "/Effect/AVC/user1/%d/enable"
|
|
#define PREF_HORIZ "/Effect/AVC/user1/%d/horiz"
|
|
#define PREV_VERT "/Effect/AVC/user1/%d/vert"
|
|
|
|
|
|
// WDR: event table for AvcCompressorDialog
|
|
|
|
BEGIN_EVENT_TABLE(AvcCompressorDialog,wxDialog)
|
|
EVT_BUTTON( wxID_OK, AvcCompressorDialog::OnOK )
|
|
EVT_BUTTON( wxID_CANCEL, AvcCompressorDialog::OnCancel )
|
|
EVT_BUTTON( ID_RESTORE_DEFAULTS, AvcCompressorDialog::OnRestoreDefaults )
|
|
EVT_CHECKBOX(ID_FIRST_CURVE_CHECK+1, AvcCompressorDialog::OnCheckBox)
|
|
EVT_CHECKBOX(ID_FIRST_CURVE_CHECK+2, AvcCompressorDialog::OnCheckBox)
|
|
EVT_CHECKBOX(ID_FIRST_CURVE_CHECK+3, AvcCompressorDialog::OnCheckBox)
|
|
EVT_CHECKBOX(ID_FIRST_CURVE_CHECK+4, AvcCompressorDialog::OnCheckBox)
|
|
EVT_CHECKBOX(ID_FIRST_CURVE_CHECK+5, AvcCompressorDialog::OnCheckBox)
|
|
END_EVENT_TABLE()
|
|
|
|
AvcCompressorDialog::AvcCompressorDialog(wxWindow *parent, wxWindowID id,
|
|
const wxString &title,
|
|
const wxPoint &position, const wxSize& size,
|
|
long style ) :
|
|
wxDialog( parent, id, title, position, size, style ),
|
|
mctlAdjWin ( 0 ),
|
|
mctlDelay ( 0 ),
|
|
mctlChangeWin ( 0 ),
|
|
mctlMinPct ( 0 )
|
|
{
|
|
for ( int i = 0 ; i < NUM_CURVE_POINTS ; ++i ) {
|
|
mctlCheckBoxes[i] = 0;
|
|
mctlXAxis[i] = 0;
|
|
mctlYAxis[i] = 0;
|
|
}
|
|
|
|
MakeAvcCompressorDialog( this, TRUE );
|
|
|
|
// First make sure all value initialized, especially horiz and vert first & last values
|
|
wxCommandEvent event;
|
|
OnRestoreDefaults(event);
|
|
// Now read in from registry
|
|
ReadPrefs();
|
|
}
|
|
|
|
AvcCompressorDialog::~AvcCompressorDialog()
|
|
{ // zero out pointers in case reference counts being used
|
|
mctlAdjWin = 0;
|
|
mctlDelay = 0;
|
|
mctlChangeWin = 0;
|
|
mctlMinPct = 0;
|
|
|
|
for ( int i = 0 ; i < NUM_CURVE_POINTS ; ++i ) {
|
|
mctlCheckBoxes[i] = 0;
|
|
mctlXAxis[i] = 0;
|
|
mctlYAxis[i] = 0;
|
|
}
|
|
}
|
|
|
|
// figure out Y value for each possible X value
|
|
void AvcCompressorDialog::GetTransformArray( unsigned short int nTransform[MULTIPLY_PCT_ARRAY_SIZE] )
|
|
{
|
|
long iCurPoint = 0; // index to mnXAxis and mnYAxis
|
|
long iPrevPoint= 0; // index to mnXAxis and mnYAxis
|
|
long iMultiply = 1; // iMultiply and iDivide used to calculate fractional slopes
|
|
long iDivide = 1;
|
|
long iBias = 0; // keeps values from decreasing
|
|
|
|
nTransform [ 0 ] = 0;
|
|
|
|
for ( long i = 0 ; i < MULTIPLY_PCT_ARRAY_SIZE - 1 ; ++i ) {
|
|
if ( i == mnXAxis [ iCurPoint ] && iCurPoint < NUM_CURVE_POINTS - 1 ) {
|
|
// time to move to next point
|
|
iPrevPoint = iCurPoint;
|
|
// find next checked point
|
|
while ( mctlCheckBoxes[++iCurPoint]->GetValue() == false)
|
|
; // last box guaranteed to be checked
|
|
// Recalculate bias based on what would be calculated with old values and
|
|
// what would be calculated with new values.
|
|
long iOld = i * iMultiply / iDivide + iBias;
|
|
|
|
iMultiply = mnYAxis [ iCurPoint ] - mnYAxis [ iPrevPoint ];
|
|
iDivide = mnXAxis [ iCurPoint ] - mnXAxis [ iPrevPoint ];
|
|
|
|
iBias = iOld - ( i * iMultiply / iDivide );
|
|
}
|
|
nTransform [ i ] = (unsigned short int)
|
|
( i * iMultiply / iDivide + iBias );
|
|
}
|
|
// set boundary case for loudest sound
|
|
nTransform [ MULTIPLY_PCT_ARRAY_SIZE - 1 ] = MULTIPLY_PCT_ARRAY_SIZE - 1;
|
|
}
|
|
|
|
bool AvcCompressorDialog::LongRangeCheck ( wxWindow *window,
|
|
const long nValue,
|
|
const long nMin,
|
|
const long nMax )
|
|
{
|
|
if ( nValue < nMin || nValue > nMax ) {
|
|
// value out of range
|
|
if ( !wxValidator::IsSilent() )
|
|
wxBell();
|
|
wxString strTemp;
|
|
strTemp.Printf ( wxT("Value must be from %d to %d."), nMin, nMax );
|
|
wxMessageBox(strTemp, wxT("Validation error"),
|
|
wxOK | wxICON_EXCLAMATION, GetParent() );
|
|
if ( window )
|
|
window->SetFocus();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// WDR: handler implementations for AvcCompressorDialog
|
|
|
|
void AvcCompressorDialog::OnOK(wxCommandEvent &event)
|
|
{
|
|
if ( Validate() && TransferDataFromWindow() ) {
|
|
// do our dialog specific validation
|
|
|
|
// Check Adjustment Settings
|
|
mstrAdjWin.ToLong(&mnAdjWin);
|
|
if ( LongRangeCheck( mctlAdjWin, mnAdjWin, ADJWIN_MIN, ADJWIN_MAX ) == false ) {
|
|
// value out of range
|
|
return;
|
|
}
|
|
|
|
mstrDelay.ToLong(&mnDelay);
|
|
if ( LongRangeCheck( mctlDelay, mnDelay, DELAY_MIN, DELAY_MAX ) == false ) {
|
|
// value out of range
|
|
return;
|
|
}
|
|
|
|
mstrChangeWin.ToLong(&mnChangeWin);
|
|
if ( LongRangeCheck( mctlChangeWin, mnChangeWin, CHANGE_MIN, CHANGE_MAX ) == false ) {
|
|
// value out of range
|
|
return;
|
|
}
|
|
|
|
if ( mnChangeWin > mnAdjWin ) {
|
|
wxMessageBox(wxT("Change window size must be less than or equal to Adjustment window size."),
|
|
wxT("Validation error"), wxOK | wxICON_EXCLAMATION, GetParent() );
|
|
if ( mctlChangeWin )
|
|
mctlChangeWin->SetFocus();
|
|
return;
|
|
}
|
|
|
|
mstrMinPct.ToLong(&mnMinPct);
|
|
if ( LongRangeCheck( mctlMinPct, mnMinPct, MINPCT_MIN, MINPCT_MAX ) == false ) {
|
|
// value out of range
|
|
return;
|
|
}
|
|
|
|
// Check Amplification Settings
|
|
long iPrevPoint= 0; // index to mnXAxis and mnYAxis
|
|
for ( int i = 0 ; i < NUM_CURVE_POINTS ; ++i ) {
|
|
mstrXAxis[i].ToLong(&mnXAxis[i]);
|
|
mstrYAxis[i].ToLong(&mnYAxis[i]);
|
|
|
|
// see if this is a checked point
|
|
if ( mctlCheckBoxes[i]->GetValue() == false)
|
|
continue; // last box guaranteed to be checked
|
|
|
|
if ( i > 0 ) {
|
|
if ( mnXAxis[i] <= mnXAxis[iPrevPoint] ) {
|
|
wxMessageBox(wxT("Values in columns must be in ascending order."),
|
|
wxT("Validation error"),
|
|
wxOK | wxICON_EXCLAMATION, GetParent() );
|
|
mctlXAxis[(i==NUM_CURVE_POINTS-1) ? iPrevPoint : i]->SetFocus();
|
|
return;
|
|
}
|
|
if ( mnYAxis[i] <= mnYAxis[iPrevPoint] ) {
|
|
wxMessageBox(wxT("Values in columns must be in ascending order."),
|
|
wxT("Validation error"),
|
|
wxOK | wxICON_EXCLAMATION, GetParent() );
|
|
mctlYAxis[(i==NUM_CURVE_POINTS-1) ? iPrevPoint : i]->SetFocus();
|
|
return;
|
|
}
|
|
}
|
|
iPrevPoint = i;
|
|
}
|
|
|
|
// AOK, time to return
|
|
WritePrefs(); // save values user entered for next execution
|
|
|
|
if ( IsModal() )
|
|
EndModal(wxID_OK);
|
|
else {
|
|
SetReturnCode(wxID_OK);
|
|
this->Show(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvcCompressorDialog::OnCancel(wxCommandEvent &event)
|
|
{
|
|
EndModal(false);
|
|
}
|
|
|
|
static int* naSampleChoicesHoriz[5] = {iHoriz_1K_1K,iHoriz_1K_3HK,iHoriz_E75_5K,iHoriz_75_3500,iHoriz_AE75_3HK};
|
|
static int* naSampleChoicesVert[5] = {iVert_1K_1K, iVert_1K_3HK, iVert_E75_5K, iVert_75_3500, iVert_AE75_3HK};
|
|
|
|
void AvcCompressorDialog::OnRestoreDefaults(wxCommandEvent &event)
|
|
{
|
|
static int* naSampleChoicesHoriz[5] = {iHoriz_1K_1K,iHoriz_1K_3HK,iHoriz_E75_5K,iHoriz_75_3500,iHoriz_AE75_3HK};
|
|
static int* naSampleChoicesVert[5] = {iVert_1K_1K, iVert_1K_3HK, iVert_E75_5K, iVert_75_3500, iVert_AE75_3HK};
|
|
mstrAdjWin.Printf("%d", ADJWIN_DEFAULT);
|
|
mstrDelay.Printf("%d", DELAY_DEFAULT);
|
|
mstrChangeWin.Printf("%d", CHANGE_DEFAULT);
|
|
mstrMinPct.Printf("%d", MINPCT_DEFAULT);
|
|
|
|
for ( int i = 0 ; i < NUM_CURVE_POINTS ; ++ i ) {
|
|
mctlCheckBoxes[i]->SetValue(true);
|
|
mctlXAxis[i]->Show ( true );
|
|
mctlYAxis[i]->Show ( true );
|
|
mstrXAxis[i].Printf( "%d", naSampleChoicesHoriz[4][i] );
|
|
mstrYAxis[i].Printf( "%d", naSampleChoicesVert[4][i] );
|
|
}
|
|
TransferDataToWindow();
|
|
}
|
|
|
|
void AvcCompressorDialog::ReadPrefs()
|
|
{
|
|
int nTemp;
|
|
bool bTemp;
|
|
wxString strTemp;
|
|
|
|
nTemp = gPrefs->Read ( PREF_ADJWIN, ADJWIN_DEFAULT );
|
|
mstrAdjWin.Printf("%d", nTemp);
|
|
nTemp = gPrefs->Read ( PREF_DELAY, DELAY_DEFAULT );
|
|
mstrDelay.Printf("%d", nTemp);
|
|
nTemp = gPrefs->Read ( PREF_CHANGE, CHANGE_DEFAULT );
|
|
mstrChangeWin.Printf("%d", nTemp);
|
|
nTemp = gPrefs->Read ( PREF_MINPCT, MINPCT_DEFAULT );
|
|
mstrMinPct.Printf("%d", nTemp);
|
|
|
|
for ( int i = 1 ; i < NUM_CURVE_POINTS - 1 ; ++ i ) {
|
|
strTemp.Printf(PREF_ENABLE,i);
|
|
bTemp = ( gPrefs->Read ( strTemp, true ) == 0 ) ? false : true;
|
|
mctlCheckBoxes[i]->SetValue(bTemp);
|
|
mctlXAxis[i]->Show ( bTemp );
|
|
mctlYAxis[i]->Show ( bTemp );
|
|
|
|
strTemp.Printf(PREF_HORIZ,i);
|
|
nTemp = gPrefs->Read ( strTemp, naSampleChoicesHoriz[4][i] );
|
|
mstrXAxis[i].Printf( "%d", nTemp );
|
|
strTemp.Printf(PREV_VERT,i);
|
|
nTemp = gPrefs->Read ( strTemp, naSampleChoicesVert[4][i] );
|
|
mstrYAxis[i].Printf( "%d", nTemp );
|
|
}
|
|
TransferDataToWindow();
|
|
}
|
|
|
|
void AvcCompressorDialog::WritePrefs()
|
|
{
|
|
wxString strTemp;
|
|
|
|
gPrefs->Write ( PREF_ADJWIN, mnAdjWin );
|
|
gPrefs->Write ( PREF_DELAY, mnDelay );
|
|
gPrefs->Write ( PREF_CHANGE, mnChangeWin );
|
|
gPrefs->Write ( PREF_MINPCT, mnMinPct );
|
|
|
|
for ( int i = 1 ; i < NUM_CURVE_POINTS - 1 ; ++ i ) {
|
|
strTemp.Printf(PREF_ENABLE,i);
|
|
gPrefs->Write ( strTemp, mctlCheckBoxes[i]->GetValue() );
|
|
|
|
strTemp.Printf(PREF_HORIZ,i);
|
|
gPrefs->Write ( strTemp, mnXAxis[i] );
|
|
strTemp.Printf(PREV_VERT,i);
|
|
gPrefs->Write ( strTemp, mnYAxis[i] );
|
|
}
|
|
}
|
|
|
|
void AvcCompressorDialog::OnCheckBox(wxCommandEvent & event)
|
|
{
|
|
bool bCheck = mctlCheckBoxes[event.m_id-ID_FIRST_CURVE_CHECK]->GetValue();
|
|
mctlXAxis[event.m_id-ID_FIRST_CURVE_CHECK]->Show ( bCheck );
|
|
mctlYAxis[event.m_id-ID_FIRST_CURVE_CHECK]->Show ( bCheck );
|
|
}
|
|
|
|
wxSizer *AvcCompressorDialog::MakeAvcCompressorDialog(wxWindow * parent, bool call_fit,
|
|
bool set_sizer)
|
|
{
|
|
wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
|
|
wxStaticBoxSizer *group;
|
|
wxBoxSizer *boxSizer;
|
|
wxStaticText *staticText;
|
|
//wxTextCtrl *textCtrl;
|
|
wxButton *button;
|
|
wxFlexGridSizer *flexGridSizer;
|
|
|
|
staticText =
|
|
new wxStaticText(parent, ID_TEXT,
|
|
wxT("Automatic Volume Control by Vincent A. Busam"),
|
|
wxDefaultPosition, wxDefaultSize, 0);
|
|
mainSizer->Add(staticText, 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
// 0. Box Sizer for horizontal components
|
|
wxBoxSizer *horizontalSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
// 1. Box Sizer for leftmost group of controls
|
|
wxBoxSizer *leftSizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
// 1.1 Group Box for adjustment window settings
|
|
|
|
group = new wxStaticBoxSizer(new wxStaticBox(parent, -1,
|
|
wxT("Adjustment Settings")), wxVERTICAL);
|
|
flexGridSizer = new wxFlexGridSizer(2, 0, 0);
|
|
|
|
// 1.1.1 Adjustment Window
|
|
staticText =
|
|
new wxStaticText(parent, ID_TEXT, wxT("Adjustment Window:"),
|
|
wxDefaultPosition, wxDefaultSize, 0 );
|
|
flexGridSizer->Add(staticText, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
|
|
|
mctlAdjWin =
|
|
new wxTextCtrl(parent, ID_ADJWINTEXT, "", wxDefaultPosition,
|
|
wxSize(40, -1), 0,
|
|
wxTextValidator(wxFILTER_NUMERIC, &mstrAdjWin ) );
|
|
flexGridSizer->Add(mctlAdjWin, 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
// 1.1.2 Adjustment Delay
|
|
staticText =
|
|
new wxStaticText(parent, ID_TEXT, wxT("Adjustment Delay:"),
|
|
wxDefaultPosition, wxDefaultSize, 0);
|
|
flexGridSizer->Add(staticText, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
|
|
|
mctlDelay =
|
|
new wxTextCtrl(parent, ID_DELAYTEXT, "", wxDefaultPosition,
|
|
wxSize(40, -1), 0,
|
|
wxTextValidator(wxFILTER_NUMERIC, &mstrDelay ));
|
|
flexGridSizer->Add(mctlDelay, 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
// 1.1.3 Min Change Window
|
|
/* i18n-hint: the minimum size of the window that is changed */
|
|
staticText =
|
|
new wxStaticText(parent, ID_TEXT, wxT("Minimum Change Window:"),
|
|
wxDefaultPosition, wxDefaultSize, 0);
|
|
flexGridSizer->Add(staticText, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
|
|
|
mctlChangeWin =
|
|
new wxTextCtrl(parent, ID_CHANGEWINTEXT, "", wxDefaultPosition,
|
|
wxSize(40, -1), 0,
|
|
wxTextValidator(wxFILTER_NUMERIC, &mstrChangeWin ));
|
|
flexGridSizer->Add(mctlChangeWin, 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
// 1.1.4 Min Change %
|
|
staticText =
|
|
new wxStaticText(parent, ID_TEXT, wxT("Minimum Change %:"),
|
|
wxDefaultPosition, wxDefaultSize, 0);
|
|
flexGridSizer->Add(staticText, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
|
|
|
mctlMinPct =
|
|
new wxTextCtrl(parent, ID_MINPCTTEXT, "", wxDefaultPosition,
|
|
wxSize(40, -1), 0,
|
|
wxTextValidator(wxFILTER_NUMERIC, &mstrMinPct ));
|
|
flexGridSizer->Add(mctlMinPct, 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
// 1.1.end Add group
|
|
group->Add( flexGridSizer, 0, wxALIGN_CENTRE|wxALL, 5 );
|
|
|
|
leftSizer->Add( group, 0, wxALIGN_TOP |wxALL, 5 );
|
|
|
|
// DMM: the following text box is too difficult to translate as-is. Taken out of
|
|
// i18n for now.
|
|
|
|
// 1.2 area under group box
|
|
staticText =
|
|
new wxStaticText(parent, ID_TEXT,
|
|
("Above values are in samples.\n"
|
|
"Adjustment Window defines number of \nsamples in moving average.\n"
|
|
"Change window defines minimum time \nbetween volume changes.\n"
|
|
"Minimum % change of volume adjustment \nbefore making a volume change.\n"
|
|
"Grid at right determines how much to amplify \neach volume level.\n"
|
|
"For more information see: \n"
|
|
"http://www.busam.com/skyland/iavc\n"
|
|
"7/21/02: WAV and MP3 files both work."
|
|
),
|
|
wxDefaultPosition, wxDefaultSize, 0);
|
|
leftSizer->Add(staticText, 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
// 1.end
|
|
horizontalSizer->Add( leftSizer, 0, wxALIGN_TOP |wxALL, 5 );
|
|
|
|
// 2. Group Box for volume settings
|
|
|
|
group = new wxStaticBoxSizer(new wxStaticBox(parent, -1,
|
|
wxT("Amplification Settings")), wxVERTICAL);
|
|
|
|
// 2.1 Add one row each time through loop
|
|
|
|
flexGridSizer = new wxFlexGridSizer(3, 0, 0);
|
|
|
|
staticText =
|
|
new wxStaticText(parent, ID_TEXT, _("Enabled"),
|
|
wxDefaultPosition, wxDefaultSize, 0);
|
|
flexGridSizer->Add(staticText, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
|
|
|
staticText =
|
|
new wxStaticText(parent, ID_TEXT, wxT("Original Value"),
|
|
wxDefaultPosition, wxDefaultSize, 0);
|
|
flexGridSizer->Add(staticText, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
|
|
|
staticText =
|
|
new wxStaticText(parent, ID_TEXT, wxT("New Value"),
|
|
wxDefaultPosition, wxDefaultSize, 0);
|
|
flexGridSizer->Add(staticText, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
|
|
|
for ( int i = 0 ; i < NUM_CURVE_POINTS ; ++i )
|
|
{
|
|
mctlCheckBoxes[i] =
|
|
new wxCheckBox(parent, ID_FIRST_CURVE_CHECK + i, "", wxDefaultPosition,
|
|
wxSize(40, -1), 0);
|
|
flexGridSizer->Add(mctlCheckBoxes[i], 0, wxALIGN_CENTRE | wxALL, 5);
|
|
mctlCheckBoxes[i]->SetValue(true);
|
|
|
|
mctlXAxis[i] =
|
|
new wxTextCtrl(parent, ID_FIRST_CURVE_X + i, "", wxDefaultPosition,
|
|
wxSize(40, -1), 0,
|
|
wxTextValidator(wxFILTER_NUMERIC, &mstrXAxis[i] ));
|
|
flexGridSizer->Add(mctlXAxis[i], 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
mctlYAxis[i] =
|
|
new wxTextCtrl(parent, ID_FIRST_CURVE_Y + i, "", wxDefaultPosition,
|
|
wxSize(40, -1), 0,
|
|
wxTextValidator(wxFILTER_NUMERIC, &mstrYAxis[i] ));
|
|
flexGridSizer->Add(mctlYAxis[i], 0, wxALIGN_CENTRE | wxALL, 5);
|
|
}
|
|
mctlCheckBoxes[0]->Enable(false);
|
|
mctlXAxis[0]->Enable(false);
|
|
mctlYAxis[0]->Enable(false);
|
|
mctlCheckBoxes[NUM_CURVE_POINTS-1]->Enable(false);
|
|
mctlXAxis[NUM_CURVE_POINTS-1]->Enable(false);
|
|
mctlYAxis[NUM_CURVE_POINTS-1]->Enable(false);
|
|
|
|
// 2.end Add group
|
|
group->Add( flexGridSizer, 0, wxALIGN_CENTRE|wxALL, 5 );
|
|
horizontalSizer->Add( group, 0, wxALIGN_CENTRE|wxALL, 5 );
|
|
|
|
mainSizer->Add( horizontalSizer, 0, wxALIGN_CENTRE|wxALL, 5 );
|
|
|
|
// Last: Add buttons
|
|
boxSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
// Add restore defaults button
|
|
button =
|
|
new wxButton(parent, ID_RESTORE_DEFAULTS, wxT("Restore Defaults"), wxDefaultPosition,
|
|
wxDefaultSize, 0);
|
|
boxSizer->Add(button, 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
// Add Cancel button
|
|
button =
|
|
new wxButton(parent, wxID_CANCEL, _("&Cancel"), wxDefaultPosition,
|
|
wxDefaultSize, 0);
|
|
boxSizer->Add(button, 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
// Add OK button
|
|
button =
|
|
new wxButton(parent, wxID_OK, _("OK"), wxDefaultPosition,
|
|
wxDefaultSize, 0);
|
|
button->SetDefault();
|
|
boxSizer->Add(button, 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
mainSizer->Add(boxSizer, 0, wxALIGN_CENTRE | wxALL, 5);
|
|
|
|
if (set_sizer) {
|
|
parent->SetAutoLayout(TRUE);
|
|
parent->SetSizer(mainSizer);
|
|
if (call_fit) {
|
|
mainSizer->Fit(parent);
|
|
mainSizer->SetSizeHints(parent);
|
|
}
|
|
}
|
|
|
|
return mainSizer;
|
|
}
|
|
|
|
|
|
// 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: 129a8b19-9efd-4b47-95cb-c5534840a0f0
|
|
|