Commit ac8e5be9 authored by Max Kellermann's avatar Max Kellermann

decoder/opus: support replay gain

Parse the R128_TRACK_GAIN comment string.
parent c7695253
...@@ -282,12 +282,18 @@ MPDOpusDecoder::HandleBOS(const ogg_packet &packet) ...@@ -282,12 +282,18 @@ MPDOpusDecoder::HandleBOS(const ogg_packet &packet)
inline DecoderCommand inline DecoderCommand
MPDOpusDecoder::HandleTags(const ogg_packet &packet) MPDOpusDecoder::HandleTags(const ogg_packet &packet)
{ {
replay_gain_info rgi;
replay_gain_info_init(&rgi);
TagBuilder tag_builder; TagBuilder tag_builder;
DecoderCommand cmd; DecoderCommand cmd;
if (ScanOpusTags(packet.packet, packet.bytes, if (ScanOpusTags(packet.packet, packet.bytes,
&rgi,
&add_tag_handler, &tag_builder) && &add_tag_handler, &tag_builder) &&
!tag_builder.IsEmpty()) { !tag_builder.IsEmpty()) {
decoder_replay_gain(decoder, &rgi);
Tag tag; Tag tag;
tag_builder.Commit(tag); tag_builder.Commit(tag);
cmd = decoder_tag(decoder, input_stream, std::move(tag)); cmd = decoder_tag(decoder, input_stream, std::move(tag));
...@@ -439,6 +445,7 @@ mpd_opus_scan_stream(InputStream &is, ...@@ -439,6 +445,7 @@ mpd_opus_scan_stream(InputStream &is,
break; break;
else if (IsOpusTags(packet)) { else if (IsOpusTags(packet)) {
if (!ScanOpusTags(packet.packet, packet.bytes, if (!ScanOpusTags(packet.packet, packet.bytes,
nullptr,
handler, handler_ctx)) handler, handler_ctx))
result = false; result = false;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "XiphTags.hxx" #include "XiphTags.hxx"
#include "tag/TagHandler.hxx" #include "tag/TagHandler.hxx"
#include "tag/Tag.hxx" #include "tag/Tag.hxx"
#include "ReplayGainInfo.hxx"
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
...@@ -41,8 +42,19 @@ ParseOpusTagName(const char *name) ...@@ -41,8 +42,19 @@ ParseOpusTagName(const char *name)
static void static void
ScanOneOpusTag(const char *name, const char *value, ScanOneOpusTag(const char *name, const char *value,
replay_gain_info *rgi,
const struct tag_handler *handler, void *ctx) const struct tag_handler *handler, void *ctx)
{ {
if (rgi != nullptr && strcmp(name, "R128_TRACK_GAIN") == 0) {
/* R128_TRACK_GAIN is a Q7.8 fixed point number in
dB */
char *endptr;
long l = strtol(value, &endptr, 10);
if (endptr > value && *endptr == 0)
rgi->tuples[REPLAY_GAIN_TRACK].gain = double(l) / 256.;
}
tag_handler_invoke_pair(handler, ctx, name, value); tag_handler_invoke_pair(handler, ctx, name, value);
if (handler->tag != nullptr) { if (handler->tag != nullptr) {
...@@ -54,6 +66,7 @@ ScanOneOpusTag(const char *name, const char *value, ...@@ -54,6 +66,7 @@ ScanOneOpusTag(const char *name, const char *value,
bool bool
ScanOpusTags(const void *data, size_t size, ScanOpusTags(const void *data, size_t size,
replay_gain_info *rgi,
const struct tag_handler *handler, void *ctx) const struct tag_handler *handler, void *ctx)
{ {
OpusReader r(data, size); OpusReader r(data, size);
...@@ -79,7 +92,7 @@ ScanOpusTags(const void *data, size_t size, ...@@ -79,7 +92,7 @@ ScanOpusTags(const void *data, size_t size,
if (eq != nullptr && eq > p) { if (eq != nullptr && eq > p) {
*eq = 0; *eq = 0;
ScanOneOpusTag(p, eq + 1, handler, ctx); ScanOneOpusTag(p, eq + 1, rgi, handler, ctx);
} }
delete[] p; delete[] p;
......
...@@ -24,8 +24,11 @@ ...@@ -24,8 +24,11 @@
#include <stddef.h> #include <stddef.h>
struct replay_gain_info;
bool bool
ScanOpusTags(const void *data, size_t size, ScanOpusTags(const void *data, size_t size,
replay_gain_info *rgi,
const struct tag_handler *handler, void *ctx); const struct tag_handler *handler, void *ctx);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment