package edu.cmu.sphinx.frontend; import edu.cmu.sphinx.util.props.PropertyException; import edu.cmu.sphinx.util.props.PropertySheet; import edu.cmu.sphinx.util.props.S4Double; import java.util.LinkedList; /** * A <code>DataProcessor</code> which wraps incoming <code>DoubleData</code>-objects into equally size blocks of defined * length. */ public class DataBlocker extends BaseDataProcessor { /** The property for the block size of generated data-blocks in milliseconds. */ @S4Double(defaultValue = 10) public static final String PROP_BLOCK_SIZE_MS = "blockSizeMs"; private double blockSizeMs; private int blockSizeSamples = Integer.MAX_VALUE; private int curFirstSamplePos; private int sampleRate = -1; private final LinkedList<DoubleData> inBuffer = new LinkedList<DoubleData>(); private int curInBufferSize; public DataBlocker() { } /** * @param blockSizeMs block size in milliseconds */ public DataBlocker(double blockSizeMs) { initLogger(); this.blockSizeMs = blockSizeMs; } @Override public void newProperties(PropertySheet propertySheet) throws PropertyException { super.newProperties(propertySheet); blockSizeMs = propertySheet.getDouble(PROP_BLOCK_SIZE_MS); } public double getBlockSizeMs() { return blockSizeMs; } @Override public Data getData() throws DataProcessingException { while (curInBufferSize < blockSizeSamples || curInBufferSize == 0) { Data data = getPredecessor().getData(); if (data instanceof DataStartSignal) { sampleRate = ((DataStartSignal) data).getSampleRate(); blockSizeSamples = (int) Math.round(sampleRate * blockSizeMs / 1000); curInBufferSize = 0; curFirstSamplePos = 0; inBuffer.clear(); } if (!(data instanceof DoubleData)) { return data; } DoubleData dd = (DoubleData) data; inBuffer.add(dd); curInBufferSize += dd.getValues().length; } // now we are ready to merge all data blocks into one double[] newSampleBlock = new double[blockSizeSamples]; int copiedSamples = 0; long firstSample = inBuffer.get(0).getFirstSampleNumber() + curFirstSamplePos; while (!inBuffer.isEmpty()) { DoubleData dd = inBuffer.remove(0); double[] values = dd.getValues(); int copyLength = Math.min(blockSizeSamples - copiedSamples, values.length - curFirstSamplePos); System.arraycopy(values, curFirstSamplePos, newSampleBlock, copiedSamples, copyLength); // does the current data-object contains more samples than necessary? -> keep the rest for the next block if (copyLength < (values.length - curFirstSamplePos)) { assert inBuffer.isEmpty(); curFirstSamplePos += copyLength; inBuffer.add(0, dd); break; } else { copiedSamples += copyLength; curFirstSamplePos = 0; } } curInBufferSize = inBuffer.isEmpty() ? 0 : inBuffer.get(0).getValues().length - curFirstSamplePos; // for (int i = 0; i < newSampleBlock.length; i++) { // newSampleBlock[i] *= 10; // } return new DoubleData(newSampleBlock, sampleRate, firstSample); } }