/// <summary> /// Decode the given input bits. /// </summary> /// <returns>1 if a terminator was found, 0 if not.</returns> public virtual int Decode(Bits bits, float[] xout) { int i, sub, wideband, ret; float[] low_pi_gain, low_exc, low_innov; /* Decode the low-band */ ret = lowdec.Decode(bits, x0d); if (ret != 0) { return(ret); } bool dtx = lowdec.Dtx; if (bits == null) { DecodeLost(xout, dtx); return(0); } /* Check "wideband bit" */ wideband = bits.Peek(); if (wideband != 0) { /* Regular wideband frame, read the submode */ wideband = bits.Unpack(1); submodeID = bits.Unpack(3); } else { /* was a narrowband frame, set "null submode" */ submodeID = 0; } for (i = 0; i < frameSize; i++) { excBuf[i] = 0; } /* If null mode (no transmission), just set a couple things to zero */ if (submodes[submodeID] == null) { if (dtx) { DecodeLost(xout, true); return(0); } for (i = 0; i < frameSize; i++) { excBuf[i] = NSpeex.NbCodec.VERY_SMALL; } first = 1; /* Final signal synthesis from excitation */ NSpeex.Filters.Iir_mem2(excBuf, excIdx, interp_qlpc, high, 0, frameSize, lpcSize, mem_sp); filters.Fir_mem_up(x0d, NSpeex.Codebook_Constants.h0, y0, fullFrameSize, NSpeex.SbCodec.QMF_ORDER, g0_mem); filters.Fir_mem_up(high, NSpeex.Codebook_Constants.h1, y1, fullFrameSize, NSpeex.SbCodec.QMF_ORDER, g1_mem); for (i = 0; i < fullFrameSize; i++) { xout[i] = 2 * (y0[i] - y1[i]); } return(0); } low_pi_gain = lowdec.PiGain; low_exc = lowdec.Exc; low_innov = lowdec.Innov; submodes[submodeID].LsqQuant.Unquant(qlsp, lpcSize, bits); if (first != 0) { for (i = 0; i < lpcSize; i++) { old_qlsp[i] = qlsp[i]; } } for (sub = 0; sub < nbSubframes; sub++) { float tmp, filter_ratio, el = 0.0f, rl = 0.0f, rh = 0.0f; int subIdx = subframeSize * sub; /* LSP interpolation */ tmp = (1.0f + sub) / nbSubframes; for (i = 0; i < lpcSize; i++) { interp_qlsp[i] = (1 - tmp) * old_qlsp[i] + tmp * qlsp[i]; } NSpeex.Lsp.Enforce_margin(interp_qlsp, lpcSize, .05f); /* LSPs to x-domain */ for (i = 0; i < lpcSize; i++) { interp_qlsp[i] = (float)System.Math.Cos(interp_qlsp[i]); } /* LSP to LPC */ m_lsp.Lsp2lpc(interp_qlsp, interp_qlpc, lpcSize); if (enhanced) { float k1, k2, k3; k1 = submodes[submodeID].LpcEnhK1; k2 = submodes[submodeID].LpcEnhK2; k3 = k1 - k2; NSpeex.Filters.Bw_lpc(k1, interp_qlpc, awk1, lpcSize); NSpeex.Filters.Bw_lpc(k2, interp_qlpc, awk2, lpcSize); NSpeex.Filters.Bw_lpc(k3, interp_qlpc, awk3, lpcSize); } /* * Calculate reponse ratio between low & high filter in band middle * (4000 Hz) */ 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 / (Math.Abs(rl) + .01f); rh = 1 / (Math.Abs(rh) + .01f); filter_ratio = Math.Abs(.01f + rh) / (.01f + Math.Abs(rl)); /* reset excitation buffer */ for (i = subIdx; i < subIdx + subframeSize; i++) { excBuf[i] = 0; } if (submodes[submodeID].Innovation == null) { float g; int quant; quant = bits.Unpack(5); g = (float)Math.Exp(((double)quant - 10) / 8.0d); g /= filter_ratio; /* High-band excitation using the low-band excitation and a gain */ for (i = subIdx; i < subIdx + subframeSize; i++) { excBuf[i] = foldingGain * g * low_innov[i]; } } else { float gc, scale; int qgc = bits.Unpack(4); for (i = subIdx; i < subIdx + subframeSize; i++) { el += low_exc[i] * low_exc[i]; } gc = (float)Math.Exp((1 / 3.7f) * qgc - 2); scale = gc * (float)Math.Sqrt(1 + el) / filter_ratio; submodes[submodeID].Innovation.Unquantify(excBuf, subIdx, subframeSize, bits); for (i = subIdx; i < subIdx + subframeSize; i++) { excBuf[i] *= scale; } if (submodes[submodeID].DoubleCodebook != 0) { for (i = 0; i < subframeSize; i++) { innov2[i] = 0; } submodes[submodeID].Innovation.Unquantify(innov2, 0, subframeSize, bits); for (i = 0; i < subframeSize; i++) { innov2[i] *= scale * (1 / 2.5f); } for (i = 0; i < subframeSize; i++) { excBuf[subIdx + i] += innov2[i]; } } } for (i = subIdx; i < subIdx + subframeSize; i++) { high[i] = excBuf[i]; } if (enhanced) { /* Use enhanced LPC filter */ NSpeex.Filters.Filter_mem2(high, subIdx, awk2, awk1, subframeSize, lpcSize, mem_sp, lpcSize); NSpeex.Filters.Filter_mem2(high, subIdx, awk3, interp_qlpc, subframeSize, lpcSize, mem_sp, 0); } else { /* Use regular filter */ for (i = 0; i < lpcSize; i++) { mem_sp[lpcSize + i] = 0; } NSpeex.Filters.Iir_mem2(high, subIdx, interp_qlpc, high, subIdx, subframeSize, lpcSize, mem_sp); } } filters.Fir_mem_up(x0d, NSpeex.Codebook_Constants.h0, y0, fullFrameSize, NSpeex.SbCodec.QMF_ORDER, g0_mem); filters.Fir_mem_up(high, NSpeex.Codebook_Constants.h1, y1, fullFrameSize, NSpeex.SbCodec.QMF_ORDER, g1_mem); for (i = 0; i < fullFrameSize; i++) { xout[i] = 2 * (y0[i] - y1[i]); } for (i = 0; i < lpcSize; i++) { old_qlsp[i] = qlsp[i]; } first = 0; return(0); }
public virtual int Decode(Bits bits, float[] xout) { int num = this.lowdec.Decode(bits, this.x0d); if (num != 0) { return(num); } bool dtx = this.lowdec.Dtx; if (bits == null) { this.DecodeLost(xout, dtx); return(0); } int num2 = bits.Peek(); if (num2 != 0) { num2 = bits.Unpack(1); this.submodeID = bits.Unpack(3); } else { this.submodeID = 0; } for (int i = 0; i < this.frameSize; i++) { this.excBuf[i] = 0f; } if (this.submodes[this.submodeID] != null) { float[] piGain = this.lowdec.PiGain; float[] exc = this.lowdec.Exc; float[] innov = this.lowdec.Innov; this.submodes[this.submodeID].LsqQuant.Unquant(this.qlsp, this.lpcSize, bits); if (this.first != 0) { for (int i = 0; i < this.lpcSize; i++) { this.old_qlsp[i] = this.qlsp[i]; } } for (int j = 0; j < this.nbSubframes; j++) { float num3 = 0f; float num4 = 0f; int num5 = this.subframeSize * j; float num6 = (1f + (float)j) / (float)this.nbSubframes; for (int i = 0; i < this.lpcSize; i++) { this.interp_qlsp[i] = (1f - num6) * this.old_qlsp[i] + num6 * this.qlsp[i]; } Lsp.Enforce_margin(this.interp_qlsp, this.lpcSize, 0.05f); for (int i = 0; i < this.lpcSize; i++) { this.interp_qlsp[i] = (float)Math.Cos((double)this.interp_qlsp[i]); } this.m_lsp.Lsp2lpc(this.interp_qlsp, this.interp_qlpc, this.lpcSize); if (this.enhanced) { float lpcEnhK = this.submodes[this.submodeID].LpcEnhK1; float lpcEnhK2 = this.submodes[this.submodeID].LpcEnhK2; float gamma = lpcEnhK - lpcEnhK2; Filters.Bw_lpc(lpcEnhK, this.interp_qlpc, this.awk1, this.lpcSize); Filters.Bw_lpc(lpcEnhK2, this.interp_qlpc, this.awk2, this.lpcSize); Filters.Bw_lpc(gamma, this.interp_qlpc, this.awk3, this.lpcSize); } num6 = 1f; this.pi_gain[j] = 0f; for (int i = 0; i <= this.lpcSize; i++) { num4 += num6 * this.interp_qlpc[i]; num6 = -num6; this.pi_gain[j] += this.interp_qlpc[i]; } float value = piGain[j]; value = 1f / (Math.Abs(value) + 0.01f); num4 = 1f / (Math.Abs(num4) + 0.01f); float num7 = Math.Abs(0.01f + num4) / (0.01f + Math.Abs(value)); for (int i = num5; i < num5 + this.subframeSize; i++) { this.excBuf[i] = 0f; } if (this.submodes[this.submodeID].Innovation == null) { int num8 = bits.Unpack(5); float num9 = (float)Math.Exp(((double)num8 - 10.0) / 8.0); num9 /= num7; for (int i = num5; i < num5 + this.subframeSize; i++) { this.excBuf[i] = this.foldingGain * num9 * innov[i]; } } else { int num10 = bits.Unpack(4); for (int i = num5; i < num5 + this.subframeSize; i++) { num3 += exc[i] * exc[i]; } float num11 = (float)Math.Exp((double)(0.270270258f * (float)num10 - 2f)); float num12 = num11 * (float)Math.Sqrt((double)(1f + num3)) / num7; this.submodes[this.submodeID].Innovation.Unquantify(this.excBuf, num5, this.subframeSize, bits); for (int i = num5; i < num5 + this.subframeSize; i++) { this.excBuf[i] *= num12; } if (this.submodes[this.submodeID].DoubleCodebook != 0) { for (int i = 0; i < this.subframeSize; i++) { this.innov2[i] = 0f; } this.submodes[this.submodeID].Innovation.Unquantify(this.innov2, 0, this.subframeSize, bits); for (int i = 0; i < this.subframeSize; i++) { this.innov2[i] *= num12 * 0.4f; } for (int i = 0; i < this.subframeSize; i++) { this.excBuf[num5 + i] += this.innov2[i]; } } } for (int i = num5; i < num5 + this.subframeSize; i++) { this.high[i] = this.excBuf[i]; } if (this.enhanced) { Filters.Filter_mem2(this.high, num5, this.awk2, this.awk1, this.subframeSize, this.lpcSize, this.mem_sp, this.lpcSize); Filters.Filter_mem2(this.high, num5, this.awk3, this.interp_qlpc, this.subframeSize, this.lpcSize, this.mem_sp, 0); } else { for (int i = 0; i < this.lpcSize; i++) { this.mem_sp[this.lpcSize + i] = 0f; } Filters.Iir_mem2(this.high, num5, this.interp_qlpc, this.high, num5, this.subframeSize, this.lpcSize, this.mem_sp); } } this.filters.Fir_mem_up(this.x0d, Codebook_Constants.h0, this.y0, this.fullFrameSize, 64, this.g0_mem); this.filters.Fir_mem_up(this.high, Codebook_Constants.h1, this.y1, this.fullFrameSize, 64, this.g1_mem); for (int i = 0; i < this.fullFrameSize; i++) { xout[i] = 2f * (this.y0[i] - this.y1[i]); } for (int i = 0; i < this.lpcSize; i++) { this.old_qlsp[i] = this.qlsp[i]; } this.first = 0; return(0); } if (dtx) { this.DecodeLost(xout, true); return(0); } for (int i = 0; i < this.frameSize; i++) { this.excBuf[i] = 0f; } this.first = 1; Filters.Iir_mem2(this.excBuf, this.excIdx, this.interp_qlpc, this.high, 0, this.frameSize, this.lpcSize, this.mem_sp); this.filters.Fir_mem_up(this.x0d, Codebook_Constants.h0, this.y0, this.fullFrameSize, 64, this.g0_mem); this.filters.Fir_mem_up(this.high, Codebook_Constants.h1, this.y1, this.fullFrameSize, 64, this.g1_mem); for (int i = 0; i < this.fullFrameSize; i++) { xout[i] = 2f * (this.y0[i] - this.y1[i]); } return(0); }