/*
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.
*
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002
* by the Xiph.Org Foundation http://www.xiph.org/
*/
package org.xiph.libvorbis;
import static org.xiph.libvorbis.vorbis_constants.integer_constants.*;
public class codebook {
int dim; // long dim // codebook dimensions (elements per vector)
int entries; // long entries // codebook entries
int used_entries; // long used_entries // populated codebook entries
static_codebook c;
// for encode, the below are entry-ordered, fully populated
// for decode, the below are ordered by bitreversed codeword and only used entries are populated
float[] valuelist; // list of dim*entries actual entry values
int[] codelist; // ogg_uint32_t *codelist // list of bitstream codewords for each entry
int[] dec_index; // only used if sparseness collapsed
char[] dec_codelengths; // chat *dec_codelengths
int[] dec_firsttable; // ogg_uint32_t *dec_firsttable
int dec_firsttablen;
int dec_maxlength;
public codebook() {
}
public void vorbis_book_init_encode(static_codebook s) {
dim = s.dim;
entries = s.entries;
used_entries = s.entries;
c = s;
codelist = _make_words(s.lengthlist, s.entries, 0);
valuelist = _book_unquantize(s, s.entries, null);
}
private int[] _make_words(int[] l, int n, int sparsecount) {
int i, j, count = 0;
int[] marker; // ogg_uint32_t marker[33];
// ogg_uint32_t *r=_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
int[] r;
if (sparsecount != 0)
r = new int[sparsecount];
else
r = new int[n];
// memset(marker,0,sizeof(marker));
marker = new int[33];
for (i = 0; i < n; i++) {
int length = l[i];
if (length > 0) {
// ogg_uint32_t entry=marker[length];
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
// _ogg_free(r);
return null;
}
r[count++] = entry;
// Look to see if the next shorter marker points to the node above. if so, update it and repeat
for (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 (j = length + 1; j < 33; j++) {
if ((marker[j] >>> 1) == entry) {
entry = marker[j];
marker[j] = marker[j - 1] << 1;
} else
break;
}
} else if (sparsecount == 0)
count++;
}
// bitreverse the words because our bitwise packer/unpacker is LSb endian
for (i = 0, count = 0; i < n; i++) {
// ogg_uint32_t temp=0;
int temp = 0;
for (j = 0; j < l[i]; j++) {
temp <<= 1;
temp |= (r[count] >>> j) & 1;
}
if (sparsecount != 0) {
if (l[i] != 0)
r[count++] = temp;
} else
r[count++] = temp;
}
return r;
}
private float ldexp(double value, long exp) {
return new Double(value * Math.pow(2, new Long(exp).intValue())).floatValue();
}
private float _float32_unpack(int val) {
double mant = val & 0x1fffff;
int sign = val & 0x80000000;
long exp = (val & 0x7fe00000L) >>> VQ_FMAN;
if (sign != 0)
mant = -mant;
return ldexp(mant, exp - (VQ_FMAN - 1) - VQ_FEXP_BIAS);
}
private float[] _book_unquantize(static_codebook b, int n, int[] sparsemap) {
int j, k, count = 0;
if (b.maptype == 1 || b.maptype == 2) {
int quantvals;
float mindel = _float32_unpack(b.q_min);
float delta = _float32_unpack(b.q_delta);
// float *r=_ogg_calloc(n*b->dim,sizeof(*r));
float[] r = new float[n * b.dim];
// maptype 1 and 2 both use a quantized value vector, but different sizes
switch (b.maptype) {
case 1: {
quantvals = b._book_maptype1_quantvals();
for (j = 0; j < b.entries; j++) {
if (((sparsemap != null) && (b.lengthlist[j] != 0)) || sparsemap == null) {
float last = 0.f;
int indexdiv = 1;
for (k = 0; k < b.dim; k++) {
int index = (j / indexdiv) % quantvals;
float val = b.quantlist[index];
val = Math.abs(val) * delta + mindel + last;
if (b.q_sequencep != 0)
last = val;
if (sparsemap != null)
r[sparsemap[count] * b.dim + k] = val;
else
r[count * b.dim + k] = val;
indexdiv *= quantvals;
}
count++;
}
}
break;
}
case 2: {
for (j = 0; j < b.entries; j++) {
if (((sparsemap != null) && (b.lengthlist[j] != 0)) || sparsemap == null) {
float last = 0.f;
for (k = 0; k < b.dim; k++) {
float val = b.quantlist[j * b.dim + k];
val = Math.abs(val) * delta + mindel + last;
if (b.q_sequencep != 0)
last = val;
if (sparsemap != null)
r[sparsemap[count] * b.dim + k] = val;
else
r[count * b.dim + k] = val;
}
count++;
}
}
break;
}
}
return r;
}
return null;
}
}