All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.beatofthedrum.alacdecoder.spi.CircularBuffer Maven / Gradle / Ivy

Go to download

Java implementation of Apple Lossless decoder supports both 16-bit and 24-bit Apple Lossless files

The newest version!
package com.beatofthedrum.alacdecoder.spi;

/**
 * CircularBuffer for asynchronous reading.
 * Adopted from Tritonus (http://www.tritonus.org/).
 * @author in-somnia
 */
class CircularBuffer {

	private static final int BUFFER_SIZE = 327670;
	private final byte[] data;
	private final Trigger trigger;
	private long readPos, writePos;
	private boolean open;

	CircularBuffer(Trigger trigger) {
		this.trigger = trigger;
		data = new byte[BUFFER_SIZE];
		readPos = 0;
		writePos = 0;
		open = true;
	}

	public void close() {
		open = false;
	}

	public boolean isOpen() {
		return open;
	}

	public int availableRead() {
		return (int) (writePos-readPos);
	}

	public int availableWrite() {
		return BUFFER_SIZE-availableRead();
	}

	private int getReadPos() {
		return (int) (readPos%BUFFER_SIZE);
	}

	private int getWritePos() {
		return (int) (writePos%BUFFER_SIZE);
	}

	public int read(byte[] b) {
		return read(b, 0, b.length);
	}

	public int read(byte[] b, int off, int len) {
		if(!isOpen()) {
			if(availableRead()>0)
				len = Math.min(len, availableRead());
			else
				return -1;
		}
		synchronized(this) {
			if (trigger != null && availableRead() < len) {
				trigger.execute();
			}
			len = Math.min(availableRead(), len);
			int remaining = len;
			while(remaining>0) {
				while(availableRead()==0) {
					try {
						wait();
					}
					catch(InterruptedException e) {
					}
				}
				int available = Math.min(availableRead(), remaining);
				int toRead;
				while(available>0) {
					toRead = Math.min(available, BUFFER_SIZE-getReadPos());
					System.arraycopy(data, getReadPos(), b, off, toRead);
					readPos += toRead;
					off += toRead;
					available -= toRead;
					remaining -= toRead;
				}
				notifyAll();
			}
			return len;
		}
	}

	public int write(byte[] b) {
		return write(b, 0, b.length);
	}

	public int write(byte[] b, int off, int len) {
		synchronized(this) {
			int remaining = len;
			while(remaining>0) {
				while(availableWrite()==0) {
					try {
						wait();
					}
					catch(InterruptedException ignored) {
					}
				}
				int available = Math.min(availableWrite(), remaining);
				int toWrite;
				while(available>0) {
					toWrite = Math.min(available, BUFFER_SIZE-getWritePos());
					System.arraycopy(b, off, data, getWritePos(), toWrite);
					writePos += toWrite;
					off += toWrite;
					available -= toWrite;
					remaining -= toWrite;
				}
				notifyAll();
			}
			return len;
		}
	}

	interface Trigger {

		void execute();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy