diff --git a/BurnOutSharp.Compression/Quantum/Decompressor.cs b/BurnOutSharp.Compression/Quantum/Decompressor.cs index 312b48b6..5fbec73f 100644 --- a/BurnOutSharp.Compression/Quantum/Decompressor.cs +++ b/BurnOutSharp.Compression/Quantum/Decompressor.cs @@ -402,8 +402,7 @@ namespace BurnOutSharp.Compression.Quantum /// private static ushort GET_SYMBOL(Model model, ref ushort H, ref ushort L, ref ushort C, byte[] inbuf, ref int inpos, ref int bitsleft, ref uint bitbuf) { - uint range = (uint)(((H - L) & 0xFFFF) + 1); - ushort symf = (ushort)(((((C - L + 1) * model.Symbols[0].CumulativeFrequency) - 1) / range) & 0xFFFF); + ushort symf = GetFrequency(model.Symbols[0].CumulativeFrequency, H, L, C); int i; for (i = 1; i < model.Entries; i++) @@ -413,39 +412,63 @@ namespace BurnOutSharp.Compression.Quantum } ushort symbol = model.Symbols[i - 1].Symbol; - - range = (uint)(H - L + 1); - H = (ushort)(L + ((model.Symbols[i - 1].CumulativeFrequency * range) / model.Symbols[0].CumulativeFrequency) - 1); - L = (ushort)(L + ((model.Symbols[i].CumulativeFrequency * range) / model.Symbols[0].CumulativeFrequency)); - - while (true) - { - if ((L & 0x8000) != (H & 0x8000)) - { - // Underflow case - if ((L & 0x4000) != 0 && (H & 0x4000) == 0) - { - C ^= 0x4000; - L &= 0x3FFF; - H |= 0x4000; - } - else - { - break; - } - } - - L <<= 1; - H = (ushort)((H << 1) | 1); - Q_FILL_BUFFER(inbuf, ref inpos, ref bitsleft, ref bitbuf); - C = (ushort)((C << 1) | Q_PEEK_BITS(1, bitbuf)); - Q_REMOVE_BITS(1, ref bitsleft, ref bitbuf); - } + GetCode(model.Symbols[i - 1].CumulativeFrequency, + model.Symbols[i].CumulativeFrequency, + model.Symbols[0].CumulativeFrequency, + ref H, ref L, ref C, + inbuf, ref inpos, ref bitsleft, ref bitbuf); UpdateModel(model, i); return symbol; } + /// + /// Get the frequency for a given range and total frequency + /// + private static ushort GetFrequency(ushort totalFrequency, ushort H, ushort L, ushort C) + { + uint range = (uint)(((H - L) & 0xFFFF) + 1); + uint freq = (uint)(((C - L + 1) * totalFrequency - 1) / range); + return (ushort)(freq & 0xFFFF); + } + + /// + /// The decoder renormalization loop + /// + private static void GetCode(int previousFrequency, + int cumulativeFrequency, + int totalFrequency, + ref ushort H, + ref ushort L, + ref ushort C, + byte[] inbuf, + ref int inpos, + ref int bitsleft, + ref uint bitbuf) + { + uint range = (uint)((H - L) + 1); + H = (ushort)(L + ((previousFrequency * range) / totalFrequency) - 1); + L = (ushort)(L + (cumulativeFrequency * range) / totalFrequency); + + while (true) + { + if ((L & 0x8000) != (H & 0x8000)) + { + if ((L & 0x4000) == 0 || (H & 0x4000) != 0) + break; + + // Underflow case + C ^= 0x4000; + L &= 0x3FFF; + H |= 0x4000; + } + + L <<= 1; + H = (ushort)((H << 1) | 1); + C = (ushort)((C << 1) | Q_READ_BITS(1, inbuf, ref inpos, ref bitsleft, ref bitbuf)); + } + } + #endregion } } \ No newline at end of file