Do not use a BiMap.
[sonitus.git] / src / main / java / net / pterodactylus / sonitus / io / mp3 / Frame.java
index 7c7e6cd..ad91a91 100644 (file)
@@ -22,7 +22,6 @@ 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 +131,7 @@ public class Frame {
                        mpegAudioVersionMapBuilder.put(MpegAudioVersion.VERSION_1, mpeg1Builder.build());
 
                        /* MPEG 2 & 2.5. */
-                       ImmutableBiMap.Builder<LayerDescription, Map<Integer, Integer>> mpeg2Builder = ImmutableBiMap.builder();
+                       ImmutableMap.Builder<LayerDescription, Map<Integer, Integer>> mpeg2Builder = ImmutableMap.builder();
 
                        /* Layer 1. */
                        bitrates = ImmutableMap.builder();
@@ -208,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;
@@ -226,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;
        }
 
@@ -235,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];
        }
@@ -285,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<Frame> create(byte[] buffer, int offset, int length) {
                if (isFrame(buffer, offset, length)) {
                        int mpegAudioVersionId = (buffer[offset + 1] & 0x18) >>> 3;