/* * Decompiled with CFR 0.152. */ package de.maxhenkel.voicechat.concentus; import de.maxhenkel.voicechat.concentus.Arrays; import de.maxhenkel.voicechat.concentus.Filters; import de.maxhenkel.voicechat.concentus.Inlines; import de.maxhenkel.voicechat.concentus.NLSFCodebook; import de.maxhenkel.voicechat.concentus.SilkChannelEncoder; import de.maxhenkel.voicechat.concentus.SilkTables; import de.maxhenkel.voicechat.concentus.Sort; class NLSF { private static final int MAX_STABILIZE_LOOPS = 20; private static final int QA = 16; private static final int BIN_DIV_STEPS_A2NLSF = 3; private static final int MAX_ITERATIONS_A2NLSF = 30; private static final byte[] ordering16 = new byte[]{0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1}; private static final byte[] ordering10 = new byte[]{0, 9, 6, 3, 4, 5, 8, 1, 2, 7}; NLSF() { } static void silk_NLSF_VQ(int[] err_Q26, short[] in_Q15, short[] pCB_Q8, int K, int LPC_order) { int pCB_idx = 0; Inlines.OpusAssert(err_Q26 != null); Inlines.OpusAssert(LPC_order <= 16); Inlines.OpusAssert((LPC_order & 1) == 0); for (int i = 0; i < K; ++i) { int sum_error_Q26 = 0; for (int m = 0; m < LPC_order; m += 2) { int diff_Q15 = Inlines.silk_SUB_LSHIFT32(in_Q15[m], pCB_Q8[pCB_idx++], 7); int sum_error_Q30 = Inlines.silk_SMULBB(diff_Q15, diff_Q15); Inlines.OpusAssert((sum_error_Q26 = Inlines.silk_ADD_RSHIFT32(sum_error_Q26, sum_error_Q30 = Inlines.silk_SMLABB(sum_error_Q30, diff_Q15 = Inlines.silk_SUB_LSHIFT32(in_Q15[m + 1], pCB_Q8[pCB_idx++], 7), diff_Q15), 4)) >= 0); Inlines.OpusAssert(sum_error_Q30 >= 0); } err_Q26[i] = sum_error_Q26; } } static void silk_NLSF_VQ_weights_laroia(short[] pNLSFW_Q_OUT, short[] pNLSF_Q15, int D) { Inlines.OpusAssert(pNLSFW_Q_OUT != null); Inlines.OpusAssert(D > 0); Inlines.OpusAssert((D & 1) == 0); int tmp1_int = Inlines.silk_max_int(pNLSF_Q15[0], 1); tmp1_int = Inlines.silk_DIV32(131072, tmp1_int); int tmp2_int = Inlines.silk_max_int(pNLSF_Q15[1] - pNLSF_Q15[0], 1); tmp2_int = Inlines.silk_DIV32(131072, tmp2_int); pNLSFW_Q_OUT[0] = (short)Inlines.silk_min_int(tmp1_int + tmp2_int, Short.MAX_VALUE); Inlines.OpusAssert(pNLSFW_Q_OUT[0] > 0); for (int k = 1; k < D - 1; k += 2) { tmp1_int = Inlines.silk_max_int(pNLSF_Q15[k + 1] - pNLSF_Q15[k], 1); tmp1_int = Inlines.silk_DIV32(131072, tmp1_int); pNLSFW_Q_OUT[k] = (short)Inlines.silk_min_int(tmp1_int + tmp2_int, Short.MAX_VALUE); Inlines.OpusAssert(pNLSFW_Q_OUT[k] > 0); tmp2_int = Inlines.silk_max_int(pNLSF_Q15[k + 2] - pNLSF_Q15[k + 1], 1); tmp2_int = Inlines.silk_DIV32(131072, tmp2_int); pNLSFW_Q_OUT[k + 1] = (short)Inlines.silk_min_int(tmp1_int + tmp2_int, Short.MAX_VALUE); Inlines.OpusAssert(pNLSFW_Q_OUT[k + 1] > 0); } tmp1_int = Inlines.silk_max_int(32768 - pNLSF_Q15[D - 1], 1); tmp1_int = Inlines.silk_DIV32(131072, tmp1_int); pNLSFW_Q_OUT[D - 1] = (short)Inlines.silk_min_int(tmp1_int + tmp2_int, Short.MAX_VALUE); Inlines.OpusAssert(pNLSFW_Q_OUT[D - 1] > 0); } static void silk_NLSF_residual_dequant(short[] x_Q10, byte[] indices, int indices_ptr, short[] pred_coef_Q8, int quant_step_size_Q16, short order) { short out_Q10 = 0; for (int i = order - 1; i >= 0; --i) { int pred_Q10 = Inlines.silk_RSHIFT(Inlines.silk_SMULBB(out_Q10, pred_coef_Q8[i]), 8); out_Q10 = Inlines.silk_LSHIFT16(indices[indices_ptr + i], 10); if (out_Q10 > 0) { out_Q10 = Inlines.silk_SUB16(out_Q10, (short)102); } else if (out_Q10 < 0) { out_Q10 = Inlines.silk_ADD16(out_Q10, (short)102); } x_Q10[i] = out_Q10 = (short)Inlines.silk_SMLAWB(pred_Q10, out_Q10, quant_step_size_Q16); } } static void silk_NLSF_unpack(short[] ec_ix, short[] pred_Q8, NLSFCodebook psNLSF_CB, int CB1_index) { short[] ec_sel = psNLSF_CB.ec_sel; int ec_sel_ptr = CB1_index * psNLSF_CB.order / 2; for (int i = 0; i < psNLSF_CB.order; i += 2) { short entry = ec_sel[ec_sel_ptr]; ++ec_sel_ptr; ec_ix[i] = (short)Inlines.silk_SMULBB(Inlines.silk_RSHIFT(entry, 1) & 7, 9); pred_Q8[i] = psNLSF_CB.pred_Q8[i + (entry & 1) * (psNLSF_CB.order - 1)]; ec_ix[i + 1] = (short)Inlines.silk_SMULBB(Inlines.silk_RSHIFT(entry, 5) & 7, 9); pred_Q8[i + 1] = psNLSF_CB.pred_Q8[i + (Inlines.silk_RSHIFT(entry, 4) & 1) * (psNLSF_CB.order - 1) + 1]; } } static void silk_NLSF_stabilize(short[] NLSF_Q15, short[] NDeltaMin_Q15, int L) { int i; int loops; int I = 0; Inlines.OpusAssert(NDeltaMin_Q15[L] >= 1); for (loops = 0; loops < 20; ++loops) { int k; int diff_Q15; int min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0]; I = 0; for (i = 1; i <= L - 1; ++i) { diff_Q15 = NLSF_Q15[i] - (NLSF_Q15[i - 1] + NDeltaMin_Q15[i]); if (diff_Q15 >= min_diff_Q15) continue; min_diff_Q15 = diff_Q15; I = i; } diff_Q15 = 32768 - (NLSF_Q15[L - 1] + NDeltaMin_Q15[L]); if (diff_Q15 < min_diff_Q15) { min_diff_Q15 = diff_Q15; I = L; } if (min_diff_Q15 >= 0) { return; } if (I == 0) { NLSF_Q15[0] = NDeltaMin_Q15[0]; continue; } if (I == L) { NLSF_Q15[L - 1] = (short)(32768 - NDeltaMin_Q15[L]); continue; } int min_center_Q15 = 0; for (k = 0; k < I; ++k) { min_center_Q15 += NDeltaMin_Q15[k]; } min_center_Q15 += Inlines.silk_RSHIFT(NDeltaMin_Q15[I], 1); int max_center_Q15 = 32768; for (k = L; k > I; --k) { max_center_Q15 -= NDeltaMin_Q15[k]; } short center_freq_Q15 = (short)Inlines.silk_LIMIT_32(Inlines.silk_RSHIFT_ROUND(NLSF_Q15[I - 1] + NLSF_Q15[I], 1), min_center_Q15, max_center_Q15 -= Inlines.silk_RSHIFT(NDeltaMin_Q15[I], 1)); NLSF_Q15[I - 1] = (short)(center_freq_Q15 - Inlines.silk_RSHIFT(NDeltaMin_Q15[I], 1)); NLSF_Q15[I] = (short)(NLSF_Q15[I - 1] + NDeltaMin_Q15[I]); } if (loops == 20) { Sort.silk_insertion_sort_increasing_all_values_int16(NLSF_Q15, L); NLSF_Q15[0] = (short)Inlines.silk_max_int(NLSF_Q15[0], NDeltaMin_Q15[0]); for (i = 1; i < L; ++i) { NLSF_Q15[i] = (short)Inlines.silk_max_int(NLSF_Q15[i], NLSF_Q15[i - 1] + NDeltaMin_Q15[i]); } NLSF_Q15[L - 1] = (short)Inlines.silk_min_int(NLSF_Q15[L - 1], 32768 - NDeltaMin_Q15[L]); for (i = L - 2; i >= 0; --i) { NLSF_Q15[i] = (short)Inlines.silk_min_int(NLSF_Q15[i], NLSF_Q15[i + 1] - NDeltaMin_Q15[i + 1]); } } } static void silk_NLSF_decode(short[] pNLSF_Q15, byte[] NLSFIndices, NLSFCodebook psNLSF_CB) { int i; short[] pred_Q8 = new short[psNLSF_CB.order]; short[] ec_ix = new short[psNLSF_CB.order]; short[] res_Q10 = new short[psNLSF_CB.order]; short[] W_tmp_QW = new short[psNLSF_CB.order]; short[] pCB = psNLSF_CB.CB1_NLSF_Q8; int pCB_element = NLSFIndices[0] * psNLSF_CB.order; for (i = 0; i < psNLSF_CB.order; ++i) { pNLSF_Q15[i] = Inlines.silk_LSHIFT16(pCB[pCB_element + i], 7); } NLSF.silk_NLSF_unpack(ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[0]); NLSF.silk_NLSF_residual_dequant(res_Q10, NLSFIndices, 1, pred_Q8, psNLSF_CB.quantStepSize_Q16, psNLSF_CB.order); NLSF.silk_NLSF_VQ_weights_laroia(W_tmp_QW, pNLSF_Q15, psNLSF_CB.order); for (i = 0; i < psNLSF_CB.order; ++i) { int W_tmp_Q9 = Inlines.silk_SQRT_APPROX(Inlines.silk_LSHIFT(W_tmp_QW[i], 16)); int NLSF_Q15_tmp = Inlines.silk_ADD32(pNLSF_Q15[i], Inlines.silk_DIV32_16(Inlines.silk_LSHIFT(res_Q10[i], 14), (short)W_tmp_Q9)); pNLSF_Q15[i] = (short)Inlines.silk_LIMIT(NLSF_Q15_tmp, 0, Short.MAX_VALUE); } NLSF.silk_NLSF_stabilize(pNLSF_Q15, psNLSF_CB.deltaMin_Q15, psNLSF_CB.order); } static int silk_NLSF_del_dec_quant(byte[] indices, short[] x_Q10, short[] w_Q5, short[] pred_coef_Q8, short[] ec_ix, short[] ec_rates_Q5, int quant_step_size_Q16, short inv_quant_step_size_Q6, int mu_Q20, short order) { int ind_tmp; int j; int out1_Q10; int out0_Q10; int i; int[] ind_sort = new int[4]; byte[][] ind = new byte[4][]; for (i = 0; i < 4; ++i) { ind[i] = new byte[16]; } short[] prev_out_Q10 = new short[8]; int[] RD_Q25 = new int[8]; int[] RD_min_Q25 = new int[4]; int[] RD_max_Q25 = new int[4]; int[] out0_Q10_table = new int[20]; int[] out1_Q10_table = new int[20]; for (i = -10; i <= 9; ++i) { out0_Q10 = Inlines.silk_LSHIFT(i, 10); out1_Q10 = Inlines.silk_ADD16((short)out0_Q10, (short)1024); if (i > 0) { out0_Q10 = Inlines.silk_SUB16((short)out0_Q10, (short)102); out1_Q10 = Inlines.silk_SUB16((short)out1_Q10, (short)102); } else if (i == 0) { out1_Q10 = Inlines.silk_SUB16((short)out1_Q10, (short)102); } else if (i == -1) { out0_Q10 = Inlines.silk_ADD16((short)out0_Q10, (short)102); } else { out0_Q10 = Inlines.silk_ADD16((short)out0_Q10, (short)102); out1_Q10 = Inlines.silk_ADD16((short)out1_Q10, (short)102); } out0_Q10_table[i + 10] = Inlines.silk_SMULWB(out0_Q10, quant_step_size_Q16); out1_Q10_table[i + 10] = Inlines.silk_SMULWB(out1_Q10, quant_step_size_Q16); } Inlines.OpusAssert(true); int nStates = 1; RD_Q25[0] = 0; prev_out_Q10[0] = 0; i = order - 1; while (true) { int pred_coef_Q16 = Inlines.silk_LSHIFT(pred_coef_Q8[i], 8); short in_Q10 = x_Q10[i]; for (j = 0; j < nStates; ++j) { int rate1_Q5; int rate0_Q5; int pred_Q10 = Inlines.silk_SMULWB(pred_coef_Q16, prev_out_Q10[j]); short res_Q10 = Inlines.silk_SUB16(in_Q10, (short)pred_Q10); ind_tmp = Inlines.silk_SMULWB(inv_quant_step_size_Q6, res_Q10); ind_tmp = Inlines.silk_LIMIT(ind_tmp, -10, 9); ind[j][i] = (byte)ind_tmp; int rates_Q5 = ec_ix[i] + ind_tmp; out0_Q10 = out0_Q10_table[ind_tmp + 10]; out1_Q10 = out1_Q10_table[ind_tmp + 10]; out0_Q10 = Inlines.silk_ADD16((short)out0_Q10, (short)pred_Q10); out1_Q10 = Inlines.silk_ADD16((short)out1_Q10, (short)pred_Q10); prev_out_Q10[j] = (short)out0_Q10; prev_out_Q10[j + nStates] = (short)out1_Q10; if (ind_tmp + 1 >= 4) { if (ind_tmp + 1 == 4) { rate0_Q5 = ec_rates_Q5[rates_Q5 + 4]; rate1_Q5 = 280; } else { rate0_Q5 = Inlines.silk_SMLABB(108, 43, ind_tmp); rate1_Q5 = Inlines.silk_ADD16((short)rate0_Q5, (short)43); } } else if (ind_tmp <= -4) { if (ind_tmp == -4) { rate0_Q5 = 280; rate1_Q5 = ec_rates_Q5[rates_Q5 + 1 + 4]; } else { rate0_Q5 = Inlines.silk_SMLABB(108, -43, ind_tmp); rate1_Q5 = Inlines.silk_SUB16((short)rate0_Q5, (short)43); } } else { rate0_Q5 = ec_rates_Q5[rates_Q5 + 4]; rate1_Q5 = ec_rates_Q5[rates_Q5 + 1 + 4]; } int RD_tmp_Q25 = RD_Q25[j]; short diff_Q10 = Inlines.silk_SUB16(in_Q10, (short)out0_Q10); RD_Q25[j] = Inlines.silk_SMLABB(Inlines.silk_MLA(RD_tmp_Q25, Inlines.silk_SMULBB(diff_Q10, diff_Q10), w_Q5[i]), mu_Q20, rate0_Q5); diff_Q10 = Inlines.silk_SUB16(in_Q10, (short)out1_Q10); RD_Q25[j + nStates] = Inlines.silk_SMLABB(Inlines.silk_MLA(RD_tmp_Q25, Inlines.silk_SMULBB(diff_Q10, diff_Q10), w_Q5[i]), mu_Q20, rate1_Q5); } if (nStates <= 2) { for (j = 0; j < nStates; ++j) { ind[j + nStates][i] = (byte)(ind[j][i] + 1); } for (j = nStates = Inlines.silk_LSHIFT(nStates, 1); j < 4; ++j) { ind[j][i] = ind[j - nStates][i]; } } else { if (i <= 0) break; for (j = 0; j < 4; ++j) { if (RD_Q25[j] > RD_Q25[j + 4]) { RD_max_Q25[j] = RD_Q25[j]; RD_min_Q25[j] = RD_Q25[j + 4]; RD_Q25[j] = RD_min_Q25[j]; RD_Q25[j + 4] = RD_max_Q25[j]; out0_Q10 = prev_out_Q10[j]; prev_out_Q10[j] = prev_out_Q10[j + 4]; prev_out_Q10[j + 4] = (short)out0_Q10; ind_sort[j] = j + 4; continue; } RD_min_Q25[j] = RD_Q25[j]; RD_max_Q25[j] = RD_Q25[j + 4]; ind_sort[j] = j; } while (true) { int min_max_Q25 = Integer.MAX_VALUE; int max_min_Q25 = 0; int ind_min_max = 0; int ind_max_min = 0; for (j = 0; j < 4; ++j) { if (min_max_Q25 > RD_max_Q25[j]) { min_max_Q25 = RD_max_Q25[j]; ind_min_max = j; } if (max_min_Q25 >= RD_min_Q25[j]) continue; max_min_Q25 = RD_min_Q25[j]; ind_max_min = j; } if (min_max_Q25 >= max_min_Q25) break; ind_sort[ind_max_min] = ind_sort[ind_min_max] ^ 4; RD_Q25[ind_max_min] = RD_Q25[ind_min_max + 4]; prev_out_Q10[ind_max_min] = prev_out_Q10[ind_min_max + 4]; RD_min_Q25[ind_max_min] = 0; RD_max_Q25[ind_min_max] = Integer.MAX_VALUE; System.arraycopy(ind[ind_min_max], 0, ind[ind_max_min], 0, order); } for (j = 0; j < 4; ++j) { byte x = (byte)Inlines.silk_RSHIFT(ind_sort[j], 2); byte[] byArray = ind[j]; int n = i; byArray[n] = (byte)(byArray[n] + x); } } --i; } ind_tmp = 0; int min_Q25 = Integer.MAX_VALUE; for (j = 0; j < 8; ++j) { if (min_Q25 <= RD_Q25[j]) continue; min_Q25 = RD_Q25[j]; ind_tmp = j; } for (j = 0; j < order; ++j) { indices[j] = ind[ind_tmp & 3][j]; Inlines.OpusAssert(indices[j] >= -10); Inlines.OpusAssert(indices[j] <= 10); } indices[0] = (byte)(indices[0] + Inlines.silk_RSHIFT(ind_tmp, 2)); Inlines.OpusAssert(indices[0] <= 10); Inlines.OpusAssert(min_Q25 >= 0); return min_Q25; } static int silk_NLSF_encode(byte[] NLSFIndices, short[] pNLSF_Q15, NLSFCodebook psNLSF_CB, short[] pW_QW, int NLSF_mu_Q20, int nSurvivors, int signalType) { short[] res_Q15 = new short[psNLSF_CB.order]; short[] res_Q10 = new short[psNLSF_CB.order]; short[] NLSF_tmp_Q15 = new short[psNLSF_CB.order]; short[] W_tmp_QW = new short[psNLSF_CB.order]; short[] W_adj_Q5 = new short[psNLSF_CB.order]; short[] pred_Q8 = new short[psNLSF_CB.order]; short[] ec_ix = new short[psNLSF_CB.order]; short[] pCB = psNLSF_CB.CB1_NLSF_Q8; Inlines.OpusAssert(nSurvivors <= 32); Inlines.OpusAssert(signalType >= 0 && signalType <= 2); Inlines.OpusAssert(NLSF_mu_Q20 <= Short.MAX_VALUE && NLSF_mu_Q20 >= 0); NLSF.silk_NLSF_stabilize(pNLSF_Q15, psNLSF_CB.deltaMin_Q15, psNLSF_CB.order); int[] err_Q26 = new int[psNLSF_CB.nVectors]; NLSF.silk_NLSF_VQ(err_Q26, pNLSF_Q15, psNLSF_CB.CB1_NLSF_Q8, psNLSF_CB.nVectors, psNLSF_CB.order); int[] tempIndices1 = new int[nSurvivors]; Sort.silk_insertion_sort_increasing(err_Q26, tempIndices1, psNLSF_CB.nVectors, nSurvivors); int[] RD_Q25 = new int[nSurvivors]; byte[][] tempIndices2 = Arrays.InitTwoDimensionalArrayByte(nSurvivors, 16); for (int s = 0; s < nSurvivors; ++s) { int i; int ind1 = tempIndices1[s]; int pCB_element = ind1 * psNLSF_CB.order; for (i = 0; i < psNLSF_CB.order; ++i) { NLSF_tmp_Q15[i] = Inlines.silk_LSHIFT16(pCB[pCB_element + i], 7); res_Q15[i] = (short)(pNLSF_Q15[i] - NLSF_tmp_Q15[i]); } NLSF.silk_NLSF_VQ_weights_laroia(W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB.order); for (i = 0; i < psNLSF_CB.order; ++i) { int W_tmp_Q9 = Inlines.silk_SQRT_APPROX(Inlines.silk_LSHIFT(W_tmp_QW[i], 16)); res_Q10[i] = (short)Inlines.silk_RSHIFT(Inlines.silk_SMULBB(res_Q15[i], W_tmp_Q9), 14); } for (i = 0; i < psNLSF_CB.order; ++i) { W_adj_Q5[i] = (short)Inlines.silk_DIV32_16(Inlines.silk_LSHIFT(pW_QW[i], 5), W_tmp_QW[i]); } NLSF.silk_NLSF_unpack(ec_ix, pred_Q8, psNLSF_CB, ind1); RD_Q25[s] = NLSF.silk_NLSF_del_dec_quant(tempIndices2[s], res_Q10, W_adj_Q5, pred_Q8, ec_ix, psNLSF_CB.ec_Rates_Q5, psNLSF_CB.quantStepSize_Q16, psNLSF_CB.invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB.order); int iCDF_ptr = (signalType >> 1) * psNLSF_CB.nVectors; int prob_Q8 = ind1 == 0 ? 256 - psNLSF_CB.CB1_iCDF[iCDF_ptr + ind1] : psNLSF_CB.CB1_iCDF[iCDF_ptr + ind1 - 1] - psNLSF_CB.CB1_iCDF[iCDF_ptr + ind1]; int bits_q7 = 1024 - Inlines.silk_lin2log(prob_Q8); RD_Q25[s] = Inlines.silk_SMLABB(RD_Q25[s], bits_q7, Inlines.silk_RSHIFT(NLSF_mu_Q20, 2)); } int[] bestIndex = new int[1]; Sort.silk_insertion_sort_increasing(RD_Q25, bestIndex, nSurvivors, 1); NLSFIndices[0] = (byte)tempIndices1[bestIndex[0]]; System.arraycopy(tempIndices2[bestIndex[0]], 0, NLSFIndices, 1, psNLSF_CB.order); NLSF.silk_NLSF_decode(pNLSF_Q15, NLSFIndices, psNLSF_CB); return RD_Q25[0]; } static void silk_NLSF2A_find_poly(int[] o, int[] cLSF, int cLSF_ptr, int dd) { o[0] = Inlines.silk_LSHIFT(1, 16); o[1] = 0 - cLSF[cLSF_ptr]; for (int k = 1; k < dd; ++k) { int ftmp = cLSF[cLSF_ptr + 2 * k]; o[k + 1] = Inlines.silk_LSHIFT(o[k - 1], 1) - (int)Inlines.silk_RSHIFT_ROUND64(Inlines.silk_SMULL(ftmp, o[k]), 16); for (int n = k; n > 1; --n) { int n2 = n; o[n2] = o[n2] + (o[n - 2] - (int)Inlines.silk_RSHIFT_ROUND64(Inlines.silk_SMULL(ftmp, o[n - 1]), 16)); } o[1] = o[1] - ftmp; } } static void silk_NLSF2A(short[] a_Q12, short[] NLSF2, int d) { int i; int k; int[] cos_LSF_QA = new int[d]; int[] P = new int[d / 2 + 1]; int[] Q = new int[d / 2 + 1]; int[] a32_QA1 = new int[d]; int idx = 0; Inlines.OpusAssert(true); Inlines.OpusAssert(d == 10 || d == 16); byte[] ordering = d == 16 ? ordering16 : ordering10; for (k = 0; k < d; ++k) { Inlines.OpusAssert(NLSF2[k] >= 0); int f_int = Inlines.silk_RSHIFT(NLSF2[k], 8); int f_frac = NLSF2[k] - Inlines.silk_LSHIFT(f_int, 8); Inlines.OpusAssert(f_int >= 0); Inlines.OpusAssert(f_int < 128); short cos_val = SilkTables.silk_LSFCosTab_Q12[f_int]; int delta = SilkTables.silk_LSFCosTab_Q12[f_int + 1] - cos_val; cos_LSF_QA[ordering[k]] = Inlines.silk_RSHIFT_ROUND(Inlines.silk_LSHIFT(cos_val, 8) + Inlines.silk_MUL(delta, f_frac), 4); } int dd = Inlines.silk_RSHIFT(d, 1); NLSF.silk_NLSF2A_find_poly(P, cos_LSF_QA, 0, dd); NLSF.silk_NLSF2A_find_poly(Q, cos_LSF_QA, 1, dd); for (k = 0; k < dd; ++k) { int Ptmp = P[k + 1] + P[k]; int Qtmp = Q[k + 1] - Q[k]; a32_QA1[k] = -Qtmp - Ptmp; a32_QA1[d - k - 1] = Qtmp - Ptmp; } for (i = 0; i < 10; ++i) { int maxabs = 0; for (k = 0; k < d; ++k) { int absval = Inlines.silk_abs(a32_QA1[k]); if (absval <= maxabs) continue; maxabs = absval; idx = k; } if ((maxabs = Inlines.silk_RSHIFT_ROUND(maxabs, 5)) <= Short.MAX_VALUE) break; maxabs = Inlines.silk_min(maxabs, 163838); int sc_Q16 = 65470 - Inlines.silk_DIV32(Inlines.silk_LSHIFT(maxabs - Short.MAX_VALUE, 14), Inlines.silk_RSHIFT32(Inlines.silk_MUL(maxabs, idx + 1), 2)); Filters.silk_bwexpander_32(a32_QA1, d, sc_Q16); } if (i == 10) { for (k = 0; k < d; ++k) { a_Q12[k] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(a32_QA1[k], 5)); a32_QA1[k] = Inlines.silk_LSHIFT(a_Q12[k], 5); } } else { for (k = 0; k < d; ++k) { a_Q12[k] = (short)Inlines.silk_RSHIFT_ROUND(a32_QA1[k], 5); } } for (i = 0; i < 16 && Filters.silk_LPC_inverse_pred_gain(a_Q12, d) < 107374; ++i) { Filters.silk_bwexpander_32(a32_QA1, d, 65536 - Inlines.silk_LSHIFT(2, i)); for (k = 0; k < d; ++k) { a_Q12[k] = (short)Inlines.silk_RSHIFT_ROUND(a32_QA1[k], 5); } } } static void silk_A2NLSF_trans_poly(int[] p, int dd) { for (int k = 2; k <= dd; ++k) { for (int n = dd; n > k; --n) { int n2 = n - 2; p[n2] = p[n2] - p[n]; } int n = k - 2; p[n] = p[n] - Inlines.silk_LSHIFT(p[k], 1); } } static int silk_A2NLSF_eval_poly(int[] p, int x, int dd) { int y32 = p[dd]; int x_Q16 = Inlines.silk_LSHIFT(x, 4); if (8 == dd) { y32 = Inlines.silk_SMLAWW(p[7], y32, x_Q16); y32 = Inlines.silk_SMLAWW(p[6], y32, x_Q16); y32 = Inlines.silk_SMLAWW(p[5], y32, x_Q16); y32 = Inlines.silk_SMLAWW(p[4], y32, x_Q16); y32 = Inlines.silk_SMLAWW(p[3], y32, x_Q16); y32 = Inlines.silk_SMLAWW(p[2], y32, x_Q16); y32 = Inlines.silk_SMLAWW(p[1], y32, x_Q16); y32 = Inlines.silk_SMLAWW(p[0], y32, x_Q16); } else { for (int n = dd - 1; n >= 0; --n) { y32 = Inlines.silk_SMLAWW(p[n], y32, x_Q16); } } return y32; } static void silk_A2NLSF_init(int[] a_Q16, int[] P, int[] Q, int dd) { int k; P[dd] = Inlines.silk_LSHIFT(1, 16); Q[dd] = Inlines.silk_LSHIFT(1, 16); for (k = 0; k < dd; ++k) { P[k] = -a_Q16[dd - k - 1] - a_Q16[dd + k]; Q[k] = -a_Q16[dd - k - 1] + a_Q16[dd + k]; } for (k = dd; k > 0; --k) { int n = k - 1; P[n] = P[n] - P[k]; int n2 = k - 1; Q[n2] = Q[n2] + Q[k]; } NLSF.silk_A2NLSF_trans_poly(P, dd); NLSF.silk_A2NLSF_trans_poly(Q, dd); } static void silk_A2NLSF(short[] NLSF2, int[] a_Q16, int d) { int root_ix; int[] P = new int[9]; int[] Q = new int[9]; int[][] PQ = new int[][]{P, Q}; int dd = Inlines.silk_RSHIFT(d, 1); NLSF.silk_A2NLSF_init(a_Q16, P, Q, dd); int[] p = P; int xlo = SilkTables.silk_LSFCosTab_Q12[0]; int ylo = NLSF.silk_A2NLSF_eval_poly(p, xlo, dd); if (ylo < 0) { NLSF2[0] = 0; p = Q; ylo = NLSF.silk_A2NLSF_eval_poly(p, xlo, dd); root_ix = 1; } else { root_ix = 0; } int k = 1; int i = 0; int thr = 0; while (true) { int xhi = SilkTables.silk_LSFCosTab_Q12[k]; int yhi = NLSF.silk_A2NLSF_eval_poly(p, xhi, dd); if (ylo <= 0 && yhi >= thr || ylo >= 0 && yhi <= -thr) { thr = yhi == 0 ? 1 : 0; int ffrac = -256; for (int m = 0; m < 3; ++m) { int xmid = Inlines.silk_RSHIFT_ROUND(xlo + xhi, 1); int ymid = NLSF.silk_A2NLSF_eval_poly(p, xmid, dd); if (ylo <= 0 && ymid >= 0 || ylo >= 0 && ymid <= 0) { xhi = xmid; yhi = ymid; continue; } xlo = xmid; ylo = ymid; ffrac = Inlines.silk_ADD_RSHIFT(ffrac, 128, m); } if (Inlines.silk_abs(ylo) < 65536) { int den = ylo - yhi; int nom = Inlines.silk_LSHIFT(ylo, 5) + Inlines.silk_RSHIFT(den, 1); if (den != 0) { ffrac += Inlines.silk_DIV32(nom, den); } } else { ffrac += Inlines.silk_DIV32(ylo, Inlines.silk_RSHIFT(ylo - yhi, 5)); } NLSF2[root_ix] = (short)Inlines.silk_min_32(Inlines.silk_LSHIFT(k, 8) + ffrac, Short.MAX_VALUE); Inlines.OpusAssert(NLSF2[root_ix] >= 0); if (++root_ix >= d) break; p = PQ[root_ix & 1]; xlo = SilkTables.silk_LSFCosTab_Q12[k - 1]; ylo = Inlines.silk_LSHIFT(1 - (root_ix & 2), 12); continue; } xlo = xhi; ylo = yhi; thr = 0; if (++k <= 128) continue; if (++i > 30) { NLSF2[0] = (short)Inlines.silk_DIV32_16(32768, (short)(d + 1)); for (k = 1; k < d; ++k) { NLSF2[k] = (short)Inlines.silk_SMULBB(k + 1, NLSF2[0]); } return; } Filters.silk_bwexpander_32(a_Q16, d, 65536 - Inlines.silk_SMULBB(10 + i, i)); NLSF.silk_A2NLSF_init(a_Q16, P, Q, dd); p = P; xlo = SilkTables.silk_LSFCosTab_Q12[0]; ylo = NLSF.silk_A2NLSF_eval_poly(p, xlo, dd); if (ylo < 0) { NLSF2[0] = 0; p = Q; ylo = NLSF.silk_A2NLSF_eval_poly(p, xlo, dd); root_ix = 1; } else { root_ix = 0; } k = 1; } } static void silk_process_NLSFs(SilkChannelEncoder psEncC, short[][] PredCoef_Q12, short[] pNLSF_Q15, short[] prev_NLSFq_Q15) { boolean doInterpolate; short[] pNLSF0_temp_Q15 = new short[16]; short[] pNLSFW_QW = new short[16]; short[] pNLSFW0_temp_QW = new short[16]; Inlines.OpusAssert(psEncC.speech_activity_Q8 >= 0); Inlines.OpusAssert(psEncC.speech_activity_Q8 <= 256); Inlines.OpusAssert(psEncC.useInterpolatedNLSFs == 1 || psEncC.indices.NLSFInterpCoef_Q2 == 4); int NLSF_mu_Q20 = Inlines.silk_SMLAWB(3146, -268434, psEncC.speech_activity_Q8); if (psEncC.nb_subfr == 2) { NLSF_mu_Q20 = Inlines.silk_ADD_RSHIFT(NLSF_mu_Q20, NLSF_mu_Q20, 1); } Inlines.OpusAssert(NLSF_mu_Q20 > 0); Inlines.OpusAssert(NLSF_mu_Q20 <= 5243); NLSF.silk_NLSF_VQ_weights_laroia(pNLSFW_QW, pNLSF_Q15, psEncC.predictLPCOrder); boolean bl = doInterpolate = psEncC.useInterpolatedNLSFs == 1 && psEncC.indices.NLSFInterpCoef_Q2 < 4; if (doInterpolate) { Inlines.silk_interpolate(pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, psEncC.indices.NLSFInterpCoef_Q2, psEncC.predictLPCOrder); NLSF.silk_NLSF_VQ_weights_laroia(pNLSFW0_temp_QW, pNLSF0_temp_Q15, psEncC.predictLPCOrder); int i_sqr_Q15 = Inlines.silk_LSHIFT(Inlines.silk_SMULBB(psEncC.indices.NLSFInterpCoef_Q2, psEncC.indices.NLSFInterpCoef_Q2), 11); for (int i = 0; i < psEncC.predictLPCOrder; ++i) { pNLSFW_QW[i] = (short)Inlines.silk_SMLAWB(Inlines.silk_RSHIFT(pNLSFW_QW[i], 1), pNLSFW0_temp_QW[i], i_sqr_Q15); Inlines.OpusAssert(pNLSFW_QW[i] >= 1); } } NLSF.silk_NLSF_encode(psEncC.indices.NLSFIndices, pNLSF_Q15, psEncC.psNLSF_CB, pNLSFW_QW, NLSF_mu_Q20, psEncC.NLSF_MSVQ_Survivors, psEncC.indices.signalType); NLSF.silk_NLSF2A(PredCoef_Q12[1], pNLSF_Q15, psEncC.predictLPCOrder); if (doInterpolate) { Inlines.silk_interpolate(pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, psEncC.indices.NLSFInterpCoef_Q2, psEncC.predictLPCOrder); NLSF.silk_NLSF2A(PredCoef_Q12[0], pNLSF0_temp_Q15, psEncC.predictLPCOrder); } else { System.arraycopy(PredCoef_Q12[1], 0, PredCoef_Q12[0], 0, psEncC.predictLPCOrder); } } }