public void Reset() { //Reset takes no args, returns no values, and cannot fail. So we're passing in nothing, outputting nothing, and ignoring the return code int _; OpusNativeMethods.opus_decoder_ctl(_decoder, Ctl.ResetState, out _); }
/// <summary> /// Creates a new Opus encoder. /// </summary> /// <param name="srcSamplingRate">The sampling rate of the input stream.</param> /// <param name="srcChannelCount">The number of channels in the input stream.</param> public OpusEncoder(int srcSamplingRate, int srcChannelCount) { if (srcSamplingRate != 8000 && srcSamplingRate != 12000 && srcSamplingRate != 16000 && srcSamplingRate != 24000 && srcSamplingRate != 48000) { throw new ArgumentOutOfRangeException("srcSamplingRate", Log.PossibleBugMessage("sample rate must be one of the valid values", "3F2C6D2D-338E-495E-8970-42A3C98243A5")); } if (srcChannelCount != 1 && srcChannelCount != 2) { throw new ArgumentOutOfRangeException("srcChannelCount", Log.PossibleBugMessage("channel count must be 1 or 2", "8FE1EC0F-09E0-4CE6-AFD7-04199202D45D")); } int error; var encoder = OpusNativeMethods.opus_encoder_create(srcSamplingRate, srcChannelCount, (int)Application.Voip, out error); if ((OpusErrors)error != OpusErrors.Ok) { throw new OpusException(Log.PossibleBugMessage(string.Format("Exception occured while creating encoder: {0}", (OpusErrors)error), "D77ECA73-413F-40D1-8427-CFD8A59CD5F6")); } _encoder = new LockedValue <IntPtr>(encoder); PermittedFrameSizes = new int[PermittedFrameSizesMs.Length]; for (var i = 0; i < PermittedFrameSizesMs.Length; i++) { PermittedFrameSizes[i] = (int)(srcSamplingRate / 1000f * PermittedFrameSizesMs[i]); } }
/// <summary> /// Encode audio samples. /// </summary> /// <returns>The total number of bytes written to dstOutputBuffer.</returns> public int EncodeFloats(ArraySegment <float> sourcePcm, ArraySegment <byte> dstEncoded) { if (sourcePcm.Array == null) { throw new ArgumentNullException("sourcePcm", Log.PossibleBugMessage("source pcm must not be null", "58AE3110-8F9A-4C36-9520-B7F3383096EC")); } if (dstEncoded.Array == null) { throw new ArgumentNullException("dstEncoded", Log.PossibleBugMessage("destination must not be null", "36C327BB-A128-400D-AFB3-FF760A1562C1")); } int encodedLen; using (var encoder = _encoder.Lock()) { if (encoder.Value == IntPtr.Zero) { throw new DissonanceException(Log.PossibleBugMessage("Attempted to access a null Opus encoder", "647001C3-39BB-418D-99EF-1D66B8EA633C")); } using (var srcHandle = sourcePcm.Pin()) using (var dstHandle = dstEncoded.Pin()) { encodedLen = OpusNativeMethods.opus_encode_float(encoder.Value, srcHandle.Ptr, sourcePcm.Count, dstHandle.Ptr, dstEncoded.Count); } } if (encodedLen < 0) { throw new OpusException(Log.PossibleBugMessage(string.Format("Encoding failed: {0}", (OpusErrors)encodedLen), "9C923F57-146B-47CB-8EEE-5BF129FA3124")); } return(encodedLen); }
/// <summary> /// Encode audio samples. /// </summary> /// <returns>The total number of bytes written to dstOutputBuffer.</returns> public int EncodeFloats(ArraySegment <float> sourcePcm, ArraySegment <byte> dstEncoded) { if (sourcePcm.Array == null) { throw new ArgumentNullException("sourcePcm", Log.PossibleBugMessage("source pcm must not be null", "58AE3110-8F9A-4C36-9520-B7F3383096EC")); } if (dstEncoded.Array == null) { throw new ArgumentNullException("dstEncoded", Log.PossibleBugMessage("destination must not be null", "36C327BB-A128-400D-AFB3-FF760A1562C1")); } if (Array.IndexOf(PermittedFrameSizes, sourcePcm.Count) == -1) { throw new ArgumentException(Log.PossibleBugMessage(string.Format("Incorrect frame size '{0}'", sourcePcm.Count), "6AFD9ADF-1D15-4197-99E9-5A19ECB8CD20"), "sourcePcm"); } int encodedLen; using (var srcHandle = sourcePcm.Pin()) using (var dstHandle = dstEncoded.Pin()) { encodedLen = OpusNativeMethods.opus_encode_float(_encoder, srcHandle.Ptr, sourcePcm.Count, dstHandle.Ptr, dstEncoded.Count); } if (encodedLen < 0) { throw new OpusException(Log.PossibleBugMessage(string.Format("Encoding failed: {0}", (OpusErrors)encodedLen), "9C923F57-146B-47CB-8EEE-5BF129FA3124")); } return(encodedLen); }
public void Reset() { using (var decoder = _decoder.Lock()) { //Reset takes no args, returns no values, and cannot fail. So we're passing in nothing, outputting nothing, and ignoring the return code OpusNativeMethods.dissonance_opus_decoder_ctl_in(decoder.Value, Ctl.ResetState, 0); } }
public void Clip(ArraySegment <float> samples) { #if !NCRUNCH using (var handle = samples.Pin()) { OpusNativeMethods.opus_pcm_soft_clip( handle.Ptr, samples.Count / _memory.Length, _memory.Length, _memory ); } #endif }
public void Reset() { using (var encoder = _encoder.Lock()) { if (encoder.Value == IntPtr.Zero) { throw Log.CreatePossibleBugException("Attempted to access a null Opus encoder", "A86D13A5-FC58-446C-9522-DDD9D199DFA6"); } //Wtf is going on here? //Reset takes no args, returns no values, and cannot fail. So we're passing in nothing, outputting nothing, and ignoring the return code OpusNativeMethods.dissonance_opus_encoder_ctl_in(encoder.Value, Ctl.ResetState, 0); } }
/// <summary> /// Decodes audio samples. /// </summary> /// <param name="srcEncodedBuffer">Encoded data (or null, to reconstruct a missing frame)</param> /// <param name="dstBuffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values starting at offset replaced with audio samples.</param> /// <returns>The number of floats decoded and written to dstBuffer.</returns> /// <remarks>Set srcEncodedBuffer to null to instruct the decoder that a packet was dropped.</remarks> public int DecodeFloats(ArraySegment <byte>?srcEncodedBuffer, ArraySegment <float> dstBuffer) { int length; using (var dstHandle = dstBuffer.Pin()) { if (srcEncodedBuffer.HasValue) { using (var srcHandle = srcEncodedBuffer.Value.Pin()) { length = OpusNativeMethods.opus_decode_float( _decoder, srcHandle.Ptr, srcEncodedBuffer.Value.Count, dstHandle.Ptr, dstBuffer.Count, false ); } } else { //Call decoder with null pointer and zero length to inform it of packet loss length = OpusNativeMethods.opus_decode_float( _decoder, IntPtr.Zero, 0, dstHandle.Ptr, dstBuffer.Count, EnableForwardErrorCorrection ); } } if (length < 0) { if (length == (int)OpusErrors.InvalidPacket) { if (!srcEncodedBuffer.HasValue) { throw new OpusException(Log.PossibleBugMessage("Decoding failed: InvalidPacket. 'null' ", "03BE7561-3BCC-4F41-A7CB-C80F03981267")); } else { throw new OpusException(Log.PossibleBugMessage(string.Format("Decoding failed: InvalidPacket. '{0}'", Convert.ToBase64String(srcEncodedBuffer.Value.Array, srcEncodedBuffer.Value.Offset, srcEncodedBuffer.Value.Count)), "EF4BC24C-491E-45D9-974C-FE5CB61BD54E")); } } else { throw new OpusException(Log.PossibleBugMessage(string.Format("Decoding failed: {0} ", (OpusErrors)length), "A9C8EF2C-7830-4D8E-9D6E-EF0B9827E0A8")); } } return(length); }
public void Dispose() { if (_disposed) { return; } GC.SuppressFinalize(this); if (_decoder != IntPtr.Zero) { OpusNativeMethods.opus_decoder_destroy(_decoder); _decoder = IntPtr.Zero; } _disposed = true; }
public OpusDecoder(int outputSampleRate, int outputChannelCount) { if (outputSampleRate != 8000 && outputSampleRate != 12000 && outputSampleRate != 16000 && outputSampleRate != 24000 && outputSampleRate != 48000) { throw new ArgumentOutOfRangeException("outputSampleRate", Log.PossibleBugMessage("sample rate must be one of the valid values", "548757DF-DC64-40C9-BEAD-9826B8245A7D")); } if (outputChannelCount != 1 && outputChannelCount != 2) { throw new ArgumentOutOfRangeException("outputChannelCount", Log.PossibleBugMessage("channel count must be 1 or 2", "BA56610F-1FA3-4D68-9507-7B0DFA0E28AB")); } int error; _decoder = new LockedValue <IntPtr>(OpusNativeMethods.opus_decoder_create(outputSampleRate, outputChannelCount, out error)); if ((OpusErrors)error != OpusErrors.Ok) { throw new OpusException(Log.PossibleBugMessage(string.Format("Exception occured while creating decoder: {0}", (OpusErrors)error), "6E09F275-99A1-4CD6-A36A-FA093B146B29")); } }
public OpusSoftClip(int channels = 1) { if (channels <= 0) { throw new ArgumentOutOfRangeException("channels", "Channels must be > 0"); } //Try to access opus, if it fails to load the DLL then disable the soft clipper try { OpusNativeMethods.opus_pcm_soft_clip(IntPtr.Zero, 0, 0, null); } catch (DllNotFoundException) { _disabled = true; } _memory = new float[channels]; }
public void Dispose() { if (_disposed) { return; } GC.SuppressFinalize(this); using (var decoder = _decoder.Lock()) { if (decoder.Value != IntPtr.Zero) { OpusNativeMethods.opus_decoder_destroy(decoder.Value); decoder.Value = IntPtr.Zero; } } _disposed = true; }
private int OpusCtlOut(Ctl ctl, out int value) { int ret; using (var encoder = _encoder.Lock()) { if (encoder.Value == IntPtr.Zero) { throw new ObjectDisposedException("OpusEncoder", Log.PossibleBugMessage("trying to use decoder after is has been disposed", "10A3BFFB-EC3B-4664-B06C-D5D42F75FE42")); } ret = OpusNativeMethods.dissonance_opus_encoder_ctl_out(encoder.Value, ctl, out value); } if (ret < 0) { throw new Exception(Log.PossibleBugMessage(string.Format("Encoder error (Ctl {0}): {1}", ctl, (OpusErrors)ret), "4AAA9AA6-8429-4346-B939-D113206FFBA8")); } return(ret); }
/// <summary> /// Decodes audio samples. /// </summary> /// <param name="srcEncodedBuffer">Encoded data (or null, to reconstruct a missing frame)</param> /// <param name="dstBuffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values starting at offset replaced with audio samples.</param> /// <returns>The number of floats decoded and written to dstBuffer.</returns> /// <remarks>Set srcEncodedBuffer to null to instruct the decoder that a packet was dropped.</remarks> public int DecodeFloats(EncodedBuffer srcEncodedBuffer, ArraySegment <float> dstBuffer) { int length; using (var decoder = _decoder.Lock()) { if (decoder.Value == IntPtr.Zero) { throw new DissonanceException(Log.PossibleBugMessage("Attempted to access a null Opus decoder", "16261551-968B-44A8-80A1-E8DFB0109469")); } //Decode some data into the dstBuffer // - We have the packet => run decode // - We have a packet but lost flag is set => run FEC (if allowed) // - We have no packet => Run PLC using (var dstHandle = dstBuffer.Pin()) { if (!srcEncodedBuffer.Encoded.HasValue || (srcEncodedBuffer.PacketLost && !EnableForwardErrorCorrection)) { Log.Trace("Lost packet, but not applying FEC (srcEncodedBuffer.Encoded.HasValue:{0}, EnableForwardErrorCorrection:{1}", srcEncodedBuffer.Encoded.HasValue, EnableForwardErrorCorrection); // We've lost a packet but cannot apply FEC because either we don't know what the next packet is (required for FEC) or FEC is explicitly disabled. // Call decoder with null pointer and zero length to invoke basic packet loss concealment length = OpusNativeMethods.opus_decode_float( decoder.Value, IntPtr.Zero, 0, dstHandle.Ptr, dstBuffer.Count, false ); } else { // Either we have a packet, or FEC is enabled and we have the _next_ packet using (var srcHandle = srcEncodedBuffer.Encoded.Value.Pin()) { length = OpusNativeMethods.opus_decode_float( decoder.Value, srcHandle.Ptr, srcEncodedBuffer.Encoded.Value.Count, dstHandle.Ptr, dstBuffer.Count, srcEncodedBuffer.PacketLost ); } } } } if (length < 0) { if (length == (int)OpusErrors.InvalidPacket) { if (!srcEncodedBuffer.Encoded.HasValue) { throw new OpusException(Log.PossibleBugMessage("Decoding failed: InvalidPacket. 'null' ", "03BE7561-3BCC-4F41-A7CB-C80F03981267")); } else { var arr = srcEncodedBuffer.Encoded.Value; // ReSharper disable once AssignNullToNotNullAttribute (Justification Array of the segment isn't null here) throw new OpusException(Log.PossibleBugMessage(string.Format("Decoding failed: InvalidPacket. '{0}'", Convert.ToBase64String(arr.Array, arr.Offset, arr.Count)), "EF4BC24C-491E-45D9-974C-FE5CB61BD54E")); } } else { throw new OpusException(Log.PossibleBugMessage(string.Format("Decoding failed: {0} ", (OpusErrors)length), "A9C8EF2C-7830-4D8E-9D6E-EF0B9827E0A8")); } } return(length); }
[NotNull] public static string OpusVersion() { // ReSharper disable once AssignNullToNotNullAttribute return(Marshal.PtrToStringAnsi(OpusNativeMethods.opus_get_version_string())); }
/// <summary> /// Decodes audio samples. /// </summary> /// <param name="srcEncodedBuffer">Encoded data (or null, to reconstruct a missing frame)</param> /// <param name="dstBuffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values starting at offset replaced with audio samples.</param> /// <returns>The number of floats decoded and written to dstBuffer.</returns> /// <remarks>Set srcEncodedBuffer to null to instruct the decoder that a packet was dropped.</remarks> public int DecodeFloats(ArraySegment <byte>?srcEncodedBuffer, ArraySegment <float> dstBuffer) { int length; using (var decoder = _decoder.Lock()) { if (decoder.Value == IntPtr.Zero) { throw new DissonanceException(Log.PossibleBugMessage("Attempted to access a null Opus decoder", "16261551-968B-44A8-80A1-E8DFB0109469")); } using (var dstHandle = dstBuffer.Pin()) { if (srcEncodedBuffer.HasValue) { using (var srcHandle = srcEncodedBuffer.Value.Pin()) { length = OpusNativeMethods.opus_decode_float( decoder.Value, srcHandle.Ptr, srcEncodedBuffer.Value.Count, dstHandle.Ptr, dstBuffer.Count, false ); } } else { //Call decoder with null pointer and zero length to inform it of packet loss length = OpusNativeMethods.opus_decode_float( decoder.Value, IntPtr.Zero, 0, dstHandle.Ptr, dstBuffer.Count, EnableForwardErrorCorrection ); } } } if (length < 0) { if (length == (int)OpusErrors.InvalidPacket) { if (!srcEncodedBuffer.HasValue) { throw new OpusException(Log.PossibleBugMessage("Decoding failed: InvalidPacket. 'null' ", "03BE7561-3BCC-4F41-A7CB-C80F03981267")); } else { // ReSharper disable once AssignNullToNotNullAttribute (Justification Array of the segment isn't null here) throw new OpusException(Log.PossibleBugMessage(string.Format("Decoding failed: InvalidPacket. '{0}'", Convert.ToBase64String(srcEncodedBuffer.Value.Array, srcEncodedBuffer.Value.Offset, srcEncodedBuffer.Value.Count)), "EF4BC24C-491E-45D9-974C-FE5CB61BD54E")); } } else { throw new OpusException(Log.PossibleBugMessage(string.Format("Decoding failed: {0} ", (OpusErrors)length), "A9C8EF2C-7830-4D8E-9D6E-EF0B9827E0A8")); } } return(length); }