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 Floor0 extends FuncFloor { | |
void pack(Object i, Buffer opb) { | |
InfoFloor0 info = (InfoFloor0) i; | |
opb.write(info.order, 8); | |
opb.write(info.rate, 16); | |
opb.write(info.barkmap, 16); | |
opb.write(info.ampbits, 6); | |
opb.write(info.ampdB, 8); | |
opb.write(info.numbooks - 1, 4); | |
for (int j = 0; j < info.numbooks; j++) | |
opb.write(info.books[j], 8); | |
} | |
Object unpack(Info vi, Buffer opb) { | |
InfoFloor0 info = new InfoFloor0(); | |
info.order = opb.read(8); | |
info.rate = opb.read(16); | |
info.barkmap = opb.read(16); | |
info.ampbits = opb.read(6); | |
info.ampdB = opb.read(8); | |
info.numbooks = opb.read(4) + 1; | |
if ((info.order < 1) || (info.rate < 1) || (info.barkmap < 1) || (info.numbooks < 1)) { | |
return (null); | |
} | |
for (int j = 0; j < info.numbooks; j++) { | |
info.books[j] = opb.read(8); | |
if (info.books[j] < 0 || info.books[j] >= vi.books) { | |
return (null); | |
} | |
} | |
return (info); | |
} | |
Object look(DspState vd, InfoMode mi, Object i) { | |
float scale; | |
Info vi = vd.vi; | |
InfoFloor0 info = (InfoFloor0) i; | |
LookFloor0 look = new LookFloor0(); | |
look.m = info.order; | |
look.n = vi.blocksizes[mi.blockflag] / 2; | |
look.ln = info.barkmap; | |
look.vi = info; | |
look.lpclook.init(look.ln, look.m); | |
// we choose a scaling constant so that: | |
scale = look.ln / toBARK((float) (info.rate / 2.)); | |
// the mapping from a linear scale to a smaller bark scale is | |
// straightforward. We do *not* make sure that the linear mapping | |
// does not skip bark-scale bins; the decoder simply skips them and | |
// the encoder may do what it wishes in filling them. They're | |
// necessary in some mapping combinations to keep the scale spacing | |
// accurate | |
look.linearmap = new int[look.n]; | |
for (int j = 0; j < look.n; j++) { | |
int val = (int) Math.floor(toBARK((float) ((info.rate / 2.) / look.n * j)) * scale); // bark numbers | |
// represent band | |
// edges | |
if (val >= look.ln) | |
val = look.ln; // guard against the approximation | |
look.linearmap[j] = val; | |
} | |
return look; | |
} | |
static float toBARK(float f) { | |
return (float) (13.1 * Math.atan(.00074 * (f)) + 2.24 * Math.atan((f) * (f) * 1.85e-8) + 1e-4 * (f)); | |
} | |
Object state(Object i) { | |
EchstateFloor0 state = new EchstateFloor0(); | |
InfoFloor0 info = (InfoFloor0) i; | |
// a safe size if usually too big (dim==1) | |
state.codewords = new int[info.order]; | |
state.curve = new float[info.barkmap]; | |
state.frameno = -1; | |
return (state); | |
} | |
void free_info(Object i) { | |
} | |
void free_look(Object i) { | |
} | |
void free_state(Object vs) { | |
} | |
int forward(Block vb, Object i, float[] in, float[] out, Object vs) { | |
return 0; | |
} | |
float[] lsp = null; | |
int inverse(Block vb, Object i, float[] out) { | |
// System.err.println("Floor0.inverse "+i.getClass()+"]"); | |
LookFloor0 look = (LookFloor0) i; | |
InfoFloor0 info = look.vi; | |
int ampraw = vb.opb.read(info.ampbits); | |
if (ampraw > 0) { // also handles the -1 out of data case | |
int maxval = (1 << info.ampbits) - 1; | |
float amp = (float) ampraw / maxval * info.ampdB; | |
int booknum = vb.opb.read(Util.ilog(info.numbooks)); | |
if (booknum != -1 && booknum < info.numbooks) { | |
synchronized (this) { | |
if (lsp == null || lsp.length < look.m) { | |
lsp = new float[look.m]; | |
} else { | |
for (int j = 0; j < look.m; j++) | |
lsp[j] = 0.f; | |
} | |
CodeBook b = vb.vd.fullbooks[info.books[booknum]]; | |
float last = 0.f; | |
for (int j = 0; j < look.m; j++) | |
out[j] = 0.0f; | |
for (int j = 0; j < look.m; j += b.dim) { | |
if (b.decodevs(lsp, j, vb.opb, 1, -1) == -1) { | |
for (int k = 0; k < look.n; k++) | |
out[k] = 0.0f; | |
return (0); | |
} | |
} | |
for (int j = 0; j < look.m;) { | |
for (int k = 0; k < b.dim; k++, j++) | |
lsp[j] += last; | |
last = lsp[j - 1]; | |
} | |
// take the coefficients back to a spectral envelope curve | |
Lsp.lsp_to_curve(out, look.linearmap, look.n, look.ln, lsp, look.m, amp, info.ampdB); | |
return (1); | |
} | |
} | |
} | |
return (0); | |
} | |
Object inverse1(Block vb, Object i, Object memo) { | |
LookFloor0 look = (LookFloor0) i; | |
InfoFloor0 info = look.vi; | |
float[] lsp = null; | |
if (memo instanceof float[]) { | |
lsp = (float[]) memo; | |
} | |
int ampraw = vb.opb.read(info.ampbits); | |
if (ampraw > 0) { // also handles the -1 out of data case | |
int maxval = (1 << info.ampbits) - 1; | |
float amp = (float) ampraw / maxval * info.ampdB; | |
int booknum = vb.opb.read(Util.ilog(info.numbooks)); | |
if (booknum != -1 && booknum < info.numbooks) { | |
CodeBook b = vb.vd.fullbooks[info.books[booknum]]; | |
float last = 0.f; | |
if (lsp == null || lsp.length < look.m + 1) { | |
lsp = new float[look.m + 1]; | |
} else { | |
for (int j = 0; j < lsp.length; j++) | |
lsp[j] = 0.f; | |
} | |
for (int j = 0; j < look.m; j += b.dim) { | |
if (b.decodev_set(lsp, j, vb.opb, b.dim) == -1) { | |
return (null); | |
} | |
} | |
for (int j = 0; j < look.m;) { | |
for (int k = 0; k < b.dim; k++, j++) | |
lsp[j] += last; | |
last = lsp[j - 1]; | |
} | |
lsp[look.m] = amp; | |
return (lsp); | |
} | |
} | |
return (null); | |
} | |
int inverse2(Block vb, Object i, Object memo, float[] out) { | |
LookFloor0 look = (LookFloor0) i; | |
InfoFloor0 info = look.vi; | |
if (memo != null) { | |
float[] lsp = (float[]) memo; | |
float amp = lsp[look.m]; | |
Lsp.lsp_to_curve(out, look.linearmap, look.n, look.ln, lsp, look.m, amp, info.ampdB); | |
return (1); | |
} | |
for (int j = 0; j < look.n; j++) { | |
out[j] = 0.f; | |
} | |
return (0); | |
} | |
static float fromdB(float x) { | |
return (float) (Math.exp((x) * .11512925)); | |
} | |
static void lsp_to_lpc(float[] lsp, float[] lpc, int m) { | |
int i, j, m2 = m / 2; | |
float[] O = new float[m2]; | |
float[] E = new float[m2]; | |
float A; | |
float[] Ae = new float[m2 + 1]; | |
float[] Ao = new float[m2 + 1]; | |
float B; | |
float[] Be = new float[m2]; | |
float[] Bo = new float[m2]; | |
float temp; | |
// even/odd roots setup | |
for (i = 0; i < m2; i++) { | |
O[i] = (float) (-2. * Math.cos(lsp[i * 2])); | |
E[i] = (float) (-2. * Math.cos(lsp[i * 2 + 1])); | |
} | |
// set up impulse response | |
for (j = 0; j < m2; j++) { | |
Ae[j] = 0.f; | |
Ao[j] = 1.f; | |
Be[j] = 0.f; | |
Bo[j] = 1.f; | |
} | |
Ao[j] = 1.f; | |
Ae[j] = 1.f; | |
// run impulse response | |
for (i = 1; i < m + 1; i++) { | |
A = B = 0.f; | |
for (j = 0; j < m2; j++) { | |
temp = O[j] * Ao[j] + Ae[j]; | |
Ae[j] = Ao[j]; | |
Ao[j] = A; | |
A += temp; | |
temp = E[j] * Bo[j] + Be[j]; | |
Be[j] = Bo[j]; | |
Bo[j] = B; | |
B += temp; | |
} | |
lpc[i - 1] = (A + Ao[j] + B - Ae[j]) / 2; | |
Ao[j] = A; | |
Ae[j] = B; | |
} | |
} | |
static void lpc_to_curve(float[] curve, float[] lpc, float amp, LookFloor0 l, String name, int frameno) { | |
// l->m+1 must be less than l->ln, but guard in case we get a bad stream | |
float[] lcurve = new float[Math.max(l.ln * 2, l.m * 2 + 2)]; | |
if (amp == 0) { | |
for (int j = 0; j < l.n; j++) | |
curve[j] = 0.0f; | |
return; | |
} | |
l.lpclook.lpc_to_curve(lcurve, lpc, amp); | |
for (int i = 0; i < l.n; i++) | |
curve[i] = lcurve[l.linearmap[i]]; | |
} | |
class InfoFloor0 { | |
int order; | |
int rate; | |
int barkmap; | |
int ampbits; | |
int ampdB; | |
int numbooks; // <= 16 | |
int[] books = new int[16]; | |
} | |
class LookFloor0 { | |
int n; | |
int ln; | |
int m; | |
int[] linearmap; | |
InfoFloor0 vi; | |
Lpc lpclook = new Lpc(); | |
} | |
class EchstateFloor0 { | |
int[] codewords; | |
float[] curve; | |
long frameno; | |
long codes; | |
} | |
} | |