X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsonitus%2Fio%2Fmp3%2FFrame.java;h=b157e2cde5a704eff5cfc4e559fc80fc1c49ca7c;hb=1b5da82617f1ba7e569c63daf4fb981d0fd7f406;hp=e6b38e018d5a8030b00938617c3700da4f2eaab7;hpb=57a36679c1eb2189a2aaaea4ce18bdd7cda69a2b;p=sonitus.git diff --git a/src/main/java/net/pterodactylus/sonitus/io/mp3/Frame.java b/src/main/java/net/pterodactylus/sonitus/io/mp3/Frame.java index e6b38e0..b157e2c 100644 --- a/src/main/java/net/pterodactylus/sonitus/io/mp3/Frame.java +++ b/src/main/java/net/pterodactylus/sonitus/io/mp3/Frame.java @@ -17,12 +17,12 @@ package net.pterodactylus.sonitus.io.mp3; +import java.util.Arrays; import java.util.Map; import com.google.common.base.Optional; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; -import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableMap; /** @@ -132,7 +132,7 @@ public class Frame { mpegAudioVersionMapBuilder.put(MpegAudioVersion.VERSION_1, mpeg1Builder.build()); /* MPEG 2 & 2.5. */ - ImmutableBiMap.Builder> mpeg2Builder = ImmutableBiMap.builder(); + ImmutableMap.Builder> mpeg2Builder = ImmutableMap.builder(); /* Layer 1. */ bitrates = ImmutableMap.builder(); @@ -216,6 +216,9 @@ public class Frame { /** The decoded emphasis mode. */ private final int emphasis; + /** The content of the frame. */ + private final byte[] content; + /** * Creates a new frame from the given values. * @@ -244,7 +247,7 @@ public class Frame { * @param emphasis * The emphasis */ - private Frame(int mpegAudioVersionId, int layerDescription, int protectionBit, int bitrateIndex, int samplingRateFrequencyIndex, int paddingBit, int privateBit, int channelMode, int modeExtension, int copyrightBit, int originalBit, int emphasis) { + private Frame(int mpegAudioVersionId, int layerDescription, int protectionBit, int bitrateIndex, int samplingRateFrequencyIndex, int paddingBit, int privateBit, int channelMode, int modeExtension, int copyrightBit, int originalBit, int emphasis, byte[] content) { this.mpegAudioVersionId = mpegAudioVersionId; this.layerDescription = layerDescription; this.protectionBit = protectionBit; @@ -257,6 +260,7 @@ public class Frame { this.copyrightBit = copyrightBit; this.originalBit = originalBit; this.emphasis = emphasis; + this.content = content; } // @@ -364,6 +368,15 @@ public class Frame { return Emphasis.values()[emphasis]; } + /** + * Returns the content of this frame. + * + * @return The content of this frame + */ + public byte[] content() { + return content; + } + // // STATIC METHODS // @@ -385,6 +398,33 @@ public class Frame { } /** + * Calculates the frame length in bytes for the frame starting at the given + * offset in the given buffer. This method should only be called for a buffer + * and an offset for which {@link #isFrame(byte[], int, int)} returns {@code + * true}. + * + * @param buffer + * The buffer storing the frame + * @param offset + * The offset of the frame + * @return The length of the frame in bytes, or {@code -1} if the frame length + * can not be calculated + */ + public static int getFrameLength(byte[] buffer, int offset) { + MpegAudioVersion mpegAudioVersion = MpegAudioVersion.values()[(buffer[offset + 1] & 0x18) >>> 3]; + LayerDescription layerDescription = LayerDescription.values()[(buffer[offset + 1] & 0x06) >>> 1]; + int bitrate = bitrateSupplier.get().get(mpegAudioVersion).get(layerDescription).get((buffer[offset + 2] & 0xf0) >>> 4) * 1000; + int samplingRate = samplingRateSupplier.get().get(mpegAudioVersion).get((buffer[offset + 2] & 0x0c) >>> 2); + int paddingBit = (buffer[offset + 2] & 0x02) >>> 1; + if (layerDescription == LayerDescription.LAYER_1) { + return (12 * bitrate / samplingRate + paddingBit) * 4; + } else if ((layerDescription == LayerDescription.LAYER_2) || (layerDescription == LayerDescription.LAYER_3)) { + return 144 * bitrate / samplingRate + paddingBit; + } + return -1; + } + + /** * Tries to create an MPEG audio from the given data. * * @param buffer @@ -410,7 +450,8 @@ public class Frame { int copyright = (buffer[offset + 3] & 0x08) >> 3; int original = (buffer[offset + 3] & 0x04) >> 2; int emphasis = buffer[offset + 3] & 0x03; - return Optional.of(new Frame(mpegAudioVersionId, layerDescription, protectionBit, bitrateIndex, samplingRateFrequencyIndex, paddingBit, privateBit, channelMode, modeExtension, copyright, original, emphasis)); + int frameLength = getFrameLength(buffer, offset); + return Optional.of(new Frame(mpegAudioVersionId, layerDescription, protectionBit, bitrateIndex, samplingRateFrequencyIndex, paddingBit, privateBit, channelMode, modeExtension, copyright, original, emphasis, Arrays.copyOfRange(buffer, 4, frameLength))); } return Optional.absent(); }