From c32a809d38fb14f7dc53ff96bb3191569d0bfa20 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 16 Oct 2020 18:28:54 +0200 Subject: [PATCH 1/6] decoder/opus: convert field `output_gain` to float --- src/decoder/plugins/OpusDecoderPlugin.cxx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/decoder/plugins/OpusDecoderPlugin.cxx b/src/decoder/plugins/OpusDecoderPlugin.cxx index a0cf02ba7..80e13ae31 100644 --- a/src/decoder/plugins/OpusDecoderPlugin.cxx +++ b/src/decoder/plugins/OpusDecoderPlugin.cxx @@ -79,7 +79,7 @@ class MPDOpusDecoder final : public OggDecoder { * The output gain from the Opus header. Initialized by * OnOggBeginning(). */ - signed output_gain; + float output_gain; /** * The pre-skip value from the Opus header. Initialized by @@ -170,10 +170,14 @@ MPDOpusDecoder::OnOggBeginning(const ogg_packet &packet) throw std::runtime_error("BOS packet must be OpusHead"); unsigned channels; - if (!ScanOpusHeader(packet.packet, packet.bytes, channels, output_gain, pre_skip) || + signed output_gain_i; + if (!ScanOpusHeader(packet.packet, packet.bytes, channels, output_gain_i, pre_skip) || !audio_valid_channel_count(channels)) throw std::runtime_error("Malformed BOS packet"); + /* convert Q7.8 fixed-point to float */ + output_gain = float(output_gain_i) / 256.0f; + granulepos = 0; skip = pre_skip; @@ -251,8 +255,8 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet) * ReplayGain. Add 5dB to compensate for the different * reference levels between ReplayGain (89dB) and EBU R128 (-23 LUFS). */ - rgi.track.gain = float(output_gain) / 256.0f + 5; - rgi.album.gain = float(output_gain) / 256.0f + 5; + rgi.track.gain = output_gain + 5; + rgi.album.gain = output_gain + 5; TagBuilder tag_builder; AddTagHandler h(tag_builder); From 78ee663660f5e38321f6bb66b4e66e1380888f37 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 16 Oct 2020 18:30:34 +0200 Subject: [PATCH 2/6] decoder/opus: move comment to `output_gain` field --- src/decoder/plugins/OpusDecoderPlugin.cxx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/decoder/plugins/OpusDecoderPlugin.cxx b/src/decoder/plugins/OpusDecoderPlugin.cxx index 80e13ae31..05200e07a 100644 --- a/src/decoder/plugins/OpusDecoderPlugin.cxx +++ b/src/decoder/plugins/OpusDecoderPlugin.cxx @@ -76,8 +76,9 @@ class MPDOpusDecoder final : public OggDecoder { opus_int16 *output_buffer = nullptr; /** - * The output gain from the Opus header. Initialized by - * OnOggBeginning(). + * The output gain from the Opus header in dB that should be + * applied unconditionally, but is often used specifically for + * ReplayGain. Initialized by OnOggBeginning(). */ float output_gain; @@ -250,9 +251,7 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet) rgi.Clear(); /** - * Output gain is a Q7.8 fixed point number in dB that should be, - * applied unconditionally, but is often used specifically for - * ReplayGain. Add 5dB to compensate for the different + * Add 5dB to compensate for the different * reference levels between ReplayGain (89dB) and EBU R128 (-23 LUFS). */ rgi.track.gain = output_gain + 5; From 1db533c8cfe2b76c6914d6ac3d490f5057611b35 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 16 Oct 2020 18:32:30 +0200 Subject: [PATCH 3/6] decoder/opus: move formula to EbuR128ToReplayGain() --- src/decoder/plugins/OpusDecoderPlugin.cxx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/decoder/plugins/OpusDecoderPlugin.cxx b/src/decoder/plugins/OpusDecoderPlugin.cxx index 05200e07a..4257b31e5 100644 --- a/src/decoder/plugins/OpusDecoderPlugin.cxx +++ b/src/decoder/plugins/OpusDecoderPlugin.cxx @@ -63,6 +63,17 @@ IsOpusTags(const ogg_packet &packet) noexcept return packet.bytes >= 8 && memcmp(packet.packet, "OpusTags", 8) == 0; } +/** + * Convert an EBU R128 value to ReplayGain. + */ +constexpr float +EbuR128ToReplayGain(float ebu_r128) noexcept +{ + /* add 5dB to compensate for the different reference levels + between ReplayGain (89dB) and EBU R128 (-23 LUFS) */ + return ebu_r128 + 5; +} + bool mpd_opus_init([[maybe_unused]] const ConfigBlock &block) { @@ -249,13 +260,7 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet) { ReplayGainInfo rgi; rgi.Clear(); - - /** - * Add 5dB to compensate for the different - * reference levels between ReplayGain (89dB) and EBU R128 (-23 LUFS). - */ - rgi.track.gain = output_gain + 5; - rgi.album.gain = output_gain + 5; + rgi.track.gain = rgi.album.gain = EbuR128ToReplayGain(output_gain); TagBuilder tag_builder; AddTagHandler h(tag_builder); From a0d43dd87f0979aaf42ed10dc40fffd2034adf0f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 16 Oct 2020 18:38:43 +0200 Subject: [PATCH 4/6] decoder/opus: submit output_gain even if there is no OpusTags packet --- NEWS | 2 ++ src/decoder/plugins/OpusDecoderPlugin.cxx | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/NEWS b/NEWS index e654211b3..dae8a13eb 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.22.1 (not yet released) +* decoder + - opus: apply the OpusHead output gain even if there is no EBU R128 tag * output - alsa: don't deadlock when the ALSA driver is buggy - jack, pulse: reduce the delay when stopping or pausing playback diff --git a/src/decoder/plugins/OpusDecoderPlugin.cxx b/src/decoder/plugins/OpusDecoderPlugin.cxx index 4257b31e5..e3022d8fc 100644 --- a/src/decoder/plugins/OpusDecoderPlugin.cxx +++ b/src/decoder/plugins/OpusDecoderPlugin.cxx @@ -123,6 +123,14 @@ class MPDOpusDecoder final : public OggDecoder { */ ogg_int64_t granulepos; + /** + * Was DecoderClient::SubmitReplayGain() called? We need to + * keep track of this, because it will usually be called by + * HandleTags(), but if there is no OpusTags packet, we need + * to submit our #output_gain value from the OpusHead. + */ + bool submitted_replay_gain = false; + public: explicit MPDOpusDecoder(DecoderReader &reader) :OggDecoder(reader) {} @@ -269,6 +277,7 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet) return; client.SubmitReplayGain(&rgi); + submitted_replay_gain = true; if (!tag_builder.empty()) { Tag tag = tag_builder.Commit(); @@ -283,6 +292,18 @@ MPDOpusDecoder::HandleAudio(const ogg_packet &packet) { assert(opus_decoder != nullptr); + if (!submitted_replay_gain) { + /* if we didn't see an OpusTags packet with EBU R128 + values, we still need to apply the output gain + value from the OpusHead packet; submit it as "track + gain" value */ + ReplayGainInfo rgi; + rgi.Clear(); + rgi.track.gain = EbuR128ToReplayGain(output_gain); + client.SubmitReplayGain(&rgi); + submitted_replay_gain = true; + } + int nframes = opus_decode(opus_decoder, (const unsigned char*)packet.packet, packet.bytes, From 31268ad7cd76cf4ceef4a9c6e2fb3ba7d0eea4be Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 16 Oct 2020 18:18:15 +0200 Subject: [PATCH 5/6] decoder/opus: fix track/album ReplayGain fallback Fixes regression by commit 23d5a2b8620cea69958d087fc7e13fe1e5adb83d - that commit always pretended that any Opus file has both track and album gain, and thus disabled the fallback to the other if one is not set. This patch changes the logic to only submit ReplayGain if at least one value is set, and apply the offset only to that value. If none is available, then the new check in HandleAudio() will submit only the output gain. Closes https://github.com/MusicPlayerDaemon/MPD/issues/977 --- NEWS | 1 + src/decoder/plugins/OpusDecoderPlugin.cxx | 13 ++++++++++--- src/decoder/plugins/OpusTags.cxx | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index dae8a13eb..07e13ff13 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.22.1 (not yet released) * decoder - opus: apply the OpusHead output gain even if there is no EBU R128 tag + - opus: fix track/album ReplayGain fallback * output - alsa: don't deadlock when the ALSA driver is buggy - jack, pulse: reduce the delay when stopping or pausing playback diff --git a/src/decoder/plugins/OpusDecoderPlugin.cxx b/src/decoder/plugins/OpusDecoderPlugin.cxx index e3022d8fc..0343e201c 100644 --- a/src/decoder/plugins/OpusDecoderPlugin.cxx +++ b/src/decoder/plugins/OpusDecoderPlugin.cxx @@ -268,7 +268,6 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet) { ReplayGainInfo rgi; rgi.Clear(); - rgi.track.gain = rgi.album.gain = EbuR128ToReplayGain(output_gain); TagBuilder tag_builder; AddTagHandler h(tag_builder); @@ -276,8 +275,16 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet) if (!ScanOpusTags(packet.packet, packet.bytes, &rgi, h)) return; - client.SubmitReplayGain(&rgi); - submitted_replay_gain = true; + if (rgi.IsDefined()) { + /* submit all valid EBU R128 values with output_gain + applied */ + if (rgi.track.IsDefined()) + rgi.track.gain += EbuR128ToReplayGain(output_gain); + if (rgi.album.IsDefined()) + rgi.album.gain += EbuR128ToReplayGain(output_gain); + client.SubmitReplayGain(&rgi); + submitted_replay_gain = true; + } if (!tag_builder.empty()) { Tag tag = tag_builder.Commit(); diff --git a/src/decoder/plugins/OpusTags.cxx b/src/decoder/plugins/OpusTags.cxx index c78586065..ee1d0cb22 100644 --- a/src/decoder/plugins/OpusTags.cxx +++ b/src/decoder/plugins/OpusTags.cxx @@ -61,7 +61,7 @@ ScanOneOpusTag(StringView name, StringView value, const char *endptr; const auto l = ParseInt64(value, &endptr, 10); if (endptr > value.begin() && endptr == value.end()) - rgi->track.gain += float(l) / 256.0f; + rgi->track.gain = float(l) / 256.0f; } else if (rgi != nullptr && name.EqualsIgnoreCase("R128_ALBUM_GAIN")) { /* R128_ALBUM_GAIN is a Q7.8 fixed point number in @@ -70,7 +70,7 @@ ScanOneOpusTag(StringView name, StringView value, const char *endptr; const auto l = ParseInt64(value, &endptr, 10); if (endptr > value.begin() && endptr == value.end()) - rgi->album.gain += float(l) / 256.0f; + rgi->album.gain = float(l) / 256.0f; } handler.OnPair(name, value); From a163beee6976638b61fadd4f788fdd947e070fb8 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 16 Oct 2020 18:53:46 +0200 Subject: [PATCH 6/6] python/build/libs.py: update CURL to 7.73.0 --- python/build/libs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/build/libs.py b/python/build/libs.py index 4886e8e19..7584caa16 100644 --- a/python/build/libs.py +++ b/python/build/libs.py @@ -377,8 +377,8 @@ ffmpeg = FfmpegProject( ) curl = AutotoolsProject( - 'http://curl.haxx.se/download/curl-7.72.0.tar.xz', - '0ded0808c4d85f2ee0db86980ae610cc9d165e9ca9da466196cc73c346513713', + 'http://curl.haxx.se/download/curl-7.73.0.tar.xz', + '7c4c7ca4ea88abe00fea4740dcf81075c031b1d0bb23aff2d5efde20a3c2408a', 'lib/libcurl.a', [ '--disable-shared', '--enable-static',