UNPKG

@gmod/cram

Version:

read CRAM files with pure Javascript

140 lines (122 loc) 3.26 kB
// @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, }