org.farng.mp3
Class MP3File

java.lang.Object
  extended by org.farng.mp3.MP3FileHelper
      extended by org.farng.mp3.MP3File
All Implemented Interfaces:
MP3AudioMetadata

public class MP3File
extends MP3FileHelper

How is MP3 built?

Most people with a little knowledge in MP3 files know that the sound is divided into smaller parts and compressed with a psycoacoustic model. This smaller pieces of the audio is then put into something called 'frames', which is a little datablock with a header. I'll focus on that header in this text.

The header is 4 bytes, 32 bits, big and begins with something called sync. This sync is, at least according to the MPEG standard, 12 set bits in a row. Some add-on standards made later uses 11 set bits and one cleared bit. The sync is directly followed by a ID bit, indicating if the file is a MPEG-1 och MPEG-2 file. 0=MPEG-2 and 1=MPEG-1

The layer is defined with the two layers bits. They are oddly defined as

0 0 Not defined
0 1 Layer III
1 0 Layer II
1 1 Layer I

With this information and the information in the bitrate field we can determine the bitrate of the audio (in kbit/s) according to this table.

Bitrate
value
MPEG-1,
layer I
MPEG-1,
layer II
MPEG-1,
layer III
MPEG-2,
layer I
MPEG-2,
layer II
MPEG-2,
layer III
0 0 0 0
0 0 0 1 32 32 32 32 32 8
0 0 1 0 64 48 40 64 48 16
0 0 1 1 96 56 48 96 56 24
0 1 0 0 128 64 56 128 64 32
0 1 0 1 160 80 64 160 80 64
0 1 1 0 192 96 80 192 96 80
0 1 1 1 224 112 96 224 112 56
1 0 0 0 256 128 112 256 128 64
1 0 0 1 288 160 128 288 160 128
1 0 1 0 320 192 160 320 192 160
1 0 1 1 352 224 192 352 224 112
1 1 0 0 384 256 224 384 256 128
1 1 0 1 416 320 256 416 320 256
1 1 1 0 448 384 320 448 384 320
1 1 1 1

The sample rate is described in the frequency field. These values is dependent of which MPEG standard is used according to the following table.

Frequency
value
MPEG-1 MPEG-2
0 0 44100 Hz 22050 Hz
0 1 48000 Hz 24000 Hz
1 0 32000 Hz 16000 Hz
1 1

Three bits is not needed in the decoding process at all. These are the copyright bit, original home bit and the private bit. The copyright has the same meaning as the copyright bit on CDs and DAT tapes, i.e. telling that it is illegal to copy the contents if the bit is set. The original home bit indicates, if set, that the frame is located on its original media. No one seems to know what the privat bit is good for.

If the protection bit is NOT set then the frame header is followed by a 16 bit checksum, inserted before the audio data. If the padding bit is set then the frame is padded with an extra byte. Knowing this the size of the complete frame can be calculated with the following formula

FrameSize = 144 * BitRate / SampleRate
when the padding bit is cleared and

FrameSize = (144 * BitRate / SampleRate) + 1
when the padding bit is set.

The frameSize is of course an integer. If for an example BitRate=128000, SampleRate=44100 and the padding bit is cleared, then the FrameSize = 144 * 128000 / 44100 = 417

The mode field is used to tell which sort of stereo/mono encoding that has been used. The purpose of the mode extension field is different for different layers, but I really don't know exactly what it's for.

Mode value mode
0 0 Stereo
0 1 Joint stereo
1 0 Dual channel
1 1 Mono

The last field is the emphasis field. It is used to sort of 're-equalize' the sound after a Dolby-like noise supression. This is not very used and will probably never be. The following noise supression model is used

Emphasis value Emphasis method
0 0 none
0 1 50/15ms
1 0
1 1 CCITT j.17

Version:
$Revision: 3 $
Author:
Eric Farng

Constructor Summary
MP3File()
          Creates a new empty MP3File object that is not associated with a specific file.
MP3File(java.io.File file)
          Creates a new MP3File object and parse the tag from the given file Object.
MP3File(java.io.File file, boolean writeable)
          Creates a new MP3File object and parse the tag from the given file Object.
