From 8ad17d25efba0f13f507576524412a2e41d0372f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 14 Oct 2021 13:37:57 +0200 Subject: [PATCH] player/CrossFade: do not cross-fade songs shorter than 20 seconds From the feature request: "I generally like to have crossfade on, but when it happens during such short tracks (e.g. 20 seconds or less) it doesn't really sound good as those tracks are not really meant to be crossfaded and intended to act as a bridge on their own." Sounds reasonable. This commit doesn't add an option, but hard-codes the limit to 20 seconds. If it turns out that users want to have it configurable, we can still add the option. Closes https://github.com/MusicPlayerDaemon/MPD/issues/1184 --- NEWS | 2 ++ src/player/CrossFade.cxx | 7 +++++-- src/player/CrossFade.hxx | 11 +++++++++-- src/player/Thread.cxx | 3 ++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 996ac24fa..1579d0e0f 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,8 @@ ver 0.23 (not yet released) * decoder - openmpt: new plugin - wavpack: fix WVC file support +* player + - do not cross-fade songs shorter than 20 seconds * output - oss: support DSD over PCM - pipewire: new plugin diff --git a/src/player/CrossFade.cxx b/src/player/CrossFade.cxx index a6d14f348..1eeead4b2 100644 --- a/src/player/CrossFade.cxx +++ b/src/player/CrossFade.cxx @@ -34,6 +34,7 @@ inline bool CrossFadeSettings::CanCrossFadeSong(SignedSongTime total_time) const noexcept { return !total_time.IsNegative() && + duration >= MIN_TOTAL_TIME && duration >= std::chrono::duration_cast(total_time); } @@ -94,7 +95,8 @@ mixramp_interpolate(const char *ramp_list, float required_db) noexcept } unsigned -CrossFadeSettings::Calculate(SignedSongTime total_time, +CrossFadeSettings::Calculate(SignedSongTime current_total_time, + SignedSongTime next_total_time, float replay_gain_db, float replay_gain_prev_db, const char *mixramp_start, const char *mixramp_prev_end, const AudioFormat af, @@ -104,7 +106,8 @@ CrossFadeSettings::Calculate(SignedSongTime total_time, unsigned int chunks = 0; if (!IsEnabled() || - !CanCrossFadeSong(total_time) || + !CanCrossFadeSong(current_total_time) || + !CanCrossFadeSong(next_total_time) || /* we can't crossfade when the audio formats are different */ af != old_format) return 0; diff --git a/src/player/CrossFade.hxx b/src/player/CrossFade.hxx index 1934d0e91..8afda835c 100644 --- a/src/player/CrossFade.hxx +++ b/src/player/CrossFade.hxx @@ -26,6 +26,11 @@ struct AudioFormat; class SignedSongTime; struct CrossFadeSettings { + /** + * Songs shorter than this will never cross-fade. + */ + static constexpr SignedSongTime MIN_TOTAL_TIME{std::chrono::seconds{20}}; + /** * The configured cross fade duration [s]. */ @@ -46,7 +51,8 @@ struct CrossFadeSettings { /** * Calculate how many music pipe chunks should be used for crossfading. * - * @param total_time total_time the duration of the new song + * @param current_total_time the duration of the current song + * @param next_total_time the duration of the new song * @param replay_gain_db the ReplayGain adjustment used for this song * @param replay_gain_prev_db the ReplayGain adjustment used on the last song * @param mixramp_start the next songs mixramp_start tag @@ -58,7 +64,8 @@ struct CrossFadeSettings { * should be disabled for this song change */ [[gnu::pure]] - unsigned Calculate(SignedSongTime total_time, + unsigned Calculate(SignedSongTime current_total_time, + SignedSongTime next_total_time, float replay_gain_db, float replay_gain_prev_db, const char *mixramp_start, const char *mixramp_prev_end, diff --git a/src/player/Thread.cxx b/src/player/Thread.cxx index 19f92995b..95ab1626e 100644 --- a/src/player/Thread.cxx +++ b/src/player/Thread.cxx @@ -1049,7 +1049,8 @@ Player::Run() noexcept calculate how many chunks will be required for it */ cross_fade_chunks = - pc.cross_fade.Calculate(dc.total_time, + pc.cross_fade.Calculate(pc.total_time, + dc.total_time, dc.replay_gain_db, dc.replay_gain_prev_db, dc.GetMixRampStart(),