Skip to content

Commit 622ede5

Browse files
authored
Merge pull request #51 from diffusionstudio/matthias/fix/silence-remove-perf-improvement
Matthias/fix/silence remove perf improvement
2 parents 2259cc5 + 267727e commit 622ede5

File tree

2 files changed

+59
-16
lines changed

2 files changed

+59
-16
lines changed

src/tracks/media/media.spec.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ describe('The Media Track Object', () => {
6060
await track.removeSilences();
6161
expect(track.clips.length).toBe(1);
6262
expect(track.clips.at(0)).toBe(clip);
63+
expect(track.clips.at(0)?.state).toBe('ATTACHED');
6364
});
6465

6566
it('removes silences', async () => {
@@ -81,10 +82,41 @@ describe('The Media Track Object', () => {
8182
expect(clip.source).toBeDefined();
8283
await track.removeSilences();
8384
expect(track.clips.length).toBe(2);
84-
expect(track.clips.at(0)?.range[0].millis).toBe(10051);
85+
expect(track.clips.at(0)?.range[0].millis).toBe(10050);
8586
expect(track.clips.at(0)?.range[1].millis).toBe(11000);
86-
expect(track.clips.at(1)?.range[0].millis).toBe(15001);
87+
expect(track.clips.at(1)?.range[0].millis).toBe(15000);
8788
expect(track.clips.at(1)?.range[1].millis).toBe(19000);
89+
expect(track.clips.at(0)?.state).toBe('ATTACHED');
90+
expect(track.clips.at(1)?.state).toBe('ATTACHED');
91+
});
92+
93+
it('removes silences twice', async () => {
94+
const clip = new MockMediaClip([new Timestamp(10000), new Timestamp(20000)], [
95+
{
96+
start: new Timestamp(0),
97+
stop: new Timestamp(500),
98+
},
99+
{
100+
start: new Timestamp(11000),
101+
stop: new Timestamp(15000),
102+
},
103+
{
104+
start: new Timestamp(19000),
105+
stop: new Timestamp(30500),
106+
},
107+
], new Audio());
108+
await track.add(clip);
109+
expect(clip.source).toBeDefined();
110+
await track.removeSilences();
111+
await track.removeSilences();
112+
expect(track.clips.length).toBe(2);
113+
expect(track.clips.at(0)?.id).not.toBe(clip.id);
114+
expect(track.clips.at(0)?.range[0].millis).toBe(10000);
115+
expect(track.clips.at(0)?.range[1].millis).toBe(11000);
116+
expect(track.clips.at(1)?.range[0].millis).toBe(15000);
117+
expect(track.clips.at(1)?.range[1].millis).toBe(19000);
118+
expect(track.clips.at(0)?.state).toBe('ATTACHED');
119+
expect(track.clips.at(1)?.state).toBe('ATTACHED');
88120
});
89121

90122
it('should propagate a seek call', async () => {

src/tracks/media/media.ts

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import { Track } from '../track';
99

10-
import type { MediaClip } from '../../clips';
10+
import type { MediaClip, MediaClipProps } from '../../clips';
1111
import { Timestamp } from '../../models';
1212
import { SilenceOptions } from '../../sources';
1313

@@ -28,6 +28,9 @@ export class MediaTrack<Clip extends MediaClip> extends Track<MediaClip> {
2828
*/
2929
public async removeSilences(options: SilenceOptions = {}) {
3030
const numClips = this.clips.length;
31+
32+
let newClips: MediaClip<MediaClipProps>[] = [];
33+
let clipsToDetach: MediaClip<MediaClipProps>[] = [];
3134
// Process each clip
3235
for (let i = 0; i < numClips; i++) {
3336
const clip = this.clips[i];
@@ -51,29 +54,37 @@ export class MediaTrack<Clip extends MediaClip> extends Track<MediaClip> {
5154
continue;
5255
}
5356

57+
clipsToDetach.push(clip);
5458
let start = clip.range[0];
55-
let currentClip = clip;
59+
let currentClip = clip.copy();
5660

5761
for (const silence of applicableSilences) {
58-
if (silence.start.millis <= start.millis) {
59-
const newClip = await currentClip.split(silence.stop.add(currentClip.offset));
60-
currentClip.detach();
61-
start = silence.stop;
62-
currentClip = newClip;
62+
if (silence.start.millis <= start.millis) {
63+
start = silence.stop;
64+
currentClip.range[0] = silence.stop;
6365
continue;
6466
}
6567

6668
if (silence.stop.millis >= currentClip.range[1].millis) {
67-
currentClip = await currentClip.split(silence.start.add(currentClip.offset));
68-
currentClip.detach();
69+
currentClip.range[1] = silence.start;
70+
start = silence.stop;
71+
newClips.push(currentClip);
6972
continue;
7073
}
71-
72-
const middleClip = await currentClip.split(silence.start.add(currentClip.offset));
73-
74-
currentClip = await middleClip.split(silence.stop.add(middleClip.offset));
75-
middleClip.detach();
74+
const middleClip = currentClip.copy();
75+
middleClip.range[0] = silence.stop;
76+
77+
currentClip.range[1] = silence.start;
78+
newClips.push(currentClip);
79+
80+
currentClip = middleClip;
81+
}
82+
if (currentClip.id !== newClips.at(-1)?.id) {
83+
newClips.push(currentClip);
7684
}
7785
}
86+
clipsToDetach.forEach((clip) => clip.detach());
87+
const promises = newClips.map((clip) => this.add(clip));
88+
await Promise.all(promises);
7889
}
7990
}

0 commit comments

Comments
 (0)