Audacity 3.2.0
Classes | Typedefs | Functions | Variables
anonymous_namespace{WaveformView.cpp} Namespace Reference

Classes

struct  WavePortion
 

Typedefs

using ValueFinder = std::function< int(WaveTrack &) >
 

Functions

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)
 
void FindWavePortions (std::vector< WavePortion > &portions, const wxRect &rect, const ZoomInfo &zoomInfo, const ClipParameters &params)
 
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, bool muted)
 
void DrawIndividualSamples (TrackPanelDrawingContext &context, int leftOffset, const wxRect &rect, float zoomMin, float zoomMax, bool dB, float dBRange, const WaveChannelInterval &clip, bool showPoints, bool muted, bool highlight)
 
void DrawEnvLine (TrackPanelDrawingContext &context, const wxRect &rect, int x0, int y0, int cy, bool top)
 
void DrawEnvelope (TrackPanelDrawingContext &context, const wxRect &rect, const double env[], float zoomMin, float zoomMax, bool dB, float dBRange, bool highlight)
 
void DrawClipWaveform (TrackPanelDrawingContext &context, const WaveTrack &track, const WaveChannelInterval &clip, const wxRect &rect, bool dB, bool muted, bool selected)
 
void DrawTimeSlider (TrackPanelDrawingContext &context, const wxRect &rect, bool rightwards, bool highlight)
 
const TranslatableString GetWaveColorStr (int colorIndex)
 

Variables

PopupMenuTable::AttachedItem sAttachment
 

Typedef Documentation

◆ ValueFinder

using anonymous_namespace{WaveformView.cpp}::ValueFinder = typedef std::function< int( WaveTrack& ) >

Definition at line 1084 of file WaveformView.cpp.

Function Documentation

◆ DrawClipWaveform()

void anonymous_namespace{WaveformView.cpp}::DrawClipWaveform ( TrackPanelDrawingContext context,
const WaveTrack track,
const WaveChannelInterval clip,
const wxRect &  rect,
bool  dB,
bool  muted,
bool  selected 
)

Definition at line 645 of file WaveformView.cpp.

