From 905238d424754e4fedff56875374e6840e8a9db1 Mon Sep 17 00:00:00 2001 From: Abelino Chavez Date: Fri, 30 Jan 2026 21:07:54 -0600 Subject: [PATCH] fix: improve audio mixing quality and prevent clipping (#677) - Use linear interpolation for resampling instead of nearest neighbor - Clamp output samples to [-1, 1] range to prevent distortion from overlapping audio clips exceeding valid amplitude range This should reduce audio artifacts in exported videos, especially when multiple audio sources overlap. Co-Authored-By: Claude Opus 4.5 --- apps/web/src/lib/media/audio.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/web/src/lib/media/audio.ts b/apps/web/src/lib/media/audio.ts index 6f789301..c70e9ce8 100644 --- a/apps/web/src/lib/media/audio.ts +++ b/apps/web/src/lib/media/audio.ts @@ -549,10 +549,19 @@ function mixAudioChannels({ const outputIndex = outputStartSample + i; if (outputIndex >= outputLength) break; - const sourceIndex = sourceStartSample + Math.floor(i / resampleRatio); - if (sourceIndex >= sourceData.length) break; + // Use linear interpolation for better resampling quality + const sourcePosition = sourceStartSample + i / resampleRatio; + const sourceIndex = Math.floor(sourcePosition); + if (sourceIndex >= sourceData.length - 1) break; - outputData[outputIndex] += sourceData[sourceIndex]; + const fraction = sourcePosition - sourceIndex; + const sample1 = sourceData[sourceIndex]; + const sample2 = sourceData[sourceIndex + 1] ?? sample1; + const interpolatedSample = sample1 + fraction * (sample2 - sample1); + + // Add sample and clamp to prevent distortion from clipping + const newValue = outputData[outputIndex] + interpolatedSample; + outputData[outputIndex] = Math.max(-1, Math.min(1, newValue)); } } }