⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xingframe.java

📁 java+eclipse做的TTPlayer
💻 JAVA
字号:
package com.hadeslee.audiotag.audio.mp3;

import com.hadeslee.audiotag.audio.exceptions.InvalidAudioFrameException;

import java.nio.ByteBuffer;
import java.util.Arrays;

/**
 * Xing Frame
 *
 * <p>In some MP3s which variable bit rate the first frame in the file contains a special frame called a Xing Frame,
 * instead of audio data. This is used to store additional information about the file. The most important aspect for
 * this library is details allowing us to determine the bitrate of a Variable Bit Rate VBR file without having
 * to process the whole file.
 *
 * Xing VBR Tag data format is 120 bytes long
 *    4 bytes for Header Tag
 *    4 bytes for Header Flags
 *    4 bytes for FRAME SIZE
 *    4 bytes for AUDIO_SIZE
 *    100 bytes for entry (NUMTOCENTRIES)
 *    4 bytes for VBR SCALE. a VBR quality indicator: 0=best 100=worst
 *
 * It my then contain a Lame Frame ( a Lame frame is in essence an extended Xing Frame
 */
public class XingFrame
{

    //The offset into first frame varies based on the MPEG frame properties
    private static final int MPEG_VERSION_1_MODE_MONO_OFFSET    = 21;
    private static final int MPEG_VERSION_1_MODE_STEREO_OFFSET  = 36;
    private static final int MPEG_VERSION_2_MODE_MONO_OFFSET    = 13;
    private static final int MPEG_VERSION_2_MODE_STEREO_OFFSET  = 21;

    private static final int XING_HEADER_BUFFER_SIZE     = 120;
    private static final int XING_IDENTIFIER_BUFFER_SIZE = 4;
    private static final int XING_FLAG_BUFFER_SIZE       = 4;
    private static final int XING_FRAMECOUNT_BUFFER_SIZE = 4;
    private static final int XING_AUDIOSIZE_BUFFER_SIZE  = 4;

    public static final int MAX_BUFFER_SIZE_NEEDED_TO_READ_XING
          = MPEG_VERSION_1_MODE_STEREO_OFFSET +
            XING_HEADER_BUFFER_SIZE +
            LameFrame.LAME_HEADER_BUFFER_SIZE;


    private static final int BYTE_1 = 0;
    private static final int BYTE_2 = 1;
    private static final int BYTE_3 = 2;
    private static final int BYTE_4 = 3;

    /** Use when it is a VBR (Variable Bitrate) file */
    private static final byte[] XING_VBR_ID =  {'X', 'i', 'n','g'};

    /** Use when it is a CBR (Constant Bitrate) file */
    private static final byte[] XING_CBR_ID =  {'I','n','f','o'};


    private static ByteBuffer header;
    private static XingFrame  xingFrame = null;

    private boolean vbr = false;
    private boolean isFrameCountEnabled = false;
    private int frameCount = -1;
    private boolean isAudioSizeEnabled = false;
    private int audioSize = -1;
    private LameFrame lameFrame;

    /** Read the Xing Properties from the buffer */
    private XingFrame()
    {
        //Go to start of Buffer
        header.rewind();

        //Set Vbr
        setVbr();

        //Read Flags, only the fourth byte of interest to us
        byte flagBuffer[] = new byte[XING_FLAG_BUFFER_SIZE];
        header.get(flagBuffer);

        //Read FrameCount if flag set
        if ((flagBuffer[BYTE_4] & (byte) (1)) != 0)
        {
            setFrameCount();
        }

        //Read Size if flag set
        if ((flagBuffer[BYTE_4] & (byte) (1 << 1)) != 0)
        {
            setAudioSize();
        }

        //TODO TOC
        //TODO VBR Quality

        //Look for LAME Header as long as we have enough bytes to do it properly
        if(header.limit()>=XING_HEADER_BUFFER_SIZE + LameFrame.LAME_HEADER_BUFFER_SIZE)
        {
            header.position(XING_HEADER_BUFFER_SIZE);
            lameFrame = LameFrame.parseLameFrame(header);
        }
    }

    public LameFrame getLameFrame()
    {
        return lameFrame;
    }
    
    /** Set whether or not VBR, (Xing can also be used for CBR though this is less useful) */
    private void setVbr()
    {
        //Is it VBR or CBR
        byte [] identifier = new byte[XING_IDENTIFIER_BUFFER_SIZE];
        header.get(identifier);
        if (Arrays.equals(identifier,XING_VBR_ID))
        {
            MP3File.log.finest("Is Vbr");
            vbr=true;
        }
    }

