random access files now used to sync visualizer with song (optimization)
This commit is contained in:
		| @@ -1,6 +1,12 @@ | ||||
| package zero1hd.rhythmbullet.audio; | ||||
|  | ||||
| import java.io.BufferedInputStream; | ||||
| import java.io.FileNotFoundException; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.RandomAccessFile; | ||||
| import java.nio.channels.Channels; | ||||
| import java.security.InvalidParameterException; | ||||
| import java.util.concurrent.ExecutorService; | ||||
| import java.util.concurrent.Executors; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| @@ -30,9 +36,9 @@ import javazoom.jl.decoder.OutputBuffer; | ||||
| public class Mp3Manager implements MusicManager { | ||||
| 	private int readWindowSize = 1024; | ||||
| 	 | ||||
| 	private int currentReadWindowIndex; | ||||
| 	private int readWindowIndex; | ||||
| 	private Music playbackMusic; | ||||
| 	private int readIndex; | ||||
| 	private int playbackIndex; | ||||
| 	 | ||||
| 	private int sampleRate; | ||||
| 	private long sampleCount; | ||||
| @@ -41,10 +47,11 @@ public class Mp3Manager implements MusicManager { | ||||
| 	Bitstream bitstream; | ||||
| 	MP3Decoder decoder; | ||||
| 	OutputBuffer sampleBuffer; | ||||
| 	InputStream inputStream; | ||||
| 	private byte[] currentByteSet; | ||||
| 	private byte[] workset; | ||||
| 	private int indexHead = -1; | ||||
| 	 | ||||
| 	private RandomAccessFile raf; | ||||
| 	private FileHandle file; | ||||
| 	ReentrantLock lock = new ReentrantLock(); | ||||
| 	 | ||||
| @@ -71,9 +78,14 @@ public class Mp3Manager implements MusicManager { | ||||
| 			lock.unlock(); | ||||
| 		}); | ||||
| 		 | ||||
| 		bitstream = new Bitstream(audioFile.read()); | ||||
| 		decoder = new MP3Decoder(); | ||||
| 		 | ||||
| 		try { | ||||
| 			raf = new RandomAccessFile(audioFile.file(), "r"); | ||||
| 			bitstream = new Bitstream(inputStream = Channels.newInputStream(raf.getChannel())); | ||||
| 			decoder = new MP3Decoder(); | ||||
| 		} catch (FileNotFoundException e2) { | ||||
| 			e2.printStackTrace(); | ||||
| 			throw new InvalidParameterException("Error with creating RandomAccessFile."); | ||||
| 		} | ||||
| 		try { | ||||
| 			Header header = bitstream.readFrame(); | ||||
| 			if (header == null) throw new GdxRuntimeException("Empty MP3"); | ||||
| @@ -88,15 +100,22 @@ public class Mp3Manager implements MusicManager { | ||||
| 		playbackMusic = Gdx.audio.newMusic(audioFile); | ||||
| 		 | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void setReadIndexToPlaybackIndex() { | ||||
| 		try { | ||||
| 			raf.seek((long) (getPositionInSeconds()*(long)sampleRate)); | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
| 	@Override | ||||
| 	public void playbackIndexUpdate() { | ||||
| 		readIndex = (int) (playbackMusic.getPosition() * sampleRate / readWindowSize); | ||||
| 		playbackIndex = (int) (playbackMusic.getPosition() * sampleRate / readWindowSize); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public int getPlaybackIndexPosition() { | ||||
| 		return readIndex; | ||||
| 		return playbackIndex; | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| @@ -132,7 +151,7 @@ public class Mp3Manager implements MusicManager { | ||||
| 				samples[sid] /= Short.MAX_VALUE+1; | ||||
| 			} | ||||
| 		} | ||||
| 		currentReadWindowIndex++; | ||||
| 		readWindowIndex++; | ||||
|  | ||||
| 		return framesRead; | ||||
| 	} | ||||
| @@ -185,8 +204,8 @@ public class Mp3Manager implements MusicManager { | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public int getCurrentReadWindowIndex() { | ||||
| 		return currentReadWindowIndex; | ||||
| 	public int getreadWindowIndex() { | ||||
| 		return readWindowIndex; | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| @@ -262,7 +281,8 @@ public class Mp3Manager implements MusicManager { | ||||
| 		try { | ||||
| 			bitstream.close(); | ||||
| 			bitstream = null; | ||||
| 		} catch (BitstreamException e) { | ||||
| 			inputStream.close(); | ||||
| 		} catch (BitstreamException | IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -13,7 +13,7 @@ public interface MusicManager extends Disposable { | ||||
| 	public void playbackIndexUpdate(); | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Gets the current position in seconds s | ||||
| 	 * Gets the current position in seconds | ||||
| 	 * @return the current frame of audio. | ||||
| 	 */ | ||||
| 	public int getPlaybackIndexPosition(); | ||||
| @@ -54,7 +54,7 @@ public interface MusicManager extends Disposable { | ||||
| 	 * The current numerical value of the last window read | ||||
| 	 * @return | ||||
| 	 */ | ||||
| 	public int getCurrentReadWindowIndex(); | ||||
| 	public int getreadWindowIndex(); | ||||
|  | ||||
| 	public void pause(); | ||||
|  | ||||
| @@ -87,4 +87,8 @@ public interface MusicManager extends Disposable { | ||||
| 	 * @return the song filehandle. | ||||
| 	 */ | ||||
| 	public FileHandle getMusicFile(); | ||||
| 	 | ||||
| 	/** | ||||
| 	 */ | ||||
| 	public void setReadIndexToPlaybackIndex(); | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,9 @@ | ||||
| package zero1hd.rhythmbullet.audio; | ||||
|  | ||||
| import java.io.BufferedInputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.RandomAccessFile; | ||||
| import java.nio.channels.Channels; | ||||
| import java.security.InvalidParameterException; | ||||
|  | ||||
| import javax.sound.sampled.AudioFormat; | ||||
| @@ -15,17 +18,20 @@ import zero1hd.rhythmbullet.audio.wavedecoder.WavDecoder; | ||||
| public class WAVManager implements MusicManager { | ||||
| 	private int readWindowSize = 1024; | ||||
| 	private AudioFormat format; | ||||
| 	private int readIndex; | ||||
| 	private int currentReadWindowIndex; | ||||
| 	private int playbackIndex; | ||||
| 	private int readWindowIndex; | ||||
| 	private Music playbackMusic; | ||||
| 	WavDecoder decoder; | ||||
| 	private FileHandle file; | ||||
| 	private String basicSongName; | ||||
| 	private RandomAccessFile raf; | ||||
| 	 | ||||
| 	public WAVManager(FileHandle file) { | ||||
| 		this.file = file; | ||||
| 		basicSongName = file.name(); | ||||
| 		try { | ||||
| 			decoder = new WavDecoder(file); | ||||
| 			raf = new RandomAccessFile(file.file(), "r"); | ||||
| 			decoder = new WavDecoder(new BufferedInputStream(Channels.newInputStream(raf.getChannel()))); | ||||
| 		} catch (InvalidParameterException | IOException e) { | ||||
| 			// TODO Auto-generated catch block | ||||
| 			e.printStackTrace(); | ||||
| @@ -36,19 +42,28 @@ public class WAVManager implements MusicManager { | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void playbackIndexUpdate() { | ||||
| 		readIndex = (int) (playbackMusic.getPosition() * decoder.getSampleRate() / readWindowSize); | ||||
| 		playbackIndex = (int) (playbackMusic.getPosition() * decoder.getSampleRate() / readWindowSize); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public int getPlaybackIndexPosition() { | ||||
| 		return readIndex; | ||||
| 		return playbackIndex; | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public int getReadWindowSize() { | ||||
| 		return readWindowSize; | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void setReadIndexToPlaybackIndex() { | ||||
| 		try { | ||||
| 			raf.seek((long) (getPositionInSeconds()*(long)getSampleRate())); | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public int readSamples(float[] samples) { | ||||
| 		int samplesRead = 0; | ||||
| @@ -59,7 +74,7 @@ public class WAVManager implements MusicManager { | ||||
| 		} | ||||
| 		 | ||||
| 		if (samplesRead != 0) { | ||||
| 			currentReadWindowIndex++; | ||||
| 			readWindowIndex++; | ||||
| 		} | ||||
| 		return samplesRead; | ||||
| 	} | ||||
| @@ -87,8 +102,8 @@ public class WAVManager implements MusicManager { | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public int getCurrentReadWindowIndex() { | ||||
| 		return currentReadWindowIndex; | ||||
| 	public int getreadWindowIndex() { | ||||
| 		return readWindowIndex; | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
|   | ||||
| @@ -172,7 +172,7 @@ public class BasicVisualizer extends VisualizerCore { | ||||
| 	} | ||||
| 	 | ||||
| 	public void flip() { | ||||
| 		flip = flip ? false : true; | ||||
| 		flip = !flip; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isFlipped() { | ||||
|   | ||||
| @@ -17,26 +17,29 @@ public class VisualizerCore implements Disposable { | ||||
| 	protected int barCount; | ||||
| 	private boolean calc; | ||||
| 	private ReentrantLock lock; | ||||
| 	private float updateRate; | ||||
| 	private float updateTimer; | ||||
| 	public VisualizerCore(int width, int height, int x, int y) { | ||||
| 		this.height = height; | ||||
| 		this.width = width; | ||||
| 		this.xPos = x; | ||||
| 		this.yPos = y; | ||||
| 		 | ||||
| 		updateRate = 1f/30f; | ||||
| 		lock = new ReentrantLock(); | ||||
| 	} | ||||
| 	 | ||||
| 	public void calculate() { | ||||
| 		if (mm != null) { | ||||
| 			mm.playbackIndexUpdate(); | ||||
| 			lock.lock(); | ||||
| 			while (calc && mm.isPlaying() && mm.getPlaybackIndexPosition() > mm.getCurrentReadWindowIndex()) { | ||||
| 	public void calculate(float delta) { | ||||
| 		if (mm != null && calc && mm.isPlaying()) { | ||||
| 			updateTimer += delta; | ||||
| 			if (updateTimer >= updateRate) { | ||||
| 				mm.playbackIndexUpdate(); | ||||
| 				lock.lock(); | ||||
| 				mm.setReadIndexToPlaybackIndex(); | ||||
| 				mm.readSamples(audioPCM); | ||||
| 				if (mm.getPlaybackIndexPosition() == mm.getCurrentReadWindowIndex()) { | ||||
| 					fft.realForward(audioPCM); | ||||
| 				} | ||||
| 				fft.realForward(audioPCM); | ||||
| 				lock.unlock(); | ||||
| 				updateTimer = 0; | ||||
| 			} | ||||
| 			lock.unlock(); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| @@ -95,4 +98,12 @@ public class VisualizerCore implements Disposable { | ||||
| 	public MusicManager getMm() { | ||||
| 		return mm; | ||||
| 	} | ||||
| 	 | ||||
| 	public void setUpdateRate(float updateRate) { | ||||
| 		this.updateRate = updateRate; | ||||
| 	} | ||||
| 	 | ||||
| 	public float getUpdateRate() { | ||||
| 		return updateRate; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,31 +1,25 @@ | ||||
| package zero1hd.rhythmbullet.audio.wavedecoder; | ||||
|  | ||||
| import java.io.BufferedInputStream; | ||||
| import java.io.IOException; | ||||
|  | ||||
| import javax.sound.sampled.AudioInputStream; | ||||
| import javax.sound.sampled.AudioSystem; | ||||
| import javax.sound.sampled.UnsupportedAudioFileException; | ||||
|  | ||||
| import com.badlogic.gdx.files.FileHandle; | ||||
|  | ||||
| public class WavDecoder { | ||||
| 	private FileHandle file; | ||||
| 	 | ||||
| 	private int channels; | ||||
| 	private double sampleRate; | ||||
| 	private String fileName; | ||||
| 	private byte[] buffer; | ||||
| 	private AudioInputStream audioInputStream; | ||||
| 	 | ||||
| 	public WavDecoder(FileHandle file) throws IOException { | ||||
| 		this.file = file; | ||||
| 	public WavDecoder(BufferedInputStream inputStream) throws IOException { | ||||
| 		try { | ||||
| 			audioInputStream = AudioSystem.getAudioInputStream(file.file()); | ||||
| 			audioInputStream = AudioSystem.getAudioInputStream(inputStream); | ||||
| 			buffer = new byte[audioInputStream.getFormat().getFrameSize()]; | ||||
| 			 | ||||
| 			channels = audioInputStream.getFormat().getChannels(); | ||||
| 			sampleRate = audioInputStream.getFormat().getSampleRate(); | ||||
| 			fileName = file.name(); | ||||
| 		} catch (UnsupportedAudioFileException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| @@ -47,14 +41,6 @@ public class WavDecoder { | ||||
| 		return audioInputStream.getFrameLength(); | ||||
| 	} | ||||
| 	 | ||||
| 	public String getFileName() { | ||||
| 		return fileName; | ||||
| 	} | ||||
| 	 | ||||
| 	public FileHandle getFile() { | ||||
| 		return file; | ||||
| 	} | ||||
| 	 | ||||
| 	public int readSamples(float[] samples) throws IOException { | ||||
| 		int framesRead = 0; | ||||
| 		 | ||||
| @@ -74,6 +60,10 @@ public class WavDecoder { | ||||
| 		return framesRead; | ||||
| 	} | ||||
| 	 | ||||
| 	public AudioInputStream getAudioInputStream() { | ||||
| 		return audioInputStream; | ||||
| 	} | ||||
| 	 | ||||
| 	public void cleanAndClose() { | ||||
| 		try { | ||||
| 			audioInputStream.close(); | ||||
|   | ||||
| @@ -40,7 +40,7 @@ public class Visualizer extends Widget implements Disposable { | ||||
| 			vis.updatePositionInfo(); | ||||
| 			vis.setxPos((getWidth() - vis.getActualWidth())/2f); | ||||
| 		} | ||||
| 		vis.calculate(); | ||||
| 		vis.calculate(delta); | ||||
| 		super.act(delta); | ||||
| 	} | ||||
| 	 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user