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;

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>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class URI {

//傳輸協議類型
public static final int _L_URI_HTTP = 1;

public static final int _L_URI_UDP = 2;

private String _uri;

private int _type;

/**
* 析構函數,用于注入uri和type
*
* @param uri
* @param type
*/
public URI(String uri, int type) {
_uri = new String(uri);
_type = type;
}

/**
* 析構函數,用于注入uri
*
* @param uri
*/
public URI(String uri) {
_uri = new String(uri);
_type = URI._L_URI_HTTP;
}

/**
* 返回uri所在位置資源的byte數組。
*
* @return
*/
public byte[] getData() {
if (_uri == null) {
return null;
}
return StreamHelper.getHttpStream(_uri);
}

public String getURI() {
return _uri;
}

public int getType() {
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>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class SoundData {

private byte[] _data;

private boolean _loop;

private int _type;

public static final int _L_SOUNDTYPE_MIDI = 1;

public static final int _L_SOUNDTYPE_WAV = 2;

/**
* 析構函數,用以注入uri,type,loop
*
* @param uri
* @param type
* @param loop
*/
public SoundData(URI uri, int type, boolean loop) {
if (uri != null) {
_data = uri.getData();
}
_type = type;
_loop = loop;
}
/**
* 析構函數,用以注入data,type,loop
*
* @param data
* @param type
* @param loop
*/
public SoundData(byte[] data, int type, boolean loop) {

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;
}
/**
* 析構函數,用以注入限定位置的resName,type,loop
* @param resName
* @param type
* @param loop
*/
public SoundData(String resName, int type, boolean loop) {
this(StreamHelper.GetDataSource(resName),type,loop);
}

public byte[] getData() {
return _data;
}

public boolean getLoop() {
return _loop;
}

public void setLoop(boolean loop) {
_loop = loop;
}

public int getType() {
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>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class SoundPlay implements MetaEventListener, Runnable {

private int _sleepTime;

private Clip _audio;

private Sequencer _midi;

private boolean _loop;

private int _soundType;

private boolean _playing;

private Thread _thread = null;

private boolean _isRun = false;

/**
* 析構函數,初始化SoundPlay
*
*/
public SoundPlay() {

_loop = false;
_soundType = 0;
_sleepTime = 1000;
_playing = false;

}

// 載入聲音文件
public boolean load(SoundData data) {
reset();
if (data == null || data.getData() == null) {
return false;
}
return init(data.getData(), data.getType(), data.getLoop());
}

/**
* 直接播放url文件
*
* @param uri
* @param ftype
* @param loop
* @return
*/
public boolean load(URI uri, int ftype, boolean loop) {

// 刷新數據
reset();
if (uri == null) {
return false;
}
// 獲得SoundData
SoundData data = new SoundData(uri, ftype, loop);
if (data == null || data.getData() == null) {
return false;
}
return init(data.getData(), data.getType(), data.getLoop());

}

/**
* 初始化sound相關數據
*
* @param data
* @param ftype
* @param loop
* @return
*/
private boolean init(byte[] data, int ftype, boolean loop) {
boolean result = false;

ByteArrayInputStream bis = null;

try {
bis = new ByteArrayInputStream(data);
} catch (Exception e) {
bis = null;
}

if (bis == null) {
return false;
}

// 判斷類型
switch (ftype) {

// MIDI
case SoundData._L_SOUNDTYPE_MIDI:

// 當MIDI不存在時
if (_midi == null) {

try {
// 獲得Sequencer
_midi = MidiSystem.getSequencer();
_midi.open();

} catch (Exception ex) {
_midi = null;
}

if (_midi != null) {
_midi.addMetaEventListener(this);
}

}

// 當MIDI依舊未獲得時
if (_midi != null) {
// 重新創建Sequence
Sequence sc = null;

try {
sc = MidiSystem.getSequence(bis);
} catch (Exception e) {
sc = null;
}

if (sc != null) {

try {

_midi.setSequence(sc);

// 獲得是否循環播放
_loop = loop;

// 獲得是否載入
result = true;

} catch (Exception ee) {
}

// 獲得聲音類型
_soundType = SoundData._L_SOUNDTYPE_MIDI;

}

}

try {
bis.close();
} catch (Exception ee) {
}

break;

// Wav
case SoundData._L_SOUNDTYPE_WAV:

AudioFileFormat type = null;

// 獲得Audio
try {
type = AudioSystem.getAudioFileFormat(bis);
} catch (Exception e) {
type = null;
}

// 關閉流
try {
bis.close();
} catch (Exception ex) {
}

if (type == null) {
return false;
}

// 根據指定信息構造數據行的信息對象
DataLine.Info di = new DataLine.Info(Clip.class, type.getFormat());

// 轉為Clip
try {
_audio = (Clip) AudioSystem.getLine(di);
} catch (Exception e) {
}

// 播放文件
try {

_audio.open(type.getFormat(), data, 0, data.length);

_loop = loop;

result = true;

} catch (Exception e) {
}

// 獲得文件類型
_soundType = SoundData._L_SOUNDTYPE_WAV;

break;

}

return result;
}

public boolean play(SoundData data) {

if (!load(data)) {
return false;
}

return play();

}

public boolean play() {

switch (_soundType) {

case SoundData._L_SOUNDTYPE_MIDI:

try {

_midi.start();

_playing = true;

_soundType = SoundData._L_SOUNDTYPE_MIDI;

} catch (Exception ee) {
}

break;

case SoundData._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;

}

/**
* 自動播放,循環停止后結束。
*
* @param data
* @return
*/
public boolean AutoPlay(SoundData data) {
if (!load(data)) {
return false;
}
return AutoPlay();
}

/**
* 自動播放,循環停止后結束。
*
* @return
*/
public boolean AutoPlay() {
_isRun = true;
_thread = new Thread(this);
_thread.start();
return _playing;
}

/**
* 停止播放
*/
public void stop() {

if (_audio != null && _audio.isActive()) {
try {
_audio.stop();
} catch (Exception e) {
}
}

if (_midi != null) {
_midi.stop();
}
_playing = false;
_isRun = false;
}

/**
* 釋放數據
*
*/
public void reset() {

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
*/
public void meta(MetaMessage meta) {
// 判斷是否循環播放MIDI
if (_loop && _soundType == SoundData._L_SOUNDTYPE_MIDI
&& meta.getType() == 47) {

if (_midi != null && _midi.isOpen()) {
_midi.setMicrosecondPosition(0);
_midi.start();

}
}

}

public void run() {
while (_isRun) {
play();
// 因為播放類型唯一,所以只會返回一個_playing結果,以此判定。
if (_midi != null) {
_playing = _midi.isRunning();
}
if (_audio != null) {
_playing = _audio.isRunning();
}
// 當播放停止
if (!_playing) {
// 釋放
reset();
}
try {
Thread.sleep(_sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public int getSleepTime() {
return _sleepTime;
}

/**
* 設定AutoPlay線程循環時間。
*
* @param time
*/
public void setSleepTime(int time) {
_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>
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class SoundPlayTest {

static void selectPlay(int ftype){
SoundData data=null;
switch(ftype){
//通過loonframework下uri從網絡播放音樂
case 0:
data=new SoundData(new URI("http://looframework.sourceforge.net/midi/誰是大英雄.mid"),SoundData._L_SOUNDTYPE_MIDI,false);
break;
//通過本地資源下音樂文件的byte[]對象播放音樂
case 1:
byte[] bytes=StreamHelper.GetResourceData("/midi/誰是大英雄.mid");
data=new SoundData(bytes,SoundData._L_SOUNDTYPE_MIDI,false);
break;
//通過音樂文件路徑播放音樂
case 2:
data=new SoundData("C:/誰是大英雄.mid",SoundData._L_SOUNDTYPE_MIDI,false);
break;
}
SoundPlay play=new SoundPlay();
//AutoPlay與Play方法的區別在于,AutoPlay播放完畢會自動停止并釋放資源,play需手動中止。
//play.play(data);
play.AutoPlay(data);
}
public static void main(String[]args){
selectPlay(2);
}
}

更詳細方法,會待Loonframework-game完全公布后,再進行解釋。
另:由于StreamHelper關聯其他Loonframework中方法,暫不給出,inputStream轉byte[]可用如下寫法:
//is為獲得的inputStream

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//用于承接byte[]
byte[] arrayByte = null;
try {
// 每次傳輸大小為4096
byte[] bytes = new byte[4096];
bytes = new byte[is.available()];
int read;
while ((read = is.read(bytes)) >= 0) {
byteArrayOutputStream.write(bytes, 0, read);
}
arrayByte = byteArrayOutputStream.toByteArray();
} catch (IOException e) {
return null;
} finally {
try {
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
byteArrayOutputStream = null;
}
if (is != null) {
is.close();
is = null;
}

} catch (IOException e) {
}
}
遺憾的是,在圖形程序開發中,我們的程序卻又難免要使用到背景音樂、效果音等配合圖像操作,哎,這實在是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>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class URI {
//傳輸協議類型
public static final int _L_URI_HTTP = 1;
public static final int _L_URI_UDP = 2;
private String _uri;
private int _type;
/**
* 析構函數,用于注入uri和type
*
* @param uri
* @param type
*/
public URI(String uri, int type) {
_uri = new String(uri);
_type = type;
}
/**
* 析構函數,用于注入uri
*
* @param uri
*/
public URI(String uri) {
_uri = new String(uri);
_type = URI._L_URI_HTTP;
}
/**
* 返回uri所在位置資源的byte數組。
*
* @return
*/
public byte[] getData() {
if (_uri == null) {
return null;
}
return StreamHelper.getHttpStream(_uri);
}
public String getURI() {
return _uri;
}
public int getType() {
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>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class SoundData {
private byte[] _data;
private boolean _loop;
private int _type;
public static final int _L_SOUNDTYPE_MIDI = 1;
public static final int _L_SOUNDTYPE_WAV = 2;
/**
* 析構函數,用以注入uri,type,loop
*
* @param uri
* @param type
* @param loop
*/
public SoundData(URI uri, int type, boolean loop) {
if (uri != null) {
_data = uri.getData();
}
_type = type;
_loop = loop;
}
/**
* 析構函數,用以注入data,type,loop
*
* @param data
* @param type
* @param loop
*/
public SoundData(byte[] data, int type, boolean loop) {
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;
}
/**
* 析構函數,用以注入限定位置的resName,type,loop
* @param resName
* @param type
* @param loop
*/
public SoundData(String resName, int type, boolean loop) {
this(StreamHelper.GetDataSource(resName),type,loop);
}
public byte[] getData() {
return _data;
}
public boolean getLoop() {
return _loop;
}
public void setLoop(boolean loop) {
_loop = loop;
}
public int getType() {
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>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class SoundPlay implements MetaEventListener, Runnable {
private int _sleepTime;
private Clip _audio;
private Sequencer _midi;
private boolean _loop;
private int _soundType;
private boolean _playing;
private Thread _thread = null;
private boolean _isRun = false;
/**
* 析構函數,初始化SoundPlay
*
*/
public SoundPlay() {
_loop = false;
_soundType = 0;
_sleepTime = 1000;
_playing = false;
}
// 載入聲音文件
public boolean load(SoundData data) {
reset();
if (data == null || data.getData() == null) {
return false;
}
return init(data.getData(), data.getType(), data.getLoop());
}
/**
* 直接播放url文件
*
* @param uri
* @param ftype
* @param loop
* @return
*/
public boolean load(URI uri, int ftype, boolean loop) {
// 刷新數據
reset();
if (uri == null) {
return false;
}
// 獲得SoundData
SoundData data = new SoundData(uri, ftype, loop);
if (data == null || data.getData() == null) {
return false;
}
return init(data.getData(), data.getType(), data.getLoop());
}
/**
* 初始化sound相關數據
*
* @param data
* @param ftype
* @param loop
* @return
*/
private boolean init(byte[] data, int ftype, boolean loop) {
boolean result = false;
ByteArrayInputStream bis = null;
try {
bis = new ByteArrayInputStream(data);
} catch (Exception e) {
bis = null;
}
if (bis == null) {
return false;
}
// 判斷類型
switch (ftype) {
// MIDI
case SoundData._L_SOUNDTYPE_MIDI:
// 當MIDI不存在時
if (_midi == null) {
try {
// 獲得Sequencer
_midi = MidiSystem.getSequencer();
_midi.open();
} catch (Exception ex) {
_midi = null;
}
if (_midi != null) {
_midi.addMetaEventListener(this);
}
}
// 當MIDI依舊未獲得時
if (_midi != null) {
// 重新創建Sequence
Sequence sc = null;
try {
sc = MidiSystem.getSequence(bis);
} catch (Exception e) {
sc = null;
}
if (sc != null) {
try {
_midi.setSequence(sc);
// 獲得是否循環播放
_loop = loop;
// 獲得是否載入
result = true;
} catch (Exception ee) {
}
// 獲得聲音類型
_soundType = SoundData._L_SOUNDTYPE_MIDI;
}
}
try {
bis.close();
} catch (Exception ee) {
}
break;
// Wav
case SoundData._L_SOUNDTYPE_WAV:
AudioFileFormat type = null;
// 獲得Audio
try {
type = AudioSystem.getAudioFileFormat(bis);
} catch (Exception e) {
type = null;
}
// 關閉流
try {
bis.close();
} catch (Exception ex) {
}
if (type == null) {
return false;
}
// 根據指定信息構造數據行的信息對象
DataLine.Info di = new DataLine.Info(Clip.class, type.getFormat());
// 轉為Clip
try {
_audio = (Clip) AudioSystem.getLine(di);
} catch (Exception e) {
}
// 播放文件
try {
_audio.open(type.getFormat(), data, 0, data.length);
_loop = loop;
result = true;
} catch (Exception e) {
}
// 獲得文件類型
_soundType = SoundData._L_SOUNDTYPE_WAV;
break;
}
return result;
}
public boolean play(SoundData data) {
if (!load(data)) {
return false;
}
return play();
}
public boolean play() {
switch (_soundType) {
case SoundData._L_SOUNDTYPE_MIDI:
try {
_midi.start();
_playing = true;
_soundType = SoundData._L_SOUNDTYPE_MIDI;
} catch (Exception ee) {
}
break;
case SoundData._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;
}
/**
* 自動播放,循環停止后結束。
*
* @param data
* @return
*/
public boolean AutoPlay(SoundData data) {
if (!load(data)) {
return false;
}
return AutoPlay();
}
/**
* 自動播放,循環停止后結束。
*
* @return
*/
public boolean AutoPlay() {
_isRun = true;
_thread = new Thread(this);
_thread.start();
return _playing;
}
/**
* 停止播放
*/
public void stop() {
if (_audio != null && _audio.isActive()) {
try {
_audio.stop();
} catch (Exception e) {
}
}
if (_midi != null) {
_midi.stop();
}
_playing = false;
_isRun = false;
}
/**
* 釋放數據
*
*/
public void reset() {
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
*/
public void meta(MetaMessage meta) {
// 判斷是否循環播放MIDI
if (_loop && _soundType == SoundData._L_SOUNDTYPE_MIDI
&& meta.getType() == 47) {
if (_midi != null && _midi.isOpen()) {
_midi.setMicrosecondPosition(0);
_midi.start();
}
}
}
public void run() {
while (_isRun) {
play();
// 因為播放類型唯一,所以只會返回一個_playing結果,以此判定。
if (_midi != null) {
_playing = _midi.isRunning();
}
if (_audio != null) {
_playing = _audio.isRunning();
}
// 當播放停止
if (!_playing) {
// 釋放
reset();
}
try {
Thread.sleep(_sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public int getSleepTime() {
return _sleepTime;
}
/**
* 設定AutoPlay線程循環時間。
*
* @param time
*/
public void setSleepTime(int time) {
_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>
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class SoundPlayTest {
static void selectPlay(int ftype){
SoundData data=null;
switch(ftype){
//通過loonframework下uri從網絡播放音樂
case 0:
data=new SoundData(new URI("http://looframework.sourceforge.net/midi/誰是大英雄.mid"),SoundData._L_SOUNDTYPE_MIDI,false);
break;
//通過本地資源下音樂文件的byte[]對象播放音樂
case 1:
byte[] bytes=StreamHelper.GetResourceData("/midi/誰是大英雄.mid");
data=new SoundData(bytes,SoundData._L_SOUNDTYPE_MIDI,false);
break;
//通過音樂文件路徑播放音樂
case 2:
data=new SoundData("C:/誰是大英雄.mid",SoundData._L_SOUNDTYPE_MIDI,false);
break;
}
SoundPlay play=new SoundPlay();
//AutoPlay與Play方法的區別在于,AutoPlay播放完畢會自動停止并釋放資源,play需手動中止。
//play.play(data);
play.AutoPlay(data);
}
public static void main(String[]args){
selectPlay(2);
}
}

更詳細方法,會待Loonframework-game完全公布后,再進行解釋。
另:由于StreamHelper關聯其他Loonframework中方法,暫不給出,inputStream轉byte[]可用如下寫法:
//is為獲得的inputStream
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//用于承接byte[]
byte[] arrayByte = null;
try {
// 每次傳輸大小為4096
byte[] bytes = new byte[4096];
bytes = new byte[is.available()];
int read;
while ((read = is.read(bytes)) >= 0) {
byteArrayOutputStream.write(bytes, 0, read);
}
arrayByte = byteArrayOutputStream.toByteArray();
} catch (IOException e) {
return null;
} finally {
try {
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
byteArrayOutputStream = null;
}
if (is != null) {
is.close();
is = null;
}
} catch (IOException e) {
}
}

浙公網安備 33010602011771號