Spaces:
Build error
Build error
/* -*-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 | |
} | |
} | |