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方法请自行替换。)
在Loonframework框架中,定制了一个基础的SoundData类,用以统一管理音频数据源。
Loonframework将音频播放相关方法,封装与SoundPlay之中,程序员可以不必理会javax.sound内部细节,而直接调用SoundPlay完成相关操作。
这时我们需要面对的,仅是封装为实体的SoundData数据和SoundPlay操作,而不必和繁复的 javax.sound再打交道。
调用方法如下:
更详细方法,会待Loonframework-game完全公布后,再进行解释。
另:由于StreamHelper关联其他Loonframework中方法,暂不给出,inputStream转byte[]可用如下写法:
遗憾的是,在图形程序开发中,我们的程序却又难免要使用到背景音乐、效果音等配合图像操作,哎,这实在是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;
import org.loon.framework.game.helper.StreamHelper;
/***/ /**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:Loonframework专用uri(统一资源标识符)
*</p>
*<p>
*Copyright:Copyright(c)2007
*</p>
*<p>
*Company:LoonFramework
*</p>
*
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/
public class URI ... {
//传输协议类型
publicstaticfinalint_L_URI_HTTP=1;
publicstaticfinalint_L_URI_UDP=2;
privateString_uri;
privateint_type;
/***//**
*析构函数,用于注入uri和type
*
*@paramuri
*@paramtype
*/
publicURI(Stringuri,inttype)...{
_uri=newString(uri);
_type=type;
}
/***//**
*析构函数,用于注入uri
*
*@paramuri
*/
publicURI(Stringuri)...{
_uri=newString(uri);
_type=URI._L_URI_HTTP;
}
/***//**
*返回uri所在位置资源的byte数组。
*
*@return
*/
publicbyte[]getData()...{
if(_uri==null)...{
returnnull;
}
returnStreamHelper.getHttpStream(_uri);
}
publicStringgetURI()...{
return_uri;
}
publicintgetType()...{
return_type;
}
}
import org.loon.framework.game.helper.StreamHelper;
/***/ /**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:Loonframework专用uri(统一资源标识符)
*</p>
*<p>
*Copyright:Copyright(c)2007
*</p>
*<p>
*Company:LoonFramework
*</p>
*
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/
public class URI ... {
//传输协议类型
publicstaticfinalint_L_URI_HTTP=1;
publicstaticfinalint_L_URI_UDP=2;
privateString_uri;
privateint_type;
/***//**
*析构函数,用于注入uri和type
*
*@paramuri
*@paramtype
*/
publicURI(Stringuri,inttype)...{
_uri=newString(uri);
_type=type;
}
/***//**
*析构函数,用于注入uri
*
*@paramuri
*/
publicURI(Stringuri)...{
_uri=newString(uri);
_type=URI._L_URI_HTTP;
}
/***//**
*返回uri所在位置资源的byte数组。
*
*@return
*/
publicbyte[]getData()...{
if(_uri==null)...{
returnnull;
}
returnStreamHelper.getHttpStream(_uri);
}
publicStringgetURI()...{
return_uri;
}
publicintgetType()...{
return_type;
}
}
在Loonframework框架中,定制了一个基础的SoundData类,用以统一管理音频数据源。
package
org.loon.framework.game.sound;
import org.loon.framework.game.helper.StreamHelper;
import org.loon.framework.game.net.URI;
/***/ /**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:用以获得并缓存声音文件数据(更进一步内容操作请见Loonframework-game框架)
*</p>
*<p>
*Copyright:Copyright(c)2007
*</p>
*<p>
*Company:LoonFramework
*</p>
*
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/
public class SoundData ... {
privatebyte[]_data;
privateboolean_loop;
privateint_type;
publicstaticfinalint_L_SOUNDTYPE_MIDI=1;
publicstaticfinalint_L_SOUNDTYPE_WAV=2;
/***//**
*析构函数,用以注入uri,type,loop
*
*@paramuri
*@paramtype
*@paramloop
*/
publicSoundData(URIuri,inttype,booleanloop)...{
if(uri!=null)...{
_data=uri.getData();
}
_type=type;
_loop=loop;
}
/***//**
*析构函数,用以注入data,type,loop
*
*@paramdata
*@paramtype
*@paramloop
*/
publicSoundData(byte[]data,inttype,booleanloop)...{
if(data!=null&&data.length>0)...{
_data=newbyte[data.length];
//直接copybyte数组
System.arraycopy(data,0,_data,0,_data.length);
}
_type=type;
_loop=loop;
}
/***//**
*析构函数,用以注入限定位置的resName,type,loop
*@paramresName
*@paramtype
*@paramloop
*/
publicSoundData(StringresName,inttype,booleanloop)...{
this(StreamHelper.GetDataSource(resName),type,loop);
}
publicbyte[]getData()...{
return_data;
}
publicbooleangetLoop()...{
return_loop;
}
publicvoidsetLoop(booleanloop)...{
_loop=loop;
}
publicintgetType()...{
return_type;
}
}
import org.loon.framework.game.helper.StreamHelper;
import org.loon.framework.game.net.URI;
/***/ /**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:用以获得并缓存声音文件数据(更进一步内容操作请见Loonframework-game框架)
*</p>
*<p>
*Copyright:Copyright(c)2007
*</p>
*<p>
*Company:LoonFramework
*</p>
*
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/
public class SoundData ... {
privatebyte[]_data;
privateboolean_loop;
privateint_type;
publicstaticfinalint_L_SOUNDTYPE_MIDI=1;
publicstaticfinalint_L_SOUNDTYPE_WAV=2;
/***//**
*析构函数,用以注入uri,type,loop
*
*@paramuri
*@paramtype
*@paramloop
*/
publicSoundData(URIuri,inttype,booleanloop)...{
if(uri!=null)...{
_data=uri.getData();
}
_type=type;
_loop=loop;
}
/***//**
*析构函数,用以注入data,type,loop
*
*@paramdata
*@paramtype
*@paramloop
*/
publicSoundData(byte[]data,inttype,booleanloop)...{
if(data!=null&&data.length>0)...{
_data=newbyte[data.length];
//直接copybyte数组
System.arraycopy(data,0,_data,0,_data.length);
}
_type=type;
_loop=loop;
}
/***//**
*析构函数,用以注入限定位置的resName,type,loop
*@paramresName
*@paramtype
*@paramloop
*/
publicSoundData(StringresName,inttype,booleanloop)...{
this(StreamHelper.GetDataSource(resName),type,loop);
}
publicbyte[]getData()...{
return_data;
}
publicbooleangetLoop()...{
return_loop;
}
publicvoidsetLoop(booleanloop)...{
_loop=loop;
}
publicintgetType()...{
return_type;
}
}
Loonframework将音频播放相关方法,封装与SoundPlay之中,程序员可以不必理会javax.sound内部细节,而直接调用SoundPlay完成相关操作。
package
org.loon.framework.game.sound;
import java.io.ByteArrayInputStream;
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;
import org.loon.framework.game.net.URI;
/***/ /**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:用以进行声音文件操作(仅为Loonframework中部分方法,更详细请参见Loonframework-game框架)
*</p>
*<p>
*Copyright:Copyright(c)2007
*</p>
*<p>
*Company:LoonFramework
*</p>
*
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/
public class SoundPlay implements MetaEventListener,Runnable ... {
privateint_sleepTime;
privateClip_audio;
privateSequencer_midi;
privateboolean_loop;
privateint_soundType;
privateboolean_playing;
privateThread_thread=null;
privateboolean_isRun=false;
/***//**
*析构函数,初始化SoundPlay
*
*/
publicSoundPlay()...{
_loop=false;
_soundType=0;
_sleepTime=1000;
_playing=false;
}
//载入声音文件
publicbooleanload(SoundDatadata)...{
reset();
if(data==null||data.getData()==null)...{
returnfalse;
}
returninit(data.getData(),data.getType(),data.getLoop());
}
/***//**
*直接播放url文件
*
*@paramuri
*@paramftype
*@paramloop
*@return
*/
publicbooleanload(URIuri,intftype,booleanloop)...{
//刷新数据
reset();
if(uri==null)...{
returnfalse;
}
//获得SoundData
SoundDatadata=newSoundData(uri,ftype,loop);
if(data==null||data.getData()==null)...{
returnfalse;
}
returninit(data.getData(),data.getType(),data.getLoop());
}
/***//**
*初始化sound相关数据
*
*@paramdata
*@paramftype
*@paramloop
*@return
*/
privatebooleaninit(byte[]data,intftype,booleanloop)...{
booleanresult=false;
ByteArrayInputStreambis=null;
try...{
bis=newByteArrayInputStream(data);
}catch(Exceptione)...{
bis=null;
}
if(bis==null)...{
returnfalse;
}
//判断类型
switch(ftype)...{
//MIDI
caseSoundData._L_SOUNDTYPE_MIDI:
//当MIDI不存在时
if(_midi==null)...{
try...{
//获得Sequencer
_midi=MidiSystem.getSequencer();
_midi.open();
}catch(Exceptionex)...{
_midi=null;
}
if(_midi!=null)...{
_midi.addMetaEventListener(this);
}
}
//当MIDI依旧未获得时
if(_midi!=null)...{
//重新创建Sequence
Sequencesc=null;
try...{
sc=MidiSystem.getSequence(bis);
}catch(Exceptione)...{
sc=null;
}
if(sc!=null)...{
try...{
_midi.setSequence(sc);
//获得是否循环播放
_loop=loop;
//获得是否载入
result=true;
}catch(Exceptionee)...{
}
//获得声音类型
_soundType=SoundData._L_SOUNDTYPE_MIDI;
}
}
try...{
bis.close();
}catch(Exceptionee)...{
}
break;
//Wav
caseSoundData._L_SOUNDTYPE_WAV:
AudioFileFormattype=null;
//获得Audio
try...{
type=AudioSystem.getAudioFileFormat(bis);
}catch(Exceptione)...{
type=null;
}
//关闭流
try...{
bis.close();
}catch(Exceptionex)...{
}
if(type==null)...{
returnfalse;
}
//根据指定信息构造数据行的信息对象
DataLine.Infodi=newDataLine.Info(Clip.class,type.getFormat());
//转为Clip
try...{
_audio=(Clip)AudioSystem.getLine(di);
}catch(Exceptione)...{
}
//播放文件
try...{
_audio.open(type.getFormat(),data,0,data.length);
_loop=loop;
result=true;
}catch(Exceptione)...{
}
//获得文件类型
_soundType=SoundData._L_SOUNDTYPE_WAV;
break;
}
returnresult;
}
publicbooleanplay(SoundDatadata)...{
if(!load(data))...{
returnfalse;
}
returnplay();
}
publicbooleanplay()...{
switch(_soundType)...{
caseSoundData._L_SOUNDTYPE_MIDI:
try...{
_midi.start();
_playing=true;
_soundType=SoundData._L_SOUNDTYPE_MIDI;
}catch(Exceptionee)...{
}
break;
caseSoundData._L_SOUNDTYPE_WAV:
if(_audio!=null)...{
if(_loop)...{
//设定循环
_audio.setLoopPoints(0,-1);
_audio.setFramePosition(0);
_audio.loop(Clip.LOOP_CONTINUOUSLY);
}else...{
//强制设定播放位置至0
_audio.setFramePosition(0);
_audio.start();
}
_playing=true;
}
break;
}
return_playing;
}
/***//**
*自动播放,循环停止后结束。
*
*@paramdata
*@return
*/
publicbooleanAutoPlay(SoundDatadata)...{
if(!load(data))...{
returnfalse;
}
returnAutoPlay();
}
/***//**
*自动播放,循环停止后结束。
*
*@return
*/
publicbooleanAutoPlay()...{
_isRun=true;
_thread=newThread(this);
_thread.start();
return_playing;
}
/***//**
*停止播放
*/
publicvoidstop()...{
if(_audio!=null&&_audio.isActive())...{
try...{
_audio.stop();
}catch(Exceptione)...{
}
}
if(_midi!=null)...{
_midi.stop();
}
_playing=false;
_isRun=false;
}
/***//**
*释放数据
*
*/
publicvoidreset()...{
stop();
_loop=false;
_soundType=0;
if(_midi!=null)...{
_midi.close();
_midi=null;
}
if(_audio!=null&&_audio.isOpen())...{
_audio.close();
_audio=null;
}
_isRun=false;
_thread=null;
}
/***//**
*设定MetaMessage
*/
publicvoidmeta(MetaMessagemeta)...{
//判断是否循环播放MIDI
if(_loop&&_soundType==SoundData._L_SOUNDTYPE_MIDI
&&meta.getType()==47)...{
if(_midi!=null&&_midi.isOpen())...{
_midi.setMicrosecondPosition(0);
_midi.start();
}
}
}
publicvoidrun()...{
while(_isRun)...{
play();
//因为播放类型唯一,所以只会返回一个_playing结果,以此判定。
if(_midi!=null)...{
_playing=_midi.isRunning();
}
if(_audio!=null)...{
_playing=_audio.isRunning();
}
//当播放停止
if(!_playing)...{
//释放
reset();
}
try...{
Thread.sleep(_sleepTime);
}catch(InterruptedExceptione)...{
e.printStackTrace();
}
}
}
publicintgetSleepTime()...{
return_sleepTime;
}
/***//**
*设定AutoPlay线程循环时间。
*
*@paramtime
*/
publicvoidsetSleepTime(inttime)...{
_sleepTime=time;
}
}
import java.io.ByteArrayInputStream;
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;
import org.loon.framework.game.net.URI;
/***/ /**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:用以进行声音文件操作(仅为Loonframework中部分方法,更详细请参见Loonframework-game框架)
*</p>
*<p>
*Copyright:Copyright(c)2007
*</p>
*<p>
*Company:LoonFramework
*</p>
*
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/
public class SoundPlay implements MetaEventListener,Runnable ... {
privateint_sleepTime;
privateClip_audio;
privateSequencer_midi;
privateboolean_loop;
privateint_soundType;
privateboolean_playing;
privateThread_thread=null;
privateboolean_isRun=false;
/***//**
*析构函数,初始化SoundPlay
*
*/
publicSoundPlay()...{
_loop=false;
_soundType=0;
_sleepTime=1000;
_playing=false;
}
//载入声音文件
publicbooleanload(SoundDatadata)...{
reset();
if(data==null||data.getData()==null)...{
returnfalse;
}
returninit(data.getData(),data.getType(),data.getLoop());
}
/***//**
*直接播放url文件
*
*@paramuri
*@paramftype
*@paramloop
*@return
*/
publicbooleanload(URIuri,intftype,booleanloop)...{
//刷新数据
reset();
if(uri==null)...{
returnfalse;
}
//获得SoundData
SoundDatadata=newSoundData(uri,ftype,loop);
if(data==null||data.getData()==null)...{
returnfalse;
}
returninit(data.getData(),data.getType(),data.getLoop());
}
/***//**
*初始化sound相关数据
*
*@paramdata
*@paramftype
*@paramloop
*@return
*/
privatebooleaninit(byte[]data,intftype,booleanloop)...{
booleanresult=false;
ByteArrayInputStreambis=null;
try...{
bis=newByteArrayInputStream(data);
}catch(Exceptione)...{
bis=null;
}
if(bis==null)...{
returnfalse;
}
//判断类型
switch(ftype)...{
//MIDI
caseSoundData._L_SOUNDTYPE_MIDI:
//当MIDI不存在时
if(_midi==null)...{
try...{
//获得Sequencer
_midi=MidiSystem.getSequencer();
_midi.open();
}catch(Exceptionex)...{
_midi=null;
}
if(_midi!=null)...{
_midi.addMetaEventListener(this);
}
}
//当MIDI依旧未获得时
if(_midi!=null)...{
//重新创建Sequence
Sequencesc=null;
try...{
sc=MidiSystem.getSequence(bis);
}catch(Exceptione)...{
sc=null;
}
if(sc!=null)...{
try...{
_midi.setSequence(sc);
//获得是否循环播放
_loop=loop;
//获得是否载入
result=true;
}catch(Exceptionee)...{
}
//获得声音类型
_soundType=SoundData._L_SOUNDTYPE_MIDI;
}
}
try...{
bis.close();
}catch(Exceptionee)...{
}
break;
//Wav
caseSoundData._L_SOUNDTYPE_WAV:
AudioFileFormattype=null;
//获得Audio
try...{
type=AudioSystem.getAudioFileFormat(bis);
}catch(Exceptione)...{
type=null;
}
//关闭流
try...{
bis.close();
}catch(Exceptionex)...{
}
if(type==null)...{
returnfalse;
}
//根据指定信息构造数据行的信息对象
DataLine.Infodi=newDataLine.Info(Clip.class,type.getFormat());
//转为Clip
try...{
_audio=(Clip)AudioSystem.getLine(di);
}catch(Exceptione)...{
}
//播放文件
try...{
_audio.open(type.getFormat(),data,0,data.length);
_loop=loop;
result=true;
}catch(Exceptione)...{
}
//获得文件类型
_soundType=SoundData._L_SOUNDTYPE_WAV;
break;
}
returnresult;
}
publicbooleanplay(SoundDatadata)...{
if(!load(data))...{
returnfalse;
}
returnplay();
}
publicbooleanplay()...{
switch(_soundType)...{
caseSoundData._L_SOUNDTYPE_MIDI:
try...{
_midi.start();
_playing=true;
_soundType=SoundData._L_SOUNDTYPE_MIDI;
}catch(Exceptionee)...{
}
break;
caseSoundData._L_SOUNDTYPE_WAV:
if(_audio!=null)...{
if(_loop)...{
//设定循环
_audio.setLoopPoints(0,-1);
_audio.setFramePosition(0);
_audio.loop(Clip.LOOP_CONTINUOUSLY);
}else...{
//强制设定播放位置至0
_audio.setFramePosition(0);
_audio.start();
}
_playing=true;
}
break;
}
return_playing;
}
/***//**
*自动播放,循环停止后结束。
*
*@paramdata
*@return
*/
publicbooleanAutoPlay(SoundDatadata)...{
if(!load(data))...{
returnfalse;
}
returnAutoPlay();
}
/***//**
*自动播放,循环停止后结束。
*
*@return
*/
publicbooleanAutoPlay()...{
_isRun=true;
_thread=newThread(this);
_thread.start();
return_playing;
}
/***//**
*停止播放
*/
publicvoidstop()...{
if(_audio!=null&&_audio.isActive())...{
try...{
_audio.stop();
}catch(Exceptione)...{
}
}
if(_midi!=null)...{
_midi.stop();
}
_playing=false;
_isRun=false;
}
/***//**
*释放数据
*
*/
publicvoidreset()...{
stop();
_loop=false;
_soundType=0;
if(_midi!=null)...{
_midi.close();
_midi=null;
}
if(_audio!=null&&_audio.isOpen())...{
_audio.close();
_audio=null;
}
_isRun=false;
_thread=null;
}
/***//**
*设定MetaMessage
*/
publicvoidmeta(MetaMessagemeta)...{
//判断是否循环播放MIDI
if(_loop&&_soundType==SoundData._L_SOUNDTYPE_MIDI
&&meta.getType()==47)...{
if(_midi!=null&&_midi.isOpen())...{
_midi.setMicrosecondPosition(0);
_midi.start();
}
}
}
publicvoidrun()...{
while(_isRun)...{
play();
//因为播放类型唯一,所以只会返回一个_playing结果,以此判定。
if(_midi!=null)...{
_playing=_midi.isRunning();
}
if(_audio!=null)...{
_playing=_audio.isRunning();
}
//当播放停止
if(!_playing)...{
//释放
reset();
}
try...{
Thread.sleep(_sleepTime);
}catch(InterruptedExceptione)...{
e.printStackTrace();
}
}
}
publicintgetSleepTime()...{
return_sleepTime;
}
/***//**
*设定AutoPlay线程循环时间。
*
*@paramtime
*/
publicvoidsetSleepTime(inttime)...{
_sleepTime=time;
}
}
这时我们需要面对的,仅是封装为实体的SoundData数据和SoundPlay操作,而不必和繁复的 javax.sound再打交道。
调用方法如下:
package
org.test;
import org.loon.framework.game.helper.StreamHelper;
import org.loon.framework.game.net.URI;
import org.loon.framework.game.sound.SoundData;
import org.loon.framework.game.sound.SoundPlay;
/***/ /**
*<p>Title:LoonFramework</p>
*<p>Description:SoundPlay播放测试</p>
*<p>Copyright:Copyright(c)2007</p>
*<p>Company:LoonFramework</p>
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/
public class SoundPlayTest ... {
staticvoidselectPlay(intftype)...{
SoundDatadata=null;
switch(ftype)...{
//通过loonframework下uri从网络播放音乐
case0:
data=newSoundData(newURI("http://looframework.sourceforge.net/midi/谁是大英雄.mid"),SoundData._L_SOUNDTYPE_MIDI,false);
break;
//通过本地资源下音乐文件的byte[]对象播放音乐
case1:
byte[]bytes=StreamHelper.GetResourceData("/midi/谁是大英雄.mid");
data=newSoundData(bytes,SoundData._L_SOUNDTYPE_MIDI,false);
break;
//通过音乐文件路径播放音乐
case2:
data=newSoundData("C:/谁是大英雄.mid",SoundData._L_SOUNDTYPE_MIDI,false);
break;
}
SoundPlayplay=newSoundPlay();
//AutoPlay与Play方法的区别在于,AutoPlay播放完毕会自动停止并释放资源,play需手动中止。
//play.play(data);
play.AutoPlay(data);
}
publicstaticvoidmain(String[]args)...{
selectPlay(2);
}
}
import org.loon.framework.game.helper.StreamHelper;
import org.loon.framework.game.net.URI;
import org.loon.framework.game.sound.SoundData;
import org.loon.framework.game.sound.SoundPlay;
/***/ /**
*<p>Title:LoonFramework</p>
*<p>Description:SoundPlay播放测试</p>
*<p>Copyright:Copyright(c)2007</p>
*<p>Company:LoonFramework</p>
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/
public class SoundPlayTest ... {
staticvoidselectPlay(intftype)...{
SoundDatadata=null;
switch(ftype)...{
//通过loonframework下uri从网络播放音乐
case0:
data=newSoundData(newURI("http://looframework.sourceforge.net/midi/谁是大英雄.mid"),SoundData._L_SOUNDTYPE_MIDI,false);
break;
//通过本地资源下音乐文件的byte[]对象播放音乐
case1:
byte[]bytes=StreamHelper.GetResourceData("/midi/谁是大英雄.mid");
data=newSoundData(bytes,SoundData._L_SOUNDTYPE_MIDI,false);
break;
//通过音乐文件路径播放音乐
case2:
data=newSoundData("C:/谁是大英雄.mid",SoundData._L_SOUNDTYPE_MIDI,false);
break;
}
SoundPlayplay=newSoundPlay();
//AutoPlay与Play方法的区别在于,AutoPlay播放完毕会自动停止并释放资源,play需手动中止。
//play.play(data);
play.AutoPlay(data);
}
publicstaticvoidmain(String[]args)...{
selectPlay(2);
}
}
更详细方法,会待Loonframework-game完全公布后,再进行解释。
另:由于StreamHelper关联其他Loonframework中方法,暂不给出,inputStream转byte[]可用如下写法:
//
is为获得的inputStream
ByteArrayOutputStreambyteArrayOutputStream = new ByteArrayOutputStream();
// 用于承接byte[]
byte []arrayByte = null ;
try ... {
//每次传输大小为4096
byte[]bytes=newbyte[4096];
bytes=newbyte[is.available()];
intread;
while((read=is.read(bytes))>=0)...{
byteArrayOutputStream.write(bytes,0,read);
}
arrayByte=byteArrayOutputStream.toByteArray();
} catch (IOExceptione) ... {
returnnull;
} finally ... {
try...{
if(byteArrayOutputStream!=null)...{
byteArrayOutputStream.close();
byteArrayOutputStream=null;
}
if(is!=null)...{
is.close();
is=null;
}
}catch(IOExceptione)...{
}
}
ByteArrayOutputStreambyteArrayOutputStream = new ByteArrayOutputStream();
// 用于承接byte[]
byte []arrayByte = null ;
try ... {
//每次传输大小为4096
byte[]bytes=newbyte[4096];
bytes=newbyte[is.available()];
intread;
while((read=is.read(bytes))>=0)...{
byteArrayOutputStream.write(bytes,0,read);
}
arrayByte=byteArrayOutputStream.toByteArray();
} catch (IOExceptione) ... {
returnnull;
} finally ... {
try...{
if(byteArrayOutputStream!=null)...{
byteArrayOutputStream.close();
byteArrayOutputStream=null;
}
if(is!=null)...{
is.close();
is=null;
}
}catch(IOExceptione)...{
}
}