|
- using System;
- using System.Runtime.InteropServices;
-
- namespace Discord.Audio
- {
- internal unsafe class OpusDecoder : OpusConverter
- {
- [DllImport("opus", EntryPoint = "opus_decoder_create", CallingConvention = CallingConvention.Cdecl)]
- private static extern IntPtr CreateDecoder(int Fs, int channels, out OpusError error);
- [DllImport("opus", EntryPoint = "opus_decoder_destroy", CallingConvention = CallingConvention.Cdecl)]
- private static extern void DestroyDecoder(IntPtr decoder);
- [DllImport("opus", EntryPoint = "opus_decode", CallingConvention = CallingConvention.Cdecl)]
- private static extern int Decode(IntPtr st, byte* data, int len, byte* pcm, int max_frame_size, int decode_fec);
-
- public OpusDecoder(int samplingRate, int channels)
- : base(samplingRate, channels)
- {
- OpusError error;
- _ptr = CreateDecoder(samplingRate, channels, out error);
- if (error != OpusError.OK)
- throw new Exception($"Opus Error: {error}");
- }
-
- /// <summary> Produces PCM samples from Opus-encoded audio. </summary>
- /// <param name="input">PCM samples to decode.</param>
- /// <param name="inputOffset">Offset of the frame in input.</param>
- /// <param name="inputCount">Number of bytes of the frame in input.</param>
- /// <param name="output">Buffer to store the decoded frame.</param>
- /// <param name="outputOffset">Zero-based offset for the output.</param>
- public unsafe int DecodeFrame(byte[] input, int inputOffset, int inputCount, byte[] output, int outputOffset)
- {
- int result = 0;
- fixed (byte* inPtr = input)
- fixed (byte* outPtr = output)
- result = Decode(_ptr, inPtr + inputOffset, inputCount, outPtr + outputOffset, (output.Length - outputOffset) / SampleSize / MaxChannels, 0);
-
- if (result < 0)
- throw new Exception($"Opus Error: {(OpusError)result}");
- return result;
- }
-
- protected override void Dispose(bool disposing)
- {
- if (_ptr != IntPtr.Zero)
- {
- DestroyDecoder(_ptr);
- _ptr = IntPtr.Zero;
- }
- }
- }
- }
|