Ejemplo n.º 1
0
 private static string PrintForceMode(OpusMode mode)
 {
     if (mode == OpusMode.MODE_CELT_ONLY)
     {
         return("CELT");
     }
     if (mode == OpusMode.MODE_SILK_ONLY)
     {
         return("SILK");
     }
     return("    ");
 }
Ejemplo n.º 2
0
 /// <summary>
 /// OPUS_DECODER_RESET_START
 /// </summary>
 internal void PartialReset()
 {
     stream_channels      = 0;
     bandwidth            = 0;
     mode                 = 0;
     prev_mode            = 0;
     frame_size           = 0;
     prev_redundancy      = 0;
     last_packet_duration = 0;
     rangeFinal           = 0;
     // fixme: do these get reset here? I don't think they do because init_celt and init_silk should both call RESET_STATE on their respective states
     //SilkDecoder.Reset();
     //CeltDecoder.Reset();
 }
Ejemplo n.º 3
0
        /** Initializes a previously allocated decoder state.
         * The state must be at least the size returned by opus_decoder_get_size().
         * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size
         * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
         * @param [in] st <tt>OpusDecoder*</tt>: Decoder state.
         * @param [in] Fs <tt>opus_int32</tt>: Sampling rate to decode to (Hz).
         *                                     This must be one of 8000, 12000, 16000,
         *                                     24000, or 48000.
         * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
         * @retval #OPUS_OK Success or @ref opus_errorcodes
         */
        internal int opus_decoder_init(int Fs, int channels)
        {
            SilkDecoder silk_dec;
            CeltDecoder celt_dec;
            int         ret;

            if ((Fs != 48000 && Fs != 24000 && Fs != 16000 && Fs != 12000 && Fs != 8000) ||
                (channels != 1 && channels != 2))
            {
                return(OpusError.OPUS_BAD_ARG);
            }
            this.Reset();

            /* Initialize SILK encoder */
            silk_dec             = this.SilkDecoder;
            celt_dec             = this.Celt_Decoder;
            this.stream_channels = this.channels = channels;

            this.Fs = Fs;
            this.DecControl.API_sampleRate = this.Fs;
            this.DecControl.nChannelsAPI   = this.channels;

            /* Reset decoder */
            ret = DecodeAPI.silk_InitDecoder(silk_dec);
            if (ret != 0)
            {
                return(OpusError.OPUS_INTERNAL_ERROR);
            }

            /* Initialize CELT decoder */
            ret = celt_dec.celt_decoder_init(Fs, channels);
            if (ret != OpusError.OPUS_OK)
            {
                return(OpusError.OPUS_INTERNAL_ERROR);
            }

            celt_dec.SetSignalling(0);

            this.prev_mode  = 0;
            this.frame_size = Fs / 400;
            return(OpusError.OPUS_OK);
        }
Ejemplo n.º 4
0
        internal static byte gen_toc(OpusMode mode, int framerate, OpusBandwidth bandwidth, int channels)
        {
            int  period;
            byte toc;

            period = 0;
            while (framerate < 400)
            {
                framerate <<= 1;
                period++;
            }
            if (mode == OpusMode.MODE_SILK_ONLY)
            {
                toc  = (byte)((bandwidth - OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND) << 5);
                toc |= (byte)((period - 2) << 3);
            }
            else if (mode == OpusMode.MODE_CELT_ONLY)
            {
                int tmp = bandwidth - OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND;
                if (tmp < 0)
                {
                    tmp = 0;
                }
                toc  = 0x80;
                toc |= (byte)(tmp << 5);
                toc |= (byte)(period << 3);
            }
            else /* Hybrid */
            {
                toc  = 0x60;
                toc |= (byte)((bandwidth - OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND) << 4);
                toc |= (byte)((period - 2) << 3);
            }
            toc |= (byte)((channels == 2 ? 1 : 0) << 2);
            return(toc);
        }
