分享

Java自由人 | Java读取MP3信息

 fondofbeyond 2007-08-28

Java读取MP3信息

2005/01/11  作者:梁夏峰   心情: sunny  星期二 (10:05)

现在有很多纯Java开发的MP3播放器,早前就接触过一个jlGui2.0,和WinAmp界面基本已经接近,但在功能表现上还不是很理想,近几天又推出最新2.3版本,已经完成大部分WinAmp的功能,并且在功能的实现上还很不错,这里先贴上一张实际运行的界面,让大家过过眼:

如果对比过jlGui2.0和2.3,大家可能会有很深的印象,之间在界面和功能上都有很大的差距,2.0还称不上叫产品,但2.3已经可以称为比较专业的产品了,估计再往下开发,大家都不一定再能认出这是Java开发的MP3播放器 :)

由于播放器封装的东西很多,所以想从浅往深了解不是很方便,现在就干脆找来底层开发MP3的Library:JLayer,可别小看它,下面列出了很多MP3开发的项目都是基于它为基础的,把JLayer介绍过后,再来看看如何进行高级功能的扩展。

JLayer是一套Open Source的Java类库,可以在不同的OS下使用,提供对MP3进行实时解码、转换和播放。1.0版本在04年11月发布,支持MPEG 1/2/2.5、Layer 1/2/3 audio format,JLayer不需要JMF,此外JLayer不仅有J2SE版本,而且还提供J2ME版:JLayerMe,以提供在手机上进行应用开发。1.0版本在JRE5下的运行速度快,消耗低(CPU仅消耗1%),下面列出采用JLayer为基础的MP3项目:

jlGui ---------- MP3 player, WinAmp clone.
MP3SPI --------- MP3 plugin for J2SE.
JLayer C# ------ C# port of JLayer.
MP3View -------- JLayer Eclipse Plugin.
Plaberbu ------- Karaoke MP3 player.
jAmp ----------- Another WinAmp clone.
Human iPod ----- Halloween funny contest.
KJ Player ------ Cross-fading MP3 player
PartyJukeBox --- JukeBox player
JavaTunes ------ Another JukeBox player.
MediaChest ----- Media organizer.
LightDev ------- Spectrum Analyzer.

下面列表是J2SE版和J2ME版的比较:

 特征 JLayer JLayerME
JVM J2SE J2SE, J2ME
音频支持 MPEG 1/2/2.5 Layer 1/2/3 MPEG 1 Layer 3 
内存 1380KB to 1900KB 760KB to 1280KB
JAR大小 105KB 46KB
License LGPL LGPL
状态 Stable Beta

下图展示了JLayer提供项目支持的架构:

图中上面部分:Plugins是一套独立的部件,基于JLayer API,Mpeg音频SPI插件实现了JavaSound1.0 的服务接口,使Mpeg音频格式的开发者也能象操作播放WAV一样方便。

在图中下面部分,是应用开发层,其中Core部分是JLayer提供的Mpeg音频解码,而jlApps是一个轻量级的用于提供给用户使用的部分,即用户界面、控制台和播放列表等等部分,其中Convert是个小工具,可以把MP3转换成WAV,但目前暂时还没提供WAV到MP3的转换。

下载JLayer1.0并解压后,只需要修改它的build-win32.bat,指定正确的JAVA_HOME和JL变量,分别是jdk的目录和JLayer所在的目录,这样就可以编辑src目录下的源码了,运行build-win32.bat即可完成编译和打包等工作。

使用下面的命令运行播放MP3:
java -cp .\classes; javazoom.jl.player.jlp vincent.mp3

简单分析:
程序的入口是javazoom.jl.player.jlp,一个基本的操作过程如下:
1、把mp3播放文件加载到InputStream;
2、生成AudioDevice,声音设备;
3、生成Player,一个具体的播放器;
4、通过Player.play()进行歌曲播放。

歌曲在JLayer里处理是被分成一个个的Frame,连续对Frame进行解码和播放,直到歌曲播放完毕。

下面接下来继续讲述高级问题,即我们都知道每首MP3歌曲里都带有一些属性如标题、歌手、专辑等等,我们来看看怎么把这些内容解析出来:

