All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.javaflacencoder.EncodedElement_32 Maven / Gradle / Ivy

Go to download

javaFlacEncoder is a pure java implementation of a FLAC encoder library. It is designed to allow third-party java applications to enable flac encoding without resorting to use of JNI or scripted file conversions. Additionally, a basic console wav->flac encoding tool is included as part of this package. Original project can be found here: http://javaflacencoder.sourceforge.net/

The newest version!
/*
 * 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 net.sourceforge.javaflacencoder;

/**
 * EncodedElement which uses an integer array as a backing, rather than the
 * byte array.
 *
 * @author Preston Lacey
 */
@Deprecated
public class EncodedElement_32 extends EncodedElement {
   int[] data_32 = null;
   boolean byteArrayValid = false;
   public EncodedElement_32() {
      offset = 0;
      usableBits = 0;
      data = null;
      data_32 = new int[100];
   }

   public EncodedElement_32(int size, int off) {
      data = null;
      usableBits = off;
      offset = off;
      data_32 = new int[size];
   }

   @Override
   public void clear(int size, int off) {
      next = null;
      previous = null;
      data = null;
      data_32 = new int[size];
      offset = off;
      usableBits = off;
      byteArrayValid = false;
   }


    /**
     * This method adds a given number of bits of an int to a byte array.
     * @param value int to store bits from
     * @param count number of low-order bits to store
     * @param startPos start bit location in array to begin writing
     * @param dest array to store bits in. dest MUST have enough space to store
     * the given data, or this function will fail.
     */
    public static void addInt(int value, int count, int startPos, int[] dest) {
        assert(count <= 32);
        assert(count > 0);
        assert(startPos >= 0);
        //System.err.println("addInt("+value+", "+count + ", "+startPos+")");
        /*
         * Because we're using both 32 bit input and 32 bit output, we only have
         * two cases to handle:
         * 1) All bits fit in one index, appropriately shifted up first.
         *      Mask upper bits we'll merge with(Ones in upper).
         *      Mask lower bits we'll merge with(Ones in lower).
         *      destMask = OR Upper and lower masks together.
         *      currentIndex = currentIndex & destMask
         *      destMask = ~destMask;
         *      upshift by 32-count-currentOffset;
         *      inputValue = inputValue & destMask;
         *      currentIndex = currentIndex | inputValue
         * 2) Some bits merge in top of one index, remaining bits merge in
         * bottom of second index
         *      A) CurrentIndex
         *          Create inputValueHigh, with high order bits which will enter
         *              currentIndex.
         *          Handle this as we handled case one(pretend it's a new value)
         *      B) CurrentIndex++
         *          We fill from upper edge. No upper mask needed.
         *          upshift value by 32-count;
         *          Mask lower bits we'll merge with(Ones in lower)
         *          currentIndex = currentIndex & destMask
         *          currentIndex = currentIndex | destMask
         */
        int currentIndex = startPos/32;
        int currentOffset = startPos%32;
        
        int totalSize = count+currentOffset;

        if(totalSize > 32) {
            //System.err.println("totalSize > 32");
            int secondIndex = currentIndex + 1;
            int secondSize = totalSize - 32;
            int secondValue = value << (32-secondSize);
            int lowerMask = -1 >>> secondSize;
            int temp = dest[secondIndex] & lowerMask;
            dest[secondIndex] = temp | secondValue;
            totalSize = 32;
            value = value >>> secondSize;
        }

        if(totalSize <= 32) {//Case 1
            int upperMask = -2 << (31-currentOffset);
            //int lowerMask = Integer.MAX_VALUE >>> (totalSize-1);
            int lowerMask = 0x7FFFFFFF >>> (totalSize-1);
            int destMask = upperMask | lowerMask;
            int temp = dest[currentIndex] & destMask;
            destMask = ~destMask;
            value = value << (32-totalSize);
            value = value & destMask;
            dest[currentIndex] = temp | value;
        }
    }

    public int[] getData32() { return data_32; }
    private static byte[] convertIntArrayToByteArray(int[] input) {
        byte[] result = new byte[input.length*4];
        for(int i = 0; i < input.length; i++) {
            //byte 3 = byte 0
            //byte 2 = byte 1
            //byte 1 = byte 2
            //byte 0 = byte 3
            int byteBase = i*4;
            int value = input[i];
            result[byteBase+0] = (byte)(value >> 24);
            result[byteBase+1] = (byte)(value >> 16);
            result[byteBase+2] = (byte)(value >> 8);
            result[byteBase+3] = (byte)(value);
        }
        return result;
    }



    /**
     * Pack a number of bits from each int of an array(within given limits)to
     * the end of this list.
     *
     * @param inputA Array containing input values.
     * @param inputBits Array containing number of bits to use for each index
     * packed. This array should be equal in size to the inputA array.
     * @param inputOffset Index of first usable index.
     * @param countA Number of indices to pack.
     * @param startPosIn First usable bit-level index in destination array(byte
     * index = startPosIn/8, bit within that byte = startPosIn%8)
     * @param dest Destination array to store input values in. This array *must*
     * be large enough to store all values or this method will fail in an
     * undefined manner.
     */
    public static void packIntByBits(int[] inputA, int[] inputBits, int inputOffset,
            int countA, int startPosIn, int[] dest) {
        if(DEBUG_LEV > 30)
            System.err.println("EncodedElement::packIntByBits : Begin");
        //int offsetCounter = 0;        
        int startPos = startPosIn;//the position to write to in output array
        int inputStop = countA+inputOffset;
        for(int valI = inputOffset; valI < inputStop; valI++) {
            //inputIter = valI+inputOffset;
            //inputIter += valI;
            //int input = inputA[valI];//value to encode
            int value = inputA[valI];
            int count = inputBits[valI];//bits of value to encode
            //EncodedElement_32.addInt(input, count, startPos, dest);
            int currentIndex = startPos/32;
            int currentOffset = startPos%32;

            int totalSize = count+currentOffset;

            if(totalSize > 32) {
                //System.err.println("totalSize > 32");
                int secondIndex = currentIndex + 1;
                int secondSize = totalSize - 32;
                int secondValue = value << (32-secondSize);
                int lowerMask = -1 >>> secondSize;
                int temp = dest[secondIndex] & lowerMask;
                dest[secondIndex] = temp | secondValue;
                totalSize = 32;
                value = value >>> secondSize;
            }

            //if(totalSize <= 32) {//Case 1
            int upperMask = -2 << (31-currentOffset);
            int lowerMask = 0x7FFFFFFF >>> (totalSize-1);
            int destMask = upperMask | lowerMask;
            int temp = dest[currentIndex] & destMask;
            destMask = ~destMask;
            value = value << (32-totalSize);
            value = value & destMask;
            dest[currentIndex] = temp | value;
            startPos += count;//startPos must not be referenced again below here!
        }
        if(DEBUG_LEV > 30)
            System.err.println("EncodedElement::addInt : End");
    }

    /**
     * Pack a number of bits from each int of an array(within given limits)to
     * the end of this list.
     *
     * @param inputA Array containing input values.
     * @param inputBits Array containing number of bits to use for each index
     * packed. This array should be equal in size to the inputA array.
     * @param inputOffset Index of first usable index.
     * @param countA Number of indices to pack.
     * @return EncodedElement containing end of packed data. Data may flow
     * between multiple EncodedElement's, if an existing element was not large
     * enough for all values.
     */
    @Override
    public EncodedElement packIntByBits(int[] inputA, int[] inputBits, int inputOffset,
            int countA) {
        byteArrayValid = false;
        //go to end if we're not there.
        if(next != null) {
            EncodedElement end = EncodedElement_32.getEnd_S(next);
            return end.packIntByBits(inputA, inputBits, inputOffset, countA);
        }

        //calculate how many we can pack into current.
        int writeBitsRemaining = data_32.length*32 - usableBits;
        int willWrite = 0;
        int writeCount = 0;
        //System.err.println("writeBitsRemaining: " + writeBitsRemaining);
        for(int i = 0; i < countA; i++) {
            writeBitsRemaining -= inputBits[inputOffset+i];
            if(writeBitsRemaining >= 0) {
                writeCount++;
                willWrite += inputBits[inputOffset+i];
            }
            else
                break;
        }
        //pack them and update usable bits.
        if(writeCount > 0) {
            EncodedElement_32.packIntByBits(inputA, inputBits, inputOffset,
                    writeCount, usableBits, data_32);
            usableBits += willWrite;
        }
        //if more remain, create child object and add there
        countA -= writeCount;
        if(countA > 0) {
            inputOffset += writeCount;
            int tOff = usableBits %32;
            int size = data_32.length/2+1;
            //guarantee that our new element can store our given value
            int remainingToWrite = 0;
            for(int i = 0; i < countA; i++) {
                remainingToWrite += inputBits[inputOffset+i];
            }
            remainingToWrite = remainingToWrite / 8 + 1;
            if(size < remainingToWrite) size = remainingToWrite+10;
            //System.err.println("remaining: "+remainingToWrite);
            //System.err.println("creating size/offset : "+size+":"+tOff);
            next = new EncodedElement_32(size, tOff);
            //add int to child
            return next.packIntByBits(inputA, inputBits, inputOffset, countA);
        }
        else {
            //System.err.println("returning....done");
            //return if this is last object we wrote to.
            return this;
        }
    }

    @Override
    public byte[] getData() {
     //   return convertIntArrayToByteArray(data_32);
        if(byteArrayValid)
            return data;
        byteArrayValid = true;
        if(data == null)
            data = new byte[data_32.length*4];
        byte[] result = data;
        for(int i = 0; i < data_32.length; i++) {
            //byte 3 = byte 0
            //byte 2 = byte 1
            //byte 1 = byte 2
            //byte 0 = byte 3
            int byteBase = i*4;
            int value = data_32[i];
            result[byteBase+0] = (byte)(value >> 24);
            result[byteBase+1] = (byte)(value >> 16);
            result[byteBase+2] = (byte)(value >> 8);
            result[byteBase+3] = (byte)(value);
        }
        data = result;
        return result;
    }

    public EncodedElement convertToEncodedElement() {
        EncodedElement ele = new EncodedElement();
        byte[] result = new byte[data_32.length*4];
        int byteBase = -4;
        int valueIndex = 0;
        /*for(int i = 0; i < data_32.length/4; i++) {
            int value0 = data_32[valueIndex++];
            int value1 = data_32[valueIndex++];
            int value2 = data_32[valueIndex++];
            int value3 = data_32[valueIndex++];
            
            byteBase += 7;
            result[byteBase--] = (byte)(value0);
            value0 = value0 >> 8;
            result[byteBase--] = (byte)(value0);
            value0 = value0 >> 8;
            result[byteBase--] = (byte)(value0);
            value0 = value0 >> 8;
            result[byteBase] = (byte)(value0);            
            
            byteBase += 7;
            result[byteBase--] = (byte)(value1);
            value1 = value1 >> 8;
            result[byteBase--] = (byte)(value1);
            value1 = value1 >> 8;
            result[byteBase--] = (byte)(value1);
            value1 = value1 >> 8;
            result[byteBase] = (byte)(value1);
            
            byteBase += 7;
            result[byteBase--] = (byte)(value2);
            value2 = value2 >> 8;
            result[byteBase--] = (byte)(value2);
            value2 = value2 >> 8;
            result[byteBase--] = (byte)(value2);
            value2 = value2 >> 8;
            result[byteBase] = (byte)(value2);
            
            byteBase += 7;
            result[byteBase--] = (byte)(value3);
            value3 = value3 >> 8;
            result[byteBase--] = (byte)(value3);
            value3 = value3 >> 8;
            result[byteBase--] = (byte)(value3);
            value3 = value3 >> 8;
            result[byteBase] = (byte)(value3);
        }*/

        for(int i = 3 ; i < data_32.length*4; i+=7) {
            //byte 3 = byte 0
            //byte 2 = byte 1
            //byte 1 = byte 2
            //byte 0 = byte 3
            //int byteBase = i*4+3;
            //byteBase += 7;
            int value = data_32[valueIndex++];
            result[i--] = (byte)(value);
            value = value >> 8;
            result[i--] = (byte)(value);
            value = value >> 8;
            result[i--] = (byte)(value);
            value = value >> 8;
            result[i] = (byte)(value);

            /*result[byteBase++] = (byte)(value >> 24);
            result[byteBase++] = (byte)(value >> 16);
            result[byteBase++] = (byte)(value >> 8);
            result[byteBase] = (byte)(value);*/
        }

        //ele.data = convertIntArrayToByteArray(data_32);
        ele.data = result;
        ele.offset = offset;
        ele.usableBits = usableBits;
        return ele;
    }
    /**
     * Add a number of bits from an int to the end of this list's data. Will
     * add a new element if necessary. The bits stored are taken from the lower-
     * order of input.
     *
     * @param input Int containing bits to append to end.
     * @param bitCount Number of bits to append.
     * @return EncodedElement which actually contains the appended value.
     */
    @Override
    public EncodedElement addInt(int input, int bitCount) {
        byteArrayValid = false;
        if(next != null) {
            EncodedElement end = EncodedElement_32.getEnd_S(next);
            return end.addInt(input, bitCount);
        }
        else if(data_32.length*32 < usableBits+bitCount) {
            //create child and attach to next.
            //Set child's offset appropriately(i.e, manually set usable bits)
            int tOff = usableBits %32;
            //int size = data.length/2+1;
            int size = 1000;
            //guarantee that our new element can store our given value
            //if(size <= bitCount+tOff) size = (size+tOff+bitCount)*10;

            next = new EncodedElement_32(size, tOff);
            System.err.println("creating next node of size:bitCount "+size+
                    ":"+bitCount+":"+usableBits+":"+data_32.length);
            System.err.println("value: "+input);
                    //+this.toString()+"::"+next.toString());
            //add int to child
            return next.addInt(input, bitCount);
        }
        else {
            //At this point, we have the space, and we are the end of the chain.
            int startPos = this.usableBits;
            int[] dest = this.data_32;
            EncodedElement_32.addInt(input, bitCount, startPos, dest);
            usableBits +=  bitCount;
            return this;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy