FileDocCategorySizeDatePackage
XingFrame.javaAPI DocJaudiotagger 2.0.48299Mon Sep 12 15:51:24 BST 2011org.jaudiotagger.audio.mp3

XingFrame

public class XingFrame extends Object
Xing Frame

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

Fields Summary
private static final int
MPEG_VERSION_1_MODE_MONO_OFFSET
private static final int
MPEG_VERSION_1_MODE_STEREO_OFFSET
private static final int
MPEG_VERSION_2_MODE_MONO_OFFSET
private static final int
MPEG_VERSION_2_MODE_STEREO_OFFSET
private static final int
XING_HEADER_BUFFER_SIZE
private static final int
XING_IDENTIFIER_BUFFER_SIZE
private static final int
XING_FLAG_BUFFER_SIZE
private static final int
XING_FRAMECOUNT_BUFFER_SIZE
private static final int
XING_AUDIOSIZE_BUFFER_SIZE
public static final int
MAX_BUFFER_SIZE_NEEDED_TO_READ_XING
private static final int
BYTE_1
private static final int
BYTE_2
private static final int
BYTE_3
private static final int
BYTE_4
private static final byte[]
XING_VBR_ID
Use when it is a VBR (Variable Bitrate) file
private static final byte[]
XING_CBR_ID
Use when it is a CBR (Constant Bitrate) file
private ByteBuffer
header
private boolean
vbr
private boolean
isFrameCountEnabled
private int
frameCount
private boolean
isAudioSizeEnabled
private int
audioSize
private LameFrame
lameFrame
Constructors Summary
private XingFrame(ByteBuffer header)
Read the Xing Properties from the buffer


                
      
    
        this.header=header;

        //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);
        }
    
Methods Summary
public final intgetAudioSize()

return
size of audio data in bytes

        return audioSize;
    
public final intgetFrameCount()

return
count of frames

        return frameCount;
    
public LameFramegetLameFrame()

        return lameFrame;
    
public final booleanisAudioSizeEnabled()

return
true if audioSize has been specified in header

        return isAudioSizeEnabled;
    
public final booleanisFrameCountEnabled()

return
true if frameCount has been specified in header

        return isFrameCountEnabled;
    
public final booleanisVbr()
Is this XingFrame detailing a variable bit rate MPEG

return

        return vbr;
    
public static java.nio.ByteBufferisXingFrame(java.nio.ByteBuffer bb, MPEGFrameHeader mpegFrameHeader)
IS this a Xing frame

param
bb
param
mpegFrameHeader
return
true if this is a Xing frame

        //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
        ByteBuffer 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 null;
        }
        MP3File.logger.finest("Found Xing Frame");
        return header;
    
public static org.jaudiotagger.audio.mp3.XingFrameparseXingFrame(java.nio.ByteBuffer header)
Parse the XingFrame of an MP3File, cannot be called until we have validated that this is a XingFrame

return
throws
InvalidAudioFrameException

        XingFrame xingFrame = new XingFrame(header);
        return xingFrame;
    
private voidsetAudioSize()
Set size of AudioData

        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;
    
private voidsetFrameCount()
Set count of frames

        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;
    
private voidsetVbr()
Set whether or not VBR, (Xing can also be used for CBR though this is less useful)

        //Is it VBR or CBR
        byte[] identifier = new byte[XING_IDENTIFIER_BUFFER_SIZE];
        header.get(identifier);
        if (Arrays.equals(identifier, XING_VBR_ID))
        {
            MP3File.logger.finest("Is Vbr");
            vbr = true;
        }
    
public java.lang.StringtoString()

return
a string representation

        return "xingheader" + " vbr:" + vbr + " frameCountEnabled:" + isFrameCountEnabled + " frameCount:" + frameCount + " audioSizeEnabled:" + isAudioSizeEnabled + " audioFileSize:" + audioSize;