android Mp3播放器之Mp3 ID3V2 、ID3V1标签解析

暑假在家学习Android,通过编写一个Mp3播放器学习MediaPalyer。在这里和大家分享一下代码。

1、ID3V2 标签解析

只解析些常见的。{歌名、艺术家、专辑、头像}

新建一个Id3v2Info类

package com.aws.mp3;


public class Id3v2Info {
	// 歌名
	private String tit2 = null;
	// 艺术家
	private String tpe1 = null;
	// 专辑
	private String talb = null;
	// 头像
	private byte[] apic = null;

	public Id3v2Info(String tit2, String tpe1, String talb, byte[] apic) {
		setTit2(tit2);
		setTpe1(tpe1);
		setTalb(talb);
		setApic(apic);

	}

	public void setTit2(String tit2) {
		this.tit2 = tit2;
	}

	public String getTit2() {
		return tit2;
	}

	public void setTpe1(String tpe1) {
		this.tpe1 = tpe1;
	}

	public String getTpe1() {
		return tpe1;
	}

	public void setTalb(String talb) {
		this.talb = talb;
	}

	public String getTalb() {
		return talb;
	}

	public void setApic(byte[] apic) {
		this.apic = apic;
	}

	public byte[] getApic() {
		return apic;
	}

}

再建立一个Mp3ReadId3v2类,用来提取Mp3中的信息。

package com.aws.mp3;

import java.io.IOException;
import java.io.InputStream;

/**
 * <b>MP3的ID3V2信息解析类</b>
 * 
 * @QQ QQ:951868171
 * @version 1.0
 * @email xi_yf_001@126.com
 * */
public class Mp3ReadId3v2 {

	private InputStream mp3ips;
	public String charset = "GBK"; // 预设编码为GBK
	private Id3v2Info info;

	public Mp3ReadId3v2(InputStream in) {
		this.mp3ips = in;
		info = new Id3v2Info("未知", "未知", "未知", null);
	}

