com.beatofthedrum.alacdecoder.spi.CircularBuffer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jald Show documentation
Show all versions of jald Show documentation
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();
}
}