1、需要类包:mp3spi1.9.1.jar、tritonus_share.jar,可以下载jlGui2.3项目的压缩包,解压后在它的lib包里得到,copy到上面JLayer项目的目录下,也可以在下面回帖并写上email,我尽快给你发;

2、修改build-win32.bat,把下面2段:
cd %JLSIMPLEPLAYER%
javac -classpath %JL%\classes -d %JL%\classes *.java
>>> 改为 >>>:
cd %JLSIMPLEPLAYER%
javac -classpath %JL%\classes;%JL%\tritonus_share.jar; -d %JL%\classes *.java

即在编译时增加tritonus_share.jar的路径;

3、在src\javazoom\jl\player\里编辑 jlp.java,用文本编辑即可;

4、增加如下类包:

import javazoom.jl.decoder.*;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioSystem;
import org.tritonus.share.sampled.file.TAudioFileFormat;
import java.util.*;
import java.io.*;

5、main的方法里,在“player.play(); ”之前增加:

File ff = new File(player.fFilename);
AudioFileFormat aff = AudioSystem.getAudioFileFormat(ff);
loadInfo(aff);
aff = null;
ff = null;

即打印MP3的资料;

6、jlp类增加方法 loadInfo 如下,主要用于打印MP3的参数:

protected static void loadInfo(AudioFileFormat aff)
    throws Exception {
    System.out.println("[MP3 info] ---------------------");
    String type = aff.getType().toString();
    if (!type.equalsIgnoreCase("mp3"))
        throw new Exception("Not MP3 audio format");
    if (aff instanceof TAudioFileFormat) {
        Map props = ((TAudioFileFormat) aff).properties();
        System.out.println("title: "+props.get("title"));
        System.out.println("author: "+props.get("author"));
        System.out.println("album: "+props.get("album"));
        if (props.containsKey("mp3.mode")) {
            String channelsMode = "";
            int mode =
                ((Integer)props.get("mp3.mode")).intValue();
            if (mode==0)
                channelsMode = "Stereo";
            else if (mode==1)
                channelsMode = "Joint Stereo";
            else if (mode==2)
                channelsMode = "Dual Channel";
            else if (mode==3)
                channelsMode = "Single Channel";
            System.out.println("mode: "+channelsMode);
        }
        System.out.println
            ("channels: "+props.get("mp3.channels"));
        System.out.println
            ("rate: "+props.get("mp3.frequency.hz"));
        System.out.println("nominalbitrate: "+
            props.get("mp3.bitrate.nominal.bps"));
        System.out.println
            ("layer: "+props.get("mp3.version.layer"));
        if (props.containsKey("mp3.version.mpeg")) {
            String version = (String)
                props.get("mp3.version.mpeg");
            if (version.equals("1"))
                version = "MPEG1";
            else if (version.equals("2"))
                version = "MPEG2-LSF";
            else if (version.equals("2.5"))
                version = "MPEG2.5-LSF";
            System.out.println("version: "+version);
        }
        System.out.println("crc: "+props.get("mp3.crc"));
        System.out.println("vbr: "+props.get("mp3.vbr"));
        System.out.println
            ("copyright: "+props.get("mp3.copyright"));
        System.out.println
            ("original: "+props.get("mp3.original"));
        System.out.println
            ("date: "+props.get("date"));
        System.out.println
            ("duration: "+props.get("duration"));
        System.out.println
            ("genre: "+props.get("mp3.id3tag.genre"));
        System.out.println
            ("track: "+props.get("mp3.id3tag.track"));       
    }   
}

6、以上存盘,运行build-win32.bat,进行自动编译、打包;

7、在JLayer项目的目录路径下,再用命令运行播放MP3:
java -cp .\classes; javazoom.jl.player.jlp vincent.mp3

这时候会发现MP3内带的不少资料已经打印出来,大功告成!

最后需要注意的是,以上都是以英文mp3来调试的,在中文歌曲方面,还有些特性需要处理,包括上面使用的mp3spi1.9.1.jar也有需要调整的地方,如各位有兴趣,请深入这个问题吧 :)


相关资源:
http:///projects/javalayer/

http://www./jlgui/jlgui.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多