fix(waveform): 4x-oversampled min/max envelope, columnMinMax homed in peaks, panel routed through shared drawWaveform — one gap-free algorithm on all surfaces
This commit is contained in:
+15
@@ -66,6 +66,21 @@ Envelope computeEnvelope(const std::vector<AudioSample>& interleaved,
|
||||
std::size_t frameCount,
|
||||
std::size_t binCount);
|
||||
|
||||
// The merged min/max for display column `col` (0-based, of `columnCount` total columns)
|
||||
// of a pre-computed per-bin ChannelEnvelope: the true extremes of every bin that projects
|
||||
// to that column. This is the display-side collapse of an envelope computed at HIGHER
|
||||
// resolution than the drawn width (oversampled bins -> per-pixel-column min/max), so a
|
||||
// steep transient whose adjacent bins hold disjoint spans (e.g. {0.9,1.0} then
|
||||
// {-1.0,-0.9}) renders as one gap-free vertical span instead of two separated dots.
|
||||
//
|
||||
// Bin->column mapping mirrors computeEnvelope's half-open partition:
|
||||
// column col owns bins [col*nbins/columnCount, (col+1)*nbins/columnCount).
|
||||
// When that range is empty (more columns than bins), the enclosing bin
|
||||
// (col*nbins/columnCount) fills the column — so no column is left empty and no bin is
|
||||
// ever dropped. columnCount <= 0 or bins.empty() returns {0, 0}; `col` is clamped to
|
||||
// [0, columnCount-1]. Pure.
|
||||
MinMax columnMinMax(const ChannelEnvelope& bins, int columnCount, int col);
|
||||
|
||||
// Sentinel returned by lastFrameAboveThreshold when NO frame in the scanned range
|
||||
// peaks above the threshold (pure silence at that level). SIZE_MAX is unambiguous:
|
||||
// no valid frame index can equal it (a real index is < frameCount <= SIZE_MAX for
|
||||
|
||||
Reference in New Issue
Block a user