@gmod/cram
Version:
read CRAM files with pure Javascript
140 lines (122 loc) • 3.26 kB
text/typescript
// @ts-nocheck
import { CramMalformedError } from '../errors.ts'
import { RANS_BYTE_L } from './constants.ts'
class FC {
// int F, C;
constructor() {
this.F = undefined
this.C = undefined
}
}
class AriDecoder {
// final FC[] fc = new FC[256];
// byte[] R;
constructor() {
this.fc = new Array(256)
for (let i = 0; i < this.fc.length; i += 1) {
this.fc[i] = new FC()
}
this.R = null
}
}
class DecodingSymbol {
// int start; // Start of range.
// int freq; // Symbol frequency.
constructor() {
this.start = undefined
this.freq = undefined
}
}
// Initialize a decoder symbol to start "start" and frequency "freq"
function symbolInit(sym, start, freq) {
if (!(start <= 1 << 16)) {
throw new CramMalformedError('assertion failed: start <= 1<<16')
}
if (!(freq <= (1 << 16) - start)) {
throw new CramMalformedError('assertion failed: freq <= 1<<16')
}
sym.start = start
sym.freq = freq
}
// Advances in the bit stream by "popping" a single symbol with range start
// "start" and frequency "freq". All frequencies are assumed to sum to
// "1 << scaleBits".
// No renormalization or output happens.
/* private static int */ function advanceStep(
/* final int */ r,
/* final int */ start,
/* final int */ freq,
/* final int */ scaleBits,
) {
/* final int */ const mask = (1 << scaleBits) - 1
// s, x = D(x)
return freq * (r >> scaleBits) + (r & mask) - start
}
// Equivalent to RansDecAdvanceStep that takes a symbol.
/* static int */ function advanceSymbolStep(
/* final int */ r,
/* final RansDecSymbol */ sym,
/* final int */ scaleBits,
) {
return advanceStep(r, sym.start, sym.freq, scaleBits)
}
// Returns the current cumulative frequency (map it to a symbol yourself!)
/* static int */ function get(/* final int */ r, /* final int */ scaleBits) {
return r & ((1 << scaleBits) - 1)
}
// Advances in the bit stream by "popping" a single symbol with range start
// "start" and frequency "freq". All frequencies are assumed to sum to
// "1 << scaleBits",
// and the resulting bytes get written to ptr (which is updated).
/* private static int */ function advance(
/* int */ r,
/* final ByteBuffer */ pptr,
/* final int */ start,
/* final int */ freq,
/* final int */ scaleBits,
) {
/* final int */ const mask = (1 << scaleBits) - 1
// s, x = D(x)
r = freq * (r >> scaleBits) + (r & mask) - start
// re-normalize
if (r < RANS_BYTE_L) {
do {
/* final int */ const b = 0xff & pptr.get()
r = (r << 8) | b
} while (r < RANS_BYTE_L)
}
return r
}
// Equivalent to RansDecAdvance that takes a symbol.
/* static int */ function advanceSymbol(
/* final int */ r,
/* final ByteBuffer */ pptr,
/* final RansDecSymbol */ sym,
/* final int */ scaleBits,
) {
return advance(r, pptr, sym.start, sym.freq, scaleBits)
}
// Re-normalize.
/* static int */ function renormalize(
/* int */ r,
/* final ByteBuffer */ pptr,
) {
// re-normalize
if (r < RANS_BYTE_L) {
do {
r = (r << 8) | (0xff & pptr.get())
} while (r < RANS_BYTE_L)
}
return r
}
export default {
FC,
AriDecoder,
DecodingSymbol,
symbolInit,
advanceStep,
advanceSymbolStep,
get,
advanceSymbol,
renormalize,
}