648{
649 const Envelope &envelope = clip.GetEnvelope();
650 auto &dc = context.dc;
651 const auto artist = TrackArtist::Get(context);
652 const auto &selectedRegion = *artist->pSelectedRegion;
653 const auto &zoomInfo = *artist->pZoomInfo;
654
656
657 bool highlightEnvelope = false;
658#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
659 auto target = dynamic_cast<EnvelopeHandle*>(context.target.get());
660 highlightEnvelope = target && target->GetEnvelope() == &envelope;
661#endif
662
663 //If clip is "too small" draw a placeholder instead of
664 //attempting to fit the contents into a few pixels
665 if (!WaveChannelView::ClipDetailsVisible(clip, zoomInfo, rect))
666 {
667 auto clipRect = ClipParameters::GetClipRect(clip, zoomInfo, rect);
668 TrackArt::DrawClipFolded(dc, clipRect);
669 return;
670 }
671
672 const ClipParameters params { clip, rect, zoomInfo };
673 const wxRect &hiddenMid = params.hiddenMid;
674 // The "hiddenMid" rect contains the part of the display actually
675 // containing the waveform, as it appears without the fisheye. If it's empty, we're done.
676 if (hiddenMid.width <= 0) {
677 return;
678 }
679
680 const double &t0 = params.t0;
681 const double playStartTime = clip.GetPlayStartTime();
682 const double &trackRectT0 = params.trackRectT0;
683 const double &averagePixelsPerSecond = params.averagePixelsPerSecond;
684 const double sampleRate = clip.GetRate();
685 const double stretchRatio = clip.GetStretchRatio();
686 double leftOffset = params.leftOffset;
687 const wxRect &mid = params.mid;
688
689 auto &settings = WaveformSettings::Get(track);
690 const float dBRange = settings.dBRange;
691
692 dc.SetPen(*wxTRANSPARENT_PEN);
693 int iColorIndex = clip.GetColourIndex();
694 artist->SetColours( iColorIndex );
695
696 // The bounds (controlled by vertical zooming; -1.0...1.0
697 // by default)
698 float zoomMin, zoomMax;
699 auto &cache = WaveformScale::Get(track);
700 cache.GetDisplayBounds(zoomMin, zoomMax);
701
702 std::vector<double> vEnv(mid.width);
703 double *const env = &vEnv[0];
704 CommonChannelView::GetEnvelopeValues(envelope, playStartTime,
705
706 // PRL: change back to make envelope evaluate only at sample times
707 // and then interpolate the display
708 0, // 1.0 / sampleRate,
709
710 env, mid.width, leftOffset, zoomInfo);
711
712 // Draw the background of the track, outlining the shape of
713 // the envelope and using a colored pen for the selected
714 // part of the waveform
715 {
716 double tt0, tt1;
718 tt0 = track.SnapToSample(selectedRegion.t0());
719 tt1 = track.SnapToSample(selectedRegion.t1());
720 }
721 else
722 tt0 = tt1 = 0.0;
723 DrawWaveformBackground(context, leftOffset, mid,
724 env,
725 zoomMin, zoomMax,
726 cache.ZeroLevelYCoordinate(mid),
727 dB, dBRange,
728 tt0, tt1,
729 !track.GetSelected(), highlightEnvelope);
730 }
731
732 WaveDisplay display(hiddenMid.width);
733
734 // For each portion separately, we will decide to draw
735 // it as min/max/rms or as individual samples.
736 std::vector<WavePortion> portions;
737 FindWavePortions(portions, rect, zoomInfo, params);
738 const unsigned nPortions = portions.size();
739
740 // Require at least 1/2 pixel per sample for drawing individual samples.
741 const double threshold1 = 0.5 * sampleRate / stretchRatio;
742 // Require at least 3 pixels per sample for drawing the draggable points.
743 const double threshold2 = 3 * sampleRate / stretchRatio;
744
745 auto &clipCache = WaveClipWaveformCache::Get(clip.GetClip());
746
747 {
748 bool showIndividualSamples = false;
749 for (unsigned ii = 0; !showIndividualSamples && ii < nPortions; ++ii) {
750 const WavePortion &portion = portions[ii];
751 showIndividualSamples =
752 !portion.inFisheye && portion.averageZoom > threshold1;
753 }
754
755 if (!showIndividualSamples) {
756 // The WaveClip class handles the details of computing the shape
757 // of the waveform. The only way GetWaveDisplay will fail is if
758 // there's a serious error, like some of the waveform data can't
759 // be loaded. So if the function returns false, we can just exit.
760
761 // Note that we compute the full width display even if there is a
762 // fisheye hiding part of it, because of the caching. If the
763 // fisheye moves over the background, there is then less to do when
764 // redrawing.
765
766 if (!clipCache.GetWaveDisplay(clip,
767 display, t0, averagePixelsPerSecond))
768 return;
769 }
770 }
771
772 // TODO Add a comment to say what this loop does.
773 // Possibly make it into a subroutine.
774 for (unsigned ii = 0; ii < nPortions; ++ii) {
775 WavePortion &portion = portions[ii];
776 const bool showIndividualSamples = portion.averageZoom > threshold1;
777 const bool showPoints = portion.averageZoom > threshold2;
778 wxRect& rectPortion = portion.rect;
779 rectPortion.Intersect(mid);
780 wxASSERT(rectPortion.width >= 0);
781
782 float *useMin = 0, *useMax = 0, *useRms = 0;
783 WaveDisplay fisheyeDisplay(rectPortion.width);
784 int skipped = 0, skippedLeft = 0, skippedRight = 0;
785 if (portion.inFisheye) {
786 if (!showIndividualSamples) {
787 fisheyeDisplay.Allocate();
788 const auto numSamples = clip.GetVisibleSampleCount();
789 // Get wave display data for different magnification
790 int jj = 0;
791 for (; jj < rectPortion.width; ++jj) {
792 const double time =
793 zoomInfo.PositionToTime(jj, -leftOffset) - playStartTime;
794 const auto sample = clip.TimeToSamples(time);
795 if (sample < 0) {
796 ++rectPortion.x;
797 ++skippedLeft;
798 continue;
799 }
800 if (sample >= numSamples)
801 break;
802 fisheyeDisplay.where[jj - skippedLeft] = sample;
803 }
804
805 skippedRight = rectPortion.width - jj;
806 skipped = skippedRight + skippedLeft;
807 rectPortion.width -= skipped;
808
809 // where needs a sentinel
810 if (jj > 0)
811 fisheyeDisplay.where[jj - skippedLeft] =
812 1 + fisheyeDisplay.where[jj - skippedLeft - 1];
813 fisheyeDisplay.width -= skipped;
814 // Get a wave display for the fisheye, uncached.
815 if (rectPortion.width > 0)
816 if (!clipCache.GetWaveDisplay(clip,
817 fisheyeDisplay, t0, -1.0)) // ignored
818 continue; // serious error. just don't draw??
819 useMin = fisheyeDisplay.min;
820 useMax = fisheyeDisplay.max;
821 useRms = fisheyeDisplay.rms;
822 }
823 }
824 else {
825 const int pos = leftOffset - params.hiddenLeftOffset;
826 useMin = display.min + pos;
827 useMax = display.max + pos;
828 useRms = display.rms + pos;
829 }
830
831 leftOffset += skippedLeft;
832
833 if (rectPortion.width > 0) {
834 if (!showIndividualSamples) {
835 std::vector<double> vEnv2(rectPortion.width);
836 double *const env2 = &vEnv2[0];
837 CommonChannelView::GetEnvelopeValues(envelope, playStartTime,
838
839 // PRL: change back to make envelope evaluate only at sample
840 // times and then interpolate the display
841 0, // 1.0 / sampleRate,
842
843 env2, rectPortion.width, leftOffset, zoomInfo);
844
845 DrawMinMaxRMS(context, rectPortion, env2,
846 zoomMin, zoomMax,
847 dB, dBRange,
848 useMin, useMax, useRms, muted);
849 }
850 else {
851 bool highlight = false;
852#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
853 auto target = dynamic_cast<SampleHandle*>(context.target.get());
854 highlight = target && target->FindChannel().get() == &track;
855#endif
857 context, leftOffset, rectPortion, zoomMin, zoomMax,
858 dB, dBRange, clip, showPoints, muted, highlight);
859 }
860 }
861
862 leftOffset += rectPortion.width + skippedRight;
863 }
864
865 const auto drawEnvelope = artist->drawEnvelope;
866 if (drawEnvelope) {
868 context, mid, env, zoomMin, zoomMax, dB, dBRange, highlightEnvelope);
870 context, mid, dB, dBRange, zoomMin, zoomMax, true, rect.x - mid.x);
871 }
872
873 // Draw arrows on the left side if the track extends to the left of the
874 // beginning of time. :)
875 if (trackRectT0 == 0.0 && playStartTime < 0.0)
876 {
878 }
879 {
880 auto clipRect = ClipParameters::GetClipRect(clip, zoomInfo, rect);
881 TrackArt::DrawClipEdges(dc, clipRect, selected);
882 }
883}
EffectDistortionSettings params
Definition: Distortion.cpp:77
static Settings & settings()
Definition: TrackInfo.cpp:69
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.
static void DrawPoints(const Envelope &env, TrackPanelDrawingContext &context, const wxRect &r, bool dB, double dBRange, float zoomMin, float zoomMax, bool mirrored, int origin=0)
Envelope * GetEnvelope() const
Piecewise linear or piecewise exponential function from double to double.
Definition: Envelope.h:72
@ WaveformView
Time required to draw a single clip.
static Stopwatch CreateStopwatch(SectionID section) noexcept
Create a Stopwatch for the section specified.
std::shared_ptr< const Channel > FindChannel() const override
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:112
static TrackArtist * Get(TrackPanelDrawingContext &)
Definition: TrackArtist.cpp:69
bool GetSelected() const
Selectedness is always the same for all channels of a group.
Definition: Track.cpp:70
double GetStretchRatio() const override
Definition: WaveTrack.cpp:128
double GetPlayStartTime() const override
Definition: WaveTrack.cpp:113
sampleCount GetVisibleSampleCount() const override
Definition: WaveTrack.cpp:103
int GetRate() const override
Definition: WaveTrack.cpp:108
int GetColourIndex() const
Definition: WaveTrack.cpp:179
const WaveClip & GetClip() const
Definition: WaveTrack.h:79
sampleCount TimeToSamples(double time) const override
Definition: WaveTrack.cpp:123
const Envelope & GetEnvelope() const
Definition: WaveTrack.cpp:97
static bool ClipDetailsVisible(const ClipTimes &clip, const ZoomInfo &zoomInfo, const wxRect &viewRect)
static WaveformScale & Get(const WaveTrack &track)
Mutative access to attachment even if the track argument is const.
static WaveformSettings & Get(const WaveTrack &track)
double SnapToSample(double t) const
static sampleCount min()
Definition: SampleCount.h:68
static sampleCount max()
Definition: SampleCount.h:69
AUDACITY_DLL_API void DrawClipFolded(wxDC &dc, const wxRect &rect)
Definition: TrackArt.cpp:346
AUDACITY_DLL_API void DrawClipEdges(wxDC &dc, const wxRect &clipRect, bool selected=false)
Definition: TrackArt.cpp:309
AUDACITY_DLL_API void DrawNegativeOffsetTrackArrows(TrackPanelDrawingContext &context, const wxRect &rect)
Definition: TrackArt.cpp:143
void DrawIndividualSamples(TrackPanelDrawingContext &context, int leftOffset, const wxRect &rect, float zoomMin, float zoomMax, bool dB, float dBRange, const WaveChannelInterval &clip, bool showPoints, bool muted, bool highlight)
void DrawEnvelope(TrackPanelDrawingContext &context, const wxRect &rect, const double env[], float zoomMin, float zoomMax, bool dB, float dBRange, bool highlight)
void FindWavePortions(std::vector< WavePortion > &portions, const wxRect &rect, const ZoomInfo &zoomInfo, const ClipParameters &params)
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, bool muted)
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)
static wxRect GetClipRect(const ClipTimes &clip, const ZoomInfo &zoomInfo, const wxRect &viewRect, bool *outShowSamples=nullptr)
static WaveClipWaveformCache & Get(const WaveClip &clip)

