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
This commit is contained in:
Max Kellermann 2021-10-14 13:37:57 +02:00
parent 46d00dd85f
commit 8ad17d25ef
4 changed files with 18 additions and 5 deletions

2
NEWS
View File

@ -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

View File

@ -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<FloatDuration>(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;

View File

@ -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,

View File

@ -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(),