/* This file is part of jpcsp. Jpcsp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Jpcsp 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.media.codec.aac; import static jpcsp.media.codec.aac.AacSbrData.ff_sbr_noise_table; import org.apache.log4j.Logger; public class SBRDSP { private static Logger log = AacDecoder.log; public static void sum64x5(float z[], int o) { for (int k = 0; k < 64; k++) { float f = z[o + k] + z[o + k + 64] + z[o + k + 128] + z[o + k + 192] + z[o + k + 256]; z[o + k] = f; } } public static void qmfPreShuffle(float z[], int o) { z[o + 64] = z[o + 0]; z[o + 65] = z[o + 1]; for (int k = 1; k < 31; k += 2) { z[o + 64 + 2 * k + 0] = -z[o + 64 - k]; z[o + 64 + 2 * k + 1] = z[o + k + 1]; z[o + 64 + 2 * k + 2] = -z[o + 63 - k]; z[o + 64 + 2 * k + 3] = z[o + k + 2]; } z[o + 64 + 2 * 31 + 0] = -z[o + 64 - 31]; z[o + 64 + 2 * 31 + 1] = z[o + 31 + 1]; } public static void qmfPostShuffle(float W[][], float z[], int o) { for (int k = 0; k < 32; k += 2) { W[k ][0] = -z[o + 63 - k]; W[k ][1] = z[o + k + 0]; W[k + 1][0] = -z[o + 62 - k]; W[k + 1][1] = z[o + k + 1]; } } public static void autocorrelate(float x[][], float phi[][][]) { float real_sum2 = x[0][0] * x[2][0] + x[0][1] * x[2][1]; float imag_sum2 = x[0][0] * x[2][1] - x[0][1] * x[2][0]; float real_sum1 = 0.0f, imag_sum1 = 0.0f, real_sum0 = 0.0f; for (int i = 1; i < 38; i++) { real_sum0 += x[i][0] * x[i ][0] + x[i][1] * x[i ][1]; real_sum1 += x[i][0] * x[i + 1][0] + x[i][1] * x[i + 1][1]; imag_sum1 += x[i][0] * x[i + 1][1] - x[i][1] * x[i + 1][0]; real_sum2 += x[i][0] * x[i + 2][0] + x[i][1] * x[i + 2][1]; imag_sum2 += x[i][0] * x[i + 2][1] - x[i][1] * x[i + 2][0]; } phi[2 - 2][1][0] = real_sum2; phi[2 - 2][1][1] = imag_sum2; phi[2 ][1][0] = real_sum0 + x[ 0][0] * x[ 0][0] + x[ 0][1] * x[ 0][1]; phi[1 ][0][0] = real_sum0 + x[38][0] * x[38][0] + x[38][1] * x[38][1]; phi[2 - 1][1][0] = real_sum1 + x[ 0][0] * x[ 1][0] + x[ 0][1] * x[ 1][1]; phi[2 - 1][1][1] = imag_sum1 + x[ 0][0] * x[ 1][1] - x[ 0][1] * x[ 1][0]; phi[0 ][0][0] = real_sum1 + x[38][0] * x[39][0] + x[38][1] * x[39][1]; phi[0 ][0][1] = imag_sum1 + x[38][0] * x[39][1] - x[38][1] * x[39][0]; } public static void qmfDeintNeg(float v[], int vOffset, final float src[], int srcOffset) { for (int i = 0; i < 32; i++) { v[vOffset + i] = src[srcOffset + 63 - 2 * i ]; v[vOffset + 63 - i] = -src[srcOffset + 63 - 2 * i - 1]; } } public static void qmfDeintBfly(float v[], int vOffset, final float src0[], int src0Offset, final float src1[], int src1Offset) { for (int i = 0; i < 64; i++) { v[vOffset + i] = src0[src0Offset + i] - src1[src1Offset + 63 - i]; v[vOffset + 127 - i] = src0[src0Offset + i] + src1[src1Offset + 63 - i]; } } public static void negOdd64(float x[], int o) { for (int i = 1; i < 64; i += 4) { x[o + i + 0] = -x[o + i + 0]; x[o + i + 2] = -x[o + i + 2]; } } public static void hf_gen(float X_high[][], int XhighOffset, final float X_low[][], int XlowOffset, final float alpha0[], final float alpha1[], float bw, int start, int end) { final float alpha[] = new float[4]; alpha[0] = alpha1[0] * bw * bw; alpha[1] = alpha1[1] * bw * bw; alpha[2] = alpha0[0] * bw; alpha[3] = alpha0[1] * bw; for (int i = start; i < end; i++) { X_high[XhighOffset + i][0] = X_low[XlowOffset + i - 2][0] * alpha[0] - X_low[XlowOffset + i - 2][1] * alpha[1] + X_low[XlowOffset + i - 1][0] * alpha[2] - X_low[XlowOffset + i - 1][1] * alpha[3] + X_low[XlowOffset + i][0]; X_high[XhighOffset + i][1] = X_low[XlowOffset + i - 2][1] * alpha[0] + X_low[XlowOffset + i - 2][0] * alpha[1] + X_low[XlowOffset + i - 1][1] * alpha[2] + X_low[XlowOffset + i - 1][0] * alpha[3] + X_low[XlowOffset + i][1]; } } public static float sum_square(float x[][], int o, int n) { float sum0 = 0.0f, sum1 = 0.0f; for (int i = 0; i < n; i += 2) { sum0 += x[o + i + 0][0] * x[o + i + 0][0]; sum1 += x[o + i + 0][1] * x[o + i + 0][1]; sum0 += x[o + i + 1][0] * x[o + i + 1][0]; sum1 += x[o + i + 1][1] * x[o + i + 1][1]; } return sum0 + sum1; } public static void hfGFilt(float Y[][], int Yoffset, final float Xhigh[][][], int Xoffset, final float gFilt[], int mMax, int ixh) { for (int m = 0; m < mMax; m++) { Y[Yoffset + m][0] = Xhigh[Xoffset + m][ixh][0] * gFilt[m]; Y[Yoffset + m][1] = Xhigh[Xoffset + m][ixh][1] * gFilt[m]; } } private static void hf_apply_noise(float Y[][], int Yoffset, float s_m[], float q_filt[], int noise, float phi_sign0, float phi_sign1, int m_max) { for (int m = 0; m < m_max; m++) { float y0 = Y[Yoffset + m][0]; float y1 = Y[Yoffset + m][1]; noise = (noise + 1) & 0x1ff; if (s_m[m] != 0f) { y0 += s_m[m] * phi_sign0; y1 += s_m[m] * phi_sign1; } else { y0 += q_filt[m] * ff_sbr_noise_table[noise][0]; y1 += q_filt[m] * ff_sbr_noise_table[noise][1]; } Y[Yoffset + m][0] = y0; Y[Yoffset + m][1] = y1; phi_sign1 = -phi_sign1; } } public static void hf_apply_noise(float Y[][], int Yoffset, float s_m[], float q_filt[], int noise, int kx, int m_max, int indexSine) { float phiSign; switch (indexSine) { case 0: hf_apply_noise(Y, Yoffset, s_m, q_filt, noise, 1.0f, 0.0f, m_max); break; case 1: phiSign = 1 - 2 * (kx & 1); hf_apply_noise(Y, Yoffset, s_m, q_filt, noise, 0.0f, phiSign, m_max); break; case 2: hf_apply_noise(Y, Yoffset, s_m, q_filt, noise, -1.0f, 0.0f, m_max); break; case 3: phiSign = 1 - 2 * (kx & 1); hf_apply_noise(Y, Yoffset, s_m, q_filt, noise, 0.0f, -phiSign, m_max); break; default: log.error(String.format("SBRDSP.hf_apply_noise unknown indexSine %d", indexSine)); break; } } }