/// <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);
        }
Exemple #2
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);
        }