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:
369
sources/wasm-gc-teavm/java/com/jcraft/jorbis/DspState.java
Normal file
369
sources/wasm-gc-teavm/java/com/jcraft/jorbis/DspState.java
Normal file
@ -0,0 +1,369 @@
|
||||
/* -*-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;
|
||||
|
||||
public class DspState {
|
||||
static final float M_PI = 3.1415926539f;
|
||||
static final int VI_TRANSFORMB = 1;
|
||||
static final int VI_WINDOWB = 1;
|
||||
|
||||
int analysisp;
|
||||
Info vi;
|
||||
int modebits;
|
||||
|
||||
float[][] pcm;
|
||||
int pcm_storage;
|
||||
int pcm_current;
|
||||
int pcm_returned;
|
||||
|
||||
float[] multipliers;
|
||||
int envelope_storage;
|
||||
int envelope_current;
|
||||
|
||||
int eofflag;
|
||||
|
||||
int lW;
|
||||
int W;
|
||||
int nW;
|
||||
int centerW;
|
||||
|
||||
long granulepos;
|
||||
long sequence;
|
||||
|
||||
long glue_bits;
|
||||
long time_bits;
|
||||
long floor_bits;
|
||||
long res_bits;
|
||||
|
||||
// local lookup storage
|
||||
float[][][][][] window; // block, leadin, leadout, type
|
||||
Object[][] transform;
|
||||
CodeBook[] fullbooks;
|
||||
// backend lookups are tied to the mode, not the backend or naked mapping
|
||||
Object[] mode;
|
||||
|
||||
// local storage, only used on the encoding side. This way the
|
||||
// application does not need to worry about freeing some packets'
|
||||
// memory and not others'; packet storage is always tracked.
|
||||
// Cleared next call to a _dsp_ function
|
||||
byte[] header;
|
||||
byte[] header1;
|
||||
byte[] header2;
|
||||
|
||||
public DspState() {
|
||||
transform = new Object[2][];
|
||||
window = new float[2][][][][];
|
||||
window[0] = new float[2][][][];
|
||||
window[0][0] = new float[2][][];
|
||||
window[0][1] = new float[2][][];
|
||||
window[0][0][0] = new float[2][];
|
||||
window[0][0][1] = new float[2][];
|
||||
window[0][1][0] = new float[2][];
|
||||
window[0][1][1] = new float[2][];
|
||||
window[1] = new float[2][][][];
|
||||
window[1][0] = new float[2][][];
|
||||
window[1][1] = new float[2][][];
|
||||
window[1][0][0] = new float[2][];
|
||||
window[1][0][1] = new float[2][];
|
||||
window[1][1][0] = new float[2][];
|
||||
window[1][1][1] = new float[2][];
|
||||
}
|
||||
|
||||
static float[] window(int type, int window, int left, int right) {
|
||||
float[] ret = new float[window];
|
||||
switch (type) {
|
||||
case 0:
|
||||
// The 'vorbis window' (window 0) is sin(sin(x)*sin(x)*2pi)
|
||||
{
|
||||
int leftbegin = window / 4 - left / 2;
|
||||
int rightbegin = window - window / 4 - right / 2;
|
||||
|
||||
for (int i = 0; i < left; i++) {
|
||||
float x = (float) ((i + .5) / left * M_PI / 2.);
|
||||
x = (float) Math.sin(x);
|
||||
x *= x;
|
||||
x *= M_PI / 2.;
|
||||
x = (float) Math.sin(x);
|
||||
ret[i + leftbegin] = x;
|
||||
}
|
||||
|
||||
for (int i = leftbegin + left; i < rightbegin; i++) {
|
||||
ret[i] = 1.f;
|
||||
}
|
||||
|
||||
for (int i = 0; i < right; i++) {
|
||||
float x = (float) ((right - i - .5) / right * M_PI / 2.);
|
||||
x = (float) Math.sin(x);
|
||||
x *= x;
|
||||
x *= M_PI / 2.;
|
||||
x = (float) Math.sin(x);
|
||||
ret[i + rightbegin] = x;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// free(ret);
|
||||
return (null);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
// Analysis side code, but directly related to blocking. Thus it's
|
||||
// here and not in analysis.c (which is for analysis transforms only).
|
||||
// The init is here because some of it is shared
|
||||
|
||||
int init(Info vi, boolean encp) {
|
||||
this.vi = vi;
|
||||
modebits = Util.ilog2(vi.modes);
|
||||
|
||||
transform[0] = new Object[VI_TRANSFORMB];
|
||||
transform[1] = new Object[VI_TRANSFORMB];
|
||||
|
||||
// MDCT is tranform 0
|
||||
|
||||
transform[0][0] = new Mdct();
|
||||
transform[1][0] = new Mdct();
|
||||
((Mdct) transform[0][0]).init(vi.blocksizes[0]);
|
||||
((Mdct) transform[1][0]).init(vi.blocksizes[1]);
|
||||
|
||||
window[0][0][0] = new float[VI_WINDOWB][];
|
||||
window[0][0][1] = window[0][0][0];
|
||||
window[0][1][0] = window[0][0][0];
|
||||
window[0][1][1] = window[0][0][0];
|
||||
window[1][0][0] = new float[VI_WINDOWB][];
|
||||
window[1][0][1] = new float[VI_WINDOWB][];
|
||||
window[1][1][0] = new float[VI_WINDOWB][];
|
||||
window[1][1][1] = new float[VI_WINDOWB][];
|
||||
|
||||
for (int i = 0; i < VI_WINDOWB; i++) {
|
||||
window[0][0][0][i] = window(i, vi.blocksizes[0], vi.blocksizes[0] / 2, vi.blocksizes[0] / 2);
|
||||
window[1][0][0][i] = window(i, vi.blocksizes[1], vi.blocksizes[0] / 2, vi.blocksizes[0] / 2);
|
||||
window[1][0][1][i] = window(i, vi.blocksizes[1], vi.blocksizes[0] / 2, vi.blocksizes[1] / 2);
|
||||
window[1][1][0][i] = window(i, vi.blocksizes[1], vi.blocksizes[1] / 2, vi.blocksizes[0] / 2);
|
||||
window[1][1][1][i] = window(i, vi.blocksizes[1], vi.blocksizes[1] / 2, vi.blocksizes[1] / 2);
|
||||
}
|
||||
|
||||
fullbooks = new CodeBook[vi.books];
|
||||
for (int i = 0; i < vi.books; i++) {
|
||||
fullbooks[i] = new CodeBook();
|
||||
fullbooks[i].init_decode(vi.book_param[i]);
|
||||
}
|
||||
|
||||
// initialize the storage vectors to a decent size greater than the
|
||||
// minimum
|
||||
|
||||
pcm_storage = 8192; // we'll assume later that we have
|
||||
// a minimum of twice the blocksize of
|
||||
// accumulated samples in analysis
|
||||
pcm = new float[vi.channels][];
|
||||
{
|
||||
for (int i = 0; i < vi.channels; i++) {
|
||||
pcm[i] = new float[pcm_storage];
|
||||
}
|
||||
}
|
||||
|
||||
// all 1 (large block) or 0 (small block)
|
||||
// explicitly set for the sake of clarity
|
||||
lW = 0; // previous window size
|
||||
W = 0; // current window size
|
||||
|
||||
// all vector indexes; multiples of samples_per_envelope_step
|
||||
centerW = vi.blocksizes[1] / 2;
|
||||
|
||||
pcm_current = centerW;
|
||||
|
||||
// initialize all the mapping/backend lookups
|
||||
mode = new Object[vi.modes];
|
||||
for (int i = 0; i < vi.modes; i++) {
|
||||
int mapnum = vi.mode_param[i].mapping;
|
||||
int maptype = vi.map_type[mapnum];
|
||||
mode[i] = FuncMapping.mapping_P[maptype].look(this, vi.mode_param[i], vi.map_param[mapnum]);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
public int synthesis_init(Info vi) {
|
||||
init(vi, false);
|
||||
// Adjust centerW to allow an easier mechanism for determining output
|
||||
pcm_returned = centerW;
|
||||
centerW -= vi.blocksizes[W] / 4 + vi.blocksizes[lW] / 4;
|
||||
granulepos = -1;
|
||||
sequence = -1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
DspState(Info vi) {
|
||||
this();
|
||||
init(vi, false);
|
||||
// Adjust centerW to allow an easier mechanism for determining output
|
||||
pcm_returned = centerW;
|
||||
centerW -= vi.blocksizes[W] / 4 + vi.blocksizes[lW] / 4;
|
||||
granulepos = -1;
|
||||
sequence = -1;
|
||||
}
|
||||
|
||||
// Unike in analysis, the window is only partially applied for each
|
||||
// block. The time domain envelope is not yet handled at the point of
|
||||
// calling (as it relies on the previous block).
|
||||
|
||||
public int synthesis_blockin(Block vb) {
|
||||
// Shift out any PCM/multipliers that we returned previously
|
||||
// centerW is currently the center of the last block added
|
||||
if (centerW > vi.blocksizes[1] / 2 && pcm_returned > 8192) {
|
||||
// don't shift too much; we need to have a minimum PCM buffer of
|
||||
// 1/2 long block
|
||||
|
||||
int shiftPCM = centerW - vi.blocksizes[1] / 2;
|
||||
shiftPCM = (pcm_returned < shiftPCM ? pcm_returned : shiftPCM);
|
||||
|
||||
pcm_current -= shiftPCM;
|
||||
centerW -= shiftPCM;
|
||||
pcm_returned -= shiftPCM;
|
||||
if (shiftPCM != 0) {
|
||||
for (int i = 0; i < vi.channels; i++) {
|
||||
System.arraycopy(pcm[i], shiftPCM, pcm[i], 0, pcm_current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lW = W;
|
||||
W = vb.W;
|
||||
nW = -1;
|
||||
|
||||
glue_bits += vb.glue_bits;
|
||||
time_bits += vb.time_bits;
|
||||
floor_bits += vb.floor_bits;
|
||||
res_bits += vb.res_bits;
|
||||
|
||||
if (sequence + 1 != vb.sequence)
|
||||
granulepos = -1; // out of sequence; lose count
|
||||
|
||||
sequence = vb.sequence;
|
||||
|
||||
{
|
||||
int sizeW = vi.blocksizes[W];
|
||||
int _centerW = centerW + vi.blocksizes[lW] / 4 + sizeW / 4;
|
||||
int beginW = _centerW - sizeW / 2;
|
||||
int endW = beginW + sizeW;
|
||||
int beginSl = 0;
|
||||
int endSl = 0;
|
||||
|
||||
// Do we have enough PCM/mult storage for the block?
|
||||
if (endW > pcm_storage) {
|
||||
// expand the storage
|
||||
pcm_storage = endW + vi.blocksizes[1];
|
||||
for (int i = 0; i < vi.channels; i++) {
|
||||
float[] foo = new float[pcm_storage];
|
||||
System.arraycopy(pcm[i], 0, foo, 0, pcm[i].length);
|
||||
pcm[i] = foo;
|
||||
}
|
||||
}
|
||||
|
||||
// overlap/add PCM
|
||||
switch (W) {
|
||||
case 0:
|
||||
beginSl = 0;
|
||||
endSl = vi.blocksizes[0] / 2;
|
||||
break;
|
||||
case 1:
|
||||
beginSl = vi.blocksizes[1] / 4 - vi.blocksizes[lW] / 4;
|
||||
endSl = beginSl + vi.blocksizes[lW] / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int j = 0; j < vi.channels; j++) {
|
||||
int _pcm = beginW;
|
||||
// the overlap/add section
|
||||
int i = 0;
|
||||
for (i = beginSl; i < endSl; i++) {
|
||||
pcm[j][_pcm + i] += vb.pcm[j][i];
|
||||
}
|
||||
// the remaining section
|
||||
for (; i < sizeW; i++) {
|
||||
pcm[j][_pcm + i] = vb.pcm[j][i];
|
||||
}
|
||||
}
|
||||
|
||||
// track the frame number... This is for convenience, but also
|
||||
// making sure our last packet doesn't end with added padding. If
|
||||
// the last packet is partial, the number of samples we'll have to
|
||||
// return will be past the vb->granulepos.
|
||||
//
|
||||
// This is not foolproof! It will be confused if we begin
|
||||
// decoding at the last page after a seek or hole. In that case,
|
||||
// we don't have a starting point to judge where the last frame
|
||||
// is. For this reason, vorbisfile will always try to make sure
|
||||
// it reads the last two marked pages in proper sequence
|
||||
|
||||
if (granulepos == -1) {
|
||||
granulepos = vb.granulepos;
|
||||
} else {
|
||||
granulepos += (_centerW - centerW);
|
||||
if (vb.granulepos != -1 && granulepos != vb.granulepos) {
|
||||
if (granulepos > vb.granulepos && vb.eofflag != 0) {
|
||||
// partial last frame. Strip the padding off
|
||||
_centerW -= (granulepos - vb.granulepos);
|
||||
} // else{ Shouldn't happen *unless* the bitstream is out of
|
||||
// spec. Either way, believe the bitstream }
|
||||
granulepos = vb.granulepos;
|
||||
}
|
||||
}
|
||||
|
||||
// Update, cleanup
|
||||
|
||||
centerW = _centerW;
|
||||
pcm_current = endW;
|
||||
if (vb.eofflag != 0)
|
||||
eofflag = 1;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
// pcm==NULL indicates we just want the pending samples, no more
|
||||
public int synthesis_pcmout(float[][][] _pcm, int[] index) {
|
||||
if (pcm_returned < centerW) {
|
||||
if (_pcm != null) {
|
||||
for (int i = 0; i < vi.channels; i++) {
|
||||
index[i] = pcm_returned;
|
||||
}
|
||||
_pcm[0] = pcm;
|
||||
}
|
||||
return (centerW - pcm_returned);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
public int synthesis_read(int bytes) {
|
||||
if (bytes != 0 && pcm_returned + bytes > centerW)
|
||||
return (-1);
|
||||
pcm_returned += bytes;
|
||||
return (0);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user