mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-28 10:58:15 -05:00
Update #44 - WebAssembly GC support, fix more WebRTC bugs
This commit is contained in:
471
sources/wasm-gc-teavm/java/com/jcraft/jorbis/CodeBook.java
Normal file
471
sources/wasm-gc-teavm/java/com/jcraft/jorbis/CodeBook.java
Normal file
@ -0,0 +1,471 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/* JOrbis
|
||||
* Copyright (C) 2000 ymnk, JCraft,Inc.
|
||||
*
|
||||
* Written by: 2000 ymnk<ymnk@jcraft.com>
|
||||
*
|
||||
* Many thanks to
|
||||
* Monty <monty@xiph.org> and
|
||||
* The XIPHOPHORUS Company http://www.xiph.org/ .
|
||||
* JOrbis has been based on their awesome works, Vorbis codec.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
package com.jcraft.jorbis;
|
||||
|
||||
import com.jcraft.jogg.*;
|
||||
|
||||
class CodeBook {
|
||||
int dim; // codebook dimensions (elements per vector)
|
||||
int entries; // codebook entries
|
||||
StaticCodeBook c = new StaticCodeBook();
|
||||
|
||||
float[] valuelist; // list of dim*entries actual entry values
|
||||
int[] codelist; // list of bitstream codewords for each entry
|
||||
DecodeAux decode_tree;
|
||||
|
||||
// returns the number of bits
|
||||
int encode(int a, Buffer b) {
|
||||
b.write(codelist[a], c.lengthlist[a]);
|
||||
return (c.lengthlist[a]);
|
||||
}
|
||||
|
||||
// One the encode side, our vector writers are each designed for a
|
||||
// specific purpose, and the encoder is not flexible without modification:
|
||||
//
|
||||
// The LSP vector coder uses a single stage nearest-match with no
|
||||
// interleave, so no step and no error return. This is specced by floor0
|
||||
// and doesn't change.
|
||||
//
|
||||
// Residue0 encoding interleaves, uses multiple stages, and each stage
|
||||
// peels of a specific amount of resolution from a lattice (thus we want
|
||||
// to match by threshhold, not nearest match). Residue doesn't *have* to
|
||||
// be encoded that way, but to change it, one will need to add more
|
||||
// infrastructure on the encode side (decode side is specced and simpler)
|
||||
|
||||
// floor0 LSP (single stage, non interleaved, nearest match)
|
||||
// returns entry number and *modifies a* to the quantization value
|
||||
int errorv(float[] a) {
|
||||
int best = best(a, 1);
|
||||
for (int k = 0; k < dim; k++) {
|
||||
a[k] = valuelist[best * dim + k];
|
||||
}
|
||||
return (best);
|
||||
}
|
||||
|
||||
// returns the number of bits and *modifies a* to the quantization value
|
||||
int encodev(int best, float[] a, Buffer b) {
|
||||
for (int k = 0; k < dim; k++) {
|
||||
a[k] = valuelist[best * dim + k];
|
||||
}
|
||||
return (encode(best, b));
|
||||
}
|
||||
|
||||
// res0 (multistage, interleave, lattice)
|
||||
// returns the number of bits and *modifies a* to the remainder value
|
||||
int encodevs(float[] a, Buffer b, int step, int addmul) {
|
||||
int best = besterror(a, step, addmul);
|
||||
return (encode(best, b));
|
||||
}
|
||||
|
||||
private int[] t = new int[15]; // decodevs_add is synchronized for re-using t.
|
||||
|
||||
synchronized int decodevs_add(float[] a, int offset, Buffer b, int n) {
|
||||
int step = n / dim;
|
||||
int entry;
|
||||
int i, j, o;
|
||||
|
||||
if (t.length < step) {
|
||||
t = new int[step];
|
||||
}
|
||||
|
||||
for (i = 0; i < step; i++) {
|
||||
entry = decode(b);
|
||||
if (entry == -1)
|
||||
return (-1);
|
||||
t[i] = entry * dim;
|
||||
}
|
||||
for (i = 0, o = 0; i < dim; i++, o += step) {
|
||||
for (j = 0; j < step; j++) {
|
||||
a[offset + o + j] += valuelist[t[j] + i];
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int decodev_add(float[] a, int offset, Buffer b, int n) {
|
||||
int i, j, entry;
|
||||
int t;
|
||||
|
||||
if (dim > 8) {
|
||||
for (i = 0; i < n;) {
|
||||
entry = decode(b);
|
||||
if (entry == -1)
|
||||
return (-1);
|
||||
t = entry * dim;
|
||||
for (j = 0; j < dim;) {
|
||||
a[offset + (i++)] += valuelist[t + (j++)];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < n;) {
|
||||
entry = decode(b);
|
||||
if (entry == -1)
|
||||
return (-1);
|
||||
t = entry * dim;
|
||||
j = 0;
|
||||
switch (dim) {
|
||||
case 8:
|
||||
a[offset + (i++)] += valuelist[t + (j++)];
|
||||
case 7:
|
||||
a[offset + (i++)] += valuelist[t + (j++)];
|
||||
case 6:
|
||||
a[offset + (i++)] += valuelist[t + (j++)];
|
||||
case 5:
|
||||
a[offset + (i++)] += valuelist[t + (j++)];
|
||||
case 4:
|
||||
a[offset + (i++)] += valuelist[t + (j++)];
|
||||
case 3:
|
||||
a[offset + (i++)] += valuelist[t + (j++)];
|
||||
case 2:
|
||||
a[offset + (i++)] += valuelist[t + (j++)];
|
||||
case 1:
|
||||
a[offset + (i++)] += valuelist[t + (j++)];
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int decodev_set(float[] a, int offset, Buffer b, int n) {
|
||||
int i, j, entry;
|
||||
int t;
|
||||
|
||||
for (i = 0; i < n;) {
|
||||
entry = decode(b);
|
||||
if (entry == -1)
|
||||
return (-1);
|
||||
t = entry * dim;
|
||||
for (j = 0; j < dim;) {
|
||||
a[offset + i++] = valuelist[t + (j++)];
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int decodevv_add(float[][] a, int offset, int ch, Buffer b, int n) {
|
||||
int i, j, entry;
|
||||
int chptr = 0;
|
||||
|
||||
for (i = offset / ch; i < (offset + n) / ch;) {
|
||||
entry = decode(b);
|
||||
if (entry == -1)
|
||||
return (-1);
|
||||
|
||||
int t = entry * dim;
|
||||
for (j = 0; j < dim; j++) {
|
||||
a[chptr++][i] += valuelist[t + j];
|
||||
if (chptr == ch) {
|
||||
chptr = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
// Decode side is specced and easier, because we don't need to find
|
||||
// matches using different criteria; we simply read and map. There are
|
||||
// two things we need to do 'depending':
|
||||
//
|
||||
// We may need to support interleave. We don't really, but it's
|
||||
// convenient to do it here rather than rebuild the vector later.
|
||||
//
|
||||
// Cascades may be additive or multiplicitive; this is not inherent in
|
||||
// the codebook, but set in the code using the codebook. Like
|
||||
// interleaving, it's easiest to do it here.
|
||||
// stage==0 -> declarative (set the value)
|
||||
// stage==1 -> additive
|
||||
// stage==2 -> multiplicitive
|
||||
|
||||
// returns the entry number or -1 on eof
|
||||
int decode(Buffer b) {
|
||||
int ptr = 0;
|
||||
DecodeAux t = decode_tree;
|
||||
int lok = b.look(t.tabn);
|
||||
|
||||
if (lok >= 0) {
|
||||
ptr = t.tab[lok];
|
||||
b.adv(t.tabl[lok]);
|
||||
if (ptr <= 0) {
|
||||
return -ptr;
|
||||
}
|
||||
}
|
||||
do {
|
||||
switch (b.read1()) {
|
||||
case 0:
|
||||
ptr = t.ptr0[ptr];
|
||||
break;
|
||||
case 1:
|
||||
ptr = t.ptr1[ptr];
|
||||
break;
|
||||
case -1:
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
} while (ptr > 0);
|
||||
return (-ptr);
|
||||
}
|
||||
|
||||
// returns the entry number or -1 on eof
|
||||
int decodevs(float[] a, int index, Buffer b, int step, int addmul) {
|
||||
int entry = decode(b);
|
||||
if (entry == -1)
|
||||
return (-1);
|
||||
switch (addmul) {
|
||||
case -1:
|
||||
for (int i = 0, o = 0; i < dim; i++, o += step)
|
||||
a[index + o] = valuelist[entry * dim + i];
|
||||
break;
|
||||
case 0:
|
||||
for (int i = 0, o = 0; i < dim; i++, o += step)
|
||||
a[index + o] += valuelist[entry * dim + i];
|
||||
break;
|
||||
case 1:
|
||||
for (int i = 0, o = 0; i < dim; i++, o += step)
|
||||
a[index + o] *= valuelist[entry * dim + i];
|
||||
break;
|
||||
default:
|
||||
// System.err.println("CodeBook.decodeves: addmul="+addmul);
|
||||
}
|
||||
return (entry);
|
||||
}
|
||||
|
||||
int best(float[] a, int step) {
|
||||
// brute force it!
|
||||
{
|
||||
int besti = -1;
|
||||
float best = 0.f;
|
||||
int e = 0;
|
||||
for (int i = 0; i < entries; i++) {
|
||||
if (c.lengthlist[i] > 0) {
|
||||
float _this = dist(dim, valuelist, e, a, step);
|
||||
if (besti == -1 || _this < best) {
|
||||
best = _this;
|
||||
besti = i;
|
||||
}
|
||||
}
|
||||
e += dim;
|
||||
}
|
||||
return (besti);
|
||||
}
|
||||
}
|
||||
|
||||
// returns the entry number and *modifies a* to the remainder value
|
||||
int besterror(float[] a, int step, int addmul) {
|
||||
int best = best(a, step);
|
||||
switch (addmul) {
|
||||
case 0:
|
||||
for (int i = 0, o = 0; i < dim; i++, o += step)
|
||||
a[o] -= valuelist[best * dim + i];
|
||||
break;
|
||||
case 1:
|
||||
for (int i = 0, o = 0; i < dim; i++, o += step) {
|
||||
float val = valuelist[best * dim + i];
|
||||
if (val == 0) {
|
||||
a[o] = 0;
|
||||
} else {
|
||||
a[o] /= val;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (best);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
}
|
||||
|
||||
private static float dist(int el, float[] ref, int index, float[] b, int step) {
|
||||
float acc = (float) 0.;
|
||||
for (int i = 0; i < el; i++) {
|
||||
float val = (ref[index + i] - b[i * step]);
|
||||
acc += val * val;
|
||||
}
|
||||
return (acc);
|
||||
}
|
||||
|
||||
int init_decode(StaticCodeBook s) {
|
||||
c = s;
|
||||
entries = s.entries;
|
||||
dim = s.dim;
|
||||
valuelist = s.unquantize();
|
||||
|
||||
decode_tree = make_decode_tree();
|
||||
if (decode_tree == null) {
|
||||
clear();
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
// given a list of word lengths, generate a list of codewords. Works
|
||||
// for length ordered or unordered, always assigns the lowest valued
|
||||
// codewords first. Extended to handle unused entries (length 0)
|
||||
static int[] make_words(int[] l, int n) {
|
||||
int[] marker = new int[33];
|
||||
int[] r = new int[n];
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
int length = l[i];
|
||||
if (length > 0) {
|
||||
int entry = marker[length];
|
||||
|
||||
// when we claim a node for an entry, we also claim the nodes
|
||||
// below it (pruning off the imagined tree that may have dangled
|
||||
// from it) as well as blocking the use of any nodes directly
|
||||
// above for leaves
|
||||
|
||||
// update ourself
|
||||
if (length < 32 && (entry >>> length) != 0) {
|
||||
// error condition; the lengths must specify an overpopulated tree
|
||||
// free(r);
|
||||
return (null);
|
||||
}
|
||||
r[i] = entry;
|
||||
|
||||
// Look to see if the next shorter marker points to the node
|
||||
// above. if so, update it and repeat.
|
||||
{
|
||||
for (int j = length; j > 0; j--) {
|
||||
if ((marker[j] & 1) != 0) {
|
||||
// have to jump branches
|
||||
if (j == 1)
|
||||
marker[1]++;
|
||||
else
|
||||
marker[j] = marker[j - 1] << 1;
|
||||
break; // invariant says next upper marker would already
|
||||
// have been moved if it was on the same path
|
||||
}
|
||||
marker[j]++;
|
||||
}
|
||||
}
|
||||
|
||||
// prune the tree; the implicit invariant says all the longer
|
||||
// markers were dangling from our just-taken node. Dangle them
|
||||
// from our *new* node.
|
||||
for (int j = length + 1; j < 33; j++) {
|
||||
if ((marker[j] >>> 1) == entry) {
|
||||
entry = marker[j];
|
||||
marker[j] = marker[j - 1] << 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bitreverse the words because our bitwise packer/unpacker is LSb
|
||||
// endian
|
||||
for (int i = 0; i < n; i++) {
|
||||
int temp = 0;
|
||||
for (int j = 0; j < l[i]; j++) {
|
||||
temp <<= 1;
|
||||
temp |= (r[i] >>> j) & 1;
|
||||
}
|
||||
r[i] = temp;
|
||||
}
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
// build the decode helper tree from the codewords
|
||||
DecodeAux make_decode_tree() {
|
||||
int top = 0;
|
||||
DecodeAux t = new DecodeAux();
|
||||
int[] ptr0 = t.ptr0 = new int[entries * 2];
|
||||
int[] ptr1 = t.ptr1 = new int[entries * 2];
|
||||
int[] codelist = make_words(c.lengthlist, c.entries);
|
||||
|
||||
if (codelist == null)
|
||||
return (null);
|
||||
t.aux = entries * 2;
|
||||
|
||||
for (int i = 0; i < entries; i++) {
|
||||
if (c.lengthlist[i] > 0) {
|
||||
int ptr = 0;
|
||||
int j;
|
||||
for (j = 0; j < c.lengthlist[i] - 1; j++) {
|
||||
int bit = (codelist[i] >>> j) & 1;
|
||||
if (bit == 0) {
|
||||
if (ptr0[ptr] == 0) {
|
||||
ptr0[ptr] = ++top;
|
||||
}
|
||||
ptr = ptr0[ptr];
|
||||
} else {
|
||||
if (ptr1[ptr] == 0) {
|
||||
ptr1[ptr] = ++top;
|
||||
}
|
||||
ptr = ptr1[ptr];
|
||||
}
|
||||
}
|
||||
|
||||
if (((codelist[i] >>> j) & 1) == 0) {
|
||||
ptr0[ptr] = -i;
|
||||
} else {
|
||||
ptr1[ptr] = -i;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
t.tabn = Util.ilog(entries) - 4;
|
||||
|
||||
if (t.tabn < 5)
|
||||
t.tabn = 5;
|
||||
int n = 1 << t.tabn;
|
||||
t.tab = new int[n];
|
||||
t.tabl = new int[n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
int p = 0;
|
||||
int j = 0;
|
||||
for (j = 0; j < t.tabn && (p > 0 || j == 0); j++) {
|
||||
if ((i & (1 << j)) != 0) {
|
||||
p = ptr1[p];
|
||||
} else {
|
||||
p = ptr0[p];
|
||||
}
|
||||
}
|
||||
t.tab[i] = p; // -code
|
||||
t.tabl[i] = j; // length
|
||||
}
|
||||
|
||||
return (t);
|
||||
}
|
||||
|
||||
class DecodeAux {
|
||||
int[] tab;
|
||||
int[] tabl;
|
||||
int tabn;
|
||||
|
||||
int[] ptr0;
|
||||
int[] ptr1;
|
||||
int aux; // number of tree entries
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user