├── Aural ├── Libs │ ├── 32bit │ │ ├── opus.dll │ │ ├── openal.dll │ │ └── libopus.dylib │ ├── 64bit │ │ ├── opus.dll │ │ └── openal.dll │ └── librpiaudio.so ├── Aural License.txt ├── readme.md ├── IO │ ├── OpenAL │ │ ├── IntSourceProperty.cs │ │ ├── ALEnum.cs │ │ ├── SourceState.cs │ │ ├── AudioFormat.cs │ │ ├── ALCStrings.cs │ │ ├── ALCEnum.cs │ │ ├── FloatSourceProperty.cs │ │ ├── PlaybackDevice.cs │ │ ├── Runner.cs │ │ └── API.cs │ ├── AudioReceivedEventArgs.cs │ ├── IAudioInput.cs │ ├── IAudioOutput.cs │ ├── RaspberryPi │ │ └── API.cs │ ├── RaspberryPiOutput.cs │ ├── OpenALInput.cs │ └── OpenALOutput.cs ├── Encoding │ ├── Opus │ │ ├── Ctl.cs │ │ ├── Application.cs │ │ ├── Errors.cs │ │ └── API.cs │ ├── IScatteredAccessEncoder.cs │ ├── IScatteredAccessDecoder.cs │ ├── IFrameWindowDecoder.cs │ ├── IFrameWindowEncoder.cs │ ├── WaveDecoder.cs │ ├── OpusDecoder.cs │ └── OpusEncoder.cs ├── Properties │ └── AssemblyInfo.cs ├── Gablarski License.txt ├── CpuArchitecture.cs ├── AudioFormat.cs ├── Opus Codec License.txt ├── Processing │ ├── Filters │ │ ├── IAudioFilter.cs │ │ ├── FilterChain.cs │ │ ├── LowPass.cs │ │ └── DecimationDownSampler.cs │ └── FFT.cs ├── PlatformDetails.cs ├── LibraryLoader.cs ├── FormatHelper.cs ├── Aural.csproj └── OpenALSoft License.txt ├── .gitignore └── Aural.sln /Aural/Libs/32bit/opus.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnACarruthers/Aural/HEAD/Aural/Libs/32bit/opus.dll -------------------------------------------------------------------------------- /Aural/Libs/64bit/opus.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnACarruthers/Aural/HEAD/Aural/Libs/64bit/opus.dll -------------------------------------------------------------------------------- /Aural/Libs/librpiaudio.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnACarruthers/Aural/HEAD/Aural/Libs/librpiaudio.so -------------------------------------------------------------------------------- /Aural/Libs/32bit/openal.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnACarruthers/Aural/HEAD/Aural/Libs/32bit/openal.dll -------------------------------------------------------------------------------- /Aural/Libs/64bit/openal.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnACarruthers/Aural/HEAD/Aural/Libs/64bit/openal.dll -------------------------------------------------------------------------------- /Aural/Libs/32bit/libopus.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnACarruthers/Aural/HEAD/Aural/Libs/32bit/libopus.dylib -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #ignore thumbnails created by windows 2 | Thumbs.db 3 | #Ignore files build by Visual Studio 4 | *.obj 5 | *.exe 6 | *.pdb 7 | *.user 8 | *.aps 9 | *.pch 10 | *.vspscc 11 | *_i.c 12 | *_p.c 13 | *.ncb 14 | *.suo 15 | *.tlb 16 | *.tlh 17 | *.bak 18 | *.cache 19 | *.ilk 20 | *.log 21 | ClientBin 22 | [Bb]in 23 | [Dd]ebug*/ 24 | [Ii]pch/ 25 | *.lib 26 | *.sbr 27 | obj/ 28 | [Rr]elease*/ 29 | _ReSharper*/ 30 | [Tt]est[Rr]esult* 31 | Examples*/ 32 | SerializerTest*/ 33 | *.csproj.user 34 | *.resharper* 35 | Download/ 36 | #Ignore files from MonoDevelop 37 | *.pidb 38 | *.userprefs -------------------------------------------------------------------------------- /Aural.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aural", "Aural\Aural.csproj", "{6283D87E-F9E8-41CE-931B-0981797D57F5}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {6283D87E-F9E8-41CE-931B-0981797D57F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {6283D87E-F9E8-41CE-931B-0981797D57F5}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {6283D87E-F9E8-41CE-931B-0981797D57F5}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {6283D87E-F9E8-41CE-931B-0981797D57F5}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /Aural/Aural License.txt: -------------------------------------------------------------------------------- 1 | Author: John Carruthers (johnc@frag-labs.com) 2 | 3 | Copyright (C) 2013 John Carruthers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Aural/readme.md: -------------------------------------------------------------------------------- 1 | # Aural 2 | 3 | Aural is a multipurpose audio library built mainly for my own personal use but others might find helpful. 4 | It's goal is to provide bindings to Xiph.Org audio codecs, a binding for OpenAL and some very basic audio 5 | processing tools. 6 | 7 | ## About 8 | 9 | Currently included in Aural is 32-bit and 64-bit support for Opus Codec and OpenAL on Windows. 10 | 11 | To use the library reference Aural.dll and add opus.dll and openal.dll to your project (maintaining the directory structure) and copy the libraries to the output directory when compiling. 12 | 13 | ## License 14 | 15 | Aural is licensed under the MIT license. 16 | 17 | ## Acknowledgements 18 | 19 | Parts of the included code are provided by 3rd parties: 20 | 21 | * OpenAL binding is based on and partially copied from Eric Maupin's [Gablarski](https://github.com/ermau/gablarski) project. 22 | * [Opus codec](http://www.opus-codec.org/) library is developed by the Xiph.Org Foundation. 23 | * [OpenAL Soft](http://kcat.strangesoft.net/openal.html) is developed by Chris Robinson (kcat(a)strangesoft.net). 24 | * The included FFT was developed by Gerald T. Beauregard. It is also available on his blog here: http://gerrybeauregard.wordpress.com/2011/04/01/an-fft-in-c/ -------------------------------------------------------------------------------- /Aural/IO/OpenAL/IntSourceProperty.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural.IO.OpenAL 26 | { 27 | internal enum IntSourceProperty 28 | { 29 | AL_SOURCE_STATE = 0x1010, 30 | AL_BUFFERS_QUEUED = 0x1015, 31 | AL_BUFFERS_PROCESSED = 0x1016 32 | } 33 | } -------------------------------------------------------------------------------- /Aural/Encoding/Opus/Ctl.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural.Encoding.Opus 26 | { 27 | public enum Ctl : int 28 | { 29 | SetBitrateRequest = 4002, 30 | GetBitrateRequest = 4003, 31 | SetInbandFECRequest = 4012, 32 | GetInbandFECRequest = 4013 33 | } 34 | } -------------------------------------------------------------------------------- /Aural/IO/OpenAL/ALEnum.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural.IO.OpenAL 26 | { 27 | internal enum ALEnum 28 | { 29 | AL_GAIN = 0x100A, 30 | AL_FREQUENCY = 0x2001, 31 | AL_BITS = 0x2002, 32 | AL_CHANNELS = 0x2003, 33 | AL_SIZE = 0x2004, 34 | } 35 | } -------------------------------------------------------------------------------- /Aural/IO/OpenAL/SourceState.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural.IO.OpenAL 26 | { 27 | internal enum SourceState 28 | { 29 | Uninitialized = -1, 30 | Initial = 0x1011, 31 | Playing = 0x1012, 32 | Paused = 0x1013, 33 | Stopped = 0x1014 34 | } 35 | } -------------------------------------------------------------------------------- /Aural/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Aural")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Aural")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0766b745-5a32-4f4d-905c-ce8dcd9e987d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Aural/IO/OpenAL/AudioFormat.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural.IO.OpenAL 26 | { 27 | internal enum AudioFormat 28 | { 29 | Unknown = 0, 30 | Mono8Bit = 0x1100, 31 | Mono16Bit = 0x1101, 32 | Stereo8Bit = 0x1102, 33 | Stereo16Bit = 0x1103 34 | } 35 | } -------------------------------------------------------------------------------- /Aural/Gablarski License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, Eric Maupin 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with 5 | or without modification, are permitted provided that 6 | the following conditions are met: 7 | 8 | - Redistributions of source code must retain the above 9 | copyright notice, this list of conditions and the 10 | following disclaimer. 11 | 12 | - Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the 14 | following disclaimer in the documentation and/or other 15 | materials provided with the distribution. 16 | 17 | - Neither the name of Gablarski nor the names of its 18 | contributors may be used to endorse or promote products 19 | or services derived from this software without specific 20 | prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 23 | AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 24 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 30 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 35 | DAMAGE. -------------------------------------------------------------------------------- /Aural/Encoding/IScatteredAccessEncoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | 28 | namespace FragLabs.Aural.Encoding 29 | { 30 | /// 31 | /// Encoder that writes encoded audio to a . 32 | /// Typically requires a seekable and writable stream. Not suitable for live streaming. 33 | /// 34 | public interface IScatteredAccessEncoder : IDisposable 35 | { 36 | } 37 | } -------------------------------------------------------------------------------- /Aural/Encoding/IScatteredAccessDecoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | 28 | namespace FragLabs.Aural.Encoding 29 | { 30 | /// 31 | /// Decoder that decodes audio from a . 32 | /// Typically requires a seekable and writable stream. Not suitable for live streaming. 33 | /// 34 | public interface IScatteredAccessDecoder : IDisposable 35 | { 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Aural/IO/OpenAL/ALCStrings.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural.IO.OpenAL 26 | { 27 | internal enum ALCStrings : int 28 | { 29 | AL_VERSION = 0xB002, 30 | ALC_DEFAULT_DEVICE_SPECIFIER = 0x1004, 31 | ALC_DEVICE_SPECIFIER = 0x1005, 32 | ALC_CAPTURE_DEVICE_SPECIFIER = 0x310, 33 | ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER = 0x311, 34 | ALC_ALL_DEVICES_SPECIFIER = 0x1013, 35 | ALC_DEFAULT_ALL_DEVICES_SPECIFIER = 0x1012 36 | } 37 | } -------------------------------------------------------------------------------- /Aural/CpuArchitecture.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | namespace FragLabs.Aural 27 | { 28 | /// 29 | /// CPU architecture. 30 | /// 31 | public enum CpuArchitecture 32 | { 33 | /// 34 | /// 32-bit 35 | /// 36 | x86, 37 | /// 38 | /// 64-bit 39 | /// 40 | x64, 41 | /// 42 | /// Unknown architecture 43 | /// 44 | Unknown 45 | } 46 | } -------------------------------------------------------------------------------- /Aural/IO/OpenAL/ALCEnum.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural.IO.OpenAL 26 | { 27 | internal enum ALCEnum 28 | { 29 | ALC_MAJOR_VERSION = 0x1000, 30 | ALC_MINOR_VERSION = 0x1001, 31 | ALC_ATTRIBUTES_SIZE = 0x1002, 32 | ALC_ALL_ATTRIBUTES = 0x1003, 33 | ALC_CAPTURE_SAMPLES = 0x312, 34 | ALC_FREQUENCY = 0x1007, 35 | ALC_REFRESH = 0x1008, 36 | ALC_SYNC = 0x1009, 37 | ALC_MONO_SOURCES = 0x1010, 38 | ALC_STEREO_SOURCES = 0x1011, 39 | } 40 | } -------------------------------------------------------------------------------- /Aural/IO/AudioReceivedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | 28 | namespace FragLabs.Aural.IO 29 | { 30 | public class AudioReceivedEventArgs : EventArgs 31 | { 32 | /// 33 | /// Audio sample buffer. 34 | /// 35 | public byte[] Buffer { get; set; } 36 | 37 | /// 38 | /// Sample count. 39 | /// 40 | public int SampleCount { get; set; } 41 | 42 | /// 43 | /// Byte count. 44 | /// 45 | public int ByteCount { get; set; } 46 | } 47 | } -------------------------------------------------------------------------------- /Aural/IO/OpenAL/FloatSourceProperty.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural.IO.OpenAL 26 | { 27 | internal enum FloatSourceProperty 28 | { 29 | AL_PITCH = 0x1003, 30 | AL_POSITION = 0x1004, 31 | AL_DIRECTION = 0x1005, 32 | AL_VELOCITY = 0x1006, 33 | AL_GAIN = 0x100A, 34 | AL_MIN_GAIN = 0x100D, 35 | AL_MAX_GAIN = 0x100E, 36 | AL_ORIENTATION = 0x100F, 37 | AL_MAX_DISTANCE = 0x1023, 38 | AL_ROLLOFF_FACTOR = 0x1021, 39 | AL_CONE_OUTER_GAIN = 0x1022, 40 | AL_CONE_INNER_ANGLE = 0x1001, 41 | AL_CONE_OUTER_ANGLE = 0x1002, 42 | AL_REFERENCE_DISTANCE = 0x1020 43 | } 44 | } -------------------------------------------------------------------------------- /Aural/AudioFormat.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural 26 | { 27 | /// 28 | /// Audio format. 29 | /// 30 | public class AudioFormat 31 | { 32 | public int BitDepth { get; set; } 33 | public int Channels { get; set; } 34 | public int SampleRate { get; set; } 35 | 36 | public override bool Equals(object obj) 37 | { 38 | var format = obj as AudioFormat; 39 | if (format != null) 40 | { 41 | return (format.BitDepth == BitDepth && format.Channels == Channels && format.SampleRate == SampleRate); 42 | } 43 | return false; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Aural/Opus Codec License.txt: -------------------------------------------------------------------------------- 1 | Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic, 2 | Jean-Marc Valin, Timothy B. Terriberry, 3 | CSIRO, Gregory Maxwell, Mark Borgerding, 4 | Erik de Castro Lopo 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | - Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | - Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | - Neither the name of Internet Society, IETF or IETF Trust, nor the 18 | names of specific contributors, may be used to endorse or promote 19 | products derived from this software without specific prior written 20 | permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 26 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | Opus is subject to the royalty-free patent licenses which are 35 | specified at: 36 | 37 | Xiph.Org Foundation: 38 | https://datatracker.ietf.org/ipr/1524/ 39 | 40 | Microsoft Corporation: 41 | https://datatracker.ietf.org/ipr/1914/ 42 | 43 | Broadcom Corporation: 44 | https://datatracker.ietf.org/ipr/1526/ -------------------------------------------------------------------------------- /Aural/Encoding/Opus/Application.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural.Encoding.Opus 26 | { 27 | /// 28 | /// Supported coding modes. 29 | /// 30 | public enum Application 31 | { 32 | /// 33 | /// Best for most VoIP/videoconference applications where listening quality and intelligibility matter most. 34 | /// 35 | Voip = 2048, 36 | /// 37 | /// Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to input. 38 | /// 39 | Audio = 2049, 40 | /// 41 | /// Only use when lowest-achievable latency is what matters most. Voice-optimized modes cannot be used. 42 | /// 43 | RestrictedLowLatency = 2051 44 | } 45 | } -------------------------------------------------------------------------------- /Aural/Processing/Filters/IAudioFilter.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | namespace FragLabs.Aural.Processing.Filters 26 | { 27 | /// 28 | /// Audio filter. 29 | /// 30 | public interface IAudioFilter 31 | { 32 | /// 33 | /// Gets the expected input audio format. 34 | /// 35 | AudioFormat InputAudioFormat { get; } 36 | 37 | /// 38 | /// Gets the output audio format. 39 | /// 40 | AudioFormat OutputAudioFormat { get; } 41 | 42 | /// 43 | /// Gets a value indicating if the filter supports the byte typed API. 44 | /// 45 | bool SupportsByte { get; } 46 | 47 | /// 48 | /// Gets a value indicating if the filter supports the double typed API. 49 | /// 50 | bool SupportsDouble { get; } 51 | 52 | int Process(byte[] inputPcmSamples, int inputOffset, byte[] outputPcmSamples, int outputOffset, int inputSampleCount); 53 | 54 | int Process(double[] inputSamples, int inputOffset, double[] outputSamples, int outputOffset, 55 | int inputSampleCount); 56 | } 57 | } -------------------------------------------------------------------------------- /Aural/Encoding/IFrameWindowDecoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | 28 | namespace FragLabs.Aural.Encoding 29 | { 30 | /// 31 | /// Decoder that writes decoded data to a byte array. 32 | /// 33 | public interface IFrameWindowDecoder : IDisposable 34 | { 35 | /// 36 | /// Decodes audio samples. 37 | /// 38 | /// Encoded data. 39 | /// The zero-based byte offset in srcEncodedBuffer at which to begin reading encoded data. 40 | /// The number of bytes to read from srcEncodedBuffer. 41 | /// 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. 42 | /// The zero-based byte offset in dstBuffer at which to begin writing decoded audio samples. 43 | /// The number of bytes decoded and written to dstBuffer. 44 | int Decode(byte[] srcEncodedBuffer, int srcOffset, int srcLength, 45 | byte[] dstBuffer, int dstOffset); 46 | } 47 | } -------------------------------------------------------------------------------- /Aural/Encoding/Opus/Errors.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | namespace FragLabs.Aural.Encoding.Opus 27 | { 28 | /// 29 | /// Opus error codes. 30 | /// 31 | public enum Errors 32 | { 33 | /// 34 | /// No error. 35 | /// 36 | OK = 0, 37 | /// 38 | /// One or more invalid/out of range arguments. 39 | /// 40 | BadArg = -1, 41 | /// 42 | /// The mode struct passed is invalid. 43 | /// 44 | BufferToSmall = -2, 45 | /// 46 | /// An internal error was detected. 47 | /// 48 | InternalError = -3, 49 | /// 50 | /// The compressed data passed is corrupted. 51 | /// 52 | InvalidPacket = -4, 53 | /// 54 | /// Invalid/unsupported request number. 55 | /// 56 | Unimplemented = -5, 57 | /// 58 | /// An encoder or decoder structure is invalid or already freed. 59 | /// 60 | InvalidState = -6, 61 | /// 62 | /// Memory allocation has failed. 63 | /// 64 | AllocFail = -7 65 | } 66 | } -------------------------------------------------------------------------------- /Aural/Encoding/IFrameWindowEncoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | 28 | namespace FragLabs.Aural.Encoding 29 | { 30 | /// 31 | /// Encoder that writes encoded audio frames to a buffer suitable for live streaming. 32 | /// 33 | public interface IFrameWindowEncoder : IDisposable 34 | { 35 | /// 36 | /// Encode audio samples. 37 | /// 38 | /// PCM samples to be encoded. 39 | /// The zero-based byte offset in srcPcmSamples at which to begin reading PCM samples. 40 | /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values starting at offset replaced with encoded audio data. 41 | /// The zero-based byte offset in dstOutputBuffer at which to begin writing encoded audio. 42 | /// The number of samples, per channel, to encode. 43 | /// The total number of bytes written to dstOutputBuffer. 44 | int Encode(byte[] srcPcmSamples, int srcOffset, byte[] dstOutputBuffer, int dstOffset, int sampleCount); 45 | 46 | /// 47 | /// Permitted frame sizes in samples per channel. 48 | /// 49 | int[] PermittedFrameSizes { get; } 50 | 51 | /// 52 | /// Gets the default frame size in samples per channel. 53 | /// 54 | int DefaultFrameSize { get; } 55 | } 56 | } -------------------------------------------------------------------------------- /Aural/PlatformDetails.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using System.IO; 28 | 29 | namespace FragLabs.Aural 30 | { 31 | /// 32 | /// Provides access to platform details. 33 | /// 34 | public class PlatformDetails 35 | { 36 | static PlatformDetails() 37 | { 38 | if (Directory.Exists("/Applications") 39 | && Directory.Exists("/System") 40 | && Directory.Exists("/Users") 41 | && Directory.Exists("/Volumes")) 42 | IsMac = true; 43 | if (Environment.OSVersion.Platform == PlatformID.Win32NT || 44 | Environment.OSVersion.Platform == PlatformID.Win32Windows) 45 | IsWindows = true; 46 | if (IntPtr.Size == 4) 47 | CpuArchitecture = CpuArchitecture.x86; 48 | else if (IntPtr.Size == 8) 49 | CpuArchitecture = CpuArchitecture.x64; 50 | else 51 | CpuArchitecture = CpuArchitecture.Unknown; 52 | } 53 | 54 | /// 55 | /// Gets the current cpu architecture. 56 | /// 57 | public static CpuArchitecture CpuArchitecture { get; private set; } 58 | 59 | /// 60 | /// Gets if the current system is a Mac OSX. 61 | /// 62 | public static bool IsMac { get; private set; } 63 | 64 | /// 65 | /// Gets if the current system is windows. 66 | /// 67 | /// true if is windows; otherwise, false. 68 | public static bool IsWindows { get; private set; } 69 | } 70 | } -------------------------------------------------------------------------------- /Aural/LibraryLoader.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using System.Runtime.InteropServices; 28 | 29 | namespace FragLabs.Aural 30 | { 31 | /// 32 | /// Library loader. 33 | /// 34 | internal class LibraryLoader 35 | { 36 | [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)] 37 | private static extern IntPtr LoadLibrary(string lpFileName); 38 | 39 | [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] 40 | private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); 41 | 42 | [DllImport ("dl", CharSet=CharSet.Ansi)] 43 | private static extern IntPtr dlopen(string filename, int flags); 44 | 45 | [DllImport("dl", CharSet = CharSet.Ansi)] 46 | static extern IntPtr dlsym(IntPtr handle, string symbol); 47 | 48 | /// 49 | /// Load a library. 50 | /// 51 | /// 52 | /// 53 | internal static IntPtr Load(string fileName) 54 | { 55 | return PlatformDetails.IsWindows ? LoadLibrary(fileName) : dlopen(fileName, 1); 56 | } 57 | 58 | /// 59 | /// Resolves library function pointer. 60 | /// 61 | /// 62 | /// 63 | /// 64 | internal static IntPtr ResolveSymbol(IntPtr image, string symbol) 65 | { 66 | return PlatformDetails.IsWindows ? GetProcAddress(image, symbol) : dlsym(image, symbol); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Aural/FormatHelper.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | 28 | namespace FragLabs.Aural 29 | { 30 | /// 31 | /// Helpful audio format methods. 32 | /// 33 | public class FormatHelper 34 | { 35 | /// 36 | /// Calculates the size of a single sample for all channels in bytes. 37 | /// 38 | /// Sample bitdepth. 39 | /// The number of channels in a sample. 40 | /// The number of bytes required to store a single sample. 41 | public static int SampleSize(int bitDepth, int channelCount) 42 | { 43 | return (bitDepth/8)*channelCount; 44 | } 45 | 46 | public static double[] Convert16BitToDouble(byte[] input) 47 | { 48 | var inputSamples = input.Length / (16 / 8); 49 | var output = new double[inputSamples]; 50 | var outputIndex = 0; 51 | for (var n = 0; n < inputSamples; n++) 52 | { 53 | var sample = BitConverter.ToInt16(input, n * 2); 54 | output[outputIndex++] = sample / 32768f; 55 | } 56 | return output; 57 | } 58 | 59 | public static byte[] ConvertDoubleto16Bit(double[] input) 60 | { 61 | var inputSamples = input.Length; 62 | var output = new byte[inputSamples*2]; 63 | for (var i = 0; i < inputSamples; i++) 64 | { 65 | var sample = input[i]*32768f; 66 | var asBytes = BitConverter.GetBytes((short) sample); 67 | Buffer.BlockCopy(asBytes, 0, output, i*2, 2); 68 | } 69 | return output; 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /Aural/IO/IAudioInput.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | 28 | namespace FragLabs.Aural.IO 29 | { 30 | /// 31 | /// Audio input. 32 | /// 33 | public interface IAudioInput : IDisposable 34 | { 35 | /// 36 | /// Event raised when audio data is received. 37 | /// 38 | event EventHandler AudioReceived; 39 | 40 | /// 41 | /// Gets the name of the audio input. 42 | /// 43 | string Name { get; } 44 | 45 | /// 46 | /// Gets if the audio input is currently being read. 47 | /// 48 | bool IsReading { get; } 49 | 50 | /// 51 | /// Gets the audio format of input. 52 | /// 53 | AudioFormat Format { get; } 54 | 55 | /// 56 | /// Starts reading audio samples from the audio input. Will raise AudioReceived when audio samples are read from the input. 57 | /// 58 | /// The number of samples, per channel, to read before raising the AudioReceived event. 59 | void StartReading(int sampleCount); 60 | 61 | /// 62 | /// Stops reading audio samples from the audio input. 63 | /// 64 | void StopReading(); 65 | 66 | /// 67 | /// Reads audio samples from the input device into a buffer. 68 | /// 69 | /// 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. 70 | /// The zero-based byte offset in dstOutputBuffer at which to begin writing audio samples. 71 | /// The number of samples, per channel, to read. 72 | /// The total number of bytes written to buffer. 73 | int Read(byte[] buffer, int offset, int sampleCount); 74 | } 75 | } -------------------------------------------------------------------------------- /Aural/IO/IAudioOutput.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | 28 | namespace FragLabs.Aural.IO 29 | { 30 | /// 31 | /// Audio output. 32 | /// 33 | public interface IAudioOutput : IDisposable 34 | { 35 | /// 36 | /// Gets a value indicating if the audio output is currently playing. 37 | /// 38 | bool IsPlaying { get; } 39 | /// 40 | /// Gets a value indicating if the audio output is currently stopped. 41 | /// 42 | bool IsStopped { get; } 43 | /// 44 | /// Gets a value indicating if the audio output is currently paused. 45 | /// 46 | bool IsPaused { get; } 47 | 48 | /// 49 | /// Gets a value indicating if the audio output is open. 50 | /// 51 | bool IsOpen { get; } 52 | 53 | /// 54 | /// Gets the device name. 55 | /// 56 | string Name { get; } 57 | 58 | /// 59 | /// Gets the number of frames queued for playback. May not be precise. 60 | /// 61 | int QueuedSampleCount { get; } 62 | 63 | /// 64 | /// Gets the audio format. 65 | /// 66 | AudioFormat Format { get; } 67 | 68 | /// 69 | /// Open the device for use. 70 | /// 71 | void Open(AudioFormat format); 72 | 73 | /// 74 | /// Close the device. 75 | /// 76 | void Close(); 77 | 78 | /// 79 | /// Begins audio playback. 80 | /// 81 | void Play(); 82 | /// 83 | /// Stops audio playback. 84 | /// 85 | void Stop(); 86 | /// 87 | /// Pauses audio playback. 88 | /// 89 | void Pause(); 90 | 91 | /// 92 | /// Queues PCM samples to be played. 93 | /// 94 | /// 95 | /// 96 | /// 97 | /// The number of samples written. 98 | int Write(byte[] pcmBuffer, int offset, int sampleCount); 99 | } 100 | } -------------------------------------------------------------------------------- /Aural/Processing/Filters/FilterChain.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System.Collections.Generic; 27 | 28 | namespace FragLabs.Aural.Processing.Filters 29 | { 30 | /// 31 | /// A simple filter chain. 32 | /// 33 | public class FilterChain : IAudioFilter 34 | { 35 | private readonly List _filters = new List(); 36 | 37 | public FilterChain() 38 | { 39 | SupportsByte = false; 40 | SupportsDouble = true; 41 | } 42 | 43 | /// 44 | /// Adds an audio filter to the chain. 45 | /// 46 | /// 47 | public void Add(IAudioFilter filter) 48 | { 49 | lock(_filters) 50 | _filters.Add(filter); 51 | if (_filters.Count == 1) 52 | InputAudioFormat = filter.InputAudioFormat; 53 | OutputAudioFormat = filter.OutputAudioFormat; 54 | } 55 | 56 | /// 57 | /// Gets the expected input audio format. 58 | /// 59 | public AudioFormat InputAudioFormat { get; private set; } 60 | 61 | /// 62 | /// Gets the output audio format. 63 | /// 64 | public AudioFormat OutputAudioFormat { get; private set; } 65 | 66 | /// 67 | /// Gets a value indicating if the filter supports the byte typed API. 68 | /// 69 | public bool SupportsByte { get; private set; } 70 | 71 | /// 72 | /// Gets a value indicating if the filter supports the double typed API. 73 | /// 74 | public bool SupportsDouble { get; private set; } 75 | 76 | public int Process(byte[] inputPcmSamples, int inputOffset, byte[] outputPcmSamples, int outputOffset, int inputSampleCount) 77 | { 78 | throw new System.NotImplementedException(); 79 | } 80 | 81 | public int Process(double[] inputSamples, int inputOffset, double[] outputSamples, int outputOffset, int inputSampleCount) 82 | { 83 | lock (_filters) 84 | { 85 | foreach (var filter in _filters) 86 | { 87 | inputSampleCount = filter.Process(inputSamples, inputOffset, outputSamples, outputOffset, inputSampleCount); 88 | } 89 | } 90 | return inputSampleCount; 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /Aural/Processing/Filters/LowPass.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | 28 | namespace FragLabs.Aural.Processing.Filters 29 | { 30 | /// 31 | /// Simple low pass filter. 32 | /// 33 | public class LowPass : IAudioFilter 34 | { 35 | private int _cutoffFrequency; 36 | 37 | public LowPass(AudioFormat audioFormat, int cutoffFrequency) 38 | { 39 | InputAudioFormat = audioFormat; 40 | OutputAudioFormat = audioFormat; 41 | CutoffFrequency = cutoffFrequency; 42 | } 43 | 44 | private double _rc; 45 | private double _dt; 46 | private double _alpha; 47 | 48 | public int CutoffFrequency 49 | { 50 | get { return _cutoffFrequency; } 51 | set 52 | { 53 | _cutoffFrequency = value; 54 | _rc = 1.0f/(_cutoffFrequency*2*3.142); 55 | _dt = 1.0f/InputAudioFormat.SampleRate; 56 | _alpha = _dt/(_rc + _dt); 57 | } 58 | } 59 | 60 | /// 61 | /// Gets or sets the expected input audio format. 62 | /// 63 | public AudioFormat InputAudioFormat { get; private set; } 64 | 65 | /// 66 | /// Gets or sets the output audio format. 67 | /// 68 | public AudioFormat OutputAudioFormat { get; private set; } 69 | 70 | /// 71 | /// Gets a value indicating if the filter supports the byte typed API. 72 | /// 73 | public bool SupportsByte { get { return false; } } 74 | 75 | /// 76 | /// Gets a value indicating if the filter supports the double typed API. 77 | /// 78 | public bool SupportsDouble { get { return true; } } 79 | 80 | public int Process(byte[] inputPcmSamples, int inputOffset, byte[] outputPcmSamples, int outputOffset, int inputSampleCount) 81 | { 82 | throw new NotSupportedException(); 83 | } 84 | 85 | public int Process(double[] inputSamples, int inputOffset, double[] outputSamples, int outputOffset, int inputSampleCount) 86 | { 87 | outputSamples[0] = inputSamples[0]; 88 | for (var i = 1; i < inputSampleCount; i++) 89 | { 90 | outputSamples[i] = outputSamples[i - 1] + (_alpha * (inputSamples[i] - outputSamples[i - 1])); 91 | } 92 | return inputSampleCount; 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /Aural/Encoding/WaveDecoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using System.IO; 28 | 29 | namespace FragLabs.Aural.Encoding 30 | { 31 | public class WaveDecoder : IFrameWindowDecoder 32 | { 33 | private readonly int _bitDepth; 34 | private readonly int _channelCount; 35 | private readonly int _sampleSize; 36 | 37 | public WaveDecoder(int bitDepth, int channelCount) 38 | { 39 | _bitDepth = bitDepth; 40 | _channelCount = channelCount; 41 | _sampleSize = FormatHelper.SampleSize(bitDepth, channelCount); 42 | } 43 | 44 | public int Decode(byte[] srcEncodedBuffer, int srcOffset, int srcLength, byte[] dstBuffer, int dstOffset) 45 | { 46 | // read as many complete samples as will fit in the buffer 47 | var maxLen = dstBuffer.Length - dstOffset; 48 | if (maxLen > srcLength) 49 | maxLen = srcLength; 50 | var sampleCount = maxLen/_sampleSize; 51 | var readCount = sampleCount*_sampleSize; 52 | Buffer.BlockCopy(srcEncodedBuffer, srcOffset, dstBuffer, dstOffset, readCount); 53 | return readCount; 54 | } 55 | 56 | public void Dispose() 57 | { 58 | } 59 | 60 | /// 61 | /// Creates a WaveDecoder instance by reading the RIFF header on a stream. 62 | /// 63 | /// 64 | /// 65 | /// 66 | /// 67 | public static WaveDecoder FromStream(Stream wavStream, out AudioFormat audioFormat, 68 | out TimeSpan duration) 69 | { 70 | var riffHeader = new byte[12]; 71 | wavStream.Read(riffHeader, 0, riffHeader.Length); 72 | 73 | var chunkSize = BitConverter.ToInt32(riffHeader, 4); 74 | 75 | var subchunkHeader = new byte[8]; 76 | wavStream.Read(subchunkHeader, 0, subchunkHeader.Length); 77 | 78 | var subchunkSize = BitConverter.ToInt32(subchunkHeader, 4); 79 | var subchunk = new byte[subchunkSize]; 80 | wavStream.Read(subchunk, 0, subchunk.Length); 81 | 82 | var channels = BitConverter.ToInt16(subchunk, 2); 83 | var sampleRate = BitConverter.ToInt32(subchunk, 4); 84 | var byteRate = BitConverter.ToInt32(subchunk, 8); 85 | var bytesPerFullSample = BitConverter.ToInt16(subchunk, 12); 86 | var bitDepth = BitConverter.ToInt16(subchunk, 14); 87 | 88 | wavStream.Read(subchunkHeader, 0, subchunkHeader.Length); 89 | var length = BitConverter.ToInt32(subchunkHeader, 4); 90 | var sampleCount = length/bytesPerFullSample; 91 | var fileDuration = sampleCount/sampleRate; 92 | 93 | duration = TimeSpan.FromSeconds(fileDuration); 94 | 95 | audioFormat = new AudioFormat 96 | { 97 | BitDepth = bitDepth, 98 | Channels = channels, 99 | SampleRate = sampleRate 100 | }; 101 | 102 | return new WaveDecoder(bitDepth, channels); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /Aural/IO/OpenAL/PlaybackDevice.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using System.Collections.Generic; 28 | 29 | namespace FragLabs.Aural.IO.OpenAL 30 | { 31 | /// 32 | /// Static OpenAL playback device methods. 33 | /// 34 | internal class PlaybackDevice 35 | { 36 | private static readonly Dictionary OpenDevices = new Dictionary(); 37 | private static readonly Dictionary OpenContexts = new Dictionary(); 38 | private static readonly Dictionary> OpenTokens = new Dictionary>(); 39 | private static int _token; 40 | 41 | /// 42 | /// Gets a device, ensuring it's open if not already open. 43 | /// 44 | /// 45 | internal static IntPtr GetDevice(string deviceName) 46 | { 47 | lock (typeof (PlaybackDevice)) 48 | { 49 | if (!OpenDevices.ContainsKey(deviceName)) 50 | OpenDevices[deviceName] = API.alcOpenDevice(deviceName); 51 | return OpenDevices[deviceName]; 52 | } 53 | } 54 | 55 | /// 56 | /// Gets a context for a device, creating one if needed. 57 | /// 58 | /// 59 | internal static IntPtr GetContext(string deviceName) 60 | { 61 | var device = GetDevice(deviceName); 62 | lock (typeof(PlaybackDevice)) 63 | { 64 | if (!OpenContexts.ContainsKey(deviceName)) 65 | OpenContexts[deviceName] = API.alcCreateContext(device, IntPtr.Zero); 66 | return OpenContexts[deviceName]; 67 | } 68 | } 69 | 70 | internal static int GetToken(string deviceName) 71 | { 72 | lock (typeof (PlaybackDevice)) 73 | { 74 | if (_token == int.MaxValue) 75 | _token = 0; 76 | _token++; 77 | if (!OpenTokens.ContainsKey(deviceName)) 78 | OpenTokens.Add(deviceName, new List()); 79 | OpenTokens[deviceName].Add(_token); 80 | return _token; 81 | } 82 | } 83 | 84 | internal static void RetireToken(int token) 85 | { 86 | lock (typeof (PlaybackDevice)) 87 | { 88 | foreach (var kvp in OpenTokens) 89 | { 90 | if (kvp.Value.Contains(token)) 91 | { 92 | kvp.Value.Remove(token); 93 | if (kvp.Value.Count == 0) 94 | { 95 | var context = OpenContexts[kvp.Key]; 96 | var device = OpenDevices[kvp.Key]; 97 | OpenContexts.Remove(kvp.Key); 98 | OpenDevices.Remove(kvp.Key); 99 | API.alcDestroyContext(context); 100 | API.alcCloseDevice(device); 101 | } 102 | break; 103 | } 104 | } 105 | } 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /Aural/Processing/Filters/DecimationDownSampler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | 28 | namespace FragLabs.Aural.Processing.Filters 29 | { 30 | /// 31 | /// Integer decimation downsampler. 32 | /// 33 | public class DecimationDownSampler : IAudioFilter 34 | { 35 | private readonly int _downsampleFactor; 36 | 37 | public DecimationDownSampler(AudioFormat inputFormat, int downsampleFactor) 38 | { 39 | _downsampleFactor = downsampleFactor; 40 | InputAudioFormat = inputFormat; 41 | OutputAudioFormat = new AudioFormat 42 | { 43 | BitDepth = InputAudioFormat.BitDepth, 44 | Channels = InputAudioFormat.Channels, 45 | SampleRate = InputAudioFormat.SampleRate / downsampleFactor 46 | }; 47 | } 48 | 49 | /// 50 | /// Gets or sets the expected input audio format. 51 | /// 52 | public AudioFormat InputAudioFormat { get; private set; } 53 | 54 | /// 55 | /// Gets or sets the output audio format. 56 | /// 57 | public AudioFormat OutputAudioFormat { get; private set; } 58 | 59 | /// 60 | /// Gets a value indicating if the filter supports the byte typed API. 61 | /// 62 | public bool SupportsByte { get { return true; } } 63 | 64 | /// 65 | /// Gets a value indicating if the filter supports the double typed API. 66 | /// 67 | public bool SupportsDouble { get { return true; } } 68 | 69 | public int Process(byte[] inputPcmSamples, int inputOffset, byte[] outputPcmSamples, int outputOffset, int inputSampleCount) 70 | { 71 | var sampleSize = FormatHelper.SampleSize(InputAudioFormat.BitDepth, InputAudioFormat.Channels); 72 | var outputSampleCount = inputSampleCount/_downsampleFactor; 73 | for (var i = 0; i < outputSampleCount; i++) 74 | { 75 | var index = inputOffset + (sampleSize * i * _downsampleFactor); 76 | double downSampleSum = 0; 77 | for(var j = 0; j < _downsampleFactor; j++) 78 | { 79 | var sample = BitConverter.ToInt16(inputPcmSamples, index + (j*sampleSize)); 80 | downSampleSum += sample; 81 | } 82 | var downSampled = downSampleSum/_downsampleFactor; 83 | var pcmSample = BitConverter.GetBytes((short)downSampled); 84 | Buffer.BlockCopy(pcmSample, 0, outputPcmSamples, outputOffset + (i * sampleSize), sampleSize); 85 | } 86 | return outputSampleCount * sampleSize; 87 | } 88 | 89 | public int Process(double[] inputSamples, int inputOffset, double[] outputSamples, int outputOffset, int inputSampleCount) 90 | { 91 | var outputSampleCount = inputSampleCount/_downsampleFactor; 92 | for (var i = 0; i < outputSampleCount; i++) 93 | { 94 | var index = inputOffset + (i*_downsampleFactor); 95 | double downSampleSum = 0; 96 | for (var j = 0; j < _downsampleFactor; j++) 97 | downSampleSum += inputSamples[index + j]; 98 | outputSamples[outputOffset + i] = downSampleSum / _downsampleFactor; 99 | } 100 | return outputSampleCount; 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /Aural/IO/OpenAL/Runner.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System.Collections.Generic; 27 | using System.Threading; 28 | 29 | namespace FragLabs.Aural.IO.OpenAL 30 | { 31 | /// 32 | /// OpenAL runner. 33 | /// 34 | internal class Runner 35 | { 36 | /// 37 | /// List of OpenAL inputs to monitor. 38 | /// 39 | private static readonly List _inputs = new List(); 40 | 41 | /// 42 | /// Runner thread. 43 | /// 44 | private static Thread _runnerThread; 45 | 46 | /// 47 | /// Runner is running? 48 | /// 49 | private static bool _isRunning; 50 | 51 | /// 52 | /// Set to true to signal the runner thread to stop. 53 | /// 54 | private static bool _stopSignal; 55 | 56 | /// 57 | /// Adds an OpenAL input to the runner for reading. 58 | /// 59 | /// 60 | public static void Add(OpenALInput input) 61 | { 62 | lock (_inputs) 63 | { 64 | _inputs.Add(input); 65 | } 66 | EnsureThreadRunning(); 67 | } 68 | 69 | /// 70 | /// Removes an OpenAL input from the runner. 71 | /// 72 | /// 73 | public static void Remove(OpenALInput input, bool allowThreadShutdown = true) 74 | { 75 | lock (_inputs) 76 | { 77 | _inputs.Remove(input); 78 | if (allowThreadShutdown && _inputs.Count == 0) 79 | { 80 | StopThread(); 81 | } 82 | } 83 | } 84 | 85 | /// 86 | /// Ensures the runner thread is running. 87 | /// 88 | private static void EnsureThreadRunning() 89 | { 90 | lock (typeof (Runner)) 91 | { 92 | if (!_isRunning) 93 | { 94 | _runnerThread = new Thread(RunnerThread); 95 | _runnerThread.Start(); 96 | } 97 | } 98 | } 99 | 100 | /// 101 | /// Stops the runner thread if it's already running. 102 | /// 103 | private static void StopThread() 104 | { 105 | lock (typeof (Runner)) 106 | { 107 | if (_isRunning) 108 | { 109 | _stopSignal = true; 110 | } 111 | } 112 | } 113 | 114 | /// 115 | /// Runner thread. 116 | /// 117 | private static void RunnerThread() 118 | { 119 | _isRunning = true; 120 | while (!_stopSignal) 121 | { 122 | lock (_inputs) 123 | { 124 | foreach (var input in _inputs) 125 | { 126 | while(input.GetSamplesAvailable() >= input.ReadSampleCount) 127 | { 128 | var readBytes = input.Read(input.ReadBuffer, 0, input.ReadSampleCount); 129 | input.ReadComplete(readBytes); 130 | } 131 | } 132 | } 133 | Thread.Sleep(1); 134 | } 135 | _runnerThread = null; 136 | _isRunning = false; 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /Aural/Encoding/Opus/API.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using System.IO; 28 | using System.Reflection; 29 | using System.Runtime.InteropServices; 30 | 31 | namespace FragLabs.Aural.Encoding.Opus 32 | { 33 | /// 34 | /// Wraps the Opus API. 35 | /// 36 | internal class API 37 | { 38 | static API() 39 | { 40 | var image = IntPtr.Zero; 41 | if (PlatformDetails.IsMac) 42 | { 43 | image = LibraryLoader.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Libs", "32bit", "libopus.dylib")); 44 | } 45 | else if (PlatformDetails.IsWindows) 46 | { 47 | if (PlatformDetails.CpuArchitecture == CpuArchitecture.x86) 48 | { 49 | image = LibraryLoader.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Libs", "32bit", "opus.dll")); 50 | } 51 | else if (PlatformDetails.CpuArchitecture == CpuArchitecture.x64) 52 | { 53 | image = LibraryLoader.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Libs", "64bit", "opus.dll")); 54 | } 55 | } 56 | else 57 | { 58 | image = LibraryLoader.Load("libopus.so.0"); 59 | if (image.Equals(IntPtr.Zero)) 60 | { 61 | image = LibraryLoader.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Libs", "libopus.so")); 62 | } 63 | } 64 | 65 | if (image != IntPtr.Zero) 66 | { 67 | var type = typeof(API); 68 | foreach (var member in type.GetFields(BindingFlags.Static | BindingFlags.NonPublic)) 69 | { 70 | var methodName = member.Name; 71 | if (methodName == "opus_encoder_ctl_out") methodName = "opus_encoder_ctl"; 72 | var fieldType = member.FieldType; 73 | var ptr = LibraryLoader.ResolveSymbol(image, methodName); 74 | if (ptr == IntPtr.Zero) 75 | throw new Exception(string.Format("Could not resolve symbol \"{0}\"", methodName)); 76 | member.SetValue(null, Marshal.GetDelegateForFunctionPointer(ptr, fieldType)); 77 | } 78 | } 79 | } 80 | 81 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 82 | internal delegate IntPtr opus_encoder_create_delegate(int sampleRate, int channelCount, int application, out IntPtr error); 83 | internal static opus_encoder_create_delegate opus_encoder_create; 84 | 85 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 86 | internal delegate void opus_encoder_destroy_delegate(IntPtr encoder); 87 | internal static opus_encoder_destroy_delegate opus_encoder_destroy; 88 | 89 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 90 | internal delegate int opus_encode_delegate(IntPtr encoder, IntPtr pcm, int frameSize, IntPtr data, int maxDataBytes); 91 | internal static opus_encode_delegate opus_encode; 92 | 93 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 94 | internal delegate IntPtr opus_decoder_create_delegate(int sampleRate, int channelCount, out IntPtr error); 95 | internal static opus_decoder_create_delegate opus_decoder_create; 96 | 97 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 98 | internal delegate void opus_decoder_destroy_delegate(IntPtr decoder); 99 | internal static opus_decoder_destroy_delegate opus_decoder_destroy; 100 | 101 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 102 | internal delegate int opus_decode_delegate(IntPtr decoder, IntPtr data, int len, IntPtr pcm, int frameSize, int decodeFec); 103 | internal static opus_decode_delegate opus_decode; 104 | 105 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 106 | internal delegate int opus_encoder_ctl_delegate(IntPtr encoder, Ctl request, int value); 107 | internal static opus_encoder_ctl_delegate opus_encoder_ctl; 108 | 109 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 110 | internal delegate int opus_encoder_ctl_out_delegate(IntPtr encoder, Ctl request, out int value); 111 | internal static opus_encoder_ctl_out_delegate opus_encoder_ctl_out; 112 | } 113 | } -------------------------------------------------------------------------------- /Aural/Encoding/OpusDecoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using FragLabs.Aural.Encoding.Opus; 28 | 29 | namespace FragLabs.Aural.Encoding 30 | { 31 | /// 32 | /// Opus decoder. 33 | /// 34 | public class OpusDecoder : IFrameWindowDecoder 35 | { 36 | /// 37 | /// Opus decoder. 38 | /// 39 | private IntPtr _decoder; 40 | 41 | /// 42 | /// Size of a sample, in bytes. 43 | /// 44 | private readonly int _sampleSize; 45 | 46 | /// 47 | /// Gets or sets if Forward Error Correction decoding is enabled. 48 | /// 49 | public bool EnableForwardErrorCorrection { get; set; } 50 | 51 | public OpusDecoder(int outputSampleRate, int outputChannelCount) 52 | { 53 | if (outputSampleRate != 8000 && 54 | outputSampleRate != 12000 && 55 | outputSampleRate != 16000 && 56 | outputSampleRate != 24000 && 57 | outputSampleRate != 48000) 58 | throw new ArgumentOutOfRangeException("outputSampleRate"); 59 | if (outputChannelCount != 1 && outputChannelCount != 2) 60 | throw new ArgumentOutOfRangeException("outputChannelCount"); 61 | 62 | IntPtr error; 63 | _decoder = API.opus_decoder_create(outputSampleRate, outputChannelCount, out error); 64 | if ((Errors)error != Errors.OK) 65 | { 66 | throw new Exception(string.Format("Exception occured while creating decoder, {0}", ((Errors)error))); 67 | } 68 | _sampleSize = FormatHelper.SampleSize(16, outputChannelCount); 69 | } 70 | 71 | ~OpusDecoder() 72 | { 73 | Dispose(); 74 | } 75 | 76 | /// 77 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 78 | /// 79 | /// 2 80 | public void Dispose() 81 | { 82 | if (_decoder != IntPtr.Zero) 83 | { 84 | API.opus_decoder_destroy(_decoder); 85 | _decoder = IntPtr.Zero; 86 | } 87 | } 88 | 89 | /// 90 | /// Decodes audio samples. 91 | /// 92 | /// Encoded data. 93 | /// The zero-based byte offset in srcEncodedBuffer at which to begin reading encoded data. 94 | /// The number of bytes to read from srcEncodedBuffer. 95 | /// 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. 96 | /// The zero-based byte offset in dstBuffer at which to begin writing decoded audio samples. 97 | /// The number of bytes decoded and written to dstBuffer. 98 | /// Set srcEncodedBuffer to null to instruct the decoder that a packet was dropped. 99 | public unsafe int Decode(byte[] srcEncodedBuffer, int srcOffset, int srcLength, byte[] dstBuffer, int dstOffset) 100 | { 101 | var availableBytes = dstBuffer.Length - dstOffset; 102 | var frameCount = availableBytes / _sampleSize; 103 | int length; 104 | fixed (byte* bdec = dstBuffer) 105 | { 106 | var decodedPtr = IntPtr.Add(new IntPtr(bdec), dstOffset); 107 | if (srcEncodedBuffer != null) 108 | { 109 | fixed (byte* bsrc = srcEncodedBuffer) 110 | { 111 | var srcPtr = IntPtr.Add(new IntPtr(bsrc), srcOffset); 112 | length = API.opus_decode(_decoder, srcPtr, srcLength, decodedPtr, frameCount, 0); 113 | } 114 | } 115 | else 116 | { 117 | // todo: check that frameCount is a multiple of 2.5ms 118 | length = API.opus_decode(_decoder, IntPtr.Zero, 0, decodedPtr, frameCount, Convert.ToInt32(EnableForwardErrorCorrection)); 119 | } 120 | } 121 | if (length < 0) 122 | throw new Exception("Decoding failed - " + ((Errors)length).ToString()); 123 | return length * _sampleSize; 124 | } 125 | } 126 | } -------------------------------------------------------------------------------- /Aural/IO/RaspberryPi/API.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2014 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using System.IO; 28 | using System.Reflection; 29 | using System.Runtime.InteropServices; 30 | 31 | namespace FragLabs.Aural.IO.RaspberryPi 32 | { 33 | /// 34 | /// RaspberryPi audio API. 35 | /// 36 | internal class API 37 | { 38 | /// 39 | /// Gets a value indicating if RPi audio is supported on the current platform. 40 | /// 41 | public static bool IsSupported { get; private set; } 42 | 43 | static API() 44 | { 45 | IsSupported = false; 46 | if (PlatformDetails.IsMac || PlatformDetails.IsWindows) 47 | return; 48 | 49 | try 50 | { 51 | var image = LibraryLoader.Load("librpiaudio.so.1"); 52 | if (image.Equals(IntPtr.Zero)) 53 | { 54 | image = 55 | LibraryLoader.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Libs", "librpiaudio.so")); 56 | } 57 | 58 | if (image != IntPtr.Zero) 59 | { 60 | var type = typeof (API); 61 | foreach (var member in type.GetFields(BindingFlags.Static | BindingFlags.NonPublic)) 62 | { 63 | var methodName = member.Name; 64 | var fieldType = member.FieldType; 65 | if (fieldType == typeof (bool)) continue; 66 | var ptr = LibraryLoader.ResolveSymbol(image, methodName); 67 | if (ptr == IntPtr.Zero) 68 | throw new Exception(string.Format("Could not resolve symbol \"{0}\"", methodName)); 69 | member.SetValue(null, Marshal.GetDelegateForFunctionPointer(ptr, fieldType)); 70 | } 71 | IsSupported = true; 72 | } 73 | } 74 | catch (Exception ex) 75 | { 76 | // ignore - not a supported platform. 77 | Console.WriteLine(ex); 78 | } 79 | } 80 | 81 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 82 | internal delegate IntPtr createDeviceDelegate(uint samplerate, uint channelCount, uint bitDepth, uint buffercount, uint bufferSize); 83 | internal static createDeviceDelegate rpi_audio_create; 84 | 85 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 86 | internal delegate void destroyDeviceDelegate(IntPtr device); 87 | internal static destroyDeviceDelegate rpi_audio_destroy; 88 | 89 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 90 | internal delegate void setDestDelegate(IntPtr device, uint dest); 91 | internal static setDestDelegate rpi_audio_set_dest; 92 | 93 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 94 | internal delegate IntPtr getBufferDelegate(IntPtr device); 95 | internal static getBufferDelegate rpi_audio_get_buffer; 96 | 97 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 98 | internal delegate IntPtr playDelegate(IntPtr device); 99 | internal static playDelegate rpi_audio_play; 100 | 101 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 102 | internal delegate IntPtr pauseDelegate(IntPtr device); 103 | internal static pauseDelegate rpi_audio_pause; 104 | 105 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 106 | internal delegate IntPtr stopDelegate(IntPtr device); 107 | internal static stopDelegate rpi_audio_stop; 108 | 109 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 110 | internal delegate void queueBufferDelegate(IntPtr device, IntPtr buffer, int byteLength); 111 | internal static queueBufferDelegate rpi_audio_queue_buffer; 112 | 113 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 114 | internal delegate uint getStateDelegate(IntPtr device); 115 | internal static getStateDelegate rpi_audio_get_state; 116 | 117 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 118 | internal delegate uint getUnplayedSamplesDelegate(IntPtr device); 119 | internal static getUnplayedSamplesDelegate rpi_audio_unplayed_samples; 120 | } 121 | 122 | internal enum OutputDest 123 | { 124 | /// 125 | /// HDMI output. 126 | /// 127 | HDMI = 0, 128 | /// 129 | /// 3.5mm audio jack. 130 | /// 131 | AudioJack = 1 132 | } 133 | 134 | internal enum OmxState 135 | { 136 | Invalid = 0, 137 | Loaded = 1, 138 | Idle = 2, 139 | Executing = 3, 140 | Pause = 4, 141 | WaitForResources = 5 142 | } 143 | } -------------------------------------------------------------------------------- /Aural/Aural.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6283D87E-F9E8-41CE-931B-0981797D57F5} 8 | Library 9 | Properties 10 | FragLabs.Aural 11 | Aural 12 | v4.0 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | true 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | true 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | PreserveNewest 87 | 88 | 89 | PreserveNewest 90 | 91 | 92 | PreserveNewest 93 | 94 | 95 | PreserveNewest 96 | 97 | 98 | PreserveNewest 99 | 100 | 101 | PreserveNewest 102 | 103 | 104 | PreserveNewest 105 | 106 | 107 | PreserveNewest 108 | 109 | 110 | 111 | 112 | 113 | PreserveNewest 114 | 115 | 116 | PreserveNewest 117 | 118 | 119 | 120 | 121 | 128 | -------------------------------------------------------------------------------- /Aural/IO/RaspberryPiOutput.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2014 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using FragLabs.Aural.IO.RaspberryPi; 28 | 29 | namespace FragLabs.Aural.IO 30 | { 31 | /// 32 | /// 33 | /// 34 | public class RaspberryPiOutput : IAudioOutput 35 | { 36 | private readonly OutputDest _dest; 37 | /// 38 | /// size of each buffer in bytes 39 | /// 40 | private uint _bufferSize; 41 | 42 | private int _samplesPerBuffer; 43 | 44 | public static RaspberryPiOutput[] GetOutputDevices() 45 | { 46 | if (!API.IsSupported) 47 | return new RaspberryPiOutput[0]; 48 | return new [] 49 | { 50 | new RaspberryPiOutput(OutputDest.HDMI), 51 | new RaspberryPiOutput(OutputDest.AudioJack) 52 | }; 53 | } 54 | 55 | private IntPtr _device; 56 | 57 | internal RaspberryPiOutput(OutputDest dest) 58 | { 59 | _dest = dest; 60 | Name = (dest == OutputDest.HDMI) ? "HDMI" : "3.5mm Jack"; 61 | } 62 | 63 | public void Dispose() 64 | { 65 | if (IsOpen) 66 | Close(); 67 | } 68 | 69 | public bool IsPlaying 70 | { 71 | get 72 | { 73 | if (!IsOpen) 74 | return false; 75 | return (OmxState) API.rpi_audio_get_state(_device) == OmxState.Executing; 76 | } 77 | } 78 | 79 | public bool IsStopped 80 | { 81 | get 82 | { 83 | if (!IsOpen) 84 | return false; 85 | return (OmxState)API.rpi_audio_get_state(_device) == OmxState.Idle; 86 | } 87 | } 88 | 89 | public bool IsPaused 90 | { 91 | get 92 | { 93 | if (!IsOpen) 94 | return false; 95 | return (OmxState)API.rpi_audio_get_state(_device) == OmxState.Pause; 96 | } 97 | } 98 | 99 | /// 100 | /// Gets a value indicating if the audio output is open. 101 | /// 102 | public bool IsOpen 103 | { 104 | get 105 | { 106 | return _device != IntPtr.Zero; 107 | } 108 | } 109 | 110 | /// 111 | /// Gets the device name. 112 | /// 113 | public string Name { get; private set; } 114 | 115 | /// 116 | /// Gets the number of frames queued for playback. May not be precise. 117 | /// 118 | public int QueuedSampleCount 119 | { 120 | get 121 | { 122 | if (!IsOpen) 123 | throw new Exception("Must open device first."); 124 | return (int)API.rpi_audio_unplayed_samples(_device); 125 | } 126 | } 127 | 128 | /// 129 | /// Gets the audio format. 130 | /// 131 | public AudioFormat Format { get; private set; } 132 | 133 | public void Open(AudioFormat format) 134 | { 135 | if (IsOpen) 136 | Close(); 137 | _bufferSize = (uint)(FormatHelper.SampleSize(format.BitDepth, format.Channels) * format.SampleRate) / 10; 138 | _samplesPerBuffer = (int)_bufferSize/FormatHelper.SampleSize(format.BitDepth, format.Channels); 139 | Format = format; 140 | // create a device that can buffer 1s of audio in 10 discrete buffers. 141 | _device = API.rpi_audio_create((uint) format.SampleRate, (uint) format.Channels, (uint) format.BitDepth, 142 | 10, _bufferSize); 143 | if (_device == IntPtr.Zero) 144 | { 145 | throw new Exception("Failed to open device."); 146 | } 147 | var dest = (uint) _dest; 148 | API.rpi_audio_set_dest(_device, dest); 149 | } 150 | 151 | public void Close() 152 | { 153 | if (IsOpen) 154 | { 155 | API.rpi_audio_destroy(_device); 156 | _device = IntPtr.Zero; 157 | } 158 | } 159 | 160 | public void Play() 161 | { 162 | if (IsOpen) 163 | API.rpi_audio_play(_device); 164 | } 165 | 166 | public void Stop() 167 | { 168 | if (IsOpen) 169 | API.rpi_audio_stop(_device); 170 | } 171 | 172 | public void Pause() 173 | { 174 | if (IsOpen) 175 | API.rpi_audio_pause(_device); 176 | } 177 | 178 | public unsafe int Write(byte[] pcmBuffer, int offset, int sampleCount) 179 | { 180 | if (!IsOpen) 181 | throw new Exception("Must open device first."); 182 | if (!IsPaused || !IsPlaying) 183 | throw new Exception("Device must be in playing or paused state to write audio samples."); 184 | 185 | var written = 0; 186 | var sampleSize = FormatHelper.SampleSize(Format.BitDepth, Format.Channels); 187 | while (written < sampleCount) 188 | { 189 | var buffer = API.rpi_audio_get_buffer(_device); 190 | if (buffer == IntPtr.Zero) return written; 191 | 192 | var pointer = (byte*)buffer.ToPointer(); 193 | var samplesToWrite = sampleCount; 194 | if (samplesToWrite > _samplesPerBuffer) 195 | samplesToWrite = _samplesPerBuffer; 196 | 197 | for (var i = 0; i < samplesToWrite; i++) 198 | { 199 | for (var j = 0; j < sampleSize; j++) 200 | { 201 | pointer[(i * sampleSize) + j] = pcmBuffer[(i * sampleSize) + j + offset]; 202 | } 203 | } 204 | API.rpi_audio_queue_buffer(_device, buffer, samplesToWrite * sampleSize); 205 | 206 | written += samplesToWrite; 207 | } 208 | return written; 209 | } 210 | } 211 | 212 | 213 | } -------------------------------------------------------------------------------- /Aural/Processing/FFT.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FragLabs.Aural.Processing 4 | { 5 | /** 6 | * Performs an in-place complex FFT. 7 | * 8 | * Released under the MIT License 9 | * 10 | * Copyright (c) 2010 Gerald T. Beauregard 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to 14 | * deal in the Software without restriction, including without limitation the 15 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | * sell copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in 20 | * all copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 28 | * IN THE SOFTWARE. 29 | */ 30 | public class FFT 31 | { 32 | // Element for linked list in which we store the 33 | // input/output data. We use a linked list because 34 | // for sequential access it's faster than array index. 35 | class FFTElement 36 | { 37 | public double re = 0.0; // Real component 38 | public double im = 0.0; // Imaginary component 39 | public FFTElement next; // Next element in linked list 40 | public uint revTgt; // Target position post bit-reversal 41 | } 42 | 43 | private uint m_logN = 0; // log2 of FFT size 44 | private uint m_N = 0; // FFT size 45 | private FFTElement[] m_X; // Vector of linked list elements 46 | 47 | /** 48 | * 49 | */ 50 | public FFT() 51 | { 52 | } 53 | 54 | /** 55 | * Initialize class to perform FFT of specified size. 56 | * 57 | * @param logN Log2 of FFT length. e.g. for 512 pt FFT, logN = 9. 58 | */ 59 | public void init( 60 | uint logN) 61 | { 62 | m_logN = logN; 63 | m_N = (uint)(1 << (int)m_logN); 64 | 65 | // Allocate elements for linked list of complex numbers. 66 | m_X = new FFTElement[m_N]; 67 | for (uint k = 0; k < m_N; k++) 68 | m_X[k] = new FFTElement(); 69 | 70 | // Set up "next" pointers. 71 | for (uint k = 0; k < m_N - 1; k++) 72 | m_X[k].next = m_X[k + 1]; 73 | 74 | // Specify target for bit reversal re-ordering. 75 | for (uint k = 0; k < m_N; k++) 76 | m_X[k].revTgt = BitReverse(k, logN); 77 | } 78 | 79 | /** 80 | * Performs in-place complex FFT. 81 | * 82 | * @param xRe Real part of input/output 83 | * @param xIm Imaginary part of input/output 84 | * @param inverse If true, do an inverse FFT 85 | */ 86 | public void run( 87 | double[] xRe, 88 | double[] xIm, 89 | bool inverse = false) 90 | { 91 | uint numFlies = m_N >> 1; // Number of butterflies per sub-FFT 92 | uint span = m_N >> 1; // Width of the butterfly 93 | uint spacing = m_N; // Distance between start of sub-FFTs 94 | uint wIndexStep = 1; // Increment for twiddle table index 95 | 96 | // Copy data into linked complex number objects 97 | // If it's an IFFT, we divide by N while we're at it 98 | FFTElement x = m_X[0]; 99 | uint k = 0; 100 | double scale = inverse ? 1.0 / m_N : 1.0; 101 | while (x != null) 102 | { 103 | x.re = scale * xRe[k]; 104 | x.im = scale * xIm[k]; 105 | x = x.next; 106 | k++; 107 | } 108 | 109 | // For each stage of the FFT 110 | for (uint stage = 0; stage < m_logN; stage++) 111 | { 112 | // Compute a multiplier factor for the "twiddle factors". 113 | // The twiddle factors are complex unit vectors spaced at 114 | // regular angular intervals. The angle by which the twiddle 115 | // factor advances depends on the FFT stage. In many FFT 116 | // implementations the twiddle factors are cached, but because 117 | // array lookup is relatively slow in C#, it's just 118 | // as fast to compute them on the fly. 119 | double wAngleInc = wIndexStep * 2.0 * Math.PI / m_N; 120 | if (inverse == false) 121 | wAngleInc *= -1; 122 | double wMulRe = Math.Cos(wAngleInc); 123 | double wMulIm = Math.Sin(wAngleInc); 124 | 125 | for (uint start = 0; start < m_N; start += spacing) 126 | { 127 | FFTElement xTop = m_X[start]; 128 | FFTElement xBot = m_X[start + span]; 129 | 130 | double wRe = 1.0; 131 | double wIm = 0.0; 132 | 133 | // For each butterfly in this stage 134 | for (uint flyCount = 0; flyCount < numFlies; ++flyCount) 135 | { 136 | // Get the top & bottom values 137 | double xTopRe = xTop.re; 138 | double xTopIm = xTop.im; 139 | double xBotRe = xBot.re; 140 | double xBotIm = xBot.im; 141 | 142 | // Top branch of butterfly has addition 143 | xTop.re = xTopRe + xBotRe; 144 | xTop.im = xTopIm + xBotIm; 145 | 146 | // Bottom branch of butterly has subtraction, 147 | // followed by multiplication by twiddle factor 148 | xBotRe = xTopRe - xBotRe; 149 | xBotIm = xTopIm - xBotIm; 150 | xBot.re = xBotRe * wRe - xBotIm * wIm; 151 | xBot.im = xBotRe * wIm + xBotIm * wRe; 152 | 153 | // Advance butterfly to next top & bottom positions 154 | xTop = xTop.next; 155 | xBot = xBot.next; 156 | 157 | // Update the twiddle factor, via complex multiply 158 | // by unit vector with the appropriate angle 159 | // (wRe + j wIm) = (wRe + j wIm) x (wMulRe + j wMulIm) 160 | double tRe = wRe; 161 | wRe = wRe * wMulRe - wIm * wMulIm; 162 | wIm = tRe * wMulIm + wIm * wMulRe; 163 | } 164 | } 165 | 166 | numFlies >>= 1; // Divide by 2 by right shift 167 | span >>= 1; 168 | spacing >>= 1; 169 | wIndexStep <<= 1; // Multiply by 2 by left shift 170 | } 171 | 172 | // The algorithm leaves the result in a scrambled order. 173 | // Unscramble while copying values from the complex 174 | // linked list elements back to the input/output vectors. 175 | x = m_X[0]; 176 | while (x != null) 177 | { 178 | uint target = x.revTgt; 179 | xRe[target] = x.re; 180 | xIm[target] = x.im; 181 | x = x.next; 182 | } 183 | } 184 | 185 | /** 186 | * Do bit reversal of specified number of places of an int 187 | * For example, 1101 bit-reversed is 1011 188 | * 189 | * @param x Number to be bit-reverse. 190 | * @param numBits Number of bits in the number. 191 | */ 192 | private uint BitReverse( 193 | uint x, 194 | uint numBits) 195 | { 196 | uint y = 0; 197 | for (uint i = 0; i < numBits; i++) 198 | { 199 | y <<= 1; 200 | y |= x & 0x0001; 201 | x >>= 1; 202 | } 203 | return y; 204 | } 205 | } 206 | } -------------------------------------------------------------------------------- /Aural/Encoding/OpusEncoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using System.Linq; 28 | using FragLabs.Aural.Encoding.Opus; 29 | 30 | namespace FragLabs.Aural.Encoding 31 | { 32 | /// 33 | /// Opus encoder. 34 | /// 35 | public class OpusEncoder : IFrameWindowEncoder 36 | { 37 | /// 38 | /// Opus encoder. 39 | /// 40 | private IntPtr _encoder; 41 | 42 | /// 43 | /// Size of each sample in bytes. 44 | /// 45 | private readonly int _sampleSize; 46 | 47 | /// 48 | /// Permitted frame sizes in ms. 49 | /// 50 | private readonly float[] _permittedFrameSizes = new[] 51 | { 52 | 2.5f, 5, 10, 53 | 20, 40, 60 54 | }; 55 | 56 | /// 57 | /// Creates a new Opus encoder. 58 | /// 59 | /// The sampling rate of the input stream. 60 | /// The number of channels in the input stream. 61 | /// Opus coding mode. 62 | public OpusEncoder(int srcSamplingRate, int srcChannelCount, Application application) 63 | { 64 | if (srcSamplingRate != 8000 && 65 | srcSamplingRate != 12000 && 66 | srcSamplingRate != 16000 && 67 | srcSamplingRate != 24000 && 68 | srcSamplingRate != 48000) 69 | throw new ArgumentOutOfRangeException("srcSamplingRate"); 70 | if (srcChannelCount != 1 && srcChannelCount != 2) 71 | throw new ArgumentOutOfRangeException("srcChannelCount"); 72 | 73 | IntPtr error; 74 | var encoder = API.opus_encoder_create(srcSamplingRate, srcChannelCount, (int)application, out error); 75 | if ((Errors)error != Errors.OK) 76 | { 77 | throw new Exception("Exception occured while creating encoder"); 78 | } 79 | _encoder = encoder; 80 | SourceSamplingRate = srcSamplingRate; 81 | SourceChannelCount = srcChannelCount; 82 | Application = application; 83 | 84 | const int bitdepth = 16; 85 | _sampleSize = FormatHelper.SampleSize(bitdepth, srcChannelCount); 86 | 87 | PermittedFrameSizes = new int[_permittedFrameSizes.Length]; 88 | for (var i = 0; i < _permittedFrameSizes.Length; i++) 89 | { 90 | PermittedFrameSizes[i] = Convert.ToInt32(srcSamplingRate/1000*_permittedFrameSizes[i]); 91 | } 92 | DefaultFrameSize = PermittedFrameSizes[2]; // default to 20ms encoding frames 93 | } 94 | 95 | ~OpusEncoder() 96 | { 97 | Dispose(); 98 | } 99 | 100 | /// 101 | /// Encode audio samples. 102 | /// 103 | /// PCM samples to be encoded. 104 | /// The zero-based byte offset in srcPcmSamples at which to begin reading PCM samples. 105 | /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values starting at offset replaced with encoded audio data. 106 | /// The zero-based byte offset in dstOutputBuffer at which to begin writing encoded audio. 107 | /// The number of samples, per channel, to encode. 108 | /// The total number of bytes written to dstOutputBuffer. 109 | public unsafe int Encode(byte[] srcPcmSamples, int srcOffset, byte[] dstOutputBuffer, int dstOffset, int sampleCount) 110 | { 111 | if (srcPcmSamples == null) throw new ArgumentNullException("srcPcmSamples"); 112 | if (dstOutputBuffer == null) throw new ArgumentNullException("dstOutputBuffer"); 113 | if (!PermittedFrameSizes.Contains(sampleCount)) 114 | throw new Exception("Frame size is not permitted"); 115 | var readSize = _sampleSize*sampleCount; 116 | if (srcOffset + readSize > srcPcmSamples.Length) 117 | throw new Exception("Not enough samples in source"); 118 | var maxSizeBytes = dstOutputBuffer.Length - dstOffset; 119 | int encodedLen; 120 | fixed (byte* benc = dstOutputBuffer) 121 | { 122 | fixed (byte* bsrc = srcPcmSamples) 123 | { 124 | var encodedPtr = IntPtr.Add(new IntPtr(benc), dstOffset); 125 | var pcmPtr = IntPtr.Add(new IntPtr(bsrc), srcOffset); 126 | encodedLen = API.opus_encode(_encoder, pcmPtr, sampleCount, encodedPtr, maxSizeBytes); 127 | } 128 | } 129 | if (encodedLen < 0) 130 | throw new Exception("Encoding failed - " + ((Errors)encodedLen).ToString()); 131 | return encodedLen; 132 | } 133 | 134 | /// 135 | /// Calculates the size of a frame in bytes. 136 | /// 137 | /// Size of the frame in samples per channel. 138 | /// The size of a frame in bytes. 139 | public int FrameSizeInBytes(int frameSizeInSamples) 140 | { 141 | return frameSizeInSamples*_sampleSize; 142 | } 143 | 144 | /// 145 | /// Permitted frame sizes in samples per channel. 146 | /// 147 | public int[] PermittedFrameSizes { get; private set; } 148 | 149 | /// 150 | /// Gets the default frame size in samples per channel. 151 | /// 152 | public int DefaultFrameSize { get; private set; } 153 | 154 | /// 155 | /// Gets or sets the bitrate setting of the encoding. 156 | /// 157 | public int Bitrate 158 | { 159 | get 160 | { 161 | if (_encoder == IntPtr.Zero) 162 | throw new ObjectDisposedException("OpusEncoder"); 163 | int bitrate; 164 | var ret = API.opus_encoder_ctl_out(_encoder, Ctl.GetBitrateRequest, out bitrate); 165 | if (ret < 0) 166 | throw new Exception("Encoder error - " + ((Errors)ret).ToString()); 167 | return bitrate; 168 | } 169 | set 170 | { 171 | if (_encoder == IntPtr.Zero) 172 | throw new ObjectDisposedException("OpusEncoder"); 173 | var ret = API.opus_encoder_ctl(_encoder, Ctl.SetBitrateRequest, value); 174 | if (ret < 0) 175 | throw new Exception("Encoder error - " + ((Errors)ret).ToString()); 176 | } 177 | } 178 | 179 | /// 180 | /// Gets or sets if Forward Error Correction encoding is enabled. 181 | /// 182 | public bool EnableForwardErrorCorrection 183 | { 184 | get 185 | { 186 | if (_encoder == IntPtr.Zero) 187 | throw new ObjectDisposedException("OpusEncoder"); 188 | int fec; 189 | var ret = API.opus_encoder_ctl_out(_encoder, Ctl.GetInbandFECRequest, out fec); 190 | if (ret < 0) 191 | throw new Exception("Encoder error - " + ((Errors)ret).ToString()); 192 | return fec > 0; 193 | } 194 | set 195 | { 196 | if (_encoder == IntPtr.Zero) 197 | throw new ObjectDisposedException("OpusEncoder"); 198 | var ret = API.opus_encoder_ctl(_encoder, Ctl.SetInbandFECRequest, Convert.ToInt32(value)); 199 | if (ret < 0) 200 | throw new Exception("Encoder error - " + ((Errors)ret).ToString()); 201 | } 202 | } 203 | 204 | /// 205 | /// Gets the sampling rate of the source stream. 206 | /// 207 | public int SourceSamplingRate { get; private set; } 208 | 209 | /// 210 | /// Gets the number of channels in the source stream. 211 | /// 212 | public int SourceChannelCount { get; private set; } 213 | 214 | /// 215 | /// Gets the coding mode of the encoder. 216 | /// 217 | public Application Application { get; private set; } 218 | 219 | /// 220 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 221 | /// 222 | /// 2 223 | public void Dispose() 224 | { 225 | if (_encoder != IntPtr.Zero) 226 | { 227 | API.opus_encoder_destroy(_encoder); 228 | _encoder = IntPtr.Zero; 229 | } 230 | } 231 | } 232 | } -------------------------------------------------------------------------------- /Aural/IO/OpenALInput.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Runtime.InteropServices; 29 | using System.Threading; 30 | using FragLabs.Aural.IO.OpenAL; 31 | using ALAudioFormat = FragLabs.Aural.IO.OpenAL.AudioFormat; 32 | 33 | namespace FragLabs.Aural.IO 34 | { 35 | /// 36 | /// OpenAL audio input. 37 | /// 38 | public class OpenALInput : IAudioInput 39 | { 40 | /// 41 | /// Gets the available input device names. 42 | /// 43 | /// 44 | public static string[] GetInputDevices() 45 | { 46 | return ReadStringsFromMemory(API.alcGetString(IntPtr.Zero, (int)ALCStrings.ALC_CAPTURE_DEVICE_SPECIFIER)); 47 | } 48 | 49 | internal static string[] ReadStringsFromMemory(IntPtr location) 50 | { 51 | if (location == IntPtr.Zero) 52 | return new string[0]; 53 | 54 | var strings = new List(); 55 | 56 | var lastNull = false; 57 | var i = -1; 58 | byte c; 59 | while (!((c = Marshal.ReadByte(location, ++i)) == '\0' && lastNull)) 60 | { 61 | if (c == '\0') 62 | { 63 | lastNull = true; 64 | 65 | strings.Add(Marshal.PtrToStringAnsi(location, i)); 66 | location = new IntPtr((long)location + i + 1); 67 | i = -1; 68 | } 69 | else 70 | lastNull = false; 71 | } 72 | 73 | return strings.ToArray(); 74 | } 75 | 76 | /// 77 | /// OpenAL device. 78 | /// 79 | private IntPtr _device; 80 | 81 | /// 82 | /// Size of each sample in bytes. 83 | /// 84 | private readonly int _sampleSize; 85 | 86 | /// 87 | /// Number of samples to read from StartReading. 88 | /// 89 | internal int ReadSampleCount; 90 | 91 | /// 92 | /// Buffer to write to from StartReading. 93 | /// 94 | internal byte[] ReadBuffer; 95 | 96 | /// 97 | /// Opens a device for input. 98 | /// 99 | /// Name of input device to open. 100 | /// Audio recording format. 101 | /// Size of internal sample buffer in bytes. 102 | public OpenALInput(string deviceName, AudioFormat recordFormat, int internalBufferSize) 103 | { 104 | if (deviceName == null) throw new ArgumentNullException("deviceName"); 105 | if (recordFormat == null) throw new ArgumentNullException("recordFormat"); 106 | if (recordFormat.BitDepth != 8 && recordFormat.BitDepth != 16) throw new ArgumentOutOfRangeException("recordFormat", "Only 8 or 16 bitdepths are supported."); 107 | if (recordFormat.Channels != 1 && recordFormat.Channels != 2) throw new ArgumentOutOfRangeException("recordFormat", "Only 1 or 2 channels are supported."); 108 | 109 | Name = deviceName; 110 | Format = new AudioFormat 111 | { 112 | BitDepth = recordFormat.BitDepth, 113 | Channels = recordFormat.Channels, 114 | SampleRate = recordFormat.SampleRate 115 | }; 116 | 117 | var format = ALAudioFormat.Unknown; 118 | if (recordFormat.BitDepth == 8 && recordFormat.Channels == 1) 119 | format = ALAudioFormat.Mono8Bit; 120 | if (recordFormat.BitDepth == 8 && recordFormat.Channels == 2) 121 | format = ALAudioFormat.Stereo8Bit; 122 | if (recordFormat.BitDepth == 16 && recordFormat.Channels == 1) 123 | format = ALAudioFormat.Mono16Bit; 124 | if (recordFormat.BitDepth == 16 && recordFormat.Channels == 2) 125 | format = ALAudioFormat.Stereo16Bit; 126 | 127 | _sampleSize = FormatHelper.SampleSize(recordFormat.BitDepth, recordFormat.Channels); 128 | _device = API.alcCaptureOpenDevice(deviceName, (uint)recordFormat.SampleRate, format, internalBufferSize); 129 | API.alcCaptureStart(_device); 130 | } 131 | 132 | ~OpenALInput() 133 | { 134 | Dispose(); 135 | } 136 | 137 | /// 138 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 139 | /// 140 | /// 2 141 | public void Dispose() 142 | { 143 | StopReading(); 144 | if (_device != IntPtr.Zero) 145 | { 146 | API.alcCaptureStop(_device); 147 | API.alcCaptureCloseDevice(_device); 148 | _device = IntPtr.Zero; 149 | } 150 | } 151 | 152 | /// 153 | /// Event raised when audio data is received. 154 | /// 155 | public event EventHandler AudioReceived; 156 | 157 | protected virtual void OnAudioReceived(AudioReceivedEventArgs e) 158 | { 159 | var handler = AudioReceived; 160 | if (handler != null) handler(this, e); 161 | } 162 | 163 | /// 164 | /// Gets the name of the audio input. 165 | /// 166 | public string Name { get; private set; } 167 | 168 | /// 169 | /// Gets if the audio input is currently being read. 170 | /// 171 | public bool IsReading { get; private set; } 172 | 173 | /// 174 | /// Gets the audio format of input. 175 | /// 176 | public AudioFormat Format { get; private set; } 177 | 178 | /// 179 | /// Starts reading audio samples from the audio input. Will raise AudioReceived when audio samples are read from the input. 180 | /// 181 | /// The number of samples, per channel, to read before raising the AudioReceived event. 182 | /// sampleCount should be small enough to allow any processing of audio samples without overrunning the internal buffer. 183 | public void StartReading(int sampleCount) 184 | { 185 | ReadSampleCount = sampleCount; 186 | var bufferSize = sampleCount*_sampleSize; 187 | ReadBuffer = new byte[bufferSize]; 188 | IsReading = true; 189 | Runner.Add(this); 190 | } 191 | 192 | /// 193 | /// Stops reading audio samples from the audio input. 194 | /// 195 | public void StopReading() 196 | { 197 | if (IsReading) 198 | { 199 | Runner.Remove(this); 200 | IsReading = false; 201 | } 202 | } 203 | 204 | /// 205 | /// Internal read complete call from Runner. 206 | /// 207 | internal void ReadComplete(int byteCount) 208 | { 209 | OnAudioReceived(new AudioReceivedEventArgs 210 | { 211 | Buffer = ReadBuffer, 212 | ByteCount = byteCount, 213 | SampleCount = byteCount/_sampleSize 214 | }); 215 | } 216 | 217 | /// 218 | /// Reads audio samples from the input device into a buffer. 219 | /// 220 | /// 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. 221 | /// The zero-based byte offset in buffer at which to begin writing audio samples. 222 | /// The number of samples, per channel, to read. 223 | /// The total number of bytes written to buffer. 224 | public int Read(byte[] buffer, int offset, int sampleCount) 225 | { 226 | if (buffer == null) throw new ArgumentNullException("buffer"); 227 | var sampleLength = _sampleSize*sampleCount; 228 | if (offset + sampleLength > buffer.Length) 229 | throw new Exception("Not enough space in buffer for requested samples"); 230 | var samplesAvailable = GetSamplesAvailable(); 231 | while (samplesAvailable < sampleCount) 232 | { 233 | Thread.Sleep(1); 234 | samplesAvailable = GetSamplesAvailable(); 235 | } 236 | ReadIntoBuffer(buffer, offset, sampleCount); 237 | return sampleLength; 238 | } 239 | 240 | /// 241 | /// Gets the number of samples available for reading immediately. 242 | /// 243 | /// 244 | public int GetSamplesAvailable() 245 | { 246 | if (_device == IntPtr.Zero) 247 | return 0; 248 | 249 | int samples; 250 | API.alcGetIntegerv(_device, ALCEnum.ALC_CAPTURE_SAMPLES, 4, out samples); 251 | // todo: error checking 252 | return samples; 253 | } 254 | 255 | /// 256 | /// Copy samples into a buffer. 257 | /// 258 | /// Buffer to copy samples into. 259 | /// The zero-based byte offset in buffer at which to begin writing audio samples. 260 | /// Number of samples to copy. 261 | unsafe void ReadIntoBuffer(byte[] buffer, int offset, int samples) 262 | { 263 | fixed (byte* bbuff = buffer) 264 | { 265 | var buffPtr = IntPtr.Add(new IntPtr(bbuff), offset); 266 | API.alcCaptureSamples(_device, buffPtr, samples); 267 | } 268 | } 269 | } 270 | } -------------------------------------------------------------------------------- /Aural/IO/OpenAL/API.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using System.IO; 28 | using System.Reflection; 29 | using System.Runtime.InteropServices; 30 | 31 | namespace FragLabs.Aural.IO.OpenAL 32 | { 33 | internal class API 34 | { 35 | static API() 36 | { 37 | var image = IntPtr.Zero; 38 | if (PlatformDetails.IsMac) 39 | { 40 | image = LibraryLoader.Load("/System/Library/Frameworks/OpenAL.framework/OpenAL"); 41 | } 42 | else if (PlatformDetails.IsWindows) 43 | { 44 | if (PlatformDetails.CpuArchitecture == CpuArchitecture.x86) 45 | { 46 | image = LibraryLoader.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Libs", "32bit", "openal.dll")); 47 | } 48 | else if (PlatformDetails.CpuArchitecture == CpuArchitecture.x64) 49 | { 50 | image = LibraryLoader.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Libs", "64bit", "openal.dll")); 51 | } 52 | } 53 | else 54 | { 55 | image = LibraryLoader.Load("libopenal.so.1"); 56 | if (image.Equals(IntPtr.Zero)) 57 | { 58 | image = LibraryLoader.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Libs", "libopenal.so")); 59 | } 60 | } 61 | 62 | if (image != IntPtr.Zero) 63 | { 64 | var type = typeof (API); 65 | foreach (var member in type.GetFields(BindingFlags.Static|BindingFlags.NonPublic)) 66 | { 67 | var methodName = member.Name; 68 | var fieldType = member.FieldType; 69 | var ptr = LibraryLoader.ResolveSymbol(image, methodName); 70 | if (ptr == IntPtr.Zero) 71 | throw new Exception(string.Format("Could not resolve symbol \"{0}\"", methodName)); 72 | member.SetValue(null, Marshal.GetDelegateForFunctionPointer(ptr, fieldType)); 73 | } 74 | } 75 | } 76 | 77 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 78 | internal delegate IntPtr alGetStringDelegate(int name); 79 | internal static alGetStringDelegate alGetString; 80 | 81 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 82 | internal delegate IntPtr alcGetStringDelegate([In] IntPtr device, int name); 83 | internal static alcGetStringDelegate alcGetString; 84 | 85 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 86 | internal delegate sbyte alcIsExtensionPresentDelegate([In] IntPtr device, string extensionName); 87 | internal static alcIsExtensionPresentDelegate alcIsExtensionPresent; 88 | 89 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 90 | internal delegate sbyte alIsExtensionPresentDelegate(string extensionName); 91 | internal static alIsExtensionPresentDelegate alIsExtensionPresent; 92 | 93 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 94 | internal delegate void alcCaptureStartDelegate(IntPtr device); 95 | internal static alcCaptureStartDelegate alcCaptureStart; 96 | 97 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 98 | internal delegate void alcCaptureStopDelegate(IntPtr device); 99 | internal static alcCaptureStopDelegate alcCaptureStop; 100 | 101 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 102 | internal delegate void alcCaptureSamplesDelegate(IntPtr device, IntPtr buffer, int numSamples); 103 | internal static alcCaptureSamplesDelegate alcCaptureSamples; 104 | 105 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 106 | internal delegate IntPtr alcCaptureOpenDeviceDelegate(string deviceName, uint frequency, AudioFormat format, int bufferSize); 107 | internal static alcCaptureOpenDeviceDelegate alcCaptureOpenDevice; 108 | 109 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 110 | internal delegate void alcCaptureCloseDeviceDelegate(IntPtr device); 111 | internal static alcCaptureCloseDeviceDelegate alcCaptureCloseDevice; 112 | 113 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 114 | internal delegate void alcGetIntegervDelegate(IntPtr device, ALCEnum param, int size, out int data); 115 | internal static alcGetIntegervDelegate alcGetIntegerv; 116 | 117 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 118 | internal delegate IntPtr alcOpenDeviceDelegate(string deviceName); 119 | internal static alcOpenDeviceDelegate alcOpenDevice; 120 | 121 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 122 | internal delegate IntPtr alcCloseDeviceDelegate(IntPtr handle); 123 | internal static alcCloseDeviceDelegate alcCloseDevice; 124 | 125 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 126 | internal delegate IntPtr alcCreateContextDelegate(IntPtr device, IntPtr attrlist); 127 | internal static alcCreateContextDelegate alcCreateContext; 128 | 129 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 130 | internal delegate void alcMakeContextCurrentDelegate(IntPtr context); 131 | internal static alcMakeContextCurrentDelegate alcMakeContextCurrent; 132 | 133 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 134 | internal delegate IntPtr alcGetContextsDeviceDelegate(IntPtr context); 135 | internal static alcGetContextsDeviceDelegate alcGetContextsDevice; 136 | 137 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 138 | internal delegate IntPtr alcGetCurrentContextDelegate(); 139 | internal static alcGetCurrentContextDelegate alcGetCurrentContext; 140 | 141 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 142 | internal delegate void alcDestroyContextDelegate(IntPtr context); 143 | internal static alcDestroyContextDelegate alcDestroyContext; 144 | 145 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 146 | internal delegate void alGetSourceiDelegate(uint sourceID, IntSourceProperty property, out int value); 147 | internal static alGetSourceiDelegate alGetSourcei; 148 | 149 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 150 | internal delegate void alSourcePlayDelegate(uint sourceID); 151 | internal static alSourcePlayDelegate alSourcePlay; 152 | 153 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 154 | internal delegate void alSourcePauseDelegate(uint sourceID); 155 | internal static alSourcePauseDelegate alSourcePause; 156 | 157 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 158 | internal delegate void alSourceStopDelegate(uint sourceID); 159 | internal static alSourceStopDelegate alSourceStop; 160 | 161 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 162 | internal delegate void alSourceQueueBuffersDelegate(uint sourceID, int number, uint[] bufferIDs); 163 | internal static alSourceQueueBuffersDelegate alSourceQueueBuffers; 164 | 165 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 166 | internal delegate void alSourceUnqueueBuffersDelegate(uint sourceID, int buffers, uint[] buffersDequeued); 167 | internal static alSourceUnqueueBuffersDelegate alSourceUnqueueBuffers; 168 | 169 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 170 | internal delegate void alGenSourcesDelegate(int count, uint[] sources); 171 | internal static alGenSourcesDelegate alGenSources; 172 | 173 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 174 | internal delegate void alDeleteSourcesDelegate(int count, uint[] sources); 175 | internal static alDeleteSourcesDelegate alDeleteSources; 176 | 177 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 178 | internal delegate void alGetSourcefDelegate(uint sourceID, FloatSourceProperty property, out float value); 179 | internal static alGetSourcefDelegate alGetSourcef; 180 | 181 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 182 | internal delegate void alGetSource3fDelegate(uint sourceID, FloatSourceProperty property, out float val1, out float val2, out float val3); 183 | internal static alGetSource3fDelegate alGetSource3f; 184 | 185 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 186 | internal delegate void alSourcefDelegate(uint sourceID, FloatSourceProperty property, float value); 187 | internal static alSourcefDelegate alSourcef; 188 | 189 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 190 | internal delegate void alSource3fDelegate(uint sourceID, FloatSourceProperty property, float val1, float val2, float val3); 191 | internal static alSource3fDelegate alSource3f; 192 | 193 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 194 | internal delegate void alGetBufferiDelegate(uint bufferID, ALEnum property, out int value); 195 | internal static alGetBufferiDelegate alGetBufferi; 196 | 197 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 198 | internal delegate void alGenBuffersDelegate(int count, uint[] bufferIDs); 199 | internal static alGenBuffersDelegate alGenBuffers; 200 | 201 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 202 | internal delegate void alBufferDataDelegate(uint bufferID, AudioFormat format, IntPtr data, int byteSize, uint frequency); 203 | internal static alBufferDataDelegate alBufferData; 204 | 205 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 206 | internal delegate void alDeleteBuffersDelegate(int numBuffers, uint[] bufferIDs); 207 | internal static alDeleteBuffersDelegate alDeleteBuffers; 208 | 209 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 210 | internal delegate void alListenerfDelegate(FloatSourceProperty param, float val); 211 | internal static alListenerfDelegate alListenerf; 212 | 213 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 214 | internal delegate void alListenerfvDelegate(FloatSourceProperty param, float[] val); 215 | internal static alListenerfvDelegate alListenerfv; 216 | 217 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 218 | internal delegate void alListener3fDelegate(FloatSourceProperty param, float val1, float val2, float val3); 219 | internal static alListener3fDelegate alListener3f; 220 | 221 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 222 | internal delegate void alGetListener3fDelegate(FloatSourceProperty param, out float val1, out float val2, out float val3); 223 | internal static alGetListener3fDelegate alGetListener3f; 224 | 225 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 226 | internal delegate void alGetListenerfDelegate(FloatSourceProperty param, out float val); 227 | internal static alGetListenerfDelegate alGetListenerf; 228 | 229 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 230 | internal delegate void alGetListenerfvDelegate(FloatSourceProperty param, float[] val); 231 | internal static alGetListenerfvDelegate alGetListenerfv; 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /Aural/IO/OpenALOutput.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Author: John Carruthers (johnc@frag-labs.com) 3 | // 4 | // Copyright (C) 2013 John Carruthers 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Runtime.InteropServices; 29 | using FragLabs.Aural.IO.OpenAL; 30 | using ALAudioFormat = FragLabs.Aural.IO.OpenAL.AudioFormat; 31 | 32 | namespace FragLabs.Aural.IO 33 | { 34 | /// 35 | /// OpenAL audio output. 36 | /// 37 | public class OpenALOutput : IAudioOutput 38 | { 39 | public static OpenALOutput[] GetOutputDevices() 40 | { 41 | var strings = new string[0]; 42 | if (GetIsExtensionPresent("ALC_ENUMERATE_ALL_EXT")) 43 | { 44 | strings = 45 | ReadStringsFromMemory(API.alcGetString(IntPtr.Zero, 46 | (int)ALCStrings.ALC_ALL_DEVICES_SPECIFIER)); 47 | } 48 | else if (GetIsExtensionPresent("ALC_ENUMERATION_EXT")) 49 | { 50 | strings = 51 | ReadStringsFromMemory(API.alcGetString(IntPtr.Zero, (int)ALCStrings.ALC_DEVICE_SPECIFIER)); 52 | } 53 | var ret = new OpenALOutput[strings.Length]; 54 | for (var i = 0; i < strings.Length; i++) 55 | { 56 | ret[i] = new OpenALOutput(strings[i]); 57 | } 58 | return ret; 59 | } 60 | 61 | private static string[] ReadStringsFromMemory(IntPtr location) 62 | { 63 | if (location == IntPtr.Zero) 64 | return new string[0]; 65 | 66 | var strings = new List(); 67 | 68 | var lastNull = false; 69 | var i = -1; 70 | byte c; 71 | while (!((c = Marshal.ReadByte(location, ++i)) == '\0' && lastNull)) 72 | { 73 | if (c == '\0') 74 | { 75 | lastNull = true; 76 | 77 | strings.Add(Marshal.PtrToStringAnsi(location, i)); 78 | location = new IntPtr((long)location + i + 1); 79 | i = -1; 80 | } 81 | else 82 | lastNull = false; 83 | } 84 | 85 | return strings.ToArray(); 86 | } 87 | 88 | private static bool GetIsExtensionPresent(string extension) 89 | { 90 | sbyte result; 91 | if (extension.StartsWith("ALC")) 92 | { 93 | result = API.alcIsExtensionPresent(IntPtr.Zero, extension); 94 | } 95 | else 96 | { 97 | result = API.alIsExtensionPresent(extension); 98 | // todo: check for errors here 99 | } 100 | 101 | return (result == 1); 102 | } 103 | 104 | public uint OutputSampleRate { get; private set; } 105 | public int BitDepth { get; private set; } 106 | public int ChannelCount { get; private set; } 107 | 108 | /// 109 | /// Size of each sample in bytes. 110 | /// 111 | private int _sampleSize; 112 | 113 | /// 114 | /// OpenAL playback source. 115 | /// 116 | private uint _source; 117 | 118 | private ALAudioFormat _format; 119 | 120 | /// 121 | /// Available buffers. 122 | /// 123 | private readonly Queue _availableBuffers = new Queue(); 124 | 125 | /// 126 | /// Buffers queued for playback on the source. 127 | /// 128 | private readonly List _queuedBuffers = new List(); 129 | 130 | private readonly Dictionary _bufferSampleCounts = new Dictionary(); 131 | 132 | /// 133 | /// OpenAL context. 134 | /// 135 | private IntPtr _context; 136 | 137 | /// 138 | /// Token issued by PlaybackDevice. 139 | /// 140 | private int _token; 141 | 142 | private int _queuedSampleCount; 143 | 144 | internal OpenALOutput(string deviceName) 145 | { 146 | if (deviceName == null) throw new ArgumentNullException("deviceName"); 147 | Name = deviceName; 148 | } 149 | 150 | ~OpenALOutput() 151 | { 152 | Dispose(); 153 | } 154 | 155 | private void CreateSource() 156 | { 157 | lock (typeof (PlaybackDevice)) 158 | { 159 | API.alcMakeContextCurrent(_context); 160 | var sources = new uint[1]; 161 | API.alGenSources(1, sources); 162 | _source = sources[0]; 163 | } 164 | } 165 | 166 | private void CreateBuffers(int bufferCount) 167 | { 168 | lock (typeof (PlaybackDevice)) 169 | { 170 | API.alcMakeContextCurrent(_context); 171 | var buffers = new uint[bufferCount]; 172 | API.alGenBuffers(bufferCount, buffers); 173 | foreach (var buffer in buffers) 174 | _availableBuffers.Enqueue(buffer); 175 | } 176 | } 177 | 178 | public string Name { get; private set; } 179 | 180 | /// 181 | /// Gets the number of frames queued for playback. 182 | /// 183 | public int QueuedSampleCount 184 | { 185 | get { CleanupPlayedBuffers(); return _queuedSampleCount; } 186 | private set { _queuedSampleCount = value; } 187 | } 188 | 189 | public AudioFormat Format { get; private set; } 190 | 191 | public void Open(AudioFormat outputFormat) 192 | { 193 | if (IsOpen) 194 | Close(); 195 | 196 | OutputSampleRate = (uint)outputFormat.SampleRate; 197 | BitDepth = outputFormat.BitDepth; 198 | ChannelCount = outputFormat.Channels; 199 | if (outputFormat.BitDepth != 8 && outputFormat.BitDepth != 16) throw new ArgumentOutOfRangeException("outputFormat", "Only 8 or 16 bitdepths are supported."); 200 | if (outputFormat.Channels != 1 && outputFormat.Channels != 2) throw new ArgumentOutOfRangeException("outputFormat", "Only 1 or 2 channels are supported."); 201 | 202 | _format = ALAudioFormat.Unknown; 203 | if (outputFormat.BitDepth == 8 && outputFormat.Channels == 1) 204 | _format = ALAudioFormat.Mono8Bit; 205 | if (outputFormat.BitDepth == 8 && outputFormat.Channels == 2) 206 | _format = ALAudioFormat.Stereo8Bit; 207 | if (outputFormat.BitDepth == 16 && outputFormat.Channels == 1) 208 | _format = ALAudioFormat.Mono16Bit; 209 | if (outputFormat.BitDepth == 16 && outputFormat.Channels == 2) 210 | _format = ALAudioFormat.Stereo16Bit; 211 | 212 | _sampleSize = FormatHelper.SampleSize(outputFormat.BitDepth, outputFormat.Channels); 213 | _context = PlaybackDevice.GetContext(Name); 214 | _token = PlaybackDevice.GetToken(Name); 215 | // todo: error checking 216 | CreateSource(); 217 | CreateBuffers(6); 218 | } 219 | 220 | public void Close() 221 | { 222 | if (IsOpen) 223 | { 224 | if (_source != 0) 225 | { 226 | CleanupPlayedBuffers(true); 227 | var buffers = _queuedBuffers.ToArray(); 228 | var removedBuffers = new uint[buffers.Length]; 229 | API.alSourceUnqueueBuffers(_source, buffers.Length, removedBuffers); 230 | API.alDeleteBuffers(buffers.Length, removedBuffers); 231 | lock (typeof(PlaybackDevice)) 232 | { 233 | API.alcMakeContextCurrent(_context); 234 | API.alDeleteSources(1, new[] { _source }); 235 | _source = 0; 236 | } 237 | } 238 | if (_context != IntPtr.Zero) 239 | _context = IntPtr.Zero; 240 | if (_token != 0) 241 | { 242 | PlaybackDevice.RetireToken(_token); 243 | _token = 0; 244 | } 245 | } 246 | } 247 | 248 | /// 249 | /// Begins playback. 250 | /// 251 | public void Play() 252 | { 253 | lock (typeof (PlaybackDevice)) 254 | { 255 | API.alcMakeContextCurrent(_context); 256 | API.alSourcePlay(_source); 257 | } 258 | } 259 | 260 | /// 261 | /// Pauses playback. 262 | /// 263 | public void Pause() 264 | { 265 | lock (typeof(PlaybackDevice)) 266 | { 267 | API.alcMakeContextCurrent(_context); 268 | API.alSourcePause(_source); 269 | } 270 | } 271 | 272 | public unsafe int Write(byte[] pcmBuffer, int offset, int sampleCount) 273 | { 274 | var pcmLength = _sampleSize * sampleCount; 275 | if (pcmLength > pcmBuffer.Length - offset) 276 | throw new Exception("Sample count is too large to be read from pcm buffer."); 277 | if (_availableBuffers.Count == 0) 278 | CreateBuffers(1); 279 | lock (typeof(PlaybackDevice)) 280 | { 281 | API.alcMakeContextCurrent(_context); 282 | var bufferId = _availableBuffers.Dequeue(); 283 | fixed (byte* bPcm = pcmBuffer) 284 | { 285 | var pcmPtr = IntPtr.Add(new IntPtr(bPcm), offset); 286 | API.alBufferData(bufferId, _format, pcmPtr, pcmLength, OutputSampleRate); 287 | API.alSourceQueueBuffers(_source, 1, new[] { bufferId }); 288 | } 289 | _bufferSampleCounts[bufferId] = sampleCount; 290 | _queuedBuffers.Add(bufferId); 291 | QueuedSampleCount += sampleCount; 292 | } 293 | CleanupPlayedBuffers(); 294 | return sampleCount; 295 | } 296 | 297 | /// 298 | /// Stops playback. 299 | /// 300 | public void Stop() 301 | { 302 | lock (typeof(PlaybackDevice)) 303 | { 304 | API.alcMakeContextCurrent(_context); 305 | API.alSourceStop(_source); 306 | } 307 | } 308 | 309 | private SourceState State 310 | { 311 | get 312 | { 313 | if (_source == 0) 314 | return SourceState.Uninitialized; 315 | 316 | int state; 317 | API.alGetSourcei(_source, IntSourceProperty.AL_SOURCE_STATE, out state); 318 | 319 | return (SourceState)state; 320 | } 321 | } 322 | 323 | /// 324 | /// Gets if the device is playing audio. 325 | /// 326 | public bool IsPlaying 327 | { 328 | get { return (State == SourceState.Playing); } 329 | } 330 | 331 | /// 332 | /// Gets if the device is paused. 333 | /// 334 | public bool IsPaused 335 | { 336 | get { return (State == SourceState.Paused); } 337 | } 338 | 339 | public bool IsOpen 340 | { 341 | get 342 | { 343 | return _source != 0; 344 | } 345 | } 346 | 347 | /// 348 | /// Gets if the device is stopped. 349 | /// 350 | public bool IsStopped 351 | { 352 | get { return (State == SourceState.Stopped); } 353 | } 354 | 355 | private void CleanupPlayedBuffers(bool destroy = false) 356 | { 357 | if (_source == 0) return; 358 | lock (typeof (PlaybackDevice)) 359 | { 360 | API.alcMakeContextCurrent(_context); 361 | int buffers; 362 | API.alGetSourcei(_source, IntSourceProperty.AL_BUFFERS_PROCESSED, out buffers); 363 | if (buffers < 1) return; 364 | 365 | var removedBuffers = new uint[buffers]; 366 | API.alSourceUnqueueBuffers(_source, buffers, removedBuffers); 367 | if (!destroy) 368 | { 369 | foreach (var buffer in removedBuffers) 370 | { 371 | _availableBuffers.Enqueue(buffer); 372 | } 373 | } 374 | else 375 | { 376 | API.alDeleteBuffers(buffers, removedBuffers); 377 | } 378 | foreach (var bufferId in removedBuffers) 379 | { 380 | var sampleCount = 0; 381 | if (_bufferSampleCounts.TryGetValue(bufferId, out sampleCount)) 382 | { 383 | _queuedSampleCount -= sampleCount; 384 | } 385 | } 386 | } 387 | } 388 | 389 | /// 390 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 391 | /// 392 | /// 2 393 | public void Dispose() 394 | { 395 | if (IsOpen) 396 | Close(); 397 | } 398 | } 399 | } -------------------------------------------------------------------------------- /Aural/OpenALSoft License.txt: -------------------------------------------------------------------------------- 1 | 2 | GNU LIBRARY GENERAL PUBLIC LICENSE 3 | Version 2, June 1991 4 | 5 | 6 | Copyright (C) 1991 Free Software Foundation, Inc. 7 | 675 Mass Ave, Cambridge, MA 02139, USA 8 | Everyone is permitted to copy and distribute verbatim copies 9 | of this license document, but changing it is not allowed. 10 | 11 | [This is the first released version of the library GPL. It is 12 | numbered 2 because it goes with version 2 of the ordinary GPL.] 13 | 14 | Preamble 15 | 16 | The licenses for most software are designed to take away your 17 | freedom to share and change it. By contrast, the GNU General Public 18 | Licenses are intended to guarantee your freedom to share and change 19 | free software--to make sure the software is free for all its users. 20 | 21 | This license, the Library General Public License, applies to some 22 | specially designated Free Software Foundation software, and to any 23 | other libraries whose authors decide to use it. You can use it for 24 | your libraries, too. 25 | 26 | When we speak of free software, we are referring to freedom, not 27 | price. Our General Public Licenses are designed to make sure that you 28 | have the freedom to distribute copies of free software (and charge for 29 | this service if you wish), that you receive source code or can get it 30 | if you want it, that you can change the software or use pieces of it 31 | in new free programs; and that you know you can do these things. 32 | 33 | To protect your rights, we need to make restrictions that forbid 34 | anyone to deny you these rights or to ask you to surrender the rights. 35 | These restrictions translate to certain responsibilities for you if 36 | you distribute copies of the library, or if you modify it. 37 | 38 | For example, if you distribute copies of the library, whether gratis 39 | or for a fee, you must give the recipients all the rights that we gave 40 | you. You must make sure that they, too, receive or can get the source 41 | code. If you link a program with the library, you must provide 42 | complete object files to the recipients so that they can relink them 43 | with the library, after making changes to the library and recompiling 44 | it. And you must show them these terms so they know their rights. 45 | 46 | Our method of protecting your rights has two steps: (1) copyright 47 | the library, and (2) offer you this license which gives you legal 48 | permission to copy, distribute and/or modify the library. 49 | 50 | Also, for each distributor's protection, we want to make certain 51 | that everyone understands that there is no warranty for this free 52 | library. If the library is modified by someone else and passed on, we 53 | want its recipients to know that what they have is not the original 54 | version, so that any problems introduced by others will not reflect on 55 | the original authors' reputations. 56 | 57 | Finally, any free program is threatened constantly by software 58 | patents. We wish to avoid the danger that companies distributing free 59 | software will individually obtain patent licenses, thus in effect 60 | transforming the program into proprietary software. To prevent this, 61 | we have made it clear that any patent must be licensed for everyone's 62 | free use or not licensed at all. 63 | 64 | Most GNU software, including some libraries, is covered by the ordinary 65 | GNU General Public License, which was designed for utility programs. This 66 | license, the GNU Library General Public License, applies to certain 67 | designated libraries. This license is quite different from the ordinary 68 | one; be sure to read it in full, and don't assume that anything in it is 69 | the same as in the ordinary license. 70 | 71 | The reason we have a separate public license for some libraries is that 72 | they blur the distinction we usually make between modifying or adding to a 73 | program and simply using it. Linking a program with a library, without 74 | changing the library, is in some sense simply using the library, and is 75 | analogous to running a utility program or application program. However, in 76 | a textual and legal sense, the linked executable is a combined work, a 77 | derivative of the original library, and the ordinary General Public License 78 | treats it as such. 79 | 80 | Because of this blurred distinction, using the ordinary General 81 | Public License for libraries did not effectively promote software 82 | sharing, because most developers did not use the libraries. We 83 | concluded that weaker conditions might promote sharing better. 84 | 85 | However, unrestricted linking of non-free programs would deprive the 86 | users of those programs of all benefit from the free status of the 87 | libraries themselves. This Library General Public License is intended to 88 | permit developers of non-free programs to use free libraries, while 89 | preserving your freedom as a user of such programs to change the free 90 | libraries that are incorporated in them. (We have not seen how to achieve 91 | this as regards changes in header files, but we have achieved it as regards 92 | changes in the actual functions of the Library.) The hope is that this 93 | will lead to faster development of free libraries. 94 | 95 | The precise terms and conditions for copying, distribution and 96 | modification follow. Pay close attention to the difference between a 97 | "work based on the library" and a "work that uses the library". The 98 | former contains code derived from the library, while the latter only 99 | works together with the library. 100 | 101 | Note that it is possible for a library to be covered by the ordinary 102 | General Public License rather than by this special one. 103 | 104 | GNU LIBRARY GENERAL PUBLIC LICENSE 105 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 106 | 107 | 0. This License Agreement applies to any software library which 108 | contains a notice placed by the copyright holder or other authorized 109 | party saying it may be distributed under the terms of this Library 110 | General Public License (also called "this License"). Each licensee is 111 | addressed as "you". 112 | 113 | A "library" means a collection of software functions and/or data 114 | prepared so as to be conveniently linked with application programs 115 | (which use some of those functions and data) to form executables. 116 | 117 | The "Library", below, refers to any such software library or work 118 | which has been distributed under these terms. A "work based on the 119 | Library" means either the Library or any derivative work under 120 | copyright law: that is to say, a work containing the Library or a 121 | portion of it, either verbatim or with modifications and/or translated 122 | straightforwardly into another language. (Hereinafter, translation is 123 | included without limitation in the term "modification".) 124 | 125 | "Source code" for a work means the preferred form of the work for 126 | making modifications to it. For a library, complete source code means 127 | all the source code for all modules it contains, plus any associated 128 | interface definition files, plus the scripts used to control compilation 129 | and installation of the library. 130 | 131 | Activities other than copying, distribution and modification are not 132 | covered by this License; they are outside its scope. The act of 133 | running a program using the Library is not restricted, and output from 134 | such a program is covered only if its contents constitute a work based 135 | on the Library (independent of the use of the Library in a tool for 136 | writing it). Whether that is true depends on what the Library does 137 | and what the program that uses the Library does. 138 | 139 | 1. You may copy and distribute verbatim copies of the Library's 140 | complete source code as you receive it, in any medium, provided that 141 | you conspicuously and appropriately publish on each copy an 142 | appropriate copyright notice and disclaimer of warranty; keep intact 143 | all the notices that refer to this License and to the absence of any 144 | warranty; and distribute a copy of this License along with the 145 | Library. 146 | 147 | You may charge a fee for the physical act of transferring a copy, 148 | and you may at your option offer warranty protection in exchange for a 149 | fee. 150 | 151 | 2. You may modify your copy or copies of the Library or any portion 152 | of it, thus forming a work based on the Library, and copy and 153 | distribute such modifications or work under the terms of Section 1 154 | above, provided that you also meet all of these conditions: 155 | 156 | a) The modified work must itself be a software library. 157 | 158 | b) You must cause the files modified to carry prominent notices 159 | stating that you changed the files and the date of any change. 160 | 161 | c) You must cause the whole of the work to be licensed at no 162 | charge to all third parties under the terms of this License. 163 | 164 | d) If a facility in the modified Library refers to a function or a 165 | table of data to be supplied by an application program that uses 166 | the facility, other than as an argument passed when the facility 167 | is invoked, then you must make a good faith effort to ensure that, 168 | in the event an application does not supply such function or 169 | table, the facility still operates, and performs whatever part of 170 | its purpose remains meaningful. 171 | 172 | (For example, a function in a library to compute square roots has 173 | a purpose that is entirely well-defined independent of the 174 | application. Therefore, Subsection 2d requires that any 175 | application-supplied function or table used by this function must 176 | be optional: if the application does not supply it, the square 177 | root function must still compute square roots.) 178 | 179 | These requirements apply to the modified work as a whole. If 180 | identifiable sections of that work are not derived from the Library, 181 | and can be reasonably considered independent and separate works in 182 | themselves, then this License, and its terms, do not apply to those 183 | sections when you distribute them as separate works. But when you 184 | distribute the same sections as part of a whole which is a work based 185 | on the Library, the distribution of the whole must be on the terms of 186 | this License, whose permissions for other licensees extend to the 187 | entire whole, and thus to each and every part regardless of who wrote 188 | it. 189 | 190 | Thus, it is not the intent of this section to claim rights or contest 191 | your rights to work written entirely by you; rather, the intent is to 192 | exercise the right to control the distribution of derivative or 193 | collective works based on the Library. 194 | 195 | In addition, mere aggregation of another work not based on the Library 196 | with the Library (or with a work based on the Library) on a volume of 197 | a storage or distribution medium does not bring the other work under 198 | the scope of this License. 199 | 200 | 3. You may opt to apply the terms of the ordinary GNU General Public 201 | License instead of this License to a given copy of the Library. To do 202 | this, you must alter all the notices that refer to this License, so 203 | that they refer to the ordinary GNU General Public License, version 2, 204 | instead of to this License. (If a newer version than version 2 of the 205 | ordinary GNU General Public License has appeared, then you can specify 206 | that version instead if you wish.) Do not make any other change in 207 | these notices. 208 | 209 | Once this change is made in a given copy, it is irreversible for 210 | that copy, so the ordinary GNU General Public License applies to all 211 | subsequent copies and derivative works made from that copy. 212 | 213 | This option is useful when you wish to copy part of the code of 214 | the Library into a program that is not a library. 215 | 216 | 4. You may copy and distribute the Library (or a portion or 217 | derivative of it, under Section 2) in object code or executable form 218 | under the terms of Sections 1 and 2 above provided that you accompany 219 | it with the complete corresponding machine-readable source code, which 220 | must be distributed under the terms of Sections 1 and 2 above on a 221 | medium customarily used for software interchange. 222 | 223 | If distribution of object code is made by offering access to copy 224 | from a designated place, then offering equivalent access to copy the 225 | source code from the same place satisfies the requirement to 226 | distribute the source code, even though third parties are not 227 | compelled to copy the source along with the object code. 228 | 229 | 5. A program that contains no derivative of any portion of the 230 | Library, but is designed to work with the Library by being compiled or 231 | linked with it, is called a "work that uses the Library". Such a 232 | work, in isolation, is not a derivative work of the Library, and 233 | therefore falls outside the scope of this License. 234 | 235 | However, linking a "work that uses the Library" with the Library 236 | creates an executable that is a derivative of the Library (because it 237 | contains portions of the Library), rather than a "work that uses the 238 | library". The executable is therefore covered by this License. 239 | Section 6 states terms for distribution of such executables. 240 | 241 | When a "work that uses the Library" uses material from a header file 242 | that is part of the Library, the object code for the work may be a 243 | derivative work of the Library even though the source code is not. 244 | Whether this is true is especially significant if the work can be 245 | linked without the Library, or if the work is itself a library. The 246 | threshold for this to be true is not precisely defined by law. 247 | 248 | If such an object file uses only numerical parameters, data 249 | structure layouts and accessors, and small macros and small inline 250 | functions (ten lines or less in length), then the use of the object 251 | file is unrestricted, regardless of whether it is legally a derivative 252 | work. (Executables containing this object code plus portions of the 253 | Library will still fall under Section 6.) 254 | 255 | Otherwise, if the work is a derivative of the Library, you may 256 | distribute the object code for the work under the terms of Section 6. 257 | Any executables containing that work also fall under Section 6, 258 | whether or not they are linked directly with the Library itself. 259 | 260 | 6. As an exception to the Sections above, you may also compile or 261 | link a "work that uses the Library" with the Library to produce a 262 | work containing portions of the Library, and distribute that work 263 | under terms of your choice, provided that the terms permit 264 | modification of the work for the customer's own use and reverse 265 | engineering for debugging such modifications. 266 | 267 | You must give prominent notice with each copy of the work that the 268 | Library is used in it and that the Library and its use are covered by 269 | this License. You must supply a copy of this License. If the work 270 | during execution displays copyright notices, you must include the 271 | copyright notice for the Library among them, as well as a reference 272 | directing the user to the copy of this License. Also, you must do one 273 | of these things: 274 | 275 | a) Accompany the work with the complete corresponding 276 | machine-readable source code for the Library including whatever 277 | changes were used in the work (which must be distributed under 278 | Sections 1 and 2 above); and, if the work is an executable linked 279 | with the Library, with the complete machine-readable "work that 280 | uses the Library", as object code and/or source code, so that the 281 | user can modify the Library and then relink to produce a modified 282 | executable containing the modified Library. (It is understood 283 | that the user who changes the contents of definitions files in the 284 | Library will not necessarily be able to recompile the application 285 | to use the modified definitions.) 286 | 287 | b) Accompany the work with a written offer, valid for at 288 | least three years, to give the same user the materials 289 | specified in Subsection 6a, above, for a charge no more 290 | than the cost of performing this distribution. 291 | 292 | c) If distribution of the work is made by offering access to copy 293 | from a designated place, offer equivalent access to copy the above 294 | specified materials from the same place. 295 | 296 | d) Verify that the user has already received a copy of these 297 | materials or that you have already sent this user a copy. 298 | 299 | For an executable, the required form of the "work that uses the 300 | Library" must include any data and utility programs needed for 301 | reproducing the executable from it. However, as a special exception, 302 | the source code distributed need not include anything that is normally 303 | distributed (in either source or binary form) with the major 304 | components (compiler, kernel, and so on) of the operating system on 305 | which the executable runs, unless that component itself accompanies 306 | the executable. 307 | 308 | It may happen that this requirement contradicts the license 309 | restrictions of other proprietary libraries that do not normally 310 | accompany the operating system. Such a contradiction means you cannot 311 | use both them and the Library together in an executable that you 312 | distribute. 313 | 314 | 7. You may place library facilities that are a work based on the 315 | Library side-by-side in a single library together with other library 316 | facilities not covered by this License, and distribute such a combined 317 | library, provided that the separate distribution of the work based on 318 | the Library and of the other library facilities is otherwise 319 | permitted, and provided that you do these two things: 320 | 321 | a) Accompany the combined library with a copy of the same work 322 | based on the Library, uncombined with any other library 323 | facilities. This must be distributed under the terms of the 324 | Sections above. 325 | 326 | b) Give prominent notice with the combined library of the fact 327 | that part of it is a work based on the Library, and explaining 328 | where to find the accompanying uncombined form of the same work. 329 | 330 | 8. You may not copy, modify, sublicense, link with, or distribute 331 | the Library except as expressly provided under this License. Any 332 | attempt otherwise to copy, modify, sublicense, link with, or 333 | distribute the Library is void, and will automatically terminate your 334 | rights under this License. However, parties who have received copies, 335 | or rights, from you under this License will not have their licenses 336 | terminated so long as such parties remain in full compliance. 337 | 338 | 9. You are not required to accept this License, since you have not 339 | signed it. However, nothing else grants you permission to modify or 340 | distribute the Library or its derivative works. These actions are 341 | prohibited by law if you do not accept this License. Therefore, by 342 | modifying or distributing the Library (or any work based on the 343 | Library), you indicate your acceptance of this License to do so, and 344 | all its terms and conditions for copying, distributing or modifying 345 | the Library or works based on it. 346 | 347 | 10. Each time you redistribute the Library (or any work based on the 348 | Library), the recipient automatically receives a license from the 349 | original licensor to copy, distribute, link with or modify the Library 350 | subject to these terms and conditions. You may not impose any further 351 | restrictions on the recipients' exercise of the rights granted herein. 352 | You are not responsible for enforcing compliance by third parties to 353 | this License. 354 | 355 | 11. If, as a consequence of a court judgment or allegation of patent 356 | infringement or for any other reason (not limited to patent issues), 357 | conditions are imposed on you (whether by court order, agreement or 358 | otherwise) that contradict the conditions of this License, they do not 359 | excuse you from the conditions of this License. If you cannot 360 | distribute so as to satisfy simultaneously your obligations under this 361 | License and any other pertinent obligations, then as a consequence you 362 | may not distribute the Library at all. For example, if a patent 363 | license would not permit royalty-free redistribution of the Library by 364 | all those who receive copies directly or indirectly through you, then 365 | the only way you could satisfy both it and this License would be to 366 | refrain entirely from distribution of the Library. 367 | 368 | If any portion of this section is held invalid or unenforceable under any 369 | particular circumstance, the balance of the section is intended to apply, 370 | and the section as a whole is intended to apply in other circumstances. 371 | 372 | It is not the purpose of this section to induce you to infringe any 373 | patents or other property right claims or to contest validity of any 374 | such claims; this section has the sole purpose of protecting the 375 | integrity of the free software distribution system which is 376 | implemented by public license practices. Many people have made 377 | generous contributions to the wide range of software distributed 378 | through that system in reliance on consistent application of that 379 | system; it is up to the author/donor to decide if he or she is willing 380 | to distribute software through any other system and a licensee cannot 381 | impose that choice. 382 | 383 | This section is intended to make thoroughly clear what is believed to 384 | be a consequence of the rest of this License. 385 | 386 | 12. If the distribution and/or use of the Library is restricted in 387 | certain countries either by patents or by copyrighted interfaces, the 388 | original copyright holder who places the Library under this License may add 389 | an explicit geographical distribution limitation excluding those countries, 390 | so that distribution is permitted only in or among countries not thus 391 | excluded. In such case, this License incorporates the limitation as if 392 | written in the body of this License. 393 | 394 | 13. The Free Software Foundation may publish revised and/or new 395 | versions of the Library General Public License from time to time. 396 | Such new versions will be similar in spirit to the present version, 397 | but may differ in detail to address new problems or concerns. 398 | 399 | Each version is given a distinguishing version number. If the Library 400 | specifies a version number of this License which applies to it and 401 | "any later version", you have the option of following the terms and 402 | conditions either of that version or of any later version published by 403 | the Free Software Foundation. If the Library does not specify a 404 | license version number, you may choose any version ever published by 405 | the Free Software Foundation. 406 | 407 | 14. If you wish to incorporate parts of the Library into other free 408 | programs whose distribution conditions are incompatible with these, 409 | write to the author to ask for permission. For software which is 410 | copyrighted by the Free Software Foundation, write to the Free 411 | Software Foundation; we sometimes make exceptions for this. Our 412 | decision will be guided by the two goals of preserving the free status 413 | of all derivatives of our free software and of promoting the sharing 414 | and reuse of software generally. 415 | 416 | NO WARRANTY 417 | 418 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 419 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 420 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 421 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 422 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 423 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 424 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 425 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 426 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 427 | 428 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 429 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 430 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 431 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 432 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 433 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 434 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 435 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 436 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 437 | DAMAGES. 438 | 439 | END OF TERMS AND CONDITIONS 440 | 441 | Appendix: How to Apply These Terms to Your New Libraries 442 | 443 | If you develop a new library, and you want it to be of the greatest 444 | possible use to the public, we recommend making it free software that 445 | everyone can redistribute and change. You can do so by permitting 446 | redistribution under these terms (or, alternatively, under the terms of the 447 | ordinary General Public License). 448 | 449 | To apply these terms, attach the following notices to the library. It is 450 | safest to attach them to the start of each source file to most effectively 451 | convey the exclusion of warranty; and each file should have at least the 452 | "copyright" line and a pointer to where the full notice is found. 453 | 454 | 455 | Copyright (C) 456 | 457 | This library is free software; you can redistribute it and/or 458 | modify it under the terms of the GNU Library General Public 459 | License as published by the Free Software Foundation; either 460 | version 2 of the License, or (at your option) any later version. 461 | 462 | This library is distributed in the hope that it will be useful, 463 | but WITHOUT ANY WARRANTY; without even the implied warranty of 464 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 465 | Library General Public License for more details. 466 | 467 | You should have received a copy of the GNU Library General Public 468 | License along with this library; if not, write to the Free 469 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 470 | 471 | Also add information on how to contact you by electronic and paper mail. 472 | 473 | You should also get your employer (if you work as a programmer) or your 474 | school, if any, to sign a "copyright disclaimer" for the library, if 475 | necessary. Here is a sample; alter the names: 476 | 477 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 478 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 479 | 480 | , 1 April 1990 481 | Ty Coon, President of Vice 482 | 483 | That's all there is to it! --------------------------------------------------------------------------------