⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 playbackthread.java

📁 Java version of ABC/HR comparator v0.5. by schnofler. Runs on Sun JRE 1.5 or later
💻 JAVA
字号:
package abchr.audio;

import guiutils.PositionMarker;

import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.io.IOException;
import java.util.Vector;
import java.util.Arrays;


public class PlaybackThread implements ChangeListener {
	private static final PlaybackThread INSTANCE=new PlaybackThread();

	public static PlaybackThread getInstance() {
		return INSTANCE;
	}

	private Mixer mixer;

	private int bufferSize;

	private Player currentPlayer;
	private float start=0.0f;
	private float end=-1.0f;
	private float startedAt=0;
	private boolean fastSwitching=true;
	private boolean loop;
	private BoundedRangeModel rangeModel;
	private PositionMarker posMarker=new PositionMarker();


	private class Player implements Runnable {
		private Sample sample;
		private AudioInputStream stream;
		private SourceDataLine line;
		private byte[] buffer;
		private boolean stop;
		private boolean playing;

		public Player(Sample sample,SourceDataLine line,float start) {
			this.sample=sample;
			buffer=new byte[line.getBufferSize()];
			initStream(start);
			this.line=line;
			//System.out.println("end="+end);
		}

		private void initStream(float start) {
			stream=sample.getStream();
			AudioFormat format=sample.getFormat();
			int offset=SampleOffset.getOffset(sample);
			int skip=((int)((start+offset/1000.0f)*format.getFrameRate()))*format.getFrameSize();
			try {
				int skipped=0;
				while(skipped<skip) {
					skipped+=stream.skip(skip-skipped);
				}
			} catch(IOException e) {
				e.printStackTrace();
			}
		}

		private void resetStream() {
			startedAt=start;
			initStream(start);
			line.close();
			try {
				line.open(stream.getFormat(),buffer.length);
			} catch(LineUnavailableException e) {
				e.printStackTrace();
			}
		}

		public void run() {
			line.start();
			int n=0;
			long linePosition;
			long lastPositionUpdate=0;
			setPlaying(true);
			try {
				while(!stopRequested()) {
					linePosition=line.getMicrosecondPosition();
					//System.out.println("lineposition="+(startedAt+linePosition/1000000.0f)+", end="+end);
					if(posMarker!=null && linePosition-lastPositionUpdate>50000l) {
						posMarker.setPosition((int)(startedAt*1000+linePosition/1000l));
						lastPositionUpdate=linePosition;
					}
					if(/*end!=-1 && */startedAt+linePosition/1000000.0f+0.01f>end) {
						if(isLooping()) {
							line.stop();
							line.flush();
							resetStream();
							lastPositionUpdate=0;
							line.start();
							continue;
						}
						break;
					}
					if(line.available()<8192){try{Thread.sleep(20);}catch(InterruptedException e){}continue;}
					n=stream.read(buffer,0,line.available());
					//System.out.println("read "+n+" bytes");
					if(n==-1) {
						//System.out.println("n==-1");
						/*if(!line.isActive()) {
							//System.out.println("line inactive");
							if(isLooping()) {
								line.flush();
								resetStream();
								lastPositionUpdate=0;
								line.start();
								continue;
							}
						}*/
						try{Thread.sleep(20);}catch(InterruptedException e){e.printStackTrace();}
						continue;
					}
					/*if(oldPlayer!=null) {
						oldPlayer.stopPlayback();
						oldPlayer=null;
					}*/
					/*if(!oldPlayers.isEmpty()) {
						((Player)oldPlayers.get(0)).stopPlayback();
						//oldPlayer=null;
					}*/
					line.write(buffer,0,n);
				}
			} catch(IOException e) {
				e.printStackTrace();
			}
			setPlaying(false);
			if(n!=-1) {
				posMarker.setPosition(-1);
			}
			//line.stop();
			line.close();
		}

		public float getPosition() {
			return startedAt+line.getMicrosecondPosition()/1000000.0f;
		}

		public synchronized void stopPlayback() {
			line.stop();
			stop=true;
		}
		public synchronized boolean stopRequested(){return stop;}
		public synchronized boolean isPlaying(){return playing;}
		private synchronized void setPlaying(boolean playing){this.playing=playing;}
	}

