From 09de406890a7a5a69998d34f1ca7468ca61af082 Mon Sep 17 00:00:00 2001 From: angel Date: Sun, 25 Jan 2026 03:01:28 +0000 Subject: [PATCH] fix: implement proper crossfade with fade-in on new tracks and fade-out on track end --- .env.local | 2 +- app/components/AudioPlayer.tsx | 7 ++++++- lib/audio-effects.ts | 6 +++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.env.local b/.env.local index 919cf84..b3427ab 100644 --- a/.env.local +++ b/.env.local @@ -1 +1 @@ -NEXT_PUBLIC_COMMIT_SHA=ed41ad6 +NEXT_PUBLIC_COMMIT_SHA=477b172 diff --git a/app/components/AudioPlayer.tsx b/app/components/AudioPlayer.tsx index 75477e1..a3876bb 100644 --- a/app/components/AudioPlayer.tsx +++ b/app/components/AudioPlayer.tsx @@ -388,6 +388,11 @@ export const AudioPlayer: React.FC = () => { // Auto-play only if the track has the autoPlay flag and audio is initialized if (currentTrack.autoPlay && (!isMobile || audioInitialized)) { + // Start crossfade fade-in if enabled + if (audioSettings.crossfadeDuration > 0 && audioEffects) { + audioEffects.startCrossfade(); + } + // Add a small delay for iOS compatibility const playPromise = isMobile ? new Promise(resolve => setTimeout(resolve, 100)).then(() => audioCurrent.play()) : @@ -410,7 +415,7 @@ export const AudioPlayer: React.FC = () => { setIsPlaying(false); } } - }, [currentTrack, onTrackStart, onTrackPlay, isMobile, audioInitialized, audioEffects, audioSettings.gaplessPlayback, audioSettings.replayGainEnabled, queue]); + }, [currentTrack, onTrackStart, onTrackPlay, isMobile, audioInitialized, audioEffects, audioSettings.gaplessPlayback, audioSettings.replayGainEnabled, audioSettings.crossfadeDuration, queue]); useEffect(() => { const audioCurrent = audioRef.current; diff --git a/lib/audio-effects.ts b/lib/audio-effects.ts index 93b5f56..266d1ae 100644 --- a/lib/audio-effects.ts +++ b/lib/audio-effects.ts @@ -126,6 +126,7 @@ export class AudioEffects { public setCrossfadeTime(seconds: number) { if (this.crossfadeGainNode) { const now = this.context.currentTime; + this.crossfadeGainNode.gain.cancelScheduledValues(now); this.crossfadeGainNode.gain.setValueAtTime(1, now); this.crossfadeGainNode.gain.linearRampToValueAtTime(0, now + seconds); } @@ -133,7 +134,10 @@ export class AudioEffects { public startCrossfade() { if (this.crossfadeGainNode) { - this.crossfadeGainNode.gain.value = 1; + const now = this.context.currentTime; + this.crossfadeGainNode.gain.cancelScheduledValues(now); + this.crossfadeGainNode.gain.setValueAtTime(0, now); + this.crossfadeGainNode.gain.linearRampToValueAtTime(1, now + 0.5); // Fast fade in } }