/*
* NellyMoser ASAO codec
* Copyright (C) 2007-2008 UAB "DKD"
* Copyright (C) 2007-2008 Joseph Artsimovich <jart@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package lt.dkd.nellymoser;
public class CodecImpl {
private static class BitStream {
private int byteOffset = 0;
private int bitOffset = 0;
public void push(int val, int len, byte[] buf) {
if (bitOffset == 0) {
buf[byteOffset] = (byte)val;
} else {
buf[byteOffset] |= (byte)(val << bitOffset);
}
bitOffset += len;
if (bitOffset >= 8) {
++byteOffset;
bitOffset -= 8;
if (bitOffset > 0) {
buf[byteOffset] = (byte)(val >> (len - bitOffset));
}
}
}
public int pop(int len, byte[] buf) {
int val = ((int)buf[byteOffset] & 0xff) >> bitOffset;
final int bits_read = 8 - bitOffset;
if (len >= bits_read) {
++byteOffset;
if (len > bits_read) {
val |= buf[byteOffset] << bits_read;
}
}
bitOffset = (bitOffset + len) & 7;
return val & ((1 << len) - 1);
}
}
private static class NormalizedInt32 {
public final int value;
public final int scale;
public NormalizedInt32(final int val) {
if (val == 0) {
value = val;
scale = 31;
return;
} else if (val >= (1 << 30)) {
value = 0;
scale = 0;
return;
}
int v = val;
int s = 0;
if (v > 0) {
do {
v <<= 1;
++s;
} while (v < (1 << 30));
} else {
final int floor = 1 << 31; // lowest possible 32bit value
do {
v <<= 1;
++s;
} while (v > floor + (1 << 30));
}
value = v;
scale = s;
}
}
private static class Factor {
public final int value;
public final int shift;
public Factor(final int val) {
if (val == 124) {
// Common case optimization.
value = 4228;
shift = 19;
return;
} else if (val == 0) {
value = 0;
shift = 0;
return;
}
final int sign = ((~val >>> 31) << 1) - 1;
int abs = val * sign;
int scale = -1;
while ((abs & (1 << 15)) == 0) {
abs <<= 1;
++scale;
}
abs >>= 1;
shift = 27 - scale;
final int table_val = table9[(abs - 0x3e00) >> 10];
int tmp = abs * table_val;
tmp = (1 << 30) - tmp;
tmp += (1 << 14);
tmp >>= 15;
tmp *= table_val;
tmp += (1 << 14);
tmp >>= 15;
final int tmp2 = tmp;
tmp *= abs;
tmp = (1 << 29) - tmp;
tmp += (1 << 14);
tmp >>= 15;
tmp *= tmp2;
tmp += (1 << 13);
tmp >>= 14;
tmp *= sign;
if (tmp > 32767 && sign == 1) {
tmp = 32767;
} else if (tmp < -32768 && sign == -1) {
tmp = -32768;
}
value = tmp;
}
}
public static void encode(float[] state, float[] in, byte[] out) {
float var_8d8[] = new float[256];
float var_2e8[] = new float[23];
float var_268[] = new float[23];
float var_4d8[] = new float[124];
float var_208[] = new float[124];
final BitStream bs = new BitStream();
fTransfm(state, in, 0, 7, var_8d8, 0);
fTransfm(state, in, 128, 7, var_8d8, 128);
for (int i = 0; i < 23; ++i) {
int bound = bandBound[i];
final int next_bound = bandBound[i + 1];
double acc = 0.0;
for (; bound < next_bound; ++bound) {
final double a = var_8d8[bound];
final double b = var_8d8[bound + 128];
acc += a*a + b*b;
}
final double tmp = Math.max(1.0, acc / (table0[i] << 1));
var_2e8[i] = Math.round(Math.log(tmp) * (1.44269502 * 1024.0));
};
int idx = findClosest(var_2e8[0], table1, 0, 64);
var_268[0] = table1[idx];
bs.push(idx, gainBit[0], out);
for (int i = 1; i < 23; ++i) {
idx = findClosest(var_2e8[i] - var_268[i - 1], table2, 0, 32);
var_268[i] = var_268[i - 1] + table2[idx];
bs.push(idx, gainBit[i], out);
}
for (int i = 0; i < 23; ++i) {
var_2e8[i] = (float)(1.0 / Math.pow(2.0, var_268[i] * (0.5 * 0.0009765625)));
}
for (int i = 0; i < 23; ++i) {
int bound = bandBound[i];
final int next_bound = bandBound[i + 1];
for (; bound < next_bound; ++bound) {
var_4d8[bound] = var_268[i];
var_208[bound] = var_2e8[i];
}
}
int packed_byte_sizes[] = new int[124];
final int leftover = wc(var_4d8, 124, 198, packed_byte_sizes);
for (int off = 0; off < 256; off += 128) {
for (int i = 0; i < 124; ++i) {
final int packedSize = packed_byte_sizes[i];
if (packedSize > 0) {
final int pow2 = 1 << packedSize;
idx = findClosestOrdered(
var_208[i] * var_8d8[off + i],
table3, pow2 - 1, (pow2 << 1) - 1
);
bs.push(idx, packedSize, out);
}
}
for (int i = leftover; i > 0; i -= 8) {
if (i > 8) {
bs.push(0, 8, out);
} else {
bs.push(0, i, out);
break;
}
}
}
}
public static void decode(float[] state, byte[] in, float[] out) {
byte[] unpacked_input = new byte[124];
float[] var_808 = new float[128];
float[] var_608 = new float[124];
float[] var_418 = new float[124];
BitStream bs = new BitStream();
int unpacked_byte = bs.pop(gainBit[0], in);
unpacked_input[0] = (byte)unpacked_byte;
var_808[0] = table1[unpacked_byte];
for (int i = 1; i < 23; ++i) {
unpacked_byte = bs.pop(gainBit[i], in);
unpacked_input[i] = (byte)unpacked_byte;
var_808[i] = var_808[i - 1] + table2[unpacked_byte];
};
for (int i = 0; i < 23; ++i) {
final float pow = (float)Math.pow(
2.0, var_808[i] * (0.5 * 0.0009765625)
);
int bound = bandBound[i];
final int next_bound = bandBound[i + 1];
for (; bound < next_bound; ++bound) {
var_418[bound] = var_808[i];
var_608[bound] = pow;
}
}
int packed_byte_sizes[] = new int[124];
final int leftover = wc(var_418, 124, 198, packed_byte_sizes);
for (int out_off = 0; out_off < 256; out_off += 128) {
for (int i = 0; i < 124; ++i) {
final int packed_size = packed_byte_sizes[i];
float val = var_608[i];
if (packed_size > 0) {
final int pow2 = 1 << packed_size;
unpacked_byte = bs.pop(packed_size, in);
unpacked_input[i] = (byte)unpacked_byte;
val *= table3[pow2 - 1 + unpacked_byte];
} else {
final double rnd_u32 = Math.random() * 4294967296.0;
if (rnd_u32 < (1<<30) + (1<<14)) {
val *= -0.707099974;
} else {
val *= 0.707099974;
}
}
var_808[i] = val;
}
for (int i = 124; i < 128; ++i) {
var_808[i] = 0;
}
for (int i = leftover; i > 0; i -= 8) {
if (i > 8) {
bs.pop(8, in);
} else {
bs.pop(i, in);
break;
}
}
iTransfm(state, var_808, 7, out, out_off);
}
}
private static void iTransfm(float[] state, float[] in,
int len_log2, float[] out, int out_off) {
final int len = 1 << len_log2;
final int quarter_len = len >> 2;
int y = len - 1;
int x = len >> 1;
int j = x - 1;
int i = 0;
/*
i--> <--j
----------------------------
x--> <--y
i, j, x, y are indexes into table7.
table7 is defined as follows:
for (int i = 0; i < 128; ++i) {
table7[i] = Math.sin((i + 0.5) / 128 * (Math.PI / 2));
}
*/
auxceps(in, 0, len_log2, out, out_off);
for (; i < quarter_len; ++i, --j, ++x, --y) {
final double state_i = state[i];
final double state_j = state[j];
final double out_x = out[out_off + x];
final double out_y = out[out_off + y];
state[i] = -out[out_off + j];
state[j] = -out[out_off + i];
out[out_off + i] = (float)(state_i * table7[y] + out_x * table7[i]);
out[out_off + j] = (float)(state_j * table7[x] + out_y * table7[j]);
out[out_off + x] = (float)(table7[x] * -out_y + table7[j] * state_j);
out[out_off + y] = (float)(table7[y] * -out_x + table7[i] * state_i);
}
}
private static void fTransfm(float[] state, float[] in, int in_off,
int len_log2, float[] out, int out_off) {
final int len = 1 << len_log2;
final int quarter_len = len >> 2;
int y = len - 1;
int x = len >> 1;
int j = x - 1;
int i = 0;
/*
i--> <--j
----------------------------
x--> <--y
i, j, x, y are indexes into table7.
table7 is defined as follows:
for (int i = 0; i < 128; ++i) {
table7[i] = Math.sin((i + 0.5) / 128 * (Math.PI / 2));
}
*/
for (; i < quarter_len; ++i, ++x, --y, --j) {
out[out_off + x] = state[i];
out[out_off + y] = state[j];
out[out_off + i] = -in[in_off + j] * table7[x] - in[in_off + x] * table7[j];
out[out_off + j] = -in[in_off + y] * table7[i] - in[in_off + i] * table7[y];
state[i] = in[in_off + i] * table7[i] - in[in_off + y] * table7[y];
state[j] = in[in_off + j] * table7[j] - in[in_off + x] * table7[x];
}
auxceps(out, out_off, len_log2, out, out_off);
}
private static void auxceps(
float[] in, final int in_off, int len_log2, float[] out, final int out_off) {
final int len = 1 << len_log2;
final int half_len_m1 = (len >> 1) - 1;
final int quarter_len = len >> 2;
for (int i = 0; i < quarter_len; ++i) {
final int i2 = i << 1;
final int j = len - 1 - i2;
final int k = j - 1;
final double in_i2 = in[in_off + i2];
final double in_i2_1 = in[in_off + i2 + 1];
final double in_j = in[in_off + j];
final double in_k = in[in_off + k];
out[out_off + i2] = (float)(table4[i] * in_i2 - table6[i] * in_j);
out[out_off + i2 + 1] = (float)(in_j * table4[i] + in_i2 * table6[i]);
out[out_off + k] = (float)(table4[half_len_m1 - i] * in_k - table6[half_len_m1 - i] * in_i2_1);
out[out_off + j] = (float)(in_i2_1 * table4[half_len_m1 - i] + in_k * table6[half_len_m1 - i]);
}
HarXfm(out, out_off, len_log2 - 1);
final float last_out = out[out_off + len - 1];
final float pre_last_out = out[out_off + len - 2];
out[out_off] = table5[0] * out[out_off];
out[out_off + len - 1] = out[out_off + 1] * -table5[0];
out[out_off + len - 2] = table5[half_len_m1] * out[out_off + len - 2] + table5[1] * last_out;
out[out_off + 1] = pre_last_out * table5[1] - last_out * table5[half_len_m1];
int i_out = len - 3;
int i_tbl = half_len_m1;
int j = 3;
for (int i = 1; i < quarter_len; ++i, --i_tbl, i_out -= 2, j += 2) {
final double old_out_a = out[out_off + i_out];
final double old_out_b = out[out_off + i_out - 1];
final double old_out_c = out[out_off + j];
final double old_out_d = out[out_off + j - 1];
out[out_off + j - 1] = (float)(table5[i_tbl] * old_out_c + table5[(j - 1) >> 1] * old_out_d);
out[out_off + j] = (float)(old_out_b * table5[(j + 1) >> 1] - old_out_a * table5[i_tbl - 1]);
out[out_off + i_out] = (float)(old_out_d * table5[i_tbl] - old_out_c * table5[(j - 1) >> 1]);
out[out_off + i_out - 1] = (float)(table5[(j + 1) >> 1] * old_out_a + table5[i_tbl - 1] * old_out_b);
}
}
private static void HarXfm(float[] data, int data_off, int half_len_log2) {
final int half_len = 1 << half_len_log2;
HarXfmHelper(data, data_off, half_len);
int j = 0;
for (int i = half_len >> 1; i > 0; --i, j += 4) {
final float j0 = data[data_off + j];
final float j1 = data[data_off + j + 1];
final float j2 = data[data_off + j + 2];
final float j3 = data[data_off + j + 3];
data[data_off + j] = j0 + j2;
data[data_off + j + 1] = j1 + j3;
data[data_off + j + 2] = j0 - j2;
data[data_off + j + 3] = j1 - j3;
}
j = 0;
for (int i = half_len >> 2; i > 0; --i, j += 8) {
final float j0 = data[data_off + j];
final float j1 = data[data_off + j + 1];
final float j2 = data[data_off + j + 2];
final float j3 = data[data_off + j + 3];
final float j4 = data[data_off + j + 4];
final float j5 = data[data_off + j + 5];
final float j6 = data[data_off + j + 6];
final float j7 = data[data_off + j + 7];
data[data_off + j] = j0 + j4;
data[data_off + j + 1] = j1 + j5;
data[data_off + j + 2] = j2 + j7;
data[data_off + j + 3] = j3 - j6;
data[data_off + j + 4] = j0 - j4;
data[data_off + j + 5] = j1 - j5;
data[data_off + j + 6] = j2 - j7;
data[data_off + j + 7] = j3 + j6;
}
int i = 0;
int x = half_len >> 3;
int y = 64;
int z = 4;
for (int idx1 = half_len_log2 - 2; idx1 > 0; --idx1, z <<= 1, y >>= 1, x >>= 1) {
j = 0;
for (int idx2 = x; idx2 != 0; --idx2, j += z << 1) {
for (int idx3 = z >> 1; idx3 > 0; --idx3, j += 2, i += y) {
final int k = j + (z << 1);
final double j0 = data[data_off + j];
final double j1 = data[data_off + j + 1];
final double k0 = data[data_off + k];
final double k1 = data[data_off + k + 1];
data[data_off + k] = (float)(j0 - (k0 * table10[128 - i] + k1 * table10[i]));
data[data_off + j] = (float)(j0 + (k0 * table10[128 - i] + k1 * table10[i]));
data[data_off + k + 1] = (float)(j1 + (k0 * table10[i] - k1 * table10[128 - i]));
data[data_off + j + 1] = (float)(j1 - (k0 * table10[i] - k1 * table10[128 - i]));
}
for (int idx4 = z >> 1; idx4 > 0; --idx4, j += 2, i -= y) {
final int k = j + (z << 1);
final double j0 = data[data_off + j];
final double j1 = data[data_off + j + 1];
final double k0 = data[data_off + k];
final double k1 = data[data_off + k + 1];
data[data_off + k] = (float)(j0 + (k0 * table10[128 - i] - k1 * table10[i]));
data[data_off + j] = (float)(j0 - (k0 * table10[128 - i] - k1 * table10[i]));
data[data_off + k + 1] = (float)(j1 + (k1 * table10[128 - i] + k0 * table10[i]));
data[data_off + j + 1] = (float)(j1 - (k1 * table10[128 - i] + k0 * table10[i]));
}
}
}
}
private static void HarXfmHelper(float[] data, int data_off, int half_len) {
final int len = half_len << 1;
int j = 1;
for (int i = 1; i < len; i += 2) {
if (i < j) {
final float tmp1 = data[data_off + i];
data[data_off + i] = data[data_off + j];
data[data_off + j] = tmp1;
final float tmp2 = data[data_off + i - 1];
data[data_off + i - 1] = data[data_off + j - 1];
data[data_off + j - 1] = tmp2;
}
int x = half_len;
while (x > 1 && x < j) {
j -= x;
x >>= 1;
}
j += x;
}
}
private static int findClosest(float target, float[] values, int from, int to) {
int min_idx = 0;
float min_distance = Math.abs(target - values[from]);
for (int i = from; i < to; ++i) {
final float distance = Math.abs(target - values[i]);
if (distance < min_distance) {
min_distance = distance;
min_idx = i - from;
}
}
return min_idx;
}
private static int findClosestOrdered(float target, float[] values, int from, int to) {
int begin = from;
int end = to;
do {
final int middle = (begin + end) >> 1;
if (target > values[middle]) {
begin = middle;
} else {
end = middle;
}
} while (end - begin > 1);
if (end != to) {
if (target - values[begin] > values[end] - target) {
begin = end;
}
}
return begin - from;
}
static int wc(float[] in, int len, int total_bits, int[] packed_sizes) {
float max_input = 0;
for (int i = 0; i < len; ++i) {
if (in[i] > max_input) {
max_input = in[i];
}
}
int max_input_scale = 0;
{
NormalizedInt32 normalized = new NormalizedInt32((int)max_input);
max_input_scale = normalized.scale - 16;
}
short scaled_input[] = new short[124];
if (max_input_scale < 0) {
for (int i = 0; i < len; ++i) {
scaled_input[i] = (short)((int)in[i] >> -max_input_scale);
}
} else {
for (int i = 0; i < len; ++i) {
scaled_input[i] = (short)((int)in[i] << max_input_scale);
}
}
final Factor factor = new Factor(len);
for (int i = 0; i < len; ++i) {
scaled_input[i] = (short)(((int)scaled_input[i] * 3) >> 2); // *= 0.75
}
int scaled_input_sum = 0;
for (int i = 0; i < len; ++i) {
scaled_input_sum += scaled_input[i];
}
max_input_scale += 11;
scaled_input_sum -= total_bits << max_input_scale;
int scaled_input_base = 0;
{
final int val = scaled_input_sum - (total_bits << max_input_scale);
final NormalizedInt32 normalized = new NormalizedInt32(val);
scaled_input_base = ((val >> 16) * factor.value) >> 15;
final int shift = 31 - factor.shift - normalized.scale;
if (shift >= 0) {
scaled_input_base <<= shift;
} else {
scaled_input_base >>= -shift;
}
}
int bits_used = getD(scaled_input, max_input_scale, len, 6, scaled_input_base);
if (bits_used != total_bits) {
int diff = bits_used - total_bits;
int diff_scale = 0;
if (diff <= 0) {
for (; diff >= -16384; diff <<= 1) {
++diff_scale;
}
} else {
for (; diff < 16384; diff <<= 1) {
++diff_scale;
}
}
int base_delta = (diff * factor.value) >> 15;
diff_scale = max_input_scale - (factor.shift + diff_scale - 15);
if (diff_scale >= 0) {
base_delta <<= diff_scale;
} else {
base_delta >>= -diff_scale;
}
int num_revisions = 1;
int last_bits_used;
int last_scaled_input_base;
for (;;) {
last_bits_used = bits_used;
last_scaled_input_base = scaled_input_base;
scaled_input_base += base_delta;
bits_used = getD(scaled_input, max_input_scale, len, 6, scaled_input_base);
if (++num_revisions > 19) {
break;
}
if ((bits_used - total_bits) * (last_bits_used - total_bits) <= 0) {
break;
}
}
if (bits_used != total_bits) {
int scaled_input_base_1;
int bits_used_1;
int bits_used_2;
if (bits_used > total_bits) {
scaled_input_base_1 = scaled_input_base;
scaled_input_base = last_scaled_input_base;
bits_used_1 = bits_used;
bits_used_2 = last_bits_used;
} else {
scaled_input_base_1 = last_scaled_input_base;
bits_used_1 = last_bits_used;
bits_used_2 = bits_used;
}
while (bits_used != total_bits && num_revisions < 20) {
final int avg = (scaled_input_base + scaled_input_base_1) >> 1;
bits_used = getD(scaled_input, max_input_scale, len, 6, avg);
++num_revisions;
if (bits_used > total_bits) {
scaled_input_base_1 = avg;
bits_used_1 = bits_used;
} else {
scaled_input_base = avg;
bits_used_2 = bits_used;
}
}
final int dev_1 = Math.abs((int)bits_used_1 - total_bits);
final int dev_2 = Math.abs((int)bits_used_2 - total_bits);
if (dev_1 < dev_2) {
scaled_input_base = scaled_input_base_1;
bits_used = bits_used_1;
} else {
bits_used = bits_used_2;
}
}
}
for (int i = 0; i < len; ++i) {
int tmp = (int)scaled_input[i] - scaled_input_base;
if (tmp >= 0) {
tmp = (tmp + (1 << (max_input_scale - 1))) >> max_input_scale;
} else {
tmp = 0;
}
packed_sizes[i] = Math.min(tmp, 6);
}
if (bits_used > total_bits) {
int i = 0;
int bit_count = 0;
for (; bit_count < total_bits; ++i) {
bit_count += packed_sizes[i];
}
bit_count -= packed_sizes[i - 1];
packed_sizes[i - 1] = total_bits - bit_count;
bits_used = total_bits;
for (; i < len; ++i) {
packed_sizes[i] = 0;
}
}
return total_bits - bits_used;
}
private static int getD(short[] in, int scale, int len, int upper_bound, int base) {
int d = 0;
if (len <= 0) {
return d;
}
final int var_1 = 1 << (scale - 1);
for (int i = 0; i < len; ++i) {
int var_2 = (int)in[i] - base;
if (var_2 < 0) {
var_2 = 0;
} else {
var_2 = (var_2 + var_1) >> scale;
}
d += Math.min(var_2, upper_bound);
}
return d;
}
private static final int bandBound[] = {
0, 2, 4, 6,
8, 10, 12, 14,
16, 18, 21, 24,
28, 32, 37, 43,
49, 56, 64, 73,
83, 95, 109, 124
};
private static final short gainBit[] = {
6, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
private static final int table0[] = {
2, 2, 2, 2,
2, 2, 2, 2,
2, 3, 3, 4,
4, 5, 6, 6,
7, 8, 9, 10,
12, 14, 15, 0
};
private static final float table1[] = {
3134, 5342, 6870, 7792,
8569, 9185, 9744, 10191,
10631, 11061, 11434, 11770,
12116, 12513, 12925, 13300,
13674, 14027, 14352, 14716,
15117, 15477, 15824, 16157,
16513, 16804, 17090, 17401,
17679, 17948, 18238, 18520,
18764, 19078, 19381, 19640,
19921, 20205, 20500, 20813,
21162, 21465, 21794, 22137,
22453, 22756, 23067, 23350,
23636, 23926, 24227, 24521,
24819, 25107, 25414, 25730,
26120, 26497, 26895, 27344,
27877, 28463, 29426, 31355
};
private static final float table2[] = {
-11725, -9420, -7910, -6801,
-5948, -5233, -4599, -4039,
-3507, -3030, -2596, -2170,
-1774, -1383, -1016, -660,
-329, -1, 337, 696,
1085, 1512, 1962, 2433,
2968, 3569, 4314, 5279,
6622, 8154, 10076, 12975
};
private static final float table3[] = {
0.0f, -0.847256005f, 0.722470999f, -1.52474797f,
-0.453148007f, 0.375360996f, 1.47178996f, -1.98225796f,
-1.19293797f, -0.582937002f, -0.0693780035f, 0.390956998f,
0.906920016f, 1.486274f, 2.22154093f, -2.38878703f,
-1.80675399f, -1.41054201f, -1.07736099f, -0.799501002f,
-0.555810988f, -0.333402008f, -0.132449001f, 0.0568020009f,
0.254877001f, 0.477355003f, 0.738685012f, 1.04430604f,
1.39544594f, 1.80987501f, 2.39187598f, -2.38938308f,
-1.98846805f, -1.75140405f, -1.56431198f, -1.39221299f,
-1.216465f, -1.04694998f, -0.890510023f, -0.764558017f,
-0.645457983f, -0.52592802f, -0.405954987f, -0.302971989f,
-0.209690005f, -0.123986997f, -0.0479229987f, 0.025773f,
0.100134f, 0.173718005f, 0.258554012f, 0.352290004f,
0.456988007f, 0.576775014f, 0.700316012f, 0.842552006f,
1.00938797f, 1.18213499f, 1.35345602f, 1.53208196f,
1.73326194f, 1.97223496f, 2.39781404f, -2.5756309f,
-2.05733204f, -1.89849198f, -1.77278101f, -1.66626f,
-1.57421803f, -1.49933195f, -1.43166399f, -1.36522806f,
-1.30009902f, -1.22809303f, -1.15885794f, -1.09212506f,
-1.013574f, -0.920284986f, -0.828705013f, -0.737488985f,
-0.644775987f, -0.559094012f, -0.485713989f, -0.411031991f,
-0.345970005f, -0.285115987f, -0.234162003f, -0.187058002f,
-0.144250005f, -0.110716999f, -0.0739680007f, -0.0365610011f,
-0.00732900016f, 0.0203610007f, 0.0479039997f, 0.0751969963f,
0.0980999991f, 0.122038998f, 0.145899996f, 0.169434994f,
0.197045997f, 0.225243002f, 0.255686998f, 0.287010014f,
0.319709986f, 0.352582991f, 0.388906986f, 0.433492005f,
0.476945996f, 0.520482004f, 0.564453006f, 0.612204015f,
0.668592989f, 0.734165013f, 0.803215981f, 0.878404021f,
0.956620991f, 1.03970695f, 1.12937701f, 1.22111595f,
1.30802798f, 1.40248001f, 1.50568199f, 1.62277305f,
1.77249599f, 1.94308805f, 2.29039311f, 0.0f
};
/**
* Lookup table.
* <pre>
* for (int i = 0; i < 64; ++i) {
* table4[i] = Math.cos((i + 0.25) / 64 * (Math.PI / 2));
* }
* </pre>
*/
private static final float table4[] = {
0.999981225f, 0.999529421f, 0.998475611f, 0.996820271f,
0.994564593f, 0.991709828f, 0.988257587f, 0.984210074f,
0.979569793f, 0.974339426f, 0.968522072f, 0.962121427f,
0.955141187f, 0.947585583f, 0.939459205f, 0.930767f,
0.921513975f, 0.911705971f, 0.901348829f, 0.890448689f,
0.879012227f, 0.867046177f, 0.854557991f, 0.841554999f,
0.828045011f, 0.81403631f, 0.799537301f, 0.784556627f,
0.769103289f, 0.753186822f, 0.736816585f, 0.720002472f,
0.702754676f, 0.685083687f, 0.666999876f, 0.64851439f,
0.629638195f, 0.610382795f, 0.590759695f, 0.570780694f,
0.550458014f, 0.529803574f, 0.50883007f, 0.487550199f,
0.465976506f, 0.444122106f, 0.422000289f, 0.399624199f,
0.377007395f, 0.354163498f, 0.331106305f, 0.307849586f,
0.284407496f, 0.260794103f, 0.237023607f, 0.213110298f,
0.189068705f, 0.164913103f, 0.1406582f, 0.116318598f,
0.0919089988f, 0.0674438998f, 0.0429382995f, 0.0184067003f
};
/**
* Lookup table.
* <pre>
* for (int i = 0; i < 64; ++i) {
* table5[i] = Math.cos(i / 64.0 * (Math.PI / 2)) * Math.sqrt(2.0 / 128);
* }
* </pre>
*/
private static final float table5[] = {
0.125f, 0.124962397f, 0.124849401f, 0.124661297f,
0.124398097f, 0.124059901f, 0.123647101f, 0.123159699f,
0.122598201f, 0.121962801f, 0.1212539f, 0.120471999f,
0.119617499f, 0.118690997f, 0.117693f, 0.116624102f,
0.115484901f, 0.114276201f, 0.112998702f, 0.111653f,
0.110240199f, 0.108760901f, 0.107216097f, 0.105606697f,
0.103933699f, 0.102198102f, 0.100400902f, 0.0985433012f,
0.0966262966f, 0.094651103f, 0.0926188976f, 0.0905309021f,
0.0883883014f, 0.0861926004f, 0.0839449018f, 0.0816465989f,
0.0792991966f, 0.076903902f, 0.0744623989f, 0.0719759986f,
0.069446303f, 0.0668746978f, 0.0642627999f, 0.0616123006f,
0.0589246005f, 0.0562013984f, 0.0534444004f, 0.0506552011f,
0.0478353985f, 0.0449868999f, 0.0421111993f, 0.0392102003f,
0.0362856016f, 0.0333391018f, 0.0303725004f, 0.0273876991f,
0.0243862998f, 0.0213702004f, 0.0183412991f, 0.0153013002f,
0.0122520998f, 0.0091955997f, 0.00613350002f, 0.00306769996f
};
/**
* Lookup table.
* <pre>
* for (int i = 0; i < 64; ++i) {
* table6[i] = -Math.sin((i + 0.25) / 64 * (Math.PI / 2));
* }
* </pre>
*/
private static final float table6[] = {
-0.00613590004f,-0.0306748003f, -0.0551952012f, -0.0796824023f,
-0.104121603f, -0.128498107f, -0.152797207f, -0.177004203f,
-0.201104596f, -0.225083902f, -0.248927593f, -0.272621393f,
-0.296150893f, -0.319501996f, -0.342660695f, -0.365613014f,
-0.388345003f, -0.410843194f, -0.433093786f, -0.455083609f,
-0.47679919f, -0.498227686f, -0.519356012f, -0.540171504f,
-0.560661614f, -0.580814004f, -0.600616515f, -0.620057225f,
-0.639124393f, -0.657806695f, -0.676092684f, -0.693971515f,
-0.711432219f, -0.728464425f, -0.745057821f, -0.761202395f,
-0.77688849f, -0.792106628f, -0.806847572f, -0.8211025f,
-0.834862888f, -0.848120272f, -0.860866904f, -0.873094976f,
-0.884797096f, -0.895966172f, -0.906595707f, -0.916679084f,
-0.926210225f, -0.935183525f, -0.943593502f, -0.95143503f,
-0.958703518f, -0.965394378f, -0.971503913f, -0.977028072f,
-0.981963873f, -0.986308098f, -0.990058184f, -0.993211925f,
-0.995767415f, -0.997723103f, -0.999077678f, -0.999830604f
};
/**
* Lookup table.
* <pre>
* for (int i = 0; i < 128; ++i) {
* table7[i] = Math.sin((i + 0.5) / 128 * (Math.PI / 2));
* }
* </pre>
*/
private static final float table7[] = {
0.00613590004f, 0.0184067003f, 0.0306748003f, 0.0429382995f,
0.0551952012f, 0.0674438998f, 0.0796824023f, 0.0919089988f,
0.104121603f, 0.116318598f, 0.128498107f, 0.1406582f,
0.152797207f, 0.164913103f, 0.177004203f, 0.189068705f,
0.201104596f, 0.213110298f, 0.225083902f, 0.237023607f,
0.248927593f, 0.260794103f, 0.272621393f, 0.284407496f,
0.296150893f, 0.307849586f, 0.319501996f, 0.331106305f,
0.342660695f, 0.354163498f, 0.365613014f, 0.377007395f,
0.388345003f, 0.399624199f, 0.410843194f, 0.422000289f,
0.433093786f, 0.444122106f, 0.455083609f, 0.465976506f,
0.47679919f, 0.487550199f, 0.498227686f, 0.50883007f,
0.519356012f, 0.529803574f, 0.540171504f, 0.550458014f,
0.560661614f, 0.570780694f, 0.580814004f, 0.590759695f,
0.600616515f, 0.610382795f, 0.620057225f, 0.629638195f,
0.639124393f, 0.64851439f, 0.657806695f, 0.666999876f,
0.676092684f, 0.685083687f, 0.693971515f, 0.702754676f,
0.711432219f, 0.720002472f, 0.728464425f, 0.736816585f,
0.745057821f, 0.753186822f, 0.761202395f, 0.769103289f,
0.77688849f, 0.784556627f, 0.792106628f, 0.799537301f,
0.806847572f, 0.81403631f, 0.8211025f, 0.828045011f,
0.834862888f, 0.841554999f, 0.848120272f, 0.854557991f,
0.860866904f, 0.867046177f, 0.873094976f, 0.879012227f,
0.884797096f, 0.890448689f, 0.895966172f, 0.901348829f,
0.906595707f, 0.911705971f, 0.916679084f, 0.921513975f,
0.926210225f, 0.930767f, 0.935183525f, 0.939459205f,
0.943593502f, 0.947585583f, 0.95143503f, 0.955141187f,
0.958703518f, 0.962121427f, 0.965394378f, 0.968522072f,
0.971503913f, 0.974339426f, 0.977028072f, 0.979569793f,
0.981963873f, 0.984210074f, 0.986308098f, 0.988257587f,
0.990058184f, 0.991709828f, 0.993211925f, 0.994564593f,
0.995767415f, 0.996820271f, 0.997723103f, 0.998475611f,
0.999077678f, 0.999529421f, 0.999830604f, 0.999981225f
};
private static final short table9[] = {
32767, 30840, 29127, 27594, 26214, 24966, 23831, 22795,
21845, 20972, 20165, 19418, 18725, 18079, 17476, 16913,
16384, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
/**
* Lookup table.
* <pre>
* for (int i = 0; i <= 128; ++i) {
* table10[i] = Math.sin((i / 128.0) * (Math.PI / 2));
* }
* </pre>
*/
private static final float table10[] = {
0.0f, 0.0122715384f, 0.024541229f, 0.0368072242f,
0.0490676723f, 0.061320737f, 0.0735645667f, 0.0857973099f,
0.0980171412f, 0.110222213f, 0.122410677f, 0.134580716f,
0.146730468f, 0.158858135f, 0.170961887f, 0.183039889f,
0.195090324f, 0.207111374f, 0.219101235f, 0.231058106f,
0.242980182f, 0.254865646f, 0.266712755f, 0.27851969f,
0.290284693f, 0.302005947f, 0.313681751f, 0.32531029f,
0.336889863f, 0.348418683f, 0.359895051f, 0.371317178f,
0.382683426f, 0.393992037f, 0.405241311f, 0.416429549f,
0.427555084f, 0.438616246f, 0.449611336f, 0.460538715f,
0.471396744f, 0.482183784f, 0.492898196f, 0.50353837f,
0.514102757f, 0.524589658f, 0.534997642f, 0.545324981f,
0.555570245f, 0.565731823f, 0.575808167f, 0.585797846f,
0.59569931f, 0.605511069f, 0.615231574f, 0.624859512f,
0.634393275f, 0.643831551f, 0.653172851f, 0.662415802f,
0.671558976f, 0.680601001f, 0.689540565f, 0.698376238f,
0.707106769f, 0.715730846f, 0.724247098f, 0.732654274f,
0.740951121f, 0.749136388f, 0.757208824f, 0.765167296f,
0.773010433f, 0.780737221f, 0.78834641f, 0.795836926f,
0.803207517f, 0.81045723f, 0.817584813f, 0.824589312f,
0.831469595f, 0.838224709f, 0.84485358f, 0.851355195f,
0.857728601f, 0.863972843f, 0.870086968f, 0.876070082f,
0.881921232f, 0.887639642f, 0.893224299f, 0.898674488f,
0.903989315f, 0.909168005f, 0.914209783f, 0.919113874f,
0.923879504f, 0.928506076f, 0.932992816f, 0.937339008f,
0.941544056f, 0.945607305f, 0.949528158f, 0.953306019f,
0.956940353f, 0.960430503f, 0.963776052f, 0.966976464f,
0.970031261f, 0.972939968f, 0.975702107f, 0.97831738f,
0.980785251f, 0.983105481f, 0.985277653f, 0.987301409f,
0.989176512f, 0.990902662f, 0.992479503f, 0.993906975f,
0.99518472f, 0.996312618f, 0.997290432f, 0.998118103f,
0.99879545f, 0.999322355f, 0.999698818f, 0.999924719f,
1.0f
};
}