/* RoundBufferSampleSource.java created 2010-09-07
*
*/
package org.signalml.domain.signal.samplesource;
/**
* Round buffer which can be used for samples storage/caching.
*
* @author Piotr Szachewicz
*/
public class RoundBufferSampleSource {
/**
* an index at which next sample will be stored in samples[] array
*/
protected int nextInsertPos = 0;
/**
* a boolean indicating, if the buffer is full
*/
protected boolean full;
/**
* an array containing samples.
*/
protected double samples[];
/**
* an integer indicating how much samples can be stored in the buffer
*/
protected int sampleCount;
/**
* Constructor. Creates a new {@link RoundBufferSampleSource} which can
* store up to a given number of samples.
* @param sampleCount number of samples which the buffer must be able
* to store
*/
public RoundBufferSampleSource(int sampleCount) {
this.sampleCount = sampleCount;
samples = new double[sampleCount];
}
/**
* Return the next position at which a new sample will be stored in the
* samples[] array.
* @return an index in the samples[] array at which next sample will be
* stored
*/
private int getNextInsertPos() {
return nextInsertPos;
}
/**
* Changes the value of the position at which the next new sample will be
* stored.
* @param nextInsertPos the new value of nextInsertPos
*/
synchronized void setNextInsertPos(int nextInsertPos) {
this.nextInsertPos = nextInsertPos;
}
/**
* Returns whether the buffer is full or not.
* @return true if the {@link RoundBufferSampleSource} is full, false
* otherwise
*/
synchronized boolean isFull() {
return full;
}
/**
* Sets the next position in the array at which a new sample
* will be stored.
*/
protected synchronized void incrNextInsertPos() {
nextInsertPos++;
if (nextInsertPos == sampleCount) {
nextInsertPos = 0;
full = true;
}
}
/**
* Adds a number of new samples to the buffer.
* @param newSamples new samples to be added to the buffer
*/
public void addSamples(double[] newSamples) {
for (int i = 0; i < newSamples.length; i++) {
samples[nextInsertPos] = newSamples[i];
incrNextInsertPos();
}
}
public void addSample(double newSample) {
samples[nextInsertPos] = newSample;
incrNextInsertPos();
}
/**
* Returns an array containing samples in this buffer.
* @return an array containing samples in this buffer
*/
public double[] getSamples() {
return this.samples;
}
/**
* Returns the given number of samples starting from a given position in time.
* @param target the array to which results will be written starting
* from position <code>arrayOffset</code>
* @param signalOffset the position (in time) in the signal starting
* from which samples will be returned
* @param count the number of samples to be returned
* @param arrayOffset the offset in <code>target</code> array starting
* from which samples will be written
*/
public void getSamples(double[] target, int signalOffset, int count, int arrayOffset) {
double[] tmp = new double[sampleCount];
if (full) {
for (int i = 0; i < sampleCount; i++) {
tmp[i] = samples[(nextInsertPos + i) % sampleCount];
}
}
else {
if (nextInsertPos == 0) {
for (int i = 0; i < sampleCount; i++) {
tmp[i] = 0.0;
}
}
else {
int n = sampleCount - nextInsertPos;
for (int i = 0; i < n; i++)
tmp[i] = 0.0;
for (int i = n; i < sampleCount; i++) {
tmp[i] = samples[i - n];
}
}
}
for (int i = 0; i < count; i++) {
target[arrayOffset + i] = tmp[signalOffset + i];
}
}
public int getSampleCount() {
return sampleCount;
}
}