Java音频播放,因为必须依赖到本地环境,所以JAVA在音频处理方面优势不大,或者说打从Java体系开发时就没太多的考虑音频播放因素,要知道最早的Java 1.1版本中,没有后来的javax.sound包,音频只能通过Applet包调取……
遗憾的是,在图形程序开发中,我们的程序却又难免要使用到背景音乐、效果音等配合图像操作,哎,这实在是Sun大神给我们开的一个不打不小的玩笑。万幸后来Sun大神开眼,提供了javax.sound包,才解救我们于水深火热当中~
但是继之而来的问题是,在javax.sound包的使用中,如同Java多媒体工具类的通病般,并没有提供十分完善的释放机制。如果我们做Windows开发,调用MediaPlayer反复N次可能没也什么大碍,但在Java中,如果音频程序反复运行的话,极容易出现内存累计损耗的情况,以至于最后抛出一个java.lang.OutOfMemoryError,然后……程序就挂了,用户就傻了,我们就疯了……
这已经是“是可忍孰不可忍”的问题了,有鉴于此,所以在本人的Loonframework框架开发中,二次整合了sound下的相关方法,力求以最简单的代码,做出最完善的音频控制类。在Loonframework-game还没有大成的现在,先摘录一部分方法,以供各位看官——拍砖!
对应网络资源调用,在Loonframework中建立了自己的uri用类,基本内容如下:
(其中StreamHelper为Loonframework自己的流媒体控制类,getHttpStream方法请自行替换。)
package
org.loon.framework.game.net;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
import
org.loon.framework.game.helper.StreamHelper;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
/** */
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:Loonframework专用uri(统一资源标识符)
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
public
class
URI
...
{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
//传输协议类型
public static final int _L_URI_HTTP = 1;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static final int _L_URI_UDP = 2;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private String _uri;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private int _type;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 析构函数,用于注入uri和type
*
* @param uri
* @param type
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public URI(String uri, int type) ...{
_uri = new String(uri);
_type = type;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 析构函数,用于注入uri
*
* @param uri
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public URI(String uri) ...{
_uri = new String(uri);
_type = URI._L_URI_HTTP;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 返回uri所在位置资源的byte数组。
*
* @return
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public byte[] getData() ...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
if (_uri == null) ...{
return null;
}
return StreamHelper.getHttpStream(_uri);
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public String getURI() ...{
return _uri;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public int getType() ...{
return _type;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
}
在Loonframework框架中,定制了一个基础的SoundData类,用以统一管理音频数据源。
package
org.loon.framework.game.sound;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
import
org.loon.framework.game.helper.StreamHelper;
import
org.loon.framework.game.net.URI;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
/** */
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:用以获得并缓存声音文件数据(更进一步内容操作请见Loonframework-game框架)
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
public
class
SoundData
...
{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private byte[] _data;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private boolean _loop;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private int _type;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static final int _L_SOUNDTYPE_MIDI = 1;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static final int _L_SOUNDTYPE_WAV = 2;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 析构函数,用以注入uri,type,loop
*
* @param uri
* @param type
* @param loop
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public SoundData(URI uri, int type, boolean loop) ...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
if (uri != null) ...{
_data = uri.getData();
}
_type = type;
_loop = loop;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 析构函数,用以注入data,type,loop
*
* @param data
* @param type
* @param loop
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public SoundData(byte[] data, int type, boolean loop) ...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
if (data != null && data.length > 0) ...{
_data = new byte[data.length];
// 直接copy byte数组
System.arraycopy(data, 0, _data, 0, _data.length);
}
_type = type;
_loop = loop;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 析构函数,用以注入限定位置的resName,type,loop
* @param resName
* @param type
* @param loop
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public SoundData(String resName, int type, boolean loop) ...{
this(StreamHelper.GetDataSource(resName),type,loop);
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public byte[] getData() ...{
return _data;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public boolean getLoop() ...{
return _loop;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public void setLoop(boolean loop) ...{
_loop = loop;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public int getType() ...{
return _type;
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
}
Loonframework将音频播放相关方法,封装与SoundPlay之中,程序员可以不必理会javax.sound内部细节,而直接调用SoundPlay完成相关操作。
package
org.loon.framework.game.sound;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
import
java.io.ByteArrayInputStream;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
import
javax.sound.midi.MetaEventListener;
import
javax.sound.midi.MetaMessage;
import
javax.sound.midi.MidiSystem;
import
javax.sound.midi.Sequence;
import
javax.sound.midi.Sequencer;
import
javax.sound.sampled.AudioFileFormat;
import
javax.sound.sampled.AudioSystem;
import
javax.sound.sampled.Clip;
import
javax.sound.sampled.DataLine;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
import
org.loon.framework.game.net.URI;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
/** */
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:用以进行声音文件操作(仅为Loonframework中部分方法,更详细请参见Loonframework-game框架)
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
public
class
SoundPlay
implements
MetaEventListener, Runnable
...
{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private int _sleepTime;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private Clip _audio;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private Sequencer _midi;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private boolean _loop;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private int _soundType;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private boolean _playing;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private Thread _thread = null;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private boolean _isRun = false;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 析构函数,初始化SoundPlay
*
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public SoundPlay() ...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
_loop = false;
_soundType = 0;
_sleepTime = 1000;
_playing = false;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
// 载入声音文件
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public boolean load(SoundData data) ...{
reset();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
if (data == null || data.getData() == null) ...{
return false;
}
return init(data.getData(), data.getType(), data.getLoop());
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 直接播放url文件
*
* @param uri
* @param ftype
* @param loop
* @return
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
public boolean load(URI uri, int ftype, boolean loop) ...