References WaveDisplay::Allocate(), anonymous_namespace{WaveformView.cpp}::WavePortion::averageZoom, WaveChannelView::ClipDetailsVisible(), FrameStatistics::CreateStopwatch(), TrackPanelDrawingContext::dc, TrackArt::DrawClipEdges(), TrackArt::DrawClipFolded(), DrawEnvelope(), DrawIndividualSamples(), DrawMinMaxRMS(), TrackArt::DrawNegativeOffsetTrackArrows(), EnvelopeEditor::DrawPoints(), DrawWaveformBackground(), SampleHandle::FindChannel(), FindWavePortions(), WaveClipWaveformCache::Get(), WaveformSettings::Get(), WaveformScale::Get(), TrackArtist::Get(), WaveChannelInterval::GetClip(), ClipParameters::GetClipRect(), WaveChannelInterval::GetColourIndex(), WaveChannelInterval::GetEnvelope(), EnvelopeHandle::GetEnvelope(), CommonChannelView::GetEnvelopeValues(), WaveChannelInterval::GetPlayStartTime(), WaveChannelInterval::GetRate(), Track::GetSelected(), WaveChannelInterval::GetStretchRatio(), WaveChannelInterval::GetVisibleSampleCount(), anonymous_namespace{WaveformView.cpp}::WavePortion::inFisheye, SyncLock::IsSelectedOrSyncLockSelected(), WaveDisplay::max, WaveDisplay::min, params, anonymous_namespace{WaveformView.cpp}::WavePortion::rect, WaveDisplay::rms, anonymous_namespace{ClipSegmentTest.cpp}::sampleRate, settings(), WideSampleSequence::SnapToSample(), TrackPanelDrawingContext::target, WaveChannelInterval::TimeToSamples(), FrameStatistics::WaveformView, WaveDisplay::where, and WaveDisplay::width.

Referenced by WaveformView::DoDraw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawEnvelope()

void anonymous_namespace{WaveformView.cpp}::DrawEnvelope ( TrackPanelDrawingContext context,
const wxRect &  rect,
const double  env[],
float  zoomMin,
float  zoomMax,
bool  dB,
float  dBRange,
bool  highlight 
)

Definition at line 605 of file WaveformView.cpp.

609{
610 auto &dc = context.dc;
611
612 int h = rect.height;
613
614 auto &pen = highlight ? AColor::uglyPen : AColor::envelopePen;
615 dc.SetPen( pen );
616
617 for (int x0 = 0; x0 < rect.width; ++x0) {
618 int cenvTop = GetWaveYPos(env[x0], zoomMin, zoomMax,
619 h, dB, true, dBRange, true);
620
621 int cenvBot = GetWaveYPos(-env[x0], zoomMin, zoomMax,
622 h, dB, true, dBRange, true);
623
624 int envTop = GetWaveYPos(env[x0], zoomMin, zoomMax,
625 h, dB, true, dBRange, false);
626
627 int envBot = GetWaveYPos(-env[x0], zoomMin, zoomMax,
628 h, dB, true, dBRange, false);
629
630 // Make the collision at zero actually look solid
631 if (cenvBot - cenvTop < 9) {
632 int value = (int)((zoomMax / (zoomMax - zoomMin)) * h);
633 cenvTop = value - 4;
634 cenvBot = value + 4;
635 }
636
637 DrawEnvLine( context, rect, x0, envTop, cenvTop, true );
638 DrawEnvLine( context, rect, x0, envBot, cenvBot, false );
639 }
640}
int GetWaveYPos(float value, float min, float max, int height, bool dB, bool outer, float dBr, bool clip)
Definition: TrackArt.cpp:66
static wxPen uglyPen
Definition: AColor.h:141
static wxPen envelopePen
Definition: AColor.h:115
void DrawEnvLine(TrackPanelDrawingContext &context, const wxRect &rect, int x0, int y0, int cy, bool top)

References TrackPanelDrawingContext::dc, DrawEnvLine(), AColor::envelopePen, GetWaveYPos(), and AColor::uglyPen.

Referenced by DrawClipWaveform().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawEnvLine()

void anonymous_namespace{WaveformView.cpp}::DrawEnvLine ( TrackPanelDrawingContext context,
const wxRect &  rect,
int  x0,
int  y0,
int  cy,
bool  top 
)

Definition at line 576 of file WaveformView.cpp.

579{
580 auto &dc = context.dc;
581
582 int xx = rect.x + x0;
583 int yy = rect.y + cy;
584
585 if (y0 < 0) {
586 if (x0 % 4 != 3) {
587 AColor::Line(dc, xx, yy, xx, yy + 3);
588 }
589 }
590 else if (y0 > rect.height) {
591 if (x0 % 4 != 3) {
592 AColor::Line(dc, xx, yy - 3, xx, yy);
593 }
594 }
595 else {
596 if (top) {
597 AColor::Line(dc, xx, yy, xx, yy + 3);
598 }
599 else {
600 AColor::Line(dc, xx, yy - 3, xx, yy);
601 }
602 }
603}
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:187

References TrackPanelDrawingContext::dc, and AColor::Line().

Referenced by DrawEnvelope().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawIndividualSamples()

void anonymous_namespace{WaveformView.cpp}::DrawIndividualSamples ( TrackPanelDrawingContext context,
int  leftOffset,
const wxRect &  rect,
float  zoomMin,
float  zoomMax,
bool  dB,
float  dBRange,
const WaveChannelInterval clip,
bool  showPoints,
bool  muted,
bool  highlight 
)

Definition at line 448 of file WaveformView.cpp.

455{
456 const Envelope &envelope = clip.GetEnvelope();
457 auto &dc = context.dc;
458 const auto artist = TrackArtist::Get(context);
459 const auto &zoomInfo = *artist->pZoomInfo;
460
461 const double toffset = clip.GetPlayStartTime();
462 const double rate = clip.GetRate() / clip.GetStretchRatio();
463 const double t0 = std::max(0.0, zoomInfo.PositionToTime(0, -leftOffset) - toffset);
464 const auto s0 = sampleCount(floor(t0 * rate));
465 const auto snSamples = clip.GetVisibleSampleCount();
466 if (s0 > snSamples)
467 return;
468
469 const double t1 = zoomInfo.PositionToTime(rect.width - 1, -leftOffset) - toffset;
470 const auto s1 = sampleCount(ceil(t1 * rate));
471
472 // Assume size_t will not overflow, else we wouldn't be here drawing the
473 // few individual samples
474 auto slen = std::min(snSamples - s0, s1 - s0 + 1).as_size_t();
475
476 if (slen <= 0)
477 return;
478
479 Floats buffer{ size_t(slen) };
480 clip.GetSamples((samplePtr)buffer.get(), floatSample, s0, slen,
481 // Suppress exceptions in this drawing operation:
482 false);
483
484 ArrayOf<int> xpos{ size_t(slen) };
485 ArrayOf<int> ypos{ size_t(slen) };
486 ArrayOf<int> clipped;
487 int clipcnt = 0;
488
489 const auto bShowClipping = artist->mShowClipping;
490 if (bShowClipping)
491 clipped.reinit( size_t(slen) );
492
493 const auto &muteSamplePen = artist->muteSamplePen;
494 const auto &samplePen = artist->samplePen;
495 auto &pen = highlight ? AColor::uglyPen : muted ? muteSamplePen : samplePen;
496 dc.SetPen( pen );
497
498 for (decltype(slen) s = 0; s < slen; s++) {
499 const double time = toffset + (s + s0).as_double() / rate;
500 const int xx = // An offset into the rectangle rect
501 std::max(-10000, std::min(10000,
502 (int)(zoomInfo.TimeToPosition(time, -leftOffset))));
503 xpos[s] = xx;
504
505 // Calculate sample as it would be rendered, so quantize time
506 double value = envelope.GetValue(time, 1.0 / clip.GetRate());
507 const double tt = buffer[s] * value;
508
509 if (clipped && bShowClipping && ((tt <= -MAX_AUDIO) || (tt >= MAX_AUDIO)))
510 clipped[clipcnt++] = xx;
511 ypos[s] =
512 std::max(-1,
513 std::min(rect.height,
514 GetWaveYPos(tt, zoomMin, zoomMax,
515 rect.height, dB, true, dBRange, false)));
516 }
517
518
519 if (showPoints) {
520 // Draw points where spacing is enough
521 const auto bigPoints = artist->bigPoints;
522 const int tickSize = bigPoints ? 4 : 3;// Bigger ellipses when draggable.
523 wxRect pr;
524 pr.width = tickSize;
525 pr.height = tickSize;
526 //different colour when draggable.
527 const auto &dragsampleBrush = artist->dragsampleBrush;
528 const auto &sampleBrush = artist->sampleBrush;
529 auto &brush = highlight
531 : bigPoints ? dragsampleBrush : sampleBrush;
532 dc.SetBrush( brush );
533 for (decltype(slen) s = 0; s < slen; s++) {
534 if (ypos[s] >= 0 && ypos[s] < rect.height) {
535 pr.x = rect.x + xpos[s] - tickSize/2;
536 pr.y = rect.y + ypos[s] - tickSize/2;
537 dc.DrawEllipse(pr);
538 }
539 }
540 }
541
542 const auto sampleDisplay = artist->mSampleDisplay;
543 if (showPoints &&
544 (sampleDisplay == (int) WaveChannelViewConstants::StemPlot)
545 ){
546 // Draw vertical lines
547 int yZero = GetWaveYPos(0.0, zoomMin, zoomMax, rect.height, dB, true, dBRange, false);
548 yZero = rect.y + std::max(-1, std::min(rect.height, yZero));
549 for (decltype(slen) s = 0; s < slen; s++) {
550 AColor::Line(dc,
551 rect.x + xpos[s], rect.y + ypos[s],
552 rect.x + xpos[s], yZero);
553 }
554 }
555 else {
556 // Connect samples with straight lines
557 for (decltype(slen) s = 0; s < slen - 1; s++) {
558 AColor::Line(dc,
559 rect.x + xpos[s], rect.y + ypos[s],
560 rect.x + xpos[s + 1], rect.y + ypos[s + 1]);
561 }
562 }
563
564 // Draw clipping
565 if (clipcnt) {
566 const auto &muteClippedPen = artist->muteClippedPen;
567 const auto &clippedPen = artist->clippedPen;
568 dc.SetPen(muted ? muteClippedPen : clippedPen);
569 while (--clipcnt >= 0) {
570 auto s = clipped[clipcnt];
571 AColor::Line(dc, rect.x + s, rect.y, rect.x + s, rect.y + rect.height);
572 }
573 }
574}
int min(int a, int b)
#define MAX_AUDIO
Definition: MemoryX.h:338
constexpr sampleFormat floatSample
Definition: SampleFormat.h:45
char * samplePtr
Definition: SampleFormat.h:57
static wxBrush uglyBrush
Definition: AColor.h:142
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:56
double GetValue(double t, double sampleDur=0) const
Get envelope value at time t.
Definition: Envelope.cpp:837
bool GetSamples(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool mayThrow=true) const
Definition: WaveTrack.cpp:143
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19

References TrackPanelDrawingContext::dc, floatSample, TrackArtist::Get(), WaveChannelInterval::GetEnvelope(), WaveChannelInterval::GetPlayStartTime(), WaveChannelInterval::GetRate(), WaveChannelInterval::GetSamples(), WaveChannelInterval::GetStretchRatio(), Envelope::GetValue(), WaveChannelInterval::GetVisibleSampleCount(), GetWaveYPos(), AColor::Line(), MAX_AUDIO, min(), ArrayOf< X >::reinit(), WaveChannelViewConstants::StemPlot, AColor::uglyBrush, and AColor::uglyPen.

Referenced by DrawClipWaveform().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawMinMaxRMS()

void anonymous_namespace{WaveformView.cpp}::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,
bool  muted 
)

Definition at line 333 of file WaveformView.cpp.

