Exemple #1
0
        /// <summary>
        /// Function to find corresponding HuffmanStruct with value.
        /// </summary>
        /// <param name="value">value to search</param>
        /// <returns>corresponding HuffmanStruct</returns>
        private SCPHuffmanStruct InterpettingData(short value)
        {
            // Check if selected Table exists
            if ((_Tables != null) &&
                (_Tables[_Selected] != null))
            {
                // Search in structs of table.
                for (int loper = 0; loper < _Tables[_Selected].Length; loper++)
                {
                    SCPHuffmanStruct h = _Tables[_Selected][loper];
                    // -1, because it can be positive and negative
                    int extra = (h.entire - h.prefix - 1);

                    // Check if value is equal to struct.
                    if ((h.value == value) &&
                        (h.tablemode != 0))
                    {
                        return(h);
                    }
                    // Check if value fits in special case.
                    else if ((extra > 0) &&
                             ((value - h.value) < (0x1 << extra)) &&
                             ((value - h.value) >= -(0x1 << extra)) &&
                             (h.tablemode != 0))
                    {
                        return(h);
                    }
                }
            }
            return(null);
        }
Exemple #2
0
        protected override int _Read(byte[] buffer, int offset)
        {
            int end = offset - Size + Length;

            if ((offset + Marshal.SizeOf(_NrTables)) > end)
            {
                return(0x1);
            }
            _NrTables = (ushort)BytesTool.readBytes(buffer, offset, Marshal.SizeOf(_NrTables), true);
            offset   += Marshal.SizeOf(_NrTables);
            if (_NrTables < _DefaultTable)
            {
                _Tables = new SCPHuffmanStruct[_NrTables][];
                for (int table = 0; table < _NrTables; table++)
                {
                    if ((offset + Marshal.SizeOf(_NrTables)) > end)
                    {
                        _Empty();
                        return(0x2);
                    }
                    _Tables[table] = new SCPHuffmanStruct[BytesTool.readBytes(buffer, offset, Marshal.SizeOf(_NrTables), true)];
                    offset        += Marshal.SizeOf(_NrTables);
                    if ((offset + (_Tables[table].Length * SCPHuffmanStruct.Size)) > end)
                    {
                        _Empty();
                        return(0x4);
                    }
                    for (int loper = 0; loper < _Tables[table].Length; loper++)
                    {
                        _Tables[table][loper] = new SCPHuffmanStruct();
                        int err = _Tables[table][loper].Read(buffer, offset);
                        if (err != 0)
                        {
                            return(err << 3 + table);
                        }
                        offset += SCPHuffmanStruct.Size;
                    }
                }
            }
            return(0x0);
        }
Exemple #3
0
        /// <summary>
        /// Function to encode signal using the huffman table.
        /// </summary>
        /// <param name="data">signal to read from</param>
        /// <param name="time">number of samples to use</param>
        /// <param name="quanta">sample distance in signal</param>
        /// <param name="usedTable">table to use for encoding</param>
        /// <param name="difference">difference to use durring decoding</param>
        /// <returns>byte array containing encoded data</returns>
        private byte[] HuffmanTableEncode(short[] data, int time, short usedTable, byte difference)
        {
            byte[] ret = null;

            // Check if input makes sense
            if ((data != null) &&
                (time <= data.Length))
            {
                // Initialize some handy variables
                int currentBit = 0;

                // Make buffer for worst case.
                byte[] buffer = null;

                if ((usedTable >= 0) &&
                    (usedTable < _Tables.Length) &&
                    (usedTable != _Selected))
                {
                    uint code = 0;
                    int  len  = 0;

                    // get TableSwap position in HuffmanTable.
                    int p = getTableSwap(usedTable);

                    // Check if table swap is possible in this table.
                    if (p >= 0)
                    {
                        // Store needed data from swap HuffmanStruct.
                        code = _Tables[_Selected][p].code;
                        len  = _Tables[_Selected][p].entire;

                        // set currently selected table.
                        _Selected = usedTable;
                    }

                    // allocate buffer for worstcase.
                    buffer = new byte[((len + (time * getWorstCase())) >> 3) + 1];

                    // add table swap.
                    for (len--; len >= 0; len--)
                    {
                        buffer[currentBit >> 3] <<= 1;
                        buffer[currentBit >> 3]  |= (byte)((code >> len) & 0x1);
                        currentBit++;
                    }
                }
                else
                {
                    // No tables swap, so only space needed for worst case.
                    buffer = new byte[((time * getWorstCase()) >> 3) + 1];
                }

                // For each sample do encode.
                for (int currentTime = 0; currentTime < time; currentTime++)
                {
                    short code = 0;

                    // Encode Differences.
                    switch (difference)
                    {
                    case 0:
                        code = data[currentTime];
                        break;

                    case 1:
                        code = (short)((currentTime < 1) ? data[currentTime] : data[currentTime] - data[currentTime - 1]);
                        break;

                    case 2:
                        code = (short)((currentTime < 2) ? data[currentTime] : data[currentTime] - (data[currentTime - 1] << 1) + data[currentTime - 2]);
                        break;

                    default:
                        // Undefined difference used exit empty.
                        return(null);
                    }

                    // Call Interpetting data to get an hit.
                    SCPHuffmanStruct h = InterpettingData(code);
                    if (h == null)
                    {
                        // not hit table or data must be wrong.
                        return(null);
                    }

                    // Push in the code.
                    for (int loper = (h.prefix - 1); loper >= 0; loper--)
                    {
                        buffer[currentBit >> 3] <<= 1;
                        buffer[currentBit >> 3]  |= (byte)((h.code >> loper) & 0x1);
                        currentBit++;
                    }

                    // Push in the extra code, for special case.
                    uint now = (uint)(code - h.value);
                    for (int loper = (h.entire - h.prefix - 1); loper >= 0; loper--)
                    {
                        buffer[currentBit >> 3] <<= 1;
                        buffer[currentBit >> 3]  |= (byte)((code >> loper) & 0x1);
                        currentBit++;
                    }
                }

                // Shift end to right position.
                if ((currentBit & 0x7) != 0x0)
                {
                    buffer[(currentBit >> 3)] <<= (0x8 - (currentBit & 0x7));
                    currentBit += (0x8 - (currentBit & 0x7));
                }
                else
                {
                    // seems to solve a small encoding bug.
                    currentBit += 8;
                }

                // Allocate a fitting buffer
                ret = new byte[(currentBit >> 3)];

                // Copy worst case buffer in fitting buffer.
                for (int loper = 0; loper < ret.Length; loper++)
                {
                    ret[loper] = buffer[loper];
                }
            }
            return(ret);
        }
Exemple #4
0
        /// <summary>
        /// Function to do huffman decode of encoded data.
        /// </summary>
        /// <param name="buffer">buffer to read in</param>
        /// <param name="offset">position to start reading</param>
        /// <param name="nrbytes">nrbytes of encoded bytes in buffer</param>
        /// <param name="length">length of signal in samples</param>
        /// <param name="difference">difference to use durring decoding</param>
        /// <returns>short array containing decoded data</returns>
        private short[] HuffmanTableDecode(byte[] buffer, int offset, int nrbytes, int length, byte difference)
        {
            // This safes us some calculations.
            nrbytes += offset;

            // Check if input data makes sense.
            if ((buffer != null) &&
                (nrbytes <= buffer.Length))
            {
                // Setting up the variables for decode.
                short[] leadData    = new short[length];
                int     currentTime = 0;
                int     currentBit  = (offset << 3);

                while (((currentBit >> 3) < nrbytes) &&
                       ((currentTime) < length))
                {
                    // Search for a hit.
                    SCPHuffmanStruct h = InterpettingData(buffer, currentBit);
                    // Exit if there was no hit.
                    if (h == null)
                    {
                        return(null);
                    }

                    // Check if hit fits.
                    if (((currentBit + h.entire) >> 3) >= nrbytes)
                    {
                        break;
                    }

                    // If table mode is 0 do switch.
                    if (h.tablemode == 0)
                    {
                        _Selected = h.value - 1;
                        continue;
                    }

                    short code = 0;
                    // read extra data behind hit if available.
                    for (int count = 0, start = (currentBit + h.prefix); count < (h.entire - h.prefix); count++)
                    {
                        code <<= 1;
                        code  += (short)((buffer[(start + count) >> 3] >> (0x7 - ((start + count) & 0x7))) & 0x1);
                        if ((count == 0) &&
                            (code != 0))
                        {
                            code = -1;
                        }
                    }
                    // add up a the value of the hit.
                    code += h.value;

                    // Decode Differences.
                    switch (difference)
                    {
                    case 0:
                        leadData[currentTime] = code;
                        break;

                    case 1:
                        leadData[currentTime] = ((currentTime == 0) ? code : (short)(code + leadData[currentTime - 1]));
                        break;

                    case 2:
                        leadData[currentTime] = ((currentTime < 2) ? code : (short)(code + (leadData[currentTime - 1] << 1) - leadData[currentTime - 2]));
                        break;

                    default:
                        // Undefined difference used exit empty.
                        return(null);
                    }

                    // Increment current bit
                    currentBit += h.entire;

                    // Increment time by one.
                    currentTime++;
                }
                return(leadData);
            }
            return(null);
        }