Ejemplo n.º 5
0
        public static void Main(string[] args)
        {
            LoadTestFile(8, false);
            LoadTestFile(12, false);
            LoadTestFile(16, false);
            LoadTestFile(24, false);
            LoadTestFile(48, false);
            LoadTestFile(8, true);
            LoadTestFile(12, true);
            LoadTestFile(16, true);
            LoadTestFile(24, true);
            LoadTestFile(48, true);

            OpusApplication[] Applications = new OpusApplication[] { OpusApplication.OPUS_APPLICATION_AUDIO, OpusApplication.OPUS_APPLICATION_VOIP, OpusApplication.OPUS_APPLICATION_RESTRICTED_LOWDELAY };
            int[]             Bitrates     = new int[] { -1, 6, 16, 20, 32, 64, 500 };
            int[]             Channels     = new int[] { 1, 2 };
            int[]             Complexities = new int[] { 0, 2, 4, 6, 8, 10 };
            int[]             SampleRates  = new int[] { 8000, 12000, 16000, 24000, 48000 };
            double[]          FrameSizes   = new double[] { 2.5, 5, 10, 20, 40, 60 };
            int[]             PacketLosses = new int[] { 0, 20 };
            OpusMode[]        ForceModes   = new OpusMode[] { OpusMode.MODE_AUTO, OpusMode.MODE_CELT_ONLY, OpusMode.MODE_SILK_ONLY };
            bool[]            DTXModes     = new bool[] { false, true };
            int[]             VBRModes     = new int[] { 0, 1, 2 };

            IList <TestParameters> allTests = new List <TestParameters>();

            for (int app_idx = 0; app_idx < Applications.Length; app_idx++)
            {
                for (int plc_idx = 0; plc_idx < PacketLosses.Length; plc_idx++)
                {
                    for (int chan_idx = 0; chan_idx < Channels.Length; chan_idx++)
                    {
                        for (int sr_idx = 0; sr_idx < SampleRates.Length; sr_idx++)
                        {
                            for (int fs_idx = 0; fs_idx < FrameSizes.Length; fs_idx++)
                            {
                                for (int cpx_idx = 0; cpx_idx < Complexities.Length; cpx_idx++)
                                {
                                    for (int bit_idx = 0; bit_idx < Bitrates.Length; bit_idx++)
                                    {
                                        for (int fm_idx = 0; fm_idx < ForceModes.Length; fm_idx++)
                                        {
                                            for (int dtx_idx = 0; dtx_idx < DTXModes.Length; dtx_idx++)
                                            {
                                                for (int vbr_idx = 0; vbr_idx < VBRModes.Length; vbr_idx++)
                                                {
                                                    TestParameters newParams = new TestParameters()
                                                    {
                                                        Application       = Applications[app_idx],
                                                        Bitrate           = Bitrates[bit_idx],
                                                        Channels          = Channels[chan_idx],
                                                        Complexity        = Complexities[cpx_idx],
                                                        PacketLossPercent = PacketLosses[plc_idx],
                                                        SampleRate        = SampleRates[sr_idx],
                                                        FrameSize         = FrameSizes[fs_idx],
                                                        ForceMode         = ForceModes[fm_idx],
                                                        UseDTX            = DTXModes[dtx_idx]
                                                    };
                                                    if (VBRModes[vbr_idx] == 0)
                                                    {
                                                        newParams.UseVBR         = false;
                                                        newParams.ConstrainedVBR = false;
                                                    }
                                                    else if (VBRModes[vbr_idx] == 1)
                                                    {
                                                        newParams.UseVBR         = true;
                                                        newParams.ConstrainedVBR = false;
                                                    }
                                                    else if (VBRModes[vbr_idx] == 2)
                                                    {
                                                        newParams.UseVBR         = true;
                                                        newParams.ConstrainedVBR = true;
                                                    }

                                                    // Validate params
                                                    if (newParams.Bitrate > 40 || newParams.FrameSize < 10)
                                                    {
                                                        // No FEC outside of SILK mode
                                                        if (newParams.PacketLossPercent > 0)
                                                        {
                                                            continue;
                                                        }
                                                        // No DTX outside of SILK mode
                                                        if (newParams.UseDTX)
                                                        {
                                                            continue;
                                                        }
                                                        if (newParams.ForceMode == OpusMode.MODE_SILK_ONLY)
                                                        {
                                                            continue;
                                                        }
                                                    }
                                                    // Constrained VBR only applies to CELT
                                                    if (newParams.ForceMode == OpusMode.MODE_SILK_ONLY && newParams.ConstrainedVBR)
                                                    {
                                                        continue;
                                                    }
                                                    // 12Khz + 2.5ms triggers an opus bug for now
                                                    if (newParams.SampleRate == 12000 && newParams.FrameSize < 5)
                                                    {
                                                        continue;
                                                    }

                                                    allTests.Add(newParams);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            TestParameters[] allTestsRandom = allTests.ToArray();
            int numTestCases = allTests.Count;

            Console.WriteLine("Preparing " + numTestCases + " test cases");

            // Shuffle the test list
            if (true)
            {
                TestParameters temp;
                int            a;
                int            b;
                Random         rand = new Random();
                for (int c = 0; c < numTestCases; c++)
                {
                    a    = rand.Next(numTestCases);
                    b    = rand.Next(numTestCases);
                    temp = allTestsRandom[a];
                    allTestsRandom[a] = allTestsRandom[b];
                    allTestsRandom[b] = temp;
                }
            }

            double concentusTime = 0.001;
            double opusTime      = 0;
            int    passedTests   = 0;
            int    testsRun      = 0;

            foreach (TestParameters p in allTestsRandom)
            {
                testsRun++;
                Console.Write("{0,5} {1} {2} Cpx={3,2} {4}Kbps {5,2}Khz {6,3} Ms PLC {7,2}% {8} {9} {10}... ",
                              testsRun,
                              PrintApplication(p.Application),
                              p.Channels == 1 ? "Mono  " : "Stereo",
                              p.Complexity,
                              p.Bitrate > 0 ? string.Format("{0,3}", p.Bitrate) : "VAR",
                              p.SampleRate / 1000,
                              p.FrameSize,
                              p.PacketLossPercent,
                              PrintVBRMode(p),
                              p.UseDTX ? "DTX" : "   ",
                              PrintForceMode(p.ForceMode));

                TestResults response = TestDriver.RunTest(p, GetTestSample(p));

                if (response.Passed)
                {
                    passedTests++;
                    if (passedTests > 7)
                    {
                        concentusTime *= 0.999;
                        opusTime      *= 0.999;
                        concentusTime += response.ConcentusTimeMs;
                        opusTime      += response.OpusTimeMs;
                    }
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("{0} (Speed {1:F2}% Pass {2:F2}%)", response.Message, (opusTime * 100 / concentusTime), ((double)passedTests * 100 / testsRun));
                    Console.ForegroundColor = ConsoleColor.Gray;
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("FAIL: " + response.Message);
                    Console.ForegroundColor = ConsoleColor.Gray;

                    //if (response.FrameCount == 0)
                    //{
                    //    PrintShortArray(response.FailureFrame);
                    //    Console.WriteLine(response.FrameLength);
                    //    Console.ReadLine();
                    //}
                }
            }

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("All tests FINISHED");
            Console.WriteLine("{0} out of {1} tests passed ({2:F2}%)", passedTests, numTestCases, ((double)passedTests * 100 / numTestCases));
            Console.WriteLine("Speed benchmark was {0:F2}%", (opusTime * 100 / concentusTime));
        }
Ejemplo n.º 6
0
        internal int opus_decode_native(byte[] data, int data_ptr,
                                        int len, short[] pcm_out, int pcm_out_ptr, int frame_size, int decode_fec,
                                        int self_delimited, out int packet_offset, int soft_clip)
        {
            int  i, nb_samples;
            int  count, offset;
            byte toc;
            int  packet_frame_size, packet_stream_channels;

            packet_offset = 0;
            OpusBandwidth packet_bandwidth;
            OpusMode      packet_mode;

            /* 48 x 2.5 ms = 120 ms */
            // fixme: make sure these values can fit in an int16
            short[] size = new short[48];
            if (decode_fec < 0 || decode_fec > 1)
            {
                return(OpusError.OPUS_BAD_ARG);
            }
            /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */
            if ((decode_fec != 0 || len == 0 || data == null) && frame_size % (this.Fs / 400) != 0)
            {
                return(OpusError.OPUS_BAD_ARG);
            }
            if (len == 0 || data == null)
            {
                int pcm_count = 0;
                do
                {
                    int ret;
                    ret = opus_decode_frame(null, 0, 0, pcm_out, pcm_out_ptr + (pcm_count * this.channels), frame_size - pcm_count, 0);
                    if (ret < 0)
                    {
                        return(ret);
                    }
                    pcm_count += ret;
                } while (pcm_count < frame_size);
                Inlines.OpusAssert(pcm_count == frame_size);
                this.last_packet_duration = pcm_count;
                return(pcm_count);
            }
            else if (len < 0)
            {
                return(OpusError.OPUS_BAD_ARG);
            }

            packet_mode            = OpusPacketInfo.GetEncoderMode(data, data_ptr);
            packet_bandwidth       = OpusPacketInfo.GetBandwidth(data, data_ptr);
            packet_frame_size      = OpusPacketInfo.GetNumSamplesPerFrame(data, data_ptr, this.Fs);
            packet_stream_channels = OpusPacketInfo.GetNumEncodedChannels(data, data_ptr);

            count = OpusPacketInfo.opus_packet_parse_impl(data, data_ptr, len, self_delimited, out toc, null, null, 0,
                                                          size, 0, out offset, out packet_offset);

            if (count < 0)
            {
                return(count);
            }

            data_ptr += offset;

            if (decode_fec != 0)
            {
                int dummy;
                int duration_copy;
                int ret;
                /* If no FEC can be present, run the PLC (recursive call) */
                if (frame_size < packet_frame_size || packet_mode == OpusMode.MODE_CELT_ONLY || this.mode == OpusMode.MODE_CELT_ONLY)
                {
                    return(opus_decode_native(null, 0, 0, pcm_out, pcm_out_ptr, frame_size, 0, 0, out dummy, soft_clip));
                }
                /* Otherwise, run the PLC on everything except the size for which we might have FEC */
                duration_copy = this.last_packet_duration;
                if (frame_size - packet_frame_size != 0)
                {
                    ret = opus_decode_native(null, 0, 0, pcm_out, pcm_out_ptr, frame_size - packet_frame_size, 0, 0, out dummy, soft_clip);
                    if (ret < 0)
                    {
                        this.last_packet_duration = duration_copy;
                        return(ret);
                    }
                    Inlines.OpusAssert(ret == frame_size - packet_frame_size);
                }
                /* Complete with FEC */
                this.mode            = packet_mode;
                this.bandwidth       = packet_bandwidth;
                this.frame_size      = packet_frame_size;
                this.stream_channels = packet_stream_channels;
                ret = opus_decode_frame(data, data_ptr, size[0], pcm_out, pcm_out_ptr + (this.channels * (frame_size - packet_frame_size)),
                                        packet_frame_size, 1);
                if (ret < 0)
                {
                    return(ret);
                }
                else
                {
                    this.last_packet_duration = frame_size;
                    return(frame_size);
                }
            }

            if (count * packet_frame_size > frame_size)
            {
                return(OpusError.OPUS_BUFFER_TOO_SMALL);
            }

            /* Update the state as the last step to avoid updating it on an invalid packet */
            this.mode            = packet_mode;
            this.bandwidth       = packet_bandwidth;
            this.frame_size      = packet_frame_size;
            this.stream_channels = packet_stream_channels;

            nb_samples = 0;
            for (i = 0; i < count; i++)
            {
                int ret;
                ret = opus_decode_frame(data, data_ptr, size[i], pcm_out, pcm_out_ptr + (nb_samples * this.channels), frame_size - nb_samples, 0);
                if (ret < 0)
                {
                    return(ret);
                }
                Inlines.OpusAssert(ret == packet_frame_size);
                data_ptr   += size[i];
                nb_samples += ret;
            }
            this.last_packet_duration = nb_samples;

            return(nb_samples);
        }
Ejemplo n.º 7
0
        internal int opus_decode_frame(byte[] data, int data_ptr,
                                       int len, short[] pcm, int pcm_ptr, int frame_size, int decode_fec)
        {
            SilkDecoder  silk_dec;
            CeltDecoder  celt_dec;
            int          i, silk_ret = 0, celt_ret = 0;
            EntropyCoder dec = new EntropyCoder(); // porting note: stack var
            int          silk_frame_size;
            int          pcm_silk_size;

            short[] pcm_silk;
            int     pcm_transition_silk_size;

            short[] pcm_transition_silk;
            int     pcm_transition_celt_size;

            short[] pcm_transition_celt;
            short[] pcm_transition = null;
            int     redundant_audio_size;

            short[] redundant_audio;

            int      audiosize;
            OpusMode mode;
            int      transition = 0;
            int      start_band;
            int      redundancy       = 0;
            int      redundancy_bytes = 0;
            int      celt_to_silk     = 0;
            int      c;
            int      F2_5, F5, F10, F20;

            int[] window;
            uint  redundant_rng = 0;
            int   celt_accum;

            silk_dec = this.SilkDecoder;
            celt_dec = this.Celt_Decoder;
            F20      = this.Fs / 50;
            F10      = F20 >> 1;
            F5       = F10 >> 1;
            F2_5     = F5 >> 1;
            if (frame_size < F2_5)
            {
                return(OpusError.OPUS_BUFFER_TOO_SMALL);
            }
            /* Limit frame_size to avoid excessive stack allocations. */
            frame_size = Inlines.IMIN(frame_size, this.Fs / 25 * 3);
            /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
            if (len <= 1)
            {
                data = null;
                /* In that case, don't conceal more than what the ToC says */
                frame_size = Inlines.IMIN(frame_size, this.frame_size);
            }
            if (data != null)
            {
                audiosize = this.frame_size;
                mode      = this.mode;
                dec.dec_init(data, data_ptr, (uint)len);
            }
            else
            {
                audiosize = frame_size;
                mode      = this.prev_mode;

                if (mode == 0)
                {
                    /* If we haven't got any packet yet, all we can do is return zeros */
                    for (i = pcm_ptr; i < pcm_ptr + (audiosize * this.channels); i++)
                    {
                        pcm[i] = 0;
                    }

                    return(audiosize);
                }

                /* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT),
                 * 10, or 20 (e.g. 12.5 or 30 ms). */
                if (audiosize > F20)
                {
                    do
                    {
                        int ret = opus_decode_frame(null, 0, 0, pcm, pcm_ptr, Inlines.IMIN(audiosize, F20), 0);
                        if (ret < 0)
                        {
                            return(ret);
                        }
                        pcm_ptr   += ret * this.channels;
                        audiosize -= ret;
                    } while (audiosize > 0);

                    return(frame_size);
                }
                else if (audiosize < F20)
                {
                    if (audiosize > F10)
                    {
                        audiosize = F10;
                    }
                    else if (mode != OpusMode.MODE_SILK_ONLY && audiosize > F5 && audiosize < F10)
                    {
                        audiosize = F5;
                    }
                }
            }

            /* In fixed-point, we can tell CELT to do the accumulation on top of the
             * SILK PCM buffer. This saves some stack space. */
            celt_accum = ((mode != OpusMode.MODE_CELT_ONLY) && (frame_size >= F10)) ? 1 : 0;

            pcm_transition_silk_size = 0;
            pcm_transition_celt_size = 0;
            if (data != null && this.prev_mode > 0 && (
                    (mode == OpusMode.MODE_CELT_ONLY && this.prev_mode != OpusMode.MODE_CELT_ONLY && (this.prev_redundancy == 0)) ||
                    (mode != OpusMode.MODE_CELT_ONLY && this.prev_mode == OpusMode.MODE_CELT_ONLY))
                )
            {
                transition = 1;
                /* Decide where to allocate the stack memory for pcm_transition */
                if (mode == OpusMode.MODE_CELT_ONLY)
                {
                    pcm_transition_celt_size = F5 * this.channels;
                }
                else
                {
                    pcm_transition_silk_size = F5 * this.channels;
                }
            }
            pcm_transition_celt = new short[pcm_transition_celt_size];
            if (transition != 0 && mode == OpusMode.MODE_CELT_ONLY)
            {
                pcm_transition = pcm_transition_celt;
                opus_decode_frame(null, 0, 0, pcm_transition, 0, Inlines.IMIN(F5, audiosize), 0);
            }
            if (audiosize > frame_size)
            {
                /*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/

                return(OpusError.OPUS_BAD_ARG);
            }
            else
            {
                frame_size = audiosize;
            }

            /* Don't allocate any memory when in CELT-only mode */
            pcm_silk_size = (mode != OpusMode.MODE_CELT_ONLY && (celt_accum == 0)) ? Inlines.IMAX(F10, frame_size) * this.channels : 0;
            pcm_silk      = new short[pcm_silk_size];

            /* SILK processing */
            if (mode != OpusMode.MODE_CELT_ONLY)
            {
                int     lost_flag, decoded_samples;
                short[] pcm_ptr2;
                int     pcm_ptr2_ptr = 0;

                if (celt_accum != 0)
                {
                    pcm_ptr2     = pcm;
                    pcm_ptr2_ptr = pcm_ptr;
                }
                else
                {
                    pcm_ptr2     = pcm_silk;
                    pcm_ptr2_ptr = 0;
                }

                if (this.prev_mode == OpusMode.MODE_CELT_ONLY)
                {
                    DecodeAPI.silk_InitDecoder(silk_dec);
                }

                /* The SILK PLC cannot produce frames of less than 10 ms */
                this.DecControl.payloadSize_ms = Inlines.IMAX(10, 1000 * audiosize / this.Fs);

                if (data != null)
                {
                    this.DecControl.nChannelsInternal = this.stream_channels;
                    if (mode == OpusMode.MODE_SILK_ONLY)
                    {
                        if (this.bandwidth == OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND)
                        {
                            this.DecControl.internalSampleRate = 8000;
                        }
                        else if (this.bandwidth == OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND)
                        {
                            this.DecControl.internalSampleRate = 12000;
                        }
                        else if (this.bandwidth == OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND)
                        {
                            this.DecControl.internalSampleRate = 16000;
                        }
                        else
                        {
                            this.DecControl.internalSampleRate = 16000;
                            Inlines.OpusAssert(false);
                        }
                    }
                    else
                    {
                        /* Hybrid mode */
                        this.DecControl.internalSampleRate = 16000;
                    }
                }

                lost_flag       = data == null ? 1 : 2 * decode_fec;
                decoded_samples = 0;
                do
                {
                    /* Call SILK decoder */
                    int first_frame = (decoded_samples == 0) ? 1 : 0;
                    silk_ret = DecodeAPI.silk_Decode(silk_dec, this.DecControl,
                                                     lost_flag, first_frame, dec, pcm_ptr2, pcm_ptr2_ptr, out silk_frame_size);
                    if (silk_ret != 0)
                    {
                        if (lost_flag != 0)
                        {
                            /* PLC failure should not be fatal */
                            silk_frame_size = frame_size;
                            Arrays.MemSetWithOffset <short>(pcm_ptr2, 0, pcm_ptr2_ptr, frame_size * this.channels);
                        }
                        else
                        {
                            return(OpusError.OPUS_INTERNAL_ERROR);
                        }
                    }
                    pcm_ptr2_ptr    += (silk_frame_size * this.channels);
                    decoded_samples += silk_frame_size;
                } while (decoded_samples < frame_size);
            }

            start_band = 0;
            if (decode_fec == 0 && mode != OpusMode.MODE_CELT_ONLY && data != null &&
                dec.tell() + 17 + 20 * (this.mode == OpusMode.MODE_HYBRID ? 1 : 0) <= 8 * len)
            {
                /* Check if we have a redundant 0-8 kHz band */
                if (mode == OpusMode.MODE_HYBRID)
                {
                    redundancy = dec.dec_bit_logp(12);
                }
                else
                {
                    redundancy = 1;
                }
                if (redundancy != 0)
                {
                    celt_to_silk = dec.dec_bit_logp(1);

                    /* redundancy_bytes will be at least two, in the non-hybrid
                     * case due to the ec_tell() check above */
                    redundancy_bytes = mode == OpusMode.MODE_HYBRID ?
                                       (int)dec.dec_uint(256) + 2 :
                                       len - ((dec.tell() + 7) >> 3);
                    len -= redundancy_bytes;

                    /* This is a sanity check. It should never happen for a valid
                     * packet, so the exact behaviour is not normative. */
                    if (len * 8 < dec.tell())
                    {
                        len = 0;
                        redundancy_bytes = 0;
                        redundancy       = 0;
                    }
                    /* Shrink decoder because of raw bits */
                    dec.storage = (uint)(dec.storage - redundancy_bytes);
                }
            }
            if (mode != OpusMode.MODE_CELT_ONLY)
            {
                start_band = 17;
            }

            {
                int endband = 21;

                switch (this.bandwidth)
                {
                case OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND:
                    endband = 13;
                    break;

                case OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND:
                case OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND:
                    endband = 17;
                    break;

                case OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND:
                    endband = 19;
                    break;

                case OpusBandwidth.OPUS_BANDWIDTH_FULLBAND:
                    endband = 21;
                    break;
                }
                celt_dec.SetEndBand(endband);
                celt_dec.SetChannels(this.stream_channels);
            }

            if (redundancy != 0)
            {
                transition = 0;
                pcm_transition_silk_size = 0;
            }

            pcm_transition_silk = new short[pcm_transition_silk_size];

            if (transition != 0 && mode != OpusMode.MODE_CELT_ONLY)
            {
                pcm_transition = pcm_transition_silk;
                opus_decode_frame(null, 0, 0, pcm_transition, 0, Inlines.IMIN(F5, audiosize), 0);
            }

            /* Only allocation memory for redundancy if/when needed */
            redundant_audio_size = redundancy != 0 ? F5 * this.channels : 0;
            redundant_audio      = new short[redundant_audio_size];

            /* 5 ms redundant frame for CELT->SILK*/
            if (redundancy != 0 && celt_to_silk != 0)
            {
                celt_dec.SetStartBand(0);
                celt_dec.celt_decode_with_ec(data, (data_ptr + len), redundancy_bytes,
                                             redundant_audio, 0, F5, null, 0);
                redundant_rng = celt_dec.GetFinalRange();
            }

            /* MUST be after PLC */
            celt_dec.SetStartBand(start_band);

            if (mode != OpusMode.MODE_SILK_ONLY)
            {
                int celt_frame_size = Inlines.IMIN(F20, frame_size);
                /* Make sure to discard any previous CELT state */
                if (mode != this.prev_mode && this.prev_mode > 0 && this.prev_redundancy == 0)
                {
                    celt_dec.ResetState();
                }
                /* Decode CELT */
                celt_ret = celt_dec.celt_decode_with_ec(decode_fec != 0 ? null : data, data_ptr,
                                                        len, pcm, pcm_ptr, celt_frame_size, dec, celt_accum);
            }
            else
            {
                if (celt_accum == 0)
                {
                    for (i = pcm_ptr; i < (frame_size * this.channels) + pcm_ptr; i++)
                    {
                        pcm[i] = 0;
                    }
                }

                /* For hybrid -> SILK transitions, we let the CELT MDCT
                 * do a fade-out by decoding a silence frame */
                if (this.prev_mode == OpusMode.MODE_HYBRID && !(redundancy != 0 && celt_to_silk != 0 && this.prev_redundancy != 0))
                {
                    celt_dec.SetStartBand(0);
                    celt_dec.celt_decode_with_ec(SILENCE, 0, 2, pcm, pcm_ptr, F2_5, null, celt_accum);
                }
            }

            if (mode != OpusMode.MODE_CELT_ONLY && celt_accum == 0)
            {
                for (i = 0; i < frame_size * this.channels; i++)
                {
                    pcm[pcm_ptr + i] = Inlines.SAT16(Inlines.ADD32(pcm[pcm_ptr + i], pcm_silk[i]));
                }
            }

            window = celt_dec.GetMode().window;

            /* 5 ms redundant frame for SILK->CELT */
            if (redundancy != 0 && celt_to_silk == 0)
            {
                celt_dec.ResetState();
                celt_dec.SetStartBand(0);

                celt_dec.celt_decode_with_ec(data, data_ptr + len, redundancy_bytes, redundant_audio, 0, F5, null, 0);
                redundant_rng = celt_dec.GetFinalRange();
                CodecHelpers.smooth_fade(pcm, pcm_ptr + this.channels * (frame_size - F2_5), redundant_audio, this.channels * F2_5,
                                         pcm, (pcm_ptr + this.channels * (frame_size - F2_5)), F2_5, this.channels, window, this.Fs);
            }
            if (redundancy != 0 && celt_to_silk != 0)
            {
                for (c = 0; c < this.channels; c++)
                {
                    for (i = 0; i < F2_5; i++)
                    {
                        pcm[this.channels * i + c + pcm_ptr] = redundant_audio[this.channels * i + c];
                    }
                }
                CodecHelpers.smooth_fade(redundant_audio, (this.channels * F2_5), pcm, (pcm_ptr + (this.channels * F2_5)),
                                         pcm, (pcm_ptr + (this.channels * F2_5)), F2_5, this.channels, window, this.Fs);
            }
            if (transition != 0)
            {
                if (audiosize >= F5)
                {
                    for (i = 0; i < this.channels * F2_5; i++)
                    {
                        pcm[i] = pcm_transition[i];
                    }
                    CodecHelpers.smooth_fade(pcm_transition, (this.channels * F2_5), pcm, (pcm_ptr + (this.channels * F2_5)),
                                             pcm, (pcm_ptr + (this.channels * F2_5)), F2_5,
                                             this.channels, window, this.Fs);
                }
                else
                {
                    /* Not enough time to do a clean transition, but we do it anyway
                     * This will not preserve amplitude perfectly and may introduce
                     * a bit of temporal aliasing, but it shouldn't be too bad and
                     * that's pretty much the best we can do. In any case, generating this
                     * transition is pretty silly in the first place */
                    CodecHelpers.smooth_fade(pcm_transition, 0, pcm, pcm_ptr,
                                             pcm, pcm_ptr, F2_5,
                                             this.channels, window, this.Fs);
                }
            }

            if (this.decode_gain != 0)
            {
                int gain;
                gain = Inlines.celt_exp2(Inlines.MULT16_16_P15(((short)(0.5 + (6.48814081e-4f) * (((int)1) << (25)))) /*Inlines.QCONST16(6.48814081e-4f, 25)*/, this.decode_gain));
                for (i = pcm_ptr; i < pcm_ptr + (frame_size * this.channels); i++)
                {
                    int x;
                    x      = Inlines.MULT16_32_P16(pcm[i], gain);
                    pcm[i] = (short)Inlines.SATURATE(x, 32767);
                }
            }

            if (len <= 1)
            {
                this.rangeFinal = 0;
            }
            else
            {
                this.rangeFinal = dec.rng ^ redundant_rng;
            }

            this.prev_mode       = mode;
            this.prev_redundancy = (redundancy != 0 && celt_to_silk == 0) ? 1 : 0;

            return(celt_ret < 0 ? celt_ret : audiosize);
        }
Ejemplo n.º 8
0
        public AudioChunk Decompress(byte[] inputPacket)
        {
            int frameSize = GetFrameSize();
            
            short[] outputBuffer = new short[frameSize];

            bool lostPacket = new Random().Next(0, 100) < _packetLoss;
            if (!lostPacket)
            {
                // Normal decoding
                _timer.Reset();
                _timer.Start();
                int thisFrameSize = _decoder.Decode(inputPacket, 0, inputPacket.Length, outputBuffer, 0, frameSize, false);
                _timer.Stop();
            }
            else
            {
                // packet loss path
                _timer.Reset();
                _timer.Start();
                int thisFrameSize = _decoder.Decode(null, 0, 0, outputBuffer, 0, frameSize, true);
                _timer.Stop();
            }

            short[] finalOutput = new short[frameSize];
            Array.Copy(outputBuffer, finalOutput, finalOutput.Length);

            // Update statistics
            _statistics.Bitrate = inputPacket.Length * 8 * 48000 / 1024 / frameSize;
            OpusMode curMode = OpusPacketInfo.GetEncoderMode(inputPacket, 0);
            if (curMode == OpusMode.MODE_CELT_ONLY)
            {
                _statistics.Mode = "CELT";
            }
            else if (curMode == OpusMode.MODE_HYBRID)
            {
                _statistics.Mode = "Hybrid";
            }
            else if (curMode == OpusMode.MODE_SILK_ONLY)
            {
                _statistics.Mode = "SILK";
            }
            else
            {
                _statistics.Mode = "Unknown";
            }
            _statistics.DecodeSpeed = _frameSize / ((double)_timer.ElapsedTicks / Stopwatch.Frequency * 1000);
            OpusBandwidth curBandwidth = OpusPacketInfo.GetBandwidth(inputPacket, 0);
            if (curBandwidth == OpusBandwidth.OPUS_BANDWIDTH_NARROWBAND)
            {
                _statistics.Bandwidth = 8000;
            }
            else if (curBandwidth == OpusBandwidth.OPUS_BANDWIDTH_MEDIUMBAND)
            {
                _statistics.Bandwidth = 12000;
            }
            else if (curBandwidth == OpusBandwidth.OPUS_BANDWIDTH_WIDEBAND)
            {
                _statistics.Bandwidth = 16000;
            }
            else if (curBandwidth == OpusBandwidth.OPUS_BANDWIDTH_SUPERWIDEBAND)
            {
                _statistics.Bandwidth = 24000;
            }
            else
            {
                _statistics.Bandwidth = 48000;
            }

            return new AudioChunk(finalOutput, 48000);
        }
Ejemplo n.º 9
0
        public void ShotgunTest()
        {
            OpusApplication[] Applications = new OpusApplication[] { OpusApplication.OPUS_APPLICATION_AUDIO, OpusApplication.OPUS_APPLICATION_VOIP, OpusApplication.OPUS_APPLICATION_RESTRICTED_LOWDELAY };
            int[]             Bitrates     = new int[] { -1, 6, 16, 20, 32, 64, 500 };
            int[]             Channels     = new int[] { 1, 2 };
            int[]             Complexities = new int[] { 0, 2, 4, 6, 8, 10 };
            int[]             SampleRates  = new int[] { 8000, 12000, 16000, 24000, 48000 };
            double[]          FrameSizes   = new double[] { 2.5, 5, 10, 20, 40, 60 };
            int[]             PacketLosses = new int[] { 0, 20 };
            OpusMode[]        ForceModes   = new OpusMode[] { OpusMode.MODE_AUTO, OpusMode.MODE_CELT_ONLY, OpusMode.MODE_SILK_ONLY };
            bool[]            DTXModes     = new bool[] { false, true };
            int[]             VBRModes     = new int[] { 0, 1, 2 };

            IList <TestParameters> allTests = new List <TestParameters>();

            for (int app_idx = 0; app_idx < Applications.Length; app_idx++)
            {
                for (int plc_idx = 0; plc_idx < PacketLosses.Length; plc_idx++)
                {
                    for (int chan_idx = 0; chan_idx < Channels.Length; chan_idx++)
                    {
                        for (int sr_idx = 0; sr_idx < SampleRates.Length; sr_idx++)
                        {
                            for (int fs_idx = 0; fs_idx < FrameSizes.Length; fs_idx++)
                            {
                                for (int cpx_idx = 0; cpx_idx < Complexities.Length; cpx_idx++)
                                {
                                    for (int bit_idx = 0; bit_idx < Bitrates.Length; bit_idx++)
                                    {
                                        for (int fm_idx = 0; fm_idx < ForceModes.Length; fm_idx++)
                                        {
                                            for (int dtx_idx = 0; dtx_idx < DTXModes.Length; dtx_idx++)
                                            {
                                                for (int vbr_idx = 0; vbr_idx < VBRModes.Length; vbr_idx++)
                                                {
                                                    TestParameters newParams = new TestParameters()
                                                    {
                                                        Application       = Applications[app_idx],
                                                        Bitrate           = Bitrates[bit_idx],
                                                        Channels          = Channels[chan_idx],
                                                        Complexity        = Complexities[cpx_idx],
                                                        PacketLossPercent = PacketLosses[plc_idx],
                                                        SampleRate        = SampleRates[sr_idx],
                                                        FrameSize         = FrameSizes[fs_idx],
                                                        ForceMode         = ForceModes[fm_idx],
                                                        UseDTX            = DTXModes[dtx_idx]
                                                    };
                                                    if (VBRModes[vbr_idx] == 0)
                                                    {
                                                        newParams.UseVBR         = false;
                                                        newParams.ConstrainedVBR = false;
                                                    }
                                                    else if (VBRModes[vbr_idx] == 1)
                                                    {
                                                        newParams.UseVBR         = true;
                                                        newParams.ConstrainedVBR = false;
                                                    }
                                                    else if (VBRModes[vbr_idx] == 2)
                                                    {
                                                        newParams.UseVBR         = true;
                                                        newParams.ConstrainedVBR = true;
                                                    }

                                                    // Validate params
                                                    if (newParams.Bitrate > 40 || newParams.FrameSize < 10)
                                                    {
                                                        // No FEC outside of SILK mode
                                                        if (newParams.PacketLossPercent > 0)
                                                        {
                                                            continue;
                                                        }
                                                        // No DTX outside of SILK mode
                                                        if (newParams.UseDTX)
                                                        {
                                                            continue;
                                                        }
                                                        if (newParams.ForceMode == OpusMode.MODE_SILK_ONLY)
                                                        {
                                                            continue;
                                                        }
                                                    }
                                                    // Constrained VBR only applies to CELT
                                                    if (newParams.ForceMode == OpusMode.MODE_SILK_ONLY && newParams.ConstrainedVBR)
                                                    {
                                                        continue;
                                                    }
                                                    // 12Khz + 2.5ms triggers an opus bug for now
                                                    if (newParams.SampleRate == 12000 && newParams.FrameSize < 5)
                                                    {
                                                        continue;
                                                    }

                                                    allTests.Add(newParams);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            TestParameters[] allTestsRandom = allTests.ToArray();
            int numTestCases = allTests.Count;

            // Shuffle the test list
            TestParameters temp;
            int            a;
            int            b;
            Random         rand = new Random();

            for (int c = 0; c < numTestCases; c++)
            {
                a    = rand.Next(numTestCases);
                b    = rand.Next(numTestCases);
                temp = allTestsRandom[a];
                allTestsRandom[a] = allTestsRandom[b];
                allTestsRandom[b] = temp;
            }

            int testsRun = 0;

            foreach (TestParameters p in allTestsRandom)
            {
                testsRun++;
                TestResults response = TestDriver.RunTest(p, GetTestSample(p));
                Assert.IsTrue(response.Passed);
                if (testsRun > 50)
                {
                    break;
                }
            }
        }
Ejemplo n.º 10
0
        public AudioChunk Decompress(byte[] inputPacket)
        {
            int frameSize = GetFrameSize();

            short[] outputBuffer = new short[frameSize];

            bool lostPacket = new Random().Next(0, 100) < _packetLoss;

            if (!lostPacket)
            {
                // normal decoding
                _timer.Reset();
                _timer.Start();
                unsafe
                {
                    fixed(short *bdec = outputBuffer)
                    {
                        IntPtr decodedPtr    = new IntPtr((byte *)(bdec));
                        int    thisFrameSize = opus_decode(_decoder, inputPacket, inputPacket.Length, decodedPtr, frameSize, 0);
                    }
                }
                _timer.Stop();
            }
            else
            {
                // packet loss path
                _timer.Reset();
                _timer.Start();
                unsafe
                {
                    fixed(short *bdec = outputBuffer)
                    {
                        IntPtr decodedPtr    = new IntPtr((byte *)(bdec));
                        int    thisFrameSize = opus_decode(_decoder, null, 0, decodedPtr, frameSize, 1);
                    }
                }
                _timer.Stop();
            }

            short[] finalOutput = new short[frameSize];
            Array.Copy(outputBuffer, finalOutput, finalOutput.Length);

            // Update statistics
            _statistics.Bitrate = inputPacket.Length * 8 * 48000 / 1024 / frameSize;
            OpusMode curMode = OpusPacketInfo.GetEncoderMode(inputPacket, 0);

            if (curMode == OpusMode.MODE_CELT_ONLY)
            {
                _statistics.Mode = "CELT";
            }
            else if (curMode == OpusMode.MODE_HYBRID)
            {
                _statistics.Mode = "Hybrid";
            }
            else if (curMode == OpusMode.MODE_SILK_ONLY)
            {
                _statistics.Mode = "SILK";
            }
            else
            {
                _statistics.Mode = "Unknown";
            }
            _statistics.DecodeSpeed = _frameSize / ((double)_timer.ElapsedTicks / Stopwatch.Frequency * 1000);

            return(new AudioChunk(finalOutput, 48000));
        }