Audacity  3.0.3
FreqWindow.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  FreqWindow.cpp
6 
7  Dominic Mazzoni
8 
9 *******************************************************************//****************************************************************//*******************************************************************/
28 
29 /*
30  Salvo Ventura - November 2006
31  Extended range check for additional FFT windows
32 */
33 
34 
35 
36 #include "FreqWindow.h"
37 
38 #include <algorithm>
39 
40 #include <wx/setup.h> // for wxUSE_* macros
41 
42 #include <wx/brush.h>
43 #include <wx/button.h>
44 #include <wx/checkbox.h>
45 #include <wx/choice.h>
46 #include <wx/dcclient.h>
47 #include <wx/dcmemory.h>
48 #include <wx/font.h>
49 #include <wx/image.h>
50 #include <wx/file.h>
51 #include <wx/intl.h>
52 #include <wx/scrolbar.h>
53 #include <wx/sizer.h>
54 #include <wx/slider.h>
55 #include <wx/statbmp.h>
56 #include <wx/stattext.h>
57 #include <wx/statusbr.h>
58 
59 #include <wx/textctrl.h>
60 #include <wx/textfile.h>
61 
62 #include <wx/wfstream.h>
63 #include <wx/txtstrm.h>
64 
65 #include <math.h>
66 
67 #include "ShuttleGui.h"
68 #include "AColor.h"
69 #include "CommonCommandFlags.h"
70 #include "FFT.h"
71 #include "PitchName.h"
72 #include "prefs/GUISettings.h"
73 #include "Prefs.h"
74 #include "Project.h"
75 #include "ProjectWindow.h"
76 #include "Theme.h"
77 #include "ViewInfo.h"
78 #include "AllThemeResources.h"
79 
80 #include "FileNames.h"
81 
82 #include "WaveTrack.h"
83 
84 #include "./widgets/HelpSystem.h"
86 #include "widgets/Ruler.h"
87 
88 #if wxUSE_ACCESSIBILITY
90 #endif
91 
92 #define FrequencyAnalysisTitle XO("Frequency Analysis")
93 
94 DEFINE_EVENT_TYPE(EVT_FREQWINDOW_RECALC);
95 
96 enum {
97  FirstID = 7000,
98 
108 };
109 
110 // These specify the minimum plot window width
111 
112 #define FREQ_WINDOW_WIDTH 480
113 #define FREQ_WINDOW_HEIGHT 330
114 
115 
116 static const char * ZoomIn[] = {
117 "16 16 6 1",
118 " c None",
119 "+ c #1C1C1C",
120 "@ c #AEAEAE",
121 "# c #F7F7F7",
122 "$ c #CFCECC",
123 "* c #1C1CA0",
124 " ++++ ",
125 " @+# @[email protected] ",
126 " + @** [email protected] ",
127 " +#@ ** #+ ",
129 " + ****** [email protected]",
130 " +# ** #[email protected]",
131 " + ** [email protected]@",
132 " +++# #[email protected]@ ",
134 " [email protected]@ @@@@ ",
135 " [email protected]@ ",
136 " [email protected]@ ",
138 "@[email protected]@ ",
139 " @@ "};
140 
141 
142 static const char * ZoomOut[] = {
143 "16 16 6 1",
144 " c None",
145 "+ c #1C1C1C",
146 "@ c #AEAEAE",
147 "# c #F7F7F7",
148 "$ c #CFCECC",
149 "* c #1C1CA0",
150 " ++++ ",
151 " @+# [email protected] ",
152 " + @@ [email protected] ",
153 " +# @ #+ ",
155 " + ****** [email protected]",
156 " +# #[email protected]",
157 " + [email protected]@",
158 " +++# #[email protected]@ ",
160 " [email protected]@ @@@@ ",
161 " [email protected]@ ",
162 " [email protected]@ ",
164 "@[email protected]@ ",
165 " @@ "};
166 
167 // FrequencyPlotDialog
168 
169 BEGIN_EVENT_TABLE(FrequencyPlotDialog, wxDialogWrapper)
183  EVT_COMMAND(wxID_ANY, EVT_FREQWINDOW_RECALC, FrequencyPlotDialog::OnRecalc)
185 
186 FrequencyPlotDialog::FrequencyPlotDialog(wxWindow * parent, wxWindowID id,
187  AudacityProject &project,
188  const TranslatableString & title,
189  const wxPoint & pos)
190 : wxDialogWrapper(parent, id, title, pos, wxDefaultSize,
191  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX),
192  mAnalyst(std::make_unique<SpectrumAnalyst>())
193 , mProject{ &project }
194 {
195  SetName();
196 
197  mMouseX = 0;
198  mMouseY = 0;
199  mRate = 0;
200  mDataLen = 0;
201 
202  gPrefs->Read(wxT("/FrequencyPlotDialog/DrawGrid"), &mDrawGrid, true);
203  gPrefs->Read(wxT("/FrequencyPlotDialog/SizeChoice"), &mSize, 3);
204 
205  int alg;
206  gPrefs->Read(wxT("/FrequencyPlotDialog/AlgChoice"), &alg, 0);
207  mAlg = static_cast<SpectrumAnalyst::Algorithm>(alg);
208 
209  gPrefs->Read(wxT("/FrequencyPlotDialog/FuncChoice"), &mFunc, 3);
210  gPrefs->Read(wxT("/FrequencyPlotDialog/AxisChoice"), &mAxis, 1);
211 
212  Populate();
213 }
214 
215 FrequencyPlotDialog::~FrequencyPlotDialog()
216 {
217 }
218 
220 {
222 
223  TranslatableStrings algChoices{
224  XO("Spectrum") ,
225  XO("Standard Autocorrelation") ,
226  XO("Cuberoot Autocorrelation") ,
227  XO("Enhanced Autocorrelation") ,
228  /* i18n-hint: This is a technical term, derived from the word
229  * "spectrum". Do not translate it unless you are sure you
230  * know the correct technical word in your language. */
231  XO("Cepstrum") ,
232  };
233 
234  TranslatableStrings sizeChoices{
235  Verbatim( "128" ) ,
236  Verbatim( "256" ) ,
237  Verbatim( "512" ) ,
238  Verbatim( "1024" ) ,
239  Verbatim( "2048" ) ,
240  Verbatim( "4096" ) ,
241  Verbatim( "8192" ) ,
242  Verbatim( "16384" ) ,
243  Verbatim( "32768" ) ,
244  Verbatim( "65536" ) ,
245  };
246 
247  TranslatableStrings funcChoices;
248  for (int i = 0, cnt = NumWindowFuncs(); i < cnt; i++)
249  {
250  funcChoices.push_back(
251  /* i18n-hint: This refers to a "window function",
252  * such as Hann or Rectangular, used in the
253  * Frequency analyze dialog box. */
254  XO("%s window").Format( WindowFuncName(i) ) );
255  }
256 
257  TranslatableStrings axisChoices{
258  XO("Linear frequency") ,
259  XO("Log frequency") ,
260  };
261 
262  mFreqFont = wxFont(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
263  mArrowCursor = std::make_unique<wxCursor>(wxCURSOR_ARROW);
264  mCrossCursor = std::make_unique<wxCursor>(wxCURSOR_CROSS);
265 
266  long size;
267  // reinterpret one of the verbatim strings above as a number
268  sizeChoices[mSize].MSGID().GET().ToLong(&size);
269  mWindowSize = size;
270 
272  if(dBRange < 90.)
273  dBRange = 90.;
274 
275  ShuttleGui S(this, eIsCreating);
276 
277  S.SetBorder(0);
278 
279  S.AddSpace(5);
280 
281  S.SetSizerProportion(1);
282  S.StartMultiColumn(3, wxEXPAND);
283  {
284  S.SetStretchyCol(1);
285  S.SetStretchyRow(0);
286 
287  // -------------------------------------------------------------------
288  // ROW 1: Freq response panel and sliders for vertical scale
289  // -------------------------------------------------------------------
290 
291  S.StartVerticalLay(2);
292  {
294  S.GetParent(), wxID_ANY, wxVERTICAL,
295  wxSize{ 100, 100 }, // Ruler can't handle small sizes
296  RulerPanel::Range{ 0.0, -dBRange },
298  XO("dB"),
300  .LabelEdges(true)
301  .TickColour( theTheme.Colour( clrGraphLabels ) )
302  );
303 
304  S.AddSpace(wxDefaultCoord, 1);
305  S.Prop(1)
306  .Position(wxALIGN_RIGHT | wxALIGN_TOP)
307  .AddWindow(vRuler);
308  S.AddSpace(wxDefaultCoord, 1);
309  }
310  S.EndVerticalLay();
311 
312  mFreqPlot = safenew FreqPlot(S.GetParent(), wxID_ANY);
313  S.Prop(1)
314  .Position(wxEXPAND)
315  .MinSize( { wxDefaultCoord, FREQ_WINDOW_HEIGHT } )
316  .AddWindow(mFreqPlot);
317 
318  S.StartHorizontalLay(wxEXPAND, 0);
319  {
320  S.StartVerticalLay();
321  {
322  mPanScroller = safenew wxScrollBar(S.GetParent(), FreqPanScrollerID,
323  wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL);
324 #if wxUSE_ACCESSIBILITY
325  // so that name can be set on a standard control
327 #endif
328  S.Prop(1);
329  S
330  .Name(XO("Scroll"))
331  .Position( wxALIGN_LEFT | wxTOP)
333  }
334  S.EndVerticalLay();
335 
336  S.StartVerticalLay();
337  {
338  wxStaticBitmap *zi = safenew wxStaticBitmap(S.GetParent(), wxID_ANY, wxBitmap(ZoomIn));
339  S.Position(wxALIGN_CENTER)
340  .AddWindow(zi);
341 
342  S.AddSpace(5);
343 
345  wxDefaultPosition, wxDefaultSize, wxSL_VERTICAL);
346  S.Prop(1);
347  S
348  .Name(XO("Zoom"))
349  .Position(wxALIGN_CENTER_HORIZONTAL)
351 #if wxUSE_ACCESSIBILITY
352  // so that name can be set on a standard control
354 #endif
355 
356  S.AddSpace(5);
357 
358  wxStaticBitmap *zo = safenew wxStaticBitmap(S.GetParent(), wxID_ANY, wxBitmap(ZoomOut));
359  S.Position(wxALIGN_CENTER)
360  .AddWindow(zo);
361  }
362  S.EndVerticalLay();
363 
364  S.AddSpace(5, wxDefaultCoord);
365  }
366  S.EndHorizontalLay();
367 
368  // -------------------------------------------------------------------
369  // ROW 2: Frequency ruler
370  // -------------------------------------------------------------------
371 
372  S.AddSpace(1);
373 
374  S.StartHorizontalLay(wxEXPAND, 0);
375  {
377  S.GetParent(), wxID_ANY, wxHORIZONTAL,
378  wxSize{ 100, 100 }, // Ruler can't handle small sizes
379  RulerPanel::Range{ 10, 20000 },
381  XO("Hz"),
383  .Log(true)
384  .Flip(true)
385  .LabelEdges(true)
386  .TickColour( theTheme.Colour( clrGraphLabels ) )
387  );
388 
389  S.AddSpace(1, wxDefaultCoord);
390  S.Prop(1)
391  .Position(wxALIGN_LEFT | wxALIGN_TOP)
392  .AddWindow(hRuler);
393  S.AddSpace(1, wxDefaultCoord);
394  }
395  S.EndHorizontalLay();
396 
397  S.AddSpace(1);
398 
399  // -------------------------------------------------------------------
400  // ROW 3: Spacer
401  // -------------------------------------------------------------------
402  S.AddSpace(5);
403  S.AddSpace(5);
404  S.AddSpace(5);
405 
406  // -------------------------------------------------------------------
407  // ROW 4: Info
408  // -------------------------------------------------------------------
409 
410  S.AddSpace(1);
411 
412  S.StartHorizontalLay(wxEXPAND);
413  {
414  S.SetSizerProportion(1);
415  S.StartMultiColumn(6);
416  S.SetStretchyCol(1);
417  S.SetStretchyCol(3);
418  {
419  S.AddPrompt(XXO("Cursor:"));
420 
421  mCursorText = S.Style(wxTE_READONLY)
422  .AddTextBox( {}, wxT(""), 10);
423 
424  S.AddPrompt(XXO("Peak:"));
425 
426  mPeakText = S.Style(wxTE_READONLY)
427  .AddTextBox( {}, wxT(""), 10);
428  S.AddSpace(5);
429 
431  }
432  S.EndMultiColumn();
433  }
434  S.EndHorizontalLay();
435 
436  S.AddSpace(1);
437  }
438  S.EndMultiColumn();
439 
440  // -------------------------------------------------------------------
441  // ROW 5: Spacer
442  // -------------------------------------------------------------------
443 
444  S.AddSpace(5);
445 
446  S.SetBorder(2);
447  S.SetSizerProportion(0);
448  S.StartMultiColumn(9, wxALIGN_CENTER);
449  {
450  // ----------------------------------------------------------------
451  // ROW 6: Algorithm, Size, Export, Replot
452  // ----------------------------------------------------------------
453 
454  S.AddSpace(5);
455 
457  .MinSize( { wxDefaultCoord, wxDefaultCoord } )
458  .AddChoice(XXO("&Algorithm:"), algChoices, mAlg);
459 
460  S.AddSpace(5);
461 
463  .MinSize( { wxDefaultCoord, wxDefaultCoord } )
464  .AddChoice(XXO("&Size:"), sizeChoices, mSize);
465 
466  S.AddSpace(5);
467 
468  mExportButton = S.Id(FreqExportButtonID).AddButton(XXO("&Export..."));
469 
470  S.AddSpace(5);
471 
472 
473  // ----------------------------------------------------------------
474  // ROW 7: Function, Axix, Grids, Close
475  // ----------------------------------------------------------------
476 
477  S.AddSpace(5);
478 
480  .MinSize( { wxDefaultCoord, wxDefaultCoord } )
481  .AddChoice(XXO("&Function:"), funcChoices, mFunc);
482  mFuncChoice->MoveAfterInTabOrder(mSizeChoice);
483 
484  S.AddSpace(5);
485 
487  .MinSize( { wxDefaultCoord, wxDefaultCoord } )
488  .AddChoice(XXO("&Axis:"), axisChoices, mAxis);
489  mAxisChoice->MoveAfterInTabOrder(mFuncChoice);
490 
491  S.AddSpace(5);
492 
493  mReplotButton = S.Id(ReplotButtonID).AddButton(XXO("&Replot..."));
494 
495  S.AddSpace(5);
496 
497  //mCloseButton = S.Id(wxID_CANCEL).AddButton(XO("&Close"));
498 
499  //S.AddSpace(5);
500  }
501  S.EndMultiColumn();
503 
504  // -------------------------------------------------------------------
505  // ROW 8: Spacer
506  // -------------------------------------------------------------------
507 
508  S.AddSpace(5);
509 
510  mProgress = safenew FreqGauge(S.GetParent(), wxID_ANY); //, wxST_SIZEGRIP);
511  S.Position(wxEXPAND)
513 
514  // Log-frequency axis works for spectrum plots only.
516  {
517  mAxis = 0;
518  mAxisChoice->Disable();
519  }
520  mLogAxis = mAxis != 0;
521 
522  mCloseButton = static_cast<wxButton*>(FindWindowById( wxID_CANCEL ));
523  mCloseButton->SetDefault();
524 
525  Layout();
526  Fit();
527  // Bug 1607:
528  Center();
529 
530  SetMinSize(GetSize());
531 
532 #if defined(__WXGTK__)
533  // This should be rechecked with wx3.
534  //
535  // The scrollbar (focus some reason) doesn't allow tabbing past it
536  // because it can't receive focus. So, convince it otherwise.
537  //
538  // Unfortunately, this still doesn't let you adjust the scrollbar
539  // from the keyboard. Near as I can tell, wxWGTK is capturing the
540  // keyboard input, so the GTK widget doesn't see it, preventing
541  // the normal scroll events from being generated.
542  //
543  // I guess the only way round it would be to handle key actions
544  // ourselves, but we'll leave that for a future date.
545 // gtk_widget_set_can_focus(mPanScroller->m_widget, true);
546 #endif
547 }
548 
549 void FrequencyPlotDialog::OnGetURL(wxCommandEvent & WXUNUSED(event))
550 {
551  // Original help page is back on-line (March 2016), but the manual should be more reliable.
552  // http://www.eramp.com/WCAG_2_audio_contrast_tool_help.htm
553  HelpSystem::ShowHelp(this, L"Plot Spectrum");
554 }
555 
557 {
558  if (!show)
559  {
560  mFreqPlot->SetCursor(*mArrowCursor);
561  }
562 
563  bool shown = IsShown();
564 
565  if (show && !shown)
566  {
568  if(dBRange < 90.)
569  dBRange = 90.;
570  GetAudio();
571  // Don't send an event. We need the recalc right away.
572  // so that mAnalyst is valid when we paint.
573  //SendRecalcEvent();
574  Recalc();
575  }
576 
577  bool res = wxDialogWrapper::Show(show);
578 
579  return res;
580 }
581 
583 {
584  mData.reset();
585  mDataLen = 0;
586 
587  int selcount = 0;
588  bool warning = false;
589  for (auto track : TrackList::Get( *mProject ).Selected< const WaveTrack >()) {
590  auto &selectedRegion = ViewInfo::Get( *mProject ).selectedRegion;
591  if (selcount==0) {
592  mRate = track->GetRate();
593  auto start = track->TimeToLongSamples(selectedRegion.t0());
594  auto end = track->TimeToLongSamples(selectedRegion.t1());
595  auto dataLen = end - start;
596  if (dataLen > 10485760) {
597  warning = true;
598  mDataLen = 10485760;
599  }
600  else
601  // dataLen is not more than 10 * 2 ^ 20
602  mDataLen = dataLen.as_size_t();
603  mData = Floats{ mDataLen };
604  // Don't allow throw for bad reads
605  track->GetFloats(mData.get(), start, mDataLen,
606  fillZero, false);
607  }
608  else {
609  if (track->GetRate() != mRate) {
611  XO(
612 "To plot the spectrum, all selected tracks must be the same sample rate.") );
613  mData.reset();
614  mDataLen = 0;
615  return;
616  }
617  auto start = track->TimeToLongSamples(selectedRegion.t0());
618  Floats buffer2{ mDataLen };
619  // Again, stop exceptions
620  track->GetFloats(buffer2.get(), start, mDataLen,
621  fillZero, false);
622  for (size_t i = 0; i < mDataLen; i++)
623  mData[i] += buffer2[i];
624  }
625  selcount++;
626  }
627 
628  if (selcount == 0)
629  return;
630 
631  if (warning) {
632  auto msg = XO(
633 "Too much audio was selected. Only the first %.1f seconds of audio will be analyzed.")
634  .Format(mDataLen / mRate);
635  AudacityMessageBox( msg );
636  }
637 }
638 
639 void FrequencyPlotDialog::OnSize(wxSizeEvent & WXUNUSED(event))
640 {
641  Layout();
642 
643  DrawPlot();
644 
645  Refresh(true);
646 }
647 
649 {
650  Layout();
651 
652  mBitmap.reset();
653 
654  mPlotRect = mFreqPlot->GetClientRect();
655 
656  mBitmap = std::make_unique<wxBitmap>(mPlotRect.width, mPlotRect.height,24);
657 
658  dc.SelectObject(*mBitmap);
659 
660  dc.SetBackground(wxBrush(wxColour(254, 254, 254)));// DONT-THEME Mask colour.
661  dc.Clear();
662 
663  dc.SetPen(*wxBLACK_PEN);
664  dc.SetBrush(*wxWHITE_BRUSH);
665  dc.DrawRectangle(mPlotRect);
666 
667  dc.SetFont(mFreqFont);
668 }
669 
671 {
672  if (!mData || mDataLen < mWindowSize || mAnalyst->GetProcessedSize() == 0) {
673  wxMemoryDC memDC;
674 
675  vRuler->ruler.SetLog(false);
676  vRuler->ruler.SetRange(0.0, -dBRange);
677 
678  hRuler->ruler.SetLog(false);
679  hRuler->ruler.SetRange(0, 1);
680 
681  DrawBackground(memDC);
682 
683  if (mDataLen < mWindowSize) {
684  wxString msg = _("Not enough data selected.");
685  wxSize sz = memDC.GetTextExtent(msg);
686  memDC.DrawText(msg,
687  (mPlotRect.GetWidth() - sz.GetWidth()) / 2,
688  (mPlotRect.GetHeight() - sz.GetHeight()) / 2);
689  }
690 
691  memDC.SelectObject(wxNullBitmap);
692 
693  mFreqPlot->Refresh();
694 
695  Refresh();
696 
697  return;
698  }
699 
700  float yRange = mYMax - mYMin;
701  float yTotal = yRange * ((float) mZoomSlider->GetValue() / 100.0f);
702 
703  int sTotal = yTotal * 100;
704  int sRange = yRange * 100;
705  int sPos = mPanScroller->GetThumbPosition() + ((mPanScroller->GetThumbSize() - sTotal) / 2);
706  mPanScroller->SetScrollbar(sPos, sTotal, sRange, sTotal);
707 
708  float yMax = mYMax - ((float)sPos / 100);
709  float yMin = yMax - yTotal;
710 
711  // Set up y axis ruler
712 
714  vRuler->ruler.SetUnits(XO("dB"));
716  } else {
717  vRuler->ruler.SetUnits({});
719  }
720  int w1, w2, h;
721  vRuler->ruler.GetMaxSize(&w1, &h);
722  vRuler->ruler.SetRange(yMax, yMin); // Note inversion for vertical.
723  vRuler->ruler.GetMaxSize(&w2, &h);
724  if( w1 != w2 ) // Reduces flicker
725  {
726  vRuler->SetMinSize(wxSize(w2,h));
727  Layout();
728  }
729  vRuler->Refresh(false);
730 
731  wxMemoryDC memDC;
732  DrawBackground(memDC);
733 
734  // Get the plot dimensions
735  //
736  // Must be done after setting the vertical ruler above since the
737  // the width could change.
738  wxRect r = mPlotRect;
739 
740  // Set up x axis ruler
741 
742  int width = r.width - 2;
743 
744  float xMin, xMax, xRatio, xStep;
745 
747  xMin = mRate / mWindowSize;
748  xMax = mRate / 2;
749  xRatio = xMax / xMin;
750  if (mLogAxis)
751  {
752  xStep = pow(2.0f, (log(xRatio) / log(2.0f)) / width);
753  hRuler->ruler.SetLog(true);
754  }
755  else
756  {
757  xStep = (xMax - xMin) / width;
758  hRuler->ruler.SetLog(false);
759  }
760  hRuler->ruler.SetUnits(XO("Hz"));
761  } else {
762  xMin = 0;
763  xMax = mAnalyst->GetProcessedSize() / mRate;
764  xStep = (xMax - xMin) / width;
765  hRuler->ruler.SetLog(false);
766  /* i18n-hint: short form of 'seconds'.*/
767  hRuler->ruler.SetUnits(XO("s"));
768  }
769  hRuler->ruler.SetRange(xMin, xMax-xStep);
770  hRuler->Refresh(false);
771 
772  // Draw the plot
774  memDC.SetPen(wxPen(theTheme.Colour( clrHzPlot ), 1, wxPENSTYLE_SOLID));
775  else
776  memDC.SetPen(wxPen(theTheme.Colour( clrWavelengthPlot), 1, wxPENSTYLE_SOLID));
777 
778  float xPos = xMin;
779 
780  for (int i = 0; i < width; i++) {
781  float y;
782 
783  if (mLogAxis)
784  y = mAnalyst->GetProcessedValue(xPos, xPos * xStep);
785  else
786  y = mAnalyst->GetProcessedValue(xPos, xPos + xStep);
787 
788  float ynorm = (y - yMin) / yTotal;
789 
790  int lineheight = (int)(ynorm * (r.height - 1));
791 
792  if (lineheight > r.height - 2)
793  lineheight = r.height - 2;
794 
795  if (ynorm > 0.0)
796  AColor::Line(memDC, r.x + 1 + i, r.y + r.height - 1 - lineheight,
797  r.x + 1 + i, r.y + r.height - 1);
798 
799  if (mLogAxis)
800  xPos *= xStep;
801  else
802  xPos += xStep;
803  }
804 
805  // Outline the graph
806  memDC.SetPen(*wxBLACK_PEN);
807  memDC.SetBrush(*wxTRANSPARENT_BRUSH);
808  memDC.DrawRectangle(r);
809 
810  if(mDrawGrid)
811  {
812  hRuler->ruler.DrawGrid(memDC, r.height, true, true, 1, 1);
813  vRuler->ruler.DrawGrid(memDC, r.width, true, true, 1, 1);
814  }
815 
816  memDC.SelectObject( wxNullBitmap );
817 
818  mFreqPlot->Refresh();
819 }
820 
821 
822 void FrequencyPlotDialog::PlotMouseEvent(wxMouseEvent & event)
823 {
824  if (event.Moving() && (event.m_x != mMouseX || event.m_y != mMouseY)) {
825  mMouseX = event.m_x;
826  mMouseY = event.m_y;
827 
828  if (mPlotRect.Contains(mMouseX, mMouseY))
829  mFreqPlot->SetCursor(*mCrossCursor);
830  else
831  mFreqPlot->SetCursor(*mArrowCursor);
832 
833  mFreqPlot->Refresh(false);
834  }
835 }
836 
837 void FrequencyPlotDialog::OnPanScroller(wxScrollEvent & WXUNUSED(event))
838 {
839  DrawPlot();
840 }
841 
842 void FrequencyPlotDialog::OnZoomSlider(wxCommandEvent & WXUNUSED(event))
843 {
844  DrawPlot();
845 }
846 
847 void FrequencyPlotDialog::OnAlgChoice(wxCommandEvent & WXUNUSED(event))
848 {
849  mAlg = SpectrumAnalyst::Algorithm(mAlgChoice->GetSelection());
850 
851  // Log-frequency axis works for spectrum plots only.
853  mAxisChoice->Enable(true);
854  mLogAxis = mAxisChoice->GetSelection() ? true : false;
855  }
856  else {
857  mAxisChoice->Disable();
858  mLogAxis = false;
859  }
860 
861  SendRecalcEvent();
862 }
863 
864 void FrequencyPlotDialog::OnSizeChoice(wxCommandEvent & WXUNUSED(event))
865 {
866  long windowSize = 0;
867  mSizeChoice->GetStringSelection().ToLong(&windowSize);
868  mWindowSize = windowSize;
869 
870  SendRecalcEvent();
871 }
872 
873 void FrequencyPlotDialog::OnFuncChoice(wxCommandEvent & WXUNUSED(event))
874 {
875  SendRecalcEvent();
876 }
877 
878 void FrequencyPlotDialog::OnAxisChoice(wxCommandEvent & WXUNUSED(event))
879 {
880  mLogAxis = mAxisChoice->GetSelection() ? true : false;
881  DrawPlot();
882 }
883 
884 void FrequencyPlotDialog::PlotPaint(wxPaintEvent & event)
885 {
886  wxPaintDC dc( (wxWindow *) event.GetEventObject() );
887 
888  dc.DrawBitmap( *mBitmap, 0, 0, true );
889  // Fix for Bug 1226 "Plot Spectrum freezes... if insufficient samples selected"
890  if (!mData || mDataLen < mWindowSize)
891  return;
892 
893  dc.SetFont(mFreqFont);
894 
895  wxRect r = mPlotRect;
896 
897  int width = r.width - 2;
898 
899  float xMin, xMax, xRatio, xStep;
900 
902  xMin = mRate / mWindowSize;
903  xMax = mRate / 2;
904  xRatio = xMax / xMin;
905  if (mLogAxis)
906  xStep = pow(2.0f, (log(xRatio) / log(2.0f)) / width);
907  else
908  xStep = (xMax - xMin) / width;
909  } else {
910  xMin = 0;
911  xMax = mAnalyst->GetProcessedSize() / mRate;
912  xStep = (xMax - xMin) / width;
913  }
914 
915  float xPos = xMin;
916 
917  // Find the peak nearest the cursor and plot it
918  if ( r.Contains(mMouseX, mMouseY) & (mMouseX!=0) & (mMouseX!=r.width-1) ) {
919  if (mLogAxis)
920  xPos = xMin * pow(xStep, mMouseX - (r.x + 1));
921  else
922  xPos = xMin + xStep * (mMouseX - (r.x + 1));
923 
924  float bestValue = 0;
925  float bestpeak = mAnalyst->FindPeak(xPos, &bestValue);
926 
927  int px;
928  if (mLogAxis)
929  px = (int)(log(bestpeak / xMin) / log(xStep));
930  else
931  px = (int)((bestpeak - xMin) * width / (xMax - xMin));
932 
933  dc.SetPen(wxPen(wxColour(160,160,160), 1, wxPENSTYLE_SOLID));
934  AColor::Line(dc, r.x + 1 + px, r.y, r.x + 1 + px, r.y + r.height);
935 
936  // print out info about the cursor location
937 
938  float value;
939 
940  if (mLogAxis) {
941  xPos = xMin * pow(xStep, mMouseX - (r.x + 1));
942  value = mAnalyst->GetProcessedValue(xPos, xPos * xStep);
943  } else {
944  xPos = xMin + xStep * (mMouseX - (r.x + 1));
945  value = mAnalyst->GetProcessedValue(xPos, xPos + xStep);
946  }
947 
948  TranslatableString cursor;
949  TranslatableString peak;
950 
952  auto xp = PitchName_Absolute(FreqToMIDInote(xPos));
953  auto pp = PitchName_Absolute(FreqToMIDInote(bestpeak));
954  /* i18n-hint: The %d's are replaced by numbers, the %s by musical notes, e.g. A#*/
955  cursor = XO("%d Hz (%s) = %d dB")
956  .Format( (int)(xPos + 0.5), xp, (int)(value + 0.5));
957  /* i18n-hint: The %d's are replaced by numbers, the %s by musical notes, e.g. A#*/
958  peak = XO("%d Hz (%s) = %.1f dB")
959  .Format( (int)(bestpeak + 0.5), pp, bestValue );
960  } else if (xPos > 0.0 && bestpeak > 0.0) {
961  auto xp = PitchName_Absolute(FreqToMIDInote(1.0 / xPos));
962  auto pp = PitchName_Absolute(FreqToMIDInote(1.0 / bestpeak));
963  /* i18n-hint: The %d's are replaced by numbers, the %s by musical notes, e.g. A#
964  * the %.4f are numbers, and 'sec' should be an abbreviation for seconds */
965  cursor = XO("%.4f sec (%d Hz) (%s) = %f")
966  .Format( xPos, (int)(1.0 / xPos + 0.5), xp, value );
967  /* i18n-hint: The %d's are replaced by numbers, the %s by musical notes, e.g. A#
968  * the %.4f are numbers, and 'sec' should be an abbreviation for seconds */
969  peak = XO("%.4f sec (%d Hz) (%s) = %.3f")
970  .Format( bestpeak, (int)(1.0 / bestpeak + 0.5), pp, bestValue );
971  }
972  mCursorText->SetValue( cursor.Translation() );
973  mPeakText->SetValue( peak.Translation() );
974  }
975  else {
976  mCursorText->SetValue(wxT(""));
977  mPeakText->SetValue(wxT(""));
978  }
979 
980 
981  // Outline the graph
982  dc.SetPen(*wxBLACK_PEN);
983  dc.SetBrush(*wxTRANSPARENT_BRUSH);
984  dc.DrawRectangle(r);
985 }
986 
987 void FrequencyPlotDialog::OnCloseWindow(wxCloseEvent & WXUNUSED(event))
988 {
989  Show(false);
990 }
991 
992 void FrequencyPlotDialog::OnCloseButton(wxCommandEvent & WXUNUSED(event))
993 {
994  gPrefs->Write(wxT("/FrequencyPlotDialog/DrawGrid"), mDrawGrid);
995  gPrefs->Write(wxT("/FrequencyPlotDialog/SizeChoice"), mSizeChoice->GetSelection());
996  gPrefs->Write(wxT("/FrequencyPlotDialog/AlgChoice"), mAlgChoice->GetSelection());
997  gPrefs->Write(wxT("/FrequencyPlotDialog/FuncChoice"), mFuncChoice->GetSelection());
998  gPrefs->Write(wxT("/FrequencyPlotDialog/AxisChoice"), mAxisChoice->GetSelection());
999  gPrefs->Flush();
1000  Show(false);
1001 }
1002 
1004 {
1005  wxCommandEvent e(EVT_FREQWINDOW_RECALC, wxID_ANY);
1006  GetEventHandler()->AddPendingEvent(e);
1007 }
1008 
1010 {
1011  if (!mData || mDataLen < mWindowSize) {
1012  DrawPlot();
1013  return;
1014  }
1015 
1017  SpectrumAnalyst::Algorithm(mAlgChoice->GetSelection());
1018  int windowFunc = mFuncChoice->GetSelection();
1019 
1020  wxWindow *hadFocus = FindFocus();
1021  // In wxMac, the skipped window MUST be a top level window. I'd originally made it
1022  // just the mProgress window with the idea of preventing user interaction with the
1023  // controls while the plot was being recalculated. This doesn't appear to be necessary
1024  // so just use the top level window instead.
1025  {
1027  if (IsShown())
1028  blocker.emplace(this);
1029  wxYieldIfNeeded();
1030 
1031  mAnalyst->Calculate(alg, windowFunc, mWindowSize, mRate,
1032  mData.get(), mDataLen,
1033  &mYMin, &mYMax, mProgress);
1034  }
1035  if (hadFocus) {
1036  hadFocus->SetFocus();
1037  }
1038 
1039  if (alg == SpectrumAnalyst::Spectrum) {
1040  if(mYMin < -dBRange)
1041  mYMin = -dBRange;
1042  if(mYMax <= -dBRange)
1043  mYMax = -dBRange + 10.; // it's all out of range, but show a scale.
1044  else
1045  mYMax += .5;
1046  }
1047 
1048  // Prime the scrollbar
1049  mPanScroller->SetScrollbar(0, (mYMax - mYMin) * 100, (mYMax - mYMin) * 100, 1);
1050 
1051  DrawPlot();
1052 }
1053 
1054 void FrequencyPlotDialog::OnExport(wxCommandEvent & WXUNUSED(event))
1055 {
1056  wxString fName = _("spectrum.txt");
1057 
1058  fName = FileNames::SelectFile(FileNames::Operation::Export,
1059  XO("Export Spectral Data As:"),
1060  wxEmptyString,
1061  fName,
1062  wxT("txt"),
1064  wxFD_SAVE | wxRESIZE_BORDER,
1065  this);
1066 
1067  if (fName.empty())
1068  return;
1069 
1070  wxFFileOutputStream ffStream{ fName };
1071  if (!ffStream.IsOk()) {
1072  AudacityMessageBox( XO("Couldn't write to file: %s").Format( fName ) );
1073  return;
1074  }
1075 
1076  wxTextOutputStream ss(ffStream);
1077 
1078  const int processedSize = mAnalyst->GetProcessedSize();
1079  const float *const processed = mAnalyst->GetProcessed();
1080  if (mAlgChoice->GetSelection() == 0) {
1081  ss
1082  << XO("Frequency (Hz)\tLevel (dB)") << '\n';
1083  for (int i = 1; i < processedSize; i++)
1084  ss
1085  << wxString::Format(wxT("%f\t%f\n"),
1086  i * mRate / mWindowSize, processed[i] );
1087  }
1088  else {
1089  ss
1090  << XO("Lag (seconds)\tFrequency (Hz)\tLevel") << '\n';
1091  for (int i = 1; i < processedSize; i++)
1092  ss
1093  << wxString::Format(wxT("%f\t%f\t%f\n"),
1094  i / mRate, mRate / i, processed[i] );
1095  }
1096 }
1097 
1098 void FrequencyPlotDialog::OnReplot(wxCommandEvent & WXUNUSED(event))
1099 {
1101  if(dBRange < 90.)
1102  dBRange = 90.;
1103  GetAudio();
1104  SendRecalcEvent();
1105 }
1106 
1107 void FrequencyPlotDialog::OnGridOnOff(wxCommandEvent & WXUNUSED(event))
1108 {
1109  mDrawGrid = mGridOnOff->IsChecked();
1110 
1111  DrawPlot();
1112 }
1113 
1114 void FrequencyPlotDialog::OnRecalc(wxCommandEvent & WXUNUSED(event))
1115 {
1116  Recalc();
1117 }
1118 
1120 {
1121  bool shown = IsShown();
1122  if (shown) {
1123  Show(false);
1124  }
1125 
1126  auto zoomSlider = mZoomSlider->GetValue();
1127  auto drawGrid = mGridOnOff->GetValue();
1128  auto sizeChoice = mSizeChoice->GetStringSelection();
1129  auto algChoice = mAlgChoice->GetSelection();
1130  auto funcChoice = mFuncChoice->GetSelection();
1131  auto axisChoice = mAxisChoice->GetSelection();
1132 
1133  SetSizer(nullptr);
1134  DestroyChildren();
1135 
1136  Populate();
1137 
1138  mZoomSlider->SetValue(zoomSlider);
1139 
1140  mDrawGrid = drawGrid;
1141  mGridOnOff->SetValue(drawGrid);
1142 
1143  long windowSize = 0;
1144  sizeChoice.ToLong(&windowSize);
1145  mWindowSize = windowSize;
1146  mSizeChoice->SetStringSelection(sizeChoice);
1147 
1148  mAlg = static_cast<SpectrumAnalyst::Algorithm>(algChoice);
1149  mAlgChoice->SetSelection(algChoice);
1150 
1151  mFunc = funcChoice;
1152  mFuncChoice->SetSelection(funcChoice);
1153 
1154  mAxis = axisChoice;
1155  mAxisChoice->SetSelection(axisChoice);
1156 
1157  if (shown) {
1158  Show(true);
1159  }
1160 }
1161 
1162 BEGIN_EVENT_TABLE(FreqPlot, wxWindow)
1163  EVT_ERASE_BACKGROUND(FreqPlot::OnErase)
1164  EVT_PAINT(FreqPlot::OnPaint)
1165  EVT_MOUSE_EVENTS(FreqPlot::OnMouseEvent)
1167 
1168 FreqPlot::FreqPlot(wxWindow *parent, wxWindowID winid)
1169 : wxWindow(parent, winid)
1170 {
1171  freqWindow = (FrequencyPlotDialog *) parent;
1172 }
1173 
1175 {
1176  return false;
1177 }
1178 
1179 void FreqPlot::OnErase(wxEraseEvent & WXUNUSED(event))
1180 {
1181  // Ignore it to prevent flashing
1182 }
1183 
1184 void FreqPlot::OnPaint(wxPaintEvent & evt)
1185 {
1186  freqWindow->PlotPaint(evt);
1187 }
1188 
1189 void FreqPlot::OnMouseEvent(wxMouseEvent & event)
1190 {
1191  freqWindow->PlotMouseEvent(event);
1192 }
1193 
1194 // Remaining code hooks this add-on into the application
1195 #include "commands/CommandContext.h"
1196 #include "commands/CommandManager.h"
1198 
1199 namespace {
1200 
1202  []( AudacityProject &parent ) -> wxWeakRef< wxWindow > {
1203  auto &window = ProjectWindow::Get( parent );
1205  &window, -1, parent, FrequencyAnalysisTitle,
1206  wxPoint{ 150, 150 }
1207  );
1208  }
1209 };
1210 
1211 // Define our extra menu item that invokes that factory
1213  void OnPlotSpectrum(const CommandContext &context)
1214  {
1215  auto &project = context.project;
1216  CommandManager::Get(project).RegisterLastAnalyzer(context); //Register Plot Spectrum as Last Analyzer
1217  auto freqWindow =
1218  &project.AttachedWindows::Get< FrequencyPlotDialog >( sFrequencyWindowKey );
1219 
1220  if( ScreenshotCommand::MayCapture( freqWindow ) )
1221  return;
1222  freqWindow->Show(true);
1223  freqWindow->Raise();
1224  freqWindow->SetFocus();
1225  }
1226 };
1227 
1229  // Handler is not stateful. Doesn't need a factory registered with
1230  // AudacityProject.
1231  static Handler instance;
1232  return instance;
1233 }
1234 
1235 // Register that menu item
1236 
1237 using namespace MenuTable;
1238 AttachedItem sAttachment{ wxT("Analyze/Analyzers/Windows"),
1240  Command( wxT("PlotSpectrum"), XXO("Plot Spectrum..."),
1241  &Handler::OnPlotSpectrum,
1243 };
1244 
1245 }
1246 
FrequencyPlotDialog::dBRange
int dBRange
Definition: FreqWindow.h:104
WaveTrack.h
FrequencyPlotDialog::OnCloseButton
void OnCloseButton(wxCommandEvent &event)
Definition: FreqWindow.cpp:992
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
FrequencyPlotDialog
Displays a spectrum plot of the waveform. Has options for selecting parameters of the plot.
Definition: FreqWindow.h:58
Optional::emplace
X & emplace(Args &&... args)
Definition: MemoryX.h:193
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:156
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:38
FrequencyPlotDialog::mSize
int mSize
Definition: FreqWindow.h:100
SpectrumAnalyst::Spectrum
@ Spectrum
Definition: SpectrumAnalyst.h:25
FrequencyPlotDialog::mYMax
float mYMax
Definition: FreqWindow.h:146
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1184
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:69
wxSliderWrapper
wxSlider wxSliderWrapper
Definition: ShuttleGui.h:105
ShuttleGui::Focus
ShuttleGui & Focus(bool focused=true)
Definition: ShuttleGui.h:644
ShuttleGuiBase::AddCheckBox
wxCheckBox * AddCheckBox(const TranslatableString &Prompt, bool Selected)
Definition: ShuttleGui.cpp:309
FrequencyPlotDialog::OnSize
void OnSize(wxSizeEvent &event)
Definition: FreqWindow.cpp:639
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption=XO("Message"), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: AudacityMessageBox.h:20
RulerPanel
RulerPanel class allows you to work with a Ruler like any other wxWindow.
Definition: Ruler.h:228
Optional
Like a smart pointer, allows for object to not exist (nullptr)
Definition: MemoryX.h:144
Ruler::LinearDBFormat
@ LinearDBFormat
Definition: Ruler.h:34
FreqPanScrollerID
@ FreqPanScrollerID
Definition: FreqWindow.cpp:100
HelpSystem.h
MenuTable::FinderScope
Definition: CommandManager.h:472
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
AllThemeResources.h
FrequencyAnalysisTitle
#define FrequencyAnalysisTitle
Definition: FreqWindow.cpp:92
EVT_COMMAND
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:91
TranslatableStrings
std::vector< TranslatableString > TranslatableStrings
Definition: TranslatableString.h:295
FirstID
@ FirstID
Definition: FreqWindow.cpp:97
ENV_DB_RANGE
#define ENV_DB_RANGE
Definition: GUISettings.h:16
ZoomIn
static const char * ZoomIn[]
Definition: FreqWindow.cpp:116
eHelpButton
@ eHelpButton
Definition: ShuttleGui.h:604
Project.h
DEFINE_EVENT_TYPE
DEFINE_EVENT_TYPE(EVT_FREQWINDOW_RECALC)
AudioIONotBusyFlag
const ReservedCommandFlag & AudioIONotBusyFlag()
Definition: CommonCommandFlags.cpp:127
FreqZoomSliderID
@ FreqZoomSliderID
Definition: FreqWindow.cpp:99
Format
Abstract base class used in importing a file.
FrequencyPlotDialog::mDrawGrid
bool mDrawGrid
Definition: FreqWindow.h:99
FrequencyPlotDialog::mRate
double mRate
Definition: FreqWindow.h:139
AColor::Line
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:112
FrequencyPlotDialog::PlotPaint
void PlotPaint(wxPaintEvent &event)
Definition: FreqWindow.cpp:884
Ruler::SetLog
void SetLog(bool log)
Definition: Ruler.cpp:142
FrequencyPlotDialog::OnCloseWindow
void OnCloseWindow(wxCloseEvent &event)
Definition: FreqWindow.cpp:987
FrequencyPlotDialog::Recalc
void Recalc()
Definition: FreqWindow.cpp:1009
PitchName.h
anonymous_namespace{FreqWindow.cpp}::findCommandHandler
CommandHandlerObject & findCommandHandler(AudacityProject &)
Definition: FreqWindow.cpp:1228
NumWindowFuncs
int NumWindowFuncs()
Definition: FFT.cpp:329
FrequencyPlotDialog::mFreqFont
wxFont mFreqFont
Definition: FreqWindow.h:120
FrequencyPlotDialog::mProgress
FreqGauge * mProgress
Definition: FreqWindow.h:116
CommandManager.h
ShuttleGui::AddSpace
wxSizerItem * AddSpace(int width, int height, int prop=0)
Definition: ShuttleGui.cpp:2447
FrequencyPlotDialog::DrawBackground
void DrawBackground(wxMemoryDC &dc)
Definition: FreqWindow.cpp:648
FreqWindow.h
FrequencyPlotDialog::mAxis
int mAxis
Definition: FreqWindow.h:103
FreqExportButtonID
@ FreqExportButtonID
Definition: FreqWindow.cpp:101
ShuttleGui::MinSize
ShuttleGui & MinSize()
Definition: ShuttleGui.h:733
XO
#define XO(s)
Definition: Internat.h:31
FrequencyPlotDialog::mSizeChoice
wxChoice * mSizeChoice
Definition: FreqWindow.h:130
Ruler::SetFormat
void SetFormat(RulerFormat format)
Definition: Ruler.cpp:131
Ruler::RealFormat
@ RealFormat
Definition: Ruler.h:31
ShuttleGuiBase::EndMultiColumn
void EndMultiColumn()
Definition: ShuttleGui.cpp:1238
ProjectWindow::Get
static ProjectWindow & Get(AudacityProject &project)
Definition: ProjectWindow.cpp:533
FrequencyPlotDialog::mAlg
SpectrumAnalyst::Algorithm mAlg
Definition: FreqWindow.h:101
FrequencyPlotDialog::mZoomSlider
wxSlider * mZoomSlider
Definition: FreqWindow.h:134
ReplotButtonID
@ ReplotButtonID
Definition: FreqWindow.cpp:106
FreqPlot::freqWindow
FrequencyPlotDialog * freqWindow
Definition: FreqWindow.h:51
MenuTable::AttachedItem
Definition: CommandManager.h:695
FileNames::AllFiles
AUDACITY_DLL_API const FileType AllFiles
Definition: FileNames.h:74
fillZero
@ fillZero
Definition: SampleFormat.h:54
HelpSystem::ShowHelp
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:237
FreqToMIDInote
double FreqToMIDInote(const double freq)
Definition: PitchName.cpp:29
PitchName_Absolute
TranslatableString PitchName_Absolute(const double dMIDInote, const PitchNameChoice choice)
Definition: PitchName.cpp:154
ClientData::Site::RegisteredFactory
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:266
WaveTracksSelectedFlag
const ReservedCommandFlag & WaveTracksSelectedFlag()
Definition: CommonCommandFlags.cpp:164
Ruler::SetUnits
void SetUnits(const TranslatableString &units)
Definition: Ruler.cpp:153
FrequencyPlotDialog::mFuncChoice
wxChoice * mFuncChoice
Definition: FreqWindow.h:131
FrequencyPlotDialog::Show
bool Show(bool show=true) override
Definition: FreqWindow.cpp:556
ShuttleGui::Id
ShuttleGui & Id(int id)
Definition: ShuttleGui.cpp:2274
FrequencyPlotDialog::PlotMouseEvent
void PlotMouseEvent(wxMouseEvent &event)
Definition: FreqWindow.cpp:822
FREQ_WINDOW_HEIGHT
#define FREQ_WINDOW_HEIGHT
Definition: FreqWindow.cpp:113
FrequencyPlotDialog::OnZoomSlider
void OnZoomSlider(wxCommandEvent &event)
Definition: FreqWindow.cpp:842
FrequencyPlotDialog::mCursorText
wxTextCtrl * mCursorText
Definition: FreqWindow.h:135
SpectrumAnalyst
Used for finding the peaks, for snapping to peaks.
Definition: SpectrumAnalyst.h:21
Ruler::GetMaxSize
void GetMaxSize(wxCoord *width, wxCoord *height)
Definition: Ruler.cpp:1603
FrequencyPlotDialog::GetAudio
void GetAudio()
Definition: FreqWindow.cpp:582
ZoomOut
static const char * ZoomOut[]
Definition: FreqWindow.cpp:142
RulerPanel::Range
std::pair< double, double > Range
Definition: Ruler.h:232
FrequencyPlotDialog::mAlgChoice
wxChoice * mAlgChoice
Definition: FreqWindow.h:129
ShuttleGui::Style
ShuttleGui & Style(long iStyle)
Definition: ShuttleGui.h:727
FFT.h
FrequencyPlotDialog::OnSizeChoice
void OnSizeChoice(wxCommandEvent &event)
Definition: FreqWindow.cpp:864
ShuttleGuiBase::SetSizerProportion
void SetSizerProportion(int iProp)
Definition: ShuttleGui.h:491
FrequencyPlotDialog::OnGetURL
void OnGetURL(wxCommandEvent &event)
Definition: FreqWindow.cpp:549
CommandContext.h
FrequencyPlotDialog::vRuler
RulerPanel * vRuler
Definition: FreqWindow.h:113
FrequencyPlotDialog::mExportButton
wxButton * mExportButton
Definition: FreqWindow.h:126
ViewInfo::selectedRegion
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:200
XXO
#define XXO(s)
Definition: Internat.h:44
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1177
FrequencyPlotDialog::mBitmap
std::unique_ptr< wxBitmap > mBitmap
Definition: FreqWindow.h:149
CommandContext
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
Definition: CommandContext.h:22
FrequencyPlotDialog::OnGridOnOff
void OnGridOnOff(wxCommandEvent &event)
Definition: FreqWindow.cpp:1107
FrequencyPlotDialog::Populate
void Populate()
Definition: FreqWindow.cpp:219
FrequencyPlotDialog::mMouseX
int mMouseX
Definition: FreqWindow.h:151
anonymous_namespace{FreqWindow.cpp}::Handler::OnPlotSpectrum
void OnPlotSpectrum(const CommandContext &context)
Definition: FreqWindow.cpp:1213
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1167
FrequencyPlotDialog::mLogAxis
bool mLogAxis
Definition: FreqWindow.h:144
FileNames::TextFiles
AUDACITY_DLL_API const FileType TextFiles
Definition: FileNames.h:77
ShuttleGuiBase::AddTextBox
wxTextCtrl * AddTextBox(const TranslatableString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:638
ShuttleGuiBase::StartMultiColumn
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:1229
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1203
FrequencyPlotDialog::mYMin
float mYMin
Definition: FreqWindow.h:145
FrequencyPlotDialog::mDataLen
size_t mDataLen
Definition: FreqWindow.h:140
Theme.h
ScreenshotCommand.h
CommandManager::RegisterLastAnalyzer
void RegisterLastAnalyzer(const CommandContext &context)
Definition: CommandManager.cpp:1229
FrequencyPlotDialog::OnFuncChoice
void OnFuncChoice(wxCommandEvent &event)
Definition: FreqWindow.cpp:873
FrequencyPlotDialog::mCloseButton
wxButton * mCloseButton
Definition: FreqWindow.h:125
FreqFuncChoiceID
@ FreqFuncChoiceID
Definition: FreqWindow.cpp:104
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:496
FrequencyPlotDialog::mPlotRect
wxRect mPlotRect
Definition: FreqWindow.h:118
FrequencyPlotDialog::mCrossCursor
std::unique_ptr< wxCursor > mCrossCursor
Definition: FreqWindow.h:123
ShuttleGuiBase::AddWindow
wxWindow * AddWindow(wxWindow *pWindow, int PositionFlags=wxALIGN_CENTRE)
Definition: ShuttleGui.cpp:299
FreqAlgChoiceID
@ FreqAlgChoiceID
Definition: FreqWindow.cpp:102
Ruler::SetRange
void SetRange(double min, double max)
Definition: Ruler.cpp:188
anonymous_namespace{FreqWindow.cpp}::sFrequencyWindowKey
AudacityProject::AttachedWindows::RegisteredFactory sFrequencyWindowKey
Definition: FreqWindow.cpp:1201
WindowAccessible
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
FrequencyPlotDialog::mAnalyst
std::unique_ptr< SpectrumAnalyst > mAnalyst
Definition: FreqWindow.h:154
FreqPlot::OnMouseEvent
void OnMouseEvent(wxMouseEvent &event)
Definition: FreqWindow.cpp:1189
ShuttleGui.h
FreqGauge
Definition: SpectrumAnalyst.h:63
ENV_DB_KEY
#define ENV_DB_KEY
Definition: GUISettings.h:15
ViewInfo.h
WindowFuncName
const TranslatableString WindowFuncName(int whichFunction)
Definition: FFT.cpp:334
Ruler.h
title
static const auto title
Definition: UpdateNoticeDialog.cpp:23
ShuttleGui::Prop
ShuttleGui & Prop(int iProp)
Definition: ShuttleGui.h:725
RulerPanel::Options::LabelEdges
Options & LabelEdges(bool l)
Definition: Ruler.h:250
ScreenshotCommand::MayCapture
static bool MayCapture(wxDialog *pDlg)
Definition: ScreenshotCommand.cpp:345
ShuttleGuiBase::AddButton
wxButton * AddButton(const TranslatableString &Text, int PositionFlags=wxALIGN_CENTRE, bool setDefault=false)
Definition: ShuttleGui.cpp:360
GUISettings.h
FreqPlot::OnPaint
void OnPaint(wxPaintEvent &event)
Definition: FreqWindow.cpp:1184
ShuttleGui::Name
ShuttleGui & Name(const TranslatableString &name)
Definition: ShuttleGui.h:663
wxDialogWrapper
Definition: wxPanelWrapper.h:81
FrequencyPlotDialog::OnPanScroller
void OnPanScroller(wxScrollEvent &event)
Definition: FreqWindow.cpp:837
FrequencyPlotDialog::DrawPlot
void DrawPlot()
Definition: FreqWindow.cpp:670
WindowAccessible.h
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:495
FrequencyPlotDialog::hRuler
RulerPanel * hRuler
Definition: FreqWindow.h:114
anonymous_namespace{FreqWindow.cpp}::Handler
Definition: FreqWindow.cpp:1212
FileNames::SelectFile
AUDACITY_DLL_API FilePath SelectFile(Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
ShuttleGui::Position
ShuttleGui & Position(int flags)
Definition: ShuttleGui.h:712
FrequencyPlotDialog::mArrowCursor
std::unique_ptr< wxCursor > mArrowCursor
Definition: FreqWindow.h:122
FreqPlot::OnErase
void OnErase(wxEraseEvent &event)
Definition: FreqWindow.cpp:1179
_
#define _(s)
Definition: Internat.h:75
MenuTable::Command
std::unique_ptr< CommandItem > Command(const CommandID &name, const TranslatableString &label_in, void(Handler::*pmf)(const CommandContext &), CommandFlag flags, const CommandManager::Options &options={}, CommandHandlerFinder finder=FinderScope::DefaultFinder())
Definition: CommandManager.h:662
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:113
FrequencyPlotDialog::mFreqPlot
FreqPlot * mFreqPlot
Definition: FreqWindow.h:115
eCloseButton
@ eCloseButton
Definition: ShuttleGui.h:610
FileNames.h
TimeSelectedFlag
const ReservedCommandFlag & TimeSelectedFlag()
Definition: CommonCommandFlags.cpp:159
AudacityMessageBox.h
FrequencyPlotDialog::OnAxisChoice
void OnAxisChoice(wxCommandEvent &event)
Definition: FreqWindow.cpp:878
RulerPanel::Options
Definition: Ruler.h:234
CommandHandlerObject
wxEvtHandler CommandHandlerObject
Definition: CommandFunctors.h:28
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
RulerPanel::ruler
Ruler ruler
Definition: Ruler.h:288
FreqSizeChoiceID
@ FreqSizeChoiceID
Definition: FreqWindow.cpp:103
FrequencyPlotDialog::UpdatePrefs
void UpdatePrefs() override
Definition: FreqWindow.cpp:1119
ThemeBase::Colour
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1197
FreqPlot::AcceptsFocus
bool AcceptsFocus() const
Definition: FreqWindow.cpp:1174
FrequencyPlotDialog::OnReplot
void OnReplot(wxCommandEvent &event)
Definition: FreqWindow.cpp:1098
FrequencyPlotDialog::SendRecalcEvent
void SendRecalcEvent()
Definition: FreqWindow.cpp:1003
wxDialogWrapper::SetTitle
void SetTitle(const TranslatableString &title)
Definition: wxPanelWrapper.cpp:66
SpectrumAnalyst::Algorithm
Algorithm
Definition: SpectrumAnalyst.h:24
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2432
FreqPlot
Works with FrequencyPlotDialog to dsplay a spectrum plot of the waveform. This class actually does th...
Definition: FreqWindow.h:38
FrequencyPlotDialog::mPanScroller
wxScrollBar * mPanScroller
Definition: FreqWindow.h:133
theTheme
AUDACITY_DLL_API Theme theTheme
Definition: Theme.cpp:203
FrequencyPlotDialog::mFunc
int mFunc
Definition: FreqWindow.h:102
Prefs.h
ShuttleGuiBase::AddPrompt
void AddPrompt(const TranslatableString &Prompt, int wrapWidth=0)
Right aligned text string.
Definition: ShuttleGui.cpp:238
ProjectWindow.h
TranslatableString::Translation
wxString Translation() const
Definition: TranslatableString.h:79
FrequencyPlotDialog::OnExport
void OnExport(wxCommandEvent &event)
Definition: FreqWindow.cpp:1054
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:489
FrequencyPlotDialog::mGridOnOff
wxCheckBox * mGridOnOff
Definition: FreqWindow.h:128
MenuTable
Definition: CommandManager.h:403
FrequencyPlotDialog::mMouseY
int mMouseY
Definition: FreqWindow.h:152
FrequencyPlotDialog::fontSize
static const int fontSize
Definition: FreqWindow.h:110
CommandManager::Get
static CommandManager & Get(AudacityProject &project)
Definition: CommandManager.cpp:203
GridOnOffID
@ GridOnOffID
Definition: FreqWindow.cpp:107
FrequencyPlotDialog::mPeakText
wxTextCtrl * mPeakText
Definition: FreqWindow.h:136
safenew
#define safenew
Definition: MemoryX.h:10
FreqAxisChoiceID
@ FreqAxisChoiceID
Definition: FreqWindow.cpp:105
anonymous_namespace{FreqWindow.cpp}::sAttachment
AttachedItem sAttachment
Definition: FreqWindow.cpp:1238
ShuttleGuiBase::SetStretchyCol
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:202
Ruler::DrawGrid
void DrawGrid(wxDC &dc, int length, bool minor=true, bool major=true, int xOffset=0, int yOffset=0) const
Definition: Ruler.cpp:1521
AColor.h
CommonCommandFlags.h
CommandContext::project
AudacityProject & project
Definition: CommandContext.h:52
TrackList::Selected
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1372
END_EVENT_TABLE
END_EVENT_TABLE()
ShuttleGuiBase::SetStretchyRow
void SetStretchyRow(int i)
Used to modify an already placed FlexGridSizer to make a row stretchy.
Definition: ShuttleGui.cpp:212
ArrayOf< float >
FrequencyPlotDialog::mAxisChoice
wxChoice * mAxisChoice
Definition: FreqWindow.h:132
FrequencyPlotDialog::mWindowSize
size_t mWindowSize
Definition: FreqWindow.h:142
RulerPanel::Options::Log
Options & Log(bool l)
Definition: Ruler.h:244
FrequencyPlotDialog::OnRecalc
void OnRecalc(wxCommandEvent &event)
Definition: FreqWindow.cpp:1114
FrequencyPlotDialog::mReplotButton
wxButton * mReplotButton
Definition: FreqWindow.h:127
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631
FrequencyPlotDialog::OnAlgChoice
void OnAlgChoice(wxCommandEvent &event)
Definition: FreqWindow.cpp:847
FrequencyPlotDialog::FreqPlot
friend class FreqPlot
Definition: FreqWindow.h:158
FrequencyPlotDialog::mData
Floats mData
Definition: FreqWindow.h:141