namespace NSpeex { using System; internal class SbDecoder : SbCodec, IDecoder { protected internal bool enhanced; private float[] innov2; protected internal IDecoder lowdec; protected internal Stereo stereo; public SbDecoder(bool ultraWide) : base(ultraWide) { this.stereo = new Stereo(); this.enhanced = true; if (ultraWide) { this.Uwbinit(); } else { this.Wbinit(); } } public virtual int Decode(Bits bits, float[] xout) { int num4 = this.lowdec.Decode(bits, base.x0d); if (num4 != 0) { return num4; } bool dtx = this.lowdec.Dtx; if (bits == null) { this.DecodeLost(xout, dtx); return 0; } if (bits.Peek != 0) { int num3 = bits.Unpack(1); base.submodeID = bits.Unpack(3); } else { base.submodeID = 0; } int index = 0; while (index < base.frameSize) { base.excBuf[index] = 0f; index++; } if (base.submodes[base.submodeID] == null) { if (dtx) { this.DecodeLost(xout, true); return 0; } for (index = 0; index < base.frameSize; index++) { base.excBuf[index] = 0f; } base.first = 1; Filters.Iir_mem2(base.excBuf, base.excIdx, base.interp_qlpc, base.high, 0, base.frameSize, base.lpcSize, base.mem_sp); base.filters.Fir_mem_up(base.x0d, Codebook_Constants.h0, base.y0, base.fullFrameSize, 0x40, base.g0_mem); base.filters.Fir_mem_up(base.high, Codebook_Constants.h1, base.y1, base.fullFrameSize, 0x40, base.g1_mem); for (index = 0; index < base.fullFrameSize; index++) { xout[index] = 2f * (base.y0[index] - base.y1[index]); } return 0; } float[] piGain = this.lowdec.PiGain; float[] exc = this.lowdec.Exc; float[] innov = this.lowdec.Innov; base.submodes[base.submodeID].LsqQuant.Unquant(base.qlsp, base.lpcSize, bits); if (base.first != 0) { index = 0; while (index < base.lpcSize) { base.old_qlsp[index] = base.qlsp[index]; index++; } } for (int i = 0; i < base.nbSubframes; i++) { float num7 = 0f; float num8 = 0f; float num9 = 0f; int es = base.subframeSize * i; float num5 = (1f + i) / ((float)base.nbSubframes); index = 0; while (index < base.lpcSize) { base.interp_qlsp[index] = ((1f - num5) * base.old_qlsp[index]) + (num5 * base.qlsp[index]); index++; } Lsp.Enforce_margin(base.interp_qlsp, base.lpcSize, 0.05f); index = 0; while (index < base.lpcSize) { base.interp_qlsp[index] = (float)Math.Cos((double)base.interp_qlsp[index]); index++; } base.m_lsp.Lsp2lpc(base.interp_qlsp, base.interp_qlpc, base.lpcSize); if (this.enhanced) { float gamma = base.submodes[base.submodeID].LpcEnhK1; float num12 = base.submodes[base.submodeID].LpcEnhK2; float num13 = gamma - num12; Filters.Bw_lpc(gamma, base.interp_qlpc, base.awk1, base.lpcSize); Filters.Bw_lpc(num12, base.interp_qlpc, base.awk2, base.lpcSize); Filters.Bw_lpc(num13, base.interp_qlpc, base.awk3, base.lpcSize); } num5 = 1f; base.pi_gain[i] = 0f; index = 0; while (index <= base.lpcSize) { num9 += num5 * base.interp_qlpc[index]; num5 = -num5; base.pi_gain[i] += base.interp_qlpc[index]; index++; } num8 = piGain[i]; num8 = 1f / (Math.Abs(num8) + 0.01f); num9 = 1f / (Math.Abs(num9) + 0.01f); float num6 = Math.Abs((float)(0.01f + num9)) / (0.01f + Math.Abs(num8)); index = es; while (index < (es + base.subframeSize)) { base.excBuf[index] = 0f; index++; } if (base.submodes[base.submodeID].Innovation == null) { float num14 = (float)Math.Exp((bits.Unpack(5) - 10.0) / 8.0); num14 /= num6; index = es; while (index < (es + base.subframeSize)) { base.excBuf[index] = (base.foldingGain * num14) * innov[index]; index++; } } else { int num18 = bits.Unpack(4); index = es; while (index < (es + base.subframeSize)) { num7 += exc[index] * exc[index]; index++; } float num16 = (float)Math.Exp((double)((0.2702703f * num18) - 2f)); float num17 = (num16 * ((float)Math.Sqrt((double)(1f + num7)))) / num6; base.submodes[base.submodeID].Innovation.Unquantify(base.excBuf, es, base.subframeSize, bits); index = es; while (index < (es + base.subframeSize)) { base.excBuf[index] *= num17; index++; } if (base.submodes[base.submodeID].DoubleCodebook != 0) { index = 0; while (index < base.subframeSize) { this.innov2[index] = 0f; index++; } base.submodes[base.submodeID].Innovation.Unquantify(this.innov2, 0, base.subframeSize, bits); index = 0; while (index < base.subframeSize) { this.innov2[index] *= num17 * 0.4f; index++; } index = 0; while (index < base.subframeSize) { base.excBuf[es + index] += this.innov2[index]; index++; } } } index = es; while (index < (es + base.subframeSize)) { base.high[index] = base.excBuf[index]; index++; } if (this.enhanced) { Filters.Filter_mem2(base.high, es, base.awk2, base.awk1, base.subframeSize, base.lpcSize, base.mem_sp, base.lpcSize); Filters.Filter_mem2(base.high, es, base.awk3, base.interp_qlpc, base.subframeSize, base.lpcSize, base.mem_sp, 0); } else { index = 0; while (index < base.lpcSize) { base.mem_sp[base.lpcSize + index] = 0f; index++; } Filters.Iir_mem2(base.high, es, base.interp_qlpc, base.high, es, base.subframeSize, base.lpcSize, base.mem_sp); } } base.filters.Fir_mem_up(base.x0d, Codebook_Constants.h0, base.y0, base.fullFrameSize, 0x40, base.g0_mem); base.filters.Fir_mem_up(base.high, Codebook_Constants.h1, base.y1, base.fullFrameSize, 0x40, base.g1_mem); for (index = 0; index < base.fullFrameSize; index++) { xout[index] = 2f * (base.y0[index] - base.y1[index]); } for (index = 0; index < base.lpcSize; index++) { base.old_qlsp[index] = base.qlsp[index]; } base.first = 0; return 0; } public int DecodeLost(float[] xout, bool dtx) { int num; int submodeID = 0; if (dtx) { submodeID = base.submodeID; base.submodeID = 1; } else { Filters.Bw_lpc(0.99f, base.interp_qlpc, base.interp_qlpc, base.lpcSize); } base.first = 1; base.awk1 = new float[base.lpcSize + 1]; base.awk2 = new float[base.lpcSize + 1]; base.awk3 = new float[base.lpcSize + 1]; if (this.enhanced) { float num3; float num4; if (base.submodes[base.submodeID] != null) { num3 = base.submodes[base.submodeID].LpcEnhK1; num4 = base.submodes[base.submodeID].LpcEnhK2; } else { num3 = num4 = 0.7f; } float gamma = num3 - num4; Filters.Bw_lpc(num3, base.interp_qlpc, base.awk1, base.lpcSize); Filters.Bw_lpc(num4, base.interp_qlpc, base.awk2, base.lpcSize); Filters.Bw_lpc(gamma, base.interp_qlpc, base.awk3, base.lpcSize); } if (!dtx) { for (num = 0; num < base.frameSize; num++) { float? nullable = 0.9f; base.excBuf[base.excIdx + num] *= nullable.Value; } } num = 0; while (num < base.frameSize) { base.high[num] = base.excBuf[base.excIdx + num]; num++; } if (this.enhanced) { Filters.Filter_mem2(base.high, 0, base.awk2, base.awk1, base.high, 0, base.frameSize, base.lpcSize, base.mem_sp, base.lpcSize); Filters.Filter_mem2(base.high, 0, base.awk3, base.interp_qlpc, base.high, 0, base.frameSize, base.lpcSize, base.mem_sp, 0); } else { for (num = 0; num < base.lpcSize; num++) { base.mem_sp[base.lpcSize + num] = 0f; } Filters.Iir_mem2(base.high, 0, base.interp_qlpc, base.high, 0, base.frameSize, base.lpcSize, base.mem_sp); } base.filters.Fir_mem_up(base.x0d, Codebook_Constants.h0, base.y0, base.fullFrameSize, 0x40, base.g0_mem); base.filters.Fir_mem_up(base.high, Codebook_Constants.h1, base.y1, base.fullFrameSize, 0x40, base.g1_mem); for (num = 0; num < base.fullFrameSize; num++) { xout[num] = 2f * (base.y0[num] - base.y1[num]); } if (dtx) { base.submodeID = submodeID; } return 0; } public virtual void DecodeStereo(float[] data, int frameSize) { this.stereo.Decode(data, frameSize); } protected override void Init(int frameSize, int subframeSize, int lpcSize, int bufSize, float foldingGain) { base.Init(frameSize, subframeSize, lpcSize, bufSize, foldingGain); base.excIdx = 0; this.innov2 = new float[subframeSize]; } private void Uwbinit() { this.lowdec = new SbDecoder(false); this.lowdec.PerceptualEnhancement = this.enhanced; this.Init(320, 80, 8, 0x500, 0.5f); } private void Wbinit() { this.lowdec = new NbDecoder(); this.lowdec.PerceptualEnhancement = this.enhanced; this.Init(160, 40, 8, 640, 0.7f); } public virtual bool PerceptualEnhancement { get { return this.enhanced; } set { this.enhanced = value; } } } }