diff --git a/ui/src/utils/calculateReplayGain.js b/ui/src/utils/calculateReplayGain.js index e73ab5559..e69e27b15 100644 --- a/ui/src/utils/calculateReplayGain.js +++ b/ui/src/utils/calculateReplayGain.js @@ -1,20 +1,19 @@ const calculateReplayGain = (preAmp, gain, peak) => { - if (gain === undefined || peak === undefined) { + if (gain == null) { return 1 } // https://wiki.hydrogenaud.io/index.php?title=ReplayGain_1.0_specification§ion=19 // Normalized to max gain - return Math.min(10 ** ((gain + preAmp) / 20), 1 / peak) + const replayGain = 10 ** ((gain + preAmp) / 20) + return peak == null ? replayGain : Math.min(replayGain, 1 / peak) } export const calculateGain = (gainInfo, song) => { switch (gainInfo.gainMode) { case 'album': { - // Fall back to track gain when the album gain is missing (singles, or - // tracks without album ReplayGain tags), matching common ReplayGain - // players instead of applying no adjustment at all. - if (song.rgAlbumGain === undefined || song.rgAlbumPeak === undefined) { + // Singles and untagged albums have no album gain, so use the track gain. + if (song.rgAlbumGain == null) { return calculateReplayGain( gainInfo.preAmp, song.rgTrackGain, diff --git a/ui/src/utils/calculateReplayGain.test.js b/ui/src/utils/calculateReplayGain.test.js index dc3e54196..0b257ba48 100644 --- a/ui/src/utils/calculateReplayGain.test.js +++ b/ui/src/utils/calculateReplayGain.test.js @@ -14,6 +14,12 @@ describe('calculateGain', () => { rgTrackGain: -3, rgTrackPeak: 1, } + const nativeTrackOnlySong = { + rgAlbumGain: null, + rgAlbumPeak: null, + rgTrackGain: -3, + rgTrackPeak: 1, + } const noGainSong = {} it('uses album gain in album mode when it is present', () => { @@ -23,12 +29,28 @@ describe('calculateGain', () => { it('falls back to track gain in album mode when the album gain is missing', () => { const result = calculateGain({ gainMode: 'album', preAmp }, trackOnlySong) - // Without the fallback this returned 1 (no adjustment). It should now use - // the track gain instead. expect(result).toBeCloseTo(10 ** (-3 / 20)) - expect(result).not.toBe(1) }) + it('falls back to track gain in album mode when the album gain is null', () => { + const result = calculateGain( + { gainMode: 'album', preAmp }, + nativeTrackOnlySong, + ) + expect(result).toBeCloseTo(10 ** (-3 / 20)) + }) + + it.each([null, undefined])( + 'keeps the album gain in album mode when the album peak is %s', + (rgAlbumPeak) => { + const result = calculateGain( + { gainMode: 'album', preAmp }, + { ...albumSong, rgAlbumPeak }, + ) + expect(result).toBeCloseTo(10 ** (-6 / 20)) + }, + ) + it('returns 1 in album mode when neither album nor track gain is present', () => { const result = calculateGain({ gainMode: 'album', preAmp }, noGainSong) expect(result).toBe(1) @@ -39,6 +61,17 @@ describe('calculateGain', () => { expect(result).toBeCloseTo(10 ** (-3 / 20)) }) + it.each([null, undefined])( + 'keeps the track gain in track mode when the track peak is %s', + (rgTrackPeak) => { + const result = calculateGain( + { gainMode: 'track', preAmp }, + { ...albumSong, rgTrackPeak }, + ) + expect(result).toBeCloseTo(10 ** (-3 / 20)) + }, + ) + it('returns 1 when gain is disabled', () => { const result = calculateGain({ gainMode: 'none', preAmp }, albumSong) expect(result).toBe(1)