1 /********************************************************************** 2 3 Audacity: A Digital Audio Editor 4 5 Equalization.h 6 7 Mitch Golden 8 Vaughan Johnson (Preview) 9 10 ***********************************************************************/ 11 12 #ifndef __AUDACITY_EFFECT_EQUALIZATION__ 13 #define __AUDACITY_EFFECT_EQUALIZATION__ 14 #define NUMBER_OF_BANDS 31 15 #define NUM_PTS 180 16 #define PANELBORDER 1 // only increase from '1' for testing purposes - MJS 17 18 #include <wx/setup.h> // for wxUSE_* macros 19 20 #include "Effect.h" 21 #include "RealFFTf.h" 22 23 // Flags to specialise the UI 24 const int kEqOptionGraphic =1; 25 const int kEqOptionCurve =1<<1; 26 // The legacy version offers both Graphic and curve on the same UI. 27 const int kEqLegacy = kEqOptionGraphic + kEqOptionCurve; 28 29 class wxBitmap; 30 class wxBoxSizer; 31 class wxButton; 32 class wxCheckBox; 33 class wxChoice; 34 class wxListCtrl; 35 class wxListEvent; 36 class wxRadioButton; 37 class wxSizer; 38 class wxSizerItem; 39 class wxSlider; 40 class wxStaticText; 41 class Envelope; 42 class EnvelopeEditor; 43 class EqualizationPanel; 44 class RulerPanel; 45 46 // 47 // One point in a curve 48 // 49 class EQPoint 50 { 51 public: EQPoint(const double f,const double d)52 EQPoint( const double f, const double d ) { Freq = f; dB = d; } 53 54 bool operator < (const EQPoint &p1) const 55 { 56 return Freq < p1.Freq; 57 } 58 59 double Freq; 60 double dB; 61 }; 62 63 // 64 // One curve in a list 65 // 66 // LLL: This "really" isn't needed as the array of points could be 67 // attached as wxClientData to the wxChoice entries. I 68 // didn't realize this until after the fact and am too 69 // lazy to change it. (But, hollar if you want me to.) 70 // 71 class EQCurve 72 { 73 public: 74 EQCurve( const wxString & name = {} ) { Name = name; } EQCurve(const wxChar * name)75 EQCurve( const wxChar * name ) { Name = name; } 76 77 bool operator < (const EQCurve &that) const 78 { 79 return Name.CmpNoCase(that.Name) < 0; 80 } 81 82 wxString Name; 83 std::vector<EQPoint> points; 84 }; 85 86 using EQCurveArray = std::vector<EQCurve>; 87 88 #ifdef EXPERIMENTAL_EQ_SSE_THREADED 89 class EffectEqualization48x; 90 #endif 91 92 class EffectEqualization : public Effect, 93 public XMLTagHandler 94 { 95 public: 96 static const ComponentInterfaceSymbol Symbol; 97 98 EffectEqualization(int Options = kEqLegacy); 99 100 virtual ~EffectEqualization(); 101 102 // ComponentInterface implementation 103 104 ComponentInterfaceSymbol GetSymbol() override; 105 TranslatableString GetDescription() override; 106 ManualPageID ManualPage() override; 107 108 // EffectDefinitionInterface implementation 109 110 EffectType GetType() override; 111 112 // EffectClientInterface implementation 113 114 bool DefineParams( ShuttleParams & S ) override; 115 bool GetAutomationParameters(CommandParameters & parms) override; 116 bool SetAutomationParameters(CommandParameters & parms) override; 117 bool LoadFactoryDefaults() override; 118 119 RegistryPaths GetFactoryPresets() override; 120 bool LoadFactoryPreset(int id) override; 121 122 // EffectUIClientInterface implementation 123 124 bool ValidateUI() override; 125 126 // Effect implementation 127 128 bool Startup() override; 129 bool Init() override; 130 bool Process() override; 131 132 bool CloseUI() override; 133 void PopulateOrExchange(ShuttleGui & S) override; 134 bool TransferDataToWindow() override; 135 bool TransferDataFromWindow() override; 136 137 private: 138 // EffectEqualization implementation 139 wxString GetPrefsPrefix(); 140 141 // Number of samples in an FFT window 142 static const size_t windowSize = 16384u; //MJS - work out the optimum for this at run time? Have a dialog box for it? 143 144 // Low frequency of the FFT. 20Hz is the 145 // low range of human hearing 146 enum {loFreqI=20}; 147 148 bool ProcessOne(int count, WaveTrack * t, 149 sampleCount start, sampleCount len); 150 bool CalcFilter(); 151 void Filter(size_t len, float *buffer); 152 153 void Flatten(); 154 void ForceRecalc(); 155 void EnvelopeUpdated(); 156 void EnvelopeUpdated(Envelope *env, bool lin); 157 bool IsLinear(); 158 159 void LoadCurves(const wxString &fileName = {}, bool append = false); 160 void SaveCurves(const wxString &fileName = {}); 161 // Merge NEW curves only or update all factory presets. 162 void UpdateDefaultCurves( bool updateAll = false); 163 void Select(int sel); 164 void setCurve(int currentCurve); 165 void setCurve(const wxString &curveName); 166 void setCurve(void); 167 bool GetDefaultFileName(wxFileName &fileName); 168 169 // XMLTagHandler callback methods for loading and saving 170 bool HandleXMLTag(const std::string_view& tag, const AttributesList &attrs) override; 171 XMLTagHandler *HandleXMLChild(const std::string_view& tag) override; 172 void WriteXML(XMLWriter &xmlFile) const; 173 174 void UpdateCurves(); 175 void UpdateDraw(); 176 177 //void LayoutEQSliders(); 178 void UpdateGraphic(void); 179 void EnvLogToLin(void); 180 void EnvLinToLog(void); 181 void ErrMin(void); 182 void GraphicEQ(Envelope *env); 183 void spline(double x[], double y[], size_t n, double y2[]); 184 double splint(double x[], double y[], size_t n, double y2[], double xr); 185 186 void OnErase( wxEvent &event ); 187 void OnSize( wxSizeEvent & event ); 188 void OnSlider( wxCommandEvent & event ); 189 void OnInterp( wxCommandEvent & event ); 190 void OnSliderM( wxCommandEvent & event ); 191 void OnSliderDBMAX( wxCommandEvent & event ); 192 void OnSliderDBMIN( wxCommandEvent & event ); 193 void OnDrawMode( wxCommandEvent &event ); 194 void OnGraphicMode( wxCommandEvent &event ); 195 void OnCurve( wxCommandEvent & event ); 196 void OnManage( wxCommandEvent & event ); 197 void OnClear( wxCommandEvent & event ); 198 void OnInvert( wxCommandEvent & event ); 199 void OnGridOnOff( wxCommandEvent & event ); 200 void OnLinFreq( wxCommandEvent & event ); 201 #ifdef EXPERIMENTAL_EQ_SSE_THREADED 202 void OnProcessingRadio( wxCommandEvent & event ); 203 void OnBench( wxCommandEvent & event ); 204 #endif 205 206 private: 207 int mOptions; 208 HFFT hFFT; 209 Floats mFFTBuffer, mFilterFuncR, mFilterFuncI; 210 size_t mM; 211 wxString mCurveName; 212 bool mLin; 213 float mdBMax; 214 float mdBMin; 215 bool mDrawMode; 216 int mInterp; 217 bool mDrawGrid; 218 219 double mWhens[NUM_PTS]; 220 double mWhenSliders[NUMBER_OF_BANDS+1]; 221 size_t mBandsInUse; 222 RulerPanel *mdBRuler; 223 RulerPanel *mFreqRuler; 224 225 bool mDisallowCustom; 226 double mLoFreq; 227 double mHiFreq; 228 size_t mWindowSize; 229 bool mDirty; 230 int mSlidersOld[NUMBER_OF_BANDS]; 231 double mEQVals[NUMBER_OF_BANDS+1]; 232 233 EQCurveArray mCurves; 234 235 std::unique_ptr<Envelope> mLogEnvelope, mLinEnvelope; 236 Envelope *mEnvelope; 237 238 #ifdef EXPERIMENTAL_EQ_SSE_THREADED 239 bool mBench; 240 std::unique_ptr<EffectEqualization48x> mEffectEqualization48x; 241 friend class EffectEqualization48x; 242 #endif 243 244 wxSizer *szrC; 245 wxSizer *szrG; 246 wxSizer *szrV; 247 wxSizer *szrH; 248 wxSizer *szrI; 249 wxSizer *szrL; 250 wxSizer *szr1; 251 wxSizer *szr2; 252 wxSizer *szr3; 253 wxSizer *szr4; 254 wxSizer *szr5; 255 256 wxSizerItem *mLeftSpacer; 257 258 EqualizationPanel *mPanel; 259 //wxPanel *mGraphicPanel; 260 wxRadioButton *mDraw; 261 wxRadioButton *mGraphic; 262 wxCheckBox *mLinFreq; 263 wxCheckBox *mGridOnOff; 264 wxChoice *mInterpChoice; 265 wxChoice *mCurve; 266 wxButton *mManage; 267 wxStaticText *mMText; 268 wxSlider *mMSlider; 269 wxSlider *mdBMinSlider; 270 wxSlider *mdBMaxSlider; 271 wxSlider *mSliders[NUMBER_OF_BANDS]; 272 273 #ifdef EXPERIMENTAL_EQ_SSE_THREADED 274 wxRadioButton *mMathProcessingType[5]; // default, sse, sse threaded, AVX, AVX threaded (note AVX is not implemented yet 275 wxBoxSizer *szrM; 276 #endif 277 278 DECLARE_EVENT_TABLE() 279 280 friend class EqualizationPanel; 281 friend class EditCurvesDialog; 282 }; 283 284 class EffectEqualizationCurve final : public EffectEqualization 285 { 286 public: 287 static const ComponentInterfaceSymbol Symbol; 288 EffectEqualizationCurve()289 EffectEqualizationCurve() : EffectEqualization( kEqOptionCurve ) {} 290 }; 291 292 class EffectEqualizationGraphic final : public EffectEqualization 293 { 294 public: 295 static const ComponentInterfaceSymbol Symbol; 296 EffectEqualizationGraphic()297 EffectEqualizationGraphic() : EffectEqualization( kEqOptionGraphic ) {} 298 }; 299 300 class EqualizationPanel final : public wxPanelWrapper 301 { 302 public: 303 EqualizationPanel( 304 wxWindow *parent, wxWindowID winid, EffectEqualization *effect); 305 ~EqualizationPanel(); 306 307 // We don't need or want to accept focus. AcceptsFocus()308 bool AcceptsFocus() const { return false; } 309 // So that wxPanel is not included in Tab traversal - see wxWidgets bug 15581 AcceptsFocusFromKeyboard()310 bool AcceptsFocusFromKeyboard() const { return false; } 311 312 void ForceRecalc(); 313 314 private: 315 void Recalc(); 316 317 void OnMouseEvent(wxMouseEvent & event); 318 void OnCaptureLost(wxMouseCaptureLostEvent & event); 319 void OnPaint(wxPaintEvent & event); 320 void OnSize (wxSizeEvent & event); 321 322 public: 323 // int & mM; 324 // float & mdBMax; 325 // float & mdBMin; 326 // Envelope & mEnvelope; 327 328 private: 329 wxWindow *mParent; 330 EffectEqualization *mEffect; 331 std::unique_ptr<EnvelopeEditor> mLinEditor, mLogEditor; 332 333 bool mRecalcRequired; 334 335 std::unique_ptr<wxBitmap> mBitmap; 336 wxRect mEnvRect; 337 int mWidth; 338 int mHeight; 339 // size_t mWindowSize; 340 // float *mFilterFuncR; 341 // float *mFilterFuncI; 342 Floats mOutr, mOuti; 343 344 // double mLoFreq; 345 // double mHiFreq; 346 347 DECLARE_EVENT_TABLE() 348 }; 349 350 // EditCurvesDialog. Note that the 'modified' curve used to be called 'custom' but is now called 'unnamed' 351 // Some things that deal with 'unnamed' curves still use, for example, 'mCustomBackup' as variable names. 352 class EditCurvesDialog final : public wxDialogWrapper 353 { 354 public: 355 EditCurvesDialog(wxWindow * parent, EffectEqualization * effect, int position); 356 ~EditCurvesDialog(); 357 358 private: 359 360 enum EQCurvesDialogControls 361 { 362 CurvesListID = 11000, 363 UpButtonID, 364 DownButtonID, 365 RenameButtonID, 366 DeleteButtonID, 367 ImportButtonID, 368 ExportButtonID, 369 LibraryButtonID, 370 DefaultsButtonID 371 }; 372 373 wxListCtrl *mList; // List of curves. 374 EQCurveArray mEditCurves; // Copy of curves to muck about with 375 wxWindow *mParent; // the parent EQ Dialog 376 EffectEqualization *mEffect; // the parent EQ effect 377 int mPosition; // position of current curve in list 378 void Populate(); 379 void PopulateOrExchange(ShuttleGui &S); 380 void PopulateList(int position); 381 void OnUp(wxCommandEvent &event); 382 void OnDown(wxCommandEvent &event); 383 long GetPreviousItem(long item); 384 void OnRename( wxCommandEvent &event ); 385 void OnDelete( wxCommandEvent &event ); 386 void OnImport( wxCommandEvent &event ); 387 void OnExport( wxCommandEvent &event ); 388 void OnLibrary( wxCommandEvent &event ); 389 void OnDefaults( wxCommandEvent &event ); 390 void OnOK(wxCommandEvent &event); 391 392 void OnListSelectionChange( wxListEvent &event ); 393 DECLARE_EVENT_TABLE() 394 }; 395 396 #endif 397