339{
340 auto &dc = context.dc;
341
342 // Display a line representing the
343 // min and max of the samples in this region
344 int lasth1 = std::numeric_limits<int>::max();
345 int lasth2 = std::numeric_limits<int>::min();
346 int h1;
347 int h2;
348 ArrayOf<int> r1{ size_t(rect.width) };
349 ArrayOf<int> r2{ size_t(rect.width) };
350 ArrayOf<int> clipped;
351 int clipcnt = 0;
352
353 const auto artist = TrackArtist::Get( context );
354 const auto bShowClipping = artist->mShowClipping;
355 if (bShowClipping) {
356 clipped.reinit( size_t(rect.width) );
357 }
358
359 long pixAnimOffset = (long)fabs((double)(wxDateTime::Now().GetTicks() * -10)) +
360 wxDateTime::Now().GetMillisecond() / 100; //10 pixels a second
361
362 const auto ms = wxDateTime::Now().GetMillisecond();
363 const auto ticks = (long)fabs((double)(wxDateTime::Now().GetTicks() * -10));
364
365 const auto &muteSamplePen = artist->muteSamplePen;
366 const auto &samplePen = artist->samplePen;
367
368 dc.SetPen(muted ? muteSamplePen : samplePen);
369 for (int x0 = 0; x0 < rect.width; ++x0) {
370 int xx = rect.x + x0;
371 double v;
372 v = min[x0] * env[x0];
373 if (clipped && bShowClipping && (v <= -MAX_AUDIO))
374 {
375 if (clipcnt == 0 || clipped[clipcnt - 1] != xx) {
376 clipped[clipcnt++] = xx;
377 }
378 }
379 h1 = GetWaveYPos(v, zoomMin, zoomMax,
380 rect.height, dB, true, dBRange, true);
381
382 v = max[x0] * env[x0];
383 if (clipped && bShowClipping && (v >= MAX_AUDIO))
384 {
385 if (clipcnt == 0 || clipped[clipcnt - 1] != xx) {
386 clipped[clipcnt++] = xx;
387 }
388 }
389 h2 = GetWaveYPos(v, zoomMin, zoomMax,
390 rect.height, dB, true, dBRange, true);
391
392 // JKC: This adjustment to h1 and h2 ensures that the drawn
393 // waveform is continuous.
394 if (x0 > 0) {
395 if (h1 < lasth2) {
396 h1 = lasth2 - 1;
397 }
398 if (h2 > lasth1) {
399 h2 = lasth1 + 1;
400 }
401 }
402 lasth1 = h1;
403 lasth2 = h2;
404
405 r1[x0] = GetWaveYPos(-rms[x0] * env[x0], zoomMin, zoomMax,
406 rect.height, dB, true, dBRange, true);
407 r2[x0] = GetWaveYPos(rms[x0] * env[x0], zoomMin, zoomMax,
408 rect.height, dB, true, dBRange, true);
409 // Make sure the rms isn't larger than the waveform min/max
410 if (r1[x0] > h1 - 1) {
411 r1[x0] = h1 - 1;
412 }
413 if (r2[x0] < h2 + 1) {
414 r2[x0] = h2 + 1;
415 }
416 if (r2[x0] > r1[x0]) {
417 r2[x0] = r1[x0];
418 }
419
420 AColor::Line(dc, xx, rect.y + h2, xx, rect.y + h1);
421 }
422
423 // Stroke rms over the min-max
424 const auto &muteRmsPen = artist->muteRmsPen;
425 const auto &rmsPen = artist->rmsPen;
426
427 dc.SetPen(muted ? muteRmsPen : rmsPen);
428 for (int x0 = 0; x0 < rect.width; ++x0) {
429 int xx = rect.x + x0;
430 if (r1[x0] != r2[x0]) {
431 AColor::Line(dc, xx, rect.y + r2[x0], xx, rect.y + r1[x0]);
432 }
433 }
434
435 // Draw the clipping lines
436 if (clipcnt) {
437 const auto &muteClippedPen = artist->muteClippedPen;
438 const auto &clippedPen = artist->clippedPen;
439
440 dc.SetPen(muted ? muteClippedPen : clippedPen);
441 while (--clipcnt >= 0) {
442 int xx = clipped[clipcnt];
443 AColor::Line(dc, xx, rect.y, xx, rect.y + rect.height);
444 }
445 }
446}

References TrackPanelDrawingContext::dc, TrackArtist::Get(), GetWaveYPos(), AColor::Line(), MAX_AUDIO, min(), and ArrayOf< X >::reinit().

Referenced by DrawClipWaveform().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawTimeSlider()

void anonymous_namespace{WaveformView.cpp}::DrawTimeSlider ( TrackPanelDrawingContext context,
const wxRect &  rect,
bool  rightwards,
bool  highlight 
)

Definition at line 885 of file WaveformView.cpp.