    /**
     * Set count of frames
     */
    private void setFrameCount()
    {
        byte frameCountBuffer[] = new byte[XING_FRAMECOUNT_BUFFER_SIZE];
        header.get(frameCountBuffer);
        isFrameCountEnabled = true;
        frameCount = (frameCountBuffer[BYTE_1] << 24)&0xFF000000 |
            (frameCountBuffer[BYTE_2] << 16)&0x00FF0000 |
            (frameCountBuffer[BYTE_3] << 8)&0x0000FF00 |
            frameCountBuffer[BYTE_4]&0x000000FF;
    }

    /**
     *
     * @return true if frameCount has been specified in header
     */
    public final boolean isFrameCountEnabled()
    {
        return isFrameCountEnabled;
    }

    /**
     *
     * @return count of frames
     */
    public final int getFrameCount()
    {
        return frameCount;
    }

    /**
     * Set size of AudioData
     */
    private void setAudioSize()
    {
        byte frameSizeBuffer[] = new byte[XING_AUDIOSIZE_BUFFER_SIZE];
        header.get(frameSizeBuffer);
        isAudioSizeEnabled = true;
        audioSize = (frameSizeBuffer[BYTE_1] << 24)&0xFF000000 |
            (frameSizeBuffer[BYTE_2] << 16)&0x00FF0000 |
            (frameSizeBuffer[BYTE_3] << 8)&0x0000FF00 |
            frameSizeBuffer[BYTE_4]&0x000000FF;
    }

    /**
     *
     * @return true if audioSize has been specified in header
     */
    public final boolean isAudioSizeEnabled()
    {
        return isAudioSizeEnabled;
    }

    /**
     *
     * @return size of audio data in bytes
     */
    public final int getAudioSize()
    {
        return audioSize;
    }

   /**
     * Parse the XingFrame of an MP3File, cannot be called until we have validated that
     * this is a XingFrame
     *
     * @return
     * @throws InvalidAudioFrameException
     */
    public static XingFrame parseXingFrame()throws InvalidAudioFrameException
    {
        xingFrame = new XingFrame();
        return xingFrame;
    }

    /**
     * IS this a Xing frame
     *
     * @return true if this is a Xing frame
     */
    public static boolean isXingFrame(ByteBuffer bb,MPEGFrameHeader mpegFrameHeader)
    {
        //We store this so can return here after scanning through buffer
        int startPosition = bb.position();

        //Get to Start of where Xing Frame Should be ( we dont know if it is one at this point)
        if(mpegFrameHeader.getVersion()==MPEGFrameHeader.VERSION_1)
        {
            if(mpegFrameHeader.getChannelMode()==MPEGFrameHeader.MODE_MONO)
            {
                bb.position(startPosition + MPEG_VERSION_1_MODE_MONO_OFFSET );
            }
            else
            {
                bb.position(startPosition + MPEG_VERSION_1_MODE_STEREO_OFFSET);
            }
        }
        //MPEGVersion 2 and 2.5
        else
        {
            if(mpegFrameHeader.getChannelMode()==MPEGFrameHeader.MODE_MONO)
            {
                bb.position(startPosition + MPEG_VERSION_2_MODE_MONO_OFFSET );
            }
            else
            {
                bb.position(startPosition + MPEG_VERSION_2_MODE_STEREO_OFFSET);
            }
        }

        //Create header from here
        header = bb.slice();

        // Return Buffer to start Point
        bb.position(startPosition);

        //Check Identifier
        byte [] identifier = new byte[XING_IDENTIFIER_BUFFER_SIZE];
        header.get(identifier);
        if ((!Arrays.equals(identifier,XING_VBR_ID))&&(!Arrays.equals(identifier,XING_CBR_ID)))
        {
            return false;
        }
        MP3File.log.finest("Found Xing Frame");
        return true;
    }

    /** Is this XingFrame detailing a varaible bit rate MPEG
     *
     * @return
     */
    public final boolean isVbr()
    {
        return vbr;
    }

    /**
     *
     * @return a string represntation
     */
    public String toString()
    {
        return "xingheader"
            +  " vbr:" + vbr
            +  " frameCountEnabled:" + isFrameCountEnabled
            +  " frameCount:" + frameCount
            +  " audioSizeEnabled:" + isAudioSizeEnabled
            +  " audioFileSize:"  + audioSize;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -