diff options
Diffstat (limited to 'src/javaFlacEncoder/CRC8.java')
-rw-r--r-- | src/javaFlacEncoder/CRC8.java | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/javaFlacEncoder/CRC8.java b/src/javaFlacEncoder/CRC8.java new file mode 100644 index 0000000..573ecc1 --- /dev/null +++ b/src/javaFlacEncoder/CRC8.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2010 Preston Lacey http://javaflacencoder.sourceforge.net/ + * All Rights Reserved. + * + * 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 javaFlacEncoder; + + +/** + * Class to calculate a CRC8 checksum. + * @author Preston Lacey + */ +public class CRC8 { + + /** For Debugging: Higher level equals more debug statements */ + public static int DEBUG_LEV = 0; + + /** CRC Divisor: 0x107 */ + static final int divisorCRC8 = 0x107 << 23; + + /** working checksum stored between calls to update(..) */ + int workingCRC8; + + /** number of valid bits stored in workingCRC8(valid bits are packed towards + * high-order side of int */ + int workingCRC8Count; + + private static final byte[] fake = {0}; + + /** + * Constructor. Creates a CRC8 object that is ready to be used. Next step + * would be to call updateCRC8 with appropriate data. + */ + public CRC8() { + reset(); + } + + /** + * Add data to the crc. Immediately creates checksum on given data. Can be + * called multiple times as it won't finalize the checksum until the method + * checksum() is called. + * + * @param inSet Array holding data to checksum. + * @param start Index of array holding first element + * @param end Index to stop at. Last index used will be end-1. + * @return intermediate result of checksum to this point. This is *not* a + * finalized result, as non-summed data must remain in workingCRC8 until + * checksum() is called. + */ + public byte updateCRC8(byte[] inSet, int start, int end) { + //we need at least one byte to work on. And cache between calls. + // Follow md5 style, updating many times, finalizing once. + + //Copy in saved value(starts out zero). + //Shift value, and divisor to top end of int. When we drop below 17 in + // working int, "OR" it with another byte, or save and return. + // I won't do this, just "assume" it's already there and use instance + // variables. + //While bits available is more than 8: + //while top bit is zero, and >8 bits in buffer. Shift Left. + //if >8 bits remain in working int, divide + //else if 8 bits remain, "OR" in another byte. + //store working int, return; + if(DEBUG_LEV > 10 ) + System.err.println("CRC8::updateCRC8: Begin"); + if(DEBUG_LEV > 20) { + System.err.println("Start:End : "+start+":"+end); + } + int current = start; + int topBit = 0; + int topMask = 1<<31; + while(current < end) {//this should leave 8 bits in workingCRC8. + if(DEBUG_LEV > 40 ) { + System.err.println("CRC8::updateCRC8: looping bytes. current: "+current); + System.err.println("workingCRC8Count : " +workingCRC8Count); + } + topBit = workingCRC8 & topMask; + while(workingCRC8Count > 8 && topBit == 0) { + if(DEBUG_LEV > 40) + System.err.println("CRC8::updateCRC8: shifting left"); + workingCRC8Count--; + workingCRC8 = workingCRC8 << 1; + topBit = workingCRC8 & topMask; + } + if( workingCRC8Count > 8 ) { + workingCRC8 = workingCRC8 ^ divisorCRC8; + } + else {//workingCRC8Count < 9 + if(DEBUG_LEV > 30) { + System.err.println("CRC8: Adding byte with workingCRC of: "+ + (workingCRC8 >>> 24)); + } + int temp = inSet[current++]; + temp = temp << 24; + temp = temp >>> 8; + workingCRC8 = workingCRC8 | temp; + workingCRC8Count+=8; + } + } + return (byte)(workingCRC8 >>> 24); + } + + /** + * Finalize the checksum, and return the value. After this is called, you + * must call reset() before attempting a new checksum. + * @return finalized checksum. + */ + public byte checksum() { + if(DEBUG_LEV > 10 ) + System.err.println("CRC8::checksum : Begin"); + //add 8 to the count, + //call update with a byte constructed to add no more. + //byte[] fake = {0}; + workingCRC8Count += 8; + byte val = updateCRC8(fake, 0, 1); + if(DEBUG_LEV > 10 ) + System.err.println("CRC8::checksum : End"); + return val; + } + + /** + * Resets all stored data, preparing object for a new checksum. + */ + public void reset() { + workingCRC8 = 0; + workingCRC8Count = 8; + } +} |