Audacity  3.2.0
WaveformView.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 WaveformView.cpp
6 
7 Paul Licameli split from WaveTrackView.cpp
8 
9 **********************************************************************/
10 
11 
12 #include "WaveformView.h"
13 
14 #include "WaveformCache.h"
15 #include "WaveformVRulerControls.h"
16 #include "WaveTrackView.h"
17 #include "WaveTrackViewConstants.h"
18 
19 #include "SampleHandle.h"
20 #include "../../../ui/EnvelopeHandle.h"
21 #include "../../../ui/TimeShiftHandle.h"
22 #include "AColor.h"
23 #include "Envelope.h"
24 #include "../../../../EnvelopeEditor.h"
25 #include "../../../../ProjectSettings.h"
26 #include "SelectedRegion.h"
27 #include "../../../../SyncLock.h"
28 #include "../../../../TrackArt.h"
29 #include "../../../../TrackArtist.h"
30 #include "../../../../TrackPanelDrawingContext.h"
31 #include "../../../../TrackPanelMouseEvent.h"
32 #include "ViewInfo.h"
33 #include "../../../../WaveClip.h"
34 #include "../../../../WaveTrack.h"
35 #include "../../../../prefs/WaveformSettings.h"
36 
37 #include <wx/graphics.h>
38 #include <wx/dc.h>
39 
42  { wxT("Waveform"), XXO("Wa&veform") }
43 };
44 
46 
47 WaveformView::~WaveformView() = default;
48 
49 std::vector<UIHandlePtr> WaveformView::DetailedHitTest(
50  const TrackPanelMouseState &st,
51  const AudacityProject *pProject, int currentTool, bool bMultiTool )
52 {
53  auto &view = *this;
54  const auto pTrack =
55  std::static_pointer_cast< WaveTrack >( view.FindTrack() );
56 
58  st, pProject, currentTool, bMultiTool, pTrack);
59  auto &results = pair.second;
60 
61  if (!pair.first) {
62  UIHandlePtr result;
63 
64  if (bMultiTool) {
65  // Conditional hit tests
66  // If Tools toolbar were eliminated, we would keep these
67  // The priority of these, in case more than one might apply at one
68  // point, seems arbitrary
69  if (NULL != (result = EnvelopeHandle::WaveTrackHitTest(
70  view.mEnvelopeHandle, st.state, st.rect,
71  pProject, pTrack )))
72  results.push_back(result);
73  if (NULL != (result = TimeShiftHandle::HitTest(
74  view.mTimeShiftHandle, st.state, st.rect, pTrack )))
75  // This is the hit test on the "grips" drawn left and
76  // right in Multi only
77  results.push_back(result);
78  if (NULL != (result = SampleHandle::HitTest(
79  view.mSampleHandle, st.state, st.rect,
80  pProject, pTrack )))
81  results.push_back(result);
82  }
83  else {
84  switch ( currentTool ) {
85  // Unconditional hits appropriate to the tool
86  // If tools toolbar were eliminated, we would eliminate these
88  auto &viewInfo = ViewInfo::Get(*pProject);
89  auto time =
90  viewInfo.PositionToTime(st.state.m_x, st.rect.GetX());
91  auto envelope = pTrack->GetEnvelopeAtTime(time);
93  view.mEnvelopeHandle, envelope, false);
94  break;
95  }
98  view.mSampleHandle, st.state, pTrack );
99  break;
100  default:
101  result = {};
102  break;
103  }
104  if (result)
105  results.push_back(result);
106  }
107  }
108 
109  return std::move( results );
110 }
111 
112 void WaveformView::DoSetMinimized( bool minimized )
113 {
114  auto wt = static_cast<WaveTrack*>( FindTrack().get() );
115 
116 #ifdef EXPERIMENTAL_HALF_WAVE
117  bool bHalfWave;
118  gPrefs->Read(wxT("/GUI/CollapseToHalfWave"), &bHalfWave, false);
119  if( bHalfWave )
120  {
121  if (minimized)
122  // Zoom to show fractionally more than the top half of the wave.
123  wt->SetDisplayBounds( -0.01f, 1.0f );
124  else
125  // Zoom out full
126  wt->SetDisplayBounds( -1.0f, 1.0f );
127  }
128 #endif
129 
130  TrackView::DoSetMinimized( minimized );
131 }
132 
133 auto WaveformView::SubViewType() const -> const Type &
134 {
135  return sType;
136 }
137 
138 std::shared_ptr<TrackVRulerControls> WaveformView::DoGetVRulerControls()
139 {
140  return std::make_shared<WaveformVRulerControls>( shared_from_this() );
141 }
142 
143 namespace
144 {
145 
147  int leftOffset, const wxRect &rect,
148  const double env[],
149  float zoomMin, float zoomMax,
150  int zeroLevelYCoordinate,
151  bool dB, float dBRange,
152  double t0, double t1,
153  bool bIsSyncLockSelected,
154  bool highlightEnvelope)
155 {
156  auto &dc = context.dc;
157  const auto artist = TrackArtist::Get( context );
158  const auto &zoomInfo = *artist->pZoomInfo;
159 
160  // Visually (one vertical slice of the waveform background, on its side;
161  // the "*" is the actual waveform background we're drawing
162  //
163  //1.0 0.0 -1.0
164  // |--------------------------------|--------------------------------|
165  // *************** ***************
166  // | | | |
167  // maxtop maxbot mintop minbot
168 
169  int h = rect.height;
170  int halfHeight = wxMax(h / 2, 1);
171  int maxtop, lmaxtop = 0;
172  int mintop, lmintop = 0;
173  int maxbot, lmaxbot = 0;
174  int minbot, lminbot = 0;
175  bool sel, lsel = false;
176  int xx, lx = 0;
177  int l, w;
178 
179  const auto &blankBrush = artist->blankBrush;
180  const auto &selectedBrush = artist->selectedBrush;
181  const auto &unselectedBrush = artist->unselectedBrush;
182 
183  dc.SetPen(*wxTRANSPARENT_PEN);
184  dc.SetBrush(blankBrush);
185  dc.DrawRectangle(rect);
186 
187  // Bug 2389 - always draw at least one pixel of selection.
188  int selectedX = zoomInfo.TimeToPosition(t0, -leftOffset);
189 
190  double time = zoomInfo.PositionToTime(0, -leftOffset), nextTime;
191  for (xx = 0; xx < rect.width; ++xx, time = nextTime) {
192  nextTime = zoomInfo.PositionToTime(xx + 1, -leftOffset);
193  // First we compute the truncated shape of the waveform background.
194  // If drawEnvelope is true, then we compute the lower border of the
195  // envelope.
196 
197  maxtop = GetWaveYPos(env[xx], zoomMin, zoomMax,
198  h, dB, true, dBRange, true);
199  maxbot = GetWaveYPos(env[xx], zoomMin, zoomMax,
200  h, dB, false, dBRange, true);
201 
202  mintop = GetWaveYPos(-env[xx], zoomMin, zoomMax,
203  h, dB, false, dBRange, true);
204  minbot = GetWaveYPos(-env[xx], zoomMin, zoomMax,
205  h, dB, true, dBRange, true);
206 
207  // Make sure it's odd so that a that max and min mirror each other
208  mintop +=1;
209  minbot +=1;
210 
211  const auto drawEnvelope = artist->drawEnvelope;
212  if (!drawEnvelope || maxbot > mintop) {
213  maxbot = halfHeight;
214  mintop = halfHeight;
215  }
216 
217  sel = (t0 <= time && nextTime < t1);
218  sel = sel || (xx == selectedX);
219  // We don't draw selection color for sync-lock selected tracks.
220  sel = sel && !bIsSyncLockSelected;
221 
222  if (lmaxtop == maxtop &&
223  lmintop == mintop &&
224  lmaxbot == maxbot &&
225  lminbot == minbot &&
226  lsel == sel) {
227  continue;
228  }
229 
230  dc.SetBrush(lsel ? selectedBrush : unselectedBrush);
231 
232  l = rect.x + lx;
233  w = xx - lx;
234  if (lmaxbot < lmintop - 1) {
235  dc.DrawRectangle(l, rect.y + lmaxtop, w, lmaxbot - lmaxtop);
236  dc.DrawRectangle(l, rect.y + lmintop, w, lminbot - lmintop);
237  }
238  else {
239  dc.DrawRectangle(l, rect.y + lmaxtop, w, lminbot - lmaxtop);
240  }
241 
242  if (highlightEnvelope && lmaxbot < lmintop - 1) {
243  dc.SetBrush( AColor::uglyBrush );
244  dc.DrawRectangle(l, rect.y + lmaxbot, w, lmintop - lmaxbot);
245  }
246 
247  lmaxtop = maxtop;
248  lmintop = mintop;
249  lmaxbot = maxbot;
250  lminbot = minbot;
251  lsel = sel;
252  lx = xx;
253  }
254 
255  dc.SetBrush(lsel ? selectedBrush : unselectedBrush);
256  l = rect.x + lx;
257  w = xx - lx;
258  if (lmaxbot < lmintop - 1) {
259  dc.DrawRectangle(l, rect.y + lmaxtop, w, lmaxbot - lmaxtop);
260  dc.DrawRectangle(l, rect.y + lmintop, w, lminbot - lmintop);
261  }
262  else {
263  dc.DrawRectangle(l, rect.y + lmaxtop, w, lminbot - lmaxtop);
264  }
265  if (highlightEnvelope && lmaxbot < lmintop - 1) {
266  dc.SetBrush( AColor::uglyBrush );
267  dc.DrawRectangle(l, rect.y + lmaxbot, w, lmintop - lmaxbot);
268  }
269 
270  // If sync-lock selected, draw in linked graphics.
271  if (bIsSyncLockSelected && t0 < t1) {
272  const int begin = std::max(0, std::min(rect.width, (int)(zoomInfo.TimeToPosition(t0, -leftOffset))));
273  const int end = std::max(0, std::min(rect.width, (int)(zoomInfo.TimeToPosition(t1, -leftOffset))));
275  { rect.x + begin, rect.y, end - 1 - begin, rect.height } );
276  }
277 
278  //OK, the display bounds are between min and max, which
279  //is spread across rect.height. Draw the line at the proper place.
280  if (zeroLevelYCoordinate >= rect.GetTop() &&
281  zeroLevelYCoordinate <= rect.GetBottom()) {
282  dc.SetPen(*wxBLACK_PEN);
283  AColor::Line(dc, rect.x, zeroLevelYCoordinate,
284  rect.x + rect.width - 1, zeroLevelYCoordinate);
285  }
286 }
287 
288 struct WavePortion {
289  wxRect rect;
292  WavePortion(int x, int y, int w, int h, double zoom, bool i)
293  : rect(x, y, w, h), averageZoom(zoom), inFisheye(i)
294  {}
295 };
296 
298  (std::vector<WavePortion> &portions, const wxRect &rect, const ZoomInfo &zoomInfo,
299  const ClipParameters &params)
300 {
301  // If there is no fisheye, then only one rectangle has nonzero width.
302  // If there is a fisheye, make rectangles for before and after
303  // (except when they are squeezed to zero width), and at least one for inside
304  // the fisheye.
305 
306  ZoomInfo::Intervals intervals;
307  zoomInfo.FindIntervals(params.rate, intervals, rect.width, rect.x);
308  ZoomInfo::Intervals::const_iterator it = intervals.begin(), end = intervals.end(), prev;
309  wxASSERT(it != end && it->position == rect.x);
310  const int rightmost = rect.x + rect.width;
311  for (int left = rect.x; left < rightmost;) {
312  while (it != end && it->position <= left)
313  prev = it++;
314  if (it == end)
315  break;
316  const int right = std::max(left, (int)(it->position));
317  const int width = right - left;
318  if (width > 0)
319  portions.push_back(
320  WavePortion(left, rect.y, width, rect.height,
321  prev->averageZoom, prev->inFisheye)
322  );
323  left = right;
324  }
325 }
326 
328  TrackPanelDrawingContext &context, const wxRect & rect, const double env[],
329  float zoomMin, float zoomMax,
330  bool dB, float dBRange,
331  const float *min, const float *max, const float *rms, const int *bl,
332  bool muted)
333 {
334  auto &dc = context.dc;
335 
336  // Display a line representing the
337  // min and max of the samples in this region
338  int lasth1 = std::numeric_limits<int>::max();
339  int lasth2 = std::numeric_limits<int>::min();
340  int h1;
341  int h2;
342  ArrayOf<int> r1{ size_t(rect.width) };
343  ArrayOf<int> r2{ size_t(rect.width) };
344  ArrayOf<int> clipped;
345  int clipcnt = 0;
346 
347  const auto artist = TrackArtist::Get( context );
348  const auto bShowClipping = artist->mShowClipping;
349  if (bShowClipping) {
350  clipped.reinit( size_t(rect.width) );
351  }
352 
353  long pixAnimOffset = (long)fabs((double)(wxDateTime::Now().GetTicks() * -10)) +
354  wxDateTime::Now().GetMillisecond() / 100; //10 pixels a second
355 
356  bool drawStripes = true;
357  bool drawWaveform = true;
358 
359  const auto &muteSamplePen = artist->muteSamplePen;
360  const auto &samplePen = artist->samplePen;
361 
362  dc.SetPen(muted ? muteSamplePen : samplePen);
363  for (int x0 = 0; x0 < rect.width; ++x0) {
364  int xx = rect.x + x0;
365  double v;
366  v = min[x0] * env[x0];
367  if (clipped && bShowClipping && (v <= -MAX_AUDIO))
368  {
369  if (clipcnt == 0 || clipped[clipcnt - 1] != xx) {
370  clipped[clipcnt++] = xx;
371  }
372  }
373  h1 = GetWaveYPos(v, zoomMin, zoomMax,
374  rect.height, dB, true, dBRange, true);
375 
376  v = max[x0] * env[x0];
377  if (clipped && bShowClipping && (v >= MAX_AUDIO))
378  {
379  if (clipcnt == 0 || clipped[clipcnt - 1] != xx) {
380  clipped[clipcnt++] = xx;
381  }
382  }
383  h2 = GetWaveYPos(v, zoomMin, zoomMax,
384  rect.height, dB, true, dBRange, true);
385 
386  // JKC: This adjustment to h1 and h2 ensures that the drawn
387  // waveform is continuous.
388  if (x0 > 0) {
389  if (h1 < lasth2) {
390  h1 = lasth2 - 1;
391  }
392  if (h2 > lasth1) {
393  h2 = lasth1 + 1;
394  }
395  }
396  lasth1 = h1;
397  lasth2 = h2;
398 
399  r1[x0] = GetWaveYPos(-rms[x0] * env[x0], zoomMin, zoomMax,
400  rect.height, dB, true, dBRange, true);
401  r2[x0] = GetWaveYPos(rms[x0] * env[x0], zoomMin, zoomMax,
402  rect.height, dB, true, dBRange, true);
403  // Make sure the rms isn't larger than the waveform min/max
404  if (r1[x0] > h1 - 1) {
405  r1[x0] = h1 - 1;
406  }
407  if (r2[x0] < h2 + 1) {
408  r2[x0] = h2 + 1;
409  }
410  if (r2[x0] > r1[x0]) {
411  r2[x0] = r1[x0];
412  }
413 
414  if (bl[x0] <= -1) {
415  if (drawStripes) {
416  // TODO:unify with buffer drawing.
417  dc.SetPen((bl[x0] % 2) ? muteSamplePen : samplePen);
418  for (int yy = 0; yy < rect.height / 25 + 1; ++yy) {
419  // we are drawing over the buffer, but I think DrawLine takes care of this.
420  AColor::Line(dc,
421  xx,
422  rect.y + 25 * yy + (x0 /*+pixAnimOffset*/) % 25,
423  xx,
424  rect.y + 25 * yy + (x0 /*+pixAnimOffset*/) % 25 + 6); //take the min so we don't draw past the edge
425  }
426  }
427 
428  // draw a dummy waveform - some kind of sinusoid. We want to animate it so the user knows it's a dummy. Use the second's unit of a get time function.
429  // Lets use a triangle wave for now since it's easier - I don't want to use sin() or make a wavetable just for this.
430  if (drawWaveform) {
431  int triX;
432  dc.SetPen(samplePen);
433  triX = fabs((double)((x0 + pixAnimOffset) % (2 * rect.height)) - rect.height) + rect.height;
434  for (int yy = 0; yy < rect.height; ++yy) {
435  if ((yy + triX) % rect.height == 0) {
436  dc.DrawPoint(xx, rect.y + yy);
437  }
438  }
439  }
440 
441  // Restore the pen for remaining pixel columns!
442  dc.SetPen(muted ? muteSamplePen : samplePen);
443  }
444  else {
445  AColor::Line(dc, xx, rect.y + h2, xx, rect.y + h1);
446  }
447  }
448 
449  // Stroke rms over the min-max
450  const auto &muteRmsPen = artist->muteRmsPen;
451  const auto &rmsPen = artist->rmsPen;
452 
453  dc.SetPen(muted ? muteRmsPen : rmsPen);
454  for (int x0 = 0; x0 < rect.width; ++x0) {
455  int xx = rect.x + x0;
456  if (bl[x0] <= -1) {
457  }
458  else if (r1[x0] != r2[x0]) {
459  AColor::Line(dc, xx, rect.y + r2[x0], xx, rect.y + r1[x0]);
460  }
461  }
462 
463  // Draw the clipping lines
464  if (clipcnt) {
465  const auto &muteClippedPen = artist->muteClippedPen;
466  const auto &clippedPen = artist->clippedPen;
467 
468  dc.SetPen(muted ? muteClippedPen : clippedPen);
469  while (--clipcnt >= 0) {
470  int xx = clipped[clipcnt];
471  AColor::Line(dc, xx, rect.y, xx, rect.y + rect.height);
472  }
473  }
474 }
475 
477  int leftOffset, const wxRect &rect,
478  float zoomMin, float zoomMax,
479  bool dB, float dBRange,
480  const WaveClip *clip,
481  bool showPoints, bool muted,
482  bool highlight)
483 {
484  auto &dc = context.dc;
485  const auto artist = TrackArtist::Get( context );
486  const auto &zoomInfo = *artist->pZoomInfo;
487 
488  const double toffset = clip->GetPlayStartTime();
489  double rate = clip->GetRate();
490  const double t0 = std::max(0.0, zoomInfo.PositionToTime(0, -leftOffset) - toffset);
491  const auto s0 = sampleCount(floor(t0 * rate));
492  const auto snSamples = clip->GetPlaySamplesCount();
493  if (s0 > snSamples)
494  return;
495 
496  const double t1 = zoomInfo.PositionToTime(rect.width - 1, -leftOffset) - toffset;
497  const auto s1 = sampleCount(ceil(t1 * rate));
498 
499  // Assume size_t will not overflow, else we wouldn't be here drawing the
500  // few individual samples
501  auto slen = std::min(snSamples - s0, s1 - s0 + 1).as_size_t();
502 
503  if (slen <= 0)
504  return;
505 
506  Floats buffer{ size_t(slen) };
507  clip->GetSamples((samplePtr)buffer.get(), floatSample, s0, slen,
508  // Suppress exceptions in this drawing operation:
509  false);
510 
511  ArrayOf<int> xpos{ size_t(slen) };
512  ArrayOf<int> ypos{ size_t(slen) };
513  ArrayOf<int> clipped;
514  int clipcnt = 0;
515 
516  const auto bShowClipping = artist->mShowClipping;
517  if (bShowClipping)
518  clipped.reinit( size_t(slen) );
519 
520  const auto &muteSamplePen = artist->muteSamplePen;
521  const auto &samplePen = artist->samplePen;
522  auto &pen = highlight ? AColor::uglyPen : muted ? muteSamplePen : samplePen;
523  dc.SetPen( pen );
524 
525  for (decltype(slen) s = 0; s < slen; s++) {
526  const double time = toffset + (s + s0).as_double() / rate;
527  const int xx = // An offset into the rectangle rect
528  std::max(-10000, std::min(10000,
529  (int)(zoomInfo.TimeToPosition(time, -leftOffset))));
530  xpos[s] = xx;
531 
532  // Calculate sample as it would be rendered, so quantize time
533  double value =
534  clip->GetEnvelope()->GetValue( time, 1.0 / clip->GetRate() );
535  const double tt = buffer[s] * value;
536 
537  if (clipped && bShowClipping && ((tt <= -MAX_AUDIO) || (tt >= MAX_AUDIO)))
538  clipped[clipcnt++] = xx;
539  ypos[s] =
540  std::max(-1,
541  std::min(rect.height,
542  GetWaveYPos(tt, zoomMin, zoomMax,
543  rect.height, dB, true, dBRange, false)));
544  }
545 
546 
547  if (showPoints) {
548  // Draw points where spacing is enough
549  const auto bigPoints = artist->bigPoints;
550  const int tickSize = bigPoints ? 4 : 3;// Bigger ellipses when draggable.
551  wxRect pr;
552  pr.width = tickSize;
553  pr.height = tickSize;
554  //different colour when draggable.
555  const auto &dragsampleBrush = artist->dragsampleBrush;
556  const auto &sampleBrush = artist->sampleBrush;
557  auto &brush = highlight
559  : bigPoints ? dragsampleBrush : sampleBrush;
560  dc.SetBrush( brush );
561  for (decltype(slen) s = 0; s < slen; s++) {
562  if (ypos[s] >= 0 && ypos[s] < rect.height) {
563  pr.x = rect.x + xpos[s] - tickSize/2;
564  pr.y = rect.y + ypos[s] - tickSize/2;
565  dc.DrawEllipse(pr);
566  }
567  }
568  }
569 
570  const auto sampleDisplay = artist->mSampleDisplay;
571  if (showPoints && (sampleDisplay == (int) WaveTrackViewConstants::StemPlot)) {
572  // Draw vertical lines
573  int yZero = GetWaveYPos(0.0, zoomMin, zoomMax, rect.height, dB, true, dBRange, false);
574  yZero = rect.y + std::max(-1, std::min(rect.height, yZero));
575  for (decltype(slen) s = 0; s < slen; s++) {
576  AColor::Line(dc,
577  rect.x + xpos[s], rect.y + ypos[s],
578  rect.x + xpos[s], yZero);
579  }
580  }
581  else {
582  // Connect samples with straight lines
583  for (decltype(slen) s = 0; s < slen - 1; s++) {
584  AColor::Line(dc,
585  rect.x + xpos[s], rect.y + ypos[s],
586  rect.x + xpos[s + 1], rect.y + ypos[s + 1]);
587  }
588  }
589 
590  // Draw clipping
591  if (clipcnt) {
592  const auto &muteClippedPen = artist->muteClippedPen;
593  const auto &clippedPen = artist->clippedPen;
594  dc.SetPen(muted ? muteClippedPen : clippedPen);
595  while (--clipcnt >= 0) {
596  auto s = clipped[clipcnt];
597  AColor::Line(dc, rect.x + s, rect.y, rect.x + s, rect.y + rect.height);
598  }
599  }
600 }
601 
603  TrackPanelDrawingContext &context,
604  const wxRect &rect, int x0, int y0, int cy, bool top )
605 {
606  auto &dc = context.dc;
607 
608  int xx = rect.x + x0;
609  int yy = rect.y + cy;
610 
611  if (y0 < 0) {
612  if (x0 % 4 != 3) {
613  AColor::Line(dc, xx, yy, xx, yy + 3);
614  }
615  }
616  else if (y0 > rect.height) {
617  if (x0 % 4 != 3) {
618  AColor::Line(dc, xx, yy - 3, xx, yy);
619  }
620  }
621  else {
622  if (top) {
623  AColor::Line(dc, xx, yy, xx, yy + 3);
624  }
625  else {
626  AColor::Line(dc, xx, yy - 3, xx, yy);
627  }
628  }
629 }
630 
632  const wxRect &rect, const double env[],
633  float zoomMin, float zoomMax,
634  bool dB, float dBRange, bool highlight)
635 {
636  auto &dc = context.dc;
637 
638  int h = rect.height;
639 
640  auto &pen = highlight ? AColor::uglyPen : AColor::envelopePen;
641  dc.SetPen( pen );
642 
643  for (int x0 = 0; x0 < rect.width; ++x0) {
644  int cenvTop = GetWaveYPos(env[x0], zoomMin, zoomMax,
645  h, dB, true, dBRange, true);
646 
647  int cenvBot = GetWaveYPos(-env[x0], zoomMin, zoomMax,
648  h, dB, true, dBRange, true);
649 
650  int envTop = GetWaveYPos(env[x0], zoomMin, zoomMax,
651  h, dB, true, dBRange, false);
652 
653  int envBot = GetWaveYPos(-env[x0], zoomMin, zoomMax,
654  h, dB, true, dBRange, false);
655 
656  // Make the collision at zero actually look solid
657  if (cenvBot - cenvTop < 9) {
658  int value = (int)((zoomMax / (zoomMax - zoomMin)) * h);
659  cenvTop = value - 4;
660  cenvBot = value + 4;
661  }
662 
663  DrawEnvLine( context, rect, x0, envTop, cenvTop, true );
664  DrawEnvLine( context, rect, x0, envBot, cenvBot, false );
665  }
666 }
667 
668 // Headers needed only for experimental drawing below
669 //#include "tracks/playabletrack/wavetrack/ui/SampleHandle.h"
670 //#include "tracks/ui/EnvelopeHandle.h"
672  const WaveTrack *track,
673  const WaveClip *clip,
674  const wxRect & rect,
675  bool dB,
676  bool muted,
677  bool selected)
678 {
679  auto &dc = context.dc;
680  const auto artist = TrackArtist::Get( context );
681  const auto &selectedRegion = *artist->pSelectedRegion;
682  const auto &zoomInfo = *artist->pZoomInfo;
683 
684 #ifdef PROFILE_WAVEFORM
685  Profiler profiler;
686 #endif
687 
688  bool highlightEnvelope = false;
689 #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
690  auto target = dynamic_cast<EnvelopeHandle*>(context.target.get());
691  highlightEnvelope = target && target->GetEnvelope() == clip->GetEnvelope();
692 #endif
693 
694  //If clip is "too small" draw a placeholder instead of
695  //attempting to fit the contents into a few pixels
696  if (!WaveTrackView::ClipDetailsVisible(*clip, zoomInfo, rect))
697  {
698  auto clipRect = ClipParameters::GetClipRect(*clip, zoomInfo, rect);
699  TrackArt::DrawClipFolded(dc, clipRect);
700  return;
701  }
702 
703  const ClipParameters params{
704  false, track, clip, rect, selectedRegion, zoomInfo };
705  const wxRect &hiddenMid = params.hiddenMid;
706  // The "hiddenMid" rect contains the part of the display actually
707  // containing the waveform, as it appears without the fisheye. If it's empty, we're done.
708  if (hiddenMid.width <= 0) {
709  return;
710  }
711 
712  const double &t0 = params.t0;
713  const double &tOffset = params.tOffset;
714  const double &h = params.h;
715  const double &tpre = params.tpre;
716  const double &tpost = params.tpost;
717  const double &t1 = params.t1;
718  const double &averagePixelsPerSample = params.averagePixelsPerSample;
719  const double &rate = params.rate;
720  double leftOffset = params.leftOffset;
721  const wxRect &mid = params.mid;
722 
723  const float dBRange = track->GetWaveformSettings().dBRange;
724 
725  dc.SetPen(*wxTRANSPARENT_PEN);
726  int iColorIndex = clip->GetColourIndex();
727  artist->SetColours( iColorIndex );
728 
729  // The bounds (controlled by vertical zooming; -1.0...1.0
730  // by default)
731  float zoomMin, zoomMax;
732  track->GetDisplayBounds(&zoomMin, &zoomMax);
733 
734  std::vector<double> vEnv(mid.width);
735  double *const env = &vEnv[0];
737  tOffset,
738 
739  // PRL: change back to make envelope evaluate only at sample times
740  // and then interpolate the display
741  0, // 1.0 / rate,
742 
743  env, mid.width, leftOffset, zoomInfo );
744 
745  // Draw the background of the track, outlining the shape of
746  // the envelope and using a colored pen for the selected
747  // part of the waveform
748  {
749  double tt0, tt1;
751  tt0 = track->LongSamplesToTime(track->TimeToLongSamples(selectedRegion.t0())),
752  tt1 = track->LongSamplesToTime(track->TimeToLongSamples(selectedRegion.t1()));
753  }
754  else
755  tt0 = tt1 = 0.0;
756  DrawWaveformBackground(context, leftOffset, mid,
757  env,
758  zoomMin, zoomMax,
759  track->ZeroLevelYCoordinate(mid),
760  dB, dBRange,
761  tt0, tt1,
762  !track->GetSelected(), highlightEnvelope);
763  }
764 
765  WaveDisplay display(hiddenMid.width);
766 
767  const double pps =
768  averagePixelsPerSample * rate;
769 
770  // For each portion separately, we will decide to draw
771  // it as min/max/rms or as individual samples.
772  std::vector<WavePortion> portions;
773  FindWavePortions(portions, rect, zoomInfo, params);
774  const unsigned nPortions = portions.size();
775 
776  // Require at least 1/2 pixel per sample for drawing individual samples.
777  const double threshold1 = 0.5 * rate;
778  // Require at least 3 pixels per sample for drawing the draggable points.
779  const double threshold2 = 3 * rate;
780 
781  auto &clipCache = WaveClipWaveformCache::Get(*clip);
782 
783  {
784  bool showIndividualSamples = false;
785  for (unsigned ii = 0; !showIndividualSamples && ii < nPortions; ++ii) {
786  const WavePortion &portion = portions[ii];
787  showIndividualSamples =
788  !portion.inFisheye && portion.averageZoom > threshold1;
789  }
790 
791  if (!showIndividualSamples) {
792  // The WaveClip class handles the details of computing the shape
793  // of the waveform. The only way GetWaveDisplay will fail is if
794  // there's a serious error, like some of the waveform data can't
795  // be loaded. So if the function returns false, we can just exit.
796 
797  // Note that we compute the full width display even if there is a
798  // fisheye hiding part of it, because of the caching. If the
799  // fisheye moves over the background, there is then less to do when
800  // redrawing.
801 
802  if (!clipCache.GetWaveDisplay( *clip, display,
803  t0, pps))
804  return;
805  }
806  }
807 
808  // TODO Add a comment to say what this loop does.
809  // Possibly make it into a subroutine.
810  for (unsigned ii = 0; ii < nPortions; ++ii) {
811  WavePortion &portion = portions[ii];
812  const bool showIndividualSamples = portion.averageZoom > threshold1;
813  const bool showPoints = portion.averageZoom > threshold2;
814  wxRect& rectPortion = portion.rect;
815  rectPortion.Intersect(mid);
816  wxASSERT(rectPortion.width >= 0);
817 
818  float *useMin = 0, *useMax = 0, *useRms = 0;
819  int *useBl = 0;
820  WaveDisplay fisheyeDisplay(rectPortion.width);
821  int skipped = 0, skippedLeft = 0, skippedRight = 0;
822  if (portion.inFisheye) {
823  if (!showIndividualSamples) {
824  fisheyeDisplay.Allocate();
825  const auto numSamples = clip->GetPlaySamplesCount();
826  // Get wave display data for different magnification
827  int jj = 0;
828  for (; jj < rectPortion.width; ++jj) {
829  const double time =
830  zoomInfo.PositionToTime(jj, -leftOffset) - tOffset;
831  const auto sample = (sampleCount)floor(time * rate + 0.5);
832  if (sample < 0) {
833  ++rectPortion.x;
834  ++skippedLeft;
835  continue;
836  }
837  if (sample >= numSamples)
838  break;
839  fisheyeDisplay.where[jj - skippedLeft] = sample;
840  }
841 
842  skippedRight = rectPortion.width - jj;
843  skipped = skippedRight + skippedLeft;
844  rectPortion.width -= skipped;
845 
846  // where needs a sentinel
847  if (jj > 0)
848  fisheyeDisplay.where[jj - skippedLeft] =
849  1 + fisheyeDisplay.where[jj - skippedLeft - 1];
850  fisheyeDisplay.width -= skipped;
851  // Get a wave display for the fisheye, uncached.
852  if (rectPortion.width > 0)
853  if (!clipCache.GetWaveDisplay( *clip,
854  fisheyeDisplay, t0, -1.0)) // ignored
855  continue; // serious error. just don't draw??
856  useMin = fisheyeDisplay.min;
857  useMax = fisheyeDisplay.max;
858  useRms = fisheyeDisplay.rms;
859  useBl = fisheyeDisplay.bl;
860  }
861  }
862  else {
863  const int pos = leftOffset - params.hiddenLeftOffset;
864  useMin = display.min + pos;
865  useMax = display.max + pos;
866  useRms = display.rms + pos;
867  useBl = display.bl + pos;
868  }
869 
870  leftOffset += skippedLeft;
871 
872  if (rectPortion.width > 0) {
873  if (!showIndividualSamples) {
874  std::vector<double> vEnv2(rectPortion.width);
875  double *const env2 = &vEnv2[0];
877  tOffset,
878 
879  // PRL: change back to make envelope evaluate only at sample times
880  // and then interpolate the display
881  0, // 1.0 / rate,
882 
883  env2, rectPortion.width, leftOffset, zoomInfo );
884  DrawMinMaxRMS( context, rectPortion, env2,
885  zoomMin, zoomMax,
886  dB, dBRange,
887  useMin, useMax, useRms, useBl, muted );
888  }
889  else {
890  bool highlight = false;
891 #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
892  auto target = dynamic_cast<SampleHandle*>(context.target.get());
893  highlight = target && target->GetTrack().get() == track;
894 #endif
896  context, leftOffset, rectPortion, zoomMin, zoomMax,
897  dB, dBRange,
898  clip,
899  showPoints, muted, highlight );
900  }
901  }
902 
903  leftOffset += rectPortion.width + skippedRight;
904  }
905 
906  const auto drawEnvelope = artist->drawEnvelope;
907  if (drawEnvelope) {
908  DrawEnvelope(
909  context, mid, env, zoomMin, zoomMax, dB, dBRange, highlightEnvelope );
911  context, mid, dB, dBRange, zoomMin, zoomMax, true, rect.x - mid.x );
912  }
913 
914  // Draw arrows on the left side if the track extends to the left of the
915  // beginning of time. :)
916  if (h == 0.0 && tOffset < 0.0) {
918  }
919  {
920  auto clipRect = ClipParameters::GetClipRect(*clip, zoomInfo, rect);
921  TrackArt::DrawClipEdges(dc, clipRect, selected);
922  }
923 }
924 
926  const wxRect & rect,
927  bool rightwards, bool highlight )
928 {
929  auto &dc = context.dc;
930 
931  const int border = 3; // 3 pixels all round.
932  const int width = 6; // width of the drag box.
933  const int taper = 6; // how much the box tapers by.
934  const int barSpacing = 4; // how far apart the bars are.
935  const int barWidth = 3;
936  const int xFlat = 3;
937 
938  //Enough space to draw in?
939  if (rect.height <= ((taper+border + barSpacing) * 2)) {
940  return;
941  }
942  if (rect.width <= (width * 2 + border * 3)) {
943  return;
944  }
945 
946  // The draggable box is tapered towards the direction you drag it.
947  int leftTaper = rightwards ? 0 : 6;
948  int rightTaper = rightwards ? 6 : 0;
949 
950  int xLeft = rightwards ? (rect.x + border - 2)
951  : (rect.x + rect.width + 1 - (border + width));
952  int yTop = rect.y + border;
953  int yBot = rect.y + rect.height - border - 1;
954 
955  AColor::Light(&dc, false, highlight);
956  AColor::Line(dc, xLeft, yBot - leftTaper, xLeft, yTop + leftTaper);
957  AColor::Line(dc, xLeft, yTop + leftTaper, xLeft + xFlat, yTop);
958  AColor::Line(dc, xLeft + xFlat, yTop, xLeft + width, yTop + rightTaper);
959 
960  AColor::Dark(&dc, false, highlight);
961  AColor::Line(dc, xLeft + width, yTop + rightTaper, xLeft + width, yBot - rightTaper);
962  AColor::Line(dc, xLeft + width, yBot - rightTaper, xLeft + width-xFlat, yBot);
963  AColor::Line(dc, xLeft + width - xFlat, yBot, xLeft, yBot - leftTaper);
964 
965  int firstBar = yTop + taper + taper / 2;
966  int nBars = (yBot - yTop - taper * 3) / barSpacing + 1;
967  xLeft += (width - barWidth + 1) / 2;
968  int yy;
969  int i;
970 
971  AColor::Light(&dc, false, highlight);
972  for (i = 0;i < nBars; i++) {
973  yy = firstBar + barSpacing * i;
974  AColor::Line(dc, xLeft, yy, xLeft + barWidth, yy);
975  }
976  AColor::Dark(&dc, false, highlight);
977  for(i = 0;i < nBars; i++){
978  yy = firstBar + barSpacing * i + 1;
979  AColor::Line(dc, xLeft, yy, xLeft + barWidth, yy);
980  }
981 }
982 
983 }
984 
985 // Header needed only for experimental drawing below
986 //#include "tracks/ui/TimeShiftHandle.h"
988  const WaveTrack *track,
989  const WaveClip* selectedClip,
990  const wxRect& rect,
991  bool muted)
992 {
993  auto &dc = context.dc;
994  const auto artist = TrackArtist::Get( context );
995 
996  bool highlight = false;
997  bool gripHit = false;
998 #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
999  auto target = dynamic_cast<TimeShiftHandle*>(context.target.get());
1000  gripHit = target && target->IsGripHit();
1001  highlight = target && target->GetTrack().get() == track;
1002 #endif
1003 
1004  const bool dB = !track->GetWaveformSettings().isLinear();
1005 
1006  const auto &blankSelectedBrush = artist->blankSelectedBrush;
1007  const auto &blankBrush = artist->blankBrush;
1009  context, rect, track, blankSelectedBrush, blankBrush );
1010 
1011  for (const auto& clip : track->GetClips())
1012  {
1013  DrawClipWaveform(context, track, clip.get(), rect,
1014  dB, muted, clip.get() == selectedClip);
1015  }
1016  DrawBoldBoundaries( context, track, rect );
1017 
1018  const auto drawSliders = artist->drawSliders;
1019  if (drawSliders) {
1020  DrawTimeSlider( context, rect, true, highlight && gripHit ); // directed right
1021  DrawTimeSlider( context, rect, false, highlight && gripHit ); // directed left
1022  }
1023 }
1024 
1026  TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass )
1027 {
1028  if ( iPass == TrackArtist::PassTracks ) {
1029  auto &dc = context.dc;
1030  // Update cache for locations, e.g. cutlines and merge points
1031  // Bug2588: do this for both channels, even if one is not drawn, so that
1032  // cut-line editing (which depends on the locations cache) works properly.
1033  // If both channels are visible, we will duplicate this effort, but that
1034  // matters little.
1035  for( auto channel:
1036  TrackList::Channels(static_cast<WaveTrack*>(FindTrack().get())) )
1037  channel->UpdateLocationsCache();
1038 
1039  const auto wt = std::static_pointer_cast<const WaveTrack>(
1040  FindTrack()->SubstitutePendingChangedTrack());
1041 
1042  const auto artist = TrackArtist::Get( context );
1043  const auto hasSolo = artist->hasSolo;
1044  bool muted = (hasSolo || wt->GetMute()) &&
1045  !wt->GetSolo();
1046 
1047 #if defined(__WXMAC__)
1048  wxAntialiasMode aamode = dc.GetGraphicsContext()->GetAntialiasMode();
1049  dc.GetGraphicsContext()->SetAntialiasMode(wxANTIALIAS_NONE);
1050 #endif
1051 
1052  auto waveTrackView = GetWaveTrackView().lock();
1053  wxASSERT(waveTrackView.use_count());
1054 
1055  auto selectedClip = waveTrackView->GetSelectedClip().lock();
1056  DoDraw(context, wt.get(), selectedClip.get(), rect, muted);
1057 
1058 #if defined(__WXMAC__)
1059  dc.GetGraphicsContext()->SetAntialiasMode(aamode);
1060 #endif
1061  }
1062  WaveTrackSubView::Draw( context, rect, iPass );
1063 }
1064 
1066  []( WaveTrackView &view ){
1067  return std::make_shared< WaveformView >( view );
1068  }
1069 };
1070 
1071 // The following attaches the wave color sub-menu to the wave track popup
1072 // menu. It is appropriate only to waveform view and so is kept in this
1073 // source file with the rest of the waveform view implementation.
1074 
1075 #include <mutex> // for std::call_once
1076 #include "WaveTrackControls.h"
1077 #include "../../../../widgets/PopupMenuTable.h"
1078 #include "../../../../ProjectAudioIO.h"
1079 #include "../../../../ProjectHistory.h"
1080 #include "../../../../RefreshCode.h"
1081 
1082 //=============================================================================
1083 // Table class for a sub-menu
1085 {
1086  WaveColorMenuTable() : PopupMenuTable{ "WaveColor", XO("&Wave Color") } {}
1088 
1089  static WaveColorMenuTable &Instance();
1090 
1091  void InitUserData(void *pUserData) override;
1092 
1094 
1095  int IdOfWaveColor(int WaveColor);
1096  void OnWaveColorChange(wxCommandEvent & event);
1097 
1099 };
1100 
1102 {
1103  static WaveColorMenuTable instance;
1104  return instance;
1105 }
1106 
1108 {
1109  mpData = static_cast<PlayableTrackControls::InitMenuData*>(pUserData);
1110 }
1111 
1112 namespace {
1113 using ValueFinder = std::function< int( WaveTrack& ) >;
1114 
1116 {
1117  return XXO("Instrument %i").Format( colorIndex+1 );
1118 }
1119 }
1120 
1122  static const auto fn = []( PopupMenuHandler &handler, wxMenu &menu, int id ){
1123  auto &me = static_cast<WaveColorMenuTable&>( handler );
1124  auto pData = me.mpData;
1125  const auto &track = *static_cast<WaveTrack*>(pData->pTrack);
1126  auto &project = pData->project;
1127  bool unsafe = ProjectAudioIO::Get( project ).IsAudioActive();
1128 
1129  menu.Check( id, id == me.IdOfWaveColor( track.GetWaveColorIndex() ) );
1130  menu.Enable( id, !unsafe );
1131  };
1132 
1133  static std::once_flag flag;
1134  std::call_once( flag, [this]{
1135  auto &hostTable = GetWaveTrackMenuTable();
1136  OnInstrument1ID = hostTable.ReserveId();
1137  OnInstrument2ID = hostTable.ReserveId();
1138  OnInstrument3ID = hostTable.ReserveId();
1139  OnInstrument4ID = hostTable.ReserveId();
1140  } );
1141 
1142  AppendRadioItem( "Instrument1", OnInstrument1ID,
1143  GetWaveColorStr(0), POPUP_MENU_FN( OnWaveColorChange ), fn );
1144  AppendRadioItem( "Instrument2", OnInstrument2ID,
1145  GetWaveColorStr(1), POPUP_MENU_FN( OnWaveColorChange ), fn );
1146  AppendRadioItem( "Instrument3", OnInstrument3ID,
1147  GetWaveColorStr(2), POPUP_MENU_FN( OnWaveColorChange ), fn );
1148  AppendRadioItem( "Instrument4", OnInstrument4ID,
1149  GetWaveColorStr(3), POPUP_MENU_FN( OnWaveColorChange ), fn );
1150 
1152 
1153 int WaveColorMenuTable::IdOfWaveColor(int WaveColor)
1155 { return OnInstrument1ID + WaveColor;}
1156 
1159 void WaveColorMenuTable::OnWaveColorChange(wxCommandEvent & event)
1160 {
1161  int id = event.GetId();
1162  wxASSERT(id >= OnInstrument1ID && id <= OnInstrument4ID);
1163  const auto pTrack = static_cast<WaveTrack*>(mpData->pTrack);
1164 
1165  int newWaveColor = id - OnInstrument1ID;
1166 
1167  AudacityProject *const project = &mpData->project;
1168 
1169  for (auto channel : TrackList::Channels(pTrack))
1170  channel->SetWaveColorIndex(newWaveColor);
1171 
1172  ProjectHistory::Get( *project )
1173  .PushState(XO("Changed '%s' to %s")
1174  .Format( pTrack->GetName(), GetWaveColorStr(newWaveColor) ),
1175  XO("WaveColor Change"));
1176 
1177  using namespace RefreshCode;
1179 }
1180 
1181 namespace {
1184  { "SubViews/Extra" },
1185  std::make_unique<PopupMenuSection>( "WaveColor",
1186  // Conditionally add sub-menu for wave color, if showing waveform
1187  PopupMenuTable::Computed< WaveTrackPopupMenuTable >(
1189  const auto pTrack = &table.FindWaveTrack();
1190  const auto &view = WaveTrackView::Get( *pTrack );
1191  const auto displays = view.GetDisplays();
1192  bool hasWaveform = (displays.end() != std::find(
1193  displays.begin(), displays.end(),
1194  WaveTrackSubView::Type{ WaveTrackViewConstants::Waveform, {} }
1195  ) );
1196  if( hasWaveform )
1198  .Get( table.mpData ) );
1199  else
1200  return nullptr;
1201  } ) )
1202 };
1203 }
1204 
SampleHandle.h
WaveformSettings::isLinear
bool isLinear() const
Definition: WaveformSettings.h:71
WaveColorMenuTable
Definition: WaveformView.cpp:1085
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
RefreshCode::FixScrollbars
@ FixScrollbars
Definition: RefreshCode.h:27
WaveTrackView::ClipDetailsVisible
static bool ClipDetailsVisible(const WaveClip &clip, const ZoomInfo &zoomInfo, const wxRect &viewRect)
Definition: WaveTrackView.cpp:1357
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
anonymous_namespace{WaveformView.cpp}::FindWavePortions
void FindWavePortions(std::vector< WavePortion > &portions, const wxRect &rect, const ZoomInfo &zoomInfo, const ClipParameters &params)
Definition: WaveformView.cpp:298
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:75
WaveTrackView
Definition: WaveTrackView.h:98
ToolCodes::drawTool
@ drawTool
Definition: ProjectSettings.h:42
GetWaveYPos
int GetWaveYPos(float value, float min, float max, int height, bool dB, bool outer, float dBr, bool clip)
Definition: TrackArt.cpp:32
fn
static const auto fn
Definition: WaveformView.cpp:1122
RefreshCode::RefreshAll
@ RefreshAll
Definition: RefreshCode.h:26
AppendRadioItem
AppendRadioItem("Instrument1", OnInstrument1ID, GetWaveColorStr(0), POPUP_MENU_FN(OnWaveColorChange), fn)
EnvelopeHandle::GetEnvelope
Envelope * GetEnvelope() const
Definition: EnvelopeHandle.h:59
flag
static std::once_flag flag
Definition: WaveformView.cpp:1133
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:71
CommonTrackView::GetEnvelopeValues
static void GetEnvelopeValues(const Envelope &env, double aligned_time, double sampleDur, double *buffer, int bufferLen, int leftOffset, const ZoomInfo &zoomInfo)
Get many envelope points for pixel columns at once, but don't assume uniform time per pixel.
Definition: CommonTrackView.cpp:104
WaveformView::SubViewType
const Type & SubViewType() const override
Definition: WaveformView.cpp:133
WaveClip::GetEnvelope
Envelope * GetEnvelope()
Definition: WaveClip.h:205
Profiler
A simple profiler to measure the average time lengths that a particular task/function takes....
Definition: Profiler.h:40
WaveClip::GetPlaySamplesCount
sampleCount GetPlaySamplesCount() const
Definition: WaveClip.cpp:932
PopupMenuTable
Definition: PopupMenuTable.h:115
ZoomInfo
Definition: ZoomInfo.h:47
EnvelopeHandle::WaveTrackHitTest
static UIHandlePtr WaveTrackHitTest(std::weak_ptr< EnvelopeHandle > &holder, const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject, const std::shared_ptr< WaveTrack > &wt)
Definition: EnvelopeHandle.cpp:90
CommonTrackPanelCell::FindTrack
std::shared_ptr< Track > FindTrack()
Definition: CommonTrackPanelCell.h:47
EnvelopeEditor::DrawPoints
static void DrawPoints(const Envelope &env, TrackPanelDrawingContext &context, const wxRect &r, bool dB, double dBRange, float zoomMin, float zoomMax, bool mirrored, int origin=0)
Definition: EnvelopeEditor.cpp:36
TrackPanelDrawingContext
Definition: TrackPanelDrawingContext.h:22
TrackList::Channels
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1483
Format
Abstract base class used in importing a file.
WaveClip::GetRate
int GetRate() const
Definition: WaveClip.h:139
AColor::Line
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:109
SampleHandle::HitAnywhere
static UIHandlePtr HitAnywhere(std::weak_ptr< SampleHandle > &holder, const wxMouseState &state, const std::shared_ptr< WaveTrack > &pTrack)
Definition: SampleHandle.cpp:74
WaveTrackSubView::DrawBoldBoundaries
static void DrawBoldBoundaries(TrackPanelDrawingContext &context, const WaveTrack *track, const wxRect &rect)
Definition: WaveTrackView.cpp:777
ArrayOf::reinit
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
Registry::Shared
std::unique_ptr< SharedItem > Shared(const BaseItemSharedPtr &ptr)
Definition: Registry.h:93
SelectedRegion.h
WaveformView::DoSetMinimized
void DoSetMinimized(bool minimized) override
Definition: WaveformView.cpp:112
XO
#define XO(s)
Definition: Internat.h:31
anonymous_namespace{WaveformView.cpp}::WavePortion::rect
wxRect rect
Definition: WaveformView.cpp:289
AColor::uglyBrush
static wxBrush uglyBrush
Definition: AColor.h:131
TrackPanelDrawingContext::dc
wxDC & dc
Definition: TrackPanelDrawingContext.h:23
CommonTrackControls::InitMenuData::result
unsigned result
Definition: CommonTrackControls.h:39
TimeShiftHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< TimeShiftHandle > &holder, const wxMouseState &state, const wxRect &rect, const std::shared_ptr< Track > &pTrack)
Definition: TimeShiftHandle.cpp:90
anonymous_namespace{WaveformView.cpp}::DrawWaveformBackground
void DrawWaveformBackground(TrackPanelDrawingContext &context, int leftOffset, const wxRect &rect, const double env[], float zoomMin, float zoomMax, int zeroLevelYCoordinate, bool dB, float dBRange, double t0, double t1, bool bIsSyncLockSelected, bool highlightEnvelope)
Definition: WaveformView.cpp:146
EnvelopeHandle
Definition: EnvelopeHandle.h:28
anonymous_namespace{WaveformView.cpp}::WavePortion::averageZoom
CONST double averageZoom
Definition: WaveformView.cpp:290
ProjectAudioIO::Get
static ProjectAudioIO & Get(AudacityProject &project)
Definition: ProjectAudioIO.cpp:24
ClipParameters::GetClipRect
static wxRect GetClipRect(const WaveClip &clip, const ZoomInfo &zoomInfo, const wxRect &viewRect, bool *outShowSamples=nullptr)
Definition: WaveTrackView.cpp:1674
WaveColorMenuTable::OnInstrument4ID
int OnInstrument4ID
Definition: WaveformView.cpp:1098
AColor::envelopePen
static wxPen envelopePen
Definition: AColor.h:104
anonymous_namespace{WaveformView.cpp}::ValueFinder
std::function< int(WaveTrack &) > ValueFinder
Definition: WaveformView.cpp:1113
anonymous_namespace{WaveformView.cpp}::sAttachment
PopupMenuTable::AttachedItem sAttachment
Definition: WaveformView.cpp:1182
TrackPanelMouseState::rect
const wxRect & rect
Definition: TrackPanelMouseEvent.h:39
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
GetWaveTrackMenuTable
WaveTrackPopupMenuTable & GetWaveTrackMenuTable()
Definition: WaveTrackControls.cpp:960
WaveformView::DetailedHitTest
std::vector< UIHandlePtr > DetailedHitTest(const TrackPanelMouseState &state, const AudacityProject *pProject, int currentTool, bool bMultiTool) override
Definition: WaveformView.cpp:49
ProjectAudioIO::IsAudioActive
bool IsAudioActive() const
Definition: ProjectAudioIO.cpp:53
TrackArt::DrawClipFolded
AUDACITY_DLL_API void DrawClipFolded(wxDC &dc, const wxRect &rect)
Definition: TrackArt.cpp:280
WaveTrack::ZeroLevelYCoordinate
int ZeroLevelYCoordinate(wxRect rect) const
Definition: WaveTrack.cpp:420
CommonTrackControls::InitMenuData::project
AudacityProject & project
Definition: CommonTrackControls.h:36
WaveTrackSubView::DoDetailedHitTest
std::pair< bool, std::vector< UIHandlePtr > > DoDetailedHitTest(const TrackPanelMouseState &state, const AudacityProject *pProject, int currentTool, bool bMultiTool, const std::shared_ptr< WaveTrack > &wt)
WaveTrackView.h
SampleHandle
Definition: SampleHandle.h:25
WaveformVRulerControls.h
WaveformView::DoGetVRulerControls
std::shared_ptr< TrackVRulerControls > DoGetVRulerControls() override
Definition: WaveformView.cpp:138
TrackArt::DrawSyncLockTiles
AUDACITY_DLL_API void DrawSyncLockTiles(TrackPanelDrawingContext &context, const wxRect &rect)
Definition: TrackArt.cpp:299
floatSample
@ floatSample
Definition: SampleFormat.h:34
WaveformView::~WaveformView
~WaveformView() override
WaveClip::GetSamples
bool GetSamples(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool mayThrow=true) const
Definition: WaveClip.cpp:126
WaveClip
This allows multiple clips to be a part of one WaveTrack.
Definition: WaveClip.h:101
WaveColorMenuTable::mpData
PlayableTrackControls::InitMenuData * mpData
Definition: WaveformView.cpp:1093
TrackArtist::Get
static TrackArtist * Get(TrackPanelDrawingContext &)
Definition: TrackArtist.cpp:69
XXO
#define XXO(s)
Definition: Internat.h:44
sType
static WaveTrackSubView::Type sType
Definition: WaveformView.cpp:40
Registry::BaseItemPtr
std::unique_ptr< BaseItem > BaseItemPtr
Definition: Registry.h:71
anonymous_namespace{WaveformView.cpp}::DrawClipWaveform
void DrawClipWaveform(TrackPanelDrawingContext &context, const WaveTrack *track, const WaveClip *clip, const wxRect &rect, bool dB, bool muted, bool selected)
Definition: WaveformView.cpp:671
WaveColorMenuTable::Instance
static WaveColorMenuTable & Instance()
Definition: WaveformView.cpp:1101
WaveTrackSubViewType
Definition: WaveTrackViewConstants.h:89
WaveDisplay::max
float * max
Definition: WaveClip.h:52
anonymous_namespace{WaveformView.cpp}::DrawEnvLine
void DrawEnvLine(TrackPanelDrawingContext &context, const wxRect &rect, int x0, int y0, int cy, bool top)
Definition: WaveformView.cpp:602
WaveClip::GetColourIndex
int GetColourIndex() const
Definition: WaveClip.h:149
TrackArt::DrawNegativeOffsetTrackArrows
AUDACITY_DLL_API void DrawNegativeOffsetTrackArrows(TrackPanelDrawingContext &context, const wxRect &rect)
Definition: TrackArt.cpp:109
TimeShiftHandle::IsGripHit
bool IsGripHit() const
Definition: TimeShiftHandle.h:273
key
static const WaveTrackSubViews::RegisteredFactory key
Definition: WaveformView.cpp:1065
AColor::Light
static void Light(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:321
WaveformView::DoDraw
static void DoDraw(TrackPanelDrawingContext &context, const WaveTrack *track, const WaveClip *selectedClip, const wxRect &rect, bool muted)
Definition: WaveformView.cpp:987
PopupMenuTable::Get
const std::shared_ptr< Registry::GroupItem > & Get(void *pUserData)
Definition: PopupMenuTable.h:146
WaveTrack::GetClips
WaveClipHolders & GetClips()
Definition: WaveTrack.h:322
WaveColorMenuTable::OnInstrument2ID
int OnInstrument2ID
Definition: WaveformView.cpp:1098
WaveDisplay::width
int width
Definition: WaveClip.h:50
WaveColorMenuTable::OnInstrument3ID
int OnInstrument3ID
Definition: WaveformView.cpp:1098
CONST
#define CONST
Definition: PrefsDialog.h:28
UIHandlePtr
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
WaveColorMenuTable::OnInstrument1ID
int OnInstrument1ID
Definition: WaveformView.cpp:1098
WaveColorMenuTable::WaveColorMenuTable
WaveColorMenuTable()
Definition: WaveformView.cpp:1086
ClipParameters
Definition: WaveTrackView.h:241
reg
static WaveTrackSubViewType::RegisteredType reg
Definition: WaveformView.cpp:45
SyncLock::IsSelectedOrSyncLockSelected
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:73
AColor::uglyPen
static wxPen uglyPen
Definition: AColor.h:130
CommonTrackControls::InitMenuData
Definition: CommonTrackControls.h:34
TrackView::DoSetMinimized
virtual void DoSetMinimized(bool isMinimized)
Definition: TrackView.cpp:141
WaveTrack::GetWaveformSettings
const WaveformSettings & GetWaveformSettings() const
Definition: WaveTrack.cpp:849
ViewInfo.h
POPUP_MENU_FN
#define POPUP_MENU_FN(memFn)
Definition: PopupMenuTable.h:324
SampleHandle::GetTrack
std::shared_ptr< WaveTrack > GetTrack() const
Definition: SampleHandle.h:45
WaveColorMenuTable::DECLARE_POPUP_MENU
DECLARE_POPUP_MENU(WaveColorMenuTable)
Track::GetSelected
bool GetSelected() const
Definition: Track.h:428
ZoomInfo::FindIntervals
void FindIntervals(double rate, Intervals &results, wxInt64 width, wxInt64 origin=0) const
Definition: ZoomInfo.cpp:110
TimeShiftHandle
Definition: TimeShiftHandle.h:262
Envelope.h
samplePtr
char * samplePtr
Definition: SampleFormat.h:49
BEGIN_POPUP_MENU
#define BEGIN_POPUP_MENU(HandlerClass)
Definition: PopupMenuTable.h:316
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
Envelope::GetValue
double GetValue(double t, double sampleDur=0) const
Get envelope value at time t.
Definition: Envelope.cpp:823
WaveColorMenuTable::InitUserData
void InitUserData(void *pUserData) override
Called before the menu items are appended.
Definition: WaveformView.cpp:1107
WaveformCache.h
ProjectHistory::PushState
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
Definition: ProjectHistory.cpp:90
TrackArt::DrawBackgroundWithSelection
AUDACITY_DLL_API void DrawBackgroundWithSelection(TrackPanelDrawingContext &context, const wxRect &rect, const Track *track, const wxBrush &selBrush, const wxBrush &unselBrush, bool useSelection=true)
Definition: TrackArt.cpp:409
WaveTrackSubViewType::RegisteredType
Definition: WaveTrackViewConstants.h:106
PopupMenuHandler
Definition: PopupMenuTable.h:85
ToolCodes::envelopeTool
@ envelopeTool
Definition: ProjectSettings.h:41
AColor::Dark
static void Dark(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:351
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
WaveTrackViewConstants.h
TrackArt::DrawClipEdges
AUDACITY_DLL_API void DrawClipEdges(wxDC &dc, const wxRect &clipRect, bool selected=false)
Definition: TrackArt.cpp:243
WaveDisplay::rms
float * rms
Definition: WaveClip.h:52
WaveTrackView::Get
static WaveTrackView & Get(WaveTrack &track)
Definition: WaveTrackView.cpp:855
anonymous_namespace{WaveformView.cpp}::WavePortion::WavePortion
WavePortion(int x, int y, int w, int h, double zoom, bool i)
Definition: WaveformView.cpp:292
WaveTrackViewConstants::StemPlot
@ StemPlot
Definition: WaveTrackViewConstants.h:45
WaveformSettings::dBRange
int dBRange
Definition: WaveformSettings.h:68
TrackPanelMouseState
Definition: TrackPanelMouseEvent.h:28
TrackPanelDrawingContext::target
UIHandlePtr target
Definition: TrackPanelDrawingContext.h:24
SampleTrack::TimeToLongSamples
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: SampleTrack.cpp:35
WaveTrackSubView::GetWaveTrackView
std::weak_ptr< WaveTrackView > GetWaveTrackView() const
Definition: WaveTrackView.cpp:818
WaveTrackPopupMenuTable::FindWaveTrack
WaveTrack & FindWaveTrack() const
Definition: WaveTrackControls.cpp:89
TrackArtist::PassTracks
@ PassTracks
Definition: TrackArtist.h:44
PopupMenuTable::AttachedItem
Definition: PopupMenuTable.h:136
WaveformView::Draw
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: WaveformView.cpp:1025
anonymous_namespace{WaveformView.cpp}::DrawIndividualSamples
void DrawIndividualSamples(TrackPanelDrawingContext &context, int leftOffset, const wxRect &rect, float zoomMin, float zoomMax, bool dB, float dBRange, const WaveClip *clip, bool showPoints, bool muted, bool highlight)
Definition: WaveformView.cpp:476
WaveDisplay::min
float * min
Definition: WaveClip.h:52
WaveTrackControls.h
WaveClipWaveformCache::Get
static WaveClipWaveformCache & Get(const WaveClip &clip)
Definition: WaveformCache.cpp:293
anonymous_namespace{WaveformView.cpp}::DrawMinMaxRMS
void DrawMinMaxRMS(TrackPanelDrawingContext &context, const wxRect &rect, const double env[], float zoomMin, float zoomMax, bool dB, float dBRange, const float *min, const float *max, const float *rms, const int *bl, bool muted)
Definition: WaveformView.cpp:327
params
EffectDistortion::Params params
Definition: Distortion.cpp:99
WaveColorMenuTable::OnWaveColorChange
void OnWaveColorChange(wxCommandEvent &event)
Definition: WaveformView.cpp:1159
anonymous_namespace{WaveformView.cpp}::WavePortion
Definition: WaveformView.cpp:288
WaveColorMenuTable::IdOfWaveColor
int IdOfWaveColor(int WaveColor)
Converts a WaveColor enumeration to a wxWidgets menu item Id.
Definition: WaveformView.cpp:1154
WaveTrack::GetDisplayBounds
void GetDisplayBounds(float *min, float *max) const
Definition: WaveTrack.cpp:358
WaveTrackPopupMenuTable
Definition: WaveTrackControls.h:74
RefreshCode
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
CommonTrackControls::InitMenuData::pTrack
Track * pTrack
Definition: CommonTrackControls.h:37
ZoomInfo::Intervals
std::vector< Interval > Intervals
Definition: ZoomInfo.h:146
WaveDisplay::Allocate
void Allocate()
Definition: WaveClip.h:66
SampleTrack::LongSamplesToTime
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
Definition: SampleTrack.cpp:40
AColor.h
anonymous_namespace{WaveformView.cpp}::DrawTimeSlider
void DrawTimeSlider(TrackPanelDrawingContext &context, const wxRect &rect, bool rightwards, bool highlight)
Definition: WaveformView.cpp:925
anonymous_namespace{WaveformView.cpp}::DrawEnvelope
void DrawEnvelope(TrackPanelDrawingContext &context, const wxRect &rect, const double env[], float zoomMin, float zoomMax, bool dB, float dBRange, bool highlight)
Definition: WaveformView.cpp:631
WaveClip::GetPlayStartTime
double GetPlayStartTime() const noexcept
Definition: WaveClip.cpp:900
WaveTrackPopupMenuTable::mpData
PlayableTrackControls::InitMenuData * mpData
Definition: WaveTrackControls.h:76
anonymous_namespace{WaveformView.cpp}::GetWaveColorStr
const TranslatableString GetWaveColorStr(int colorIndex)
Definition: WaveformView.cpp:1115
ArrayOf< int >
MAX_AUDIO
#define MAX_AUDIO
Definition: MemoryX.h:505
WaveDisplay
Definition: WaveClip.h:48
WaveDisplay::where
sampleCount * where
Definition: WaveClip.h:51
TrackPanelMouseState::state
wxMouseState & state
Definition: TrackPanelMouseEvent.h:38
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
WaveDisplay::bl
int * bl
Definition: WaveClip.h:53
WaveTrackViewConstants::Waveform
@ Waveform
Definition: WaveTrackViewConstants.h:24
EnvelopeHandle::HitAnywhere
static UIHandlePtr HitAnywhere(std::weak_ptr< EnvelopeHandle > &holder, Envelope *envelope, bool timeTrack)
Definition: EnvelopeHandle.cpp:48
anonymous_namespace{WaveformView.cpp}::WavePortion::inFisheye
CONST bool inFisheye
Definition: WaveformView.cpp:291
WaveformView.h
END_POPUP_MENU
#define END_POPUP_MENU()
Definition: PopupMenuTable.h:331
SampleHandle::HitTest
static UIHandlePtr HitTest(std::weak_ptr< SampleHandle > &holder, const wxMouseState &state, const wxRect &rect, const AudacityProject *pProject, const std::shared_ptr< WaveTrack > &pTrack)
Definition: SampleHandle.cpp:112
TrackPanelDrawable::Draw
virtual void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass)
Definition: TrackPanelDrawable.cpp:17