	public void readId3v2() throws Exception {
		try {
			readId3v2(1024*100);		//读取前100KB
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 
	 * */
	public void readId3v2(int buffSize) throws Exception {
		try {
			if(buffSize > mp3ips.available()){
				buffSize = mp3ips.available();
			}
			byte[] buff = new byte[buffSize];
			mp3ips.read(buff, 0, buffSize);

			if (ByteUtil.indexOf("ID3".getBytes(), buff, 1, 512) == -1)
				throw new Exception("未发现ID3V2");
			//获取头像
			if (ByteUtil.indexOf("APIC".getBytes(), buff, 1, 512) != -1) {
				int searLen = ByteUtil.indexOf(new byte[] { (byte) 0xFF,
						(byte) 0xFB }, buff);
				int imgStart = ByteUtil.indexOf(new byte[] { (byte) 0xFF,
						(byte) 0xD8 }, buff);
				int imgEnd = ByteUtil.lastIndexOf(new byte[] { (byte) 0xFF,
						(byte) 0xD9 }, buff, 1, searLen) + 2;
				byte[] imgb = ByteUtil.cutBytes(imgStart, imgEnd, buff);
				info.setApic(imgb);
			}
			if (ByteUtil.indexOf("TIT2".getBytes(), buff, 1, 512) != -1) {
				info.setTit2(new String(readInfo(buff, "TIT2"), charset));
				System.out.println("info:" + info.getTit2());
			}
			if (ByteUtil.indexOf("TPE1".getBytes(), buff, 1, 512) != -1) {
				info.setTpe1(new String(readInfo(buff, "TPE1"), charset));
				System.out.println("info:" + info.getTpe1());

			}
			if (ByteUtil.indexOf("TALB".getBytes(), buff, 1, 512) != -1) {
				info.setTalb(new String(readInfo(buff, "TALB"), charset));
				System.out.println("info:" + info.getTalb());
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			
			mp3ips.close();
		}

	}

	/**
	 *读取文本标签
	 **/
	private byte[] readInfo(byte[] buff, String tag) {
		int len = 0;
		int offset = ByteUtil.indexOf(tag.getBytes(), buff);
		len = buff[offset + 4] & 0xFF;
		len = (len << 8) + (buff[offset + 5] & 0xFF);
		len = (len << 8) + (buff[offset + 6] & 0xFF);
		len = (len << 8) + (buff[offset + 7] & 0xFF);
		len = len - 1;
		return ByteUtil.cutBytes(ByteUtil.indexOf(tag.getBytes(), buff) + 11,
				ByteUtil.indexOf(tag.getBytes(), buff) + 11 + len, buff);

	}

	public void setInfo(Id3v2Info info) {
		this.info = info;
	}

	public Id3v2Info getInfo() {
		return info;
	}

	public String getName() {
		return getInfo().getTit2();

	}

	public String getAuthor() {

		return getInfo().getTpe1();

	}

	public String getSpecial() {
		return getInfo().getTalb();
	}

	public byte[] getImg() {
		return getInfo().getApic();
	}
}

 Mp3ReadId3v2用到了很多字节查找,字节数组查找等,所以自己实现了个字节索引、操作类ByteUtil。(好像java里没有提供吧) 

package com.aws.mp3;

/**
 * 字节操作类
 * */
public class ByteUtil {

	/**
	 * 正向索引
	 * */
	public static int indexOf(byte[] tag, byte[] src) {
		return indexOf(tag, src, 1);
	}

	/**
	 * 获取第index个的位置<br />
	 * index从1开始
	 * */
	public static int indexOf(byte[] tag, byte[] src, int index) {
		return indexOf(tag, src, 1, src.length);
	}

	/**
	 * 获取第index个的位置<br />
	 * index从1开始
	 * 
	 * */
	public static int indexOf(byte[] tag, byte[] src, int index, int len) {
		if (len > src.length) {
			try {
				throw new Exception("大于总个数");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		int size = 0;
		int tagLen = tag.length;
		byte[] tmp = new byte[tagLen];
		for (int j = 0; j < len - tagLen + 1; j++) {
			for (int i = 0; i < tagLen; i++) {
				tmp[i] = src[j + i];
			}
			// 判断是否相等
			for (int i = 0; i < tagLen; i++) {
				if (tmp[i] != tag[i])
					break;
				if (i == tagLen - 1) {
					size++;
					return j;
				}
			}

		}
		return -1;
	}

	/**
	 * 倒序索引<br />
	 * 
	 * */
	public static int lastIndexOf(byte[] tag, byte[] src) {

		return lastIndexOf(tag, src, 1);
	}

	/**
	 * 倒序获取第index个的位置<br />
	 * index从1开始
	 * */
	public static int lastIndexOf(byte[] tag, byte[] src, int index) {
		return lastIndexOf(tag, src, src.length);
	}

	/**
	 * 倒序获取第index个的位置<br />
	 * index从1开始
	 * */
	public static int lastIndexOf(byte[] tag, byte[] src, int index, int len) {
		if (len > src.length) {
			try {
				throw new Exception("大于总个数");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		int size = 0;
		int tagLen = tag.length;
		byte[] tmp = new byte[tagLen];
		for (int j = len - tagLen; j >= 0; j--) {
			for (int i = 0; i < tagLen; i++) {
				tmp[i] = src[j + i];

			}
			for (int i = 0; i < tagLen; i++) {
				if (tmp[i] != tag[i])
					break;
				if (i == tagLen - 1) {
					size++;
					return j;
				}
			}

		}
		return -1;
	}

	/**
	 * 统计个数
	 * */
	public static int size(byte[] tag, byte[] src) {
		int size = 0;
		int tagLen = tag.length;
		int srcLen = src.length;
		byte[] tmp = new byte[tagLen];
		for (int j = 0; j < srcLen - tagLen + 1; j++) {
			for (int i = 0; i < tagLen; i++) {
				tmp[i] = src[j + i];
			}
			for (int i = 0; i < tagLen; i++) {
				if (tmp[i] != tag[i])
					break;
				if (i == tagLen - 1) {
					size++;
				}
			}
			// 速度较慢
			// if (Arrays.equals(tmp, tag)) {
			// size++;
			// }
		}
		return size;
	}

	/**
	 * 截取byte[]
	 * */
	public static byte[] cutBytes(int start, int end, byte[] src) {
		if (end <= start || start < 0 || end > src.length) {
			try {
				throw new Exception("参数错误");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		byte[] tmp = new byte[end - start];
		for (int i = 0; i < end - start; i++) {
			tmp[i] = src[start + i];
		}
		return tmp;
	}

}


2、ID3V1 标签解析

v1标签解析比较简单,就是操作mp3后128个字节。懒得贴代码。

3、资源下载地址

播放器源码下载http://download.csdn.net/source/3553639


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值