mirror of
https://github.com/cookiengineer/audacity
synced 2025-09-08 08:30:02 +02:00
Merge Draw Tool bug fixes and enhancements: ...
Enable draw tool in Waveform dB view Bug1005: draw tool performance Bug1003: Use correct envelope value in pencil tool drag Bug1002: Alt-click in pencil tool never starts a drag Bug1004: undo history message Pulled repeated code into a function; share some calcs with Envelope editor Remove unused variables; fewer casts
This commit is contained in:
commit
b288a8500a
@ -4956,16 +4956,27 @@ bool TrackPanel::IsSampleEditingPossible( wxMouseEvent & WXUNUSED(event), Track
|
||||
|
||||
//Get out of here if we shouldn't be drawing right now:
|
||||
//If we aren't displaying the waveform, Display a message dialog
|
||||
if(((WaveTrack *)t)->GetDisplay() != WaveTrack::WaveformDisplay)
|
||||
WaveTrack *const wt = static_cast<WaveTrack*>(t);
|
||||
const int display = wt->GetDisplay();
|
||||
#if 1
|
||||
if (!(WaveTrack::WaveformDisplay == display ||
|
||||
WaveTrack::WaveformDBDisplay == display))
|
||||
{
|
||||
wxMessageBox(_("To use Draw, choose 'Waveform' or 'Waveform dB' in the Track Drop-down Menu."), wxT("Draw Tool"));
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if(WaveTrack::WaveformDisplay != display)
|
||||
{
|
||||
wxMessageBox(_("To use Draw, choose 'Waveform' in the Track Drop-down Menu."), wxT("Draw Tool"));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//Get rate in order to calculate the critical zoom threshold
|
||||
//Find out the zoom level
|
||||
double rate = ((WaveTrack *)t)->GetRate();
|
||||
bool showPoints = (mViewInfo->zoom / rate > 3.0);
|
||||
const double rate = wt->GetRate();
|
||||
const bool showPoints = (mViewInfo->zoom / rate > 3.0);
|
||||
|
||||
//If we aren't zoomed in far enough, show a message dialog.
|
||||
if(!showPoints)
|
||||
@ -4985,17 +4996,44 @@ bool TrackPanel::IsSampleEditingPossible( wxMouseEvent & WXUNUSED(event), Track
|
||||
return true;
|
||||
}
|
||||
|
||||
float TrackPanel::FindSampleEditingLevel(wxMouseEvent &event, double t0)
|
||||
{
|
||||
// Calculate where the mouse is located vertically (between +/- 1)
|
||||
float zoomMin, zoomMax;
|
||||
mDrawingTrack->GetDisplayBounds(&zoomMin, &zoomMax);
|
||||
|
||||
const int y = event.m_y - mDrawingTrackTop;
|
||||
const int height = mDrawingTrack->GetHeight();
|
||||
const bool dB = (WaveTrack::WaveformDBDisplay == mDrawingTrack->GetDisplay());
|
||||
float newLevel = ::ValueOfPixel(y, height, false, dB, mdBr, zoomMin, zoomMax);
|
||||
|
||||
//Take the envelope into account
|
||||
Envelope *const env = mDrawingTrack->GetEnvelopeAtX(event.m_x);
|
||||
if (env)
|
||||
{
|
||||
double envValue = env->GetValue(t0);
|
||||
if (envValue > 0)
|
||||
newLevel /= envValue;
|
||||
else
|
||||
newLevel = 0;
|
||||
|
||||
//Make sure the new level is between +/-1
|
||||
newLevel = std::max(-1.0f, std::min(1.0f, newLevel));
|
||||
}
|
||||
|
||||
return newLevel;
|
||||
}
|
||||
|
||||
/// We're in a track view and zoomed enough to see the samples.
|
||||
/// Someone has just clicked the mouse. What do we do?
|
||||
void TrackPanel::HandleSampleEditingClick( wxMouseEvent & event )
|
||||
{
|
||||
//declare a rectangle to determine clicking position
|
||||
wxRect r;
|
||||
Track *t;
|
||||
|
||||
//Get the track the mouse is over, and save it away for future events
|
||||
mDrawingTrack = NULL;
|
||||
t = FindTrack(event.m_x, event.m_y, false, false, &r);
|
||||
Track *const t = FindTrack(event.m_x, event.m_y, false, false, &r);
|
||||
|
||||
if (!t || (t->GetKind() != Track::Wave))
|
||||
return;
|
||||
@ -5006,28 +5044,19 @@ void TrackPanel::HandleSampleEditingClick( wxMouseEvent & event )
|
||||
ReleaseMouse();
|
||||
return;
|
||||
}
|
||||
SetCapturedTrack( t, IsAdjustingSample);
|
||||
|
||||
/// \todo Should mCapturedTrack take the place of mDrawingTrack??
|
||||
mDrawingTrack = t;
|
||||
mDrawingTrack = static_cast<WaveTrack*>(t);
|
||||
mDrawingTrackTop=r.y;
|
||||
|
||||
//If we are still around, we are drawing in earnest. Set some member data structures up:
|
||||
//First, calculate the starting sample. To get this, we need the time
|
||||
double t0 = PositionToTime(event.m_x, GetLeftOffset());
|
||||
double rate = ((WaveTrack *)mDrawingTrack)->GetRate();
|
||||
|
||||
// Default to zero for ALT case, so it doesn't cause a runtime fault on MSVC in
|
||||
// the mDrawingLastDragSampleValue assignment at the bottom of this method.
|
||||
float newLevel = 0.0f; //Declare this for use later
|
||||
|
||||
//convert t0 to samples
|
||||
mDrawingStartSample = (sampleCount) (double)(t0 * rate + 0.5 );
|
||||
|
||||
//Now, figure out what the value of that sample is.
|
||||
//First, get the sequence of samples so you can mess with it
|
||||
//Sequence *seq = ((WaveTrack *)mDrawingTrack)->GetSequence();
|
||||
|
||||
mDrawingStartSample = mDrawingTrack->TimeToLongSamples(t0);
|
||||
// quantize
|
||||
t0 = mDrawingTrack->LongSamplesToTime(mDrawingStartSample);
|
||||
|
||||
//Determine how drawing should occur. If alt is down,
|
||||
//do a smoothing, instead of redrawing.
|
||||
@ -5051,7 +5080,7 @@ void TrackPanel::HandleSampleEditingClick( wxMouseEvent & event )
|
||||
float * newSampleRegion = new float[1 + 2 * SMOOTHING_BRUSH_RADIUS];
|
||||
|
||||
//Get a sample from the track to do some tricks on.
|
||||
((WaveTrack*)mDrawingTrack)->Get((samplePtr)sampleRegion, floatSample,
|
||||
mDrawingTrack->Get((samplePtr)sampleRegion, floatSample,
|
||||
(int)mDrawingStartSample - SMOOTHING_KERNEL_RADIUS - SMOOTHING_BRUSH_RADIUS,
|
||||
sampleRegionSize);
|
||||
int i, j;
|
||||
@ -5093,11 +5122,13 @@ void TrackPanel::HandleSampleEditingClick( wxMouseEvent & event )
|
||||
sampleRegion[SMOOTHING_BRUSH_RADIUS + SMOOTHING_KERNEL_RADIUS + j] * (1 - prob);
|
||||
}
|
||||
//Set the sample to the point of the mouse event
|
||||
((WaveTrack*)mDrawingTrack)->Set((samplePtr)newSampleRegion, floatSample, mDrawingStartSample - SMOOTHING_BRUSH_RADIUS, 1 + 2 * SMOOTHING_BRUSH_RADIUS);
|
||||
mDrawingTrack->Set((samplePtr)newSampleRegion, floatSample, mDrawingStartSample - SMOOTHING_BRUSH_RADIUS, 1 + 2 * SMOOTHING_BRUSH_RADIUS);
|
||||
|
||||
//Clean this up right away to avoid a memory leak
|
||||
delete[] sampleRegion;
|
||||
delete[] newSampleRegion;
|
||||
|
||||
mDrawingLastDragSampleValue = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5105,38 +5136,19 @@ void TrackPanel::HandleSampleEditingClick( wxMouseEvent & event )
|
||||
//*** PLAIN DOWN-CLICK (NORMAL DRAWING) ***
|
||||
//*************************************************
|
||||
|
||||
SetCapturedTrack(t, IsAdjustingSample);
|
||||
|
||||
//Otherwise (e.g., the alt button is not down) do normal redrawing, based on the mouse position.
|
||||
// Calculate where the mouse is located vertically (between +/- 1)
|
||||
((WaveTrack*)mDrawingTrack)->Get((samplePtr)&mDrawingStartSampleValue, floatSample,(int) mDrawingStartSample, 1);
|
||||
float zoomMin, zoomMax;
|
||||
((WaveTrack *)mDrawingTrack)->GetDisplayBounds(&zoomMin, &zoomMax);
|
||||
newLevel = zoomMax -
|
||||
((event.m_y - mDrawingTrackTop)/(float)mDrawingTrack->GetHeight()) *
|
||||
(zoomMax - zoomMin);
|
||||
|
||||
//Take the envelope into account
|
||||
Envelope *env = ((WaveTrack *)mDrawingTrack)->GetEnvelopeAtX(event.GetX());
|
||||
|
||||
if (env)
|
||||
{
|
||||
double envValue = env->GetValue(t0);
|
||||
if (envValue > 0)
|
||||
newLevel /= envValue;
|
||||
else
|
||||
newLevel = 0;
|
||||
|
||||
//Make sure the new level is between +/-1
|
||||
newLevel = newLevel > 1.0 ? 1.0: newLevel;
|
||||
newLevel = newLevel < -1.0 ? -1.0: newLevel;
|
||||
}
|
||||
const float newLevel = FindSampleEditingLevel(event, t0);
|
||||
|
||||
//Set the sample to the point of the mouse event
|
||||
((WaveTrack*)mDrawingTrack)->Set((samplePtr)&newLevel, floatSample, mDrawingStartSample, 1);
|
||||
mDrawingTrack->Set((samplePtr)&newLevel, floatSample, mDrawingStartSample, 1);
|
||||
|
||||
mDrawingLastDragSampleValue = newLevel;
|
||||
}
|
||||
|
||||
//Set the member data structures for drawing
|
||||
mDrawingLastDragSample=mDrawingStartSample;
|
||||
mDrawingLastDragSampleValue = newLevel;
|
||||
|
||||
//Redraw the region of the selected track
|
||||
RefreshTrack(mDrawingTrack);
|
||||
@ -5155,88 +5167,59 @@ void TrackPanel::HandleSampleEditingDrag( wxMouseEvent & event )
|
||||
return;
|
||||
|
||||
//Exit dragging if the alt key is down--Don't allow left-right dragging for smoothing operation
|
||||
if (event.m_altDown)
|
||||
if (mMouseCapture != IsAdjustingSample)
|
||||
return;
|
||||
|
||||
//Get the rate of the sequence, for use later
|
||||
float rate = ((WaveTrack *)mDrawingTrack)->GetRate();
|
||||
sampleCount s0; //declare this for use below. It designates the sample number which to draw.
|
||||
|
||||
// Figure out what time the click was at
|
||||
double t0 = PositionToTime(event.m_x, GetLeftOffset());
|
||||
float newLevel;
|
||||
//Find the point that we want to redraw at. If the control button is down,
|
||||
//adjust only the originally clicked-on sample
|
||||
|
||||
//*************************************************
|
||||
//*** CTRL-DOWN (Hold Initial Sample Constant ***
|
||||
//*************************************************
|
||||
|
||||
if( event.m_controlDown) {
|
||||
//*************************************************
|
||||
//*** CTRL-DOWN (Hold Initial Sample Constant ***
|
||||
//*************************************************
|
||||
|
||||
s0 = mDrawingStartSample;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
//*************************************************
|
||||
//*** Normal CLICK-drag (Normal drawing) ***
|
||||
//*************************************************
|
||||
|
||||
//Otherwise, adjust the sample you are dragging over right now.
|
||||
//convert this to samples
|
||||
s0 = (sampleCount) (double)(t0 * rate + 0.5);
|
||||
const double t = PositionToTime(event.m_x, GetLeftOffset());
|
||||
s0 = mDrawingTrack->TimeToLongSamples(t);
|
||||
}
|
||||
|
||||
//Sequence *seq = ((WaveTrack *)mDrawingTrack)->GetSequence();
|
||||
((WaveTrack*)mDrawingTrack)->Get((samplePtr)&mDrawingStartSampleValue, floatSample, (int)mDrawingStartSample, 1);
|
||||
const double t0 = mDrawingTrack->LongSamplesToTime(s0);
|
||||
|
||||
//Otherwise, do normal redrawing, based on the mouse position.
|
||||
// Calculate where the mouse is located vertically (between +/- 1)
|
||||
|
||||
const float newLevel = FindSampleEditingLevel(event, t0);
|
||||
|
||||
float zoomMin, zoomMax;
|
||||
((WaveTrack *)mDrawingTrack)->GetDisplayBounds(&zoomMin, &zoomMax);
|
||||
newLevel = zoomMax -
|
||||
((event.m_y - mDrawingTrackTop)/(float)mDrawingTrack->GetHeight()) *
|
||||
(zoomMax - zoomMin);
|
||||
|
||||
//Take the envelope into account
|
||||
Envelope *env = ((WaveTrack *)mDrawingTrack)->GetEnvelopeAtX(event.GetX());
|
||||
if (env)
|
||||
{
|
||||
double envValue = env->GetValue(t0);
|
||||
if (envValue > 0)
|
||||
newLevel /= envValue;
|
||||
else
|
||||
newLevel = 0;
|
||||
|
||||
//Make sure the new level is between +/-1
|
||||
newLevel = newLevel > 1.0 ? 1.0: newLevel;
|
||||
newLevel = newLevel < -1.0 ? -1.0: newLevel;
|
||||
//Now, redraw all samples between current and last redrawn sample, inclusive
|
||||
//Go from the smaller to larger sample.
|
||||
const int start = std::min( s0, mDrawingLastDragSample);
|
||||
const int end = std::max( s0, mDrawingLastDragSample);
|
||||
const int size = end - start + 1;
|
||||
if (size == 1) {
|
||||
mDrawingTrack->Set((samplePtr)&newLevel, floatSample, start, size);
|
||||
}
|
||||
|
||||
//Now, redraw all samples between current and last redrawn sample
|
||||
|
||||
float tmpvalue;
|
||||
//Handle cases of 0 or 1 special, to improve speed
|
||||
//JKC I don't think this makes any noticeable difference to speed
|
||||
// whatsoever! The real reason for the special case is probably to
|
||||
// avoid division by zero....
|
||||
#define LLABS(n) ((n) < 0 ? -(n) : (n))
|
||||
if(LLABS(s0 - mDrawingLastDragSample) <= 1){
|
||||
((WaveTrack*)mDrawingTrack)->Set((samplePtr)&newLevel, floatSample, s0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Go from the smaller to larger sample.
|
||||
int start = wxMin( s0, mDrawingLastDragSample) +1;
|
||||
int end = wxMax( s0, mDrawingLastDragSample);
|
||||
for(sampleCount i= start; i<= end; i++) {
|
||||
else {
|
||||
std::vector<float> values(size);
|
||||
for (sampleCount i = start; i <= end; ++i) {
|
||||
//This interpolates each sample linearly:
|
||||
tmpvalue=mDrawingLastDragSampleValue + (newLevel - mDrawingLastDragSampleValue) *
|
||||
(float)(i-mDrawingLastDragSample)/(s0-mDrawingLastDragSample );
|
||||
((WaveTrack*)mDrawingTrack)->Set((samplePtr)&tmpvalue, floatSample, i, 1);
|
||||
values[i - start] =
|
||||
mDrawingLastDragSampleValue + (newLevel - mDrawingLastDragSampleValue) *
|
||||
(float)(i - mDrawingLastDragSample) / (s0 - mDrawingLastDragSample);
|
||||
}
|
||||
mDrawingTrack->Set((samplePtr)&values[0], floatSample, start, size);
|
||||
}
|
||||
|
||||
//Update the member data structures.
|
||||
mDrawingLastDragSample=s0;
|
||||
mDrawingLastDragSampleValue = newLevel;
|
||||
@ -5253,7 +5236,7 @@ void TrackPanel::HandleSampleEditingButtonUp( wxMouseEvent & WXUNUSED(event))
|
||||
SetCapturedTrack( NULL );
|
||||
//On up-click, send the state to the undo stack
|
||||
mDrawingTrack=NULL; //Set this to NULL so it will catch improper drag events.
|
||||
MakeParentPushState(_("Moved Sample"),
|
||||
MakeParentPushState(_("Moved Samples"),
|
||||
_("Sample Edit"),
|
||||
PUSH_CONSOLIDATE|PUSH_AUTOSAVE);
|
||||
}
|
||||
@ -5266,7 +5249,6 @@ void TrackPanel::HandleSampleEditingButtonUp( wxMouseEvent & WXUNUSED(event))
|
||||
/// jump to a new track
|
||||
/// - mDrawingTrackTop: The top position of the drawing track--makes drawing easier.
|
||||
/// - mDrawingStartSample: The sample you clicked down on, so that you can hold it steady
|
||||
/// - mDrawingStartSampleValue: The original value of the initial sample
|
||||
/// - mDrawingLastDragSample: When drag-drawing, this keeps track of the last sample you dragged over,
|
||||
/// so it can smoothly redraw samples that got skipped over
|
||||
/// - mDrawingLastDragSampleValue: The value of the last
|
||||
@ -7097,7 +7079,8 @@ bool TrackPanel::HitTestSamples(Track *track, wxRect &r, wxMouseEvent & event)
|
||||
return false;
|
||||
|
||||
int displayType = wavetrack->GetDisplay();
|
||||
if ( displayType > 1)
|
||||
bool dB = (WaveTrack::WaveformDBDisplay == displayType);
|
||||
if (!(WaveTrack::WaveformDisplay == displayType) || dB)
|
||||
return false; // Not a wave, so return.
|
||||
|
||||
float oneSample;
|
||||
@ -7109,7 +7092,6 @@ bool TrackPanel::HitTestSamples(Track *track, wxRect &r, wxMouseEvent & event)
|
||||
wavetrack->Get((samplePtr)&oneSample, floatSample, s0, 1);
|
||||
|
||||
// Get y distance of envelope point from center line (in pixels).
|
||||
bool dB = (displayType == 1);
|
||||
float zoomMin, zoomMax;
|
||||
|
||||
wavetrack->GetDisplayBounds(&zoomMin, &zoomMax);
|
||||
@ -8500,7 +8482,6 @@ void TrackPanel::OnTrackMenu(Track *t)
|
||||
theMenu->Enable(OnSplitStereoMonoID, t->GetLinked());
|
||||
|
||||
// We only need to set check marks. Clearing checks causes problems on Linux (bug 851)
|
||||
int channels = t->GetChannel();
|
||||
switch (t->GetChannel()) {
|
||||
case Track::LeftChannel:
|
||||
theMenu->Check(OnChannelLeftID, true);
|
||||
|
@ -396,6 +396,7 @@ protected:
|
||||
// Handle sample editing using the 'draw' tool.
|
||||
virtual bool IsSampleEditingPossible( wxMouseEvent & event, Track * t );
|
||||
virtual void HandleSampleEditing(wxMouseEvent & event);
|
||||
float FindSampleEditingLevel(wxMouseEvent &event, double t0);
|
||||
virtual void HandleSampleEditingClick( wxMouseEvent & event );
|
||||
virtual void HandleSampleEditingDrag( wxMouseEvent & event );
|
||||
virtual void HandleSampleEditingButtonUp( wxMouseEvent & event );
|
||||
@ -676,10 +677,9 @@ protected:
|
||||
|
||||
NumericConverter mConverter;
|
||||
|
||||
Track * mDrawingTrack; // Keeps track of which track you are drawing on between events cf. HandleDraw()
|
||||
WaveTrack * mDrawingTrack; // Keeps track of which track you are drawing on between events cf. HandleDraw()
|
||||
int mDrawingTrackTop; // Keeps track of the top position of the drawing track.
|
||||
sampleCount mDrawingStartSample; // sample of last click-down
|
||||
float mDrawingStartSampleValue; // value of last click-down
|
||||
sampleCount mDrawingLastDragSample; // sample of last drag-over
|
||||
float mDrawingLastDragSampleValue; // value of last drag-over
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user