Пример #1
0
        /// <summary>
        /// Produces PCM samples from Opus encoded data.
        /// </summary>
        /// <param name="inputOpusData">Opus encoded data to decode, null for dropped packet.</param>
        /// <param name="dataLength">Length of data to decode.</param>
        /// <param name="decodedLength">Set to the length of the decoded sample data.</param>
        /// <returns>PCM audio samples.</returns>
        public unsafe void DecodeFloat(ReadOnlySpan <byte> inputOpusData, Span <float> outputFloat, out int dataLength)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("OpusDecoder");
            }

            int frameCount = GetSamples(inputOpusData) * OutputChannels;
            int length;

            fixed(byte *inputPtr = inputOpusData)
            fixed(float *outputPtr = outputFloat)
            {
                if (inputOpusData != null)
                {
                    length = OpusAPI.opus_decode_float(DecoderInstance, inputPtr, inputOpusData.Length, outputPtr, frameCount, 0);
                }
                else
                {
                    length = OpusAPI.opus_decode_float(DecoderInstance, null, 0, outputPtr, frameCount, (ForwardErrorCorrection) ? 1 : 0);
                }
            }

            if (length < 0)
            {
                throw new Exception("Decoding failed - " + (Errors)length);
            }

            dataLength = length * OutputChannels;
        }
Пример #2
0
        /// <summary>
        /// Produces PCM samples from Opus encoded data.
        /// </summary>
        /// <param name="inputOpusData">Opus encoded data to decode, null for dropped packet.</param>
        /// <param name="dataLength">Length of data to decode.</param>
        /// <param name="decodedLength">Set to the length of the decoded sample data.</param>
        /// <returns>PCM audio samples.</returns>
        public unsafe byte[] Decode(Span <byte> inputOpusData, int dataLength, out int decodedLength)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("OpusDecoder");
            }

            int frameCount = MaxDataBytes * OutputChannels;

            byte[] decoded = new byte[frameCount * 2];
            int    length  = 0;

            fixed(byte *inputPtr = inputOpusData)
            fixed(byte *outputPtr = decoded)
            {
                if (inputOpusData != null)
                {
                    length = OpusAPI.opus_decode(DecoderInstance, inputPtr, dataLength, outputPtr, frameCount, 0);
                }
                else
                {
                    length = OpusAPI.opus_decode(DecoderInstance, null, 0, outputPtr, frameCount, (ForwardErrorCorrection) ? 1 : 0);
                }

                decodedLength = length * 2 * OutputChannels;
                if (length < 0)
                {
                    throw new Exception("Decoding failed - " + ((Errors)length));
                }

                return(decoded);
            }
        }
Пример #3
0
        /// <summary>
        /// Produces PCM samples from Opus encoded data.
        /// </summary>
        /// <param name="inputOpusData">Opus encoded data to decode, null for dropped packet.</param>
        /// <param name="dataLength">Length of data to decode.</param>
        /// <param name="decodedLength">Set to the length of the decoded sample data.</param>
        /// <returns>PCM audio samples.</returns>
        public unsafe float[] DecodeFloat(ReadOnlySpan <byte> inputOpusData)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("OpusDecoder");
            }

            int frameCount = GetSamples(inputOpusData) * OutputChannels;

            float[] decoded = new float[frameCount];
            int     length  = 0;

            fixed(byte *inputPtr = inputOpusData)
            fixed(float *outputPtr = decoded)
            {
                if (inputOpusData != null)
                {
                    length = OpusAPI.opus_decode_float(DecoderInstance, inputPtr, inputOpusData.Length, outputPtr, frameCount, 0);
                }
                else
                {
                    length = OpusAPI.opus_decode_float(DecoderInstance, null, 0, outputPtr, frameCount, (ForwardErrorCorrection) ? 1 : 0);
                }
            }

            if (length < 0)
            {
                throw new Exception("Decoding failed - " + (Errors)length);
            }

            //decodedCount = length * OutputChannels;
            Array.Resize(ref decoded, length * OutputChannels);

            return(decoded);
        }
Пример #4
0
        /// <summary>
        /// Creates a new Opus decoder.
        /// </summary>
        /// <param name="outputSampleRate">Sample rate to decode at (Hz). This must be one of 8000, 12000, 16000, 24000, or 48000.</param>
        /// <param name="outputChannels">Number of channels to decode.</param>
        /// <returns>A new <c>OpusDecoder</c>.</returns>
        public static OpusDecoder Create(int outputSampleRate, int outputChannels)
        {
            if (outputSampleRate != 8000 &&
                outputSampleRate != 12000 &&
                outputSampleRate != 16000 &&
                outputSampleRate != 24000 &&
                outputSampleRate != 48000)
            {
                throw new ArgumentOutOfRangeException(nameof(outputSampleRate));
            }

            if (outputChannels != 1 && outputChannels != 2)
            {
                throw new ArgumentOutOfRangeException(nameof(outputChannels));
            }

            IntPtr decoder = OpusAPI.opus_decoder_create(outputSampleRate, outputChannels, out var error);

            if ((Errors)error != Errors.OK)
            {
                throw new Exception("Exception occured while creating decoder");
            }

            return(new OpusDecoder(decoder, outputSampleRate, outputChannels));
        }
Пример #5
0
        /// <summary>
        /// Produces Opus encoded audio from PCM samples.
        /// </summary>
        /// <param name="inputPcmSamples">PCM samples to encode.</param>
        /// <param name="sampleLength">How many samples to encode.</param>
        /// <param name="encodedLength">Set to length of encoded audio.</param>
        /// <returns>Opus encoded audio buffer.</returns>
        public unsafe void Encode(ReadOnlySpan <float> inputPcmSamples, Span <byte> outputSpan, int sampleLength, out int encodedLength)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("OpusEncoder");
            }

            int length = 0;

            fixed(float *inputPtr = inputPcmSamples)
            fixed(byte *outputPtr = outputSpan)
            {
                length = OpusAPI.opus_encode_float(EncoderInstance, inputPtr, sampleLength, outputPtr, outputSpan.Length);
            }

            encodedLength = length;
            if (length < 0)
            {
                var exception = new Exception("Encoding failed - " + (Errors)length);
                exception.Data.Add("inputPcmSamples.Length", inputPcmSamples.Length);
                exception.Data.Add("sampleLength", sampleLength);
                exception.Data.Add("InputChannels", InputChannels);

                throw exception;
            }
        }
Пример #6
0
        /// <summary>
        /// Produces Opus encoded audio from PCM samples.
        /// </summary>
        /// <param name="inputPcmSamples">PCM samples to encode.</param>
        /// <param name="sampleLength">How many bytes to encode.</param>
        /// <param name="encodedLength">Set to length of encoded audio.</param>
        /// <returns>Opus encoded audio buffer.</returns>
        public unsafe byte[] Encode(Span <byte> inputPcmSamples, int sampleLength, out int encodedLength)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("OpusEncoder");
            }

            int maxDataBytes = sampleLength * InputChannels * sizeof(short);

            byte[] encoded = new byte[maxDataBytes];
            int    length  = 0;

            fixed(byte *inputPtr = inputPcmSamples)
            fixed(byte *outputPtr = encoded)
            {
                length = OpusAPI.opus_encode(EncoderInstance, inputPtr, sampleLength, outputPtr, maxDataBytes);
            }

            encodedLength = length;
            if (length < 0)
            {
                var exception = new Exception("Encoding failed - " + (Errors)length);
                exception.Data.Add("inputPcmSamples.Length", inputPcmSamples.Length.ToString());
                exception.Data.Add("sampleLength", sampleLength.ToString());
                exception.Data.Add("MaxDataBytes", maxDataBytes.ToString());
                throw exception;
            }

            return(encoded);
        }
Пример #7
0
        /// <summary>
        /// Creates a new Opus encoder.
        /// </summary>
        /// <param name="inputSamplingRate">Sampling rate of the input signal (Hz). This must be one of 8000, 12000, 16000, 24000, or 48000.</param>
        /// <param name="inputChannels">Number of channels (1 or 2) in input signal.</param>
        /// <param name="application">Coding mode.</param>
        /// <returns>A new <c>OpusEncoder</c></returns>
        public static OpusEncoder Create(int inputSamplingRate, int inputChannels, Application application)
        {
            if (inputSamplingRate != 8000 &&
                inputSamplingRate != 12000 &&
                inputSamplingRate != 16000 &&
                inputSamplingRate != 24000 &&
                inputSamplingRate != 48000)
            {
                throw new ArgumentOutOfRangeException(nameof(inputSamplingRate));
            }

            if (inputChannels != 1 && inputChannels != 2)
            {
                throw new ArgumentOutOfRangeException(nameof(inputChannels));
            }

            IntPtr encoder = OpusAPI.opus_encoder_create(inputSamplingRate, inputChannels, (int)application, out var error);

            if ((Errors)error != Errors.OK)
            {
                throw new Exception("Exception occured while creating encoder");
            }

            return(new OpusEncoder(encoder, inputSamplingRate, inputChannels, application));
        }
Пример #8
0
        private void SetCtl(Ctl ctl, int value)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("OpusEncoder");
            }

            var ret = OpusAPI.opus_encoder_ctl(EncoderInstance, ctl, value);

            if (ret < 0)
            {
                throw new Exception("Encoder error - " + (Errors)ret);
            }
        }
Пример #9
0
        private int GetCtl(Ctl ctl)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("OpusEncoder");
            }

            var ret = OpusAPI.opus_encoder_ctl_out(EncoderInstance, ctl, out int result);

            if (ret < 0)
            {
                throw new Exception("Encoder error - " + (Errors)ret);
            }

            return(result);
        }
Пример #10
0
        public void Dispose()
        {
            if (disposed)
            {
                return;
            }

            GC.SuppressFinalize(this);

            if (DecoderInstance != IntPtr.Zero)
            {
                OpusAPI.opus_decoder_destroy(DecoderInstance);
                DecoderInstance = IntPtr.Zero;
            }

            disposed = true;
        }
Пример #11
0
 public unsafe int GetSamples(ReadOnlySpan <byte> data)
 {
     fixed(byte *ptr = data)
     return(OpusAPI.opus_packet_get_nb_samples(ptr, data.Length, OutputSamplingRate));
 }
Пример #12
0
 public unsafe int GetFrames(byte[] data)
 {
     fixed(byte *ptr = data)
     return(OpusAPI.opus_packet_get_nb_frames(ptr, data.Length));
 }
Пример #13
0
 public unsafe int GetChannels(byte[] data)
 {
     fixed(byte *ptr = data)
     return(OpusAPI.opus_packet_get_nb_channels(ptr));
 }