1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-24 00:18:07 +02:00

Change the drawing of wave track envelope at high zoom...

... The function defined by the envelope is evaluated exactly at the times of
samples, but not between samples -- instead there is a simple interpolation.

Therefore the curve might not go through the control points when they are not at
sample times.

The exact value of the function defined by the envelope has no influence on
rendering of the sound in between samples.  So this can make it clear that
the middle point has no influence at all in case three points are very close.

Drawing of other envelopes (Time track, Equalization curves) is not changed.
This commit is contained in:
Paul Licameli 2017-05-26 14:19:29 -04:00
parent 537ccfbc4f
commit e428425c7d
4 changed files with 49 additions and 8 deletions

View File

@ -1306,10 +1306,45 @@ void Envelope::GetValuesRelative(double *buffer, int bufferLen,
}
void Envelope::GetValues
(double *buffer, int bufferLen, int leftOffset, const ZoomInfo &zoomInfo) const
( double alignedTime, double sampleDur,
double *buffer, int bufferLen, int leftOffset,
const ZoomInfo &zoomInfo )
const
{
for (int xx = 0; xx < bufferLen; ++xx)
buffer[xx] = GetValue(zoomInfo.PositionToTime(xx, -leftOffset));
// Getting many envelope values, corresponding to pixel columns, which may
// not be uniformly spaced in time when there is a fisheye.
double prevDiscreteTime, prevSampleVal, nextSampleVal;
for ( int xx = 0; xx < bufferLen; ++xx ) {
auto time = zoomInfo.PositionToTime( xx, -leftOffset );
if ( sampleDur <= 0 )
// Sample interval not defined (as for time track)
buffer[xx] = GetValue( time );
else {
// The level of zoom-in may resolve individual samples.
// If so, then instead of evaluating the envelope directly,
// we draw a piecewise curve with knees at each sample time.
// This actually makes clearer what happens as you drag envelope
// points and make discontinuities.
auto leftDiscreteTime = alignedTime +
sampleDur * floor( ( time - alignedTime ) / sampleDur );
if ( xx == 0 || leftDiscreteTime != prevDiscreteTime ) {
prevDiscreteTime = leftDiscreteTime;
prevSampleVal =
GetValue( prevDiscreteTime, sampleDur );
nextSampleVal =
GetValue( prevDiscreteTime + sampleDur, sampleDur );
}
auto ratio = ( time - leftDiscreteTime ) / sampleDur;
if ( GetExponential() )
buffer[ xx ] = exp(
( 1.0 - ratio ) * log( prevSampleVal )
+ ratio * log( nextSampleVal ) );
else
buffer[ xx ] =
( 1.0 - ratio ) * prevSampleVal + ratio * nextSampleVal;
}
}
}
// relative time

View File

@ -142,10 +142,13 @@ public:
* more than one value in a row. */
void GetValues(double *buffer, int len, double t0, double tstep) const;
/** \brief Get many envelope points at once, but don't assume uniform time step.
/** \brief Get many envelope points for pixel columns at once,
* but don't assume uniform time per pixel.
*/
void GetValues
(double *buffer, int bufferLen, int leftOffset, const ZoomInfo &zoomInfo) const;
( double aligned_time, double sampleDur,
double *buffer, int bufferLen, int leftOffset,
const ZoomInfo &zoomInfo) const;
// Guarantee an envelope point at the end of the domain.
void Cap( double sampleDur );

View File

@ -281,7 +281,8 @@ void TimeTrack::Draw(wxDC & dc, const wxRect & r, const ZoomInfo &zoomInfo) cons
mRuler->Draw(dc, this);
Doubles envValues{ size_t(mid.width) };
GetEnvelope()->GetValues(envValues.get(), mid.width, 0, zoomInfo);
GetEnvelope()->GetValues
( 0, 0, envValues.get(), mid.width, 0, zoomInfo );
dc.SetPen(AColor::envelopePen);

View File

@ -1781,7 +1781,8 @@ void TrackArtist::DrawClipWaveform(const WaveTrack *track,
std::vector<double> vEnv(mid.width);
double *const env = &vEnv[0];
clip->GetEnvelope()->GetValues(env, mid.width, leftOffset, zoomInfo);
clip->GetEnvelope()->GetValues
( tOffset, 1.0 / rate, env, mid.width, leftOffset, zoomInfo );
// Draw the background of the track, outlining the shape of
// the envelope and using a colored pen for the selected
@ -1912,7 +1913,8 @@ void TrackArtist::DrawClipWaveform(const WaveTrack *track,
if (!showIndividualSamples) {
std::vector<double> vEnv2(rect.width);
double *const env2 = &vEnv2[0];
clip->GetEnvelope()->GetValues(env2, rect.width, leftOffset, zoomInfo);
clip->GetEnvelope()->GetValues
( tOffset, 1.0 / rate, env2, rect.width, leftOffset, zoomInfo );
DrawMinMaxRMS(dc, rect, env2,
zoomMin, zoomMax,
dB, dBRange,