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; | |
class Mdct { | |
int n; | |
int log2n; | |
float[] trig; | |
int[] bitrev; | |
float scale; | |
void init(int n) { | |
bitrev = new int[n / 4]; | |
trig = new float[n + n / 4]; | |
log2n = (int) Math.rint(Math.log(n) / Math.log(2)); | |
this.n = n; | |
int AE = 0; | |
int AO = 1; | |
int BE = AE + n / 2; | |
int BO = BE + 1; | |
int CE = BE + n / 2; | |
int CO = CE + 1; | |
// trig lookups... | |
for (int i = 0; i < n / 4; i++) { | |
trig[AE + i * 2] = (float) Math.cos((Math.PI / n) * (4 * i)); | |
trig[AO + i * 2] = (float) -Math.sin((Math.PI / n) * (4 * i)); | |
trig[BE + i * 2] = (float) Math.cos((Math.PI / (2 * n)) * (2 * i + 1)); | |
trig[BO + i * 2] = (float) Math.sin((Math.PI / (2 * n)) * (2 * i + 1)); | |
} | |
for (int i = 0; i < n / 8; i++) { | |
trig[CE + i * 2] = (float) Math.cos((Math.PI / n) * (4 * i + 2)); | |
trig[CO + i * 2] = (float) -Math.sin((Math.PI / n) * (4 * i + 2)); | |
} | |
{ | |
int mask = (1 << (log2n - 1)) - 1; | |
int msb = 1 << (log2n - 2); | |
for (int i = 0; i < n / 8; i++) { | |
int acc = 0; | |
for (int j = 0; msb >>> j != 0; j++) | |
if (((msb >>> j) & i) != 0) | |
acc |= 1 << j; | |
bitrev[i * 2] = ((~acc) & mask); | |
// bitrev[i*2]=((~acc)&mask)-1; | |
bitrev[i * 2 + 1] = acc; | |
} | |
} | |
scale = 4.f / n; | |
} | |
void clear() { | |
} | |
void forward(float[] in, float[] out) { | |
} | |
float[] _x = new float[1024]; | |
float[] _w = new float[1024]; | |
synchronized void backward(float[] in, float[] out) { | |
if (_x.length < n / 2) { | |
_x = new float[n / 2]; | |
} | |
if (_w.length < n / 2) { | |
_w = new float[n / 2]; | |
} | |
float[] x = _x; | |
float[] w = _w; | |
int n2 = n >>> 1; | |
int n4 = n >>> 2; | |
int n8 = n >>> 3; | |
// rotate + step 1 | |
{ | |
int inO = 1; | |
int xO = 0; | |
int A = n2; | |
int i; | |
for (i = 0; i < n8; i++) { | |
A -= 2; | |
x[xO++] = -in[inO + 2] * trig[A + 1] - in[inO] * trig[A]; | |
x[xO++] = in[inO] * trig[A + 1] - in[inO + 2] * trig[A]; | |
inO += 4; | |
} | |
inO = n2 - 4; | |
for (i = 0; i < n8; i++) { | |
A -= 2; | |
x[xO++] = in[inO] * trig[A + 1] + in[inO + 2] * trig[A]; | |
x[xO++] = in[inO] * trig[A] - in[inO + 2] * trig[A + 1]; | |
inO -= 4; | |
} | |
} | |
float[] xxx = mdct_kernel(x, w, n, n2, n4, n8); | |
int xx = 0; | |
// step 8 | |
{ | |
int B = n2; | |
int o1 = n4, o2 = o1 - 1; | |
int o3 = n4 + n2, o4 = o3 - 1; | |
for (int i = 0; i < n4; i++) { | |
float temp1 = (xxx[xx] * trig[B + 1] - xxx[xx + 1] * trig[B]); | |
float temp2 = -(xxx[xx] * trig[B] + xxx[xx + 1] * trig[B + 1]); | |
out[o1] = -temp1; | |
out[o2] = temp1; | |
out[o3] = temp2; | |
out[o4] = temp2; | |
o1++; | |
o2--; | |
o3++; | |
o4--; | |
xx += 2; | |
B += 2; | |
} | |
} | |
} | |
private float[] mdct_kernel(float[] x, float[] w, int n, int n2, int n4, int n8) { | |
// step 2 | |
int xA = n4; | |
int xB = 0; | |
int w2 = n4; | |
int A = n2; | |
for (int i = 0; i < n4;) { | |
float x0 = x[xA] - x[xB]; | |
float x1; | |
w[w2 + i] = x[xA++] + x[xB++]; | |
x1 = x[xA] - x[xB]; | |
A -= 4; | |
w[i++] = x0 * trig[A] + x1 * trig[A + 1]; | |
w[i] = x1 * trig[A] - x0 * trig[A + 1]; | |
w[w2 + i] = x[xA++] + x[xB++]; | |
i++; | |
} | |
// step 3 | |
{ | |
for (int i = 0; i < log2n - 3; i++) { | |
int k0 = n >>> (i + 2); | |
int k1 = 1 << (i + 3); | |
int wbase = n2 - 2; | |
A = 0; | |
float[] temp; | |
for (int r = 0; r < (k0 >>> 2); r++) { | |
int w1 = wbase; | |
w2 = w1 - (k0 >> 1); | |
float AEv = trig[A], wA; | |
float AOv = trig[A + 1], wB; | |
wbase -= 2; | |
k0++; | |
for (int s = 0; s < (2 << i); s++) { | |
wB = w[w1] - w[w2]; | |
x[w1] = w[w1] + w[w2]; | |
wA = w[++w1] - w[++w2]; | |
x[w1] = w[w1] + w[w2]; | |
x[w2] = wA * AEv - wB * AOv; | |
x[w2 - 1] = wB * AEv + wA * AOv; | |
w1 -= k0; | |
w2 -= k0; | |
} | |
k0--; | |
A += k1; | |
} | |
temp = w; | |
w = x; | |
x = temp; | |
} | |
} | |
// step 4, 5, 6, 7 | |
{ | |
int C = n; | |
int bit = 0; | |
int x1 = 0; | |
int x2 = n2 - 1; | |
for (int i = 0; i < n8; i++) { | |
int t1 = bitrev[bit++]; | |
int t2 = bitrev[bit++]; | |
float wA = w[t1] - w[t2 + 1]; | |
float wB = w[t1 - 1] + w[t2]; | |
float wC = w[t1] + w[t2 + 1]; | |
float wD = w[t1 - 1] - w[t2]; | |
float wACE = wA * trig[C]; | |
float wBCE = wB * trig[C++]; | |
float wACO = wA * trig[C]; | |
float wBCO = wB * trig[C++]; | |
x[x1++] = (wC + wACO + wBCE) * .5f; | |
x[x2--] = (-wD + wBCO - wACE) * .5f; | |
x[x1++] = (wD + wBCO - wACE) * .5f; | |
x[x2--] = (wC - wACO - wBCE) * .5f; | |
} | |
} | |
return (x); | |
} | |
} | |