MP3File(MP3File copyObject)
          Creates a new MP3File object.
MP3File(java.lang.String filename)
          Creates a new MP3File object and parse the tag from the given filename.
 
Method Summary
 boolean adjustID3v2Padding()
          Adjust the lenght of the ID3v2 padding at the beginning of the MP3 file referred to in this object.
 boolean adjustID3v2Padding(int paddingSize, boolean willShorten, boolean copyID3v2Tag)
          Adjust the length of the ID3v2 padding at the beginning of the MP3 file this object refers to.
 boolean adjustID3v2Padding(int paddingSize, boolean willShorten, boolean copyID3v2Tag, java.io.File file)
          Adjust the length of the ID3v2 padding at the beginning of the MP3 file this object refers to.
 void delete(AbstractMP3Tag mp3tag)
           
 FilenameTag getFilenameTag()
          Sets the filename tag for this MP3 File.
 java.util.List getFrameAcrossTags(java.lang.String identifier)
          Gets the frames from all four (id3v1, lyrics3, filename, id3v2) mp3 tags in this instance for each tag that exists.
 ID3v1 getID3v1Tag()
          Returns the ID3v1 tag for this object.
 AbstractID3v2 getID3v2Tag()
          Returns the ID3v2 tag for this object.
 AbstractLyrics3 getLyrics3Tag()
          Returns the ID3v1 tag for this object.
 java.io.File getMp3file()
           
 long getMp3StartByte()
          Returns the byte position of the first MP3 Frame that this object refers to.
 long getMp3StartByte(java.io.File file)
          Returns the byte position of the first MP3 Frame that the file arguement refers to.
 java.util.Set getUnsynchronizedFragments()
          Returns a HashSet of unsynchronized fragments across all tags in this object.
 boolean hasFilenameTag()
          Returns true if this object contains an filename pseudo-tag
 boolean hasID3v1Tag()
          Returns true if this object contains an Id3v1 tag
 boolean hasID3v2Tag()
          Returns true if this object contains an Id3v2 tag
 boolean hasLyrics3Tag()
          Returns true if this object contains an Lyrics3 tag
 boolean isUnsynchronized()
          Returns true if there are any unsynchronized tags in this object.
 void save()
          Saves the tags in this object to the file referred to by this object.
 void save(java.io.File file)
          Saves the tags in this object to the file argument.
 void save(java.io.File file, int saveMode)
          Saves the tags in this object to the file argument.
 void save(int saveMode)
          Saves the tags in this object to the file referred to by this object.
 void save(java.lang.String filename)
          Saves the tags in this object to the file argument.
 void save(java.lang.String filename, int saveMode)
          Saves the tags in this object to the file argument.
 boolean seekMP3Frame()
          Returns true if the first MP3 frame can be found for the MP3 file that this object refers to.
 boolean seekMP3Frame(java.io.RandomAccessFile seekFile)
          Returns true if the first MP3 frame can be found for the MP3 file argument.
 void setFilenameTag(FilenameTag filenameTag)
          Sets the filename tag for this MP3 File.
 void setFrameAcrossTags(AbstractID3v2Frame frame)
          Sets all four (id3v1, lyrics3, filename, id3v2) tags in this instance to the frame argument if the tag exists.
 void setID3v1Tag(AbstractMP3Tag mp3tag)
          Sets the ID3v1 tag for this object.
 void setID3v1Tag(ID3v1 id3v1tag)
           
 void setID3v2Tag(AbstractID3v2 id3v2tag)
           
 void setID3v2Tag(AbstractMP3Tag mp3tag)
          Sets the ID3v2 tag for this object.
 void setLyrics3Tag(AbstractLyrics3 lyrics3tag)
           
 void setLyrics3Tag(AbstractMP3Tag mp3tag)
          Sets the Lyrics3 tag for this object.
 void setMp3file(java.io.File mp3file)
           
 
Methods inherited from class org.farng.mp3.MP3FileHelper
getBitRate, getEmphasis, getFile, getFrequency, getLayer, getMode, getModeExtension, getMpegVersion, getNumberMP3SyncFrame, isCopyProtected, isHome, isPadding, isPrivacy, isProtection, isVariableBitRate, parseMpegAudio, setBitRate, setCopyProtected, setEmphasis, setFile, setFrequency, setHome, setLayer, setMode, setModeExtension, setMpegVersion, setNumberMP3SyncFrame, setPadding, setPrivacy, setProtection, setVariableBitRate
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

MP3File

public MP3File()
Creates a new empty MP3File object that is not associated with a specific file.


MP3File

public MP3File(MP3File copyObject)
Creates a new MP3File object.


MP3File

public MP3File(java.lang.String filename)
        throws java.io.IOException,
               TagException
Creates a new MP3File object and parse the tag from the given filename.

Parameters:
filename - MP3 file
Throws:
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

MP3File

public MP3File(java.io.File file)
        throws java.io.IOException,
               TagException
Creates a new MP3File object and parse the tag from the given file Object.

Parameters:
file - MP3 file
Throws:
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

MP3File

public MP3File(java.io.File file,
               boolean writeable)
        throws java.io.IOException,
               TagException
Creates a new MP3File object and parse the tag from the given file Object.

Parameters:
file - MP3 file
writeable - open in read (false) or read-write (true) mode
Throws:
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.
Method Detail

setFilenameTag

public void setFilenameTag(FilenameTag filenameTag)
Sets the filename tag for this MP3 File. Refer to TagUtilities.parseFileName and TagUtilities.createID3v2Tag for more information about parsing file names into ID3v2_4 objects.

Parameters:
filenameTag - parsed ID3v2_4 filename tag

getFilenameTag

public FilenameTag getFilenameTag()
Sets the filename tag for this MP3 File. Refer to TagUtilities.parseFileName and TagUtilities.createID3v2Tag for more information about parsing file names into ID3v2_4 objects.

Returns:
parsed ID3v2_4 filename tag

setFrameAcrossTags

public void setFrameAcrossTags(AbstractID3v2Frame frame)
Sets all four (id3v1, lyrics3, filename, id3v2) tags in this instance to the frame argument if the tag exists. This method does not use the options inside the tagOptions object.

Parameters:
frame - frame to set / replace in all four tags.

getFrameAcrossTags

public java.util.List getFrameAcrossTags(java.lang.String identifier)
Gets the frames from all four (id3v1, lyrics3, filename, id3v2) mp3 tags in this instance for each tag that exists. This method does not use the options inside the tagOptions object.

Parameters:
identifier - ID3v2.4 Tag Frame Identifier.
Returns:
ArrayList of all instances of the desired frame. Each instance is returned as an ID3v2_4Frame. The nature of the code returns the array in a specific order, but this order is not guaranteed for future versions of this library.

setID3v1Tag

public void setID3v1Tag(AbstractMP3Tag mp3tag)
Sets the ID3v1 tag for this object. A new ID3v1_1 object is created from the argument and then used here.

Parameters:
mp3tag - Any MP3Tag object can be used and will be converted into a new ID3v1_1 object.

setID3v1Tag

public void setID3v1Tag(ID3v1 id3v1tag)

getID3v1Tag

public ID3v1 getID3v1Tag()
Returns the ID3v1 tag for this object.

Returns:
the ID3v1 tag for this object

setID3v2Tag

public void setID3v2Tag(AbstractMP3Tag mp3tag)
Sets the ID3v2 tag for this object. A new ID3v2_4 object is created from the argument and then used here.

Parameters:
mp3tag - Any MP3Tag object can be used and will be converted into a new ID3v2_4 object.

setID3v2Tag

public void setID3v2Tag(AbstractID3v2 id3v2tag)

getID3v2Tag

public AbstractID3v2 getID3v2Tag()
Returns the ID3v2 tag for this object.

Returns:
the ID3v2 tag for this object

setLyrics3Tag

public void setLyrics3Tag(AbstractMP3Tag mp3tag)
Sets the Lyrics3 tag for this object. A new Lyrics3v2 object is created from the argument and then used here.

Parameters:
mp3tag - Any MP3Tag object can be used and will be converted into a new Lyrics3v2 object.

setLyrics3Tag

public void setLyrics3Tag(AbstractLyrics3 lyrics3tag)

getLyrics3Tag

public AbstractLyrics3 getLyrics3Tag()
Returns the ID3v1 tag for this object.

Returns:
the ID3v1 tag for this object

getMp3StartByte

public long getMp3StartByte()
                     throws java.io.IOException,
                            java.io.FileNotFoundException
Returns the byte position of the first MP3 Frame that this object refers to. This is the first byte of music data and not the ID3 Tag Frame.

Returns:
the byte position of the first MP3 Frame
Throws:
java.io.IOException - on any I/O error
java.io.FileNotFoundException - if the file exists but is a directory rather than a regular file or cannot be opened for any other reason

getMp3StartByte

public long getMp3StartByte(java.io.File file)
                     throws java.io.IOException,
                            java.io.FileNotFoundException
Returns the byte position of the first MP3 Frame that the file arguement refers to. This is the first byte of music data and not the ID3 Tag Frame.

Parameters:
file - MP3 file to search
Returns:
the byte position of the first MP3 Frame
Throws:
java.io.IOException - on any I/O error
java.io.FileNotFoundException - if the file exists but is a directory rather than a regular file or cannot be opened for any other reason

setMp3file

public void setMp3file(java.io.File mp3file)

getMp3file

public java.io.File getMp3file()

isUnsynchronized

public boolean isUnsynchronized()
Returns true if there are any unsynchronized tags in this object. A fragment is unsynchronized if it exists in two or more tags but is not equal across all of them.

Returns:
true of any fragments are unsynchronized.

getUnsynchronizedFragments

public java.util.Set getUnsynchronizedFragments()
Returns a HashSet of unsynchronized fragments across all tags in this object. A fragment is unsynchronized if it exists in two or more tags but is not equal across all of them.

Returns:
a HashSet of unsynchronized fragments

adjustID3v2Padding

public boolean adjustID3v2Padding()
                           throws java.io.FileNotFoundException,
                                  java.io.IOException,
                                  TagException
Adjust the lenght of the ID3v2 padding at the beginning of the MP3 file referred to in this object. The ID3v2 size will be calculated, then a new file will be created with enough size to fit the ID3v2 tag in this object. The old file will be deleted, and the new file renamed. All parameters will be taken from the tagOptions object.

Throws:
java.io.FileNotFoundException - if the file exists but is a directory rather than a regular file or cannot be opened for any other reason
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

adjustID3v2Padding

public boolean adjustID3v2Padding(int paddingSize,
                                  boolean willShorten,
                                  boolean copyID3v2Tag)
                           throws java.io.FileNotFoundException,
                                  java.io.IOException,
                                  TagException
Adjust the length of the ID3v2 padding at the beginning of the MP3 file this object refers to. The ID3v2 size will be calculated, then a new file will be created with enough size to fit the ID3v2 tag. The old file will be deleted, and the new file renamed.

Parameters:
paddingSize - Initial padding size. This size is doubled until the ID3v2 tag will fit.
willShorten - if the newly calculated padding size is less than the padding length of the file, then news the new shorter padding size if this is true.
copyID3v2Tag - if true, write the ID3v2 tag of this object into the file
Throws:
java.io.FileNotFoundException - if the file exists but is a directory rather than a regular file or cannot be opened for any other reason
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

adjustID3v2Padding

public boolean adjustID3v2Padding(int paddingSize,
                                  boolean willShorten,
                                  boolean copyID3v2Tag,
                                  java.io.File file)
                           throws java.io.FileNotFoundException,
                                  java.io.IOException,
                                  TagException
Adjust the length of the ID3v2 padding at the beginning of the MP3 file this object refers to. The ID3v2 size will be calculated, then a new file will be created with enough size to fit the ID3v2 tag. The old file will be deleted, and the new file renamed.

Parameters:
paddingSize - Initial padding size. This size is doubled until the ID3v2 tag will fit. A paddingSize of zero will create a padding length exactly equal to the tag size.
willShorten - Shorten the padding size by halves if the ID3v2 tag will fit
copyID3v2Tag - if true, write the ID3v2 tag of this object into the file
file - The file to adjust the padding length of
Throws:
java.io.FileNotFoundException - if the file exists but is a directory rather than a regular file or cannot be opened for any other reason
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

delete

public void delete(AbstractMP3Tag mp3tag)
            throws java.io.FileNotFoundException,
                   java.io.IOException
Throws:
java.io.FileNotFoundException
java.io.IOException

hasFilenameTag

public boolean hasFilenameTag()
Returns true if this object contains an filename pseudo-tag

Returns:
true if this object contains an filename pseudo-tag

hasID3v1Tag

public boolean hasID3v1Tag()
Returns true if this object contains an Id3v1 tag

Returns:
true if this object contains an Id3v1 tag

hasID3v2Tag

public boolean hasID3v2Tag()
Returns true if this object contains an Id3v2 tag

Returns:
true if this object contains an Id3v2 tag

hasLyrics3Tag

public boolean hasLyrics3Tag()
Returns true if this object contains an Lyrics3 tag

Returns:
true if this object contains an Lyrics3 tag

save

public void save()
          throws java.io.IOException,
                 TagException
Saves the tags in this object to the file referred to by this object. It will be saved as TagConstants.MP3_FILE_SAVE_WRITE

Throws:
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

save

public void save(int saveMode)
          throws java.io.IOException,
                 TagException
Saves the tags in this object to the file referred to by this object. It will be saved as TagConstants.MP3_FILE_SAVE_WRITE

Parameters:
saveMode - write, overwrite, or append. Defined as TagConstants.MP3_FILE_SAVE_WRITE TagConstants.MP3_FILE_SAVE_OVERWRITE TagConstants.MP3_FILE_SAVE_APPEND
Throws:
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

save

public void save(java.lang.String filename)
          throws java.io.IOException,
                 TagException
Saves the tags in this object to the file argument. It will be saved as TagConstants.MP3_FILE_SAVE_WRITE

Parameters:
filename - file to save the this object's tags to
Throws:
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

save

public void save(java.io.File file)
          throws java.io.IOException,
                 TagException
Saves the tags in this object to the file argument. It will be saved as TagConstants.MP3_FILE_SAVE_WRITE

Parameters:
file - file to save the this object's tags to
Throws:
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

save

public void save(java.lang.String filename,
                 int saveMode)
          throws java.io.IOException,
                 TagException
Saves the tags in this object to the file argument. It will be saved as TagConstants.MP3_FILE_SAVE_WRITE

Parameters:
filename - file to save the this object's tags to
saveMode - write, overwrite, or append. Defined as TagConstants.MP3_FILE_SAVE_WRITE TagConstants.MP3_FILE_SAVE_OVERWRITE TagConstants.MP3_FILE_SAVE_APPEND
Throws:
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

save

public void save(java.io.File file,
                 int saveMode)
          throws java.io.IOException,
                 TagException
Saves the tags in this object to the file argument. It will be saved as TagConstants.MP3_FILE_SAVE_WRITE

Parameters:
file - file to save the this object's tags to
saveMode - write, overwrite, or append. Defined as TagConstants.MP3_FILE_SAVE_WRITE TagConstants.MP3_FILE_SAVE_OVERWRITE TagConstants.MP3_FILE_SAVE_APPEND
Throws:
java.io.IOException - on any I/O error
TagException - on any exception generated by this library.

seekMP3Frame

public boolean seekMP3Frame()
                     throws java.io.IOException
Returns true if the first MP3 frame can be found for the MP3 file that this object refers to. This is the first byte of music data and not the ID3 Tag Frame.

Returns:
true if the first MP3 frame can be found
Throws:
java.io.IOException - on any I/O error

seekMP3Frame

public boolean seekMP3Frame(java.io.RandomAccessFile seekFile)
                     throws java.io.IOException
Returns true if the first MP3 frame can be found for the MP3 file argument. It tries to sync as many frame as defined in TagOptions.getNumberMP3SyncFrame This is the first byte of music data and not the ID3 Tag Frame.

Parameters:
seekFile - MP3 file to seek
Returns:
true if the first MP3 frame can be found
Throws:
java.io.IOException - on any I/O error