mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-24 10:36:46 -06:00
Merge pull request #780 from Silvertree2010/fix/772-heal-separation-missing-behavior
Heal separations left by a cut, not only splits
This commit is contained in:
@@ -405,7 +405,8 @@ pub fn trim_end_to(s: &mut Session, track: TrackId, at: Samples) -> usize {
|
|||||||
n
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Heal separations inside `range`: merge neighbouring audio clips that continue the same file.
|
/// Heal separations inside `range`: merge neighbouring audio clips that continue the same file,
|
||||||
|
/// either touching (a split) or with an empty gap that matches the gap in the source (a cut).
|
||||||
pub fn heal(s: &mut Session, track: TrackId, range: Range) -> usize {
|
pub fn heal(s: &mut Session, track: TrackId, range: Range) -> usize {
|
||||||
let Some(pl) = s.track_mut(track).and_then(|t| t.playlist_mut()) else { return 0 };
|
let Some(pl) = s.track_mut(track).and_then(|t| t.playlist_mut()) else { return 0 };
|
||||||
pl.sort();
|
pl.sort();
|
||||||
@@ -413,13 +414,16 @@ pub fn heal(s: &mut Session, track: TrackId, range: Range) -> usize {
|
|||||||
let mut healed = 0;
|
let mut healed = 0;
|
||||||
for c in pl.clips.drain(..) {
|
for c in pl.clips.drain(..) {
|
||||||
if let Some(prev) = out.last_mut() {
|
if let Some(prev) = out.last_mut() {
|
||||||
let contiguous = prev.end() == c.start && c.start >= range.start && c.start <= range.end;
|
let contiguous = c.start >= prev.end() && prev.end() >= range.start && c.start <= range.end;
|
||||||
|
let gap = if contiguous { c.start.saturating_sub(prev.end()) } else { 0 };
|
||||||
let same = match (&prev.content, &c.content) {
|
let same = match (&prev.content, &c.content) {
|
||||||
(ClipContent::Audio { source: a, offset: oa }, ClipContent::Audio { source: b, offset: ob }) => a == b && oa + prev.length == *ob,
|
(ClipContent::Audio { source: a, offset: oa }, ClipContent::Audio { source: b, offset: ob }) => {
|
||||||
|
a == b && oa.saturating_add(prev.length).saturating_add(gap) == *ob
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if contiguous && same && (prev.gain_db - c.gain_db).abs() < 1e-6 {
|
if contiguous && same && (prev.gain_db - c.gain_db).abs() < 1e-6 {
|
||||||
prev.length += c.length;
|
prev.length = c.end().saturating_sub(prev.start);
|
||||||
prev.fade_out = c.fade_out;
|
prev.fade_out = c.fade_out;
|
||||||
healed += 1;
|
healed += 1;
|
||||||
continue;
|
continue;
|
||||||
@@ -880,6 +884,37 @@ mod tests {
|
|||||||
assert_eq!(clips(&s, t), vec![(1000, 4000, 1000)]);
|
assert_eq!(clips(&s, t), vec![(1000, 4000, 1000)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn heal_rejoins_cut_separation() {
|
||||||
|
let (mut s, t) = session_with_clip();
|
||||||
|
clear_range(&mut s, t, Range::new(2000, 3000), false);
|
||||||
|
assert_eq!(heal(&mut s, t, Range::new(1500, 3500)), 1);
|
||||||
|
assert_eq!(clips(&s, t), vec![(1000, 4000, 1000)]);
|
||||||
|
// A selection that does not span the whole gap leaves it alone.
|
||||||
|
let (mut s, t) = session_with_clip();
|
||||||
|
clear_range(&mut s, t, Range::new(2000, 3000), false);
|
||||||
|
assert_eq!(heal(&mut s, t, Range::new(2500, 3500)), 0);
|
||||||
|
// Shuffled pieces no longer line up with their source and stay apart.
|
||||||
|
let (mut s, t) = session_with_clip();
|
||||||
|
clear_range(&mut s, t, Range::new(2000, 3000), true);
|
||||||
|
assert_eq!(heal(&mut s, t, Range::new(0, 10_000)), 0);
|
||||||
|
// Moved apart: the timeline gap no longer matches the source gap.
|
||||||
|
let (mut s, t) = session_with_clip();
|
||||||
|
clear_range(&mut s, t, Range::new(2000, 3000), false);
|
||||||
|
if let Some(pl) = s.track_mut(t).and_then(|t| t.playlist_mut()) {
|
||||||
|
pl.clips[1].start = 3500;
|
||||||
|
}
|
||||||
|
assert_eq!(heal(&mut s, t, Range::new(0, 10_000)), 0);
|
||||||
|
// Overlapping neighbours whose offsets line up are not a separation.
|
||||||
|
let (mut s, t) = session_with_clip();
|
||||||
|
assert_eq!(separate_at(&mut s, t, 3000), 1);
|
||||||
|
if let Some(pl) = s.track_mut(t).and_then(|t| t.playlist_mut()) {
|
||||||
|
pl.clips[1].start = 2500;
|
||||||
|
}
|
||||||
|
assert_eq!(heal(&mut s, t, Range::new(0, 10_000)), 0);
|
||||||
|
assert_eq!(clips(&s, t).len(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn clear_slip_and_shuffle() {
|
fn clear_slip_and_shuffle() {
|
||||||
let (mut s, t) = session_with_clip();
|
let (mut s, t) = session_with_clip();
|
||||||
|
|||||||
Reference in New Issue
Block a user