public FilterBank(bool smallFrames, int channels)
        {
            if (smallFrames)
            {
                length        = WINDOW_SMALL_LEN_LONG;
                shortLen      = WINDOW_SMALL_LEN_SHORT;
                LONG_WINDOWS  = new[] { SINE_960, KBD_960 };
                SHORT_WINDOWS = new[] { SINE_120, KBD_120 };
            }
            else
            {
                length        = WINDOW_LEN_LONG;
                shortLen      = WINDOW_LEN_SHORT;
                LONG_WINDOWS  = new[] { SINE_1024, KBD_1024 };
                SHORT_WINDOWS = new[] { SINE_128, KBD_128 };
            }
            mid   = (length - shortLen) / 2;
            trans = shortLen / 2;

            mdctShort = new MDCT(shortLen * 2);
            mdctLong  = new MDCT(length * 2);

            overlaps = Enumerable.Range(0, channels).Select(x => new float[length]).ToArray();
            buf      = new float[2 * length];
        }
Exemplo n.º 2
0
        // fixme: test the perf of this alternate implementation
        //int logSum(int a, int b)
        //{
        //    return log2(pow(4, a) + pow(4, b)) / 2;
        //}

        internal static void surround_analysis <T>(CeltMode celt_mode, T[] pcm, int pcm_ptr,
                                                   int[] bandLogE, int[] mem, int[] preemph_mem,
                                                   int len, int overlap, int channels, int rate, opus_copy_channel_in_func <T> copy_channel_in
                                                   )
        {
            int c;
            int i;
            int LM;

            int[] pos = { 0, 0, 0, 0, 0, 0, 0, 0 };
            int   upsample;
            int   frame_size;
            int   channel_offset;

            int[][] bandE    = Arrays.InitTwoDimensionalArray <int>(1, 21);
            int[][] maskLogE = Arrays.InitTwoDimensionalArray <int>(3, 21);
            int[]   input;
            short[] x;
            int[][] freq;

            upsample   = CeltCommon.resampling_factor(rate);
            frame_size = len * upsample;

            for (LM = 0; LM < celt_mode.maxLM; LM++)
            {
                if (celt_mode.shortMdctSize << LM == frame_size)
                {
                    break;
                }
            }

            input = new int[frame_size + overlap];
            x     = new short[len];
            freq  = Arrays.InitTwoDimensionalArray <int>(1, frame_size);

            channel_pos(channels, pos);

            for (c = 0; c < 3; c++)
            {
                for (i = 0; i < 21; i++)
                {
                    maskLogE[c][i] = -((short)(0.5 + (28.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(28.0f, CeltConstants.DB_SHIFT)*/;
                }
            }

            for (c = 0; c < channels; c++)
            {
                Array.Copy(mem, c * overlap, input, 0, overlap);
                copy_channel_in(x, 0, 1, pcm, pcm_ptr, channels, c, len);
                BoxedValueInt boxed_preemph = new BoxedValueInt(preemph_mem[c]);
                CeltCommon.celt_preemphasis(x, input, overlap, frame_size, 1, upsample, celt_mode.preemph, boxed_preemph, 0);
                preemph_mem[c] = boxed_preemph.Val;

                MDCT.clt_mdct_forward(
                    celt_mode.mdct,
                    input,
                    0,
                    freq[0],
                    0,
                    celt_mode.window,
                    overlap,
                    celt_mode.maxLM - LM,
                    1);
                if (upsample != 1)
                {
                    int bound = len;
                    for (i = 0; i < bound; i++)
                    {
                        freq[0][i] *= upsample;
                    }
                    for (; i < frame_size; i++)
                    {
                        freq[0][i] = 0;
                    }
                }

                Bands.compute_band_energies(celt_mode, freq, bandE, 21, 1, LM);
                QuantizeBands.amp2Log2(celt_mode, 21, 21, bandE[0], bandLogE, 21 * c, 1);
                /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
                for (i = 1; i < 21; i++)
                {
                    bandLogE[21 * c + i] = Inlines.MAX16(bandLogE[21 * c + i], bandLogE[21 * c + i - 1] - ((short)(0.5 + (1.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(1.0f, CeltConstants.DB_SHIFT)*/);
                }
                for (i = 19; i >= 0; i--)
                {
                    bandLogE[21 * c + i] = Inlines.MAX16(bandLogE[21 * c + i], bandLogE[21 * c + i + 1] - ((short)(0.5 + (2.0f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(2.0f, CeltConstants.DB_SHIFT)*/);
                }
                if (pos[c] == 1)
                {
                    for (i = 0; i < 21; i++)
                    {
                        maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21 * c + i]);
                    }
                }
                else if (pos[c] == 3)
                {
                    for (i = 0; i < 21; i++)
                    {
                        maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21 * c + i]);
                    }
                }
                else if (pos[c] == 2)
                {
                    for (i = 0; i < 21; i++)
                    {
                        maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21 * c + i] - ((short)(0.5 + (.5f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(.5f, CeltConstants.DB_SHIFT)*/);
                        maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21 * c + i] - ((short)(0.5 + (.5f) * (((int)1) << (CeltConstants.DB_SHIFT)))) /*Inlines.QCONST16(.5f, CeltConstants.DB_SHIFT)*/);
                    }
                }
                Array.Copy(input, frame_size, mem, c * overlap, overlap);
            }
            for (i = 0; i < 21; i++)
            {
                maskLogE[1][i] = Inlines.MIN32(maskLogE[0][i], maskLogE[2][i]);
            }
            channel_offset = Inlines.HALF16(Inlines.celt_log2(((int)(0.5 + (2.0f) * (((int)1) << (14)))) /*Inlines.QCONST32(2.0f, 14)*/ / (channels - 1)));
            for (c = 0; c < 3; c++)
            {
                for (i = 0; i < 21; i++)
                {
                    maskLogE[c][i] += channel_offset;
                }
            }

            for (c = 0; c < channels; c++)
            {
                int[] mask;
                if (pos[c] != 0)
                {
                    mask = maskLogE[pos[c] - 1];
                    for (i = 0; i < 21; i++)
                    {
                        bandLogE[21 * c + i] = bandLogE[21 * c + i] - mask[i];
                    }
                }
                else
                {
                    for (i = 0; i < 21; i++)
                    {
                        bandLogE[21 * c + i] = 0;
                    }
                }
            }
        }