Changed the criterion for deciding when two clips are immediately next to each other, and made it into a function: WaveClip::SharesBoundaryWithNextClip.
When When two clips are immediately next to each other, the GetEndTime() of the first clip and the GetStartTime() of the second clip may not be exactly equal due to rounding errors. The existing code assumed they were equal, and this lead to the wrong clip boundaries or clips being found.
There are a number of ways of fixing this which could be explored. The current solution involves changing only the code for the keyboard interaction with clips.
The fix:
1. The test used for two clips being immediately next to each other is that GetEndSample() on the first clip is equal to to GetStartSample() on the second clip.
2. When searching for the start/end times of clips, the cases where GetEndTime() and GetStartTime() are not equal are taken into account. This is done in the two functions AudacityProject::AdjustForFindingStartTimes and AudacityProject::AdjustForFindingEndTimes.
... Formerly this was done correctly only for cut and delete from WaveTrack,
paste into WaveTrack, and sync-lock adjustment of WaveTrack (either lengthening
or shortening).
Now also properly done for TimeTrack cut and paste, and also for:
Split cut
Split delete
Trim
... rather than some of them being relative to the Envelope's offset.
In case of the envelopes used in TimeTrack or Equalization, offset was
always zero, so this doesn't matter, except to make the contract of the
Envelope class more explicit and sensible in isolation.
In case of InsertSpace at least, this does fix an obscure bug, which could
only happen when you have a clip, with an envelope, that starts before zero,
and you select a region overlapping that clip and some other clip, with a void
between, and you use the Join command.
Aren't you relieved that's fixed now?
Clip Left
Clip Right
If the cursor lies within a clip, the clip and the cursor is moved 1 pixel left/right.
If the cursor position is at both a clip end and a clip start, the second of these clips is moved.
The movement currently ignores the snap to setting on the selection bar, and there is no snapping to the clip boundaries of other clips.
Following the behaviour or shifting with the mouse, the distance moved is rounded to an integral number of samples, and the minimum distance moved is one sample.
... in WaveClip and WaveTrack, to save as much recording as we can,
assuming the strong guarantees that Sequence will give.
Also comment that some other WaveTrack methods can give strong guarantee,
incidentally to making HandleClear give strong.
... The return codes were mostly ignored anyway, and exceptions will be thrown
instead.
It seems there was also confusion whether the return values of Track::Paste
and Track::SyncLockAdjust were to indicate success or indicate whether there
was any change. No matter now.
... Eliminate CreateFromCopy, add new one-step constructor instead.
It was wasteful to create a copy only to re-create the Sequence at once.
Sequence::Copy is a factory returning a unique_ptr.
Some error checks are removed, but there will be exceptions instead later.
... To short selections (under 1/100 second), at the start of the second of
two separated clips, in a project with a high sampling rate of 192000.
Symptom was that the audio moved so it was pasted to the end of the first clip.
Other uses of the constant WAVETRACK_MERGE_POINT_TOLERANCE should be
reviewed too but this is a conservative fix made close to release time.
... This is done with Shift+Ctrl+wheel and pointer in the vertical ruler, and
the pointer y coordinate near the bottom of the dB scale.
If y coordinate is far from there, then Shift+Ctrl+wheel changes dB level
without change of magnification (as before this commit).
... whenever they really describe the size of a buffer that fits in memory, or
of a block file (which is never now more than a megabyte and so could be fit in
memory all at once), or a part thereof.
... with run-time assertions.
I examined each place and reasoned that the narrowing was safe, and commented
why so.
Again, there are places where the sampleCount variable will later be changed
to have a different type, and they are not changed here.
... A non-narrowing conversion out to long long is a necessity, but the
conversions to float and double are simply conveniences.
Conversion from floating is explicit, to avoid unintended consequences with
arithmetic operators, when later sampleCount ceases to be an alias for an
integral type.
Some conversions are not made explicit, where I expect to change the type of
the variable later to have mere size_t width.