888{
889 auto &dc = context.dc;
890
891 const int border = 3; // 3 pixels all round.
892 const int width = 6; // width of the drag box.
893 const int taper = 6; // how much the box tapers by.
894 const int barSpacing = 4; // how far apart the bars are.
895 const int barWidth = 3;
896 const int xFlat = 3;
897
898 //Enough space to draw in?
899 if (rect.height <= ((taper+border + barSpacing) * 2)) {
900 return;
901 }
902 if (rect.width <= (width * 2 + border * 3)) {
903 return;
904 }
905
906 // The draggable box is tapered towards the direction you drag it.
907 int leftTaper = rightwards ? 0 : 6;
908 int rightTaper = rightwards ? 6 : 0;
909
910 int xLeft = rightwards ? (rect.x + border - 2)
911 : (rect.x + rect.width + 1 - (border + width));
912 int yTop = rect.y + border;
913 int yBot = rect.y + rect.height - border - 1;
914
915 AColor::Light(&dc, false, highlight);
916 AColor::Line(dc, xLeft, yBot - leftTaper, xLeft, yTop + leftTaper);
917 AColor::Line(dc, xLeft, yTop + leftTaper, xLeft + xFlat, yTop);
918 AColor::Line(dc, xLeft + xFlat, yTop, xLeft + width, yTop + rightTaper);
919
920 AColor::Dark(&dc, false, highlight);
921 AColor::Line(dc, xLeft + width, yTop + rightTaper, xLeft + width, yBot - rightTaper);
922 AColor::Line(dc, xLeft + width, yBot - rightTaper, xLeft + width-xFlat, yBot);
923 AColor::Line(dc, xLeft + width - xFlat, yBot, xLeft, yBot - leftTaper);
924
925 int firstBar = yTop + taper + taper / 2;
926 int nBars = (yBot - yTop - taper * 3) / barSpacing + 1;
927 xLeft += (width - barWidth + 1) / 2;
928 int yy;
929 int i;
930
931 AColor::Light(&dc, false, highlight);
932 for (i = 0;i < nBars; i++) {
933 yy = firstBar + barSpacing * i;
934 AColor::Line(dc, xLeft, yy, xLeft + barWidth, yy);
935 }
936 AColor::Dark(&dc, false, highlight);
937 for(i = 0;i < nBars; i++){
938 yy = firstBar + barSpacing * i + 1;
939 AColor::Line(dc, xLeft, yy, xLeft + barWidth, yy);
940 }
941}
static void Light(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:413
static void Dark(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:443

References AColor::Dark(), TrackPanelDrawingContext::dc, AColor::Light(), and AColor::Line().

Referenced by WaveformView::DoDraw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawWaveformBackground()

void anonymous_namespace{WaveformView.cpp}::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 at line 153 of file WaveformView.cpp.

162{
163 auto &dc = context.dc;
164 const auto artist = TrackArtist::Get( context );
165 const auto &zoomInfo = *artist->pZoomInfo;
166
167 // Visually (one vertical slice of the waveform background, on its side;
168 // the "*" is the actual waveform background we're drawing
169 //
170 //1.0 0.0 -1.0
171 // |--------------------------------|--------------------------------|
172 // *************** ***************
173 // | | | |
174 // maxtop maxbot mintop minbot
175
176 int h = rect.height;
177 int halfHeight = wxMax(h / 2, 1);
178 int maxtop, lmaxtop = 0;
179 int mintop, lmintop = 0;
180 int maxbot, lmaxbot = 0;
181 int minbot, lminbot = 0;
182 bool sel, lsel = false;
183 int xx, lx = 0;
184 int l, w;
185
186 const auto &blankBrush = artist->blankBrush;
187 const auto &selectedBrush = artist->selectedBrush;
188 const auto &unselectedBrush = artist->unselectedBrush;
189
190 dc.SetPen(*wxTRANSPARENT_PEN);
191 dc.SetBrush(blankBrush);
192 dc.DrawRectangle(rect);
193
194 // Bug 2389 - always draw at least one pixel of selection.
195 int selectedX = zoomInfo.TimeToPosition(t0, -leftOffset);
196
197 double time = zoomInfo.PositionToTime(0, -leftOffset), nextTime;
198 for (xx = 0; xx < rect.width; ++xx, time = nextTime) {
199 nextTime = zoomInfo.PositionToTime(xx + 1, -leftOffset);
200 // First we compute the truncated shape of the waveform background.
201 // If drawEnvelope is true, then we compute the lower border of the
202 // envelope.
203
204 maxtop = GetWaveYPos(env[xx], zoomMin, zoomMax,
205 h, dB, true, dBRange, true);
206 maxbot = GetWaveYPos(env[xx], zoomMin, zoomMax,
207 h, dB, false, dBRange, true);
208
209 mintop = GetWaveYPos(-env[xx], zoomMin, zoomMax,
210 h, dB, false, dBRange, true);
211 minbot = GetWaveYPos(-env[xx], zoomMin, zoomMax,
212 h, dB, true, dBRange, true);
213
214 // Make sure it's odd so that a that max and min mirror each other
215 mintop +=1;
216 minbot +=1;
217
218 const auto drawEnvelope = artist->drawEnvelope;
219 if (!drawEnvelope || maxbot > mintop) {
220 maxbot = halfHeight;
221 mintop = halfHeight;
222 }
223
224 sel = (t0 <= time && nextTime < t1);
225 sel = sel || (xx == selectedX);
226 // We don't draw selection color for sync-lock selected tracks.
227 sel = sel && !bIsSyncLockSelected;
228
229 if (lmaxtop == maxtop &&
230 lmintop == mintop &&
231 lmaxbot == maxbot &&
232 lminbot == minbot &&
233 lsel == sel) {
234 continue;
235 }
236
237 dc.SetBrush(lsel ? selectedBrush : unselectedBrush);
238
239 l = rect.x + lx;
240 w = xx - lx;
241 if (lmaxbot < lmintop - 1) {
242 dc.DrawRectangle(l, rect.y + lmaxtop, w, lmaxbot - lmaxtop);
243 dc.DrawRectangle(l, rect.y + lmintop, w, lminbot - lmintop);
244 }
245 else {
246 dc.DrawRectangle(l, rect.y + lmaxtop, w, lminbot - lmaxtop);
247 }
248
249 if (highlightEnvelope && lmaxbot < lmintop - 1) {
250 dc.SetBrush( AColor::uglyBrush );
251 dc.DrawRectangle(l, rect.y + lmaxbot, w, lmintop - lmaxbot);
252 }
253
254 lmaxtop = maxtop;
255 lmintop = mintop;
256 lmaxbot = maxbot;
257 lminbot = minbot;
258 lsel = sel;
259 lx = xx;
260 }
261
262 dc.SetBrush(lsel ? selectedBrush : unselectedBrush);
263 l = rect.x + lx;
264 w = xx - lx;
265 if (lmaxbot < lmintop - 1) {
266 dc.DrawRectangle(l, rect.y + lmaxtop, w, lmaxbot - lmaxtop);
267 dc.DrawRectangle(l, rect.y + lmintop, w, lminbot - lmintop);
268 }
269 else {
270 dc.DrawRectangle(l, rect.y + lmaxtop, w, lminbot - lmaxtop);
271 }
272 if (highlightEnvelope && lmaxbot < lmintop - 1) {
273 dc.SetBrush( AColor::uglyBrush );
274 dc.DrawRectangle(l, rect.y + lmaxbot, w, lmintop - lmaxbot);
275 }
276
277 // If sync-lock selected, draw in linked graphics.
278 if (bIsSyncLockSelected && t0 < t1) {
279 const int begin = std::max(0, std::min(rect.width, (int)(zoomInfo.TimeToPosition(t0, -leftOffset))));
280 const int end = std::max(0, std::min(rect.width, (int)(zoomInfo.TimeToPosition(t1, -leftOffset))));
282 { rect.x + begin, rect.y, end - 1 - begin, rect.height } );
283 }
284
285 //OK, the display bounds are between min and max, which
286 //is spread across rect.height. Draw the line at the proper place.
287 if (zeroLevelYCoordinate >= rect.GetTop() &&
288 zeroLevelYCoordinate <= rect.GetBottom()) {
289 dc.SetPen(*wxBLACK_PEN);
290 AColor::Line(dc, rect.x, zeroLevelYCoordinate,
291 rect.x + rect.width - 1, zeroLevelYCoordinate);
292 }
293}
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
AUDACITY_DLL_API void DrawSyncLockTiles(TrackPanelDrawingContext &context, const wxRect &rect)
Definition: TrackArt.cpp:365

References PackedArray::begin(), TrackPanelDrawingContext::dc, TrackArt::DrawSyncLockTiles(), PackedArray::end(), TrackArtist::Get(), GetWaveYPos(), AColor::Line(), min(), and AColor::uglyBrush.

Referenced by DrawClipWaveform().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ FindWavePortions()

void anonymous_namespace{WaveformView.cpp}::FindWavePortions ( std::vector< WavePortion > &  portions,
const wxRect &  rect,
const ZoomInfo zoomInfo,
const ClipParameters params 
)

Definition at line 304 of file WaveformView.cpp.

307{
308 // If there is no fisheye, then only one rectangle has nonzero width.
309 // If there is a fisheye, make rectangles for before and after
310 // (except when they are squeezed to zero width), and at least one for inside
311 // the fisheye.
312
313 const auto intervals = zoomInfo.FindIntervals(rect.width, rect.x);
314 ZoomInfo::Intervals::const_iterator it = intervals.begin(), end = intervals.end(), prev;
315 wxASSERT(it != end && it->position == rect.x);
316 const int rightmost = rect.x + rect.width;
317 for (int left = rect.x; left < rightmost;) {
318 while (it != end && it->position <= left)
319 prev = it++;
320 if (it == end)
321 break;
322 const int right = std::max(left, (int)(it->position));
323 const int width = right - left;
324 if (width > 0)
325 portions.push_back(
326 WavePortion(left, rect.y, width, rect.height,
327 prev->averageZoom, prev->inFisheye)
328 );
329 left = right;
330 }
331}
Intervals FindIntervals(int64 width, int64 origin=0) const
Definition: ZoomInfo.cpp:99

References PackedArray::end(), and ZoomInfo::FindIntervals().

Referenced by DrawClipWaveform().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetWaveColorStr()

const TranslatableString anonymous_namespace{WaveformView.cpp}::GetWaveColorStr ( int  colorIndex)

Definition at line 1086 of file WaveformView.cpp.

1087{
1088 return XXO("Instrument %i").Format( colorIndex+1 );
1089}
XXO("&Cut/Copy/Paste Toolbar")

References XXO().

Referenced by WaveColorMenuTable::OnWaveColorChange().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ sAttachment

PopupMenuTable::AttachedItem anonymous_namespace{WaveformView.cpp}::sAttachment
Initial value:
{
{ "SubViews/Extra" },
std::make_unique<PopupMenuSection>( "WaveColor",
PopupMenuTable::Adapt<WaveTrackPopupMenuTable>(
const auto pTrack = &table.FindWaveTrack();
const auto &view = WaveChannelView::Get(*pTrack);
const auto displays = view.GetDisplays();
bool hasWaveform = (displays.end() != std::find(
displays.begin(), displays.end(),
WaveChannelViewConstants::Waveform, {} }
) );
return hasWaveform
.Get(table.mpData))
: nullptr;
} ) )
}
WaveTrackPopupMenuTable & GetWaveTrackMenuTable()
static WaveChannelView & Get(WaveChannel &channel)
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:196
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
Definition: Registry.h:175
static WaveColorMenuTable & Instance()
WaveTrack & FindWaveTrack() const
PlayableTrackControls::InitMenuData * mpData

Definition at line 1152 of file WaveformView.cpp.