68#include <wx/dcclient.h>
69#include <wx/dcmemory.h>
71#include <wx/listctrl.h>
76#include <wx/radiobut.h>
78#include <wx/stattext.h>
80#include <wx/textdlg.h>
83#include <wx/stdpaths.h>
84#include <wx/settings.h>
86#include <wx/checkbox.h>
87#include <wx/tooltip.h>
92#include "../ShuttleAutomation.h"
93#include "../ShuttleGui.h"
97#include "../EnvelopeEditor.h"
102#include "../TrackArtist.h"
103#include "../WaveClip.h"
105#include "../WaveTrack.h"
106#include "../widgets/Ruler.h"
107#include "../widgets/AudacityTextEntryDialog.h"
112#if wxUSE_ACCESSIBILITY
113#include "../widgets/WindowAccessible.h"
116#include "../widgets/FileDialog/FileDialog.h"
118#ifdef EXPERIMENTAL_EQ_SSE_THREADED
139#ifdef EXPERIMENTAL_EQ_SSE_THREADED
151#define EQCURVES_VERSION 1
152#define EQCURVES_REVISION 0
167 20., 25., 31., 40., 50., 63., 80., 100., 125., 160., 200.,
168 250., 315., 400., 500., 630., 800., 1000., 1250., 1600., 2000.,
169 2500., 3150., 4000., 5000., 6300., 8000., 10000., 12500., 16000., 20000.,
188 (effect.mLin ? effect.mLinEnvelope : effect.mLogEnvelope).get();
201{
XO(
"Equalization") };
208{ wxT(
"Filter Curve"),
XO(
"Filter Curve EQ") };
213{ wxT(
"Graphic EQ"),
XO(
"Graphic EQ") };
225 wxEVT_COMMAND_SLIDER_UPDATED,
239#ifdef EXPERIMENTAL_EQ_SSE_THREADED
240 EVT_RADIOBUTTON(ID_DefaultMath, EffectEqualization::OnProcessingRadio)
241 EVT_RADIOBUTTON(ID_SSE, EffectEqualization::OnProcessingRadio)
242 EVT_RADIOBUTTON(ID_SSEThreaded, EffectEqualization::OnProcessingRadio)
243 EVT_RADIOBUTTON(ID_AVX, EffectEqualization::OnProcessingRadio)
244 EVT_RADIOBUTTON(ID_AVXThreaded, EffectEqualization::OnProcessingRadio)
245 EVT_BUTTON(ID_Bench, EffectEqualization::OnBench)
250 : mFFTBuffer{ windowSize }
251 , mFilterFuncR{ windowSize }
252 , mFilterFuncI{ windowSize }
254 Parameters().Reset(*
this);
263 hFFT =
GetFFT(windowSize);
265 SetLinearEffectFlag(
true);
267 mCurveName = CurveName.def;
278 mLogEnvelope = std::make_unique<Envelope>
280 dBMin.min, dBMax.max,
282 mLogEnvelope->SetTrackLen(1.0);
284 mLinEnvelope = std::make_unique<Envelope>
286 dBMin.min, dBMax.max,
288 mLinEnvelope->SetTrackLen(1.0);
290 mEnvelope = (mLin ? mLinEnvelope : mLogEnvelope).get();
292 mWindowSize = windowSize;
295 mDisallowCustom =
false;
306 mWhens[i] = (
double)i/(
NUM_PTS-1.);
311#ifdef EXPERIMENTAL_EQ_SSE_THREADED
314 if(useSSE && !mEffectEqualization48x)
315 mEffectEqualization48x = std::make_unique<EffectEqualization48x>();
317 mEffectEqualization48x.reset();
324 auto trackList = inputTracks();
325 const auto t = trackList
326 ? *trackList->Any<
const WaveTrack >().first
335 mHiFreq = mProjectRate / 2.0;
357 return XO(
"Adjusts the volume levels of particular frequencies");
364 return L
"Graphic_EQ";
366 return L
"Filter_Curve_EQ";
367 return L
"Equalization";
384 int numPoints =
mCurves[ 0 ].points.size();
386 for( point = 0; point < numPoints; point++ )
388 const wxString nameFreq = wxString::Format(
"f%i",point);
389 const wxString nameVal = wxString::Format(
"v%i",point);
391 0.0, 0.0, 0.0, 0.0 );
393 0.0, 0.0, 0.0, 0.0 );
408 for (
int i = 0; i < 200; i++)
410 const wxString nameFreq = wxString::Format(
"f%i",i);
411 const wxString nameVal = wxString::Format(
"v%i",i);
414 visitor.
Define( f, nameFreq, 0.0, -10000.0, 1000000.0, 0.0 );
415 visitor.
Define( d, nameVal, 0.0, -10000.0, 10000.0, 0.0 );
459 {
kCURVE,
XO(
"100Hz Rumble"), wxT(
"f0=\"20.0\" v0=\"-80.0\" f1=\"49.237316986327\" v1=\"-33.107692718506\" f2=\"54.196034330446\" v2=\"-29.553844451904\" f3=\"88.033573501041\" v3=\"-6.923076629639\" f4=\"95.871851182279\" v4=\"-4.523078918457\" f5=\"108.957037410504\" v5=\"-1.938461303711\" f6=\"123.828171198057\" v6=\"-0.73846244812\" f7=\"149.228077614658\" v7=\"-0.092308044434\"") },
460 {
kCURVE,
XO(
"AM Radio"), wxT(
"f0=\"20.0\" v0=\"-63.67\" f1=\"31.0\" v1=\"-33.219\" f2=\"50.0\" v2=\"-3.01\" f3=\"63.0\" v3=\"-0.106\" f4=\"100.0\" v4=\"0.0\" f5=\"2500.0\" v5=\"0.0\" f6=\"4000.0\" v6=\"-0.614\" f7=\"5000.0\" v7=\"-8.059\" f8=\"8000.0\" v8=\"-39.981\" f9=\"20000.0\" v9=\"-103.651\" f10=\"48000.0\" v10=\"-164.485\"") },
461 {
kBOTH,
XO(
"Bass Boost"), wxT(
"f0=\"100.0\" v0=\"9.0\" f1=\"500.0\" v1=\"0.0\"") },
462 {
kBOTH,
XO(
"Bass Cut"), wxT(
"f0=\"150.0\" v0=\"-50.0\" f1=\"300.0\" v1=\"0.0\"") },
463 {
kCURVE,
XO(
"Low rolloff for speech"), wxT(
"f0=\"50.0\" v0=\"-120.0\" f1=\"60.0\" v1=\"-50.0\" f2=\"65.0\" v2=\"-24.0\" f3=\"70.0\" v3=\"-12.0\" f4=\"80.0\" v4=\"-4.0\" f5=\"90.0\" v5=\"-1.0\" f6=\"100.0\" v6=\"0.0\"") },
464 {
kBOTH,
XO(
"RIAA"), wxT(
"f0=\"20.0\" v0=\"19.274\" f1=\"25.0\" v1=\"18.954\" f2=\"31.0\" v2=\"18.516\" f3=\"40.0\" v3=\"17.792\" f4=\"50.0\" v4=\"16.946\" f5=\"63.0\" v5=\"15.852\" f6=\"80.0\" v6=\"14.506\" f7=\"100.0\" v7=\"13.088\" f8=\"125.0\" v8=\"11.563\" f9=\"160.0\" v9=\"9.809\" f10=\"200.0\" v10=\"8.219\" f11=\"250.0\" v11=\"6.677\" f12=\"315.0\" v12=\"5.179\" f13=\"400.0\" v13=\"3.784\" f14=\"500.0\" v14=\"2.648\" f15=\"630.0\" v15=\"1.642\" f16=\"800.0\" v16=\"0.751\" f17=\"1000.0\" v17=\"0.0\" f18=\"1250.0\" v18=\"-0.744\" f19=\"1600.0\" v19=\"-1.643\" f20=\"2000.0\" v20=\"-2.589\" f21=\"2500.0\" v21=\"-3.7\" f22=\"3150.0\" v22=\"-5.038\" f23=\"4000.0\" v23=\"-6.605\" f24=\"5000.0\" v24=\"-8.21\" f25=\"6300.0\" v25=\"-9.98\" f26=\"8000.0\" v26=\"-11.894\" f27=\"10000.0\" v27=\"-13.734\" f28=\"12500.0\" v28=\"-15.609\" f29=\"16000.0\" v29=\"-17.708\" f30=\"20000.0\" v30=\"-19.62\" f31=\"25000.0\" v31=\"-21.542\" f32=\"48000.0\" v32=\"-27.187\"") },
465 {
kCURVE,
XO(
"Telephone"), wxT(
"f0=\"20.0\" v0=\"-94.087\" f1=\"200.0\" v1=\"-14.254\" f2=\"250.0\" v2=\"-7.243\" f3=\"315.0\" v3=\"-2.245\" f4=\"400.0\" v4=\"-0.414\" f5=\"500.0\" v5=\"0.0\" f6=\"2500.0\" v6=\"0.0\" f7=\"3150.0\" v7=\"-0.874\" f8=\"4000.0\" v8=\"-3.992\" f9=\"5000.0\" v9=\"-9.993\" f10=\"48000.0\" v10=\"-88.117\"") },
466 {
kBOTH,
XO(
"Treble Boost"), wxT(
"f0=\"4000.0\" v0=\"0.0\" f1=\"5000.0\" v1=\"9.0\"") },
467 {
kBOTH,
XO(
"Treble Cut"), wxT(
"f0=\"6000.0\" v0=\"0.0\" f1=\"10000.0\" v1=\"-110.0\"") },
468 {
kCURVE,
XO(
"Walkie-talkie"), wxT(
"f0=\"100.0\" v0=\"-120.0\" f1=\"101.0\" v1=\"0.0\" f2=\"2000.0\" v2=\"0.0\" f3=\"2001.0\" v3=\"-120.0\"") },
508 S.SetForWriting( &eap );
528 XO(
"To use this filter curve in a macro, please choose a new name for it.\nChoose the 'Save/Manage Curves...' button and rename the 'unnamed' curve, then use that one."),
530 XO(
"Filter Curve EQ needs a different name") );
541 mLogEnvelope->GetPoints(when.get(), value.get(), numPoints);
542 for (
size_t i = 0, j = 0; j + 2 < numPoints; i++, j++)
544 if ((value[i] < value[i + 1] + .05) && (value[i] > value[i + 1] - .05) &&
545 (value[i + 1] < value[i + 2] + .05) && (value[i + 1] > value[i + 2] - .05))
573 wxString base = wxT(
"/Effects/Equalization/");
575 base = wxT(
"/Effects/GraphicEq/");
577 base = wxT(
"/Effects/FilterCurve/");
589 rate = (*(trackRange.first++)) ->
GetRate();
592 for (
auto track : trackRange) {
593 if (track->GetRate() != rate) {
596"To apply Equalization, all selected tracks must have the same sample rate.") );
607 XO(
"Track sample rate is too low for this effect."),
609 XO(
"Effect Unavailable") );
633#ifdef EXPERIMENTAL_EQ_SSE_THREADED
634 if(mEffectEqualization48x) {
637 return mEffectEqualization48x->Benchmark(
this);
640 return mEffectEqualization48x->Process(
this);
645 bool bGoodResult =
true;
649 double trackStart = track->GetStartTime();
650 double trackEnd = track->GetEndTime();
651 double t0 =
mT0 < trackStart? trackStart:
mT0;
652 double t1 =
mT1 > trackEnd? trackEnd:
mT1;
655 auto start = track->TimeToLongSamples(t0);
656 auto end = track->TimeToLongSamples(t1);
657 auto len =
end - start;
695 S.SetSizerProportion(1);
696 S.Prop(1).StartMultiColumn(1, wxEXPAND);
712 S.SetSizerProportion(1);
713 S.Prop(1).StartMultiColumn(3, wxEXPAND);
719 S.StartVerticalLay(wxEXPAND, 1);
722 S.GetParent(), wxID_ANY, wxVERTICAL,
729 .TicksAtExtremes(
true)
730 .TickColour( { 0, 0, 0 } )
733 S.Prop(0).AddSpace(0, 1);
744 .MinSize( { wxDefaultCoord, wxDefaultCoord } )
748 S.StartVerticalLay();
750 S.AddVariableText(
XO(
"+ dB"),
false, wxCENTER);
753 .Style(wxSL_VERTICAL | wxSL_INVERSE)
754 .AddSlider( {}, 30, 60, 0);
755#if wxUSE_ACCESSIBILITY
761 .Style(wxSL_VERTICAL | wxSL_INVERSE)
762 .AddSlider( {}, -30, -10, -120);
763 S.AddVariableText(
XO(
"- dB"),
false, wxCENTER);
764#if wxUSE_ACCESSIBILITY
779 S.GetParent(), wxID_ANY, wxHORIZONTAL,
788 .TicksAtExtremes(
true)
789 .TickColour( { 0, 0, 0 } )
794 .Position(wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP | wxLEFT)
806 S.SetSizerProportion(1);
807 S.StartHorizontalLay(wxEXPAND, 1);
816 wxWindow *pParent =
S.GetParent();
831 S.StartVerticalLay();
833 S.AddFixedText( fNum );
835 wxDefaultPosition, wxSize(-1,50), wxSL_VERTICAL | wxSL_INVERSE);
837#if wxUSE_ACCESSIBILITY
857 S.EndHorizontalLay();
862 S.SetSizerProportion(1);
863 S.Prop(1).StartMultiColumn(7, wxALIGN_CENTER_HORIZONTAL);
871 S.StartHorizontalLay(wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
873 S.AddPrompt(
XXO(
"&EQ Type:"));
875 S.EndHorizontalLay();
877 S.StartHorizontalLay(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 1);
879 S.StartHorizontalLay(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 1);
882 .Name(
XO(
"Draw Curves"))
883 .AddRadioButton(
XXO(
"&Draw"));
886 .Name(
XO(
"Graphic EQ"))
887 .AddRadioButtonToGroup(
XXO(
"&Graphic"));
889 S.EndHorizontalLay();
891 S.EndHorizontalLay();
894 S.StartHorizontalLay(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 0);
898 S.StartHorizontalLay(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 1);
903 .Name(
XO(
"Interpolation type"))
906#if wxUSE_ACCESSIBILITY
911 S.EndHorizontalLay();
913 S.StartHorizontalLay(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 1);
918 .Name(
XO(
"Linear Frequency Scale"))
919 .AddCheckBox(
XXO(
"Li&near Frequency Scale"),
false);
921 S.EndHorizontalLay();
923 S.EndHorizontalLay();
930 S.StartHorizontalLay(wxEXPAND, 0);
932 S.StartHorizontalLay(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 0);
934 S.AddPrompt(
XXO(
"Length of &Filter:"));
936 S.EndHorizontalLay();
938 S.StartHorizontalLay(wxEXPAND, 1);
941 .Name(
XO(
"Length of Filter"))
942 .Style(wxSL_HORIZONTAL)
943 .AddSlider( {}, (
mM - 1) / 2, 4095, 10);
945 S.EndHorizontalLay();
947 S.StartHorizontalLay(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 0);
956 S.EndHorizontalLay();
958 S.EndHorizontalLay();
967 S.StartHorizontalLay(wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
969 S.AddPrompt(
XXO(
"&Select Curve:"));
971 S.EndHorizontalLay();
973 S.StartHorizontalLay(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 1);
975 S.StartHorizontalLay(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 1);
978 .Name(
XO(
"Select Curve"))
982 for (
const auto &curve :
mCurves)
983 curves.push_back(
Verbatim( curve.Name ) );
988 S.EndHorizontalLay();
990 S.EndHorizontalLay();
995 S.StartHorizontalLay(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 1);
1001 .Name(
XO(
"Show grid lines"))
1002 .AddCheckBox(
XXO(
"Show g&rid lines"),
false);
1004 S.EndHorizontalLay();
1012#ifdef EXPERIMENTAL_EQ_SSE_THREADED
1013 if (mEffectEqualization48x)
1022 S.StartHorizontalLay();
1024 S.AddUnits(
XO(
"&Processing: "));
1027 int mathPath = EffectEqualization48x::GetMathPath();
1029 (mathPath & MATH_FUNCTION_SSE)
1030 ? (mathPath & MATH_FUNCTION_THREADED)
1034 ? (mathPath & MATH_FUNCTION_THREADED)
1039 mMathProcessingType[0] =
S.Id(ID_DefaultMath)
1040 .AddRadioButton(
XXO(
"D&efault"),
1042 mMathProcessingType[1] =
S.Id(ID_SSE)
1043 .Disable(!EffectEqualization48x::GetMathCaps()->SSE)
1044 .AddRadioButtonToGroup(
XXO(
"&SSE"),
1046 mMathProcessingType[2] =
S.Id(ID_SSEThreaded)
1047 .Disable(!EffectEqualization48x::GetMathCaps()->SSE)
1048 .AddRadioButtonToGroup(
XXO(
"SSE &Threaded"),
1050 mMathProcessingType[3] =
S.Id(ID_AVX)
1053 .AddRadioButtonToGroup(
XXO(
"A&VX"),
1055 mMathProcessingType[4] =
S.Id(ID_AVXThreaded)
1058 .AddRadioButtonToGroup(
XXO(
"AV&X Threaded"),
1060 S.Id(ID_Bench).AddButton(
XXO(
"&Bench"));
1062 S.EndHorizontalLay();
1086 wxSize sz =
szrV->GetMinSize();
1087 sz += wxSize( 30, 0);
1098 wxSize sz =
szrV->GetMinSize();
1099 sz += wxSize( 400, 100);
1100 szrV->SetMinSize(sz);
1114 wxCommandEvent dummyEvent;
1152 wxGetTopLevelParent(
mUIParent)->Layout();
1187 if (idealBlockLen % L != 0)
1188 idealBlockLen += (L - (idealBlockLen % L));
1190 Floats buffer{ idealBlockLen };
1194 float *thisWindow = window1.get();
1195 float *lastWindow = window2.get();
1197 auto originalLen = len;
1203 bool bLoopSuccess =
true;
1205 int offset = (
mM - 1) / 2;
1213 for(
size_t i = 0; i < block; i += L)
1215 wcopy = std::min <size_t> (L, block - i);
1216 for(
size_t j = 0; j < wcopy; j++)
1217 thisWindow[j] = buffer[i+j];
1224 for(
size_t j = 0; (j <
mM - 1) && (j < wcopy); j++)
1225 buffer[i+j] = thisWindow[j] + lastWindow[L + j];
1226 for(
size_t j =
mM - 1; j < wcopy; j++)
1227 buffer[i+j] = thisWindow[j];
1237 originalLen.as_double()))
1239 bLoopSuccess =
false;
1247 if(wcopy < (
mM - 1)) {
1252 for(; j <
mM - 1 - wcopy; j++)
1253 buffer[j] = lastWindow[wcopy + j] + thisWindow[L + wcopy + j];
1255 for( ; j <
mM - 1; j++)
1256 buffer[j] = lastWindow[wcopy + j];
1258 for(
size_t j = 0; j <
mM - 1; j++)
1259 buffer[j] = lastWindow[wcopy + j];
1279 std::vector<std::pair<double, double> > clipStartEndTimes;
1280 std::vector<std::pair<double, double> > clipRealStartEndTimes;
1281 for (
const auto &clip : t->
GetClips())
1286 clipStartT = clip->GetPlayStartTime();
1287 clipEndT = clip->GetPlayEndTime();
1288 if( clipEndT <= startT )
1290 if( clipStartT >= startT + lenT )
1294 clipRealStartEndTimes.push_back(std::pair<double,double>(clipStartT,clipEndT));
1296 if( clipStartT < startT )
1297 clipStartT = startT;
1298 if( clipEndT > startT + lenT )
1299 clipEndT = startT + lenT;
1302 clipStartEndTimes.push_back(std::pair<double,double>(clipStartT,clipEndT));
1305 for(
unsigned int i = 0; i < clipStartEndTimes.size(); i++)
1308 t->
Clear(clipStartEndTimes[i].first,clipStartEndTimes[i].second);
1309 auto toClipOutput = output->Copy(clipStartEndTimes[i].first-startT+offsetT0,clipStartEndTimes[i].second-startT+offsetT0);
1311 t->
Paste(clipStartEndTimes[i].first, toClipOutput.get());
1314 if( (clipRealStartEndTimes[i].first != clipStartEndTimes[i].first ||
1315 clipRealStartEndTimes[i].second != clipStartEndTimes[i].second) &&
1316 !(clipRealStartEndTimes[i].first <= startT &&
1317 clipRealStartEndTimes[i].second >= startT+lenT) )
1318 t->
Join(clipRealStartEndTimes[i].first,clipRealStartEndTimes[i].second);
1322 return bLoopSuccess;
1327 double loLog = log10(
mLoFreq);
1328 double hiLog = log10(
mHiFreq);
1329 double denom = hiLog - loLog;
1346 double freq = delta;
1354 when = (log10(freq) - loLog)/denom;
1393 for(; i <= (
mM - 1) / 2; i++)
1399 0.5 * cos(2 *
M_PI * (i + (
mM - 1) / 2.0) / (
mM - 1)) +
1400 .08 * cos(4 *
M_PI * (i + (
mM - 1) / 2.0) / (
mM - 1));
1415 for(; i < (
mM - 1) / 2; i++)
1417 tempr[(
mM - 1) / 2 + i] = outr[i];
1420 tempr[(
mM - 1) / 2 + i] = outr[i];
1423 for (
size_t i = 0; i <
mM; i++)
1448 for(
size_t i = 1; i < (len / 2); i++)
1450 re=buffer[
hFFT->BitReversed[i] ];
1451 im=buffer[
hFFT->BitReversed[i]+1];
1474 mCurves.push_back( wxT(
"unnamed") );
1485 if(fileName.empty()) {
1488 wxString eqCurvesInstalledVersion;
1491 bool needUpdate = (eqCurvesCurrentVersion != eqCurvesInstalledVersion);
1510 EQCurve tempCustom(wxT(
"temp"));
1511 if( append ==
false )
1521 const wxString fullPath{
fn.GetFullPath() };
1522 if( !reader.
Parse(
this, fullPath ) )
1525 auto msg =
XO(
"Error Loading EQ Curves from file:\n%s\nError message says:\n%s")
1531 XO(
"Error Loading EQ Curves") );
1537 int numCurves =
mCurves.size();
1539 EQCurve tempUnnamed(wxT(
"tempUnnamed"));
1540 for( curve = 0; curve < numCurves-1; curve++ )
1542 if(
mCurves[curve].Name ==
_(
"unnamed") )
1551 if(
mCurves.back().Name !=
_(
"unnamed") )
1553 if( append ==
true )
1569 wxString unnamed = wxT(
"unnamed");
1572 EQCurve userUnnamed(wxT(
"temp"));
1580 wxLogDebug(wxT(
"Attempting to load EQDefaultCurves.xml from %s"),
fn.GetFullPath());
1583 if(!reader.
Parse(
this,
fn.GetFullPath())) {
1584 wxLogError(wxT(
"EQDefaultCurves.xml could not be read."));
1588 wxLogDebug(wxT(
"Loading EQDefaultCurves.xml successful."));
1595 if (defaultCurves.back().Name == unnamed) {
1596 defaultCurves.pop_back();
1599 wxLogError(wxT(
"Error in EQDefaultCurves.xml"));
1602 int numUserCurves = userCurves.size();
1603 int numDefaultCurves = defaultCurves.size();
1604 EQCurve tempCurve(wxT(
"test"));
1612 for (
int curveCount = 0; curveCount < numUserCurves; curveCount++) {
1613 bool isCustom =
true;
1614 tempCurve = userCurves[curveCount];
1616 for (
int defCurveCount = 0; defCurveCount < numDefaultCurves; defCurveCount++) {
1617 if (tempCurve.
Name ==
mCurves[defCurveCount].Name) {
1630 for (
int defCurveCount = 0; defCurveCount < numDefaultCurves; defCurveCount++) {
1631 bool isUserCurve =
false;
1633 for (
int userCurveCount = 0; userCurveCount < numUserCurves; userCurveCount++) {
1634 if (userCurves[userCurveCount].Name == defaultCurves[defCurveCount].Name) {
1636 mCurves.push_back(userCurves[userCurveCount]);
1641 mCurves.push_back(defaultCurves[defCurveCount]);
1646 for (
int userCurveCount = 0; userCurveCount < numUserCurves; userCurveCount++) {
1647 bool isDefaultCurve =
false;
1648 tempCurve = userCurves[userCurveCount];
1649 for (
int defCurveCount = 0; defCurveCount < numDefaultCurves; defCurveCount++) {
1650 if (tempCurve.
Name == defaultCurves[defCurveCount].Name) {
1651 isDefaultCurve =
true;
1655 if (!isDefaultCurve) {
1660 defaultCurves.clear();
1664 if(userUnnamed.
Name == unnamed) {
1665 mCurves.push_back( userUnnamed );
1686 if( !fileName.FileExists() )
1691 if( !fileName.FileExists() )
1703 return (fileName.FileExists());
1713 if( fileName.empty() )
1724 if( !
fn.DirExists() )
1727 if( !
fn.Mkdir(
fn.GetPath(), 511, wxPATH_MKDIR_FULL ) )
1739 const wxString fullPath{
fn.GetFullPath() };
1740 XMLFileWriter eqFile{ fullPath,
XO(
"Error Saving Equalization Curves") };
1755 wxASSERT( currentCurve < (
int)
mCurves.size() );
1759 int numPoints = (int)
mCurves[currentCurve].points.size();
1771 if (numPoints == 0) {
1779 if (numPoints == 1) {
1781 when =
mCurves[currentCurve].points[0].Freq;
1787 double loLog = log10((
double)
loFreqI);
1788 double hiLog = log10(
mHiFreq);
1789 double denom = hiLog - loLog;
1790 when = (log10(std::max((
double)
loFreqI, when)) - loLog)/denom;
1792 value =
mCurves[currentCurve].points[0].dB;
1799 std::sort(
mCurves[currentCurve].points.begin(),
1800 mCurves[currentCurve].points.end());
1802 if (
mCurves[currentCurve].points[0].Freq < 0) {
1809 for(
int pointCount = 0; pointCount < numPoints; pointCount++) {
1811 value =
mCurves[currentCurve].points[pointCount].dB;
1813 env->
Insert(when, value);
1821 double nextDB =
mCurves[currentCurve].points[pointCount].dB;
1822 if (pointCount > 0) {
1823 double nextF =
mCurves[currentCurve].points[pointCount].Freq;
1824 double lastF =
mCurves[currentCurve].points[pointCount-1].Freq;
1825 double lastDB =
mCurves[currentCurve].points[pointCount-1].dB;
1827 ((nextDB - lastDB) *
1828 ((
mHiFreq - lastF) / (nextF - lastF)));
1832 env->
Insert(when, value);
1838 double loLog = log10((
double)
loFreqI);
1839 double hiLog = log10(
mHiFreq);
1840 double denom = hiLog - loLog;
1845 for (firstAbove20Hz = 0; firstAbove20Hz < numPoints; firstAbove20Hz++) {
1850 if (firstAbove20Hz == numPoints) {
1853 value =
mCurves[currentCurve].points[numPoints-1].dB;
1854 env->
Insert(when, value);
1859 if (firstAbove20Hz > 0) {
1862 double prevF =
mCurves[currentCurve].points[firstAbove20Hz-1].Freq;
1863 prevF = log10(std::max(1.0, prevF));
1864 double prevDB =
mCurves[currentCurve].points[firstAbove20Hz-1].dB;
1865 double nextF = log10(
mCurves[currentCurve].points[firstAbove20Hz].Freq);
1866 double nextDB =
mCurves[currentCurve].points[firstAbove20Hz].dB;
1868 value = nextDB - ((nextDB - prevDB) * ((nextF - loLog) / (nextF - prevF)));
1869 env->
Insert(when, value);
1873 for(
int pointCount = firstAbove20Hz; pointCount < numPoints; pointCount++)
1875 double flog = log10(
mCurves[currentCurve].points[pointCount].Freq);
1876 wxASSERT(
mCurves[currentCurve].points[pointCount].Freq >=
loFreqI);
1878 when = (flog - loLog)/denom;
1879 value =
mCurves[currentCurve].points[pointCount].dB;
1881 env->
Insert(when, value);
1897 if (pointCount > 0) {
1898 double lastDB =
mCurves[currentCurve].points[pointCount-1].dB;
1900 log10(
mCurves[currentCurve].points[pointCount-1].Freq);
1903 ((log10(
mHiFreq) - logLastF) / (flog - logLastF)));
1905 env->
Insert(when, value);
1921 for( i = 0; i <
mCurves.size(); i++ )
1922 if( curveName ==
mCurves[ i ].Name )
1927 XO(
"Requested curve not found, using 'unnamed'"),
1929 XO(
"Curve not found") );
1944 mCurve->SetSelection( curve );
1981 env->
GetPoints( when.get(), value.get(), numPoints );
1984 int curve =
mCurves.size() - 1;
1985 mCurves[ curve ].points.clear();
1990 for (
size_t point = 0; point < numPoints; point++)
1992 double freq = when[ point ] *
mHiFreq;
1993 double db = value[ point ];
2001 double loLog = log10( 20. );
2002 double hiLog = log10(
mHiFreq );
2003 double denom = hiLog - loLog;
2006 for (
size_t point = 0; point < numPoints; point++)
2008 double freq = pow( 10., ( ( when[ point ] * denom ) + loLog ));
2009 double db = value[ point ];
2050 tip.Printf( wxT(
"%dHz\n%.1fdB"), (
int)
kThirdOct[i], 0. );
2052 tip.Printf( wxT(
"%gkHz\n%.1fdB"),
kThirdOct[i]/1000., 0. );
2065 if (tag ==
"equalizationeffect")
2074 for (
auto pair : attrs)
2076 auto attr = pair.first;
2077 auto value = pair.second;
2080 if( attr ==
"name" )
2082 const wxString strValue = value.ToWString();
2085 wxString strValueTemp = strValue;
2090 for(
size_t i = 0; i <
mCurves.size(); i++)
2093 strValueTemp.Printf(wxT(
"%s (%d)"),strValue,n);
2094 if(
mCurves[i].Name == strValueTemp)
2102 while(exists ==
true);
2121 for (
auto pair : attrs)
2123 auto attr = pair.first;
2124 auto value = pair.second;
2129 if (!value.TryGet(dblValue))
2134 else if( attr ==
"d" )
2136 if (!value.TryGet(dblValue))
2158 if (tag ==
"equalizationeffect")
2183 xmlFile.StartTag( wxT(
"equalizationeffect" ) );
2186 int numCurves = mCurves.size();
2188 for( curve = 0; curve < numCurves; curve++ )
2191 xmlFile.StartTag( wxT(
"curve" ) );
2192 xmlFile.WriteAttr( wxT(
"name" ), mCurves[ curve ].Name );
2195 int numPoints = mCurves[ curve ].points.size();
2197 for( point = 0; point < numPoints; point++ )
2200 xmlFile.StartTag( wxT(
"point" ) );
2201 xmlFile.WriteAttr( wxT(
"f" ), mCurves[ curve ].points[ point ].Freq, 12 );
2202 xmlFile.WriteAttr( wxT(
"d" ), mCurves[ curve ].points[ point ].dB, 12 );
2203 xmlFile.EndTag( wxT(
"point" ) );
2207 xmlFile.EndTag( wxT(
"curve" ) );
2211 xmlFile.EndTag( wxT(
"equalizationeffect" ) );
2227 bool selectedCurveExists =
false;
2228 for (
size_t i = 0, cnt =
mCurves.size(); i < cnt; i++)
2231 selectedCurveExists =
true;
2236 if (!selectedCurveExists)
2243 mCurve->SetMinSize({-1, -1});
2254 double deltadB = 0.1;
2255 double dx, dy, dx1, dy1, err;
2257 mLogEnvelope->GetPoints( when.get(), value.get(), numPoints );
2267 mLogEnvelope->GetPoints( when.get(), value.get(), numPoints );
2268 for (
size_t j = 0; j + 2 < numPoints; j++)
2270 dx = when[j+2+numDeleted] - when[j+numDeleted];
2271 dy = value[j+2+numDeleted] - value[j+numDeleted];
2272 dx1 = when[j+numDeleted+1] - when[j+numDeleted];
2273 dy1 = dy * dx1 / dx;
2274 err = fabs(value[j+numDeleted+1] - (value[j+numDeleted] + dy1));
2298 wxGetTopLevelParent(
mUIParent)->Layout();
2304 double loLog = log10(
mLoFreq);
2305 double hiLog = log10(
mHiFreq);
2306 double denom = hiLog - loLog;
2310 double step = pow(2., 1./12.);
2312 for(
double freq=10.; freq<
mHiFreq; freq*=step)
2355 wxGetTopLevelParent(
mUIParent)->Layout();
2357 wxGetTopLevelParent(
mUIParent)->Layout();
2366 if( numPoints == 0 )
2376 mLogEnvelope->GetPoints( when.get(), value.get(), numPoints );
2378 double loLog = log10(20.);
2379 double hiLog = log10(
mHiFreq);
2380 double denom = hiLog - loLog;
2382 for (
size_t i = 0; i < numPoints; i++)
2390 if( numPoints == 0 )
2400 mLinEnvelope->GetPoints( when.get(), value.get(), numPoints );
2402 double loLog = log10(20.);
2403 double hiLog = log10(
mHiFreq);
2404 double denom = hiLog - loLog;
2405 bool changed =
false;
2407 for (
size_t i = 0; i < numPoints; i++)
2413 double flog = (log10(when[i]*
mHiFreq)-loLog)/denom;
2419 double v = value[i];
2433 double oldError = 0.0;
2434 double mEQValsOld = 0.0;
2435 double correction = 1.6;
2440 for(
size_t i = 0; i <
NUM_PTS; i++)
2441 vals[i] = testEnvelope.GetValue(
mWhens[i]);
2446 for(
size_t i = 0; i <
NUM_PTS; i++)
2448 double err = vals[i] - testEnvelope.GetValue(
mWhens[i]);
2455 if( (j > 0) & (i == 0) )
2457 if( correction > 0 )
2458 correction = -correction;
2460 correction = -correction/2.;
2480 for(
size_t k = 0; k <
NUM_PTS; k++)
2482 double err = vals[k] - testEnvelope.GetValue(
mWhens[k]);
2486 while( (error < oldError) &&
flag );
2487 if( error > oldError )
2510 double dist, span, s;
2520 for(
size_t i = 0; i <
NUM_PTS; i++)
2533 value =
mEQVals[0]*(s + 1.5)*(s + 1.5)/2.;
2535 value =
mEQVals[0]*(.75 - s*s) +
mEQVals[1]*(s + .5)*(s + .5)/2.;
2559 value =
mEQVals[minF]*(0.75 - s*s);
2561 value +=
mEQVals[minF+1]*(s+.5)*(s+.5)/2.;
2563 value +=
mEQVals[minF-1]*(s-.5)*(s-.5)/2.;
2567 value =
mEQVals[minF]*(s-1.5)*(s-1.5)/2.;
2569 value +=
mEQVals[minF+1]*(.75-(1.-s)*(1.-s));
2571 value +=
mEQVals[minF+2]*(s-.5)*(s-.5)/2.;
2586 for(
size_t i = 0; i <
NUM_PTS; i++)
2615 value =
mEQVals[minF]*(1. + cos(
M_PI*(span-dist)/span))/2. +
2632 for(
double xf=0; xf<1.; xf+=1./
NUM_PTS)
2652 for (
size_t i = 1; i + 1 < n; i++)
2654 sig = ( x[i] - x[i-1] ) / ( x[i+1] - x[i-1] );
2655 p = sig * y2[i-1] + 2.;
2656 y2[i] = (sig - 1.)/p;
2657 u[i] = ( y[i+1] - y[i] ) / ( x[i+1] - x[i] ) - ( y[i] - y[i-1] ) / ( x[i] - x[i-1] );
2658 u[i] = (6.*u[i]/( x[i+1] - x[i-1] ) - sig * u[i-1]) / p;
2661 for (
size_t i = n - 1; i--;)
2662 y2[i] = y2[i]*y2[i+1] + u[i];
2670 static double xlast = 0.;
2671 static size_t k = 0;
2676 while( (x[k] <= xr) && (k + 1 < n) )
2681 a = ( x[k+1] - xr )/h;
2683 return( a*y[k]+b*y[k+1]+((a*a*a-a)*y2[k]+(b*b*b-b)*y2[k+1])*h*h/6.);
2698 wxSlider *s = (wxSlider *)event.GetEventObject();
2703 int posn =
mSliders[i]->GetValue();
2704 if( wxGetKeyState(WXK_SHIFT) )
2718 int newPosn = (int)
mEQVals[i];
2759 size_t m = 2 *
mMSlider->GetValue() + 1;
2761 wxASSERT( (m & 1) == 1 );
2766 tip.Printf(wxT(
"%d"), (
int)
mM);
2781 tip.Printf(
_(
"%d dB"), (
int)
mdBMin);
2793 tip.Printf(
_(
"%d dB"), (
int)
mdBMax);
2805 wxASSERT(
mCurve != NULL );
2838 int newPosn = (int)
mEQVals[i];
2867 if( numPoints == 0 )
2874 mLinEnvelope->GetPoints( when.get(), value.get(), numPoints );
2876 mLogEnvelope->GetPoints( when.get(), value.get(), numPoints );
2879 for (
size_t i = 0; i < numPoints; i++)
2928#ifdef EXPERIMENTAL_EQ_SSE_THREADED
2930void EffectEqualization::OnProcessingRadio(wxCommandEvent & event)
2932 int testEvent=
event.GetId();
2935 case ID_DefaultMath: EffectEqualization48x::SetMathPath(MATH_FUNCTION_ORIGINAL);
2937 case ID_SSE: EffectEqualization48x::SetMathPath(MATH_FUNCTION_SSE);
2939 case ID_SSEThreaded: EffectEqualization48x::SetMathPath(MATH_FUNCTION_THREADED | MATH_FUNCTION_SSE);
2941 case ID_AVX: testEvent = 2;
2943 case ID_AVXThreaded: testEvent = 2;
2949void EffectEqualization::OnBench( wxCommandEvent & event)
2979 mLinEditor = std::make_unique<EnvelopeEditor>(*mEffect->mLinEnvelope,
false);
2980 mLogEditor = std::make_unique<EnvelopeEditor>(*mEffect->mLogEnvelope,
false);
2981 mEffect->mEnvelope->Flatten(0.);
2982 mEffect->mEnvelope->SetTrackLen(1.0);
3013#include "../TrackPanelDrawingContext.h"
3022 GetSize(&width, &height);
3031 wxBrush bkgndBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
3039 bkgndRect.width =
mWidth;
3041 memDC.SetBrush(bkgndBrush);
3042 memDC.SetPen(*wxTRANSPARENT_PEN);
3043 memDC.DrawRectangle(bkgndRect);
3046 memDC.DrawRectangle(bkgndRect);
3054 memDC.SetBrush(*wxWHITE_BRUSH);
3055 memDC.SetPen(*wxBLACK_PEN);
3056 memDC.DrawRectangle(border);
3062 memDC.SetPen(wxPen(
theTheme.
Colour( clrGraphLines ), 1, wxPENSTYLE_SOLID));
3076 memDC.SetPen(wxPen(
theTheme.
Colour(clrGraphLines), 3, wxPENSTYLE_SOLID));
3079 int x, y, xlast = 0, ylast = 0;
3083 bool off =
false, off1 =
false;
3084 for (
int i = 0; i <
mEnvRect.width; i++)
3098 if ((i != 0) & (!off1))
3111 memDC.SetPen(wxPen(
theTheme.
Colour( clrResponseLines ), 1, wxPENSTYLE_SOLID));
3120 step /= ((double)
mEnvRect.width-1.);
3124 for(
int i=0; i<
mEnvRect.width; i++)
3127 freq = lin ? step*i : pow(10., loLog + i*step);
3128 if( ( lin ? step : (pow(10., loLog + (i+1)*step)-freq) ) < delta)
3132 double wtemp = sin(0.5 * theta);
3133 double wpr = -2.0 * wtemp * wtemp;
3134 double wpi = -1.0 * sin(theta);
3135 double wr = cos(theta*halfM);
3136 double wi = sin(theta*halfM);
3139 for(
int j=0;j<halfM;j++)
3141 yF += 2. *
mOutr[j] * wr;
3143 wr = (wtemp = wr) * wpr - wi * wpi + wr;
3144 wi = wi * wpr + wtemp * wpi + wi;
3155 n = (int)(freq/delta + .5);
3161 if(yF < mEffect->mdBMin)
3163 yF = center-scale*yF;
3178 memDC.SetPen(*wxBLACK_PEN);
3194 dc.Blit(0, 0,
mWidth,
mHeight, &memDC, 0, 0, wxCOPY, FALSE);
3204 if (event.ButtonDown() && !HasCapture())
3218 if (event.ButtonUp() && HasCapture())
3251 EVT_LIST_ITEM_DESELECTED(CurvesListID,
3257 wxDefaultPosition, wxDefaultSize,
3258 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
3260 SetLabel(
XO(
"Manage Curves"));
3261 SetName(
XO(
"Manage Curves List"));
3264 mPosition = position;
3266 mEditCurves.clear();
3267 for (
unsigned int i = 0; i < mEffect->mCurves.size(); i++)
3269 mEditCurves.push_back(mEffect->mCurves[i].Name);
3270 mEditCurves[i].points = mEffect->mCurves[i].points;
3274 SetMinSize(GetSize());
3293 S.StartHorizontalLay(wxEXPAND);
3295 S.StartStatic(
XO(
"&Curves"), 1);
3298 .Style(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES )
3299 .AddListControlReportMode({
3300 {
XO(
"Curve Name"), wxLIST_FORMAT_RIGHT }
3304 S.StartVerticalLay(0);
3317 S.EndHorizontalLay();
3318 S.AddStandardButtons();
3319 S.StartStatic(
XO(
"Help"));
3320 S.AddConstTextBox( {},
XO(
"Rename 'unnamed' to save a new entry.\n'OK' saves all changes, 'Cancel' doesn't."));
3330 mList->DeleteAllItems();
3331 for (
unsigned int i = 0; i <
mEditCurves.size(); i++)
3333 mList->SetColumnWidth(0, wxLIST_AUTOSIZE);
3334 int curvesWidth =
mList->GetColumnWidth(0);
3335 mList->SetColumnWidth(0, wxLIST_AUTOSIZE_USEHEADER);
3336 int headerWidth =
mList->GetColumnWidth(0);
3337 mList->SetColumnWidth(0, wxMax(headerWidth, curvesWidth));
3339 mList->EnsureVisible(position);
3340 mList->SetItemState(position, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
3345 long item =
mList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3349 item =
mList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3353 if ( item ==
mList->GetItemCount()-1)
3356 XO(
"'unnamed' always stays at the bottom of the list"),
3358 XO(
"'unnamed' is special") );
3361 state =
mList->GetItemState(item-1, wxLIST_STATE_SELECTED);
3362 if ( state != wxLIST_STATE_SELECTED )
3371 wxString sTemp =
mList->GetItemText(item);
3372 mList->SetItem(item, 0,
mList->GetItemText(item-1));
3373 mList->SetItem(item-1, 0, sTemp);
3374 mList->SetItemState(item, 0, wxLIST_STATE_SELECTED);
3375 mList->SetItemState(item-1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
3377 item =
mList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3389 if( (item !=
mList->GetItemCount()-1) && (item !=
mList->GetItemCount()-2) )
3391 state =
mList->GetItemState(item+1, wxLIST_STATE_SELECTED);
3392 if ( state != wxLIST_STATE_SELECTED )
3401 wxString sTemp =
mList->GetItemText(item);
3402 mList->SetItem(item, 0,
mList->GetItemText(item+1));
3403 mList->SetItem(item+1, 0, sTemp);
3404 mList->SetItemState(item, 0, wxLIST_STATE_SELECTED);
3405 mList->SetItemState(item+1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
3415 long itemTemp =
mList->GetNextItem(-1, wxLIST_NEXT_ALL,
3416 wxLIST_STATE_SELECTED);
3417 while( (itemTemp != -1) && (itemTemp < item) )
3419 lastItem = itemTemp;
3420 itemTemp =
mList->GetNextItem(itemTemp, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3441 long item =
mList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3442 long firstItem = item;
3446 bool overwrite =
false;
3455 dlg.SetTextValidator( wxFILTER_EXCLUDE_CHAR_LIST );
3457 wxString::Format(
_(
"Rename '%s'"),
mEditCurves[ item ].Name ) );
3458 wxTextValidator *tv = dlg.GetTextValidator();
3459 tv->SetExcludes( exclude );
3460 if( dlg.ShowModal() == wxID_CANCEL )
3467 name = dlg.GetValue();
3470 for( curve = 0; curve < numCurves; curve++ )
3479 XO(
"Name is the same as the original one"),
3484 int answer =
mEffect->Effect::MessageBox(
3487 XO(
"Curve exists") );
3488 if (answer == wxYES)
3511 if( item == (numCurves-1) )
3519 else if( item == (numCurves-1) )
3534 item =
mList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3549 long item =
mList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3552 long highlight = -1;
3556 if(item ==
mList->GetItemCount()-1)
3559 XO(
"You cannot delete the 'unnamed' curve."),
3561 XO(
"Can't delete 'unnamed'") );
3566 auto quest =
XO(
"Delete '%s'?")
3570 int ans =
mEffect->Effect::MessageBox(
3572 wxYES_NO | wxCENTRE,
3573 XO(
"Confirm Deletion") );
3580 highlight = item-deleted;
3583 item =
mList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3591 int count =
mList->GetSelectedItemCount();
3592 long item =
mList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3596 quest =
XO(
"Delete %d items?").Format( count );
3599 quest =
XO(
"Delete '%s'?").Format(
mEditCurves[ item ].Name );
3603 int ans =
mEffect->Effect::MessageBox(
3605 wxYES_NO | wxCENTRE,
3606 XO(
"Confirm Deletion") );
3614 if(item ==
mList->GetItemCount()-1)
3617 XO(
"You cannot delete the 'unnamed' curve, it is special."),
3619 XO(
"Can't delete 'unnamed'") );
3626 item =
mList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3648 if( filePicker.
ShowModal() == wxID_CANCEL)
3651 fileName = filePicker.
GetPath();
3669 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER);
3671 if( filePicker.
ShowModal() == wxID_CANCEL)
3674 fileName = filePicker.
GetPath();
3679 exportCurves.clear();
3680 long item =
mList->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3684 if(item !=
mList->GetItemCount()-1)
3687 exportCurves[i].points =
mEditCurves[item].points;
3692 XO(
"You cannot export 'unnamed' curve, it is special."),
3694 XO(
"Cannot Export 'unnamed'") );
3696 item =
mList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
3703 auto message =
XO(
"%d curves exported to %s").Format( i, fileName );
3707 XO(
"Curves exported") );
3711 XO(
"No curves exported"),
3713 XO(
"No curves exported") );
3719 wxLaunchDefaultBrowser(wxT(
"https://wiki.audacityteam.org/wiki/EQCurvesDownload"));
3736 wxString backupPlace = wxFileName(
FileNames::DataDir(), wxT(
"EQBackup.xml") ).GetFullPath();
3740 for (
unsigned int i = 0; i <
mEditCurves.size(); i++)
3752 long item =
mList->GetNextItem(-1,
3754 wxLIST_STATE_SELECTED);
3756 item =
mList->GetItemCount()-1;
3763 const bool enable =
mList->GetSelectedItemCount() > 0;
3764 static const int ids[] = {
3771 FindWindowById(
id,
this)->Enable(enable);
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), F3 delayedHandler=DefaultDelayedHandlerAction) noexcept(noexcept(handler(std::declval< AudacityException * >())) &&noexcept(handler(nullptr)) &&noexcept(std::function< void(AudacityException *)>{std::move(delayedHandler)}))
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
EffectDistortion::Params params
const RegistryPath & CurrentSettingsGroup()
Component of a configuration key path, for last-used destructive settings.
#define EQCURVES_REVISION
EVT_COMMAND_RANGE(ID_Slider, ID_Slider+NUMBER_OF_BANDS - 1, wxEVT_COMMAND_SLIDER_UPDATED, EffectEqualization::OnSlider) EffectEqualization
static const FileNames::FileTypes & XMLtypes()
static const double kThirdOct[]
EVT_LIST_ITEM_SELECTED(CurvesListID, EditCurvesDialog::OnListSelectionChange) EVT_LIST_ITEM_DESELECTED(CurvesListID
Constructor.
const TranslatableString name
static const struct @25 FactoryPresets[]
const int kEqOptionGraphic
std::vector< EQCurve > EQCurveArray
void InverseRealFFT(size_t NumSamples, const float *RealIn, const float *ImagIn, float *RealOut)
void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *ImagOut)
std::vector< RegistryPath > RegistryPaths
void RealFFTf(fft_type *buffer, const FFTParam *h)
void InverseRealFFTf(fft_type *buffer, const FFTParam *h)
void ReorderToTime(const FFTParam *hFFT, const fft_type *buffer, fft_type *TimeOut)
HFFT GetFFT(size_t fftlen)
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
TranslatableStrings Msgids(const EnumValueSymbol strings[], size_t nStrings)
Convenience function often useful when adding choice controls.
static Settings & settings()
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
std::vector< TranslatableString > TranslatableStrings
std::vector< Attribute > AttributesList
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Wrap wxTextEntryDialog so that caption IS translatable.
Generates EffectParameterMethods overrides from variadic template arguments.
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the SettingsVis...
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
EQCurve is used with EffectEqualization.
std::vector< EQPoint > points
EQPoint is used with EQCurve and hence EffectEqualization.
void OnUp(wxCommandEvent &event)
void OnOK(wxCommandEvent &event)
void OnImport(wxCommandEvent &event)
EffectEqualization * mEffect
void OnDown(wxCommandEvent &event)
long GetPreviousItem(long item)
void Populate()
Creates the dialog and its contents.
void OnDelete(wxCommandEvent &event)
void PopulateList(int position)
void OnLibrary(wxCommandEvent &event)
void OnRename(wxCommandEvent &event)
void OnListSelectionChange(wxListEvent &event)
void OnDefaults(wxCommandEvent &event)
void OnExport(wxCommandEvent &event)
void PopulateOrExchange(ShuttleGui &S)
Defines the dialog and does data exchange with it.
std::shared_ptr< TrackList > mOutputTracks
void ReplaceProcessedTracks(const bool bGoodResult)
const AudacityProject * FindProject() const
static const ComponentInterfaceSymbol Symbol
static const ComponentInterfaceSymbol Symbol
An Effect that modifies volume in different frequency bands.
RegistryPaths GetFactoryPresets() const override
Report names of factory presets.
void OnLinFreq(wxCommandEvent &event)
bool GetDefaultFileName(wxFileName &fileName)
const EffectParameterMethods & Parameters() const override
static const size_t windowSize
bool LoadFactoryDefaults(EffectSettings &settings) const override
Change settings back to "factory default".
virtual ~EffectEqualization()
std::unique_ptr< Envelope > mLinEnvelope
friend class EqualizationPanel
static constexpr EffectParameter DrawGrid
EqualizationPanel * mPanel
EffectType GetType() const override
Type determines how it behaves.
void OnSliderDBMIN(wxCommandEvent &event)
bool TransferDataToWindow(const EffectSettings &settings) override
Update controls for the settings.
static constexpr EffectParameter InterpLin
std::unique_ptr< EffectUIValidator > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access) override
Add controls to effect panel; always succeeds.
void OnGraphicMode(wxCommandEvent &event)
bool VisitSettings(SettingsVisitor &visitor, EffectSettings &settings) override
void GraphicEQ(Envelope *env)
void OnGridOnOff(wxCommandEvent &event)
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
void OnErase(wxEvent &event)
static constexpr EffectParameter dBMin
std::unique_ptr< Envelope > mLogEnvelope
TranslatableString GetDescription() const override
void OnManage(wxCommandEvent &event)
void Filter(size_t len, float *buffer)
void OnClear(wxCommandEvent &event)
void setCurve(int currentCurve)
double splint(double x[], double y[], size_t n, double y2[], double xr)
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
void OnInvert(wxCommandEvent &event)
void spline(double x[], double y[], size_t n, double y2[])
wxString GetPrefsPrefix()
void OnCurve(wxCommandEvent &event)
void OnSliderDBMAX(wxCommandEvent &event)
bool Process(EffectInstance &instance, EffectSettings &settings) override
Actually do the effect here.
bool DoLoadFactoryDefaults(EffectSettings &settings)
static const EnumValueSymbol kInterpStrings[nInterpolations]
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
int mSlidersOld[NUMBER_OF_BANDS]
void WriteXML(XMLWriter &xmlFile) const
EffectEqualization(int Options=kEqLegacy)
static constexpr EffectParameter FilterLength
void LoadCurves(const wxString &fileName={}, bool append=false)
static constexpr EffectParameter DrawMode
wxSlider * mSliders[NUMBER_OF_BANDS]
static const ComponentInterfaceSymbol Symbol
ComponentInterfaceSymbol GetSymbol() const override
bool ValidateUI(EffectSettings &) override
double mEQVals[NUMBER_OF_BANDS+1]
bool LoadFactoryPreset(int id, EffectSettings &settings) const override
Change settings to the preset whose name is GetFactoryPresets()[id]
void SaveCurves(const wxString &fileName={})
void OnDrawMode(wxCommandEvent &event)
void OnSize(wxSizeEvent &event)
void OnSliderM(wxCommandEvent &event)
void OnSlider(wxCommandEvent &event)
double mWhenSliders[NUMBER_OF_BANDS+1]
static constexpr EnumParameter InterpMeth
void OnInterp(wxCommandEvent &event)
bool Init() override
Call once to set up state for whole list of tracks to be processed.
void UpdateDefaultCurves(bool updateAll=false)
static constexpr EffectParameter dBMax
bool ProcessOne(int count, WaveTrack *t, sampleCount start, sampleCount len)
const EffectSettingsManager & GetDefinition() const override
bool VisitSettings(SettingsVisitor &visitor, EffectSettings &settings) override
void CopyInputTracks(bool allSyncLockSelected=false)
bool LoadFactoryDefaults(EffectSettings &settings) const override
Change settings back to "factory default".
int MessageBox(const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={}) const
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
bool IsBatchProcessing() const override
bool LoadUserPreset(const RegistryPath &name, EffectSettings &settings) const override
Change settings to a user-named preset.
Performs effect computation.
Interface for manipulations of an Effect's settings.
void ModifySettings(Function &&function)
Do a correct read-modify-write of settings.
static void DrawPoints(const Envelope &env, TrackPanelDrawingContext &context, const wxRect &r, bool dB, double dBRange, float zoomMin, float zoomMax, bool mirrored, int origin=0)
Piecewise linear or piecewise exponential function from double to double.
void SetTrackLen(double trackLen, double sampleDur=0.0)
void GetValues(double *buffer, int len, double t0, double tstep) const
Get many envelope points at once.
size_t GetNumberOfPoints() const
Return number of points.
int Reassign(double when, double value)
Move a point at when to value.
void GetPoints(double *bufferWhen, double *bufferValue, int bufferLen) const
Returns the sets of when and value pairs.
void Insert(int point, const EnvPoint &p)
insert a point
void Flatten(double value)
EqualizationPanel is used with EqualizationDialog and controls a graph for EffectEqualization....
void OnSize(wxSizeEvent &event)
EffectEqualization * mEffect
void OnCaptureLost(wxMouseCaptureLostEvent &event)
std::unique_ptr< wxBitmap > mBitmap
std::unique_ptr< EnvelopeEditor > mLinEditor
void OnMouseEvent(wxMouseEvent &event)
void OnPaint(wxPaintEvent &event)
std::unique_ptr< EnvelopeEditor > mLogEditor
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
virtual wxString GetPath() const
FILES_API const FileType XMLFiles
std::vector< FileType > FileTypes
void DrawGrid(wxDC &dc, int length, bool minor=true, bool major=true, int xOffset=0, int yOffset=0) const
void GetMaxSize(wxCoord *width, wxCoord *height)
void SetRange(double min, double max)
RulerPanel class allows you to work with a Ruler like any other wxWindow.
std::pair< double, double > Range
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
Retrieve samples from a track in floating-point format, regardless of the storage format.
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
Visitor of effect or command parameters. This is a base class with lots of virtual functions that do ...
virtual void Define(Arg< bool > var, const wxChar *key, bool vdefault, bool vmin=false, bool vmax=false, bool vscl=false)
SettingsVisitor that gets parameter values into a string.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
SettingsVisitor that sets parameters to a value (from a string)
wxColour & Colour(int iIndex)
This class handles the actual rendering of WaveTracks (both waveforms and spectra),...
static TrackList & Get(AudacityProject &project)
auto Selected() -> TrackIterRange< TrackType >
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
A Track that contains audio waveform data.
void Paste(double t0, const Track *src) override
void ConvertToSampleFormat(sampleFormat format, const std::function< void(size_t)> &progressReport={})
size_t GetMaxBlockSize() const override
This returns a nonnegative number of samples meant to size a memory buffer.
void Join(double t0, double t1)
void Clear(double t0, double t1) override
Holder EmptyCopy(const SampleBlockFactoryPtr &pFactory={}) const
WaveClipHolders & GetClips()
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
Reads a file and passes the results through an XMLTagHandler.
const TranslatableString & GetErrorStr() const
bool Parse(XMLTagHandler *baseHandler, const FilePath &fname)
Wrapper to output XML data to files.
This class is an interface which should be implemented by classes which wish to be able to load and s...
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Positions or offsets within audio files need a wide type.
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
FILES_API FilePath ResourcesDir()
FILES_API FilePath DataDir()
Audacity user data directory.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for, if Traits<Type>::iterated_type is defined.
bool SetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, const Value &value)
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
BuiltinEffectsModule::Registration< EffectEqualizationCurve > reg2
BuiltinEffectsModule::Registration< EffectEqualizationGraphic > reg3
void OnClear(wxCommandEvent &e)
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
const Type def
Default value.
Externalized state of a plug-in.
Options & LabelEdges(bool l)