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 Mapping0 extends FuncMapping { | |
static int seq = 0; | |
void free_info(Object imap) { | |
}; | |
void free_look(Object imap) { | |
} | |
Object look(DspState vd, InfoMode vm, Object m) { | |
// System.err.println("Mapping0.look"); | |
Info vi = vd.vi; | |
LookMapping0 look = new LookMapping0(); | |
InfoMapping0 info = look.map = (InfoMapping0) m; | |
look.mode = vm; | |
look.time_look = new Object[info.submaps]; | |
look.floor_look = new Object[info.submaps]; | |
look.residue_look = new Object[info.submaps]; | |
look.time_func = new FuncTime[info.submaps]; | |
look.floor_func = new FuncFloor[info.submaps]; | |
look.residue_func = new FuncResidue[info.submaps]; | |
for (int i = 0; i < info.submaps; i++) { | |
int timenum = info.timesubmap[i]; | |
int floornum = info.floorsubmap[i]; | |
int resnum = info.residuesubmap[i]; | |
look.time_func[i] = FuncTime.time_P[vi.time_type[timenum]]; | |
look.time_look[i] = look.time_func[i].look(vd, vm, vi.time_param[timenum]); | |
look.floor_func[i] = FuncFloor.floor_P[vi.floor_type[floornum]]; | |
look.floor_look[i] = look.floor_func[i].look(vd, vm, vi.floor_param[floornum]); | |
look.residue_func[i] = FuncResidue.residue_P[vi.residue_type[resnum]]; | |
look.residue_look[i] = look.residue_func[i].look(vd, vm, vi.residue_param[resnum]); | |
} | |
if (vi.psys != 0 && vd.analysisp != 0) { | |
// ?? | |
} | |
look.ch = vi.channels; | |
return (look); | |
} | |
void pack(Info vi, Object imap, Buffer opb) { | |
InfoMapping0 info = (InfoMapping0) imap; | |
/* | |
* another 'we meant to do it this way' hack... up to beta 4, we packed 4 binary | |
* zeros here to signify one submapping in use. We now redefine that to mean | |
* four bitflags that indicate use of deeper features; bit0:submappings, | |
* bit1:coupling, bit2,3:reserved. This is backward compatable with all actual | |
* uses of the beta code. | |
*/ | |
if (info.submaps > 1) { | |
opb.write(1, 1); | |
opb.write(info.submaps - 1, 4); | |
} else { | |
opb.write(0, 1); | |
} | |
if (info.coupling_steps > 0) { | |
opb.write(1, 1); | |
opb.write(info.coupling_steps - 1, 8); | |
for (int i = 0; i < info.coupling_steps; i++) { | |
opb.write(info.coupling_mag[i], Util.ilog2(vi.channels)); | |
opb.write(info.coupling_ang[i], Util.ilog2(vi.channels)); | |
} | |
} else { | |
opb.write(0, 1); | |
} | |
opb.write(0, 2); /* 2,3:reserved */ | |
/* we don't write the channel submappings if we only have one... */ | |
if (info.submaps > 1) { | |
for (int i = 0; i < vi.channels; i++) | |
opb.write(info.chmuxlist[i], 4); | |
} | |
for (int i = 0; i < info.submaps; i++) { | |
opb.write(info.timesubmap[i], 8); | |
opb.write(info.floorsubmap[i], 8); | |
opb.write(info.residuesubmap[i], 8); | |
} | |
} | |
// also responsible for range checking | |
Object unpack(Info vi, Buffer opb) { | |
InfoMapping0 info = new InfoMapping0(); | |
if (opb.read(1) != 0) { | |
info.submaps = opb.read(4) + 1; | |
} else { | |
info.submaps = 1; | |
} | |
if (opb.read(1) != 0) { | |
info.coupling_steps = opb.read(8) + 1; | |
for (int i = 0; i < info.coupling_steps; i++) { | |
int testM = info.coupling_mag[i] = opb.read(Util.ilog2(vi.channels)); | |
int testA = info.coupling_ang[i] = opb.read(Util.ilog2(vi.channels)); | |
if (testM < 0 || testA < 0 || testM == testA || testM >= vi.channels || testA >= vi.channels) { | |
// goto err_out; | |
info.free(); | |
return (null); | |
} | |
} | |
} | |
if (opb.read(2) > 0) { /* 2,3:reserved */ | |
info.free(); | |
return (null); | |
} | |
if (info.submaps > 1) { | |
for (int i = 0; i < vi.channels; i++) { | |
info.chmuxlist[i] = opb.read(4); | |
if (info.chmuxlist[i] >= info.submaps) { | |
info.free(); | |
return (null); | |
} | |
} | |
} | |
for (int i = 0; i < info.submaps; i++) { | |
info.timesubmap[i] = opb.read(8); | |
if (info.timesubmap[i] >= vi.times) { | |
info.free(); | |
return (null); | |
} | |
info.floorsubmap[i] = opb.read(8); | |
if (info.floorsubmap[i] >= vi.floors) { | |
info.free(); | |
return (null); | |
} | |
info.residuesubmap[i] = opb.read(8); | |
if (info.residuesubmap[i] >= vi.residues) { | |
info.free(); | |
return (null); | |
} | |
} | |
return info; | |
} | |
float[][] pcmbundle = null; | |
int[] zerobundle = null; | |
int[] nonzero = null; | |
Object[] floormemo = null; | |
synchronized int inverse(Block vb, Object l) { | |
DspState vd = vb.vd; | |
Info vi = vd.vi; | |
LookMapping0 look = (LookMapping0) l; | |
InfoMapping0 info = look.map; | |
InfoMode mode = look.mode; | |
int n = vb.pcmend = vi.blocksizes[vb.W]; | |
float[] window = vd.window[vb.W][vb.lW][vb.nW][mode.windowtype]; | |
if (pcmbundle == null || pcmbundle.length < vi.channels) { | |
pcmbundle = new float[vi.channels][]; | |
nonzero = new int[vi.channels]; | |
zerobundle = new int[vi.channels]; | |
floormemo = new Object[vi.channels]; | |
} | |
// time domain information decode (note that applying the | |
// information would have to happen later; we'll probably add a | |
// function entry to the harness for that later | |
// NOT IMPLEMENTED | |
// recover the spectral envelope; store it in the PCM vector for now | |
for (int i = 0; i < vi.channels; i++) { | |
float[] pcm = vb.pcm[i]; | |
int submap = info.chmuxlist[i]; | |
floormemo[i] = look.floor_func[submap].inverse1(vb, look.floor_look[submap], floormemo[i]); | |
if (floormemo[i] != null) { | |
nonzero[i] = 1; | |
} else { | |
nonzero[i] = 0; | |
} | |
for (int j = 0; j < n / 2; j++) { | |
pcm[j] = 0; | |
} | |
} | |
for (int i = 0; i < info.coupling_steps; i++) { | |
if (nonzero[info.coupling_mag[i]] != 0 || nonzero[info.coupling_ang[i]] != 0) { | |
nonzero[info.coupling_mag[i]] = 1; | |
nonzero[info.coupling_ang[i]] = 1; | |
} | |
} | |
// recover the residue, apply directly to the spectral envelope | |
for (int i = 0; i < info.submaps; i++) { | |
int ch_in_bundle = 0; | |
for (int j = 0; j < vi.channels; j++) { | |
if (info.chmuxlist[j] == i) { | |
if (nonzero[j] != 0) { | |
zerobundle[ch_in_bundle] = 1; | |
} else { | |
zerobundle[ch_in_bundle] = 0; | |
} | |
pcmbundle[ch_in_bundle++] = vb.pcm[j]; | |
} | |
} | |
look.residue_func[i].inverse(vb, look.residue_look[i], pcmbundle, zerobundle, ch_in_bundle); | |
} | |
for (int i = info.coupling_steps - 1; i >= 0; i--) { | |
float[] pcmM = vb.pcm[info.coupling_mag[i]]; | |
float[] pcmA = vb.pcm[info.coupling_ang[i]]; | |
for (int j = 0; j < n / 2; j++) { | |
float mag = pcmM[j]; | |
float ang = pcmA[j]; | |
if (mag > 0) { | |
if (ang > 0) { | |
pcmM[j] = mag; | |
pcmA[j] = mag - ang; | |
} else { | |
pcmA[j] = mag; | |
pcmM[j] = mag + ang; | |
} | |
} else { | |
if (ang > 0) { | |
pcmM[j] = mag; | |
pcmA[j] = mag + ang; | |
} else { | |
pcmA[j] = mag; | |
pcmM[j] = mag - ang; | |
} | |
} | |
} | |
} | |
// /* compute and apply spectral envelope */ | |
for (int i = 0; i < vi.channels; i++) { | |
float[] pcm = vb.pcm[i]; | |
int submap = info.chmuxlist[i]; | |
look.floor_func[submap].inverse2(vb, look.floor_look[submap], floormemo[i], pcm); | |
} | |
// transform the PCM data; takes PCM vector, vb; modifies PCM vector | |
// only MDCT right now.... | |
for (int i = 0; i < vi.channels; i++) { | |
float[] pcm = vb.pcm[i]; | |
// _analysis_output("out",seq+i,pcm,n/2,0,0); | |
((Mdct) vd.transform[vb.W][0]).backward(pcm, pcm); | |
} | |
// now apply the decoded pre-window time information | |
// NOT IMPLEMENTED | |
// window the data | |
for (int i = 0; i < vi.channels; i++) { | |
float[] pcm = vb.pcm[i]; | |
if (nonzero[i] != 0) { | |
for (int j = 0; j < n; j++) { | |
pcm[j] *= window[j]; | |
} | |
} else { | |
for (int j = 0; j < n; j++) { | |
pcm[j] = 0.f; | |
} | |
} | |
} | |
// now apply the decoded post-window time information | |
// NOT IMPLEMENTED | |
// all done! | |
return (0); | |
} | |
class InfoMapping0 { | |
int submaps; // <= 16 | |
int[] chmuxlist = new int[256]; // up to 256 channels in a Vorbis stream | |
int[] timesubmap = new int[16]; // [mux] | |
int[] floorsubmap = new int[16]; // [mux] submap to floors | |
int[] residuesubmap = new int[16];// [mux] submap to residue | |
int[] psysubmap = new int[16]; // [mux]; encode only | |
int coupling_steps; | |
int[] coupling_mag = new int[256]; | |
int[] coupling_ang = new int[256]; | |
void free() { | |
chmuxlist = null; | |
timesubmap = null; | |
floorsubmap = null; | |
residuesubmap = null; | |
psysubmap = null; | |
coupling_mag = null; | |
coupling_ang = null; | |
} | |
} | |
class LookMapping0 { | |
InfoMode mode; | |
InfoMapping0 map; | |
Object[] time_look; | |
Object[] floor_look; | |
Object[] floor_state; | |
Object[] residue_look; | |
PsyLook[] psy_look; | |
FuncTime[] time_func; | |
FuncFloor[] floor_func; | |
FuncResidue[] residue_func; | |
int ch; | |
float[][] decay; | |
int lastframe; // if a different mode is called, we need to | |
// invalidate decay and floor state | |
} | |
} | |