Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Player: optionally use album gain for loudness normalisation #739

Merged
merged 1 commit into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,19 @@ public static NormalizationData read(@NotNull InputStream in) throws IOException
return new NormalizationData(buffer.getFloat(), buffer.getFloat(), buffer.getFloat(), buffer.getFloat());
}

public float getFactor(float normalisationPregain) {
float normalisationFactor = (float) Math.pow(10, (track_gain_db + normalisationPregain) / 20);
public float getFactor(float normalisationPregain, boolean useAlbumGain) {
float gain = useAlbumGain? album_gain_db : track_gain_db;
LOGGER.trace("Using gain: {}", gain);
float normalisationFactor = (float) Math.pow(10, (gain + normalisationPregain) / 20);
if (normalisationFactor * track_peak > 1) {
LOGGER.warn("Reducing normalisation factor to prevent clipping. Please add negative pregain to avoid.");
normalisationFactor = 1 / track_peak;
}

return normalisationFactor;
}

public float getFactor(float normalisationPregain) {
return getFactor(normalisationPregain, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ public PlayerConfiguration toPlayer() {
.setAutoplayEnabled(config.get("player.autoplayEnabled"))
.setCrossfadeDuration(config.get("player.crossfadeDuration"))
.setEnableNormalisation(config.get("player.enableNormalisation"))
.setUseAlbumGain(config.get("player.useAlbumGain"))
.setInitialVolume(config.get("player.initialVolume"))
.setLogAvailableMixers(config.get("player.logAvailableMixers"))
.setMetadataPipe(metadataPipe())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public final class PlayerConfiguration {
// Audio
public final AudioQuality preferredQuality;
public final boolean enableNormalisation;
public final boolean useAlbumGain;
public final float normalisationPregain;
public final boolean autoplayEnabled;
public final int crossfadeDuration;
Expand All @@ -52,11 +53,12 @@ public final class PlayerConfiguration {
// Local files
public final File localFilesPath;

private PlayerConfiguration(AudioQuality preferredQuality, boolean enableNormalisation, float normalisationPregain, boolean autoplayEnabled, int crossfadeDuration, boolean preloadEnabled,
private PlayerConfiguration(AudioQuality preferredQuality, boolean enableNormalisation, boolean useAlbumGain, float normalisationPregain, boolean autoplayEnabled, int crossfadeDuration, boolean preloadEnabled,
AudioOutput output, String outputClass, Object[] outputClassParams, File outputPipe, File metadataPipe, String[] mixerSearchKeywords, boolean logAvailableMixers, int releaseLineDelay,
int initialVolume, int volumeSteps, boolean bypassSinkVolume, File localFilesPath) {
this.preferredQuality = preferredQuality;
this.enableNormalisation = enableNormalisation;
this.useAlbumGain = useAlbumGain;
this.normalisationPregain = normalisationPregain;
this.autoplayEnabled = autoplayEnabled;
this.crossfadeDuration = crossfadeDuration;
Expand All @@ -83,6 +85,7 @@ public final static class Builder {
// Audio
private AudioQuality preferredQuality = AudioQuality.NORMAL;
private boolean enableNormalisation = true;
private boolean useAlbumGain = false;
private float normalisationPregain = 3.0f;
private boolean autoplayEnabled = true;
private int crossfadeDuration = 0;
Expand Down Expand Up @@ -119,6 +122,11 @@ public Builder setEnableNormalisation(boolean enableNormalisation) {
return this;
}

public Builder setUseAlbumGain(boolean useAlbumGain) {
this.useAlbumGain = useAlbumGain;
return this;
}

public Builder setNormalisationPregain(float normalisationPregain) {
this.normalisationPregain = normalisationPregain;
return this;
Expand Down Expand Up @@ -207,7 +215,7 @@ public Builder setLocalFilesPath(File localFilesPath) {

@Contract(value = " -> new", pure = true)
public @NotNull PlayerConfiguration build() {
return new PlayerConfiguration(preferredQuality, enableNormalisation, normalisationPregain, autoplayEnabled, crossfadeDuration, preloadEnabled,
return new PlayerConfiguration(preferredQuality, enableNormalisation, useAlbumGain, normalisationPregain, autoplayEnabled, crossfadeDuration, preloadEnabled,
output, outputClass, outputClassParams, outputPipe, metadataPipe, mixerSearchKeywords, logAvailableMixers, releaseLineDelay,
initialVolume, volumeSteps, bypassSinkVolume, localFilesPath);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ private void load(boolean preload) throws IOException, Decoder.DecoderException,

float normalizationFactor;
if (stream.normalizationData == null || !conf.enableNormalisation) normalizationFactor = 1;
else normalizationFactor = stream.normalizationData.getFactor(conf.normalisationPregain);
else normalizationFactor = stream.normalizationData.getFactor(conf.normalisationPregain, conf.useAlbumGain);

Iterator<Decoder> iter = Decoders.initDecoder(stream.in.codec(), stream.in.stream(), normalizationFactor, metadata.duration());
while (iter.hasNext()) {
Expand Down
3 changes: 2 additions & 1 deletion player/src/main/resources/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ manualCorrection = 0 # Manual time correction in millis
autoplayEnabled = true # Autoplay similar songs when your music ends
preferredAudioQuality = "NORMAL" # Preferred audio quality (NORMAL, HIGH, VERY_HIGH)
enableNormalisation = true # Whether to apply the Spotify loudness normalisation
useAlbumGain = false # Whether to apply album gain (instead of track gain) for normalisation
normalisationPregain = +3.0 # Normalisation pregain in decibels (loud at +6, normal at +3, quiet at -5)
initialVolume = 65536 # Initial volume (0-65536)
volumeSteps = 64 # Number of volume notches
Expand Down Expand Up @@ -83,4 +84,4 @@ onPanicState = ""
onConnectionDropped = ""
onConnectionEstablished = ""
onStartedLoading = ""
onFinishedLoading = ""
onFinishedLoading = ""
Loading