Technical Information
Section titled “Technical Information”This section contains more indepth technical information regarding Music Assistant’s workings for those interested.
Volume Normalization
Section titled “Volume Normalization”The normalization value to totally avoid clipping should be -23 LUFS based on this official documentation https://tech.ebu.ch/docs/r/r128.pdf but values differ per plattform so it is complicated to get the right value.
Here is a good document from the mastering plugin developer izotope comparing different plattforms like YouTube, Spotify, Deezer, Tidal and many more. This page explains the whole topic very well
Noting the above, the default value is -14 which should be a good compromise in 99% of cases.
In general, it is not recommended to turn off the volume normalization because there are so many different loudness levels, especially if music is played from different sources. MA uses an integrated loudness level based on the EBU-R128 standard and only adjusts gain of the entire track up or down so there is no compression of dynamic range as long as you use a value low enough to keep headroom. It’s the user’s responsibility to use sane values for the target level of the volume normalization, a value somewhere between -23 and -12 LUFS is recommended. The default value is set to -14 LUFS. Audio is processed internally as 32 bit floating point, so the gain adjustment has headroom to work in. If a hard ceiling on the output is wanted, a Safety Limiter filter can be added in the DSP settings.
If audio is only played from one single source (e.g. Deezer) and that audio source already has normalized its audio files, then its safe to disable normalization in MA. If audio is played from different sources or audio is not normalized at the source, it is highly recommended to leave normalization enabled for the best experience. Some sources, Spotify among them, deliver their audio at a loudness target of their own and tell MA so. Those streams are left untouched and the Audio Pipeline view reports the normalization as coming from the source.
Where the loudness value comes from
Section titled “Where the loudness value comes from”MA needs an integrated loudness value for a track, in LUFS, before it can work out a gain adjustment. It looks for one in this order:
R128_TRACK_GAINandR128_ALBUM_GAINtags on the fileREPLAYGAIN_TRACK_GAINandREPLAYGAIN_ALBUM_GAINtags on the file- A loudness value supplied by the music provider itself, which Plex and Subsonic both report
- MA’s own measurement, produced by the Loudness Analysis provider
Tags and provider values take priority over MA’s own measurement, and a track that already carries one is not analysed at all. Tags are read when the track is scanned into the library. If you add or change them later, use Refresh item on the track to pick up the new values.
Once a value exists from any of these sources it is used, whichever method is selected under Settings → System → Streams → Queue Playback, unless that method is Dynamic, Fixed Gain or Disabled. The methods otherwise differ only in what happens while no value is available yet. Where no value exists and the method allows it, MA falls back to a dynamic normalizer, which is less accurate but will at least prevent a sudden drop or spike in the volume level.
Track gain and album gain
Section titled “Track gain and album gain”Album gain keeps the relative loudness between the tracks of an album intact, so a quiet interlude still sits below the track that follows it. MA uses the album value in place of the track value when all of the following are true:
- The track is playing as part of an album that was queued as an album. A single track added to the queue, or a playlist that happens to contain the track, uses track gain
- Repeat mode is not set to repeat a single track
- An album loudness value is available for the track
- The method in use is measurement based, rather than Dynamic or Fixed Gain
Album loudness only ever comes from file tags or a music provider. MA’s own measurement covers the individual track, so a library with no album gain tags normalizes per track. Which of the two was used is shown for the current track in the Audio Pipeline view.
More technical details
Section titled “More technical details”All tracks are processed internally as raw pcm by Music Assistant. So everything that is played will be first decoded to raw pcm of 32 bits floating point in the sample rate of the origin (unless explicit resampling is enabled/needed, such as when flow mode is enabled), and the gain adjustment is done while extracting the raw source media so the pcm chunks passed into the streaming engine have the gain adjustment applied. In this way there should be enough headroom within the (final) 16 or 24 bits bit depth. If a playback target does not support bit depths higher than 16 bits, dithering will be applied to bring the signal down again to 16 bits without quality loss.
All further processing in MA is done at PCM raw audio level, such as the DSP Settings - if “flow mode” is enabled crossfading is also done on the raw pcm chunks but that will resample all audio into one static sample rate and bit depth to create one “flow” of audio to send to the player.
The final part in the chain is that MA needs to send the audio to the player. By default MA encodes the raw PCM into FLAC because it is lossless while still providing a descent amount of compression. For players that can not handle FLAC very well, or simply to save bandwidth, MA provides an option (per player) to encode to MP3 instead.
The Settings → System → Streams → Queue Playback settings contain the normalization method and the target level, both of which apply to all playback. Turning normalization on and off is done under Settings → System → Player Queues and can be overridden on an individual queue basis.
Stream Selection
Section titled “Stream Selection”When the same track is available from more than one source — say a Spotify stream and a FLAC file on disk — Music Assistant picks one automatically when you press play. It always chooses the highest quality available.
Quality is judged on sample rate, bit depth and codec, in that order. Where two sources are of equal quality, the local one is preferred over the cloud one.
You can see which sources hold a given item, and how they are linked together, in the Provider Details section of the item.
Track Queueing
Section titled “Track Queueing”MA has 2 ways of enqueuing tracks to players:
NATIVE ENQUEUE SUPPORT The player has native enqueue support so MA tells it what the next track will be right before the current one ends. This is a special feature that not all players support. Its supported (and by default enabled) for example on Squeezelite, Google Cast and Sonos players. Some DLNA players support it but others don’t so MA offers a player setting to enable it so a user can try and see if the player accepts it. The benefit of this is full support gapless playback and, in the case of Squeezelite and Sonos, also crossfade. Full metadata will also be sent to the player which is currently playing.
FLOW MODE As an alternative to native enqueuing, one stream of audio can be sent to the player and Music Assistant can stitch the songs together (with gapless or crossfade). This mode is used by default for AirPlay, Snapcast and any mediaplayers imported from Home Assistant, and flow mode will also be used by DLNA and Cast if crossfade gets enabled. The downside of this approach is that most players lose metadata display (on the speaker itself). Some DLNA players however support “ICY metadata” which is what MA will send to inform what is playing.
NOTE on player support: Always prefer a native Player provider within Music Assistant over a generic imported player from Home Assistant! The media players within Home Assistant are designed with automation of the player/music in mind, not to provide an optimal streaming experience itself. Native player providers in Music Assistant have been tweaked optimally to give the best (audio) quality and experience as well as supporting imported features such as grouping and enqueuing.
Player Perfect Sync
Section titled “Player Perfect Sync”Audio sync between speakers is only possible if there is accurate knowledge of the exact (millisecond-precise) timestamp a player played each audio frame. In practice there are 2 common strategies used to sync audio:
-
Sending timestamped frames to each player - there is one master clock and audio frames are sent to each receiving device in a sync group including the timestamp. So each player will have knowledge when it should play each frame and it can drop or inject frames to keep in sync. This strategy is often used in the proprietary protocols such as Google Cast, Sonos, Roon RAAT, BluOS and even Apple AirPlay (RAOP). This is by far the best (most precise) sync method because each player is responsible for sending the correct audio frames to the DAC (or digital transport).
-
Server-side corrected sync. Each player is sent the audio stream from the centralized source and then the server keeps track of each player’s latency and corrects it by pausing/forwarding, playing faster/slower or injecting frames. This is easier to implement because the only thing needed client-side is accurate progress reporting of the client (how many milliseconds it played) and the server contains all the centralized logic to keep the sync. This is used by, for example, Squeezelite and Snapcast.
How well the time synchronisation works depends on multiple factors but often it will be found that strategy 1 is superior to strategy 2 and/or strategy 2 needs tweaking to get it right. For example, on Snapcast skipping may be heard (small disturbances to the sound while its adjusting) and Squeezelite works less optimally with WiFi based devices due to changing player latency.
RECOMMENDATION: To have the best synced audio experiences of players, try to stick with one ecosystem and, if possible, choose one of the options that implement strategy 1 (proprietary protocol).
AirPlay is favoured because it a very good sync protocol that originally was proprietary but has been reverse engineered. AirPlay targets are now available in both commercially available audio gear (even high end equipment) and DIY devices. It outperforms all the strategy 2 stream protocols by a wide margin. The same applies to a $35 Chromecast audio puck with the Google Cast protocol. It works really well out of the box.
This website uses privacy-first analytics to help us improve the site. You can view all data in our public dashboard.