	private PlaybackThread() {
		Mixer.Info[] info=AudioSystem.getMixerInfo();
		/*System.out.println(Arrays.deepToString(info));
		for(Mixer.Info in : info) {
			System.out.println(in.getDescription());
			Mixer mixer=AudioSystem.getMixer(in);
			Line.Info[] sourceLineInfo=mixer.getSourceLineInfo();
			for(int i=0;i<sourceLineInfo.length;i++) {
				System.out.println(sourceLineInfo[i].toString());
			}
		}
		mixer=null;
		for(int i=0;i<info.length;i++) {
			if(info[i].getName().startsWith("Java Sound")) {
				mixer=AudioSystem.getMixer(info[i]);
				javaAudioMixer=true;
			}
		}*/
		for(Mixer.Info in : info) {
			Mixer m=AudioSystem.getMixer(in);
			if(m.getSourceLineInfo().length!=0){mixer=m;}
		}
		//mixer=AudioSystem.getMixer(info[0]);
		Control[] controls=mixer.getControls();
		for(int i=0;i<controls.length;i++) {
			if(controls[i].getType()==EnumControl.Type.REVERB) {
				Object[] values=((EnumControl)controls[i]).getValues();
				ReverbType rt;
				for(int j=0;j<values.length;j++) {
					rt=(ReverbType)values[j];
					if(rt.getEarlyReflectionIntensity()==0.0f && rt.getLateReflectionIntensity()==0.0f && rt.getDecayTime()==0) {
						((EnumControl)controls[i]).setValue(values[j]);
						//System.out.println("Set Reverb to "+controls[i]);
					}
				}
			}
		}
	}

	public void shutdown() {
		stopPlayback();
	}

	private Vector oldPlayers=new Vector();

	public void play(Sample sample) {
		SourceDataLine line=null;
		AudioFormat format=sample.getFormat();
		DataLine.Info info=new DataLine.Info(SourceDataLine.class,format,format.getFrameSize()*(int)(bufferSize*format.getSampleRate()/1000));
		try {
			line=(SourceDataLine)mixer.getLine(info);
			line.open(format,format.getFrameSize()*(int)(bufferSize*format.getSampleRate()/1000));
			if(SampleGain.getGain(sample)!=0.0f) {
				FloatControl gainControl=(FloatControl)line.getControl(FloatControl.Type.MASTER_GAIN);
				gainControl.setValue(SampleGain.getGain(sample));
			}
		} catch(LineUnavailableException e) {
			e.printStackTrace();
		}
		if(currentPlayer!=null){oldPlayers.add(currentPlayer);}
		if(currentPlayer!=null && currentPlayer.isPlaying() && fastSwitching) {
			startedAt=currentPlayer.getPosition();
		} else {
			startedAt=start;
		}
		currentPlayer=new Player(sample,line,startedAt);
		Thread t=new Thread(currentPlayer);
		t.start();
		Thread.yield();
		if(!oldPlayers.isEmpty()) {
			synchronized(oldPlayers) {
				while(!oldPlayers.isEmpty()) {
					((Player)oldPlayers.get(0)).stopPlayback();
					oldPlayers.remove(0);
				}
			}
		}
	}

	public void stopPlayback() {
		stopPlayback(false);
	}

	public void stopPlayback(boolean pause) {
		posMarker.setPosition(-1);
		//System.out.println("stopPlayback");
		if(currentPlayer!=null){currentPlayer.stopPlayback();}
	}

	public boolean isFastSwitching(){return fastSwitching;}
	public void setFastSwitching(boolean fastSwitching){this.fastSwitching=fastSwitching;}
	public synchronized boolean isLooping(){return loop;}
	public synchronized void setLooping(boolean loop){this.loop=loop;}

	public void stateChanged(ChangeEvent e) {
		stopPlayback();
		start=rangeModel.getValue()/1000.0f;
		end=(rangeModel.getValue()+rangeModel.getExtent())/1000.0f;
	}

	public void setRangeModel(BoundedRangeModel model) {
		if(rangeModel!=null){rangeModel.removeChangeListener(this);}
		rangeModel=model;
		if(rangeModel!=null){rangeModel.addChangeListener(this);}
		stateChanged(null);
	}

	public BoundedRangeModel getRangeModel(){return rangeModel;}
	public PositionMarker getPosMarker(){return posMarker;}

	public int getBufferSize(){return bufferSize;}
	public void setBufferSize(int bufferSize){this.bufferSize=bufferSize;}

	public Mixer.Info getMixer(){return mixer.getMixerInfo();}
	public void setMixer(Mixer.Info info){stopPlayback();mixer=AudioSystem.getMixer(info);}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -