Skip to content

Commit c8cf8d2

Browse files
authored
Merge pull request #739 from skeller/use_album_gain
Player: optionally use album gain for loudness normalisation
2 parents cc22e29 + 01df6e1 commit c8cf8d2

5 files changed

Lines changed: 22 additions & 6 deletions

File tree

lib/src/main/java/xyz/gianlu/librespot/audio/NormalizationData.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,19 @@ public static NormalizationData read(@NotNull InputStream in) throws IOException
6262
return new NormalizationData(buffer.getFloat(), buffer.getFloat(), buffer.getFloat(), buffer.getFloat());
6363
}
6464

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

7274
return normalisationFactor;
7375
}
76+
77+
public float getFactor(float normalisationPregain) {
78+
return getFactor(normalisationPregain, false);
79+
}
7480
}

player/src/main/java/xyz/gianlu/librespot/player/FileConfiguration.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ public PlayerConfiguration toPlayer() {
439439
.setAutoplayEnabled(config.get("player.autoplayEnabled"))
440440
.setCrossfadeDuration(config.get("player.crossfadeDuration"))
441441
.setEnableNormalisation(config.get("player.enableNormalisation"))
442+
.setUseAlbumGain(config.get("player.useAlbumGain"))
442443
.setInitialVolume(config.get("player.initialVolume"))
443444
.setLogAvailableMixers(config.get("player.logAvailableMixers"))
444445
.setMetadataPipe(metadataPipe())

player/src/main/java/xyz/gianlu/librespot/player/PlayerConfiguration.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public final class PlayerConfiguration {
2929
// Audio
3030
public final AudioQuality preferredQuality;
3131
public final boolean enableNormalisation;
32+
public final boolean useAlbumGain;
3233
public final float normalisationPregain;
3334
public final boolean autoplayEnabled;
3435
public final int crossfadeDuration;
@@ -52,11 +53,12 @@ public final class PlayerConfiguration {
5253
// Local files
5354
public final File localFilesPath;
5455

55-
private PlayerConfiguration(AudioQuality preferredQuality, boolean enableNormalisation, float normalisationPregain, boolean autoplayEnabled, int crossfadeDuration, boolean preloadEnabled,
56+
private PlayerConfiguration(AudioQuality preferredQuality, boolean enableNormalisation, boolean useAlbumGain, float normalisationPregain, boolean autoplayEnabled, int crossfadeDuration, boolean preloadEnabled,
5657
AudioOutput output, String outputClass, Object[] outputClassParams, File outputPipe, File metadataPipe, String[] mixerSearchKeywords, boolean logAvailableMixers, int releaseLineDelay,
5758
int initialVolume, int volumeSteps, boolean bypassSinkVolume, File localFilesPath) {
5859
this.preferredQuality = preferredQuality;
5960
this.enableNormalisation = enableNormalisation;
61+
this.useAlbumGain = useAlbumGain;
6062
this.normalisationPregain = normalisationPregain;
6163
this.autoplayEnabled = autoplayEnabled;
6264
this.crossfadeDuration = crossfadeDuration;
@@ -83,6 +85,7 @@ public final static class Builder {
8385
// Audio
8486
private AudioQuality preferredQuality = AudioQuality.NORMAL;
8587
private boolean enableNormalisation = true;
88+
private boolean useAlbumGain = false;
8689
private float normalisationPregain = 3.0f;
8790
private boolean autoplayEnabled = true;
8891
private int crossfadeDuration = 0;
@@ -119,6 +122,11 @@ public Builder setEnableNormalisation(boolean enableNormalisation) {
119122
return this;
120123
}
121124

125+
public Builder setUseAlbumGain(boolean useAlbumGain) {
126+
this.useAlbumGain = useAlbumGain;
127+
return this;
128+
}
129+
122130
public Builder setNormalisationPregain(float normalisationPregain) {
123131
this.normalisationPregain = normalisationPregain;
124132
return this;
@@ -207,7 +215,7 @@ public Builder setLocalFilesPath(File localFilesPath) {
207215

208216
@Contract(value = " -> new", pure = true)
209217
public @NotNull PlayerConfiguration build() {
210-
return new PlayerConfiguration(preferredQuality, enableNormalisation, normalisationPregain, autoplayEnabled, crossfadeDuration, preloadEnabled,
218+
return new PlayerConfiguration(preferredQuality, enableNormalisation, useAlbumGain, normalisationPregain, autoplayEnabled, crossfadeDuration, preloadEnabled,
211219
output, outputClass, outputClassParams, outputPipe, metadataPipe, mixerSearchKeywords, logAvailableMixers, releaseLineDelay,
212220
initialVolume, volumeSteps, bypassSinkVolume, localFilesPath);
213221
}

player/src/main/java/xyz/gianlu/librespot/player/playback/PlayerQueueEntry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ private void load(boolean preload) throws IOException, Decoder.DecoderException,
135135

136136
float normalizationFactor;
137137
if (stream.normalizationData == null || !conf.enableNormalisation) normalizationFactor = 1;
138-
else normalizationFactor = stream.normalizationData.getFactor(conf.normalisationPregain);
138+
else normalizationFactor = stream.normalizationData.getFactor(conf.normalisationPregain, conf.useAlbumGain);
139139

140140
Iterator<Decoder> iter = Decoders.initDecoder(stream.in.codec(), stream.in.stream(), normalizationFactor, metadata.duration());
141141
while (iter.hasNext()) {

player/src/main/resources/default.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ manualCorrection = 0 # Manual time correction in millis
3737
autoplayEnabled = true # Autoplay similar songs when your music ends
3838
preferredAudioQuality = "NORMAL" # Preferred audio quality (NORMAL, HIGH, VERY_HIGH)
3939
enableNormalisation = true # Whether to apply the Spotify loudness normalisation
40+
useAlbumGain = false # Whether to apply album gain (instead of track gain) for normalisation
4041
normalisationPregain = +3.0 # Normalisation pregain in decibels (loud at +6, normal at +3, quiet at -5)
4142
initialVolume = 65536 # Initial volume (0-65536)
4243
volumeSteps = 64 # Number of volume notches
@@ -83,4 +84,4 @@ onPanicState = ""
8384
onConnectionDropped = ""
8485
onConnectionEstablished = ""
8586
onStartedLoading = ""
86-
onFinishedLoading = ""
87+
onFinishedLoading = ""

0 commit comments

Comments
 (0)