JavaSoundEngine-声音引擎播放器源代码
JavaSoundEngine-声音引擎播放器源代码
## 实现一
```
import java.io.*;
import javax.sound.sampled.*;
/**
* Class SoundEngine provides functionality to process sound files.
* Sounds can be loaded, played, paused, resumed, and stopped.
*
* The sound engine can play multiple sounds simultaniously, but only
* the last sound loaded can be controlled (pased, resumed, etc.).
*
* The sound engine accepts files in WAV, AIFF, and AU formats (although
* not all WAV files - it depends on the encoding in the file).
*
* @author Michael Kolling and David J Barnes
* @version 1.0
*/
public class SoundEngine
{
// the following three fields hold information about the sound clip
// currently loaded in this engine
private Clip currentSoundClip = null;
private int currentSoundDuration = 0;
private int currentSoundFrameLength = 0;
/**
* Create a SoundEngine that can play sound files.
*/
public SoundEngine()
{
}
/**
* Load and play a specified sound file. If the file is not in a
* recognised file format, false is returned. Otherwise the sound
* is started and true is returned. The method returns immediately
* after the sound starts (not after the sound finishes).
*
* @param soundFile The file to be loaded.
* @return True, if the sound file could be loaded, false otherwise.
*/
public boolean play(File soundFile)
{
if(loadSound(soundFile)) {
currentSoundClip.start();
return true;
}
else {
return false;
}
}
/**
* Stop the currently playing sound (if there is one playing). If no
* sound is playing, this method has no effect.
*/
public void stop()
{
if(currentSoundClip != null) {
currentSoundClip.stop();
currentSoundClip = null;
}
}
/**
* Pause the currently playing sound. If no sound is currently playing,
* calling this method has no effect.
*/
public void pause()
{
if(currentSoundClip != null) {
currentSoundClip.stop();
}
}
/**
* Resume the currently paused sound. If no sound is currently paused,
* this method has no effect.
*/
public void resume()
{
if(currentSoundClip != null) {
currentSoundClip.start();
}
}
/**
* Set the current playing position in the currently playing sound to 'value'.
* 'value' is a percentage value (0 to 100). If there is no sound currently
* playing, this method has no effect.
*
* @param value The target position in the sound file, as a percentage.
*/
public void seek(int value)
{
if(currentSoundClip != null) {
int seekPosition = currentSoundFrameLength / 100 * value;
currentSoundClip.setFramePosition(seekPosition);
}
}
/**
* Set the playback volume of the current sound. If no sound is currently
* loaded, this method has no effect.
*
* @param vol Volume level as a percentage (0..100).
*/
public void setVolume(int vol)
{
if(currentSoundClip == null) {
return;
}
if(vol < 0 &##124;&##124; vol > 100) {
vol = 100;
}
double val = vol / 100.0;
try {
FloatControl volControl =
(FloatControl) currentSoundClip.getControl(FloatControl.Type.MASTER_GAIN);
float dB = (float)(Math.log(val == 0.0 ? 0.0001 : val) / Math.log(10.0) * 20.0);
volControl.setValue(dB);
} catch (Exception ex) {
System.out.println("could not set volume");
}
}
/**
* Return the duration of the currently loaded sound clip.
*
* @return The duration of the current sound, or 0 if no sound has been loaded.
*/
public int getDuration()
{
return currentSoundDuration;
}
/**
* Load the sound file supplied by the parameter into this sound engine.
*
* @return True if successful, false if the file could not be decoded.
*/
private boolean loadSound(File file)
{
currentSoundDuration = 0;
try {
AudioInputStream stream = AudioSystem.getAudioInputStream(file);
AudioFormat format = stream.getFormat();
// we cannot play ALAW/ULAW, so we convert them to PCM
//
if ((format.getEncoding() == AudioFormat.Encoding.ULAW) &##124;&##124;
(format.getEncoding() == AudioFormat.Encoding.ALAW))
{
AudioFormat tmp = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
format.getSampleRate(),
format.getSampleSizeInBits() * 2,
format.getChannels(),
format.getFrameSize() * 2,
format.getFrameRate(),
true);
stream = AudioSystem.getAudioInputStream(tmp, stream);
format = tmp;
}
DataLine.Info info = new DataLine.Info(Clip.class,
stream.getFormat(),
((int) stream.getFrameLength() *
format.getFrameSize()));
currentSoundClip = (Clip) AudioSystem.getLine(info);
currentSoundClip.open(stream);
currentSoundFrameLength = (int) stream.getFrameLength();
currentSoundDuration = (int) (currentSoundClip.getBufferSize() /
(currentSoundClip.getFormat().getFrameSize() *
currentSoundClip.getFormat().getFrameRate()));
return true;
} catch (Exception ex) {
currentSoundClip = null;
return false;
}
}
}
```
## 实现二
```
package com.zhenzhigu.higame.audio;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.SourceDataLine;
import com.zhenzhigu.higame.util.FileUtil;
public class Sound {
public static void main(String[] args) throws InterruptedException {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
// TODO Auto-generated method stub
}
}, 0,100);
for(int i=1;i<=10000;i++){
Sound pl = new Sound ();
pl.init(FileUtil.getAssetAsFile("music/swish-1.mp3"));
pl.loop(1);
Thread.sleep(100);
System.out.println(i);
}
}
private Clip clip = null;
private int loops = 1;
private boolean closed = false;
public void init(File file){
try {
AudioInputStream srcInput = AudioSystem.getAudioInputStream(file);
AudioInputStream audioInput = null;
if(srcInput.getFormat().getEncoding()==Encoding.PCM_SIGNED){
audioInput = srcInput;
}else{
//根据原始音频流格式创建新的PCM格式
final AudioFormat outFormat = this.getOutFormat(srcInput.getFormat());
audioInput = AudioSystem.getAudioInputStream(outFormat, srcInput);
}
DataLine.Info clipInfo = new DataLine.Info(Clip.class, audioInput.getFormat());
this.clip = ((Clip)AudioSystem.getLine(clipInfo));
this.clip.open(audioInput);
this.clip.addLineListener(new LineListener() {
public void update(LineEvent event) {
if(closed &##124;&##124; isDone() ){
clip.close();
}
}
});
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
private AudioFormat getOutFormat(AudioFormat inFormat) {
final int ch = inFormat.getChannels();
final float rate = inFormat.getSampleRate();
return new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, rate, 16, ch, ch * 2, rate, false);
}
//---------- Controller -----------
public void start(){
this.clip.start();
}
public void stop()
{
clip.stop();
clip.setFramePosition(0);
}
public void pause()
{
clip.stop();
}
public void close(){
closed = true;
clip.close();
clip = null;
}
public boolean isDone(){
return (loops!=0 && (loops*clip.getFrameLength()==clip.getFramePosition()));
}
/*
* 设置音量:0-200
*/
public void setGain(float vol) {
double value = vol / 100.0f;
try {
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
float db = (float)(Math.log(value==0.0?0.0001:value)/Math.log(10.0)*20.0);
System.out.println(db);
gainControl.setValue(db);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* 循环次数:0代表无限循环,1代表播放1次
* @param i
*/
public void loop(int i)
{
clip.setLoopPoints(0, -1);
clip.loop(i-1);
this.loops = i;
}
public void setPosition(int frames){
clip.setFramePosition(frames);
}
public int getPosition()
{
return clip.getFramePosition();
}
public boolean isRunning()
{
return clip.isRunning();
}
}
```