Back to project page rfcx-guardian-android.
The source code is released under:
Apache License
If you think the Android project rfcx-guardian-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (C) 2010 Preston Lacey http://javaflacencoder.sourceforge.net/ * All Rights Reserved.//w ww . j a v a 2 s. com * * 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 net.sourceforge.javaFlacEncoder; /** * The RiceEncoder class is used to create FLAC-compliant rice-encoded * residuals. * * @author Preston Lacey */ public class RiceEncoder { /** For debugging: Higher values equals greater output, generally in * increments of 10 */ public static int DEBUG_LEV = 0; private static final int POSITIVE = 0; private static final int NEGATIVE = 1; private static final int STOP_BIT = 0xFFFFFFFF; private static final int UNARY_BIT = 0; private int[] _dataToEncode = null; private int[] _bitsToEncode = null; /** * Constructor. A RiceEncoder object is used(as opposed to potentially * faster static methods), for memory considerations; some temporary, * dynamically created arrays are kept between calls to the encode methods * to prevent frequently allocating and freeing similarly sized arrays. */ public RiceEncoder() { } /** * Create the residual headers for a FLAC stream. * * @param useFiveBitParam Set TRUE if using a five-bit parameter size, FALSE * for a four-bit parameter * @param order Specify order of partitions to be used(actual number of * partitions will be 2^order. * @param ele EncodedElement to write header to. * @return total written size of header. */ public static int beginResidual(boolean useFiveBitParam, byte order, EncodedElement ele) { ele = ele.getEnd(); int paramSize = (useFiveBitParam) ? 1:0; ele.addInt(paramSize, 2); ele.addInt(order, 4); return 6; } public static int encodeRicePartitionEscaped(int[] values, int inputOffset, int inputStep, int inputCount, EncodedElement destEle, int bitParam, boolean fiveBitParam) { if(DEBUG_LEV > 0) System.err.println("RiceEncoder::encode : Begin"); /* Currently, we're passing in an EncodedElement with a set byte[], and filling that array. We should therefore ensure that we're not writing too much to it. We *can* add another element to the given one if need.*/ //write headers(i.e, write the parameter) int bitsWritten = 0; if(fiveBitParam) { destEle.addInt(255, 5); destEle.addInt(16,5); bitsWritten += 10; } else { destEle.addInt(255, 4); destEle.addInt(16,5); bitsWritten += 9; } for(int i = 0; i < inputCount; i++) { destEle.addInt(values[i*inputStep+inputOffset], 16); bitsWritten += 16; } if(DEBUG_LEV > 0) System.err.println("RiceEncoder::encode : End"); return bitsWritten; } /** * Rice-encode a set of values, adding necessary headers for FLAC format. This * encodes a single rice-partition. In general, beginResidual(...) should be * used before this method. * * @param values array of integer values to save * @param inputOffset start index in input array * @param inputStep number of values to skip between target values(for * interleaved data. * @param inputCount number of total values to encode * @param bitParam rice-parameter to use. This value should be based upon * the distribution of the input data(roughly speeking, each value * will require at least bitParam+1 bits to save, so this value * should reflect the average magnitude of input values. * @param destEle EncodedElement to save result to. * @param fiveBitParam Set true if this header should use a five-bit * rice-parameter, false for a four bit parameter. * @return total encoded size(including headers) */ public int encodeRicePartition(int[] values, int inputOffset, int inputStep, int inputCount, EncodedElement destEle, final int bitParam, boolean fiveBitParam) { //Pack int version of encode partition if(DEBUG_LEV > 0) { System.err.println("RiceEncoder::encode : Begin"); System.err.println("-- bitParam: " + bitParam); } //write headers(i.e, write the parameter) int startBits = destEle.getTotalBits(); if(fiveBitParam) { destEle.addInt(bitParam, 5); } else { destEle.addInt(bitParam, 4); } //encode each input value; if(_dataToEncode == null || _bitsToEncode == null) { _dataToEncode = new int[values.length*4]; _bitsToEncode = new int[values.length*4]; } int[] dataToEncode = _dataToEncode; int[] bitsToEncode = _bitsToEncode; int nextToEncode = 0; int maxToEncode = dataToEncode.length; int inputIndex = inputOffset-inputStep; final int stopbit = (bitParam >0) ? STOP_BIT << bitParam:STOP_BIT; final int maskParam = (bitParam == 0) ? 0:0xFFFFFFFF>>>(32-bitParam); for(int i = 0; i < inputCount; i++) { inputIndex +=inputStep; int value = values[inputIndex]; value = (value < 0) ? -2*value-1:2*value; int upperBits = value >> bitParam; //make sure we won't write to much. Handle if we will. int dataToEncodeSpaceNeeded = (2+upperBits/32); if(upperBits%32 != 0) dataToEncodeSpaceNeeded++; if(dataToEncodeSpaceNeeded+nextToEncode >= maxToEncode) { //write everything we have: destEle.packIntByBits(dataToEncode, bitsToEncode, 0, nextToEncode); nextToEncode = 0; } //write unary upper bits: int count = 0; while(upperBits > 0) { int tempVal = (upperBits > 32) ? 32:upperBits;//can only write 32 bits at a time. dataToEncode[nextToEncode] = UNARY_BIT; bitsToEncode[nextToEncode++] = tempVal; upperBits -= tempVal; count++; } dataToEncode[nextToEncode] = (value&maskParam) | stopbit ; bitsToEncode[nextToEncode++] = bitParam+1; } //System.err.println("end loop"); //write remaining data to encode if(nextToEncode > 0) { destEle.packIntByBits(dataToEncode, bitsToEncode, 0, nextToEncode); nextToEncode = 0; } int bitsWritten = destEle.getTotalBits() - startBits; //System.err.println("RiceENcoder encode end:"); return bitsWritten; } /** * Calculate how large a given set of values will be once it has been * rice-encoded. While this method duplicates much of the process of * rice-encoding, it is faster than an actual encode since the data is not * actually written to the flac bitstream format(a rather costly write). * * @param values array of integer values to save * @param inputOffset start index in input array * @param inputStep number of values to skip between target values(for * interleaved data. * @param inputCount number of total values to encode * @param bitParam rice-parameter to use. This value should be based upon * the distribution of the input data(roughly speeking, each value * will require at least bitParam+1 bits to save, so this value * should reflect the average magnitude of input values. * @return total encoded-size with given data and rice-parameter. */ public static int calculateEncodeSize(int[] values, int inputOffset, int inputStep, int inputCount, int bitParam) { //Pack int version of encode partition if(DEBUG_LEV > 0) { System.err.println("RiceEncoder::calculateEncodeSize : Begin"); System.err.println("-- bitParam: " + bitParam); } int totalEncodeLength = inputCount*(bitParam+1); int index = inputOffset-inputStep; for(int i = 0; i < inputCount; i++) { index += inputStep; int value = values[index]; value = (value < 0) ? -2*value-1:2*value; int upperBits = value >> bitParam; totalEncodeLength += upperBits; } if(bitParam > 14) totalEncodeLength += 5+6; else totalEncodeLength += 4+6; return totalEncodeLength; } }