From 17d23c3b64a6367390d28f24d37ef0b0047baaa2 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Tue, 14 Jan 2025 21:48:07 +0100 Subject: [PATCH] Chore: Simplify volume normalization a bit --- music_assistant/controllers/streams.py | 29 ++++++++++---------------- music_assistant/helpers/audio.py | 14 +++++++++++-- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/music_assistant/controllers/streams.py b/music_assistant/controllers/streams.py index 5087401f..e3eba351 100644 --- a/music_assistant/controllers/streams.py +++ b/music_assistant/controllers/streams.py @@ -914,35 +914,24 @@ class StreamsController(CoreController): filter_params = [] extra_input_args = streamdetails.extra_input_args or [] # handle volume normalization - enable_volume_normalization = ( - streamdetails.target_loudness is not None - and streamdetails.volume_normalization_mode != VolumeNormalizationMode.DISABLED - ) - dynamic_volume_normalization = ( - streamdetails.volume_normalization_mode == VolumeNormalizationMode.DYNAMIC - and enable_volume_normalization - ) - if dynamic_volume_normalization: + if streamdetails.volume_normalization_mode == VolumeNormalizationMode.DYNAMIC: # volume normalization using loudnorm filter (in dynamic mode) # which also collects the measurement on the fly during playback # more info: https://k.ylo.ph/2016/04/04/loudnorm.html filter_rule = f"loudnorm=I={streamdetails.target_loudness}:TP=-2.0:LRA=10.0:offset=0.0" filter_rule += ":print_format=json" filter_params.append(filter_rule) - elif ( - enable_volume_normalization - and streamdetails.volume_normalization_mode == VolumeNormalizationMode.FIXED_GAIN - ): + elif streamdetails.volume_normalization_mode == VolumeNormalizationMode.FIXED_GAIN: # apply used defined fixed volume/gain correction gain_correct: float = await self.mass.config.get_core_config_value( self.domain, - CONF_VOLUME_NORMALIZATION_FIXED_GAIN_RADIO - if streamdetails.media_type == MediaType.RADIO - else CONF_VOLUME_NORMALIZATION_FIXED_GAIN_TRACKS, + CONF_VOLUME_NORMALIZATION_FIXED_GAIN_TRACKS + if streamdetails.media_type == MediaType.TRACK + else CONF_VOLUME_NORMALIZATION_FIXED_GAIN_RADIO, ) gain_correct = round(gain_correct, 2) filter_params.append(f"volume={gain_correct}dB") - elif enable_volume_normalization and streamdetails.loudness is not None: + elif streamdetails.volume_normalization_mode == VolumeNormalizationMode.MEASUREMENT_ONLY: # volume normalization with known loudness measurement # apply volume/gain correction gain_correct = streamdetails.target_loudness - streamdetails.loudness @@ -987,7 +976,11 @@ class StreamsController(CoreController): # pad some silence before the radio stream starts to create some headroom # for radio stations that do not provide any look ahead buffer # without this, some radio streams jitter a lot, especially with dynamic normalization - pad_seconds = 5 if dynamic_volume_normalization else 2 + pad_seconds = ( + 5 + if streamdetails.volume_normalization_mode == VolumeNormalizationMode.DYNAMIC + else 2 + ) async for chunk in get_silence(pad_seconds, pcm_format): yield chunk diff --git a/music_assistant/helpers/audio.py b/music_assistant/helpers/audio.py index 3d82d92d..47e9ec70 100644 --- a/music_assistant/helpers/audio.py +++ b/music_assistant/helpers/audio.py @@ -264,10 +264,10 @@ async def get_stream_details( streamdetails.prefer_album_loudness = prefer_album_loudness player_settings = await mass.config.get_player_config(streamdetails.queue_id) core_config = await mass.config.get_core_config("streams") + streamdetails.target_loudness = player_settings.get_value(CONF_VOLUME_NORMALIZATION_TARGET) streamdetails.volume_normalization_mode = _get_normalization_mode( core_config, player_settings, streamdetails ) - streamdetails.target_loudness = player_settings.get_value(CONF_VOLUME_NORMALIZATION_TARGET) process_time = int((time.time() - time_start) * 1000) LOGGER.debug( @@ -311,7 +311,7 @@ async def get_media_stream( await ffmpeg_proc.start() logger.debug( "Started media stream for %s" - " - using streamtype: %s " + " - using streamtype: %s" " - volume normalization: %s" " - pcm format: %s" " - ffmpeg PID: %s", @@ -993,6 +993,9 @@ def _get_normalization_mode( if not player_config.get_value(CONF_VOLUME_NORMALIZATION): # disabled for this player return VolumeNormalizationMode.DISABLED + if streamdetails.target_loudness is None: + # no target loudness set, disable normalization + return VolumeNormalizationMode.DISABLED # work out preference for track or radio preference = VolumeNormalizationMode( core_config.get_value( @@ -1014,5 +1017,12 @@ def _get_normalization_mode( if streamdetails.loudness is None and preference == VolumeNormalizationMode.FALLBACK_FIXED_GAIN: return VolumeNormalizationMode.FIXED_GAIN + # handle measurement available - chosen mode is measurement + if streamdetails.loudness and preference not in ( + VolumeNormalizationMode.DISABLED, + VolumeNormalizationMode.FIXED_GAIN, + ): + return VolumeNormalizationMode.MEASUREMENT_ONLY + # simply return the preference return preference -- 2.34.1