X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsonitus%2Fio%2Fmp3%2FFrame.java;h=ad91a913caef259dd7b15d9c3705884c47bdc1eb;hb=404a2cee82a4e0c0283d578fbf4345744c04d697;hp=1d3a3505e7d169a3ece9e46b479c5f69e71366cb;hpb=5e7624c78c82e47a5d6040ac27186e55f5ff4c8f;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 1d3a350..ad91a91 100644 --- a/src/main/java/net/pterodactylus/sonitus/io/mp3/Frame.java +++ b/src/main/java/net/pterodactylus/sonitus/io/mp3/Frame.java @@ -22,11 +22,12 @@ 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; /** * A single MPEG audio frame. + *

+ * This uses information from mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm. * * @author David ‘Bombe’ Roden */ @@ -130,7 +131,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(); @@ -206,15 +207,43 @@ public class Frame { private final int modeExtension; /** The decoded copyright bit. */ - private final int copyright; + private final int copyrightBit; /** The deocded original bit. */ - private final int original; + private final int originalBit; /** The decoded emphasis mode. */ private final int emphasis; - private Frame(int mpegAudioVersionId, int layerDescription, int protectionBit, int bitrateIndex, int samplingRateFrequencyIndex, int paddingBit, int privateBit, int channelMode, int modeExtension, int copyright, int original, int emphasis) { + /** + * Creates a new frame from the given values. + * + * @param mpegAudioVersionId + * The MPEG audio version ID + * @param layerDescription + * The layer description + * @param protectionBit + * The protection bit + * @param bitrateIndex + * The bitrate index + * @param samplingRateFrequencyIndex + * The sampling rate frequency index + * @param paddingBit + * The padding bit + * @param privateBit + * The private bit + * @param channelMode + * The channel mode + * @param modeExtension + * The mode extension + * @param copyrightBit + * The copyright bit + * @param originalBit + * The original bit + * @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) { this.mpegAudioVersionId = mpegAudioVersionId; this.layerDescription = layerDescription; this.protectionBit = protectionBit; @@ -224,8 +253,8 @@ public class Frame { this.privateBit = privateBit; this.channelMode = channelMode; this.modeExtension = modeExtension; - this.copyright = copyright; - this.original = original; + this.copyrightBit = copyrightBit; + this.originalBit = originalBit; this.emphasis = emphasis; } @@ -233,48 +262,103 @@ public class Frame { // ACCESSORS // + /** + * Returns the MPEG audio version. + * + * @return The MPEG audio version + */ public MpegAudioVersion mpegAudioVersion() { return MpegAudioVersion.values()[mpegAudioVersionId]; } + /** + * Returns the layer description. + * + * @return The layer description + */ public LayerDescription layerDescription() { return LayerDescription.values()[layerDescription]; } + /** + * Returns the protection bit. + * + * @return {@code true} if the protection bit is set, {@code false} otherwise + */ public boolean protectionBit() { return protectionBit != 0; } + /** + * Returns the bitrate of this frame. + * + * @return The bitrate of this frame (in kbps) + */ public int bitrate() { return bitrateSupplier.get().get(mpegAudioVersion()).get(layerDescription()).get(bitrateIndex); } + /** + * Returns the sampling rate of the audio data in this frame. + * + * @return The sample rate (in Hertz) + */ public int samplingRate() { return samplingRateSupplier.get().get(mpegAudioVersion()).get(samplingRateFrequencyIndex); } + /** + * Returns the padding bit. + * + * @return {@code true} if the padding bit is set, {@code false} otherwise + */ public boolean paddingBit() { return paddingBit != 0; } + /** + * Returns the private bit. + * + * @return {@code true} if the private bit is set, {@code false} otherwise + */ public boolean privateBit() { return privateBit != 0; } + /** + * Returns the channel mode. + * + * @return The channel mode + */ public ChannelMode channelMode() { return ChannelMode.values()[channelMode]; } /* TODO - mode extension. */ + /** + * Returns the copyright bit. + * + * @return {@code true} if the copyright bit is set, {@code false} otherwise + */ public boolean copyrightBit() { - return copyright != 0; + return copyrightBit != 0; } + /** + * Returns the original bit. + * + * @return {@code true} if the original bit is set, {@code false} otherwise + */ public boolean originalBit() { - return original != 0; + return originalBit != 0; } + /** + * Returns the emphasis. + * + * @return The emphasis + */ public Emphasis emphasis() { return Emphasis.values()[emphasis]; } @@ -283,10 +367,34 @@ public class Frame { // STATIC METHODS // + /** + * Returns whether the data beginning at the given offset is an MPEG audio + * frame. + * + * @param buffer + * The buffer in which the data is stored + * @param offset + * The beginning of the data to parse + * @param length + * The length of the data to parse + * @return {@code true} if the data at the given offset is an MPEG audio frame + */ public static boolean isFrame(byte[] buffer, int offset, int length) { - return (((buffer[offset] & 0xff) == 0xff) && ((buffer[offset + 1] & 0xe0) == 0xe0)); + return (length > 3) && (((buffer[offset] & 0xff) == 0xff) && ((buffer[offset + 1] & 0xe0) == 0xe0)); } + /** + * Tries to create an MPEG audio from the given data. + * + * @param buffer + * The buffer in which the data is stored + * @param offset + * The offset at which to look for a frame + * @param length + * The length of the data in the buffer + * @return The frame if it could be parsed, or {@link Optional#absent()} if no + * frame could be found + */ public static Optional create(byte[] buffer, int offset, int length) { if (isFrame(buffer, offset, length)) { int mpegAudioVersionId = (buffer[offset + 1] & 0x18) >>> 3;