/* * Copyright (C) 2004 Keith Stribley <tech@thanlwinsoft.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ package org.thanlwinsoft.languagetest.sound; /** Class to cache data from an AudioFile to save it being reparsed each time * @author Keith Stribley */ public class CacheBuffer { int bufferLength = 0; int startIndex = 0; int cachedLength = 0; long startOffset = 0; byte [] buffer = null; /** Creates a new instance of CacheBuffer * @param size Cache size in bytes */ public CacheBuffer(int size) { this.bufferLength = size; buffer = new byte[bufferLength]; } /** Reinitialises cache resetting the start position of the cache * within the audio file. * @param startOffset start byte offset of cache within the audio file */ public void reinit(long startOffset) { this.startOffset = startOffset; this.cachedLength = 0; this.startIndex = 0; System.out.println("CacheBuffer init at " + startOffset); } /** Retrieves the position of the start of the cached data within * the audio file. * @return Byte offset of start of cache within audiofile */ public long getStartOffset() { return startOffset; } /** Retreives the length of data actually held in the cache * @return length of data in cache in bytes */ public long getCachedLength() { return cachedLength; } /** * Reads data cached from sound file if it is in cache * @param readBuffer buffer to write data into * @param readStartOffset start byte offset of data in sound file * @param length number of bytes to read * @return number of bytes read */ public int read(byte [] readBuffer, long readStartOffset, int length) { int read = 0; if (readStartOffset >= startOffset && readStartOffset < startOffset + cachedLength) { long actualLength = length; if (startOffset + cachedLength < readStartOffset + length) { actualLength = startOffset + cachedLength - readStartOffset; } for (; read < actualLength; read++) { readBuffer[read] = getData(readStartOffset + read); } } return read; } /** Writes data into the cache. It is assumed that the data to be * written in sequential to the last write. The first byte to be * written should be at the position {@link #getWriteOffset()} * @param writeBuffer Buffer containing data to write * @param length length of data to write * @return Number of bytes actually written */ public int write(byte [] writeBuffer, int length) { int i; int writeIndex = indexFromOffset(startOffset + cachedLength); for (i = 0; i < length; i++) { if (writeIndex >= bufferLength) writeIndex = 0; buffer[writeIndex] = writeBuffer[i]; writeIndex++; if (cachedLength == bufferLength) { startIndex++; startOffset++; if (startIndex >= bufferLength) startIndex = 0; } else { cachedLength++; } } return i; } /** Retrieves a byte of data from cache. * @param offset Offset in file * @return data at offset */ protected byte getData(long offset) { return buffer[indexFromOffset(offset)]; } /** Converts an offset in the audiofile into the index of the byte in the cache. * @param offset Byte offset in audiofile * @return index in cache byte array */ protected int indexFromOffset(long offset) { int bufferIndex = (int)(offset - startOffset + startIndex); if (bufferIndex >= bufferLength) bufferIndex -= bufferLength; return bufferIndex; } /** Retrieves the byte offset in the audiofile of the end of the data cache. This * is the index that should be used for the next write operation. * @return Byte offset for next write */ public long getWriteOffset() { return startOffset + cachedLength; } /** Test whether the specified offset in the audio file is held in the cache. * @param offset Offset in audiofile * @return true if offset is cached. */ public boolean isCached(long offset) { boolean cached = false; if (offset < startOffset) cached = false; else if (offset < startOffset + cachedLength) { cached = true; } return cached; } /** Frees the cache buffer. The cache cannot be used after clear has been * called. */ public void clear() { buffer = null; bufferLength = 0; startIndex = 0; cachedLength = 0; startOffset = 0; } }