├── Aural
├── Libs
│ ├── 32bit
│ │ ├── openal.dll
│ │ ├── opus.dll
│ │ └── libopus.dylib
│ ├── 64bit
│ │ ├── openal.dll
│ │ └── opus.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/openal.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnACarruthers/Aural/master/Aural/Libs/32bit/openal.dll
--------------------------------------------------------------------------------
/Aural/Libs/32bit/opus.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnACarruthers/Aural/master/Aural/Libs/32bit/opus.dll
--------------------------------------------------------------------------------
/Aural/Libs/64bit/openal.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnACarruthers/Aural/master/Aural/Libs/64bit/openal.dll
--------------------------------------------------------------------------------
/Aural/Libs/64bit/opus.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnACarruthers/Aural/master/Aural/Libs/64bit/opus.dll
--------------------------------------------------------------------------------
/Aural/Libs/librpiaudio.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnACarruthers/Aural/master/Aural/Libs/librpiaudio.so
--------------------------------------------------------------------------------
/Aural/Libs/32bit/libopus.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnACarruthers/Aural/master/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!
--------------------------------------------------------------------------------