From: Marcel van der Veldt Date: Fri, 7 Nov 2025 14:47:18 +0000 (+0100) Subject: More crossfade tweaks X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=8c0b70ac33062b73e4801a738ffdf218d56d54f2;p=music-assistant-server.git More crossfade tweaks --- diff --git a/music_assistant/controllers/streams.py b/music_assistant/controllers/streams.py index 9f71353e..f83514bc 100644 --- a/music_assistant/controllers/streams.py +++ b/music_assistant/controllers/streams.py @@ -124,7 +124,8 @@ class CrossfadeData: data: bytes fade_in_size: int - pcm_format: AudioFormat + pcm_format: AudioFormat # Format of the 'data' bytes (current/previous track's format) + fade_in_pcm_format: AudioFormat # Format for 'fade_in_size' (next track's format) queue_item_id: str @@ -1453,8 +1454,9 @@ class StreamsController(CoreController): if crossfade_data: # Calculate discard amount in seconds (format-independent) + # Use fade_in_pcm_format because fade_in_size is in the next track's original format fade_in_duration_seconds = ( - crossfade_data.fade_in_size / crossfade_data.pcm_format.pcm_sample_size + crossfade_data.fade_in_size / crossfade_data.fade_in_pcm_format.pcm_sample_size ) discard_seconds = int(fade_in_duration_seconds) - 1 # Calculate discard amounts in CURRENT track's format @@ -1620,7 +1622,7 @@ class StreamsController(CoreController): # edge case: pcm format mismatch, we need to resample the next track's # beginning part before crossfading self.logger.debug( - "Resampling next track from %s to %s for queue %s", + "Resampling next track's crossfade from %s to %s for queue %s", next_queue_item_pcm_format.sample_rate, pcm_format.sample_rate, queue.display_name, @@ -1662,15 +1664,17 @@ class StreamsController(CoreController): for _chunk in divide_chunks(crossfade_first, pcm_format.pcm_sample_size): yield _chunk # store the other half for the next track - # IMPORTANT: Use original buffer size (in next track's format) for fade_in_size - # because the next track will stream in its native format and needs to know - # how many bytes to discard in that format. - # However, crossfade_second data is in current track's format (pcm_format) + # IMPORTANT: crossfade_second data is in CURRENT track's format (pcm_format) # because it was created from the resampled buffer used for mixing. + # BUT fade_in_size represents bytes in NEXT track's original format + # (next_queue_item_pcm_format) because that's how much of the next track + # was consumed during the crossfade. We need both formats to correctly + # handle the crossfade data when the next track starts. self._crossfade_data[queue_item.queue_id] = CrossfadeData( data=crossfade_second, fade_in_size=original_buffer_size, - pcm_format=pcm_format, + pcm_format=pcm_format, # Format of the data (current track) + fade_in_pcm_format=next_queue_item_pcm_format, # Format for fade_in_size queue_item_id=next_queue_item.queue_item_id, ) except Exception as err: