All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
de.jarnbjo.vorbis.MdctFloat Maven / Gradle / Ivy
/*
* $ProjectName$
* $ProjectRevision$
* -----------------------------------------------------------
* $Id: MdctFloat.java,v 1.3 2003/04/10 19:49:04 jarnbjo Exp $
* -----------------------------------------------------------
*
* $Author: jarnbjo $
*
* Description:
*
* Copyright 2002-2003 Tor-Einar Jarnbjo
* -----------------------------------------------------------
*
* Change History
* -----------------------------------------------------------
* $Log: MdctFloat.java,v $
* Revision 1.3 2003/04/10 19:49:04 jarnbjo
* no message
*
* Revision 1.2 2003/03/16 01:11:12 jarnbjo
* no message
*/
package de.jarnbjo.vorbis;
/**
* Implements the Modified Discrete Cosine Transform (MDCT) using
* single-precision floating-point arithmetic.
*/
class MdctFloat {
static private final float cPI3_8 = 0.38268343236508977175f;
static private final float cPI2_8 = 0.70710678118654752441f;
static private final float cPI1_8 = 0.92387953251128675613f;
final private int n;
final private int log2n;
final private float[] trig;
final private int[] bitrev;
private float[] equalizer;
final private float scale;
private int itmp1, itmp2, itmp3, itmp4, itmp5, itmp6, itmp7, itmp8, itmp9;
private float dtmp1, dtmp2, dtmp3, dtmp4, dtmp5, dtmp6, dtmp7, dtmp8, dtmp9;
protected MdctFloat(int n) {
bitrev = new int[n / 4];
trig = new float[n + n / 4];
int n2 = n >>> 1;
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 + 1] = acc;
}
}
scale = 4.f / n;
}
private float[] tmpX = new float[1024];
private float[] tmpW = new float[1024];
protected void setEqualizer(float[] equalizer) {
this.equalizer = equalizer;
}
protected float[] getEqualizer() {
return equalizer;
}
protected synchronized void imdct(
final float[] frq, final float[] window, final int[] pcm) {
//, float[] out){
float[] in = frq; //, out=buf;
if (tmpX.length < n / 2) {
tmpX = new float[n / 2];
}
if (tmpW.length < n / 2) {
tmpW = new float[n / 2];
}
final float[] x = tmpX;
final float[] w = tmpW;
int n2 = n >> 1;
int n4 = n >> 2;
int n8 = n >> 3;
if (equalizer != null) {
for (int i = 0; i < n; i++) {
frq[i] *= equalizer[i];
}
}
// rotate + step 1
{
int inO = -1;
int xO = 0;
int A = n2;
int i;
for (i = 0; i < n8; i++) {
dtmp1 = in[inO += 2];
dtmp2 = in[inO += 2];
dtmp3 = trig[--A];
dtmp4 = trig[--A];
x[xO++] = -dtmp2 * dtmp3 - dtmp1 * dtmp4;
x[xO++] = dtmp1 * dtmp3 - dtmp2 * dtmp4;
}
inO = n2; //-4;
for (i = 0; i < n8; i++) {
dtmp1 = in[inO -= 2];
dtmp2 = in[inO -= 2];
dtmp3 = trig[--A];
dtmp4 = trig[--A];
x[xO++] = dtmp2 * dtmp3 + dtmp1 * dtmp4;
x[xO++] = dtmp2 * dtmp4 - dtmp1 * dtmp3;
}
}
float[] xxx = 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++) {
dtmp1 = xxx[xx++];
dtmp2 = xxx[xx++];
dtmp3 = trig[B++];
dtmp4 = trig[B++];
float temp1 = (dtmp1 * dtmp4 - dtmp2 * dtmp3);
float temp2 = -(dtmp1 * dtmp3 + dtmp2 * dtmp4);
pcm[o1] = (int) (-temp1 * window[o1]);
pcm[o2] = (int) (temp1 * window[o2]);
pcm[o3] = (int) (temp2 * window[o3]);
pcm[o4] = (int) (temp2 * window[o4]);
o1++;
o2--;
o3++;
o4--;
}
}
}
private float[] 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++) {
dtmp1 = w[w1];
dtmp2 = w[w2];
wB = dtmp1 - dtmp2;
x[w1] = dtmp1 + dtmp2;
dtmp1 = w[++w1];
dtmp2 = w[++w2];
wA = dtmp1 - dtmp2;
x[w1] = dtmp1 + dtmp2;
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) * 16383.0f;
x[x2--] = (-wD + wBCO - wACE) * 16383.0f;
x[x1++] = (wD + wBCO - wACE) * 16383.0f;
x[x2--] = (wC - wACO - wBCE) * 16383.0f;
}
}
return x;
}
}