}
)
-CONF_ENTRY_SUPPORT_CROSSFADE_DIFFERENT_SAMPLE_RATES = ConfigEntry(
- key="crossfade_different_sample_rates",
+CONF_ENTRY_SUPPORT_GAPLESS_DIFFERENT_SAMPLE_RATES = ConfigEntry(
+ key="gapless_different_sample_rates",
type=ConfigEntryType.BOOLEAN,
- label="Allow crossfade between tracks with different sample rates",
- description="Enable this option to allow crossfading between tracks that have different "
+ label="Allow gapless playback (and crossfades) between tracks of different sample rates",
+ description="Enable this option to allow gapless playback between tracks that have different "
"sample rates (e.g. 44.1kHz to 48kHz). \n\n "
"Only enable this option if your player actually support this, otherwise you may "
- "experience audio glitches during crossfades.",
+ "experience audio glitches during transitioning between tracks.",
default_value=False,
category="advanced",
)
OPTIONAL_FEATURES = {
PlayerFeature.ENQUEUE,
PlayerFeature.GAPLESS_PLAYBACK,
- PlayerFeature.GAPLESS_DIFFERENT_SAMPLERATE,
PlayerFeature.NEXT_PREVIOUS,
PlayerFeature.PAUSE,
PlayerFeature.PLAY_ANNOUNCEMENT,
CONF_CROSSFADE_DURATION,
CONF_ENTRY_ENABLE_ICY_METADATA,
CONF_ENTRY_LOG_LEVEL,
+ CONF_ENTRY_SUPPORT_GAPLESS_DIFFERENT_SAMPLE_RATES,
CONF_HTTP_PROFILE,
CONF_OUTPUT_CHANNELS,
CONF_OUTPUT_CODEC,
),
)
supported_sample_rates = tuple(int(x[0]) for x in supported_rates_conf)
- # use highest supported rate below content rate
+ # use highest supported rate within content rate
output_sample_rate = max(
- (r for r in supported_sample_rates if r < streamdetails.audio_format.sample_rate),
+ (r for r in supported_sample_rates if r <= streamdetails.audio_format.sample_rate),
default=48000,
)
# work out pcm format based on streamdetails
pcm_format.channels = 2 # force stereo for crossfading
# allows upsample to same sample rate for crossfade
# if the device does not support gapless playback with different sample rates
- if PlayerFeature.GAPLESS_DIFFERENT_SAMPLERATE not in player.supported_features:
+ if not self.mass.config.get_raw_player_config_value(
+ player.player_id,
+ CONF_ENTRY_SUPPORT_GAPLESS_DIFFERENT_SAMPLE_RATES.key,
+ CONF_ENTRY_SUPPORT_GAPLESS_DIFFERENT_SAMPLE_RATES.default_value,
+ ):
new_sample_rate = max(
pcm_format.sample_rate,
48000, # sane/safe default
if new_sample_rate != pcm_format.sample_rate:
self.logger.debug(
"Player does not support crossfade with different sample rates, "
- "content will be (HQ) upsampled to at least 48kHz for crossfade."
+ "content will be (HQ) upsampled to %s for crossfade.",
+ new_sample_rate,
)
pcm_format.sample_rate = new_sample_rate
PlayerFeature.SEEK,
PlayerFeature.SELECT_SOURCE,
PlayerFeature.GAPLESS_PLAYBACK,
- PlayerFeature.GAPLESS_DIFFERENT_SAMPLERATE,
}
SOURCE_LINE_IN = "line_in"
PlayerFeature.SELECT_SOURCE,
PlayerFeature.SET_MEMBERS,
PlayerFeature.GAPLESS_PLAYBACK,
- PlayerFeature.GAPLESS_DIFFERENT_SAMPLERATE,
}
PlayerFeature.VOLUME_SET,
PlayerFeature.ENQUEUE,
PlayerFeature.GAPLESS_PLAYBACK,
- PlayerFeature.GAPLESS_DIFFERENT_SAMPLERATE,
)
# Source Mapping
PlayerType,
RepeatMode,
)
-from music_assistant_models.errors import (
- InvalidCommand,
- MusicAssistantError,
-)
+from music_assistant_models.errors import InvalidCommand, MusicAssistantError
from music_assistant_models.media_items import AudioFormat
from music_assistant.constants import (
CONF_ENTRY_DEPRECATED_EQ_TREBLE,
CONF_ENTRY_HTTP_PROFILE_FORCED_2,
CONF_ENTRY_OUTPUT_CODEC,
- CONF_ENTRY_SUPPORT_CROSSFADE_DIFFERENT_SAMPLE_RATES,
+ CONF_ENTRY_SUPPORT_GAPLESS_DIFFERENT_SAMPLE_RATES,
CONF_ENTRY_SYNC_ADJUST,
INTERNAL_PCM_FORMAT,
VERBOSE_LOG_LEVEL,
PlayerFeature.PAUSE,
PlayerFeature.ENQUEUE,
PlayerFeature.GAPLESS_PLAYBACK,
- PlayerFeature.GAPLESS_DIFFERENT_SAMPLERATE,
}
self._attr_can_group_with = {provider.instance_id}
self.multi_client_stream: MultiClientStream | None = None
create_sample_rates_config_entry(
max_sample_rate=max_sample_rate, max_bit_depth=24, safe_max_bit_depth=24
),
- CONF_ENTRY_SUPPORT_CROSSFADE_DIFFERENT_SAMPLE_RATES,
+ CONF_ENTRY_SUPPORT_GAPLESS_DIFFERENT_SAMPLE_RATES,
]
async def power(self, powered: bool) -> None: