Home > Tutorials > Parsing MP3 Basic Info manually

Parsing MP3 Basic Info manually


Let’s continue from my previous article on MP3 file structure.

We’re going into practice to parse MP3 basic info: Title, Artist, Year, Album. These are the most basic ones and we can achieve by reading the very last 128 bytes at the end of file.

First you need to put the file into Emulator, in my case, I put into “/sdcard/music.mp3“. After parsing just display it to screen:

MP3 Info Parsing

MP3 Info Parsing

Think it simple, just Java, no Android thought here!

This is how I did it 🙂

package pete.android.study;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;

public class MP3HeaderInfo {

	// --- { constants } --- >>>
	// ID3 tag value
	public static final String ID3_TAG = "TAG";
	public static final int BYTE_128 = 128;
	public static final int[] OFFSET_TAG = new int[] { 0, 3 };
	public static final int[] OFFSET_TITLE = new int[] { 3, 33 };
	public static final int[] OFFSET_ARTIST = new int[] { 33, 63 };
	public static final int[] OFFSET_YEAR = new int[] { 93, 97 };
	public static final int[] OFFSET_ALBUM = new int[] { 63, 93 };

	// indexer
	public static final int FROM = 0;
	public static final int TO = 1;

	// key attribute
	public static final String TITLE = "Title";
	public static final String ARTIST = "Artist";
	public static final String YEAR = "Year";
	public static final String ALBUM = "Album";

	// default values for each key value
	public static final String DEFAULT_TITLE = "Unknown Title";
	public static final String DEFAULT_ARTIST = "Unknown Artist";
	public static final String DEFAULT_YEAR = String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
	public static final String DEFAULT_ALBUM = "Unknown Album";
	// --- { constants } --- <<<

	// --- { fields } --- >>>
	private String mFile;
	private String mTitle = DEFAULT_TITLE;
	private String mArtist = DEFAULT_ARTIST;
	private String mYear = DEFAULT_YEAR;
	private String mAlbum = DEFAULT_ALBUM;
	private String mErrorLog; // for error information
	// --- { fields } --- <<<

	// --- { constructor } --- >>>
	public MP3HeaderInfo(String file) {
		mFile = file;
		// auto parse file, only once
		parseAudio();
	}
	// --- { constructor } --- <<<

	// --- { properties } --- >>>
	public String getTitle() {
		return !mTitle.equals("") ? mTitle.trim() : DEFAULT_TITLE;
	}

	public String getArtist() {
		return !mArtist.equals("") ? mArtist.trim() : DEFAULT_ARTIST;
	}

	public String getYear() {
		return !mYear.equals("") ? mYear.trim() : DEFAULT_YEAR;
	}

	public String getAlbum() {
		return !mAlbum.equals("") ? mAlbum.trim() : DEFAULT_ALBUM;
	}

	public String getErrorLog() {
		return mErrorLog;
	}
	// --- { properties } --- <<<

	// --- { private methods } --- >>>
	private boolean parseAudio() {
		// create MP3 File object
		File mp3 = new File(mFile);
		FileInputStream fis;
		try {
			// create new file stream for parsing file in binary
			fis = new FileInputStream(mp3);
			// get file size
			int size = (int) mp3.length();
			// offset to the first byte of the last 128 bytes
			fis.skip(size - BYTE_128);
			// read chunk of 128 bytes
			byte[] chunk = new byte[BYTE_128];
			fis.read(chunk);
			// convert chunk to string
			String id3 = new String(chunk);
			// get first 3 byte
			String tag = id3.substring(OFFSET_TAG[FROM], OFFSET_TAG[TO]);
			// if equals to "TAG" meaning a valid readable one
			if(tag.equals(ID3_TAG)) {
				mTitle = id3.substring(OFFSET_TITLE[FROM], OFFSET_TITLE[TO]);
				mArtist = id3.substring(OFFSET_ARTIST[FROM], OFFSET_ARTIST[TO]);
				mYear = id3.substring(OFFSET_YEAR[FROM], OFFSET_YEAR[TO]);
				mAlbum = id3.substring(OFFSET_ALBUM[FROM], OFFSET_ALBUM[TO]);
			}

			// close stream after done
			fis.close();
			// return complete
			return true;
		} catch (FileNotFoundException e) {
			// log error
			mErrorLog = e.getMessage();
			return false;
		} catch (IOException e) {
			// log error
			mErrorLog = e.getMessage();
			return false;
		}
	}

	// --- { private methods } --- <<<

	// --- { public methods } --- >>>
	public static HashMap<String, String> getInfo(String file) {
		HashMap<String, String> result = new HashMap<String, String>();
		MP3HeaderInfo info = new MP3HeaderInfo(file);
		result.put(ARTIST, info.getArtist());
		result.put(TITLE, info.getTitle());
		result.put(YEAR, info.getYear());
		result.put(ALBUM, info.getAlbum());

		return result;
	}
	// --- { public methods } --- <<<

}

For MainActivity, just input file name to parse and display:

package pete.android.study;

import java.util.HashMap;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        TextView tvMain = (TextView)findViewById(R.id.tvMain);

        HashMap<String, String> info = MP3HeaderInfo.getInfo("/sdcard/music.mp3");

        String out = "";
        out += info.get("Title") + " - " + info.get("Year") + "\n";
        out += info.get("Album") + "\n" + info.get("Artist") + "\n";
        tvMain.setText(out);
    }
}

Very very basic of Java file handling, isn’t it?
Talking about MP3 Song Duration or Bit-rate, well, it’s quite complicated … I’m still not good enough at parsing them at the moment, it would take some more time to study about.
However, I guess those above info is enough to display to users. Or you can even achieve reading more metadata on MP3 file by using third-party libraries for your applications.
Have fun!

Cheers,
Pete Houston

Categories: Tutorials Tags: , , ,
  1. tyo
    January 15, 2013 at 10:59 pm

    nice tutorial .. so how to find info of the played song in this case we have many song on the sdcard . thank

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: