Example #1
0
    //Initialization. Material is duplicated due to previous implementation - currently serves no purpose.
    private void Awake()
    {
        rb = GetComponent <Rigidbody>();
        mr = GetComponent <MeshRenderer>();

        Material newMat = Instantiate(mr.material);

        mr.material = newMat;

        start = new VQ(transform.position, transform.rotation);
    }
Example #2
0
        internal void celt_decode_lost(int N, int LM)
        {
            int c;
            int i;
            int C = this.channels;

            int[][]  out_syn      = new int[2][];
            int[]    out_syn_ptrs = new int[2];
            CeltMode mode;
            int      nbEBands;
            int      overlap;
            int      noise_based;

            short[] eBands;

            mode     = this.mode;
            nbEBands = mode.nbEBands;
            overlap  = mode.overlap;
            eBands   = mode.eBands;

            c = 0; do
            {
                out_syn[c]      = this.decode_mem[c];
                out_syn_ptrs[c] = CeltConstants.DECODE_BUFFER_SIZE - N;
            } while (++c < C);

            noise_based = (loss_count >= 5 || start != 0) ? 1 : 0;
            if (noise_based != 0)
            {
                /* Noise-based PLC/CNG */
                int[][] X;
                uint    seed;
                int     end;
                int     effEnd;
                int     decay;
                end    = this.end;
                effEnd = Inlines.IMAX(start, Inlines.IMIN(end, mode.effEBands));

                X = Arrays.InitTwoDimensionalArray <int>(C, N);   /**< Interleaved normalised MDCTs */

                /* Energy decay */
                decay = loss_count == 0 ? ((short)(0.5 + (1.5f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(1.5f, CeltConstants.DB_SHIFT)*/ : ((short)(0.5 + (0.5f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(0.5f, CeltConstants.DB_SHIFT)*/;
                c     = 0; do
                {
                    for (i = start; i < end; i++)
                    {
                        this.oldEBands[c * nbEBands + i] = Inlines.MAX16(backgroundLogE[c * nbEBands + i], this.oldEBands[c * nbEBands + i] - decay);
                    }
                } while (++c < C);
                seed = this.rng;
                for (c = 0; c < C; c++)
                {
                    for (i = start; i < effEnd; i++)
                    {
                        int j;
                        int boffs;
                        int blen;
                        boffs = (eBands[i] << LM);
                        blen  = (eBands[i + 1] - eBands[i]) << LM;
                        for (j = 0; j < blen; j++)
                        {
                            seed            = Bands.celt_lcg_rand(seed);
                            X[c][boffs + j] = (unchecked ((int)seed) >> 20);
                        }

                        VQ.renormalise_vector(X[c], 0, blen, CeltConstants.Q15ONE);
                    }
                }
                this.rng = seed;

                c = 0;
                do
                {
                    Arrays.MemMoveInt(this.decode_mem[c], N, 0, CeltConstants.DECODE_BUFFER_SIZE - N + (overlap >> 1));
                } while (++c < C);

                CeltCommon.celt_synthesis(mode, X, out_syn, out_syn_ptrs, this.oldEBands, start, effEnd, C, C, 0, LM, this.downsample, 0);
            }
            else
            {
                /* Pitch-based PLC */
                int[] window;
                int   fade = CeltConstants.Q15ONE;
                int   pitch_index;
                int[] etmp;
                int[] exc;

                if (loss_count == 0)
                {
                    this.last_pitch_index = pitch_index = CeltCommon.celt_plc_pitch_search(this.decode_mem, C);
                }
                else
                {
                    pitch_index = this.last_pitch_index;
                    fade        = ((short)(0.5 + (.8f) * (((int)1) << (15)))) /*Inlines.QCONST16(.8f, 15)*/;
                }

                etmp   = new int[overlap];
                exc    = new int[CeltConstants.MAX_PERIOD];
                window = mode.window;
                c      = 0; do
                {
                    int   decay;
                    int   attenuation;
                    int   S1 = 0;
                    int[] buf;
                    int   extrapolation_offset;
                    int   extrapolation_len;
                    int   exc_length;
                    int   j;

                    buf = this.decode_mem[c];
                    for (i = 0; i < CeltConstants.MAX_PERIOD; i++)
                    {
                        exc[i] = Inlines.ROUND16(buf[CeltConstants.DECODE_BUFFER_SIZE - CeltConstants.MAX_PERIOD + i], CeltConstants.SIG_SHIFT);
                    }

                    if (loss_count == 0)
                    {
                        int[] ac = new int[CeltConstants.LPC_ORDER + 1];

                        /* Compute LPC coefficients for the last MAX_PERIOD samples before
                         * the first loss so we can work in the excitation-filter domain. */
                        Autocorrelation._celt_autocorr(exc, ac, window, overlap,
                                                       CeltConstants.LPC_ORDER, CeltConstants.MAX_PERIOD);
                        /* Add a noise floor of -40 dB. */
                        ac[0] += Inlines.SHR32(ac[0], 13);
                        /* Use lag windowing to stabilize the Levinson-Durbin recursion. */
                        for (i = 1; i <= CeltConstants.LPC_ORDER; i++)
                        {
                            /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
                            ac[i] -= Inlines.MULT16_32_Q15(2 * i * i, ac[i]);
                        }
                        CeltLPC.celt_lpc(this.lpc[c], ac, CeltConstants.LPC_ORDER);
                    }

                    /* We want the excitation for 2 pitch periods in order to look for a
                     * decaying signal, but we can't get more than MAX_PERIOD. */
                    exc_length = Inlines.IMIN(2 * pitch_index, CeltConstants.MAX_PERIOD);

                    /* Initialize the LPC history with the samples just before the start
                     * of the region for which we're computing the excitation. */
                    {
                        int[] lpc_mem = new int[CeltConstants.LPC_ORDER];
                        for (i = 0; i < CeltConstants.LPC_ORDER; i++)
                        {
                            lpc_mem[i] =
                                Inlines.ROUND16(buf[CeltConstants.DECODE_BUFFER_SIZE - exc_length - 1 - i], CeltConstants.SIG_SHIFT);
                        }

                        /* Compute the excitation for exc_length samples before the loss. */
                        Kernels.celt_fir(exc, (CeltConstants.MAX_PERIOD - exc_length), this.lpc[c], 0,
                                         exc, (CeltConstants.MAX_PERIOD - exc_length), exc_length, CeltConstants.LPC_ORDER, lpc_mem);
                    }

                    /* Check if the waveform is decaying, and if so how fast.
                     * We do this to avoid adding energy when concealing in a segment
                     * with decaying energy. */
                    {
                        int E1 = 1, E2 = 1;
                        int decay_length;
                        int shift = Inlines.IMAX(0, 2 * Inlines.celt_zlog2(Inlines.celt_maxabs16(exc, (CeltConstants.MAX_PERIOD - exc_length), exc_length)) - 20);
                        decay_length = exc_length >> 1;
                        for (i = 0; i < decay_length; i++)
                        {
                            int e;
                            e   = exc[CeltConstants.MAX_PERIOD - decay_length + i];
                            E1 += Inlines.SHR32(Inlines.MULT16_16(e, e), shift);
                            e   = exc[CeltConstants.MAX_PERIOD - 2 * decay_length + i];
                            E2 += Inlines.SHR32(Inlines.MULT16_16(e, e), shift);
                        }
                        E1    = Inlines.MIN32(E1, E2);
                        decay = Inlines.celt_sqrt(Inlines.frac_div32(Inlines.SHR32(E1, 1), E2));
                    }

                    /* Move the decoder memory one frame to the left to give us room to
                     * add the data for the new frame. We ignore the overlap that extends
                     * past the end of the buffer, because we aren't going to use it. */
                    Arrays.MemMoveInt(buf, N, 0, CeltConstants.DECODE_BUFFER_SIZE - N);

                    /* Extrapolate from the end of the excitation with a period of
                     * "pitch_index", scaling down each period by an additional factor of
                     * "decay". */
                    extrapolation_offset = CeltConstants.MAX_PERIOD - pitch_index;

                    /* We need to extrapolate enough samples to cover a complete MDCT
                     * window (including overlap/2 samples on both sides). */
                    extrapolation_len = N + overlap;
                    /* We also apply fading if this is not the first loss. */
                    attenuation = Inlines.MULT16_16_Q15(fade, decay);
                    for (i = j = 0; i < extrapolation_len; i++, j++)
                    {
                        int tmp;
                        if (j >= pitch_index)
                        {
                            j          -= pitch_index;
                            attenuation = Inlines.MULT16_16_Q15(attenuation, decay);
                        }
                        buf[CeltConstants.DECODE_BUFFER_SIZE - N + i] =
                            Inlines.SHL32((Inlines.MULT16_16_Q15(attenuation,
                                                                 exc[extrapolation_offset + j])), CeltConstants.SIG_SHIFT);

                        /* Compute the energy of the previously decoded signal whose
                         * excitation we're copying. */
                        tmp = Inlines.ROUND16(
                            buf[CeltConstants.DECODE_BUFFER_SIZE - CeltConstants.MAX_PERIOD - N + extrapolation_offset + j],
                            CeltConstants.SIG_SHIFT);
                        S1 += Inlines.SHR32(Inlines.MULT16_16(tmp, tmp), 8);
                    }

                    {
                        int[] lpc_mem = new int[CeltConstants.LPC_ORDER];

                        /* Copy the last decoded samples (prior to the overlap region) to
                         * synthesis filter memory so we can have a continuous signal. */
                        for (i = 0; i < CeltConstants.LPC_ORDER; i++)
                        {
                            lpc_mem[i] = Inlines.ROUND16(buf[CeltConstants.DECODE_BUFFER_SIZE - N - 1 - i], CeltConstants.SIG_SHIFT);
                        }

                        /* Apply the synthesis filter to convert the excitation back into
                         * the signal domain. */
                        CeltLPC.celt_iir(buf, CeltConstants.DECODE_BUFFER_SIZE - N, this.lpc[c],
                                         buf, CeltConstants.DECODE_BUFFER_SIZE - N, extrapolation_len, CeltConstants.LPC_ORDER,
                                         lpc_mem);
                    }

                    /* Check if the synthesis energy is higher than expected, which can
                     * happen with the signal changes during our window. If so,
                     * attenuate. */
                    {
                        int S2 = 0;
                        for (i = 0; i < extrapolation_len; i++)
                        {
                            int tmp = Inlines.ROUND16(buf[CeltConstants.DECODE_BUFFER_SIZE - N + i], CeltConstants.SIG_SHIFT);
                            S2 += Inlines.SHR32(Inlines.MULT16_16(tmp, tmp), 8);
                        }
                        /* This checks for an "explosion" in the synthesis. */
                        if (!(S1 > Inlines.SHR32(S2, 2)))
                        {
                            for (i = 0; i < extrapolation_len; i++)
                            {
                                buf[CeltConstants.DECODE_BUFFER_SIZE - N + i] = 0;
                            }
                        }
                        else if (S1 < S2)
                        {
                            int ratio = Inlines.celt_sqrt(Inlines.frac_div32(Inlines.SHR32(S1, 1) + 1, S2 + 1));
                            for (i = 0; i < overlap; i++)
                            {
                                int tmp_g = CeltConstants.Q15ONE
                                            - Inlines.MULT16_16_Q15(window[i], CeltConstants.Q15ONE - ratio);
                                buf[CeltConstants.DECODE_BUFFER_SIZE - N + i] =
                                    Inlines.MULT16_32_Q15(tmp_g, buf[CeltConstants.DECODE_BUFFER_SIZE - N + i]);
                            }
                            for (i = overlap; i < extrapolation_len; i++)
                            {
                                buf[CeltConstants.DECODE_BUFFER_SIZE - N + i] =
                                    Inlines.MULT16_32_Q15(ratio, buf[CeltConstants.DECODE_BUFFER_SIZE - N + i]);
                            }
                        }
                    }

                    /* Apply the pre-filter to the MDCT overlap for the next frame because
                     * the post-filter will be re-applied in the decoder after the MDCT
                     * overlap. */
                    CeltCommon.comb_filter(etmp, 0, buf, CeltConstants.DECODE_BUFFER_SIZE,
                                           this.postfilter_period, this.postfilter_period, overlap,
                                           -this.postfilter_gain, -this.postfilter_gain,
                                           this.postfilter_tapset, this.postfilter_tapset, null, 0);

                    /* Simulate TDAC on the concealed audio so that it blends with the
                     * MDCT of the next frame. */
                    for (i = 0; i < overlap / 2; i++)
                    {
                        buf[CeltConstants.DECODE_BUFFER_SIZE + i] =
                            Inlines.MULT16_32_Q15(window[i], etmp[overlap - 1 - i])
                            + Inlines.MULT16_32_Q15(window[overlap - i - 1], etmp[i]);
                    }
                } while (++c < C);
            }

            this.loss_count = loss_count + 1;
        }
Example #3
0
        /// <summary>
        /// Codebook Search Quantification (Split Shape).
        /// </summary>
        /// <param name="target"></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,
                                          Bits bits, int complexity)
        {
            int i, j, k, m, n, q;

            float[] resp;
            float[] ndist, odist;
            int[]   best_index;
            float[] best_dist;

            int N = complexity;

            if (N > 10)
            {
                N = 10;
            }

            resp = new float[_shapeCbSize * _subVectSize];

            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 < _nbSubvect; 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);

            /* Pre-compute codewords response and energy */
            for (i = 0; i < _shapeCbSize; i++)
            {
                int res;
                int shape;

                res   = i * _subVectSize;
                shape = i * _subVectSize;

                /* Compute codeword response using convolution with impulse response */
                for (j = 0; j < _subVectSize; j++)
                {
                    resp[res + j] = 0;
                    for (k = 0; k <= j; k++)
                    {
                        resp[res + j] += 0.03125f * _shapeCb[shape + k] * r[j - k];
                    }
                }

                /* Compute codeword energy */
                E[i] = 0;
                for (j = 0; j < _subVectSize; j++)
                {
                    E[i] += resp[res + j] * resp[res + j];
                }
            }

            for (j = 0; j < N; j++)
            {
                odist[j] = 0;
            }
            /*For all subvectors*/
            for (i = 0; i < _nbSubvect; i++)
            {
                int offset = i * _subVectSize;
                /*"erase" nbest list*/
                for (j = 0; j < N; j++)
                {
                    ndist[j] = -1;
                }

                /*For all n-bests of previous subvector*/
                for (j = 0; j < N; j++)
                {
                    /*Find new n-best based on previous n-best j*/
                    if (_haveSign != 0)
                    {
                        VQ.nbest_sign(_ot[j], offset, resp, _subVectSize, _shapeCbSize, E, N, best_index, best_dist);
                    }
                    else
                    {
                        VQ.nbest(_ot[j], offset, resp, _subVectSize, _shapeCbSize, E, N, best_index, best_dist);
                    }

                    /*For all new n-bests*/
                    for (k = 0; k < N; k++)
                    {
                        float[] ct;
                        float   err = 0;
                        ct = _ot[j];
                        /*update target*/

                        /*previous target*/
                        for (m = offset; m < offset + _subVectSize; m++)
                        {
                            t[m] = ct[m];
                        }

                        /* New code: update only enough of the target to calculate error*/
                        {
                            int   rind;
                            int   res;
                            float sign = 1;
                            rind = best_index[k];
                            if (rind >= _shapeCbSize)
                            {
                                sign  = -1;
                                rind -= _shapeCbSize;
                            }
                            res = rind * _subVectSize;
                            if (sign > 0)
                            {
                                for (m = 0; m < _subVectSize; m++)
                                {
                                    t[offset + m] -= resp[res + m];
                                }
                            }
                            else
                            {
                                for (m = 0; m < _subVectSize; m++)
                                {
                                    t[offset + m] += resp[res + m];
                                }
                            }
                        }

                        /*compute error (distance)*/
                        err = odist[j];
                        for (m = offset; m < offset + _subVectSize; m++)
                        {
                            err += t[m] * t[m];
                        }
                        /*update n-best list*/
                        if (err < ndist[N - 1] || ndist[N - 1] < -.5)
                        {
                            /*previous target (we don't care what happened before*/
                            for (m = offset + _subVectSize; m < nsf; m++)
                            {
                                t[m] = ct[m];
                            }
                            /* New code: update the rest of the target only if it's worth it */
                            for (m = 0; m < _subVectSize; m++)
                            {
                                float g;
                                int   rind;
                                float sign = 1;
                                rind = best_index[k];
                                if (rind >= _shapeCbSize)
                                {
                                    sign  = -1;
                                    rind -= _shapeCbSize;
                                }

                                g = sign * 0.03125f * _shapeCb[rind * _subVectSize + m];
                                q = _subVectSize - m;
                                for (n = offset + _subVectSize; n < nsf; n++, q++)
                                {
                                    t[n] -= g * r[q];
                                }
                            }


                            for (m = 0; m < N; m++)
                            {
                                if (err < ndist[m] || ndist[m] < -.5)
                                {
                                    for (n = N - 1; n > m; n--)
                                    {
                                        for (q = offset + _subVectSize; q < nsf; q++)
                                        {
                                            _nt[n][q] = _nt[n - 1][q];
                                        }
                                        for (q = 0; q < _nbSubvect; q++)
                                        {
                                            _nind[n][q] = _nind[n - 1][q];
                                        }
                                        ndist[n] = ndist[n - 1];
                                    }
                                    for (q = offset + _subVectSize; q < nsf; q++)
                                    {
                                        _nt[m][q] = t[q];
                                    }
                                    for (q = 0; q < _nbSubvect; q++)
                                    {
                                        _nind[m][q] = _oind[j][q];
                                    }
                                    _nind[m][i] = best_index[k];
                                    ndist[m]    = err;
                                    break;
                                }
                            }
                        }
                    }
                    if (i == 0)
                    {
                        break;
                    }
                }

                /*update old-new data*/
                /* just swap pointers instead of a long copy */
                {
                    float[][] tmp2;
                    tmp2 = _ot;
                    _ot  = _nt;
                    _nt  = tmp2;
                }
                for (j = 0; j < N; j++)
                {
                    for (m = 0; m < _nbSubvect; m++)
                    {
                        _oind[j][m] = _nind[j][m];
                    }
                }
                for (j = 0; j < N; j++)
                {
                    odist[j] = ndist[j];
                }
            }

            /*save indices*/
            for (i = 0; i < _nbSubvect; i++)
            {
                _ind[i] = _nind[0][i];
                bits.Pack(_ind[i], _shapeBits + _haveSign);
            }

            /* Put everything back together */
            for (i = 0; i < _nbSubvect; i++)
            {
                int   rind;
                float sign = 1;
                rind = _ind[i];
                if (rind >= _shapeCbSize)
                {
                    sign  = -1;
                    rind -= _shapeCbSize;
                }

                for (j = 0; j < _subVectSize; j++)
                {
                    e[_subVectSize * i + j] = sign * 0.03125f * _shapeCb[rind * _subVectSize + j];
                }
            }
            /* Update excitation */
            for (j = 0; j < nsf; j++)
            {
                exc[es + j] += e[j];
            }

            /* Update target */
            Filters.syn_percep_zero(e, 0, ak, awk1, awk2, r2, nsf, p);
            for (j = 0; j < nsf; j++)
            {
                target[j] -= r2[j];
            }
        }