From e80c7243009d369b587a7fc8c7ebd6640280a157 Mon Sep 17 00:00:00 2001 From: nift4 Date: Fri, 10 Oct 2025 22:46:36 +0200 Subject: [PATCH 01/14] Parse ReplayGain data from LAME Xing/Info header see http://gabriel.mp3-tech.org/mp3infotag.html#replaygain --- .../media3/extractor/mp3/Mp3Extractor.java | 10 +- .../extractor/mp3/Mp3InfoReplayGain.java | 227 ++++++++++++++++++ .../media3/extractor/mp3/XingFrame.java | 42 +++- ...ar-vbr-xing-header-replaygain-accurate.mp3 | Bin 0 -> 45357 bytes .../bear-vbr-xing-header-replaygain-fast.mp3 | Bin 0 -> 45357 bytes 5 files changed, 272 insertions(+), 7 deletions(-) create mode 100644 libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java create mode 100644 libraries/test_data/src/test/assets/media/mp3/bear-vbr-xing-header-replaygain-accurate.mp3 create mode 100644 libraries/test_data/src/test/assets/media/mp3/bear-vbr-xing-header-replaygain-fast.mp3 diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java index b0576bed724..4d8f8665ee6 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java @@ -177,6 +177,7 @@ public final class Mp3Extractor implements Extractor { private int synchronizedHeaderData; @Nullable private Metadata metadata; + @Nullable private Metadata infoMetadata; private long basisTimeUs; private long samplesRead; private long firstSamplePosition; @@ -293,6 +294,12 @@ private int readInternal(ExtractorInput input) throws IOException { if (seeker == null) { seeker = computeSeeker(input); extractorOutput.seekMap(seeker); + @Nullable Metadata finalMetadata = (flags & FLAG_DISABLE_ID3_METADATA) != 0 ? null : metadata; + if (finalMetadata != null) { + finalMetadata = finalMetadata.copyWithAppendedEntriesFrom(infoMetadata); + } else { + finalMetadata = infoMetadata; + } Format.Builder format = new Format.Builder() .setContainerMimeType(MimeTypes.AUDIO_MPEG) @@ -302,7 +309,7 @@ private int readInternal(ExtractorInput input) throws IOException { .setSampleRate(synchronizedHeader.sampleRate) .setEncoderDelay(gaplessInfoHolder.encoderDelay) .setEncoderPadding(gaplessInfoHolder.encoderPadding) - .setMetadata((flags & FLAG_DISABLE_ID3_METADATA) != 0 ? null : metadata); + .setMetadata(finalMetadata); if (seeker.getAverageBitrate() != C.RATE_UNSET_INT) { format.setAverageBitrate(seeker.getAverageBitrate()); } @@ -583,6 +590,7 @@ private Seeker maybeReadSeekFrame(ExtractorInput input) throws IOException { gaplessInfoHolder.encoderDelay = xingFrame.encoderDelay; gaplessInfoHolder.encoderPadding = xingFrame.encoderPadding; } + infoMetadata = xingFrame.getMetadata(); long startPosition = input.getPosition(); if (input.getLength() != C.LENGTH_UNSET && xingFrame.dataSize != C.LENGTH_UNSET diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java new file mode 100644 index 00000000000..f1c6f473e76 --- /dev/null +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java @@ -0,0 +1,227 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.media3.extractor.mp3; + +import static java.lang.annotation.ElementType.TYPE_USE; + +import android.annotation.SuppressLint; +import androidx.annotation.IntDef; +import androidx.media3.common.Metadata; +import androidx.media3.common.util.UnstableApi; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Objects; + +/** Representation of the ReplayGain data stored in a LAME Xing or Info frame. */ +@UnstableApi +public final class Mp3InfoReplayGain implements Metadata.Entry { + /** + * 32 bit floating point "Peak signal amplitude". + * + *

1.0 is maximal signal amplitude store-able in decoding format. 0.8 is 80% of maximal signal + * amplitude store-able in decoding format. 1.5 is 150% of maximal signal amplitude store-able in + * decoding format. + * + *

A value above 1.0 can occur for example due to "true peak" measurement. A value of 0.0 means + * the peak signal amplitude is unknown. + */ + public final float peak; + + /** A gain field can store one gain adjustment with name and originator metadata. */ + public static final class GainField { + /** This gain field contains no valid data, and should be ignored. */ + public static final int NAME_INVALID = 0; + + /** + * This gain field contains a gain adjustment that will make all the tracks sound equally loud + * (as they do on the radio, hence the name!). If the ReplayGain is calculated on a + * track-by-track basis (i.e. an individual ReplayGain calculation is carried out for each + * track), this will be the result. + */ + public static final int NAME_RADIO = 1; + + /** + * The problem with the "Radio" setting is that tracks which should be quiet will be brought up + * to the level of all the rest. + * + *

To solve this problem, the "Audiophile" setting represents the ideal listening gain for + * each track. ReplayGain can have a good guess at this too, by reading the entire CD, and + * calculating a single gain adjustment for the whole disc. This works because quiet tracks then + * stay quieter than the rest, since the gain won't be changed for each track. It still solves + * the basic problem (annoying, unwanted level differences between discs) because quiet or loud + * discs are still adjusted overall. + * + *

Where ReplayGain will fail is if you have an entire CD of quiet music. It will bring it up + * to an average level. This is why the "Audiophile" Replay Gain adjustment must be user + * adjustable. The ReplayGain whole disc value represents a good guess, and should be stored in + * the file. Later, the user can tweak it if required. If the file has originated from the + * artist, then the "Audiophile" setting can be specified by the artist. Naturally, the user is + * free to change the value if they desire. + */ + public static final int NAME_AUDIOPHILE = 2; + + /** The origin of this gain adjustment is not known. */ + public static final int ORIGINATOR_UNKNOWN = 0; + + /** This gain adjustment was manually determined by the artist. */ + public static final int ORIGINATOR_ARTIST = 1; + + /** This gain adjustment was manually determined by the user. */ + public static final int ORIGINATOR_USER = 2; + + /** This gain adjustment was automatically determined by the ReplayGain algorithm. */ + public static final int ORIGINATOR_REPLAYGAIN = 3; + + /** This gain adjustment was automatically determined by a simple RMS algorithm. */ + public static final int ORIGINATOR_SIMPLE_RMS = 4; + + /** Creates a gain field from already unpacked values. */ + public GainField(@Name int name, @Originator int originator, float gain) { + this.name = name; + this.originator = originator; + this.gain = gain; + } + + /** Creates a gain field from the packed representation. */ + @SuppressLint("WrongConstant") + public GainField(short field) { + this.name = (field >> 13) & 7; + this.originator = (field >> 10) & 7; + this.gain = ((field & 0x1ff) * ((field & 0x200) != 0 ? -1 : 1)) / 10f; + } + + @Documented + @Retention(RetentionPolicy.SOURCE) + @Target(TYPE_USE) + @IntDef({NAME_INVALID, NAME_RADIO, NAME_AUDIOPHILE}) + public @interface Name {} + + @Documented + @Retention(RetentionPolicy.SOURCE) + @Target(TYPE_USE) + @IntDef({ + ORIGINATOR_UNKNOWN, + ORIGINATOR_ARTIST, + ORIGINATOR_USER, + ORIGINATOR_REPLAYGAIN, + ORIGINATOR_SIMPLE_RMS + }) + public @interface Originator {} + + /** + * Name/type of the gain field. + * + *

If equal to {@link #NAME_INVALID}, or an unknown name, the entire {@link GainField} should + * be ignored. + */ + public final @Name int name; + + /** + * Originator of the gain field, i.e. who determined the value / in what way it was determined. + * + *

Either a human (user / artist) set the value according to their preferences, or an + * algorithm like ReplayGain or simple RMS average was used to determine it. + */ + public final @Originator int originator; + + /** + * Absolute gain adjustment in decibels. + * + *

Positive values mean the signal should be amplified, negative values mean it should be + * attenuated. + * + *

Due to limitations of the storage format, this is only accurate to the first decimal + * place. + */ + public final float gain; + + /** + * @return Whether the name field is set to a valid value, hence, whether this gain field should + * be considered or not. If false, the entire field should be ignored. + */ + public boolean isValid() { + return name == NAME_RADIO || name == NAME_AUDIOPHILE; + } + + @Override + public String toString() { + return "GainField{" + "name=" + name + ", originator=" + originator + ", gain=" + gain + '}'; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof GainField)) { + return false; + } + GainField gainField = (GainField) o; + return name == gainField.name + && originator == gainField.originator + && Float.compare(gain, gainField.gain) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(name, originator, gain); + } + } + + /** The first of two gain fields in the LAME MP3 Info header. */ + public GainField field1; + + /** The second of two gain fields in the LAME MP3 Info header. */ + public GainField field2; + + /** Creates the gain field from already unpacked values. */ + public Mp3InfoReplayGain(float peak, GainField field1, GainField field2) { + this.peak = peak; + this.field1 = field1; + this.field2 = field2; + } + + /** Creates the gain fields from the packed representation. */ + public Mp3InfoReplayGain(float peak, short field1, short field2) { + this(peak, new GainField(field1), new GainField(field2)); + } + + @Override + public String toString() { + return "ReplayGain Xing/Info: " + + "peak=" + + peak + + ", field 1=" + + field1 + + ", field 2=" + + field2; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Mp3InfoReplayGain)) { + return false; + } + Mp3InfoReplayGain that = (Mp3InfoReplayGain) o; + return Float.compare(peak, that.peak) == 0 + && Objects.equals(field1, that.field1) + && Objects.equals(field2, that.field2); + } + + @Override + public int hashCode() { + return Objects.hash(peak, field1, field2); + } +} diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java index 421f05ac200..f5ef33a6699 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java @@ -17,6 +17,7 @@ import androidx.annotation.Nullable; import androidx.media3.common.C; +import androidx.media3.common.Metadata; import androidx.media3.common.util.ParsableByteArray; import androidx.media3.common.util.Util; import androidx.media3.extractor.MpegAudioUtil; @@ -35,6 +36,9 @@ */ public final long dataSize; + /** ReplayGain data. Only present if this frame is an Info or the LAME variant of a Xing frame. */ + public final @Nullable Mp3InfoReplayGain replayGain; + /** * The number of samples to skip at the start of the stream, or {@link C#LENGTH_UNSET} if not * present in the header. @@ -58,12 +62,14 @@ private XingFrame( long frameCount, long dataSize, @Nullable long[] tableOfContents, + @Nullable Mp3InfoReplayGain replayGain, int encoderDelay, int encoderPadding) { this.header = new MpegAudioUtil.Header(header); this.frameCount = frameCount; this.dataSize = dataSize; this.tableOfContents = tableOfContents; + this.replayGain = replayGain; this.encoderDelay = encoderDelay; this.encoderPadding = encoderPadding; } @@ -98,23 +104,39 @@ public static XingFrame parse(MpegAudioUtil.Header mpegAudioHeader, ParsableByte frame.skipBytes(4); // Quality indicator } + @Nullable Mp3InfoReplayGain replayGain; int encoderDelay; int encoderPadding; - // Skip: version string (9), revision & VBR method (1), lowpass filter (1), replay gain (8), - // encoding flags & ATH type (1), bitrate (1). - int bytesToSkipBeforeEncoderDelayAndPadding = 9 + 1 + 1 + 8 + 1 + 1; - if (frame.bytesLeft() >= bytesToSkipBeforeEncoderDelayAndPadding + 3) { - frame.skipBytes(bytesToSkipBeforeEncoderDelayAndPadding); + // Skip: version string (9), revision & VBR method (1), lowpass filter (1). + int bytesToSkipBeforeReplayGain = 9 + 1 + 1; + // Skip: encoding flags & ATH type (1), bitrate (1). + int bytesToSkipAfterReplayGain = 1 + 1; + // And account for values we parse, ReplayGain (8) and encoder delay & padding (3). + if (frame.bytesLeft() >= bytesToSkipBeforeReplayGain + 8 + bytesToSkipAfterReplayGain + 3) { + frame.skipBytes(bytesToSkipBeforeReplayGain); + float peak = frame.readFloat(); + short field1 = frame.readShort(); + short field2 = frame.readShort(); + replayGain = new Mp3InfoReplayGain(peak, field1, field2); + + frame.skipBytes(bytesToSkipAfterReplayGain); int encoderDelayAndPadding = frame.readUnsignedInt24(); encoderDelay = (encoderDelayAndPadding & 0xFFF000) >> 12; encoderPadding = (encoderDelayAndPadding & 0xFFF); } else { + replayGain = null; encoderDelay = C.LENGTH_UNSET; encoderPadding = C.LENGTH_UNSET; } return new XingFrame( - mpegAudioHeader, frameCount, dataSize, tableOfContents, encoderDelay, encoderPadding); + mpegAudioHeader, + frameCount, + dataSize, + tableOfContents, + replayGain, + encoderDelay, + encoderPadding); } /** @@ -132,4 +154,12 @@ public long computeDurationUs() { return Util.sampleCountToDurationUs( (frameCount * header.samplesPerFrame) - 1, header.sampleRate); } + + /** Provide the metadata derived from this Xing frame, such as ReplayGain data. */ + public @Nullable Metadata getMetadata() { + if (replayGain != null) { + return new Metadata(replayGain); + } + return null; + } } diff --git a/libraries/test_data/src/test/assets/media/mp3/bear-vbr-xing-header-replaygain-accurate.mp3 b/libraries/test_data/src/test/assets/media/mp3/bear-vbr-xing-header-replaygain-accurate.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0f2e3fa0294fc106f5f062a2024f3fea4d86af37 GIT binary patch literal 45357 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 literal 0 HcmV?d00001 diff --git a/libraries/test_data/src/test/assets/media/mp3/bear-vbr-xing-header-replaygain-fast.mp3 b/libraries/test_data/src/test/assets/media/mp3/bear-vbr-xing-header-replaygain-fast.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..ae9d87ab25c4441e4cc9afb2ec4ffc4cfcda29d8 GIT binary patch literal 45357 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 Date: Fri, 2 Jan 2026 17:30:39 +0000 Subject: [PATCH 02/14] Update test dump files --- .../extractor/mp3/Mp3ExtractorTest.java | 24 + .../mp3/bear-id3-numeric-genre.mp3.0.dump | 2 +- .../mp3/bear-id3-numeric-genre.mp3.1.dump | 2 +- .../mp3/bear-id3-numeric-genre.mp3.2.dump | 2 +- .../mp3/bear-id3-numeric-genre.mp3.3.dump | 2 +- ...-id3-numeric-genre.mp3.unknown_length.dump | 2 +- .../mp3/bear-id3.mp3.id3-disabled.0.dump | 1 + .../mp3/bear-id3.mp3.id3-disabled.1.dump | 1 + .../mp3/bear-id3.mp3.id3-disabled.2.dump | 1 + .../mp3/bear-id3.mp3.id3-disabled.3.dump | 1 + ...r-id3.mp3.id3-disabled.unknown_length.dump | 1 + .../mp3/bear-id3.mp3.id3-enabled.0.dump | 2 +- .../mp3/bear-id3.mp3.id3-enabled.1.dump | 2 +- .../mp3/bear-id3.mp3.id3-enabled.2.dump | 2 +- .../mp3/bear-id3.mp3.id3-enabled.3.dump | 2 +- ...ar-id3.mp3.id3-enabled.unknown_length.dump | 2 +- .../bear-vbr-xing-header-no-toc.mp3.0.dump | 2 +- ...eader-no-toc.mp3.cbr-seeking-always.0.dump | 2 +- ...eader-no-toc.mp3.cbr-seeking-always.1.dump | 2 +- ...eader-no-toc.mp3.cbr-seeking-always.2.dump | 2 +- ...eader-no-toc.mp3.cbr-seeking-always.3.dump | 2 +- ...mp3.cbr-seeking-always.unknown_length.dump | 2 +- ...-xing-header-no-toc.mp3.cbr-seeking.0.dump | 2 +- ...-xing-header-no-toc.mp3.cbr-seeking.1.dump | 2 +- ...-xing-header-no-toc.mp3.cbr-seeking.2.dump | 2 +- ...-xing-header-no-toc.mp3.cbr-seeking.3.dump | 2 +- ...no-toc.mp3.cbr-seeking.unknown_length.dump | 2 +- ...ing-header-no-toc.mp3.index-seeking.0.dump | 2 +- ...ing-header-no-toc.mp3.index-seeking.1.dump | 2 +- ...ing-header-no-toc.mp3.index-seeking.2.dump | 2 +- ...ing-header-no-toc.mp3.index-seeking.3.dump | 2 +- ...-toc.mp3.index-seeking.unknown_length.dump | 2 +- ...xing-header-no-toc.mp3.unknown_length.dump | 2 +- ...xing-header-replaygain-accurate.mp3.0.dump | 491 ++++++++++++++++++ ...xing-header-replaygain-accurate.mp3.1.dump | 339 ++++++++++++ ...xing-header-replaygain-accurate.mp3.2.dump | 183 +++++++ ...xing-header-replaygain-accurate.mp3.3.dump | 27 + ...eplaygain-accurate.mp3.unknown_length.dump | 491 ++++++++++++++++++ ...vbr-xing-header-replaygain-fast.mp3.0.dump | 491 ++++++++++++++++++ ...vbr-xing-header-replaygain-fast.mp3.1.dump | 339 ++++++++++++ ...vbr-xing-header-replaygain-fast.mp3.2.dump | 183 +++++++ ...vbr-xing-header-replaygain-fast.mp3.3.dump | 27 + ...er-replaygain-fast.mp3.unknown_length.dump | 491 ++++++++++++++++++ .../mp3/bear-vbr-xing-header.mp3.0.dump | 2 +- .../mp3/bear-vbr-xing-header.mp3.1.dump | 2 +- .../mp3/bear-vbr-xing-header.mp3.2.dump | 2 +- .../mp3/bear-vbr-xing-header.mp3.3.dump | 2 +- ...ar-vbr-xing-header.mp3.unknown_length.dump | 2 +- ...test-cbr-info-header-pcut-frame.mp3.0.dump | 2 +- ...test-cbr-info-header-pcut-frame.mp3.1.dump | 2 +- ...test-cbr-info-header-pcut-frame.mp3.2.dump | 2 +- ...test-cbr-info-header-pcut-frame.mp3.3.dump | 2 +- ...-header-pcut-frame.mp3.unknown_length.dump | 2 +- .../mp3/test-cbr-info-header.mp3.0.dump | 2 +- .../mp3/test-cbr-info-header.mp3.1.dump | 2 +- .../mp3/test-cbr-info-header.mp3.2.dump | 2 +- .../mp3/test-cbr-info-header.mp3.3.dump | 2 +- ...st-cbr-info-header.mp3.unknown_length.dump | 2 +- 58 files changed, 3133 insertions(+), 42 deletions(-) create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.0.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.1.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.2.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.3.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.unknown_length.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.0.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.1.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.2.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.3.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.unknown_length.dump diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java index b30ca2127ad..df47793f7e3 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java @@ -318,6 +318,30 @@ public void sampleWith200kBGarbagePrefix_sniffingFailsAfterPeeking128kB() throws /* expectedResult= */ false); } + @Test + public void sampleWithLameReplayGainFast( + @TestParameter(valuesProvider = ExtractorAsserts.ConfigProvider.class) + ExtractorAsserts.SimulationConfig simulationConfig) + throws Exception { + ExtractorAsserts.assertBehavior( + Mp3Extractor::new, + "media/mp3/bear-vbr-xing-header-replaygain-fast.mp3", + /* peekLimit= */ 1201, + simulationConfig); + } + + @Test + public void sampleWithLameReplayGainAccurate( + @TestParameter(valuesProvider = ExtractorAsserts.ConfigProvider.class) + ExtractorAsserts.SimulationConfig simulationConfig) + throws Exception { + ExtractorAsserts.assertBehavior( + Mp3Extractor::new, + "media/mp3/bear-vbr-xing-header-replaygain-accurate.mp3", + /* peekLimit= */ 1201, + simulationConfig); + } + @Nullable private static String getDumpFilePath(String inputFilePath, Enum flagConfig) { String configName = flagConfig.name(); diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.0.dump index bf3a6e0e45f..bd6f14987d2 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.0.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9]] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.1.dump index eafac7a6cca..356913d9f15 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.1.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9]] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 943000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.2.dump index 3f0892a6b4b..ee2e6b02e96 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.2.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9]] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 1879000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.3.dump index fe26e0b0756..d7f73b8d220 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.3.dump @@ -18,5 +18,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9]] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.unknown_length.dump index bf3a6e0e45f..bd6f14987d2 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.unknown_length.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9]] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.0.dump index 8b84b79047d..f7c05d68670 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.0.dump @@ -18,6 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 + metadata = entries=[ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.1.dump index 2a75c2bb3f7..17a123908d4 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.1.dump @@ -18,6 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 + metadata = entries=[ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 943000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.2.dump index 8cf7cddb906..2dc09c77b20 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.2.dump @@ -18,6 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 + metadata = entries=[ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 1879000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.3.dump index 8f32b9426a9..cd0b3284c92 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.3.dump @@ -18,4 +18,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 + metadata = entries=[ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.unknown_length.dump index 8b84b79047d..f7c05d68670 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.unknown_length.dump @@ -18,6 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 + metadata = entries=[ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.0.dump index 069b98e317f..59aa105956e 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.0.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore]] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.1.dump index 5059438ec55..1e058e42755 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.1.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore]] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 943000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.2.dump index 16419ce6395..cf3a8571e6f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.2.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore]] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 1879000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.3.dump index a0273aac08a..89e1a0b5728 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.3.dump @@ -18,5 +18,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore]] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.unknown_length.dump index 069b98e317f..59aa105956e 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.unknown_length.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore]] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.0.dump index 5cfd3266218..63ed6bdec24 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.0.dump @@ -16,7 +16,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.0.dump index deb9adcbd9d..a3b9c1c9051 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.1.dump index 8cebd97c777..79ababb2d7f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 943055 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.2.dump index ee5e5a6f7d0..3c8b7abd4ae 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 1879045 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.3.dump index daec3f68336..068c2ec81c0 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.3.dump @@ -19,5 +19,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.unknown_length.dump index deb9adcbd9d..a3b9c1c9051 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.0.dump index deb9adcbd9d..a3b9c1c9051 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.1.dump index 8cebd97c777..79ababb2d7f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 943055 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.2.dump index ee5e5a6f7d0..3c8b7abd4ae 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 1879045 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.3.dump index daec3f68336..068c2ec81c0 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.3.dump @@ -19,5 +19,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.unknown_length.dump index deb9adcbd9d..a3b9c1c9051 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.0.dump index c1fb30310ef..706bde3a36f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.0.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.1.dump index 07aaf5caa82..1883df980be 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.1.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 840000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.2.dump index 62fdef977d9..102d3dfe463 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.2.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 1800000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.3.dump index 9ec7986fb60..08aaa060442 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.3.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 2760000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.unknown_length.dump index c1fb30310ef..706bde3a36f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.unknown_length.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.unknown_length.dump index 5cfd3266218..63ed6bdec24 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.unknown_length.dump @@ -16,7 +16,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.0.dump new file mode 100644 index 00000000000..9aa7068113c --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.0.dump @@ -0,0 +1,491 @@ +seekMap: + isSeekable = true + duration = 2807978 + getPosition(0) = [[timeUs=0, position=429]] + getPosition(1) = [[timeUs=0, position=429], [timeUs=23999, position=813]] + getPosition(1403989) = [[timeUs=1391989, position=22701], [timeUs=1415988, position=23085]] + getPosition(2807978) = [[timeUs=2783978, position=44973]] +numberOfTracks = 1 +track 0: + total output bytes = 44928 + sample count = 117 + track duration = 2807978 + format 0: + averageBitrate = 128001 + containerMimeType = audio/mpeg + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 48000 + encoderDelay = 576 + encoderPadding = 576 + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=GainField{name=0, originator=0, gain=0.0}] + sample 0: + time = 0 + flags = 1 + data = length 384, hash D3A746E7 + sample 1: + time = 24000 + flags = 1 + data = length 384, hash F1E9E3E + sample 2: + time = 48000 + flags = 1 + data = length 384, hash 456DA228 + sample 3: + time = 72000 + flags = 1 + data = length 384, hash CDB09F78 + sample 4: + time = 96000 + flags = 1 + data = length 384, hash 5BFF9C1A + sample 5: + time = 120000 + flags = 1 + data = length 384, hash 861FDAA7 + sample 6: + time = 144000 + flags = 1 + data = length 384, hash 1FE36A4D + sample 7: + time = 168000 + flags = 1 + data = length 384, hash 4DD5C0F4 + sample 8: + time = 192000 + flags = 1 + data = length 384, hash D64A8BC6 + sample 9: + time = 216000 + flags = 1 + data = length 384, hash E20D4988 + sample 10: + time = 240000 + flags = 1 + data = length 384, hash ED2BF624 + sample 11: + time = 264000 + flags = 1 + data = length 384, hash 60E5ABBC + sample 12: + time = 288000 + flags = 1 + data = length 384, hash 404244BF + sample 13: + time = 312000 + flags = 1 + data = length 384, hash C65FF8C1 + sample 14: + time = 336000 + flags = 1 + data = length 384, hash 42386869 + sample 15: + time = 360000 + flags = 1 + data = length 384, hash 592F129A + sample 16: + time = 384000 + flags = 1 + data = length 384, hash 299ACDD7 + sample 17: + time = 408000 + flags = 1 + data = length 384, hash 8FF937AC + sample 18: + time = 432000 + flags = 1 + data = length 384, hash 4B5C2884 + sample 19: + time = 456000 + flags = 1 + data = length 384, hash 862D22F1 + sample 20: + time = 480000 + flags = 1 + data = length 384, hash 49AFE67D + sample 21: + time = 504000 + flags = 1 + data = length 384, hash 420EFE5F + sample 22: + time = 528000 + flags = 1 + data = length 384, hash 52759113 + sample 23: + time = 552000 + flags = 1 + data = length 384, hash 880C2AB2 + sample 24: + time = 576000 + flags = 1 + data = length 384, hash 1F7E786A + sample 25: + time = 600000 + flags = 1 + data = length 384, hash DF5D2BCF + sample 26: + time = 624000 + flags = 1 + data = length 384, hash D4020EB3 + sample 27: + time = 648000 + flags = 1 + data = length 384, hash BF6D1CA6 + sample 28: + time = 672000 + flags = 1 + data = length 384, hash 68B200EE + sample 29: + time = 696000 + flags = 1 + data = length 384, hash A71C4AFF + sample 30: + time = 720000 + flags = 1 + data = length 384, hash C36CA276 + sample 31: + time = 744000 + flags = 1 + data = length 384, hash 5AB9C9AA + sample 32: + time = 768000 + flags = 1 + data = length 384, hash CAC81110 + sample 33: + time = 792000 + flags = 1 + data = length 384, hash B45D0135 + sample 34: + time = 816000 + flags = 1 + data = length 384, hash 9F0FF1E6 + sample 35: + time = 840000 + flags = 1 + data = length 384, hash F3F425FD + sample 36: + time = 864000 + flags = 1 + data = length 384, hash 15C4DA8 + sample 37: + time = 888000 + flags = 1 + data = length 384, hash 9B5D1E2 + sample 38: + time = 912000 + flags = 1 + data = length 384, hash 40914CAF + sample 39: + time = 936000 + flags = 1 + data = length 384, hash F7EFB71E + sample 40: + time = 960000 + flags = 1 + data = length 384, hash 53FBE77C + sample 41: + time = 984000 + flags = 1 + data = length 384, hash 77E58178 + sample 42: + time = 1008000 + flags = 1 + data = length 384, hash E3B86048 + sample 43: + time = 1032000 + flags = 1 + data = length 384, hash 6E64349 + sample 44: + time = 1056000 + flags = 1 + data = length 384, hash AC0B5E18 + sample 45: + time = 1080000 + flags = 1 + data = length 384, hash 7B4CE779 + sample 46: + time = 1104000 + flags = 1 + data = length 384, hash 50D10931 + sample 47: + time = 1128000 + flags = 1 + data = length 384, hash F0D97D3E + sample 48: + time = 1152000 + flags = 1 + data = length 384, hash ED786460 + sample 49: + time = 1176000 + flags = 1 + data = length 384, hash 435543F4 + sample 50: + time = 1200000 + flags = 1 + data = length 384, hash 523ED198 + sample 51: + time = 1224000 + flags = 1 + data = length 384, hash 705705D3 + sample 52: + time = 1248000 + flags = 1 + data = length 384, hash 4A95F442 + sample 53: + time = 1272000 + flags = 1 + data = length 384, hash 56D7EF4B + sample 54: + time = 1296000 + flags = 1 + data = length 384, hash B47AAC17 + sample 55: + time = 1320000 + flags = 1 + data = length 384, hash 38E76A4D + sample 56: + time = 1344000 + flags = 1 + data = length 384, hash ADF5E978 + sample 57: + time = 1368000 + flags = 1 + data = length 384, hash 349125C2 + sample 58: + time = 1392000 + flags = 1 + data = length 384, hash D69B3903 + sample 59: + time = 1416000 + flags = 1 + data = length 384, hash 852DA91C + sample 60: + time = 1440000 + flags = 1 + data = length 384, hash 21F87C6E + sample 61: + time = 1464000 + flags = 1 + data = length 384, hash 68686E41 + sample 62: + time = 1488000 + flags = 1 + data = length 384, hash 4DAC9F6A + sample 63: + time = 1512000 + flags = 1 + data = length 384, hash B5CA6FCF + sample 64: + time = 1536000 + flags = 1 + data = length 384, hash 9B7216B3 + sample 65: + time = 1560000 + flags = 1 + data = length 384, hash AC7162DA + sample 66: + time = 1584000 + flags = 1 + data = length 384, hash 545A4B9C + sample 67: + time = 1608000 + flags = 1 + data = length 384, hash 380FA5D4 + sample 68: + time = 1632000 + flags = 1 + data = length 384, hash 53BF79E9 + sample 69: + time = 1656000 + flags = 1 + data = length 384, hash FE2460DB + sample 70: + time = 1680000 + flags = 1 + data = length 384, hash 2525E09 + sample 71: + time = 1704000 + flags = 1 + data = length 384, hash ECCB42AA + sample 72: + time = 1728000 + flags = 1 + data = length 384, hash 1E5EC5FA + sample 73: + time = 1752000 + flags = 1 + data = length 384, hash C2597D09 + sample 74: + time = 1776000 + flags = 1 + data = length 384, hash 32CD263E + sample 75: + time = 1800000 + flags = 1 + data = length 384, hash 6B3A0DC7 + sample 76: + time = 1824000 + flags = 1 + data = length 384, hash 5155B353 + sample 77: + time = 1848000 + flags = 1 + data = length 384, hash 220C783 + sample 78: + time = 1872000 + flags = 1 + data = length 384, hash E0925905 + sample 79: + time = 1896000 + flags = 1 + data = length 384, hash 824C0D02 + sample 80: + time = 1920000 + flags = 1 + data = length 384, hash 5166F8F3 + sample 81: + time = 1944000 + flags = 1 + data = length 384, hash B5F38EE6 + sample 82: + time = 1968000 + flags = 1 + data = length 384, hash 659E483F + sample 83: + time = 1992000 + flags = 1 + data = length 384, hash A022EFCB + sample 84: + time = 2016000 + flags = 1 + data = length 384, hash 93DCF4B5 + sample 85: + time = 2040000 + flags = 1 + data = length 384, hash C965128 + sample 86: + time = 2064000 + flags = 1 + data = length 384, hash 6FD595F4 + sample 87: + time = 2088000 + flags = 1 + data = length 384, hash BF6CDB31 + sample 88: + time = 2112000 + flags = 1 + data = length 384, hash 67C738C0 + sample 89: + time = 2136000 + flags = 1 + data = length 384, hash BCFCD1CC + sample 90: + time = 2160000 + flags = 1 + data = length 384, hash A4A85D04 + sample 91: + time = 2184000 + flags = 1 + data = length 384, hash 6CD26641 + sample 92: + time = 2208000 + flags = 1 + data = length 384, hash 53817862 + sample 93: + time = 2232000 + flags = 1 + data = length 384, hash 1C98DD10 + sample 94: + time = 2256000 + flags = 1 + data = length 384, hash 5B8EE2C9 + sample 95: + time = 2280000 + flags = 1 + data = length 384, hash 227883D0 + sample 96: + time = 2304000 + flags = 1 + data = length 384, hash 50267C46 + sample 97: + time = 2328000 + flags = 1 + data = length 384, hash F02EA205 + sample 98: + time = 2352000 + flags = 1 + data = length 384, hash ED7BE6DF + sample 99: + time = 2376000 + flags = 1 + data = length 384, hash AEE4E608 + sample 100: + time = 2400000 + flags = 1 + data = length 384, hash 8EA81A05 + sample 101: + time = 2424000 + flags = 1 + data = length 384, hash C9D6BC51 + sample 102: + time = 2448000 + flags = 1 + data = length 384, hash FBE2EF0F + sample 103: + time = 2472000 + flags = 1 + data = length 384, hash 64E44326 + sample 104: + time = 2496000 + flags = 1 + data = length 384, hash 2A371FEA + sample 105: + time = 2520000 + flags = 1 + data = length 384, hash BC1F17B6 + sample 106: + time = 2544000 + flags = 1 + data = length 384, hash 759FA7C2 + sample 107: + time = 2568000 + flags = 1 + data = length 384, hash ED978C15 + sample 108: + time = 2592000 + flags = 1 + data = length 384, hash 2393BA70 + sample 109: + time = 2616000 + flags = 1 + data = length 384, hash F84E2847 + sample 110: + time = 2640000 + flags = 1 + data = length 384, hash FF006E14 + sample 111: + time = 2664000 + flags = 1 + data = length 384, hash 840D19F5 + sample 112: + time = 2688000 + flags = 1 + data = length 384, hash B17A5934 + sample 113: + time = 2712000 + flags = 1 + data = length 384, hash 2879F06E + sample 114: + time = 2736000 + flags = 1 + data = length 384, hash 386AB993 + sample 115: + time = 2760000 + flags = 1 + data = length 384, hash 276609B5 + sample 116: + time = 2784000 + flags = 1 + data = length 384, hash 5FE294B5 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.1.dump new file mode 100644 index 00000000000..d5e0e76cef9 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.1.dump @@ -0,0 +1,339 @@ +seekMap: + isSeekable = true + duration = 2807978 + getPosition(0) = [[timeUs=0, position=429]] + getPosition(1) = [[timeUs=0, position=429], [timeUs=23999, position=813]] + getPosition(1403989) = [[timeUs=1391989, position=22701], [timeUs=1415988, position=23085]] + getPosition(2807978) = [[timeUs=2783978, position=44973]] +numberOfTracks = 1 +track 0: + total output bytes = 30336 + sample count = 79 + track duration = 2807978 + format 0: + averageBitrate = 128001 + containerMimeType = audio/mpeg + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 48000 + encoderDelay = 576 + encoderPadding = 576 + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=GainField{name=0, originator=0, gain=0.0}] + sample 0: + time = 911992 + flags = 1 + data = length 384, hash 40914CAF + sample 1: + time = 935992 + flags = 1 + data = length 384, hash F7EFB71E + sample 2: + time = 959992 + flags = 1 + data = length 384, hash 53FBE77C + sample 3: + time = 983992 + flags = 1 + data = length 384, hash 77E58178 + sample 4: + time = 1007992 + flags = 1 + data = length 384, hash E3B86048 + sample 5: + time = 1031992 + flags = 1 + data = length 384, hash 6E64349 + sample 6: + time = 1055992 + flags = 1 + data = length 384, hash AC0B5E18 + sample 7: + time = 1079992 + flags = 1 + data = length 384, hash 7B4CE779 + sample 8: + time = 1103992 + flags = 1 + data = length 384, hash 50D10931 + sample 9: + time = 1127992 + flags = 1 + data = length 384, hash F0D97D3E + sample 10: + time = 1151992 + flags = 1 + data = length 384, hash ED786460 + sample 11: + time = 1175992 + flags = 1 + data = length 384, hash 435543F4 + sample 12: + time = 1199992 + flags = 1 + data = length 384, hash 523ED198 + sample 13: + time = 1223992 + flags = 1 + data = length 384, hash 705705D3 + sample 14: + time = 1247992 + flags = 1 + data = length 384, hash 4A95F442 + sample 15: + time = 1271992 + flags = 1 + data = length 384, hash 56D7EF4B + sample 16: + time = 1295992 + flags = 1 + data = length 384, hash B47AAC17 + sample 17: + time = 1319992 + flags = 1 + data = length 384, hash 38E76A4D + sample 18: + time = 1343992 + flags = 1 + data = length 384, hash ADF5E978 + sample 19: + time = 1367992 + flags = 1 + data = length 384, hash 349125C2 + sample 20: + time = 1391992 + flags = 1 + data = length 384, hash D69B3903 + sample 21: + time = 1415992 + flags = 1 + data = length 384, hash 852DA91C + sample 22: + time = 1439992 + flags = 1 + data = length 384, hash 21F87C6E + sample 23: + time = 1463992 + flags = 1 + data = length 384, hash 68686E41 + sample 24: + time = 1487992 + flags = 1 + data = length 384, hash 4DAC9F6A + sample 25: + time = 1511992 + flags = 1 + data = length 384, hash B5CA6FCF + sample 26: + time = 1535992 + flags = 1 + data = length 384, hash 9B7216B3 + sample 27: + time = 1559992 + flags = 1 + data = length 384, hash AC7162DA + sample 28: + time = 1583992 + flags = 1 + data = length 384, hash 545A4B9C + sample 29: + time = 1607992 + flags = 1 + data = length 384, hash 380FA5D4 + sample 30: + time = 1631992 + flags = 1 + data = length 384, hash 53BF79E9 + sample 31: + time = 1655992 + flags = 1 + data = length 384, hash FE2460DB + sample 32: + time = 1679992 + flags = 1 + data = length 384, hash 2525E09 + sample 33: + time = 1703992 + flags = 1 + data = length 384, hash ECCB42AA + sample 34: + time = 1727992 + flags = 1 + data = length 384, hash 1E5EC5FA + sample 35: + time = 1751992 + flags = 1 + data = length 384, hash C2597D09 + sample 36: + time = 1775992 + flags = 1 + data = length 384, hash 32CD263E + sample 37: + time = 1799992 + flags = 1 + data = length 384, hash 6B3A0DC7 + sample 38: + time = 1823992 + flags = 1 + data = length 384, hash 5155B353 + sample 39: + time = 1847992 + flags = 1 + data = length 384, hash 220C783 + sample 40: + time = 1871992 + flags = 1 + data = length 384, hash E0925905 + sample 41: + time = 1895992 + flags = 1 + data = length 384, hash 824C0D02 + sample 42: + time = 1919992 + flags = 1 + data = length 384, hash 5166F8F3 + sample 43: + time = 1943992 + flags = 1 + data = length 384, hash B5F38EE6 + sample 44: + time = 1967992 + flags = 1 + data = length 384, hash 659E483F + sample 45: + time = 1991992 + flags = 1 + data = length 384, hash A022EFCB + sample 46: + time = 2015992 + flags = 1 + data = length 384, hash 93DCF4B5 + sample 47: + time = 2039992 + flags = 1 + data = length 384, hash C965128 + sample 48: + time = 2063992 + flags = 1 + data = length 384, hash 6FD595F4 + sample 49: + time = 2087992 + flags = 1 + data = length 384, hash BF6CDB31 + sample 50: + time = 2111992 + flags = 1 + data = length 384, hash 67C738C0 + sample 51: + time = 2135992 + flags = 1 + data = length 384, hash BCFCD1CC + sample 52: + time = 2159992 + flags = 1 + data = length 384, hash A4A85D04 + sample 53: + time = 2183992 + flags = 1 + data = length 384, hash 6CD26641 + sample 54: + time = 2207992 + flags = 1 + data = length 384, hash 53817862 + sample 55: + time = 2231992 + flags = 1 + data = length 384, hash 1C98DD10 + sample 56: + time = 2255992 + flags = 1 + data = length 384, hash 5B8EE2C9 + sample 57: + time = 2279992 + flags = 1 + data = length 384, hash 227883D0 + sample 58: + time = 2303992 + flags = 1 + data = length 384, hash 50267C46 + sample 59: + time = 2327992 + flags = 1 + data = length 384, hash F02EA205 + sample 60: + time = 2351992 + flags = 1 + data = length 384, hash ED7BE6DF + sample 61: + time = 2375992 + flags = 1 + data = length 384, hash AEE4E608 + sample 62: + time = 2399992 + flags = 1 + data = length 384, hash 8EA81A05 + sample 63: + time = 2423992 + flags = 1 + data = length 384, hash C9D6BC51 + sample 64: + time = 2447992 + flags = 1 + data = length 384, hash FBE2EF0F + sample 65: + time = 2471992 + flags = 1 + data = length 384, hash 64E44326 + sample 66: + time = 2495992 + flags = 1 + data = length 384, hash 2A371FEA + sample 67: + time = 2519992 + flags = 1 + data = length 384, hash BC1F17B6 + sample 68: + time = 2543992 + flags = 1 + data = length 384, hash 759FA7C2 + sample 69: + time = 2567992 + flags = 1 + data = length 384, hash ED978C15 + sample 70: + time = 2591992 + flags = 1 + data = length 384, hash 2393BA70 + sample 71: + time = 2615992 + flags = 1 + data = length 384, hash F84E2847 + sample 72: + time = 2639992 + flags = 1 + data = length 384, hash FF006E14 + sample 73: + time = 2663992 + flags = 1 + data = length 384, hash 840D19F5 + sample 74: + time = 2687992 + flags = 1 + data = length 384, hash B17A5934 + sample 75: + time = 2711992 + flags = 1 + data = length 384, hash 2879F06E + sample 76: + time = 2735992 + flags = 1 + data = length 384, hash 386AB993 + sample 77: + time = 2759992 + flags = 1 + data = length 384, hash 276609B5 + sample 78: + time = 2783992 + flags = 1 + data = length 384, hash 5FE294B5 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.2.dump new file mode 100644 index 00000000000..e2a4f83b096 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.2.dump @@ -0,0 +1,183 @@ +seekMap: + isSeekable = true + duration = 2807978 + getPosition(0) = [[timeUs=0, position=429]] + getPosition(1) = [[timeUs=0, position=429], [timeUs=23999, position=813]] + getPosition(1403989) = [[timeUs=1391989, position=22701], [timeUs=1415988, position=23085]] + getPosition(2807978) = [[timeUs=2783978, position=44973]] +numberOfTracks = 1 +track 0: + total output bytes = 15360 + sample count = 40 + track duration = 2807978 + format 0: + averageBitrate = 128001 + containerMimeType = audio/mpeg + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 48000 + encoderDelay = 576 + encoderPadding = 576 + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=GainField{name=0, originator=0, gain=0.0}] + sample 0: + time = 1847985 + flags = 1 + data = length 384, hash 220C783 + sample 1: + time = 1871985 + flags = 1 + data = length 384, hash E0925905 + sample 2: + time = 1895985 + flags = 1 + data = length 384, hash 824C0D02 + sample 3: + time = 1919985 + flags = 1 + data = length 384, hash 5166F8F3 + sample 4: + time = 1943985 + flags = 1 + data = length 384, hash B5F38EE6 + sample 5: + time = 1967985 + flags = 1 + data = length 384, hash 659E483F + sample 6: + time = 1991985 + flags = 1 + data = length 384, hash A022EFCB + sample 7: + time = 2015985 + flags = 1 + data = length 384, hash 93DCF4B5 + sample 8: + time = 2039985 + flags = 1 + data = length 384, hash C965128 + sample 9: + time = 2063985 + flags = 1 + data = length 384, hash 6FD595F4 + sample 10: + time = 2087985 + flags = 1 + data = length 384, hash BF6CDB31 + sample 11: + time = 2111985 + flags = 1 + data = length 384, hash 67C738C0 + sample 12: + time = 2135985 + flags = 1 + data = length 384, hash BCFCD1CC + sample 13: + time = 2159985 + flags = 1 + data = length 384, hash A4A85D04 + sample 14: + time = 2183985 + flags = 1 + data = length 384, hash 6CD26641 + sample 15: + time = 2207985 + flags = 1 + data = length 384, hash 53817862 + sample 16: + time = 2231985 + flags = 1 + data = length 384, hash 1C98DD10 + sample 17: + time = 2255985 + flags = 1 + data = length 384, hash 5B8EE2C9 + sample 18: + time = 2279985 + flags = 1 + data = length 384, hash 227883D0 + sample 19: + time = 2303985 + flags = 1 + data = length 384, hash 50267C46 + sample 20: + time = 2327985 + flags = 1 + data = length 384, hash F02EA205 + sample 21: + time = 2351985 + flags = 1 + data = length 384, hash ED7BE6DF + sample 22: + time = 2375985 + flags = 1 + data = length 384, hash AEE4E608 + sample 23: + time = 2399985 + flags = 1 + data = length 384, hash 8EA81A05 + sample 24: + time = 2423985 + flags = 1 + data = length 384, hash C9D6BC51 + sample 25: + time = 2447985 + flags = 1 + data = length 384, hash FBE2EF0F + sample 26: + time = 2471985 + flags = 1 + data = length 384, hash 64E44326 + sample 27: + time = 2495985 + flags = 1 + data = length 384, hash 2A371FEA + sample 28: + time = 2519985 + flags = 1 + data = length 384, hash BC1F17B6 + sample 29: + time = 2543985 + flags = 1 + data = length 384, hash 759FA7C2 + sample 30: + time = 2567985 + flags = 1 + data = length 384, hash ED978C15 + sample 31: + time = 2591985 + flags = 1 + data = length 384, hash 2393BA70 + sample 32: + time = 2615985 + flags = 1 + data = length 384, hash F84E2847 + sample 33: + time = 2639985 + flags = 1 + data = length 384, hash FF006E14 + sample 34: + time = 2663985 + flags = 1 + data = length 384, hash 840D19F5 + sample 35: + time = 2687985 + flags = 1 + data = length 384, hash B17A5934 + sample 36: + time = 2711985 + flags = 1 + data = length 384, hash 2879F06E + sample 37: + time = 2735985 + flags = 1 + data = length 384, hash 386AB993 + sample 38: + time = 2759985 + flags = 1 + data = length 384, hash 276609B5 + sample 39: + time = 2783985 + flags = 1 + data = length 384, hash 5FE294B5 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.3.dump new file mode 100644 index 00000000000..700732389ce --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.3.dump @@ -0,0 +1,27 @@ +seekMap: + isSeekable = true + duration = 2807978 + getPosition(0) = [[timeUs=0, position=429]] + getPosition(1) = [[timeUs=0, position=429], [timeUs=23999, position=813]] + getPosition(1403989) = [[timeUs=1391989, position=22701], [timeUs=1415988, position=23085]] + getPosition(2807978) = [[timeUs=2783978, position=44973]] +numberOfTracks = 1 +track 0: + total output bytes = 384 + sample count = 1 + track duration = 2807978 + format 0: + averageBitrate = 128001 + containerMimeType = audio/mpeg + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 48000 + encoderDelay = 576 + encoderPadding = 576 + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=GainField{name=0, originator=0, gain=0.0}] + sample 0: + time = 2783978 + flags = 1 + data = length 384, hash 5FE294B5 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.unknown_length.dump new file mode 100644 index 00000000000..9aa7068113c --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.unknown_length.dump @@ -0,0 +1,491 @@ +seekMap: + isSeekable = true + duration = 2807978 + getPosition(0) = [[timeUs=0, position=429]] + getPosition(1) = [[timeUs=0, position=429], [timeUs=23999, position=813]] + getPosition(1403989) = [[timeUs=1391989, position=22701], [timeUs=1415988, position=23085]] + getPosition(2807978) = [[timeUs=2783978, position=44973]] +numberOfTracks = 1 +track 0: + total output bytes = 44928 + sample count = 117 + track duration = 2807978 + format 0: + averageBitrate = 128001 + containerMimeType = audio/mpeg + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 48000 + encoderDelay = 576 + encoderPadding = 576 + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=GainField{name=0, originator=0, gain=0.0}] + sample 0: + time = 0 + flags = 1 + data = length 384, hash D3A746E7 + sample 1: + time = 24000 + flags = 1 + data = length 384, hash F1E9E3E + sample 2: + time = 48000 + flags = 1 + data = length 384, hash 456DA228 + sample 3: + time = 72000 + flags = 1 + data = length 384, hash CDB09F78 + sample 4: + time = 96000 + flags = 1 + data = length 384, hash 5BFF9C1A + sample 5: + time = 120000 + flags = 1 + data = length 384, hash 861FDAA7 + sample 6: + time = 144000 + flags = 1 + data = length 384, hash 1FE36A4D + sample 7: + time = 168000 + flags = 1 + data = length 384, hash 4DD5C0F4 + sample 8: + time = 192000 + flags = 1 + data = length 384, hash D64A8BC6 + sample 9: + time = 216000 + flags = 1 + data = length 384, hash E20D4988 + sample 10: + time = 240000 + flags = 1 + data = length 384, hash ED2BF624 + sample 11: + time = 264000 + flags = 1 + data = length 384, hash 60E5ABBC + sample 12: + time = 288000 + flags = 1 + data = length 384, hash 404244BF + sample 13: + time = 312000 + flags = 1 + data = length 384, hash C65FF8C1 + sample 14: + time = 336000 + flags = 1 + data = length 384, hash 42386869 + sample 15: + time = 360000 + flags = 1 + data = length 384, hash 592F129A + sample 16: + time = 384000 + flags = 1 + data = length 384, hash 299ACDD7 + sample 17: + time = 408000 + flags = 1 + data = length 384, hash 8FF937AC + sample 18: + time = 432000 + flags = 1 + data = length 384, hash 4B5C2884 + sample 19: + time = 456000 + flags = 1 + data = length 384, hash 862D22F1 + sample 20: + time = 480000 + flags = 1 + data = length 384, hash 49AFE67D + sample 21: + time = 504000 + flags = 1 + data = length 384, hash 420EFE5F + sample 22: + time = 528000 + flags = 1 + data = length 384, hash 52759113 + sample 23: + time = 552000 + flags = 1 + data = length 384, hash 880C2AB2 + sample 24: + time = 576000 + flags = 1 + data = length 384, hash 1F7E786A + sample 25: + time = 600000 + flags = 1 + data = length 384, hash DF5D2BCF + sample 26: + time = 624000 + flags = 1 + data = length 384, hash D4020EB3 + sample 27: + time = 648000 + flags = 1 + data = length 384, hash BF6D1CA6 + sample 28: + time = 672000 + flags = 1 + data = length 384, hash 68B200EE + sample 29: + time = 696000 + flags = 1 + data = length 384, hash A71C4AFF + sample 30: + time = 720000 + flags = 1 + data = length 384, hash C36CA276 + sample 31: + time = 744000 + flags = 1 + data = length 384, hash 5AB9C9AA + sample 32: + time = 768000 + flags = 1 + data = length 384, hash CAC81110 + sample 33: + time = 792000 + flags = 1 + data = length 384, hash B45D0135 + sample 34: + time = 816000 + flags = 1 + data = length 384, hash 9F0FF1E6 + sample 35: + time = 840000 + flags = 1 + data = length 384, hash F3F425FD + sample 36: + time = 864000 + flags = 1 + data = length 384, hash 15C4DA8 + sample 37: + time = 888000 + flags = 1 + data = length 384, hash 9B5D1E2 + sample 38: + time = 912000 + flags = 1 + data = length 384, hash 40914CAF + sample 39: + time = 936000 + flags = 1 + data = length 384, hash F7EFB71E + sample 40: + time = 960000 + flags = 1 + data = length 384, hash 53FBE77C + sample 41: + time = 984000 + flags = 1 + data = length 384, hash 77E58178 + sample 42: + time = 1008000 + flags = 1 + data = length 384, hash E3B86048 + sample 43: + time = 1032000 + flags = 1 + data = length 384, hash 6E64349 + sample 44: + time = 1056000 + flags = 1 + data = length 384, hash AC0B5E18 + sample 45: + time = 1080000 + flags = 1 + data = length 384, hash 7B4CE779 + sample 46: + time = 1104000 + flags = 1 + data = length 384, hash 50D10931 + sample 47: + time = 1128000 + flags = 1 + data = length 384, hash F0D97D3E + sample 48: + time = 1152000 + flags = 1 + data = length 384, hash ED786460 + sample 49: + time = 1176000 + flags = 1 + data = length 384, hash 435543F4 + sample 50: + time = 1200000 + flags = 1 + data = length 384, hash 523ED198 + sample 51: + time = 1224000 + flags = 1 + data = length 384, hash 705705D3 + sample 52: + time = 1248000 + flags = 1 + data = length 384, hash 4A95F442 + sample 53: + time = 1272000 + flags = 1 + data = length 384, hash 56D7EF4B + sample 54: + time = 1296000 + flags = 1 + data = length 384, hash B47AAC17 + sample 55: + time = 1320000 + flags = 1 + data = length 384, hash 38E76A4D + sample 56: + time = 1344000 + flags = 1 + data = length 384, hash ADF5E978 + sample 57: + time = 1368000 + flags = 1 + data = length 384, hash 349125C2 + sample 58: + time = 1392000 + flags = 1 + data = length 384, hash D69B3903 + sample 59: + time = 1416000 + flags = 1 + data = length 384, hash 852DA91C + sample 60: + time = 1440000 + flags = 1 + data = length 384, hash 21F87C6E + sample 61: + time = 1464000 + flags = 1 + data = length 384, hash 68686E41 + sample 62: + time = 1488000 + flags = 1 + data = length 384, hash 4DAC9F6A + sample 63: + time = 1512000 + flags = 1 + data = length 384, hash B5CA6FCF + sample 64: + time = 1536000 + flags = 1 + data = length 384, hash 9B7216B3 + sample 65: + time = 1560000 + flags = 1 + data = length 384, hash AC7162DA + sample 66: + time = 1584000 + flags = 1 + data = length 384, hash 545A4B9C + sample 67: + time = 1608000 + flags = 1 + data = length 384, hash 380FA5D4 + sample 68: + time = 1632000 + flags = 1 + data = length 384, hash 53BF79E9 + sample 69: + time = 1656000 + flags = 1 + data = length 384, hash FE2460DB + sample 70: + time = 1680000 + flags = 1 + data = length 384, hash 2525E09 + sample 71: + time = 1704000 + flags = 1 + data = length 384, hash ECCB42AA + sample 72: + time = 1728000 + flags = 1 + data = length 384, hash 1E5EC5FA + sample 73: + time = 1752000 + flags = 1 + data = length 384, hash C2597D09 + sample 74: + time = 1776000 + flags = 1 + data = length 384, hash 32CD263E + sample 75: + time = 1800000 + flags = 1 + data = length 384, hash 6B3A0DC7 + sample 76: + time = 1824000 + flags = 1 + data = length 384, hash 5155B353 + sample 77: + time = 1848000 + flags = 1 + data = length 384, hash 220C783 + sample 78: + time = 1872000 + flags = 1 + data = length 384, hash E0925905 + sample 79: + time = 1896000 + flags = 1 + data = length 384, hash 824C0D02 + sample 80: + time = 1920000 + flags = 1 + data = length 384, hash 5166F8F3 + sample 81: + time = 1944000 + flags = 1 + data = length 384, hash B5F38EE6 + sample 82: + time = 1968000 + flags = 1 + data = length 384, hash 659E483F + sample 83: + time = 1992000 + flags = 1 + data = length 384, hash A022EFCB + sample 84: + time = 2016000 + flags = 1 + data = length 384, hash 93DCF4B5 + sample 85: + time = 2040000 + flags = 1 + data = length 384, hash C965128 + sample 86: + time = 2064000 + flags = 1 + data = length 384, hash 6FD595F4 + sample 87: + time = 2088000 + flags = 1 + data = length 384, hash BF6CDB31 + sample 88: + time = 2112000 + flags = 1 + data = length 384, hash 67C738C0 + sample 89: + time = 2136000 + flags = 1 + data = length 384, hash BCFCD1CC + sample 90: + time = 2160000 + flags = 1 + data = length 384, hash A4A85D04 + sample 91: + time = 2184000 + flags = 1 + data = length 384, hash 6CD26641 + sample 92: + time = 2208000 + flags = 1 + data = length 384, hash 53817862 + sample 93: + time = 2232000 + flags = 1 + data = length 384, hash 1C98DD10 + sample 94: + time = 2256000 + flags = 1 + data = length 384, hash 5B8EE2C9 + sample 95: + time = 2280000 + flags = 1 + data = length 384, hash 227883D0 + sample 96: + time = 2304000 + flags = 1 + data = length 384, hash 50267C46 + sample 97: + time = 2328000 + flags = 1 + data = length 384, hash F02EA205 + sample 98: + time = 2352000 + flags = 1 + data = length 384, hash ED7BE6DF + sample 99: + time = 2376000 + flags = 1 + data = length 384, hash AEE4E608 + sample 100: + time = 2400000 + flags = 1 + data = length 384, hash 8EA81A05 + sample 101: + time = 2424000 + flags = 1 + data = length 384, hash C9D6BC51 + sample 102: + time = 2448000 + flags = 1 + data = length 384, hash FBE2EF0F + sample 103: + time = 2472000 + flags = 1 + data = length 384, hash 64E44326 + sample 104: + time = 2496000 + flags = 1 + data = length 384, hash 2A371FEA + sample 105: + time = 2520000 + flags = 1 + data = length 384, hash BC1F17B6 + sample 106: + time = 2544000 + flags = 1 + data = length 384, hash 759FA7C2 + sample 107: + time = 2568000 + flags = 1 + data = length 384, hash ED978C15 + sample 108: + time = 2592000 + flags = 1 + data = length 384, hash 2393BA70 + sample 109: + time = 2616000 + flags = 1 + data = length 384, hash F84E2847 + sample 110: + time = 2640000 + flags = 1 + data = length 384, hash FF006E14 + sample 111: + time = 2664000 + flags = 1 + data = length 384, hash 840D19F5 + sample 112: + time = 2688000 + flags = 1 + data = length 384, hash B17A5934 + sample 113: + time = 2712000 + flags = 1 + data = length 384, hash 2879F06E + sample 114: + time = 2736000 + flags = 1 + data = length 384, hash 386AB993 + sample 115: + time = 2760000 + flags = 1 + data = length 384, hash 276609B5 + sample 116: + time = 2784000 + flags = 1 + data = length 384, hash 5FE294B5 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.0.dump new file mode 100644 index 00000000000..3f8adaa10b9 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.0.dump @@ -0,0 +1,491 @@ +seekMap: + isSeekable = true + duration = 2807978 + getPosition(0) = [[timeUs=0, position=429]] + getPosition(1) = [[timeUs=0, position=429], [timeUs=23999, position=813]] + getPosition(1403989) = [[timeUs=1391989, position=22701], [timeUs=1415988, position=23085]] + getPosition(2807978) = [[timeUs=2783978, position=44973]] +numberOfTracks = 1 +track 0: + total output bytes = 44928 + sample count = 117 + track duration = 2807978 + format 0: + averageBitrate = 128001 + containerMimeType = audio/mpeg + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 48000 + encoderDelay = 576 + encoderPadding = 576 + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + sample 0: + time = 0 + flags = 1 + data = length 384, hash D3A746E7 + sample 1: + time = 24000 + flags = 1 + data = length 384, hash F1E9E3E + sample 2: + time = 48000 + flags = 1 + data = length 384, hash 456DA228 + sample 3: + time = 72000 + flags = 1 + data = length 384, hash CDB09F78 + sample 4: + time = 96000 + flags = 1 + data = length 384, hash 5BFF9C1A + sample 5: + time = 120000 + flags = 1 + data = length 384, hash 861FDAA7 + sample 6: + time = 144000 + flags = 1 + data = length 384, hash 1FE36A4D + sample 7: + time = 168000 + flags = 1 + data = length 384, hash 4DD5C0F4 + sample 8: + time = 192000 + flags = 1 + data = length 384, hash D64A8BC6 + sample 9: + time = 216000 + flags = 1 + data = length 384, hash E20D4988 + sample 10: + time = 240000 + flags = 1 + data = length 384, hash ED2BF624 + sample 11: + time = 264000 + flags = 1 + data = length 384, hash 60E5ABBC + sample 12: + time = 288000 + flags = 1 + data = length 384, hash 404244BF + sample 13: + time = 312000 + flags = 1 + data = length 384, hash C65FF8C1 + sample 14: + time = 336000 + flags = 1 + data = length 384, hash 42386869 + sample 15: + time = 360000 + flags = 1 + data = length 384, hash 592F129A + sample 16: + time = 384000 + flags = 1 + data = length 384, hash 299ACDD7 + sample 17: + time = 408000 + flags = 1 + data = length 384, hash 8FF937AC + sample 18: + time = 432000 + flags = 1 + data = length 384, hash 4B5C2884 + sample 19: + time = 456000 + flags = 1 + data = length 384, hash 862D22F1 + sample 20: + time = 480000 + flags = 1 + data = length 384, hash 49AFE67D + sample 21: + time = 504000 + flags = 1 + data = length 384, hash 420EFE5F + sample 22: + time = 528000 + flags = 1 + data = length 384, hash 52759113 + sample 23: + time = 552000 + flags = 1 + data = length 384, hash 880C2AB2 + sample 24: + time = 576000 + flags = 1 + data = length 384, hash 1F7E786A + sample 25: + time = 600000 + flags = 1 + data = length 384, hash DF5D2BCF + sample 26: + time = 624000 + flags = 1 + data = length 384, hash D4020EB3 + sample 27: + time = 648000 + flags = 1 + data = length 384, hash BF6D1CA6 + sample 28: + time = 672000 + flags = 1 + data = length 384, hash 68B200EE + sample 29: + time = 696000 + flags = 1 + data = length 384, hash A71C4AFF + sample 30: + time = 720000 + flags = 1 + data = length 384, hash C36CA276 + sample 31: + time = 744000 + flags = 1 + data = length 384, hash 5AB9C9AA + sample 32: + time = 768000 + flags = 1 + data = length 384, hash CAC81110 + sample 33: + time = 792000 + flags = 1 + data = length 384, hash B45D0135 + sample 34: + time = 816000 + flags = 1 + data = length 384, hash 9F0FF1E6 + sample 35: + time = 840000 + flags = 1 + data = length 384, hash F3F425FD + sample 36: + time = 864000 + flags = 1 + data = length 384, hash 15C4DA8 + sample 37: + time = 888000 + flags = 1 + data = length 384, hash 9B5D1E2 + sample 38: + time = 912000 + flags = 1 + data = length 384, hash 40914CAF + sample 39: + time = 936000 + flags = 1 + data = length 384, hash F7EFB71E + sample 40: + time = 960000 + flags = 1 + data = length 384, hash 53FBE77C + sample 41: + time = 984000 + flags = 1 + data = length 384, hash 77E58178 + sample 42: + time = 1008000 + flags = 1 + data = length 384, hash E3B86048 + sample 43: + time = 1032000 + flags = 1 + data = length 384, hash 6E64349 + sample 44: + time = 1056000 + flags = 1 + data = length 384, hash AC0B5E18 + sample 45: + time = 1080000 + flags = 1 + data = length 384, hash 7B4CE779 + sample 46: + time = 1104000 + flags = 1 + data = length 384, hash 50D10931 + sample 47: + time = 1128000 + flags = 1 + data = length 384, hash F0D97D3E + sample 48: + time = 1152000 + flags = 1 + data = length 384, hash ED786460 + sample 49: + time = 1176000 + flags = 1 + data = length 384, hash 435543F4 + sample 50: + time = 1200000 + flags = 1 + data = length 384, hash 523ED198 + sample 51: + time = 1224000 + flags = 1 + data = length 384, hash 705705D3 + sample 52: + time = 1248000 + flags = 1 + data = length 384, hash 4A95F442 + sample 53: + time = 1272000 + flags = 1 + data = length 384, hash 56D7EF4B + sample 54: + time = 1296000 + flags = 1 + data = length 384, hash B47AAC17 + sample 55: + time = 1320000 + flags = 1 + data = length 384, hash 38E76A4D + sample 56: + time = 1344000 + flags = 1 + data = length 384, hash ADF5E978 + sample 57: + time = 1368000 + flags = 1 + data = length 384, hash 349125C2 + sample 58: + time = 1392000 + flags = 1 + data = length 384, hash D69B3903 + sample 59: + time = 1416000 + flags = 1 + data = length 384, hash 852DA91C + sample 60: + time = 1440000 + flags = 1 + data = length 384, hash 21F87C6E + sample 61: + time = 1464000 + flags = 1 + data = length 384, hash 68686E41 + sample 62: + time = 1488000 + flags = 1 + data = length 384, hash 4DAC9F6A + sample 63: + time = 1512000 + flags = 1 + data = length 384, hash B5CA6FCF + sample 64: + time = 1536000 + flags = 1 + data = length 384, hash 9B7216B3 + sample 65: + time = 1560000 + flags = 1 + data = length 384, hash AC7162DA + sample 66: + time = 1584000 + flags = 1 + data = length 384, hash 545A4B9C + sample 67: + time = 1608000 + flags = 1 + data = length 384, hash 380FA5D4 + sample 68: + time = 1632000 + flags = 1 + data = length 384, hash 53BF79E9 + sample 69: + time = 1656000 + flags = 1 + data = length 384, hash FE2460DB + sample 70: + time = 1680000 + flags = 1 + data = length 384, hash 2525E09 + sample 71: + time = 1704000 + flags = 1 + data = length 384, hash ECCB42AA + sample 72: + time = 1728000 + flags = 1 + data = length 384, hash 1E5EC5FA + sample 73: + time = 1752000 + flags = 1 + data = length 384, hash C2597D09 + sample 74: + time = 1776000 + flags = 1 + data = length 384, hash 32CD263E + sample 75: + time = 1800000 + flags = 1 + data = length 384, hash 6B3A0DC7 + sample 76: + time = 1824000 + flags = 1 + data = length 384, hash 5155B353 + sample 77: + time = 1848000 + flags = 1 + data = length 384, hash 220C783 + sample 78: + time = 1872000 + flags = 1 + data = length 384, hash E0925905 + sample 79: + time = 1896000 + flags = 1 + data = length 384, hash 824C0D02 + sample 80: + time = 1920000 + flags = 1 + data = length 384, hash 5166F8F3 + sample 81: + time = 1944000 + flags = 1 + data = length 384, hash B5F38EE6 + sample 82: + time = 1968000 + flags = 1 + data = length 384, hash 659E483F + sample 83: + time = 1992000 + flags = 1 + data = length 384, hash A022EFCB + sample 84: + time = 2016000 + flags = 1 + data = length 384, hash 93DCF4B5 + sample 85: + time = 2040000 + flags = 1 + data = length 384, hash C965128 + sample 86: + time = 2064000 + flags = 1 + data = length 384, hash 6FD595F4 + sample 87: + time = 2088000 + flags = 1 + data = length 384, hash BF6CDB31 + sample 88: + time = 2112000 + flags = 1 + data = length 384, hash 67C738C0 + sample 89: + time = 2136000 + flags = 1 + data = length 384, hash BCFCD1CC + sample 90: + time = 2160000 + flags = 1 + data = length 384, hash A4A85D04 + sample 91: + time = 2184000 + flags = 1 + data = length 384, hash 6CD26641 + sample 92: + time = 2208000 + flags = 1 + data = length 384, hash 53817862 + sample 93: + time = 2232000 + flags = 1 + data = length 384, hash 1C98DD10 + sample 94: + time = 2256000 + flags = 1 + data = length 384, hash 5B8EE2C9 + sample 95: + time = 2280000 + flags = 1 + data = length 384, hash 227883D0 + sample 96: + time = 2304000 + flags = 1 + data = length 384, hash 50267C46 + sample 97: + time = 2328000 + flags = 1 + data = length 384, hash F02EA205 + sample 98: + time = 2352000 + flags = 1 + data = length 384, hash ED7BE6DF + sample 99: + time = 2376000 + flags = 1 + data = length 384, hash AEE4E608 + sample 100: + time = 2400000 + flags = 1 + data = length 384, hash 8EA81A05 + sample 101: + time = 2424000 + flags = 1 + data = length 384, hash C9D6BC51 + sample 102: + time = 2448000 + flags = 1 + data = length 384, hash FBE2EF0F + sample 103: + time = 2472000 + flags = 1 + data = length 384, hash 64E44326 + sample 104: + time = 2496000 + flags = 1 + data = length 384, hash 2A371FEA + sample 105: + time = 2520000 + flags = 1 + data = length 384, hash BC1F17B6 + sample 106: + time = 2544000 + flags = 1 + data = length 384, hash 759FA7C2 + sample 107: + time = 2568000 + flags = 1 + data = length 384, hash ED978C15 + sample 108: + time = 2592000 + flags = 1 + data = length 384, hash 2393BA70 + sample 109: + time = 2616000 + flags = 1 + data = length 384, hash F84E2847 + sample 110: + time = 2640000 + flags = 1 + data = length 384, hash FF006E14 + sample 111: + time = 2664000 + flags = 1 + data = length 384, hash 840D19F5 + sample 112: + time = 2688000 + flags = 1 + data = length 384, hash B17A5934 + sample 113: + time = 2712000 + flags = 1 + data = length 384, hash 2879F06E + sample 114: + time = 2736000 + flags = 1 + data = length 384, hash 386AB993 + sample 115: + time = 2760000 + flags = 1 + data = length 384, hash 276609B5 + sample 116: + time = 2784000 + flags = 1 + data = length 384, hash 5FE294B5 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.1.dump new file mode 100644 index 00000000000..e826f19ee86 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.1.dump @@ -0,0 +1,339 @@ +seekMap: + isSeekable = true + duration = 2807978 + getPosition(0) = [[timeUs=0, position=429]] + getPosition(1) = [[timeUs=0, position=429], [timeUs=23999, position=813]] + getPosition(1403989) = [[timeUs=1391989, position=22701], [timeUs=1415988, position=23085]] + getPosition(2807978) = [[timeUs=2783978, position=44973]] +numberOfTracks = 1 +track 0: + total output bytes = 30336 + sample count = 79 + track duration = 2807978 + format 0: + averageBitrate = 128001 + containerMimeType = audio/mpeg + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 48000 + encoderDelay = 576 + encoderPadding = 576 + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + sample 0: + time = 911992 + flags = 1 + data = length 384, hash 40914CAF + sample 1: + time = 935992 + flags = 1 + data = length 384, hash F7EFB71E + sample 2: + time = 959992 + flags = 1 + data = length 384, hash 53FBE77C + sample 3: + time = 983992 + flags = 1 + data = length 384, hash 77E58178 + sample 4: + time = 1007992 + flags = 1 + data = length 384, hash E3B86048 + sample 5: + time = 1031992 + flags = 1 + data = length 384, hash 6E64349 + sample 6: + time = 1055992 + flags = 1 + data = length 384, hash AC0B5E18 + sample 7: + time = 1079992 + flags = 1 + data = length 384, hash 7B4CE779 + sample 8: + time = 1103992 + flags = 1 + data = length 384, hash 50D10931 + sample 9: + time = 1127992 + flags = 1 + data = length 384, hash F0D97D3E + sample 10: + time = 1151992 + flags = 1 + data = length 384, hash ED786460 + sample 11: + time = 1175992 + flags = 1 + data = length 384, hash 435543F4 + sample 12: + time = 1199992 + flags = 1 + data = length 384, hash 523ED198 + sample 13: + time = 1223992 + flags = 1 + data = length 384, hash 705705D3 + sample 14: + time = 1247992 + flags = 1 + data = length 384, hash 4A95F442 + sample 15: + time = 1271992 + flags = 1 + data = length 384, hash 56D7EF4B + sample 16: + time = 1295992 + flags = 1 + data = length 384, hash B47AAC17 + sample 17: + time = 1319992 + flags = 1 + data = length 384, hash 38E76A4D + sample 18: + time = 1343992 + flags = 1 + data = length 384, hash ADF5E978 + sample 19: + time = 1367992 + flags = 1 + data = length 384, hash 349125C2 + sample 20: + time = 1391992 + flags = 1 + data = length 384, hash D69B3903 + sample 21: + time = 1415992 + flags = 1 + data = length 384, hash 852DA91C + sample 22: + time = 1439992 + flags = 1 + data = length 384, hash 21F87C6E + sample 23: + time = 1463992 + flags = 1 + data = length 384, hash 68686E41 + sample 24: + time = 1487992 + flags = 1 + data = length 384, hash 4DAC9F6A + sample 25: + time = 1511992 + flags = 1 + data = length 384, hash B5CA6FCF + sample 26: + time = 1535992 + flags = 1 + data = length 384, hash 9B7216B3 + sample 27: + time = 1559992 + flags = 1 + data = length 384, hash AC7162DA + sample 28: + time = 1583992 + flags = 1 + data = length 384, hash 545A4B9C + sample 29: + time = 1607992 + flags = 1 + data = length 384, hash 380FA5D4 + sample 30: + time = 1631992 + flags = 1 + data = length 384, hash 53BF79E9 + sample 31: + time = 1655992 + flags = 1 + data = length 384, hash FE2460DB + sample 32: + time = 1679992 + flags = 1 + data = length 384, hash 2525E09 + sample 33: + time = 1703992 + flags = 1 + data = length 384, hash ECCB42AA + sample 34: + time = 1727992 + flags = 1 + data = length 384, hash 1E5EC5FA + sample 35: + time = 1751992 + flags = 1 + data = length 384, hash C2597D09 + sample 36: + time = 1775992 + flags = 1 + data = length 384, hash 32CD263E + sample 37: + time = 1799992 + flags = 1 + data = length 384, hash 6B3A0DC7 + sample 38: + time = 1823992 + flags = 1 + data = length 384, hash 5155B353 + sample 39: + time = 1847992 + flags = 1 + data = length 384, hash 220C783 + sample 40: + time = 1871992 + flags = 1 + data = length 384, hash E0925905 + sample 41: + time = 1895992 + flags = 1 + data = length 384, hash 824C0D02 + sample 42: + time = 1919992 + flags = 1 + data = length 384, hash 5166F8F3 + sample 43: + time = 1943992 + flags = 1 + data = length 384, hash B5F38EE6 + sample 44: + time = 1967992 + flags = 1 + data = length 384, hash 659E483F + sample 45: + time = 1991992 + flags = 1 + data = length 384, hash A022EFCB + sample 46: + time = 2015992 + flags = 1 + data = length 384, hash 93DCF4B5 + sample 47: + time = 2039992 + flags = 1 + data = length 384, hash C965128 + sample 48: + time = 2063992 + flags = 1 + data = length 384, hash 6FD595F4 + sample 49: + time = 2087992 + flags = 1 + data = length 384, hash BF6CDB31 + sample 50: + time = 2111992 + flags = 1 + data = length 384, hash 67C738C0 + sample 51: + time = 2135992 + flags = 1 + data = length 384, hash BCFCD1CC + sample 52: + time = 2159992 + flags = 1 + data = length 384, hash A4A85D04 + sample 53: + time = 2183992 + flags = 1 + data = length 384, hash 6CD26641 + sample 54: + time = 2207992 + flags = 1 + data = length 384, hash 53817862 + sample 55: + time = 2231992 + flags = 1 + data = length 384, hash 1C98DD10 + sample 56: + time = 2255992 + flags = 1 + data = length 384, hash 5B8EE2C9 + sample 57: + time = 2279992 + flags = 1 + data = length 384, hash 227883D0 + sample 58: + time = 2303992 + flags = 1 + data = length 384, hash 50267C46 + sample 59: + time = 2327992 + flags = 1 + data = length 384, hash F02EA205 + sample 60: + time = 2351992 + flags = 1 + data = length 384, hash ED7BE6DF + sample 61: + time = 2375992 + flags = 1 + data = length 384, hash AEE4E608 + sample 62: + time = 2399992 + flags = 1 + data = length 384, hash 8EA81A05 + sample 63: + time = 2423992 + flags = 1 + data = length 384, hash C9D6BC51 + sample 64: + time = 2447992 + flags = 1 + data = length 384, hash FBE2EF0F + sample 65: + time = 2471992 + flags = 1 + data = length 384, hash 64E44326 + sample 66: + time = 2495992 + flags = 1 + data = length 384, hash 2A371FEA + sample 67: + time = 2519992 + flags = 1 + data = length 384, hash BC1F17B6 + sample 68: + time = 2543992 + flags = 1 + data = length 384, hash 759FA7C2 + sample 69: + time = 2567992 + flags = 1 + data = length 384, hash ED978C15 + sample 70: + time = 2591992 + flags = 1 + data = length 384, hash 2393BA70 + sample 71: + time = 2615992 + flags = 1 + data = length 384, hash F84E2847 + sample 72: + time = 2639992 + flags = 1 + data = length 384, hash FF006E14 + sample 73: + time = 2663992 + flags = 1 + data = length 384, hash 840D19F5 + sample 74: + time = 2687992 + flags = 1 + data = length 384, hash B17A5934 + sample 75: + time = 2711992 + flags = 1 + data = length 384, hash 2879F06E + sample 76: + time = 2735992 + flags = 1 + data = length 384, hash 386AB993 + sample 77: + time = 2759992 + flags = 1 + data = length 384, hash 276609B5 + sample 78: + time = 2783992 + flags = 1 + data = length 384, hash 5FE294B5 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.2.dump new file mode 100644 index 00000000000..a2e7c578b4b --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.2.dump @@ -0,0 +1,183 @@ +seekMap: + isSeekable = true + duration = 2807978 + getPosition(0) = [[timeUs=0, position=429]] + getPosition(1) = [[timeUs=0, position=429], [timeUs=23999, position=813]] + getPosition(1403989) = [[timeUs=1391989, position=22701], [timeUs=1415988, position=23085]] + getPosition(2807978) = [[timeUs=2783978, position=44973]] +numberOfTracks = 1 +track 0: + total output bytes = 15360 + sample count = 40 + track duration = 2807978 + format 0: + averageBitrate = 128001 + containerMimeType = audio/mpeg + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 48000 + encoderDelay = 576 + encoderPadding = 576 + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + sample 0: + time = 1847985 + flags = 1 + data = length 384, hash 220C783 + sample 1: + time = 1871985 + flags = 1 + data = length 384, hash E0925905 + sample 2: + time = 1895985 + flags = 1 + data = length 384, hash 824C0D02 + sample 3: + time = 1919985 + flags = 1 + data = length 384, hash 5166F8F3 + sample 4: + time = 1943985 + flags = 1 + data = length 384, hash B5F38EE6 + sample 5: + time = 1967985 + flags = 1 + data = length 384, hash 659E483F + sample 6: + time = 1991985 + flags = 1 + data = length 384, hash A022EFCB + sample 7: + time = 2015985 + flags = 1 + data = length 384, hash 93DCF4B5 + sample 8: + time = 2039985 + flags = 1 + data = length 384, hash C965128 + sample 9: + time = 2063985 + flags = 1 + data = length 384, hash 6FD595F4 + sample 10: + time = 2087985 + flags = 1 + data = length 384, hash BF6CDB31 + sample 11: + time = 2111985 + flags = 1 + data = length 384, hash 67C738C0 + sample 12: + time = 2135985 + flags = 1 + data = length 384, hash BCFCD1CC + sample 13: + time = 2159985 + flags = 1 + data = length 384, hash A4A85D04 + sample 14: + time = 2183985 + flags = 1 + data = length 384, hash 6CD26641 + sample 15: + time = 2207985 + flags = 1 + data = length 384, hash 53817862 + sample 16: + time = 2231985 + flags = 1 + data = length 384, hash 1C98DD10 + sample 17: + time = 2255985 + flags = 1 + data = length 384, hash 5B8EE2C9 + sample 18: + time = 2279985 + flags = 1 + data = length 384, hash 227883D0 + sample 19: + time = 2303985 + flags = 1 + data = length 384, hash 50267C46 + sample 20: + time = 2327985 + flags = 1 + data = length 384, hash F02EA205 + sample 21: + time = 2351985 + flags = 1 + data = length 384, hash ED7BE6DF + sample 22: + time = 2375985 + flags = 1 + data = length 384, hash AEE4E608 + sample 23: + time = 2399985 + flags = 1 + data = length 384, hash 8EA81A05 + sample 24: + time = 2423985 + flags = 1 + data = length 384, hash C9D6BC51 + sample 25: + time = 2447985 + flags = 1 + data = length 384, hash FBE2EF0F + sample 26: + time = 2471985 + flags = 1 + data = length 384, hash 64E44326 + sample 27: + time = 2495985 + flags = 1 + data = length 384, hash 2A371FEA + sample 28: + time = 2519985 + flags = 1 + data = length 384, hash BC1F17B6 + sample 29: + time = 2543985 + flags = 1 + data = length 384, hash 759FA7C2 + sample 30: + time = 2567985 + flags = 1 + data = length 384, hash ED978C15 + sample 31: + time = 2591985 + flags = 1 + data = length 384, hash 2393BA70 + sample 32: + time = 2615985 + flags = 1 + data = length 384, hash F84E2847 + sample 33: + time = 2639985 + flags = 1 + data = length 384, hash FF006E14 + sample 34: + time = 2663985 + flags = 1 + data = length 384, hash 840D19F5 + sample 35: + time = 2687985 + flags = 1 + data = length 384, hash B17A5934 + sample 36: + time = 2711985 + flags = 1 + data = length 384, hash 2879F06E + sample 37: + time = 2735985 + flags = 1 + data = length 384, hash 386AB993 + sample 38: + time = 2759985 + flags = 1 + data = length 384, hash 276609B5 + sample 39: + time = 2783985 + flags = 1 + data = length 384, hash 5FE294B5 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.3.dump new file mode 100644 index 00000000000..c7339786041 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.3.dump @@ -0,0 +1,27 @@ +seekMap: + isSeekable = true + duration = 2807978 + getPosition(0) = [[timeUs=0, position=429]] + getPosition(1) = [[timeUs=0, position=429], [timeUs=23999, position=813]] + getPosition(1403989) = [[timeUs=1391989, position=22701], [timeUs=1415988, position=23085]] + getPosition(2807978) = [[timeUs=2783978, position=44973]] +numberOfTracks = 1 +track 0: + total output bytes = 384 + sample count = 1 + track duration = 2807978 + format 0: + averageBitrate = 128001 + containerMimeType = audio/mpeg + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 48000 + encoderDelay = 576 + encoderPadding = 576 + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + sample 0: + time = 2783978 + flags = 1 + data = length 384, hash 5FE294B5 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.unknown_length.dump new file mode 100644 index 00000000000..3f8adaa10b9 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.unknown_length.dump @@ -0,0 +1,491 @@ +seekMap: + isSeekable = true + duration = 2807978 + getPosition(0) = [[timeUs=0, position=429]] + getPosition(1) = [[timeUs=0, position=429], [timeUs=23999, position=813]] + getPosition(1403989) = [[timeUs=1391989, position=22701], [timeUs=1415988, position=23085]] + getPosition(2807978) = [[timeUs=2783978, position=44973]] +numberOfTracks = 1 +track 0: + total output bytes = 44928 + sample count = 117 + track duration = 2807978 + format 0: + averageBitrate = 128001 + containerMimeType = audio/mpeg + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 48000 + encoderDelay = 576 + encoderPadding = 576 + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + sample 0: + time = 0 + flags = 1 + data = length 384, hash D3A746E7 + sample 1: + time = 24000 + flags = 1 + data = length 384, hash F1E9E3E + sample 2: + time = 48000 + flags = 1 + data = length 384, hash 456DA228 + sample 3: + time = 72000 + flags = 1 + data = length 384, hash CDB09F78 + sample 4: + time = 96000 + flags = 1 + data = length 384, hash 5BFF9C1A + sample 5: + time = 120000 + flags = 1 + data = length 384, hash 861FDAA7 + sample 6: + time = 144000 + flags = 1 + data = length 384, hash 1FE36A4D + sample 7: + time = 168000 + flags = 1 + data = length 384, hash 4DD5C0F4 + sample 8: + time = 192000 + flags = 1 + data = length 384, hash D64A8BC6 + sample 9: + time = 216000 + flags = 1 + data = length 384, hash E20D4988 + sample 10: + time = 240000 + flags = 1 + data = length 384, hash ED2BF624 + sample 11: + time = 264000 + flags = 1 + data = length 384, hash 60E5ABBC + sample 12: + time = 288000 + flags = 1 + data = length 384, hash 404244BF + sample 13: + time = 312000 + flags = 1 + data = length 384, hash C65FF8C1 + sample 14: + time = 336000 + flags = 1 + data = length 384, hash 42386869 + sample 15: + time = 360000 + flags = 1 + data = length 384, hash 592F129A + sample 16: + time = 384000 + flags = 1 + data = length 384, hash 299ACDD7 + sample 17: + time = 408000 + flags = 1 + data = length 384, hash 8FF937AC + sample 18: + time = 432000 + flags = 1 + data = length 384, hash 4B5C2884 + sample 19: + time = 456000 + flags = 1 + data = length 384, hash 862D22F1 + sample 20: + time = 480000 + flags = 1 + data = length 384, hash 49AFE67D + sample 21: + time = 504000 + flags = 1 + data = length 384, hash 420EFE5F + sample 22: + time = 528000 + flags = 1 + data = length 384, hash 52759113 + sample 23: + time = 552000 + flags = 1 + data = length 384, hash 880C2AB2 + sample 24: + time = 576000 + flags = 1 + data = length 384, hash 1F7E786A + sample 25: + time = 600000 + flags = 1 + data = length 384, hash DF5D2BCF + sample 26: + time = 624000 + flags = 1 + data = length 384, hash D4020EB3 + sample 27: + time = 648000 + flags = 1 + data = length 384, hash BF6D1CA6 + sample 28: + time = 672000 + flags = 1 + data = length 384, hash 68B200EE + sample 29: + time = 696000 + flags = 1 + data = length 384, hash A71C4AFF + sample 30: + time = 720000 + flags = 1 + data = length 384, hash C36CA276 + sample 31: + time = 744000 + flags = 1 + data = length 384, hash 5AB9C9AA + sample 32: + time = 768000 + flags = 1 + data = length 384, hash CAC81110 + sample 33: + time = 792000 + flags = 1 + data = length 384, hash B45D0135 + sample 34: + time = 816000 + flags = 1 + data = length 384, hash 9F0FF1E6 + sample 35: + time = 840000 + flags = 1 + data = length 384, hash F3F425FD + sample 36: + time = 864000 + flags = 1 + data = length 384, hash 15C4DA8 + sample 37: + time = 888000 + flags = 1 + data = length 384, hash 9B5D1E2 + sample 38: + time = 912000 + flags = 1 + data = length 384, hash 40914CAF + sample 39: + time = 936000 + flags = 1 + data = length 384, hash F7EFB71E + sample 40: + time = 960000 + flags = 1 + data = length 384, hash 53FBE77C + sample 41: + time = 984000 + flags = 1 + data = length 384, hash 77E58178 + sample 42: + time = 1008000 + flags = 1 + data = length 384, hash E3B86048 + sample 43: + time = 1032000 + flags = 1 + data = length 384, hash 6E64349 + sample 44: + time = 1056000 + flags = 1 + data = length 384, hash AC0B5E18 + sample 45: + time = 1080000 + flags = 1 + data = length 384, hash 7B4CE779 + sample 46: + time = 1104000 + flags = 1 + data = length 384, hash 50D10931 + sample 47: + time = 1128000 + flags = 1 + data = length 384, hash F0D97D3E + sample 48: + time = 1152000 + flags = 1 + data = length 384, hash ED786460 + sample 49: + time = 1176000 + flags = 1 + data = length 384, hash 435543F4 + sample 50: + time = 1200000 + flags = 1 + data = length 384, hash 523ED198 + sample 51: + time = 1224000 + flags = 1 + data = length 384, hash 705705D3 + sample 52: + time = 1248000 + flags = 1 + data = length 384, hash 4A95F442 + sample 53: + time = 1272000 + flags = 1 + data = length 384, hash 56D7EF4B + sample 54: + time = 1296000 + flags = 1 + data = length 384, hash B47AAC17 + sample 55: + time = 1320000 + flags = 1 + data = length 384, hash 38E76A4D + sample 56: + time = 1344000 + flags = 1 + data = length 384, hash ADF5E978 + sample 57: + time = 1368000 + flags = 1 + data = length 384, hash 349125C2 + sample 58: + time = 1392000 + flags = 1 + data = length 384, hash D69B3903 + sample 59: + time = 1416000 + flags = 1 + data = length 384, hash 852DA91C + sample 60: + time = 1440000 + flags = 1 + data = length 384, hash 21F87C6E + sample 61: + time = 1464000 + flags = 1 + data = length 384, hash 68686E41 + sample 62: + time = 1488000 + flags = 1 + data = length 384, hash 4DAC9F6A + sample 63: + time = 1512000 + flags = 1 + data = length 384, hash B5CA6FCF + sample 64: + time = 1536000 + flags = 1 + data = length 384, hash 9B7216B3 + sample 65: + time = 1560000 + flags = 1 + data = length 384, hash AC7162DA + sample 66: + time = 1584000 + flags = 1 + data = length 384, hash 545A4B9C + sample 67: + time = 1608000 + flags = 1 + data = length 384, hash 380FA5D4 + sample 68: + time = 1632000 + flags = 1 + data = length 384, hash 53BF79E9 + sample 69: + time = 1656000 + flags = 1 + data = length 384, hash FE2460DB + sample 70: + time = 1680000 + flags = 1 + data = length 384, hash 2525E09 + sample 71: + time = 1704000 + flags = 1 + data = length 384, hash ECCB42AA + sample 72: + time = 1728000 + flags = 1 + data = length 384, hash 1E5EC5FA + sample 73: + time = 1752000 + flags = 1 + data = length 384, hash C2597D09 + sample 74: + time = 1776000 + flags = 1 + data = length 384, hash 32CD263E + sample 75: + time = 1800000 + flags = 1 + data = length 384, hash 6B3A0DC7 + sample 76: + time = 1824000 + flags = 1 + data = length 384, hash 5155B353 + sample 77: + time = 1848000 + flags = 1 + data = length 384, hash 220C783 + sample 78: + time = 1872000 + flags = 1 + data = length 384, hash E0925905 + sample 79: + time = 1896000 + flags = 1 + data = length 384, hash 824C0D02 + sample 80: + time = 1920000 + flags = 1 + data = length 384, hash 5166F8F3 + sample 81: + time = 1944000 + flags = 1 + data = length 384, hash B5F38EE6 + sample 82: + time = 1968000 + flags = 1 + data = length 384, hash 659E483F + sample 83: + time = 1992000 + flags = 1 + data = length 384, hash A022EFCB + sample 84: + time = 2016000 + flags = 1 + data = length 384, hash 93DCF4B5 + sample 85: + time = 2040000 + flags = 1 + data = length 384, hash C965128 + sample 86: + time = 2064000 + flags = 1 + data = length 384, hash 6FD595F4 + sample 87: + time = 2088000 + flags = 1 + data = length 384, hash BF6CDB31 + sample 88: + time = 2112000 + flags = 1 + data = length 384, hash 67C738C0 + sample 89: + time = 2136000 + flags = 1 + data = length 384, hash BCFCD1CC + sample 90: + time = 2160000 + flags = 1 + data = length 384, hash A4A85D04 + sample 91: + time = 2184000 + flags = 1 + data = length 384, hash 6CD26641 + sample 92: + time = 2208000 + flags = 1 + data = length 384, hash 53817862 + sample 93: + time = 2232000 + flags = 1 + data = length 384, hash 1C98DD10 + sample 94: + time = 2256000 + flags = 1 + data = length 384, hash 5B8EE2C9 + sample 95: + time = 2280000 + flags = 1 + data = length 384, hash 227883D0 + sample 96: + time = 2304000 + flags = 1 + data = length 384, hash 50267C46 + sample 97: + time = 2328000 + flags = 1 + data = length 384, hash F02EA205 + sample 98: + time = 2352000 + flags = 1 + data = length 384, hash ED7BE6DF + sample 99: + time = 2376000 + flags = 1 + data = length 384, hash AEE4E608 + sample 100: + time = 2400000 + flags = 1 + data = length 384, hash 8EA81A05 + sample 101: + time = 2424000 + flags = 1 + data = length 384, hash C9D6BC51 + sample 102: + time = 2448000 + flags = 1 + data = length 384, hash FBE2EF0F + sample 103: + time = 2472000 + flags = 1 + data = length 384, hash 64E44326 + sample 104: + time = 2496000 + flags = 1 + data = length 384, hash 2A371FEA + sample 105: + time = 2520000 + flags = 1 + data = length 384, hash BC1F17B6 + sample 106: + time = 2544000 + flags = 1 + data = length 384, hash 759FA7C2 + sample 107: + time = 2568000 + flags = 1 + data = length 384, hash ED978C15 + sample 108: + time = 2592000 + flags = 1 + data = length 384, hash 2393BA70 + sample 109: + time = 2616000 + flags = 1 + data = length 384, hash F84E2847 + sample 110: + time = 2640000 + flags = 1 + data = length 384, hash FF006E14 + sample 111: + time = 2664000 + flags = 1 + data = length 384, hash 840D19F5 + sample 112: + time = 2688000 + flags = 1 + data = length 384, hash B17A5934 + sample 113: + time = 2712000 + flags = 1 + data = length 384, hash 2879F06E + sample 114: + time = 2736000 + flags = 1 + data = length 384, hash 386AB993 + sample 115: + time = 2760000 + flags = 1 + data = length 384, hash 276609B5 + sample 116: + time = 2784000 + flags = 1 + data = length 384, hash 5FE294B5 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.0.dump index 9dde5408e01..ea1713da08a 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.1.dump index b47319b0f7c..c9114e76833 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 958033 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.2.dump index 7eabbad4cb7..10f0a3a99fa 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 1886757 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.3.dump index 47ba03e7576..fb419ec0376 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.3.dump @@ -19,5 +19,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.unknown_length.dump index 9dde5408e01..ea1713da08a 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.0.dump index 08c75fa3453..12618852b59 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.1.dump index cd171718f2c..d1d1427df9e 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 356871 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.2.dump index 103044e917a..fcea591b5d6 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 727157 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.3.dump index 5f40a3c8a4d..de3fe7654b7 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.3.dump @@ -19,5 +19,5 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.unknown_length.dump index 08c75fa3453..12618852b59 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.0.dump index adffb2383f0..10bd2ce865b 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.1.dump index 60efc784e76..b10b292a04b 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 365625 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.2.dump index 8e6b025b683..5e11eaa2d37 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 705250 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.3.dump index 796a47b3615..1abd645c3a2 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.3.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 1018750 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.unknown_length.dump index adffb2383f0..10bd2ce865b 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 From 568028790ac7ce1589060c12a7d50e624abab5ab Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Fri, 2 Jan 2026 17:52:04 +0000 Subject: [PATCH 03/14] Re-order some elements, use unsigned shorts and other tweaks --- .../media3/extractor/mp3/Mp3Extractor.java | 20 ++-- .../extractor/mp3/Mp3InfoReplayGain.java | 99 ++++++++++--------- .../media3/extractor/mp3/XingFrame.java | 4 +- 3 files changed, 64 insertions(+), 59 deletions(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java index 4d8f8665ee6..2f14857b95b 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java @@ -176,7 +176,7 @@ public final class Mp3Extractor implements Extractor { private int synchronizedHeaderData; - @Nullable private Metadata metadata; + @Nullable private Metadata id3Metadata; @Nullable private Metadata infoMetadata; private long basisTimeUs; private long samplesRead; @@ -294,11 +294,11 @@ private int readInternal(ExtractorInput input) throws IOException { if (seeker == null) { seeker = computeSeeker(input); extractorOutput.seekMap(seeker); - @Nullable Metadata finalMetadata = (flags & FLAG_DISABLE_ID3_METADATA) != 0 ? null : metadata; - if (finalMetadata != null) { - finalMetadata = finalMetadata.copyWithAppendedEntriesFrom(infoMetadata); + Metadata metadata; + if (id3Metadata != null && (flags & FLAG_DISABLE_ID3_METADATA) == 0){ + metadata = infoMetadata != null ? id3Metadata.copyWithAppendedEntriesFrom(infoMetadata) : id3Metadata; } else { - finalMetadata = infoMetadata; + metadata = infoMetadata; } Format.Builder format = new Format.Builder() @@ -309,7 +309,7 @@ private int readInternal(ExtractorInput input) throws IOException { .setSampleRate(synchronizedHeader.sampleRate) .setEncoderDelay(gaplessInfoHolder.encoderDelay) .setEncoderPadding(gaplessInfoHolder.encoderPadding) - .setMetadata(finalMetadata); + .setMetadata(metadata); if (seeker.getAverageBitrate() != C.RATE_UNSET_INT) { format.setAverageBitrate(seeker.getAverageBitrate()); } @@ -395,9 +395,9 @@ private boolean synchronize(ExtractorInput input, boolean sniffing) throws IOExc boolean parseAllId3Frames = (flags & FLAG_DISABLE_ID3_METADATA) == 0; Id3Decoder.FramePredicate id3FramePredicate = parseAllId3Frames ? null : REQUIRED_ID3_FRAME_PREDICATE; - metadata = id3Peeker.peekId3Data(input, id3FramePredicate, MAX_SEARCH_BYTES); - if (metadata != null) { - gaplessInfoHolder.setFromMetadata(metadata); + id3Metadata = id3Peeker.peekId3Data(input, id3FramePredicate, MAX_SEARCH_BYTES); + if (id3Metadata != null) { + gaplessInfoHolder.setFromMetadata(id3Metadata); } peekedId3Bytes = (int) input.getPeekPosition(); if (!sniffing) { @@ -482,7 +482,7 @@ private Seeker computeSeeker(ExtractorInput input) throws IOException { // Read past any seek frame and set the seeker based on metadata or a seek frame. Metadata // takes priority as it can provide greater precision. Seeker seekFrameSeeker = maybeReadSeekFrame(input); - Seeker metadataSeeker = maybeHandleSeekMetadata(metadata, input.getPosition()); + Seeker metadataSeeker = maybeHandleSeekMetadata(id3Metadata, input.getPosition()); if (disableSeeking) { return new UnseekableSeeker(); diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java index f1c6f473e76..a52a2db767f 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java @@ -44,19 +44,32 @@ public final class Mp3InfoReplayGain implements Metadata.Entry { /** A gain field can store one gain adjustment with name and originator metadata. */ public static final class GainField { + + /** + * The name of a gain field. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @Target(TYPE_USE) + @IntDef(value = {NAME_INVALID, NAME_RADIO, NAME_AUDIOPHILE}, open = true) + public @interface Name {} + /** This gain field contains no valid data, and should be ignored. */ public static final int NAME_INVALID = 0; /** - * This gain field contains a gain adjustment that will make all the tracks sound equally loud - * (as they do on the radio, hence the name!). If the ReplayGain is calculated on a + * A gain adjustment that makes all the tracks sound equally loud. + * + *

This behaves like tracks do on the radio, hence the name. If the ReplayGain is calculated on a * track-by-track basis (i.e. an individual ReplayGain calculation is carried out for each * track), this will be the result. */ public static final int NAME_RADIO = 1; /** - * The problem with the "Radio" setting is that tracks which should be quiet will be brought up + * A gain adjustment that represents the ideal listening gain for each track. + * + *

The problem with {@link #NAME_RADIO} is that tracks which should be quiet will be brought up * to the level of all the rest. * *

To solve this problem, the "Audiophile" setting represents the ideal listening gain for @@ -75,6 +88,21 @@ public static final class GainField { */ public static final int NAME_AUDIOPHILE = 2; + /** + * The originator of a gain field. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @Target(TYPE_USE) + @IntDef(value = { + ORIGINATOR_UNKNOWN, + ORIGINATOR_ARTIST, + ORIGINATOR_USER, + ORIGINATOR_REPLAYGAIN, + ORIGINATOR_SIMPLE_RMS + }, open = true) + public @interface Originator {} + /** The origin of this gain adjustment is not known. */ public static final int ORIGINATOR_UNKNOWN = 0; @@ -90,39 +118,6 @@ public static final class GainField { /** This gain adjustment was automatically determined by a simple RMS algorithm. */ public static final int ORIGINATOR_SIMPLE_RMS = 4; - /** Creates a gain field from already unpacked values. */ - public GainField(@Name int name, @Originator int originator, float gain) { - this.name = name; - this.originator = originator; - this.gain = gain; - } - - /** Creates a gain field from the packed representation. */ - @SuppressLint("WrongConstant") - public GainField(short field) { - this.name = (field >> 13) & 7; - this.originator = (field >> 10) & 7; - this.gain = ((field & 0x1ff) * ((field & 0x200) != 0 ? -1 : 1)) / 10f; - } - - @Documented - @Retention(RetentionPolicy.SOURCE) - @Target(TYPE_USE) - @IntDef({NAME_INVALID, NAME_RADIO, NAME_AUDIOPHILE}) - public @interface Name {} - - @Documented - @Retention(RetentionPolicy.SOURCE) - @Target(TYPE_USE) - @IntDef({ - ORIGINATOR_UNKNOWN, - ORIGINATOR_ARTIST, - ORIGINATOR_USER, - ORIGINATOR_REPLAYGAIN, - ORIGINATOR_SIMPLE_RMS - }) - public @interface Originator {} - /** * Name/type of the gain field. * @@ -150,6 +145,15 @@ public GainField(short field) { */ public final float gain; + /** + * Parses an instance from the packed representation. + * */ + private GainField(int field) { + name = (field >> 13) & 7; + originator = (field >> 10) & 7; + gain = ((field & 0x1ff) * ((field & 0x200) != 0 ? -1 : 1)) / 10f; + } + /** * @return Whether the name field is set to a valid value, hence, whether this gain field should * be considered or not. If false, the entire field should be ignored. @@ -176,7 +180,10 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(name, originator, gain); + int result = name; + result = 31 * result + originator; + result = 31 * result + Float.hashCode(gain); + return result; } } @@ -186,16 +193,11 @@ public int hashCode() { /** The second of two gain fields in the LAME MP3 Info header. */ public GainField field2; - /** Creates the gain field from already unpacked values. */ - public Mp3InfoReplayGain(float peak, GainField field1, GainField field2) { - this.peak = peak; - this.field1 = field1; - this.field2 = field2; - } - /** Creates the gain fields from the packed representation. */ - public Mp3InfoReplayGain(float peak, short field1, short field2) { - this(peak, new GainField(field1), new GainField(field2)); + public Mp3InfoReplayGain(float peak, int field1, int field2) { + this.peak = peak; + this.field1 = new GainField(field1); + this.field2 = new GainField(field2); } @Override @@ -222,6 +224,9 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(peak, field1, field2); + int result = Float.hashCode(peak); + result = 31 * result + field1.hashCode(); + result = 31 * result + field2.hashCode(); + return result; } } diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java index f5ef33a6699..e4a763bf248 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java @@ -115,8 +115,8 @@ public static XingFrame parse(MpegAudioUtil.Header mpegAudioHeader, ParsableByte if (frame.bytesLeft() >= bytesToSkipBeforeReplayGain + 8 + bytesToSkipAfterReplayGain + 3) { frame.skipBytes(bytesToSkipBeforeReplayGain); float peak = frame.readFloat(); - short field1 = frame.readShort(); - short field2 = frame.readShort(); + int field1 = frame.readUnsignedShort(); + int field2 = frame.readUnsignedShort(); replayGain = new Mp3InfoReplayGain(peak, field1, field2); frame.skipBytes(bytesToSkipAfterReplayGain); From b737716295680fe3720b81c1fd95532eacdd99cb Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Fri, 2 Jan 2026 17:56:19 +0000 Subject: [PATCH 04/14] Remove isValid to conceptually allow apps to interpret 'unknown' (to us) field names --- .../extractor/mp3/Mp3InfoReplayGain.java | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java index a52a2db767f..89d898649a7 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java @@ -17,7 +17,6 @@ import static java.lang.annotation.ElementType.TYPE_USE; -import android.annotation.SuppressLint; import androidx.annotation.IntDef; import androidx.media3.common.Metadata; import androidx.media3.common.util.UnstableApi; @@ -51,17 +50,17 @@ public static final class GainField { @Documented @Retention(RetentionPolicy.SOURCE) @Target(TYPE_USE) - @IntDef(value = {NAME_INVALID, NAME_RADIO, NAME_AUDIOPHILE}, open = true) + @IntDef(value = {NAME_UNSET, NAME_RADIO, NAME_AUDIOPHILE}, open = true) public @interface Name {} /** This gain field contains no valid data, and should be ignored. */ - public static final int NAME_INVALID = 0; + public static final int NAME_UNSET = 0; /** * A gain adjustment that makes all the tracks sound equally loud. * - *

This behaves like tracks do on the radio, hence the name. If the ReplayGain is calculated on a - * track-by-track basis (i.e. an individual ReplayGain calculation is carried out for each + *

This behaves like tracks do on the radio, hence the name. If the ReplayGain is calculated + * on a track-by-track basis (i.e. an individual ReplayGain calculation is carried out for each * track), this will be the result. */ public static final int NAME_RADIO = 1; @@ -69,8 +68,8 @@ public static final class GainField { /** * A gain adjustment that represents the ideal listening gain for each track. * - *

The problem with {@link #NAME_RADIO} is that tracks which should be quiet will be brought up - * to the level of all the rest. + *

The problem with {@link #NAME_RADIO} is that tracks which should be quiet will be brought + * up to the level of all the rest. * *

To solve this problem, the "Audiophile" setting represents the ideal listening gain for * each track. ReplayGain can have a good guess at this too, by reading the entire CD, and @@ -95,7 +94,7 @@ public static final class GainField { @Retention(RetentionPolicy.SOURCE) @Target(TYPE_USE) @IntDef(value = { - ORIGINATOR_UNKNOWN, + ORIGINATOR_UNSET, ORIGINATOR_ARTIST, ORIGINATOR_USER, ORIGINATOR_REPLAYGAIN, @@ -103,8 +102,8 @@ public static final class GainField { }, open = true) public @interface Originator {} - /** The origin of this gain adjustment is not known. */ - public static final int ORIGINATOR_UNKNOWN = 0; + /** The origin of this gain adjustment is not set. */ + public static final int ORIGINATOR_UNSET = 0; /** This gain adjustment was manually determined by the artist. */ public static final int ORIGINATOR_ARTIST = 1; @@ -121,7 +120,7 @@ public static final class GainField { /** * Name/type of the gain field. * - *

If equal to {@link #NAME_INVALID}, or an unknown name, the entire {@link GainField} should + *

If equal to {@link #NAME_UNSET}, or an unknown name, the entire {@link GainField} should * be ignored. */ public final @Name int name; @@ -148,20 +147,12 @@ public static final class GainField { /** * Parses an instance from the packed representation. * */ - private GainField(int field) { + private GainField(int field) { name = (field >> 13) & 7; originator = (field >> 10) & 7; gain = ((field & 0x1ff) * ((field & 0x200) != 0 ? -1 : 1)) / 10f; } - /** - * @return Whether the name field is set to a valid value, hence, whether this gain field should - * be considered or not. If false, the entire field should be ignored. - */ - public boolean isValid() { - return name == NAME_RADIO || name == NAME_AUDIOPHILE; - } - @Override public String toString() { return "GainField{" + "name=" + name + ", originator=" + originator + ", gain=" + gain + '}'; From 695bcf6e760cc8cc21780636318e33033ec87185 Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Fri, 2 Jan 2026 17:57:24 +0000 Subject: [PATCH 05/14] Format with google-java-format --- .../media3/extractor/mp3/Mp3Extractor.java | 7 ++-- .../extractor/mp3/Mp3InfoReplayGain.java | 36 +++++++++---------- .../extractor/mp3/Mp3ExtractorTest.java | 4 +-- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java index 2f14857b95b..469a30883a9 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java @@ -295,8 +295,11 @@ private int readInternal(ExtractorInput input) throws IOException { seeker = computeSeeker(input); extractorOutput.seekMap(seeker); Metadata metadata; - if (id3Metadata != null && (flags & FLAG_DISABLE_ID3_METADATA) == 0){ - metadata = infoMetadata != null ? id3Metadata.copyWithAppendedEntriesFrom(infoMetadata) : id3Metadata; + if (id3Metadata != null && (flags & FLAG_DISABLE_ID3_METADATA) == 0) { + metadata = + infoMetadata != null + ? id3Metadata.copyWithAppendedEntriesFrom(infoMetadata) + : id3Metadata; } else { metadata = infoMetadata; } diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java index 89d898649a7..9fb4007c8a3 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java @@ -44,13 +44,13 @@ public final class Mp3InfoReplayGain implements Metadata.Entry { /** A gain field can store one gain adjustment with name and originator metadata. */ public static final class GainField { - /** - * The name of a gain field. - */ + /** The name of a gain field. */ @Documented @Retention(RetentionPolicy.SOURCE) @Target(TYPE_USE) - @IntDef(value = {NAME_UNSET, NAME_RADIO, NAME_AUDIOPHILE}, open = true) + @IntDef( + value = {NAME_UNSET, NAME_RADIO, NAME_AUDIOPHILE}, + open = true) public @interface Name {} /** This gain field contains no valid data, and should be ignored. */ @@ -87,19 +87,19 @@ public static final class GainField { */ public static final int NAME_AUDIOPHILE = 2; - /** - * The originator of a gain field. - */ + /** The originator of a gain field. */ @Documented @Retention(RetentionPolicy.SOURCE) @Target(TYPE_USE) - @IntDef(value = { - ORIGINATOR_UNSET, - ORIGINATOR_ARTIST, - ORIGINATOR_USER, - ORIGINATOR_REPLAYGAIN, - ORIGINATOR_SIMPLE_RMS - }, open = true) + @IntDef( + value = { + ORIGINATOR_UNSET, + ORIGINATOR_ARTIST, + ORIGINATOR_USER, + ORIGINATOR_REPLAYGAIN, + ORIGINATOR_SIMPLE_RMS + }, + open = true) public @interface Originator {} /** The origin of this gain adjustment is not set. */ @@ -144,13 +144,11 @@ public static final class GainField { */ public final float gain; - /** - * Parses an instance from the packed representation. - * */ + /** Parses an instance from the packed representation. */ private GainField(int field) { name = (field >> 13) & 7; - originator = (field >> 10) & 7; - gain = ((field & 0x1ff) * ((field & 0x200) != 0 ? -1 : 1)) / 10f; + originator = (field >> 10) & 7; + gain = ((field & 0x1ff) * ((field & 0x200) != 0 ? -1 : 1)) / 10f; } @Override diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java index df47793f7e3..cf720fdc048 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java @@ -321,7 +321,7 @@ public void sampleWith200kBGarbagePrefix_sniffingFailsAfterPeeking128kB() throws @Test public void sampleWithLameReplayGainFast( @TestParameter(valuesProvider = ExtractorAsserts.ConfigProvider.class) - ExtractorAsserts.SimulationConfig simulationConfig) + ExtractorAsserts.SimulationConfig simulationConfig) throws Exception { ExtractorAsserts.assertBehavior( Mp3Extractor::new, @@ -333,7 +333,7 @@ public void sampleWithLameReplayGainFast( @Test public void sampleWithLameReplayGainAccurate( @TestParameter(valuesProvider = ExtractorAsserts.ConfigProvider.class) - ExtractorAsserts.SimulationConfig simulationConfig) + ExtractorAsserts.SimulationConfig simulationConfig) throws Exception { ExtractorAsserts.assertBehavior( Mp3Extractor::new, From b08586f4b5d0534a62790731a531f832029d6510 Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Fri, 2 Jan 2026 18:01:06 +0000 Subject: [PATCH 06/14] Add release note --- RELEASENOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index efcb086435b..bb2bb34788c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -36,6 +36,8 @@ media speed with `setSpeed()`. * Track Selection: * Extractors: + * MP3: Parse LAME ReplayGain data + ([#2840](https://github.com/androidx/media/pull/2840)). * Inspector: * Audio: * Change underlying decoding library for IAMF decoder extension from From 6f746ba1f6d4bee1c51999325117d41cf0b29296 Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Fri, 2 Jan 2026 18:16:31 +0000 Subject: [PATCH 07/14] Re-add lint suppression with explanatory comment --- .../java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java index 9fb4007c8a3..2b46a9dfa47 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java @@ -145,6 +145,8 @@ public static final class GainField { public final float gain; /** Parses an instance from the packed representation. */ + // Lint incorrectly thinks we're doing bitwise flag manipulation. + @SuppressWarnings("WrongConstant") private GainField(int field) { name = (field >> 13) & 7; originator = (field >> 10) & 7; From 76bbe1a54914217b9cc0f0133ddaa946ffe7dff4 Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Fri, 2 Jan 2026 18:18:00 +0000 Subject: [PATCH 08/14] Rename infoMetadata to xingMetadata for consistency with xingFrame --- .../androidx/media3/extractor/mp3/Mp3Extractor.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java index 469a30883a9..5c3a910d12f 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java @@ -177,7 +177,7 @@ public final class Mp3Extractor implements Extractor { private int synchronizedHeaderData; @Nullable private Metadata id3Metadata; - @Nullable private Metadata infoMetadata; + @Nullable private Metadata xingMetadata; private long basisTimeUs; private long samplesRead; private long firstSamplePosition; @@ -297,11 +297,11 @@ private int readInternal(ExtractorInput input) throws IOException { Metadata metadata; if (id3Metadata != null && (flags & FLAG_DISABLE_ID3_METADATA) == 0) { metadata = - infoMetadata != null - ? id3Metadata.copyWithAppendedEntriesFrom(infoMetadata) + xingMetadata != null + ? id3Metadata.copyWithAppendedEntriesFrom(xingMetadata) : id3Metadata; } else { - metadata = infoMetadata; + metadata = xingMetadata; } Format.Builder format = new Format.Builder() @@ -593,7 +593,7 @@ private Seeker maybeReadSeekFrame(ExtractorInput input) throws IOException { gaplessInfoHolder.encoderDelay = xingFrame.encoderDelay; gaplessInfoHolder.encoderPadding = xingFrame.encoderPadding; } - infoMetadata = xingFrame.getMetadata(); + xingMetadata = xingFrame.getMetadata(); long startPosition = input.getPosition(); if (input.getLength() != C.LENGTH_UNSET && xingFrame.dataSize != C.LENGTH_UNSET From d9b6f84f1ce3739f48a522c16faf3d04c31815e2 Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Fri, 2 Jan 2026 18:20:02 +0000 Subject: [PATCH 09/14] Move @Nullable annotations to correct place --- .../main/java/androidx/media3/extractor/mp3/XingFrame.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java index e4a763bf248..f9c2d4feada 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java @@ -37,7 +37,7 @@ public final long dataSize; /** ReplayGain data. Only present if this frame is an Info or the LAME variant of a Xing frame. */ - public final @Nullable Mp3InfoReplayGain replayGain; + @Nullable public final Mp3InfoReplayGain replayGain; /** * The number of samples to skip at the start of the stream, or {@link C#LENGTH_UNSET} if not @@ -156,7 +156,7 @@ public long computeDurationUs() { } /** Provide the metadata derived from this Xing frame, such as ReplayGain data. */ - public @Nullable Metadata getMetadata() { + @Nullable public Metadata getMetadata() { if (replayGain != null) { return new Metadata(replayGain); } From 7d8e46d8ab5d884e5b27004037665214c1f4a473 Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Mon, 5 Jan 2026 10:18:23 +0000 Subject: [PATCH 10/14] Add missing @Nullable to equals() overrides --- .../androidx/media3/extractor/mp3/Mp3InfoReplayGain.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java index 2b46a9dfa47..7de3028d3e7 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java @@ -18,6 +18,7 @@ import static java.lang.annotation.ElementType.TYPE_USE; import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import androidx.media3.common.Metadata; import androidx.media3.common.util.UnstableApi; import java.lang.annotation.Documented; @@ -159,7 +160,7 @@ public String toString() { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (!(o instanceof GainField)) { return false; } @@ -203,7 +204,7 @@ public String toString() { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (!(o instanceof Mp3InfoReplayGain)) { return false; } From b8d30c14ffce1ec49b6f962e61dec7be7c2573ee Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Tue, 6 Jan 2026 10:42:27 +0000 Subject: [PATCH 11/14] Ignore replay gain entries where both fields are unset --- .../extractor/mp3/Mp3InfoReplayGain.java | 84 +++++++++++++------ .../media3/extractor/mp3/XingFrame.java | 5 +- .../mp3/bear-id3-numeric-genre.mp3.0.dump | 2 +- .../mp3/bear-id3-numeric-genre.mp3.1.dump | 2 +- .../mp3/bear-id3-numeric-genre.mp3.2.dump | 2 +- .../mp3/bear-id3-numeric-genre.mp3.3.dump | 2 +- ...-id3-numeric-genre.mp3.unknown_length.dump | 2 +- .../mp3/bear-id3.mp3.id3-disabled.0.dump | 1 - .../mp3/bear-id3.mp3.id3-disabled.1.dump | 1 - .../mp3/bear-id3.mp3.id3-disabled.2.dump | 1 - .../mp3/bear-id3.mp3.id3-disabled.3.dump | 1 - ...r-id3.mp3.id3-disabled.unknown_length.dump | 1 - .../mp3/bear-id3.mp3.id3-enabled.0.dump | 2 +- .../mp3/bear-id3.mp3.id3-enabled.1.dump | 2 +- .../mp3/bear-id3.mp3.id3-enabled.2.dump | 2 +- .../mp3/bear-id3.mp3.id3-enabled.3.dump | 2 +- ...ar-id3.mp3.id3-enabled.unknown_length.dump | 2 +- .../bear-vbr-xing-header-no-toc.mp3.0.dump | 2 +- ...eader-no-toc.mp3.cbr-seeking-always.0.dump | 2 +- ...eader-no-toc.mp3.cbr-seeking-always.1.dump | 2 +- ...eader-no-toc.mp3.cbr-seeking-always.2.dump | 2 +- ...eader-no-toc.mp3.cbr-seeking-always.3.dump | 2 +- ...mp3.cbr-seeking-always.unknown_length.dump | 2 +- ...-xing-header-no-toc.mp3.cbr-seeking.0.dump | 2 +- ...-xing-header-no-toc.mp3.cbr-seeking.1.dump | 2 +- ...-xing-header-no-toc.mp3.cbr-seeking.2.dump | 2 +- ...-xing-header-no-toc.mp3.cbr-seeking.3.dump | 2 +- ...no-toc.mp3.cbr-seeking.unknown_length.dump | 2 +- ...ing-header-no-toc.mp3.index-seeking.0.dump | 2 +- ...ing-header-no-toc.mp3.index-seeking.1.dump | 2 +- ...ing-header-no-toc.mp3.index-seeking.2.dump | 2 +- ...ing-header-no-toc.mp3.index-seeking.3.dump | 2 +- ...-toc.mp3.index-seeking.unknown_length.dump | 2 +- ...xing-header-no-toc.mp3.unknown_length.dump | 2 +- ...xing-header-replaygain-accurate.mp3.0.dump | 2 +- ...xing-header-replaygain-accurate.mp3.1.dump | 2 +- ...xing-header-replaygain-accurate.mp3.2.dump | 2 +- ...xing-header-replaygain-accurate.mp3.3.dump | 2 +- ...eplaygain-accurate.mp3.unknown_length.dump | 2 +- ...vbr-xing-header-replaygain-fast.mp3.0.dump | 2 +- ...vbr-xing-header-replaygain-fast.mp3.1.dump | 2 +- ...vbr-xing-header-replaygain-fast.mp3.2.dump | 2 +- ...vbr-xing-header-replaygain-fast.mp3.3.dump | 2 +- ...er-replaygain-fast.mp3.unknown_length.dump | 2 +- .../mp3/bear-vbr-xing-header.mp3.0.dump | 2 +- .../mp3/bear-vbr-xing-header.mp3.1.dump | 2 +- .../mp3/bear-vbr-xing-header.mp3.2.dump | 2 +- .../mp3/bear-vbr-xing-header.mp3.3.dump | 2 +- ...ar-vbr-xing-header.mp3.unknown_length.dump | 2 +- ...test-cbr-info-header-pcut-frame.mp3.0.dump | 2 +- ...test-cbr-info-header-pcut-frame.mp3.1.dump | 2 +- ...test-cbr-info-header-pcut-frame.mp3.2.dump | 2 +- ...test-cbr-info-header-pcut-frame.mp3.3.dump | 2 +- ...-header-pcut-frame.mp3.unknown_length.dump | 2 +- .../mp3/test-cbr-info-header.mp3.0.dump | 2 +- .../mp3/test-cbr-info-header.mp3.1.dump | 2 +- .../mp3/test-cbr-info-header.mp3.2.dump | 2 +- .../mp3/test-cbr-info-header.mp3.3.dump | 2 +- ...st-cbr-info-header.mp3.unknown_length.dump | 2 +- 59 files changed, 113 insertions(+), 85 deletions(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java index 7de3028d3e7..367d1af5fdf 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Android Open Source Project + * Copyright 2026 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package androidx.media3.extractor.mp3; +import static com.google.common.base.Preconditions.checkArgument; import static java.lang.annotation.ElementType.TYPE_USE; import androidx.annotation.IntDef; @@ -50,13 +51,10 @@ public static final class GainField { @Retention(RetentionPolicy.SOURCE) @Target(TYPE_USE) @IntDef( - value = {NAME_UNSET, NAME_RADIO, NAME_AUDIOPHILE}, + value = {NAME_RADIO, NAME_AUDIOPHILE}, open = true) public @interface Name {} - /** This gain field contains no valid data, and should be ignored. */ - public static final int NAME_UNSET = 0; - /** * A gain adjustment that makes all the tracks sound equally loud. * @@ -118,12 +116,7 @@ public static final class GainField { /** This gain adjustment was automatically determined by a simple RMS algorithm. */ public static final int ORIGINATOR_SIMPLE_RMS = 4; - /** - * Name/type of the gain field. - * - *

If equal to {@link #NAME_UNSET}, or an unknown name, the entire {@link GainField} should - * be ignored. - */ + /** Name/type of the gain field. */ public final @Name int name; /** @@ -145,13 +138,31 @@ public static final class GainField { */ public final float gain; - /** Parses an instance from the packed representation. */ // Lint incorrectly thinks we're doing bitwise flag manipulation. @SuppressWarnings("WrongConstant") - private GainField(int field) { - name = (field >> 13) & 7; - originator = (field >> 10) & 7; - gain = ((field & 0x1ff) * ((field & 0x200) != 0 ? -1 : 1)) / 10f; + private GainField(@Name int name, @Originator int originator, float gain) { + this.name = name; + this.originator = originator; + this.gain = gain; + } + + /** + * Parses an instance from the packed representation. + * + *

Returns {@code null} if the representation is invalid or should be ignored (e.g. {@code + * name} is unset). + */ + // Lint incorrectly thinks we're doing bitwise flag manipulation. + @SuppressWarnings("WrongConstant") + @Nullable + private static GainField parse(int field) { + int name = (field >> 13) & 7; + if (name == 0) { + return null; + } + int originator = (field >> 10) & 7; + float gain = ((field & 0x1ff) * ((field & 0x200) != 0 ? -1 : 1)) / 10f; + return new GainField(name, originator, gain); } @Override @@ -179,17 +190,38 @@ public int hashCode() { } } - /** The first of two gain fields in the LAME MP3 Info header. */ - public GainField field1; + /** + * The first of two gain fields in the LAME MP3 Info header, or null if the field is invalid or + * unset. + */ + @Nullable public GainField field1; - /** The second of two gain fields in the LAME MP3 Info header. */ - public GainField field2; + /** + * The second of two gain fields in the LAME MP3 Info header, or null if the field is invalid or + * unset. + */ + @Nullable public GainField field2; - /** Creates the gain fields from the packed representation. */ - public Mp3InfoReplayGain(float peak, int field1, int field2) { + private Mp3InfoReplayGain(float peak, @Nullable GainField field1, @Nullable GainField field2) { + checkArgument(field1 != null || field2 != null); this.peak = peak; - this.field1 = new GainField(field1); - this.field2 = new GainField(field2); + this.field1 = field1; + this.field2 = field2; + } + + /** + * Parses an instance from the packed representation. + * + *

Returns null if both {@code field1} and {@code field2} are invalid or should be ignored. + */ + @Nullable + public static Mp3InfoReplayGain parse(float peak, int field1, int field2) { + GainField parsedField1 = GainField.parse(field1); + GainField parsedField2 = GainField.parse(field2); + if (parsedField1 == null && parsedField2 == null) { + return null; + } + return new Mp3InfoReplayGain(peak, parsedField1, parsedField2); } @Override @@ -217,8 +249,8 @@ public boolean equals(@Nullable Object o) { @Override public int hashCode() { int result = Float.hashCode(peak); - result = 31 * result + field1.hashCode(); - result = 31 * result + field2.hashCode(); + result = 31 * result + (field1 != null ? field1.hashCode() : 0); + result = 31 * result + (field2 != null ? field2.hashCode() : 0); return result; } } diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java index f9c2d4feada..b62e0f074e2 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/XingFrame.java @@ -117,7 +117,7 @@ public static XingFrame parse(MpegAudioUtil.Header mpegAudioHeader, ParsableByte float peak = frame.readFloat(); int field1 = frame.readUnsignedShort(); int field2 = frame.readUnsignedShort(); - replayGain = new Mp3InfoReplayGain(peak, field1, field2); + replayGain = Mp3InfoReplayGain.parse(peak, field1, field2); frame.skipBytes(bytesToSkipAfterReplayGain); int encoderDelayAndPadding = frame.readUnsignedInt24(); @@ -156,7 +156,8 @@ public long computeDurationUs() { } /** Provide the metadata derived from this Xing frame, such as ReplayGain data. */ - @Nullable public Metadata getMetadata() { + @Nullable + public Metadata getMetadata() { if (replayGain != null) { return new Metadata(replayGain); } diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.0.dump index bd6f14987d2..bf3a6e0e45f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.0.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.1.dump index 356913d9f15..eafac7a6cca 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.1.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9]] sample 0: time = 943000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.2.dump index ee2e6b02e96..3f0892a6b4b 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.2.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9]] sample 0: time = 1879000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.3.dump index d7f73b8d220..fe26e0b0756 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.3.dump @@ -18,5 +18,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9]] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.unknown_length.dump index bd6f14987d2..bf3a6e0e45f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3-numeric-genre.mp3.unknown_length.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[9]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.0.dump index f7c05d68670..8b84b79047d 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.0.dump @@ -18,7 +18,6 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.1.dump index 17a123908d4..2a75c2bb3f7 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.1.dump @@ -18,7 +18,6 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 943000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.2.dump index 2dc09c77b20..8cf7cddb906 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.2.dump @@ -18,7 +18,6 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 1879000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.3.dump index cd0b3284c92..8f32b9426a9 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.3.dump @@ -18,5 +18,4 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.unknown_length.dump index f7c05d68670..8b84b79047d 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-disabled.unknown_length.dump @@ -18,7 +18,6 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.0.dump index 59aa105956e..069b98e317f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.0.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.1.dump index 1e058e42755..5059438ec55 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.1.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore]] sample 0: time = 943000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.2.dump index cf3a8571e6f..16419ce6395 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.2.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore]] sample 0: time = 1879000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.3.dump index 89e1a0b5728..a0273aac08a 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.3.dump @@ -18,5 +18,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore]] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.unknown_length.dump index 59aa105956e..069b98e317f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-id3.mp3.id3-enabled.unknown_length.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TIT2: description=null: values=[Test title], TPE1: description=null: values=[Test Artist], TALB: description=null: values=[Test Album], TXXX: description=Test description: values=[Test user info], COMM: language=eng, description=Test description, text=Test comment, WXXX: url=Test URL, TSSE: description=null: values=[Lavf58.29.100], MLLT, PRIV: owner=test@gmail.com, UNKN, GEOB: mimeType=test/mime, filename=Testfilename.txt, description=Test description, CHAP, CHAP, CTOC, APIC: mimeType=image/jpeg, description=Test description, TCON: description=null: values=[Gorpcore]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.0.dump index 63ed6bdec24..5cfd3266218 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.0.dump @@ -16,7 +16,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.0.dump index a3b9c1c9051..deb9adcbd9d 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.1.dump index 79ababb2d7f..8cebd97c777 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 943055 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.2.dump index 3c8b7abd4ae..ee5e5a6f7d0 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 1879045 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.3.dump index 068c2ec81c0..daec3f68336 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.3.dump @@ -19,5 +19,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.unknown_length.dump index a3b9c1c9051..deb9adcbd9d 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking-always.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.0.dump index a3b9c1c9051..deb9adcbd9d 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.1.dump index 79ababb2d7f..8cebd97c777 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 943055 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.2.dump index 3c8b7abd4ae..ee5e5a6f7d0 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 1879045 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.3.dump index 068c2ec81c0..daec3f68336 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.3.dump @@ -19,5 +19,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.unknown_length.dump index a3b9c1c9051..deb9adcbd9d 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.cbr-seeking.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.0.dump index 706bde3a36f..c1fb30310ef 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.0.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.1.dump index 1883df980be..07aaf5caa82 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.1.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 840000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.2.dump index 102d3dfe463..62fdef977d9 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.2.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 1800000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.3.dump index 08aaa060442..9ec7986fb60 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.3.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 2760000 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.unknown_length.dump index 706bde3a36f..c1fb30310ef 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.index-seeking.unknown_length.dump @@ -18,7 +18,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.unknown_length.dump index 63ed6bdec24..5cfd3266218 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-no-toc.mp3.unknown_length.dump @@ -16,7 +16,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.0.dump index 9aa7068113c..3f4a5e2991a 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=null] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.1.dump index d5e0e76cef9..d4564f9757e 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=null] sample 0: time = 911992 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.2.dump index e2a4f83b096..40372d30314 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=null] sample 0: time = 1847985 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.3.dump index 700732389ce..2d705c22f7b 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.3.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=null] sample 0: time = 2783978 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.unknown_length.dump index 9aa7068113c..3f4a5e2991a 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-accurate.mp3.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=8.14048E-40, field 1=GainField{name=1, originator=3, gain=23.3}, field 2=null] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.0.dump index 3f8adaa10b9..457facc2495 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=null] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.1.dump index e826f19ee86..2ae4be63a28 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=null] sample 0: time = 911992 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.2.dump index a2e7c578b4b..176b1e30fc9 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=null] sample 0: time = 1847985 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.3.dump index c7339786041..649cd2e6565 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.3.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=null] sample 0: time = 2783978 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.unknown_length.dump index 3f8adaa10b9..457facc2495 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header-replaygain-fast.mp3.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=23.0}, field 2=null] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.0.dump index ea1713da08a..9dde5408e01 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.1.dump index c9114e76833..b47319b0f7c 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 958033 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.2.dump index 10f0a3a99fa..7eabbad4cb7 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 1886757 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.3.dump index fb419ec0376..47ba03e7576 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.3.dump @@ -19,5 +19,5 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.unknown_length.dump index ea1713da08a..9dde5408e01 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-vbr-xing-header.mp3.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 48000 encoderDelay = 576 encoderPadding = 576 - metadata = entries=[TSSE: description=null: values=[Lavf58.29.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.29.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.0.dump index 12618852b59..08c75fa3453 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.1.dump index d1d1427df9e..cd171718f2c 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] sample 0: time = 356871 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.2.dump index fcea591b5d6..103044e917a 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] sample 0: time = 727157 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.3.dump index de3fe7654b7..5f40a3c8a4d 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.3.dump @@ -19,5 +19,5 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.unknown_length.dump index 12618852b59..08c75fa3453 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header-pcut-frame.mp3.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.0.dump index 10bd2ce865b..adffb2383f0 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.0.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.1.dump index b10b292a04b..60efc784e76 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.1.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.1.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] sample 0: time = 365625 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.2.dump index 5e11eaa2d37..8e6b025b683 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.2.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.2.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] sample 0: time = 705250 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.3.dump index 1abd645c3a2..796a47b3615 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.3.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.3.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] sample 0: time = 1018750 flags = 1 diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.unknown_length.dump index 10bd2ce865b..adffb2383f0 100644 --- a/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/test-cbr-info-header.mp3.unknown_length.dump @@ -19,7 +19,7 @@ track 0: sampleRate = 44100 encoderDelay = 576 encoderPadding = 1404 - metadata = entries=[TSSE: description=null: values=[Lavf58.45.100], ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=0, originator=0, gain=0.0}, field 2=GainField{name=0, originator=0, gain=0.0}] + metadata = entries=[TSSE: description=null: values=[Lavf58.45.100]] sample 0: time = 0 flags = 1 From 8c91eae481fe3019567125ae3c0ed2e521e767bb Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Tue, 6 Jan 2026 11:07:12 +0000 Subject: [PATCH 12/14] Ignore replay gain entries with zero or negative peak values --- .../java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java index 367d1af5fdf..6e44fbec246 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java @@ -212,13 +212,13 @@ private Mp3InfoReplayGain(float peak, @Nullable GainField field1, @Nullable Gain /** * Parses an instance from the packed representation. * - *

Returns null if both {@code field1} and {@code field2} are invalid or should be ignored. + *

Returns null if the representation is invalid or should be ignored. */ @Nullable public static Mp3InfoReplayGain parse(float peak, int field1, int field2) { GainField parsedField1 = GainField.parse(field1); GainField parsedField2 = GainField.parse(field2); - if (parsedField1 == null && parsedField2 == null) { + if (peak <= 0 || parsedField1 == null && parsedField2 == null) { return null; } return new Mp3InfoReplayGain(peak, parsedField1, parsedField2); From 21e557c41cdec6767b7741f91cf2d4556296d044 Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Tue, 6 Jan 2026 11:29:04 +0000 Subject: [PATCH 13/14] Tweak gain check to be and'd with null field checks --- .../java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java index 6e44fbec246..432dfb4702f 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java @@ -218,7 +218,7 @@ private Mp3InfoReplayGain(float peak, @Nullable GainField field1, @Nullable Gain public static Mp3InfoReplayGain parse(float peak, int field1, int field2) { GainField parsedField1 = GainField.parse(field1); GainField parsedField2 = GainField.parse(field2); - if (peak <= 0 || parsedField1 == null && parsedField2 == null) { + if (peak <= 0 && parsedField1 == null && parsedField2 == null) { return null; } return new Mp3InfoReplayGain(peak, parsedField1, parsedField2); From eccedd1e8ce1e3ab0f0d9903d44b5ab3925ce637 Mon Sep 17 00:00:00 2001 From: Ian Baker Date: Tue, 6 Jan 2026 13:47:31 +0000 Subject: [PATCH 14/14] Resolve review feedback --- .../extractor/mp3/Mp3InfoReplayGain.java | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java index 432dfb4702f..6f7866d9bc4 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3InfoReplayGain.java @@ -15,7 +15,6 @@ */ package androidx.media3.extractor.mp3; -import static com.google.common.base.Preconditions.checkArgument; import static java.lang.annotation.ElementType.TYPE_USE; import androidx.annotation.IntDef; @@ -31,17 +30,6 @@ /** Representation of the ReplayGain data stored in a LAME Xing or Info frame. */ @UnstableApi public final class Mp3InfoReplayGain implements Metadata.Entry { - /** - * 32 bit floating point "Peak signal amplitude". - * - *

1.0 is maximal signal amplitude store-able in decoding format. 0.8 is 80% of maximal signal - * amplitude store-able in decoding format. 1.5 is 150% of maximal signal amplitude store-able in - * decoding format. - * - *

A value above 1.0 can occur for example due to "true peak" measurement. A value of 0.0 means - * the peak signal amplitude is unknown. - */ - public final float peak; /** A gain field can store one gain adjustment with name and originator metadata. */ public static final class GainField { @@ -190,6 +178,18 @@ public int hashCode() { } } + /** + * 32 bit floating point "Peak signal amplitude". + * + *

1.0 is maximal signal amplitude store-able in decoding format. 0.8 is 80% of maximal signal + * amplitude store-able in decoding format. 1.5 is 150% of maximal signal amplitude store-able in + * decoding format. + * + *

A value above 1.0 can occur for example due to "true peak" measurement. A value of 0.0 means + * the peak signal amplitude is unknown. + */ + public final float peak; + /** * The first of two gain fields in the LAME MP3 Info header, or null if the field is invalid or * unset. @@ -203,7 +203,6 @@ public int hashCode() { @Nullable public GainField field2; private Mp3InfoReplayGain(float peak, @Nullable GainField field1, @Nullable GainField field2) { - checkArgument(field1 != null || field2 != null); this.peak = peak; this.field1 = field1; this.field2 = field2;