/// <summary>Line Spectral Pair Quantification (Lbr).</summary> /// <remarks>Line Spectral Pair Quantification (Lbr).</remarks> /// <param name="lsp">- Line Spectral Pairs table.</param> /// <param name="qlsp">- Quantified Line Spectral Pairs table.</param> /// <param name="order"></param> /// <param name="bits">- Speex bits buffer.</param> public override sealed void quant(float[] lsp, float[] qlsp, int order, org.xiph.speex.Bits bits) { int i; float tmp1; float tmp2; int id; float[] quant_weight = new float[MAX_LSP_SIZE]; for (i = 0; i < order; i++) { qlsp[i] = lsp[i]; } quant_weight[0] = 1 / (qlsp[1] - qlsp[0]); quant_weight[order - 1] = 1 / (qlsp[order - 1] - qlsp[order - 2]); for (i = 1; i < order - 1; i++) { tmp1 = 1 / ((.15f + qlsp[i] - qlsp[i - 1]) * (.15f + qlsp[i] - qlsp[i - 1])); tmp2 = 1 / ((.15f + qlsp[i + 1] - qlsp[i]) * (.15f + qlsp[i + 1] - qlsp[i])); quant_weight[i] = tmp1 > tmp2 ? tmp1 : tmp2; } for (i = 0; i < order; i++) { qlsp[i] -= (.25f * i + .25f); } for (i = 0; i < order; i++) { qlsp[i] *= 256; } id = lsp_quant(qlsp, 0, cdbk_nb, NB_CDBK_SIZE, order); bits.pack(id, 6); for (i = 0; i < order; i++) { qlsp[i] *= 2; } id = lsp_weight_quant(qlsp, 0, quant_weight, 0, cdbk_nb_low1, NB_CDBK_SIZE_LOW1, 5); bits.pack(id, 6); id = lsp_weight_quant(qlsp, 5, quant_weight, 5, cdbk_nb_high1, NB_CDBK_SIZE_HIGH1 , 5); bits.pack(id, 6); for (i = 0; i < order; i++) { qlsp[i] *= 0.0019531f; } for (i = 0; i < order; i++) { qlsp[i] = lsp[i] - qlsp[i]; } }
/// <summary>Line Spectral Pair Quantification (high).</summary> /// <remarks>Line Spectral Pair Quantification (high).</remarks> /// <param name="lsp">- Line Spectral Pairs table.</param> /// <param name="qlsp">- Quantified Line Spectral Pairs table.</param> /// <param name="order"></param> /// <param name="bits">- Speex bits buffer.</param> public override sealed void quant(float[] lsp, float[] qlsp, int order, org.xiph.speex.Bits bits) { int i; float tmp1; float tmp2; int id; float[] quant_weight = new float[MAX_LSP_SIZE]; for (i = 0; i < order; i++) { qlsp[i] = lsp[i]; } quant_weight[0] = 1 / (qlsp[1] - qlsp[0]); quant_weight[order - 1] = 1 / (qlsp[order - 1] - qlsp[order - 2]); for (i = 1; i < order - 1; i++) { tmp1 = 1 / (qlsp[i] - qlsp[i - 1]); tmp2 = 1 / (qlsp[i + 1] - qlsp[i]); quant_weight[i] = tmp1 > tmp2 ? tmp1 : tmp2; } for (i = 0; i < order; i++) { qlsp[i] -= (.3125f * i + .75f); } for (i = 0; i < order; i++) { qlsp[i] *= 256; } id = lsp_quant(qlsp, 0, high_lsp_cdbk, 64, order); bits.pack(id, 6); for (i = 0; i < order; i++) { qlsp[i] *= 2; } id = lsp_weight_quant(qlsp, 0, quant_weight, 0, high_lsp_cdbk2, 64, order); bits.pack(id, 6); for (i = 0; i < order; i++) { qlsp[i] *= 0.0019531f; } for (i = 0; i < order; i++) { qlsp[i] = lsp[i] - qlsp[i]; } }
// private float reserved1; /** Reserved for future use */ // private float reserved2; /** Reserved for future use */ /// <summary> /// Transforms a stereo frame into a mono frame and stores intensity stereo /// info in 'bits'. /// </summary> /// <remarks> /// Transforms a stereo frame into a mono frame and stores intensity stereo /// info in 'bits'. /// </remarks> /// <param name="bits">- Speex bits buffer.</param> /// <param name="data"></param> /// <param name="frameSize"></param> public static void encode(org.xiph.speex.Bits bits, float[] data, int frameSize) { int i; int tmp; float e_left = 0; float e_right = 0; float e_tot = 0; float balance; float e_ratio; for (i = 0; i < frameSize; i++) { e_left += data[2 * i] * data[2 * i]; e_right += data[2 * i + 1] * data[2 * i + 1]; data[i] = .5f * (data[2 * i] + data[2 * i + 1]); e_tot += data[i] * data[i]; } balance = (e_left + 1) / (e_right + 1); e_ratio = e_tot / (1 + e_left + e_right); bits.pack(14, 5); bits.pack(SPEEX_INBAND_STEREO, 4); balance = (float)(4 * System.Math.Log(balance)); if (balance > 0) { bits.pack(0, 1); } else { bits.pack(1, 1); } balance = (float)System.Math.Floor(.5f + System.Math.Abs(balance)); if (balance > 30) { balance = 31; } bits.pack((int)balance, 5); tmp = org.xiph.speex.VQ.index(e_ratio, e_ratio_quant, 4); bits.pack(tmp, 2); }
/// <summary>Codebook Search Quantification (Split Shape).</summary> /// <remarks>Codebook Search Quantification (Split Shape).</remarks> /// <param name="target">target vector</param> /// <param name="ak">LPCs for this subframe</param> /// <param name="awk1">Weighted LPCs for this subframe</param> /// <param name="awk2">Weighted LPCs for this subframe</param> /// <param name="p">number of LPC coeffs</param> /// <param name="nsf">number of samples in subframe</param> /// <param name="exc">excitation array.</param> /// <param name="es">position in excitation array.</param> /// <param name="r"></param> /// <param name="bits">Speex bits buffer.</param> /// <param name="complexity"></param> public override sealed void quant(float[] target, float[] ak, float[] awk1, float [] awk2, int p, int nsf, float[] exc, int es, float[] r, org.xiph.speex.Bits bits , int complexity) { int i; int j; int k; int m; int n; int q; float[] resp; float[] ndist; float[] odist; int[] best_index; float[] best_dist; int N = complexity; if (N > 10) { N = 10; } resp = new float[shape_cb_size * subvect_size]; best_index = new int[N]; best_dist = new float[N]; ndist = new float[N]; odist = new float[N]; for (i = 0; i < N; i++) { for (j = 0; j < nb_subvect; j++) { nind[i][j] = oind[i][j] = -1; } } for (j = 0; j < N; j++) { for (i = 0; i < nsf; i++) { ot[j][i] = target[i]; } } // System.arraycopy(target, 0, t, 0, nsf); for (i = 0; i < shape_cb_size; i++) { int res; int shape; res = i * subvect_size; shape = i * subvect_size; for (j = 0; j < subvect_size; j++) { resp[res + j] = 0; for (k = 0; k <= j; k++) { resp[res + j] += 0.03125f * shape_cb[shape + k] * r[j - k]; } } E[i] = 0; for (j = 0; j < subvect_size; j++) { E[i] += resp[res + j] * resp[res + j]; } } for (j = 0; j < N; j++) { odist[j] = 0; } for (i = 0; i < nb_subvect; i++) { int offset = i * subvect_size; for (j = 0; j < N; j++) { ndist[j] = -1; } for (j = 0; j < N; j++) { if (have_sign != 0) { org.xiph.speex.VQ.nbest_sign(ot[j], offset, resp, subvect_size, shape_cb_size, E, N, best_index, best_dist); } else { org.xiph.speex.VQ.nbest(ot[j], offset, resp, subvect_size, shape_cb_size, E, N, best_index , best_dist); } for (k = 0; k < N; k++) { float[] ct; float err = 0; ct = ot[j]; for (m = offset; m < offset + subvect_size; m++) { t[m] = ct[m]; } int rind; int res; float sign = 1; rind = best_index[k]; if (rind >= shape_cb_size) { sign = -1; rind -= shape_cb_size; } res = rind * subvect_size; if (sign > 0) { for (m = 0; m < subvect_size; m++) { t[offset + m] -= resp[res + m]; } } else { for (m = 0; m < subvect_size; m++) { t[offset + m] += resp[res + m]; } } err = odist[j]; for (m = offset; m < offset + subvect_size; m++) { err += t[m] * t[m]; } if (err < ndist[N - 1] || ndist[N - 1] < -0.5f) { for (m = offset + subvect_size; m < nsf; m++) { t[m] = ct[m]; } for (m = 0; m < subvect_size; m++) { float g; //int rind; //float sign = 1; sign = 1; rind = best_index[k]; if (rind >= shape_cb_size) { sign = -1; rind -= shape_cb_size; } g = sign * 0.03125f * shape_cb[rind * subvect_size + m]; q = subvect_size - m; for (n = offset + subvect_size; n < nsf; n++, q++) { t[n] -= g * r[q]; } } for (m = 0; m < N; m++) { if (err < ndist[m] || ndist[m] < -0.5f) { for (n = N - 1; n > m; n--) { for (q = offset + subvect_size; q < nsf; q++) { nt[n][q] = nt[n - 1][q]; } for (q = 0; q < nb_subvect; q++) { nind[n][q] = nind[n - 1][q]; } ndist[n] = ndist[n - 1]; } for (q = offset + subvect_size; q < nsf; q++) { nt[m][q] = t[q]; } for (q = 0; q < nb_subvect; q++) { nind[m][q] = oind[j][q]; } nind[m][i] = best_index[k]; ndist[m] = err; break; } } } } if (i == 0) { break; } } float[][] tmp2; tmp2 = ot; ot = nt; nt = tmp2; for (j = 0; j < N; j++) { for (m = 0; m < nb_subvect; m++) { oind[j][m] = nind[j][m]; } } for (j = 0; j < N; j++) { odist[j] = ndist[j]; } } for (i = 0; i < nb_subvect; i++) { ind[i] = nind[0][i]; bits.pack(ind[i], shape_bits + have_sign); } for (i = 0; i < nb_subvect; i++) { int rind; float sign = 1; rind = ind[i]; if (rind >= shape_cb_size) { sign = -1; rind -= shape_cb_size; } for (j = 0; j < subvect_size; j++) { e[subvect_size * i + j] = sign * 0.03125f * shape_cb[rind * subvect_size + j]; } } for (j = 0; j < nsf; j++) { exc[es + j] += e[j]; } org.xiph.speex.Filters.syn_percep_zero(e, 0, ak, awk1, awk2, r2, nsf, p); for (j = 0; j < nsf; j++) { target[j] -= r2[j]; } }
/// <summary>Encode the given input signal.</summary> /// <remarks>Encode the given input signal.</remarks> /// <param name="bits">- Speex bits buffer.</param> /// <param name="in">- the raw mono audio frame to encode.</param> /// <returns>return 1 if successful.</returns> public virtual int encode(org.xiph.speex.Bits bits, float[] @in) { int i; float[] res; float[] target; float[] mem; float[] syn_resp; float[] orig; float ener; //TODO: Check System.Array.Copy(frmBuf, frameSize, frmBuf, 0, bufSize - frameSize); frmBuf[bufSize - frameSize] = @in[0] - preemph * pre_mem; for (i = 1; i < frameSize; i++) { frmBuf[bufSize - frameSize + i] = @in[i] - preemph * @in[i - 1]; } pre_mem = @in[frameSize - 1]; System.Array.Copy(exc2Buf, frameSize, exc2Buf, 0, bufSize - frameSize); System.Array.Copy(excBuf, frameSize, excBuf, 0, bufSize - frameSize); System.Array.Copy(swBuf, frameSize, swBuf, 0, bufSize - frameSize); for (i = 0; i < windowSize; i++) { buf2[i] = frmBuf[i + frmIdx] * window[i]; } org.xiph.speex.Lpc.autocorr(buf2, autocorr, lpcSize + 1, windowSize); autocorr[0] += 10; autocorr[0] *= lpc_floor; for (i = 0; i < lpcSize + 1; i++) { autocorr[i] *= lagWindow[i]; } org.xiph.speex.Lpc.wld(lpc, autocorr, rc, lpcSize); // tmperr System.Array.Copy(lpc, 0, lpc, 1, lpcSize); lpc[0] = 1; int roots = org.xiph.speex.Lsp.lpc2lsp(lpc, lpcSize, lsp, 15, 0.2f); if (roots == lpcSize) { for (i = 0; i < lpcSize; i++) { lsp[i] = (float)System.Math.Acos(lsp[i]); } } else { if (complexity > 1) { roots = org.xiph.speex.Lsp.lpc2lsp(lpc, lpcSize, lsp, 11, 0.05f); } if (roots == lpcSize) { for (i = 0; i < lpcSize; i++) { lsp[i] = (float)System.Math.Acos(lsp[i]); } } else { for (i = 0; i < lpcSize; i++) { lsp[i] = old_lsp[i]; } } } float lsp_dist = 0; for (i = 0; i < lpcSize; i++) { lsp_dist += (old_lsp[i] - lsp[i]) * (old_lsp[i] - lsp[i]); } float ol_gain; int ol_pitch; float ol_pitch_coef; if (first != 0) { for (i = 0; i < lpcSize; i++) { interp_lsp[i] = lsp[i]; } } else { for (i = 0; i < lpcSize; i++) { interp_lsp[i] = .375f * old_lsp[i] + .625f * lsp[i]; } } org.xiph.speex.Lsp.enforce_margin(interp_lsp, lpcSize, .002f); for (i = 0; i < lpcSize; i++) { interp_lsp[i] = (float)System.Math.Cos(interp_lsp[i]); } m_lsp.lsp2lpc(interp_lsp, interp_lpc, lpcSize); if (submodes[submodeID] == null || vbr_enabled != 0 || vad_enabled != 0 || submodes [submodeID].forced_pitch_gain != 0 || submodes[submodeID].lbr_pitch != -1) { int[] nol_pitch = new int[6]; float[] nol_pitch_coef = new float[6]; org.xiph.speex.Filters.bw_lpc(gamma1, interp_lpc, bw_lpc1, lpcSize); org.xiph.speex.Filters.bw_lpc(gamma2, interp_lpc, bw_lpc2, lpcSize); org.xiph.speex.Filters.filter_mem2(frmBuf, frmIdx, bw_lpc1, bw_lpc2, swBuf, swIdx , frameSize, lpcSize, mem_sw_whole, 0); org.xiph.speex.Ltp.open_loop_nbest_pitch(swBuf, swIdx, min_pitch, max_pitch, frameSize , nol_pitch, nol_pitch_coef, 6); ol_pitch = nol_pitch[0]; ol_pitch_coef = nol_pitch_coef[0]; for (i = 1; i < 6; i++) { if ((nol_pitch_coef[i] > .85f * ol_pitch_coef) && (System.Math.Abs(nol_pitch[i] - ol_pitch / 2.0f) <= 1 || System.Math.Abs(nol_pitch[i] - ol_pitch / 3.0f) <= 1 || System.Math.Abs(nol_pitch[i] - ol_pitch / 4.0f) <= 1 || System.Math.Abs(nol_pitch [i] - ol_pitch / 5.0f) <= 1)) { ol_pitch = nol_pitch[i]; } } } else { ol_pitch = 0; ol_pitch_coef = 0; } org.xiph.speex.Filters.fir_mem2(frmBuf, frmIdx, interp_lpc, excBuf, excIdx, frameSize , lpcSize, mem_exc); ol_gain = 0; for (i = 0; i < frameSize; i++) { ol_gain += excBuf[excIdx + i] * excBuf[excIdx + i]; } ol_gain = (float)System.Math.Sqrt(1 + ol_gain / frameSize); if (vbr != null && (vbr_enabled != 0 || vad_enabled != 0)) { if (abr_enabled != 0) { float qual_change = 0; if (abr_drift2 * abr_drift > 0) { qual_change = -.00001f * abr_drift / (1 + abr_count); if (qual_change > .05f) { qual_change = .05f; } if (qual_change < -.05f) { qual_change = -.05f; } } vbr_quality += qual_change; if (vbr_quality > 10) { vbr_quality = 10; } if (vbr_quality < 0) { vbr_quality = 0; } } relative_quality = vbr.analysis(@in, frameSize, ol_pitch, ol_pitch_coef); if (vbr_enabled != 0) { int mode; int choice = 0; float min_diff = 100; mode = 8; while (mode > 0) { int v1; float thresh; v1 = (int)System.Math.Floor(vbr_quality); if (v1 == 10) { thresh = org.xiph.speex.Vbr.nb_thresh[mode][v1]; } else { thresh = (vbr_quality - v1) * org.xiph.speex.Vbr.nb_thresh[mode][v1 + 1] + (1 + v1 - vbr_quality) * org.xiph.speex.Vbr.nb_thresh[mode][v1]; } if (relative_quality > thresh && relative_quality - thresh < min_diff) { choice = mode; min_diff = relative_quality - thresh; } mode--; } mode = choice; if (mode == 0) { if (dtx_count == 0 || lsp_dist > .05 || dtx_enabled == 0 || dtx_count > 20) { mode = 1; dtx_count = 1; } else { mode = 0; dtx_count++; } } else { dtx_count = 0; } setMode(mode); if (abr_enabled != 0) { int bitrate; bitrate = getBitRate(); abr_drift += (bitrate - abr_enabled); abr_drift2 = .95f * abr_drift2 + .05f * (bitrate - abr_enabled); abr_count += 1.0f; } } else { int mode; if (relative_quality < 2) { if (dtx_count == 0 || lsp_dist > .05 || dtx_enabled == 0 || dtx_count > 20) { dtx_count = 1; mode = 1; } else { mode = 0; dtx_count++; } } else { dtx_count = 0; mode = submodeSelect; } submodeID = mode; } } else { relative_quality = -1; } bits.pack(0, 1); bits.pack(submodeID, NB_SUBMODE_BITS); if (submodes[submodeID] == null) { for (i = 0; i < frameSize; i++) { excBuf[excIdx + i] = exc2Buf[exc2Idx + i] = swBuf[swIdx + i] = VERY_SMALL; } for (i = 0; i < lpcSize; i++) { mem_sw[i] = 0; } first = 1; bounded_pitch = 1; org.xiph.speex.Filters.iir_mem2(excBuf, excIdx, interp_qlpc, frmBuf, frmIdx, frameSize , lpcSize, mem_sp); @in[0] = frmBuf[frmIdx] + preemph * pre_mem2; for (i = 1; i < frameSize; i++) { @in[i] = frmBuf[frmIdx + i] + preemph * @in[i - 1]; } pre_mem2 = @in[frameSize - 1]; return 0; } if (first != 0) { for (i = 0; i < lpcSize; i++) { old_lsp[i] = lsp[i]; } } //#if 1 /*0 for unquantized*/ submodes[submodeID].lsqQuant.quant(lsp, qlsp, lpcSize, bits); //#else // for (i=0;i<lpcSize;i++) // qlsp[i]=lsp[i]; //#endif if (submodes[submodeID].lbr_pitch != -1) { bits.pack(ol_pitch - min_pitch, 7); } if (submodes[submodeID].forced_pitch_gain != 0) { int quant; quant = (int)System.Math.Floor(.5f + 15 * ol_pitch_coef); if (quant > 15) { quant = 15; } if (quant < 0) { quant = 0; } bits.pack(quant, 4); ol_pitch_coef = (float)0.066667f * quant; } int qe = (int)(System.Math.Floor(0.5 + 3.5 * System.Math.Log(ol_gain))); if (qe < 0) { qe = 0; } if (qe > 31) { qe = 31; } ol_gain = (float)System.Math.Exp(qe / 3.5); bits.pack(qe, 5); if (first != 0) { for (i = 0; i < lpcSize; i++) { old_qlsp[i] = qlsp[i]; } } res = new float[subframeSize]; target = new float[subframeSize]; syn_resp = new float[subframeSize]; mem = new float[lpcSize]; orig = new float[frameSize]; for (i = 0; i < frameSize; i++) { orig[i] = frmBuf[frmIdx + i]; } for (int sub = 0; sub < nbSubframes; sub++) { float tmp; int offset; int sp; int sw; int exc; int exc2; int pitchval; offset = subframeSize * sub; sp = frmIdx + offset; exc = excIdx + offset; sw = swIdx + offset; exc2 = exc2Idx + offset; tmp = (float)(1.0 + sub) / nbSubframes; for (i = 0; i < lpcSize; i++) { interp_lsp[i] = (1 - tmp) * old_lsp[i] + tmp * lsp[i]; } for (i = 0; i < lpcSize; i++) { interp_qlsp[i] = (1 - tmp) * old_qlsp[i] + tmp * qlsp[i]; } org.xiph.speex.Lsp.enforce_margin(interp_lsp, lpcSize, .002f); org.xiph.speex.Lsp.enforce_margin(interp_qlsp, lpcSize, .002f); for (i = 0; i < lpcSize; i++) { interp_lsp[i] = (float)System.Math.Cos(interp_lsp[i]); } m_lsp.lsp2lpc(interp_lsp, interp_lpc, lpcSize); for (i = 0; i < lpcSize; i++) { interp_qlsp[i] = (float)System.Math.Cos(interp_qlsp[i]); } m_lsp.lsp2lpc(interp_qlsp, interp_qlpc, lpcSize); tmp = 1; pi_gain[sub] = 0; for (i = 0; i <= lpcSize; i++) { pi_gain[sub] += tmp * interp_qlpc[i]; tmp = -tmp; } org.xiph.speex.Filters.bw_lpc(gamma1, interp_lpc, bw_lpc1, lpcSize); if (gamma2 >= 0) { org.xiph.speex.Filters.bw_lpc(gamma2, interp_lpc, bw_lpc2, lpcSize); } else { bw_lpc2[0] = 1; bw_lpc2[1] = -preemph; for (i = 2; i <= lpcSize; i++) { bw_lpc2[i] = 0; } } for (i = 0; i < subframeSize; i++) { excBuf[exc + i] = VERY_SMALL; } excBuf[exc] = 1; org.xiph.speex.Filters.syn_percep_zero(excBuf, exc, interp_qlpc, bw_lpc1, bw_lpc2 , syn_resp, subframeSize, lpcSize); for (i = 0; i < subframeSize; i++) { excBuf[exc + i] = VERY_SMALL; } for (i = 0; i < subframeSize; i++) { exc2Buf[exc2 + i] = VERY_SMALL; } for (i = 0; i < lpcSize; i++) { mem[i] = mem_sp[i]; } org.xiph.speex.Filters.iir_mem2(excBuf, exc, interp_qlpc, excBuf, exc, subframeSize , lpcSize, mem); for (i = 0; i < lpcSize; i++) { mem[i] = mem_sw[i]; } org.xiph.speex.Filters.filter_mem2(excBuf, exc, bw_lpc1, bw_lpc2, res, 0, subframeSize , lpcSize, mem, 0); for (i = 0; i < lpcSize; i++) { mem[i] = mem_sw[i]; } org.xiph.speex.Filters.filter_mem2(frmBuf, sp, bw_lpc1, bw_lpc2, swBuf, sw, subframeSize , lpcSize, mem, 0); for (i = 0; i < subframeSize; i++) { target[i] = swBuf[sw + i] - res[i]; } for (i = 0; i < subframeSize; i++) { excBuf[exc + i] = exc2Buf[exc2 + i] = 0; } // if (submodes[submodeID].ltp.quant) // { int pit_min; int pit_max; if (submodes[submodeID].lbr_pitch != -1) { int margin; margin = submodes[submodeID].lbr_pitch; if (margin != 0) { if (ol_pitch < min_pitch + margin - 1) { ol_pitch = min_pitch + margin - 1; } if (ol_pitch > max_pitch - margin) { ol_pitch = max_pitch - margin; } pit_min = ol_pitch - margin + 1; pit_max = ol_pitch + margin; } else { pit_min = pit_max = ol_pitch; } } else { pit_min = min_pitch; pit_max = max_pitch; } if (bounded_pitch != 0 && pit_max > offset) { pit_max = offset; } pitchval = submodes[submodeID].ltp.quant(target, swBuf, sw, interp_qlpc, bw_lpc1, bw_lpc2, excBuf, exc, pit_min, pit_max, ol_pitch_coef, lpcSize, subframeSize, bits , exc2Buf, exc2, syn_resp, complexity); pitch[sub] = pitchval; // } else { // speex_error ("No pitch prediction, what's wrong"); // } org.xiph.speex.Filters.syn_percep_zero(excBuf, exc, interp_qlpc, bw_lpc1, bw_lpc2 , res, subframeSize, lpcSize); for (i = 0; i < subframeSize; i++) { target[i] -= res[i]; } int innovptr; //float ener = 0; ener = 0; float ener_1; innovptr = sub * subframeSize; for (i = 0; i < subframeSize; i++) { innov[innovptr + i] = 0; } org.xiph.speex.Filters.residue_percep_zero(target, 0, interp_qlpc, bw_lpc1, bw_lpc2 , buf2, subframeSize, lpcSize); for (i = 0; i < subframeSize; i++) { ener += buf2[i] * buf2[i]; } ener = (float)System.Math.Sqrt(.1f + ener / subframeSize); ener /= ol_gain; if (submodes[submodeID].have_subframe_gain != 0) { //int qe; ener = (float)System.Math.Log(ener); if (submodes[submodeID].have_subframe_gain == 3) { qe = org.xiph.speex.VQ.index(ener, exc_gain_quant_scal3, 8); bits.pack(qe, 3); ener = exc_gain_quant_scal3[qe]; } else { qe = org.xiph.speex.VQ.index(ener, exc_gain_quant_scal1, 2); bits.pack(qe, 1); ener = exc_gain_quant_scal1[qe]; } ener = (float)System.Math.Exp(ener); } else { ener = 1f; } ener *= ol_gain; ener_1 = 1 / ener; for (i = 0; i < subframeSize; i++) { target[i] *= ener_1; } // if (submodes[submodeID].innovation != null) // { submodes[submodeID].innovation.quant(target, interp_qlpc, bw_lpc1, bw_lpc2, lpcSize , subframeSize, innov, innovptr, syn_resp, bits, complexity); for (i = 0; i < subframeSize; i++) { innov[innovptr + i] *= ener; } for (i = 0; i < subframeSize; i++) { excBuf[exc + i] += innov[innovptr + i]; } // } else { // speex_error("No fixed codebook"); // } if (submodes[submodeID].double_codebook != 0) { float[] innov2 = new float[subframeSize]; // for (i = 0; i < subframeSize; i++) // innov2[i] = 0; for (i = 0; i < subframeSize; i++) { target[i] *= 2.2f; } submodes[submodeID].innovation.quant(target, interp_qlpc, bw_lpc1, bw_lpc2, lpcSize , subframeSize, innov2, 0, syn_resp, bits, complexity); for (i = 0; i < subframeSize; i++) { innov2[i] *= ener * (1f / 2.2f); } for (i = 0; i < subframeSize; i++) { excBuf[exc + i] += innov2[i]; } } for (i = 0; i < subframeSize; i++) { target[i] *= ener; } for (i = 0; i < lpcSize; i++) { mem[i] = mem_sp[i]; } org.xiph.speex.Filters.iir_mem2(excBuf, exc, interp_qlpc, frmBuf, sp, subframeSize , lpcSize, mem_sp); org.xiph.speex.Filters.filter_mem2(frmBuf, sp, bw_lpc1, bw_lpc2, swBuf, sw, subframeSize , lpcSize, mem_sw, 0); for (i = 0; i < subframeSize; i++) { exc2Buf[exc2 + i] = excBuf[exc + i]; } } if (submodeID >= 1) { for (i = 0; i < lpcSize; i++) { old_lsp[i] = lsp[i]; } for (i = 0; i < lpcSize; i++) { old_qlsp[i] = qlsp[i]; } } if (submodeID == 1) { if (dtx_count != 0) { bits.pack(15, 4); } else { bits.pack(0, 4); } } first = 0; //float ener = 0; ener = 0; float err = 0; //float snr; for (i = 0; i < frameSize; i++) { ener += frmBuf[frmIdx + i] * frmBuf[frmIdx + i]; err += (frmBuf[frmIdx + i] - orig[i]) * (frmBuf[frmIdx + i] - orig[i]); } //snr = (float) (10*Math.log((ener+1)/(err+1))); //System.out.println("Frame result: SNR="+snr+" E="+ener+" Err="+err+"\r\n"); @in[0] = frmBuf[frmIdx] + preemph * pre_mem2; for (i = 1; i < frameSize; i++) { @in[i] = frmBuf[frmIdx + i] + preemph * @in[i - 1]; } pre_mem2 = @in[frameSize - 1]; if (submodes[submodeID].innovation is org.xiph.speex.NoiseSearch || submodeID == 0) { bounded_pitch = 1; } else { bounded_pitch = 0; } return 1; }
/// <summary>Long Term Prediction Quantification (3Tap).</summary> /// <remarks>Long Term Prediction Quantification (3Tap).</remarks> /// <returns>pitch</returns> public override sealed int quant(float[] target, float[] sw, int sws, float[] ak, float[] awk1, float[] awk2, float[] exc, int es, int start, int end, float pitch_coef , int p, int nsf, org.xiph.speex.Bits bits, float[] exc2, int e2s, float[] r, int complexity) { int i; int j; int[] cdbk_index = new int[1]; int pitch = 0; int best_gain_index = 0; float[] best_exc; int best_pitch = 0; float err; float best_err = -1; int N; int[] nbest; float[] gains; N = complexity; if (N > 10) { N = 10; } nbest = new int[N]; gains = new float[N]; if (N == 0 || end < start) { bits.pack(0, pitch_bits); bits.pack(0, gain_bits); for (i = 0; i < nsf; i++) { exc[es + i] = 0; } return start; } best_exc = new float[nsf]; if (N > end - start + 1) { N = end - start + 1; } open_loop_nbest_pitch(sw, sws, start, end, nsf, nbest, gains, N); for (i = 0; i < N; i++) { pitch = nbest[i]; for (j = 0; j < nsf; j++) { exc[es + j] = 0; } err = pitch_gain_search_3tap(target, ak, awk1, awk2, exc, es, pitch, p, nsf, bits , exc2, e2s, r, cdbk_index); if (err < best_err || best_err < 0) { for (j = 0; j < nsf; j++) { best_exc[j] = exc[es + j]; } best_err = err; best_pitch = pitch; best_gain_index = cdbk_index[0]; } } bits.pack(best_pitch - start, pitch_bits); bits.pack(best_gain_index, gain_bits); for (i = 0; i < nsf; i++) { exc[es + i] = best_exc[i]; } return pitch; }
/// <summary>Encode the given input signal.</summary> /// <remarks>Encode the given input signal.</remarks> /// <param name="bits">- Speex bits buffer.</param> /// <param name="in">- the raw mono audio frame to encode.</param> /// <returns>1 if successful.</returns> public virtual int encode(org.xiph.speex.Bits bits, float[] @in) { int i; float[] mem; float[] innov; float[] syn_resp; float[] low_pi_gain; float[] low_exc; float[] low_innov; int dtx; org.xiph.speex.Filters.qmf_decomp(@in, h0, x0d, x1d, fullFrameSize, QMF_ORDER, h0_mem ); lowenc.encode(bits, x0d); for (i = 0; i < windowSize - frameSize; i++) { high[i] = high[frameSize + i]; } for (i = 0; i < frameSize; i++) { high[windowSize - frameSize + i] = x1d[i]; } System.Array.Copy(excBuf, frameSize, excBuf, 0, bufSize - frameSize); low_pi_gain = lowenc.getPiGain(); low_exc = lowenc.getExc(); low_innov = lowenc.getInnov(); int low_mode = lowenc.getMode(); if (low_mode == 0) { dtx = 1; } else { dtx = 0; } for (i = 0; i < windowSize; i++) { buf[i] = high[i] * window[i]; } org.xiph.speex.Lpc.autocorr(buf, autocorr, lpcSize + 1, windowSize); autocorr[0] += 1; autocorr[0] *= lpc_floor; for (i = 0; i < lpcSize + 1; i++) { autocorr[i] *= lagWindow[i]; } org.xiph.speex.Lpc.wld(lpc, autocorr, rc, lpcSize); // tmperr System.Array.Copy(lpc, 0, lpc, 1, lpcSize); lpc[0] = 1; int roots = org.xiph.speex.Lsp.lpc2lsp(lpc, lpcSize, lsp, 15, 0.2f); if (roots != lpcSize) { roots = org.xiph.speex.Lsp.lpc2lsp(lpc, lpcSize, lsp, 11, 0.02f); if (roots != lpcSize) { for (i = 0; i < lpcSize; i++) { lsp[i] = (float)System.Math.Cos(System.Math.PI * ((float)(i + 1)) / (lpcSize + 1) ); } } } for (i = 0; i < lpcSize; i++) { lsp[i] = (float)System.Math.Acos(lsp[i]); } float lsp_dist = 0; for (i = 0; i < lpcSize; i++) { lsp_dist += (old_lsp[i] - lsp[i]) * (old_lsp[i] - lsp[i]); } if ((vbr_enabled != 0 || vad_enabled != 0) && dtx == 0) { float e_low = 0; float e_high = 0; float ratio; if (abr_enabled != 0) { float qual_change = 0; if (abr_drift2 * abr_drift > 0) { qual_change = -.00001f * abr_drift / (1 + abr_count); if (qual_change > .1f) { qual_change = .1f; } if (qual_change < -.1f) { qual_change = -.1f; } } vbr_quality += qual_change; if (vbr_quality > 10) { vbr_quality = 10; } if (vbr_quality < 0) { vbr_quality = 0; } } for (i = 0; i < frameSize; i++) { e_low += x0d[i] * x0d[i]; e_high += high[i] * high[i]; } ratio = (float)System.Math.Log((1 + e_high) / (1 + e_low)); relative_quality = lowenc.getRelativeQuality(); if (ratio < -4) { ratio = -4; } if (ratio > 2) { ratio = 2; } if (vbr_enabled != 0) { int modeid; modeid = nb_modes - 1; relative_quality += 1.0f * (ratio + 2f); if (relative_quality < -1) { relative_quality = -1; } while (modeid != 0) { int v1; float thresh; v1 = (int)System.Math.Floor(vbr_quality); if (v1 == 10) { thresh = org.xiph.speex.Vbr.hb_thresh[modeid][v1]; } else { thresh = (vbr_quality - v1) * org.xiph.speex.Vbr.hb_thresh[modeid][v1 + 1] + (1 + v1 - vbr_quality) * org.xiph.speex.Vbr.hb_thresh[modeid][v1]; } if (relative_quality >= thresh) { break; } modeid--; } setMode(modeid); if (abr_enabled != 0) { int bitrate; bitrate = getBitRate(); abr_drift += (bitrate - abr_enabled); abr_drift2 = .95f * abr_drift2 + .05f * (bitrate - abr_enabled); abr_count += 1.0f; } } else { int modeid; if (relative_quality < 2.0) { modeid = 1; } else { modeid = submodeSelect; } submodeID = modeid; } } bits.pack(1, 1); if (dtx != 0) { bits.pack(0, SB_SUBMODE_BITS); } else { bits.pack(submodeID, SB_SUBMODE_BITS); } if (dtx != 0 || submodes[submodeID] == null) { for (i = 0; i < frameSize; i++) { excBuf[excIdx + i] = swBuf[i] = VERY_SMALL; } for (i = 0; i < lpcSize; i++) { mem_sw[i] = 0; } first = 1; org.xiph.speex.Filters.iir_mem2(excBuf, excIdx, interp_qlpc, high, 0, subframeSize , lpcSize, mem_sp); filters.fir_mem_up(x0d, h0, y0, fullFrameSize, QMF_ORDER, g0_mem); filters.fir_mem_up(high, h1, y1, fullFrameSize, QMF_ORDER, g1_mem); for (i = 0; i < fullFrameSize; i++) { @in[i] = 2 * (y0[i] - y1[i]); } if (dtx != 0) { return 0; } else { return 1; } } submodes[submodeID].lsqQuant.quant(lsp, qlsp, lpcSize, bits); if (first != 0) { for (i = 0; i < lpcSize; i++) { old_lsp[i] = lsp[i]; } for (i = 0; i < lpcSize; i++) { old_qlsp[i] = qlsp[i]; } } mem = new float[lpcSize]; syn_resp = new float[subframeSize]; innov = new float[subframeSize]; for (int sub = 0; sub < nbSubframes; sub++) { float tmp; float filter_ratio; int exc; int sp; int sw; int resp; int offset; float rl; float rh; float eh = 0; float el = 0; // int fold; offset = subframeSize * sub; sp = offset; exc = excIdx + offset; resp = offset; sw = offset; tmp = (1.0f + sub) / nbSubframes; for (i = 0; i < lpcSize; i++) { interp_lsp[i] = (1 - tmp) * old_lsp[i] + tmp * lsp[i]; } for (i = 0; i < lpcSize; i++) { interp_qlsp[i] = (1 - tmp) * old_qlsp[i] + tmp * qlsp[i]; } org.xiph.speex.Lsp.enforce_margin(interp_lsp, lpcSize, .05f); org.xiph.speex.Lsp.enforce_margin(interp_qlsp, lpcSize, .05f); for (i = 0; i < lpcSize; i++) { interp_lsp[i] = (float)System.Math.Cos(interp_lsp[i]); } for (i = 0; i < lpcSize; i++) { interp_qlsp[i] = (float)System.Math.Cos(interp_qlsp[i]); } m_lsp.lsp2lpc(interp_lsp, interp_lpc, lpcSize); m_lsp.lsp2lpc(interp_qlsp, interp_qlpc, lpcSize); org.xiph.speex.Filters.bw_lpc(gamma1, interp_lpc, bw_lpc1, lpcSize); org.xiph.speex.Filters.bw_lpc(gamma2, interp_lpc, bw_lpc2, lpcSize); rl = rh = 0; tmp = 1; pi_gain[sub] = 0; for (i = 0; i <= lpcSize; i++) { rh += tmp * interp_qlpc[i]; tmp = -tmp; pi_gain[sub] += interp_qlpc[i]; } rl = low_pi_gain[sub]; rl = 1 / (System.Math.Abs(rl) + .01f); rh = 1 / (System.Math.Abs(rh) + .01f); filter_ratio = System.Math.Abs(.01f + rh) / (.01f + System.Math.Abs(rl)); // fold = filter_ratio<5 ? 1 : 0; // fold=0; org.xiph.speex.Filters.fir_mem2(high, sp, interp_qlpc, excBuf, exc, subframeSize, lpcSize, mem_sp2); for (i = 0; i < subframeSize; i++) { eh += excBuf[exc + i] * excBuf[exc + i]; } if (submodes[submodeID].innovation == null) { float g; for (i = 0; i < subframeSize; i++) { el += low_innov[offset + i] * low_innov[offset + i]; } g = eh / (.01f + el); g = (float)System.Math.Sqrt(g); g *= filter_ratio; int quant = (int)System.Math.Floor(.5 + 10 + 8.0 * System.Math.Log((g + .0001))); if (quant < 0) { quant = 0; } if (quant > 31) { quant = 31; } bits.pack(quant, 5); g = (float)(.1 * System.Math.Exp(quant / 9.4)); g /= filter_ratio; } else { float gc; float scale; float scale_1; for (i = 0; i < subframeSize; i++) { el += low_exc[offset + i] * low_exc[offset + i]; } gc = (float)(System.Math.Sqrt(1 + eh) * filter_ratio / System.Math.Sqrt((1 + el) * subframeSize)); int qgc = (int)System.Math.Floor(.5 + 3.7 * (System.Math.Log(gc) + 2)); if (qgc < 0) { qgc = 0; } if (qgc > 15) { qgc = 15; } bits.pack(qgc, 4); gc = (float)System.Math.Exp((1 / 3.7) * qgc - 2); scale = gc * (float)System.Math.Sqrt(1 + el) / filter_ratio; scale_1 = 1 / scale; for (i = 0; i < subframeSize; i++) { excBuf[exc + i] = 0; } excBuf[exc] = 1; org.xiph.speex.Filters.syn_percep_zero(excBuf, exc, interp_qlpc, bw_lpc1, bw_lpc2 , syn_resp, subframeSize, lpcSize); for (i = 0; i < subframeSize; i++) { excBuf[exc + i] = 0; } for (i = 0; i < lpcSize; i++) { mem[i] = mem_sp[i]; } org.xiph.speex.Filters.iir_mem2(excBuf, exc, interp_qlpc, excBuf, exc, subframeSize , lpcSize, mem); for (i = 0; i < lpcSize; i++) { mem[i] = mem_sw[i]; } org.xiph.speex.Filters.filter_mem2(excBuf, exc, bw_lpc1, bw_lpc2, res, resp, subframeSize , lpcSize, mem, 0); for (i = 0; i < lpcSize; i++) { mem[i] = mem_sw[i]; } org.xiph.speex.Filters.filter_mem2(high, sp, bw_lpc1, bw_lpc2, swBuf, sw, subframeSize , lpcSize, mem, 0); for (i = 0; i < subframeSize; i++) { target[i] = swBuf[sw + i] - res[resp + i]; } for (i = 0; i < subframeSize; i++) { excBuf[exc + i] = 0; } for (i = 0; i < subframeSize; i++) { target[i] *= scale_1; } for (i = 0; i < subframeSize; i++) { innov[i] = 0; } submodes[submodeID].innovation.quant(target, interp_qlpc, bw_lpc1, bw_lpc2, lpcSize , subframeSize, innov, 0, syn_resp, bits, (complexity + 1) >> 1); for (i = 0; i < subframeSize; i++) { excBuf[exc + i] += innov[i] * scale; } if (submodes[submodeID].double_codebook != 0) { float[] innov2 = new float[subframeSize]; for (i = 0; i < subframeSize; i++) { innov2[i] = 0; } for (i = 0; i < subframeSize; i++) { target[i] *= 2.5f; } submodes[submodeID].innovation.quant(target, interp_qlpc, bw_lpc1, bw_lpc2, lpcSize , subframeSize, innov2, 0, syn_resp, bits, (complexity + 1) >> 1); for (i = 0; i < subframeSize; i++) { innov2[i] *= scale * (1f / 2.5f); } for (i = 0; i < subframeSize; i++) { excBuf[exc + i] += innov2[i]; } } } for (i = 0; i < lpcSize; i++) { mem[i] = mem_sp[i]; } org.xiph.speex.Filters.iir_mem2(excBuf, exc, interp_qlpc, high, sp, subframeSize, lpcSize, mem_sp); org.xiph.speex.Filters.filter_mem2(high, sp, bw_lpc1, bw_lpc2, swBuf, sw, subframeSize , lpcSize, mem_sw, 0); } //#ifndef RELEASE filters.fir_mem_up(x0d, h0, y0, fullFrameSize, QMF_ORDER, g0_mem); filters.fir_mem_up(high, h1, y1, fullFrameSize, QMF_ORDER, g1_mem); for (i = 0; i < fullFrameSize; i++) { @in[i] = 2 * (y0[i] - y1[i]); } //#endif for (i = 0; i < lpcSize; i++) { old_lsp[i] = lsp[i]; } for (i = 0; i < lpcSize; i++) { old_qlsp[i] = qlsp[i]; } first = 0; return 1; }