diff --git a/OpusDemo/Form1.cs b/OpusDemo/Form1.cs index e2b543c..bdbe2ea 100644 --- a/OpusDemo/Form1.cs +++ b/OpusDemo/Form1.cs @@ -7,7 +7,7 @@ using System.Text; using System.Windows.Forms; using NAudio.Wave; -using FragLabs.Audio.Codecs; +using OpusNet; namespace OpusDemo { @@ -64,9 +64,9 @@ void StartEncoding() _startTime = DateTime.Now; _bytesSent = 0; _segmentFrames = 960; - _encoder = OpusEncoder.Create(48000, 1, FragLabs.Audio.Codecs.Opus.Application.Voip); + _encoder = new OpusEncoder(48000, 1, OpusNet.OpusApplication.Voip); _encoder.Bitrate = 8192; - _decoder = OpusDecoder.Create(48000, 1); + _decoder = new OpusDecoder(48000, 1); _bytesPerSegment = _encoder.FrameByteCount(_segmentFrames); _waveIn = new WaveIn(WaveCallbackInfo.FunctionCallback()); diff --git a/OpusDemo/OpusDemo.csproj b/OpusDemo/OpusDemo.csproj index d31dff3..9b2be7e 100644 --- a/OpusDemo/OpusDemo.csproj +++ b/OpusDemo/OpusDemo.csproj @@ -1,5 +1,5 @@  - + Debug @@ -9,11 +9,12 @@ Properties OpusDemo OpusDemo - v4.0 + v4.5.1 512 + - x86 + AnyCPU true full false @@ -21,15 +22,17 @@ DEBUG;TRACE prompt 4 + false - x86 + AnyCPU pdbonly true bin\Release\ TRACE prompt 4 + false @@ -66,7 +69,9 @@ True Resources.resx + True + SettingsSingleFileGenerator @@ -79,9 +84,9 @@ - + {838bdb0b-5eb1-4c1e-9026-0a8842ac00c6} - OpusWrapper + OpusNet diff --git a/OpusDemo/Properties/Resources.Designer.cs b/OpusDemo/Properties/Resources.Designer.cs index ff7e2b0..51f9f3c 100644 --- a/OpusDemo/Properties/Resources.Designer.cs +++ b/OpusDemo/Properties/Resources.Designer.cs @@ -1,17 +1,17 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.17929 +// Runtime Version:4.0.30319.34003 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ -namespace OpusDemo.Properties -{ - - +namespace OpusDemo.Properties { + using System; + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -22,48 +22,40 @@ namespace OpusDemo.Properties [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources - { - + internal class Resources { + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() - { + internal Resources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager - { - get - { - if ((resourceMan == null)) - { + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpusDemo.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture - { - get - { + internal static global::System.Globalization.CultureInfo Culture { + get { return resourceCulture; } - set - { + set { resourceCulture = value; } } diff --git a/OpusDemo/Properties/Settings.Designer.cs b/OpusDemo/Properties/Settings.Designer.cs index b4b4fc3..1478348 100644 --- a/OpusDemo/Properties/Settings.Designer.cs +++ b/OpusDemo/Properties/Settings.Designer.cs @@ -1,28 +1,24 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.17929 +// Runtime Version:4.0.30319.34003 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ -namespace OpusDemo.Properties -{ - - +namespace OpusDemo.Properties { + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { + + public static Settings Default { + get { return defaultInstance; } } diff --git a/OpusDemo/app.config b/OpusDemo/app.config new file mode 100644 index 0000000..37fee69 --- /dev/null +++ b/OpusDemo/app.config @@ -0,0 +1,3 @@ + + + diff --git a/OpusWrapper.sln b/OpusNet.sln similarity index 88% rename from OpusWrapper.sln rename to OpusNet.sln index 3b3bb89..f9806bc 100644 --- a/OpusWrapper.sln +++ b/OpusNet.sln @@ -1,26 +1,26 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpusWrapper", "OpusWrapper\OpusWrapper.csproj", "{838BDB0B-5EB1-4C1E-9026-0A8842AC00C6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpusDemo", "OpusDemo\OpusDemo.csproj", "{A015969C-3FC3-456C-87D8-9C5C09B5BA22}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {838BDB0B-5EB1-4C1E-9026-0A8842AC00C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {838BDB0B-5EB1-4C1E-9026-0A8842AC00C6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {838BDB0B-5EB1-4C1E-9026-0A8842AC00C6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {838BDB0B-5EB1-4C1E-9026-0A8842AC00C6}.Release|Any CPU.Build.0 = Release|Any CPU - {A015969C-3FC3-456C-87D8-9C5C09B5BA22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A015969C-3FC3-456C-87D8-9C5C09B5BA22}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A015969C-3FC3-456C-87D8-9C5C09B5BA22}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A015969C-3FC3-456C-87D8-9C5C09B5BA22}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpusNet", "OpusNet\OpusNet.csproj", "{838BDB0B-5EB1-4C1E-9026-0A8842AC00C6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpusDemo", "OpusDemo\OpusDemo.csproj", "{A015969C-3FC3-456C-87D8-9C5C09B5BA22}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {838BDB0B-5EB1-4C1E-9026-0A8842AC00C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {838BDB0B-5EB1-4C1E-9026-0A8842AC00C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {838BDB0B-5EB1-4C1E-9026-0A8842AC00C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {838BDB0B-5EB1-4C1E-9026-0A8842AC00C6}.Release|Any CPU.Build.0 = Release|Any CPU + {A015969C-3FC3-456C-87D8-9C5C09B5BA22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A015969C-3FC3-456C-87D8-9C5C09B5BA22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A015969C-3FC3-456C-87D8-9C5C09B5BA22}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A015969C-3FC3-456C-87D8-9C5C09B5BA22}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/OpusNet/Library.cs b/OpusNet/Library.cs new file mode 100644 index 0000000..015fec6 --- /dev/null +++ b/OpusNet/Library.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace OpusNet +{ + public static class Library + { + public static string opus_x32 = "opus32.dll"; + public static string opus_x64 = "opus64.dll"; + + public static string opus_dll = IntPtr.Size == 4 ? opus_x32 : opus_x64; + + } +} diff --git a/OpusWrapper/OpusDecoder.cs b/OpusNet/OpusDecoder.cs similarity index 79% rename from OpusWrapper/OpusDecoder.cs rename to OpusNet/OpusDecoder.cs index 2155abf..2771682 100644 --- a/OpusWrapper/OpusDecoder.cs +++ b/OpusNet/OpusDecoder.cs @@ -1,20 +1,26 @@ using System; -using FragLabs.Audio.Codecs.Opus; -namespace FragLabs.Audio.Codecs +namespace OpusNet { /// /// Opus audio decoder. /// public class OpusDecoder : IDisposable { + private IntPtr _decoder; + + static OpusDecoder() + { + Wrapper.Initialize(); + } + /// /// Creates a new Opus decoder. /// /// Sample rate to decode at (Hz). This must be one of 8000, 12000, 16000, 24000, or 48000. /// Number of channels to decode. /// A new OpusDecoder. - public static OpusDecoder Create(int outputSampleRate, int outputChannels) + public OpusDecoder(int outputSampleRate, int outputChannels) { if (outputSampleRate != 8000 && outputSampleRate != 12000 && @@ -26,22 +32,13 @@ public static OpusDecoder Create(int outputSampleRate, int outputChannels) throw new ArgumentOutOfRangeException("inputChannels"); IntPtr error; - IntPtr decoder = API.opus_decoder_create(outputSampleRate, outputChannels, out error); + this._decoder = Wrapper.opus_decoder_create(outputSampleRate, outputChannels, out error); if ((Errors)error != Errors.OK) - { throw new Exception("Exception occured while creating decoder"); - } - return new OpusDecoder(decoder, outputSampleRate, outputChannels); - } - private IntPtr _decoder; - - private OpusDecoder(IntPtr decoder, int outputSamplingRate, int outputChannels) - { - _decoder = decoder; - OutputSamplingRate = outputSamplingRate; - OutputChannels = outputChannels; - MaxDataBytes = 4000; + this.OutputSamplingRate = outputSampleRate; + this.OutputChannels = outputChannels; + this.MaxDataBytes = 4000; } /// @@ -63,9 +60,9 @@ public unsafe byte[] Decode(byte[] inputOpusData, int dataLength, out int decode fixed (byte* bdec = decoded) { decodedPtr = new IntPtr((void*)bdec); - length = API.opus_decode(_decoder, inputOpusData, dataLength, decodedPtr, frameCount, 0); + length = Wrapper.opus_decode(_decoder, inputOpusData, dataLength, decodedPtr, frameCount, 0); } - decodedLength = length * 2; + decodedLength = length * 2 * OutputChannels; if (length < 0) throw new Exception("Decoding failed - " + ((Errors)length).ToString()); @@ -115,7 +112,7 @@ public void Dispose() if (_decoder != IntPtr.Zero) { - API.opus_decoder_destroy(_decoder); + Wrapper.opus_decoder_destroy(_decoder); _decoder = IntPtr.Zero; } diff --git a/OpusWrapper/OpusEncoder.cs b/OpusNet/OpusEncoder.cs similarity index 76% rename from OpusWrapper/OpusEncoder.cs rename to OpusNet/OpusEncoder.cs index 0d68fa6..04537d5 100644 --- a/OpusWrapper/OpusEncoder.cs +++ b/OpusNet/OpusEncoder.cs @@ -1,14 +1,21 @@ using System; using System.Collections.Generic; -using FragLabs.Audio.Codecs.Opus; -namespace FragLabs.Audio.Codecs +namespace OpusNet { /// /// Opus codec wrapper. /// public class OpusEncoder : IDisposable { + private IntPtr _encoder; + + + static OpusEncoder() + { + Wrapper.Initialize(); + } + /// /// Creates a new Opus encoder. /// @@ -16,35 +23,27 @@ public class OpusEncoder : IDisposable /// Number of channels (1 or 2) in input signal. /// Coding mode. /// A new OpusEncoder - public static OpusEncoder Create(int inputSamplingRate, int inputChannels, Application application) + public OpusEncoder(int inputSamplingRate, int inputChannels, OpusApplication application) { if (inputSamplingRate != 8000 && - inputSamplingRate != 12000 && - inputSamplingRate != 16000 && - inputSamplingRate != 24000 && - inputSamplingRate != 48000) + inputSamplingRate != 12000 && + inputSamplingRate != 16000 && + inputSamplingRate != 24000 && + inputSamplingRate != 48000) throw new ArgumentOutOfRangeException("inputSamplingRate"); if (inputChannels != 1 && inputChannels != 2) throw new ArgumentOutOfRangeException("inputChannels"); IntPtr error; - IntPtr encoder = API.opus_encoder_create(inputSamplingRate, inputChannels, (int)application, out error); + this._encoder = Wrapper.opus_encoder_create(inputSamplingRate, inputChannels, (int)application, out error); + if ((Errors)error != Errors.OK) - { throw new Exception("Exception occured while creating encoder"); - } - return new OpusEncoder(encoder, inputSamplingRate, inputChannels, application); - } - private IntPtr _encoder; - - private OpusEncoder(IntPtr encoder, int inputSamplingRate, int inputChannels, Application application) - { - _encoder = encoder; - InputSamplingRate = inputSamplingRate; - InputChannels = inputChannels; - Application = application; - MaxDataBytes = 4000; + this.InputSamplingRate = inputSamplingRate; + this.InputChannels = inputChannels; + this.Application = application; + this.MaxDataBytes = 4000; } /// @@ -66,7 +65,7 @@ public unsafe byte[] Encode(byte[] inputPcmSamples, int sampleLength, out int en fixed (byte* benc = encoded) { encodedPtr = new IntPtr((void*)benc); - length = API.opus_encode(_encoder, inputPcmSamples, frames, encodedPtr, sampleLength); + length = Wrapper.opus_encode(_encoder, inputPcmSamples, frames, encodedPtr, sampleLength); } encodedLength = length; if (length < 0) @@ -113,7 +112,7 @@ public int FrameByteCount(int frameCount) /// /// Gets the coding mode of the encoder. /// - public Application Application { get; private set; } + public OpusApplication Application { get; private set; } /// /// Gets or sets the size of memory allocated for reading encoded data. @@ -131,7 +130,7 @@ public int Bitrate if (disposed) throw new ObjectDisposedException("OpusEncoder"); int bitrate; - var ret = API.opus_encoder_ctl(_encoder, Ctl.GetBitrateRequest, out bitrate); + var ret = Wrapper.opus_encoder_ctl2(_encoder, Ctl.GetBitrateRequest, out bitrate); if (ret < 0) throw new Exception("Encoder error - " + ((Errors)ret).ToString()); return bitrate; @@ -140,7 +139,7 @@ public int Bitrate { if (disposed) throw new ObjectDisposedException("OpusEncoder"); - var ret = API.opus_encoder_ctl(_encoder, Ctl.SetBitrateRequest, value); + var ret = Wrapper.opus_encoder_ctl1(_encoder, Ctl.SetBitrateRequest, value); if (ret < 0) throw new Exception("Encoder error - " + ((Errors)ret).ToString()); } @@ -161,7 +160,7 @@ public void Dispose() if (_encoder != IntPtr.Zero) { - API.opus_encoder_destroy(_encoder); + Wrapper.opus_encoder_destroy(_encoder); _encoder = IntPtr.Zero; } diff --git a/OpusWrapper/OpusWrapper.csproj b/OpusNet/OpusNet.csproj similarity index 74% rename from OpusWrapper/OpusWrapper.csproj rename to OpusNet/OpusNet.csproj index ba4614d..4b1bc60 100644 --- a/OpusWrapper/OpusWrapper.csproj +++ b/OpusNet/OpusNet.csproj @@ -1,64 +1,72 @@ - - - - - Debug - AnyCPU - {838BDB0B-5EB1-4C1E-9026-0A8842AC00C6} - Library - Properties - FragLabs.Audio.Codecs - OpusWrapper - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - x86 - true - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - x86 - true - - - - - - - - - - - - - - - - - - - Always - - - - + + + + + Debug + AnyCPU + {838BDB0B-5EB1-4C1E-9026-0A8842AC00C6} + Library + Properties + OpusNet + OpusNet + v4.5.1 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AnyCPU + true + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AnyCPU + true + false + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + \ No newline at end of file diff --git a/OpusWrapper/Properties/AssemblyInfo.cs b/OpusNet/Properties/AssemblyInfo.cs similarity index 84% rename from OpusWrapper/Properties/AssemblyInfo.cs rename to OpusNet/Properties/AssemblyInfo.cs index 6ffe153..6265782 100644 --- a/OpusWrapper/Properties/AssemblyInfo.cs +++ b/OpusNet/Properties/AssemblyInfo.cs @@ -5,12 +5,12 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("OpusWrapper")] +[assembly: AssemblyTitle("OpusNet")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("OpusWrapper")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2012")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpusNet")] +[assembly: AssemblyCopyright("Copyright ©")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/OpusWrapper/Opus/API.cs b/OpusNet/Types.cs similarity index 51% rename from OpusWrapper/Opus/API.cs rename to OpusNet/Types.cs index 830a900..20c4aaa 100644 --- a/OpusWrapper/Opus/API.cs +++ b/OpusNet/Types.cs @@ -1,96 +1,65 @@ -using System; -using System.Runtime.InteropServices; - -namespace FragLabs.Audio.Codecs.Opus -{ - /// - /// Wraps the Opus API. - /// - internal class API - { - [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr opus_encoder_create(int Fs, int channels, int application, out IntPtr error); - - [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern void opus_encoder_destroy(IntPtr encoder); - - [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern int opus_encode(IntPtr st, byte[] pcm, int frame_size, IntPtr data, int max_data_bytes); - - [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr opus_decoder_create(int Fs, int channels, out IntPtr error); - - [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern void opus_decoder_destroy(IntPtr decoder); - - [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern int opus_decode(IntPtr st, byte[] data, int len, IntPtr pcm, int frame_size, int decode_fec); - - [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern int opus_encoder_ctl(IntPtr st, Ctl request, int value); - - [DllImport("opus.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern int opus_encoder_ctl(IntPtr st, Ctl request, out int value); - } - - public enum Ctl : int - { - SetBitrateRequest = 4002, - GetBitrateRequest = 4003 - } - - /// - /// Supported coding modes. - /// - public enum Application - { - /// - /// Best for most VoIP/videoconference applications where listening quality and intelligibility matter most. - /// - Voip = 2048, - /// - /// Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to input. - /// - Audio = 2049, - /// - /// Only use when lowest-achievable latency is what matters most. Voice-optimized modes cannot be used. - /// - Restricted_LowLatency = 2051 - } - - public enum Errors - { - /// - /// No error. - /// - OK = 0, - /// - /// One or more invalid/out of range arguments. - /// - BadArg = -1, - /// - /// The mode struct passed is invalid. - /// - BufferToSmall = -2, - /// - /// An internal error was detected. - /// - InternalError = -3, - /// - /// The compressed data passed is corrupted. - /// - InvalidPacket = -4, - /// - /// Invalid/unsupported request number. - /// - Unimplemented = -5, - /// - /// An encoder or decoder structure is invalid or already freed. - /// - InvalidState = -6, - /// - /// Memory allocation has failed. - /// - AllocFail = -7 - } -} +using System; + +namespace OpusNet +{ + public enum Ctl : int + { + SetBitrateRequest = 4002, + GetBitrateRequest = 4003 + } + + /// + /// Supported coding modes. + /// + public enum OpusApplication + { + /// + /// Best for most VoIP/videoconference applications where listening quality and intelligibility matter most. + /// + Voip = 2048, + /// + /// Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to input. + /// + Audio = 2049, + /// + /// Only use when lowest-achievable latency is what matters most. Voice-optimized modes cannot be used. + /// + Restricted_LowLatency = 2051 + } + + public enum Errors + { + /// + /// No error. + /// + OK = 0, + /// + /// One or more invalid/out of range arguments. + /// + BadArg = -1, + /// + /// The mode struct passed is invalid. + /// + BufferToSmall = -2, + /// + /// An internal error was detected. + /// + InternalError = -3, + /// + /// The compressed data passed is corrupted. + /// + InvalidPacket = -4, + /// + /// Invalid/unsupported request number. + /// + Unimplemented = -5, + /// + /// An encoder or decoder structure is invalid or already freed. + /// + InvalidState = -6, + /// + /// Memory allocation has failed. + /// + AllocFail = -7 + } +} diff --git a/OpusNet/Wrapper.cs b/OpusNet/Wrapper.cs new file mode 100644 index 0000000..0dcaac9 --- /dev/null +++ b/OpusNet/Wrapper.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace OpusNet +{ + internal class Wrapper + { + #region Variables + //---------------------------------------------------------------------------------------------------------------- + + [DllImport("kernel32")] + extern static IntPtr LoadLibrary(string librayName); + + [DllImport("kernel32")] + static extern IntPtr GetProcAddress(IntPtr hModule, String procName); + + //---------------------------------------------------------------------------------------------------------------- + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr del_opus_encoder_create(int Fs, int channels, int application, out IntPtr error); + internal static del_opus_encoder_create opus_encoder_create; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void del_opus_encoder_destroy(IntPtr encoder); + internal static del_opus_encoder_destroy opus_encoder_destroy; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate int del_opus_encode(IntPtr st, byte[] pcm, int frame_size, IntPtr data, int max_data_bytes); + internal static del_opus_encode opus_encode; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr del_opus_decoder_create(int Fs, int channels, out IntPtr error); + internal static del_opus_decoder_create opus_decoder_create; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void del_opus_decoder_destroy(IntPtr decoder); + internal static del_opus_decoder_destroy opus_decoder_destroy; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate int del_opus_decode(IntPtr st, byte[] data, int len, IntPtr pcm, int frame_size, int decode_fec); + internal static del_opus_decode opus_decode; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate int del_opus_encoder_ctl1(IntPtr st, Ctl request, int value); + internal static del_opus_encoder_ctl1 opus_encoder_ctl1; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate int del_opus_encoder_ctl2(IntPtr st, Ctl request, out int value); + internal static del_opus_encoder_ctl2 opus_encoder_ctl2; + + //---------------------------------------------------------------------------------------------------------------- + + static IntPtr m_libraryHandle; + static bool Initialized = false; + + //---------------------------------------------------------------------------------------------------------------- + #endregion + + + #region Constructor + //---------------------------------------------------------------------------------------------------------------- + static Wrapper() + { + } + //---------------------------------------------------------------------------------------------------------------- + #endregion + + + #region Functions + //---------------------------------------------------------------------------------------------------------------- + public static void Initialize() + { + if (!Initialized) + { + Initialized = true; + _LoadLibrary(Library.opus_dll); + + opus_encoder_create = GetFunction("opus_encoder_create"); + opus_encoder_destroy = GetFunction("opus_encoder_destroy"); + opus_encode = GetFunction("opus_encode"); + opus_decoder_create = GetFunction("opus_decoder_create"); + opus_decoder_destroy = GetFunction("opus_decoder_destroy"); + opus_decode = GetFunction("opus_decode"); + opus_encoder_ctl1 = GetFunction("opus_encoder_ctl"); + opus_encoder_ctl2 = GetFunction("opus_encoder_ctl"); + } + } + //---------------------------------------------------------------------------------------------------------------- + + private static void _LoadLibrary(String path) + { + m_libraryHandle = LoadLibrary(path); + + if (m_libraryHandle == IntPtr.Zero) + { + int hr = Marshal.GetHRForLastWin32Error(); + Exception innerException = Marshal.GetExceptionForHR(hr); + if (innerException != null) + throw new Exception("Error loading unmanaged library from path: " + path + ", see inner exception for details.\n" + innerException.Message, innerException); + else + throw new Exception("Error loading unmanaged library from path: " + path); + } + } + + //---------------------------------------------------------------------------------------------------------------- + + internal static T GetFunction(String functionName) where T : class + { + var procAddr = GetProcAddress(m_libraryHandle, functionName); + + if (procAddr == IntPtr.Zero) + return null; + + var function = Marshal.GetDelegateForFunctionPointer(procAddr, typeof(T)); + + return function as T; + } + + //---------------------------------------------------------------------------------------------------------------- + #endregion + + } +} diff --git a/OpusNet/opus32.dll b/OpusNet/opus32.dll new file mode 100644 index 0000000..57bfbbe Binary files /dev/null and b/OpusNet/opus32.dll differ diff --git a/OpusNet/opus64.dll b/OpusNet/opus64.dll new file mode 100644 index 0000000..240c352 Binary files /dev/null and b/OpusNet/opus64.dll differ diff --git a/OpusWrapper/opus.dll b/OpusWrapper/opus.dll deleted file mode 100644 index 560be64..0000000 Binary files a/OpusWrapper/opus.dll and /dev/null differ diff --git a/readme.md b/readme.md index 37fca25..1f17f15 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# Open Interactive Audio Codec +# Open Interactive Audio Codec ## Overview @@ -30,6 +30,8 @@ The WinForms demo app makes use of the excellent NAudio library. Opus.NET is licensed under the MIT license. +Native opus library version is opus-1.0.2. + # Licenses A copy of all licenses are available in the repository.