tags:

views:

70

answers:

1

I'm implementing an audio track class and I'm in need of a good circular buffer implementation. I'm using shorts for my audio samples, so I would prefer to use a ShortBuffer class for the actual buffer. This track will need to be thread-safe but I can guarantee that only one thread will read and another will write on the track. My current implementation looks like this (it doesn't handle wrapping).

public class Track {
    //sample rate 44100, 2 channels with room for 4 seconds
    private volatile ShortBuffer buffer = ShortBuffer.allocate((44100 * 2) * 4);
    //keep count of the samples in the buffer
    private AtomicInteger count = new AtomicInteger(0);
    private ReentrantLock lock = new ReentrantLock(true);
    private int readPosition = 0;

    public int getSampleCount() {
        int i = count.get();
        return i > 0 ? i / 2 : 0;
    }

    public short[] getSamples(int sampleCount) {
        short[] samples = new short[sampleCount];
        try {
            lock.tryLock(10, TimeUnit.MILLISECONDS);
            int writePosition = buffer.position();
            buffer.position(readPosition);
            buffer.get(samples);
            //set new read position
            readPosition = buffer.position();
            // set back to write position
            buffer.position(writePosition);
            count.addAndGet(-sampleCount);
        } catch (InterruptedException e) {
            System.err.println("Exception getting samples" + e);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return samples;
    }

    public void pushSamples(short[] samples) {
        try {
            lock.tryLock(10, TimeUnit.MILLISECONDS);
            buffer.put(samples);
            count.addAndGet(samples.length);
        } catch (InterruptedException e) {
            System.err.println("Exception getting samples" + e);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}
A: 

Here's the solution that I have come up with http://pastebin.com/2St01Wzf I decided it was easier to use a head and tail property with a short array, instead of just the read position with a ShortBuffer. I also took an idea from the Java collections classes to detect when the buffer is full.

Mondain