From 0d25ca7589e1d9713ac07976e1e3113f2a2580cd Mon Sep 17 00:00:00 2001 From: "SND\\AstrorEnales_cp" Date: Wed, 3 Oct 2012 20:47:56 +0000 Subject: [PATCH] - Added OggUtils Support project by making use of the csogg and csvorbis projects - Implemented native Song playback in OpenAL and XAudio2 - Some tweaks in the MediaPlayer and MediaQueue - Added a testmusic.ogg file to the media folder --- ...NX.Framework.Content.Pipeline_Linux.csproj | 1 + ...X.Framework.Content.Pipeline_PSVita.csproj | 1 + ...ework.Content.Pipeline_WindowsMetro.csproj | 5 +- ...entPipeline.Extensions_WindowsMetro.csproj | 4 +- .../ANX.Framework.TestCenter_Linux.csproj | 1 + .../ANX.Framework.TestCenter_PSVita.csproj | 1 + ...X.Framework.TestCenter_WindowsMetro.csproj | 9 +- ANX.Framework.sln | 17 + ANX.Framework/ANX.Framework.csproj | 1 + ANX.Framework/ANX.Framework_Linux.csproj | 3 + ANX.Framework/ANX.Framework_PSVita.csproj | 3 + .../ANX.Framework_WindowsMetro.csproj | 1 + ANX.Framework/Content/ContentManager.cs | 1 - ANX.Framework/Content/ContentReader.cs | 23 + .../Content/MediaTypeReaders/SongReader.cs | 23 + .../MediaTypeReaders/SoundEffectReader.cs | 8 + ANX.Framework/Media/MediaLibrary.cs | 4 + ANX.Framework/Media/MediaPlayer.cs | 10 +- ANX.Framework/Media/MediaQueue.cs | 4 +- ANX.Framework/Media/Song.cs | 29 +- .../NonXNA/SoundSystem/ISoundSystemCreator.cs | 1 + ANX.Framework_Linux.sln | 53 +- ANX.Framework_PSVita.sln | 53 +- ANX.Framework_WindowsMetro.sln | 53 +- ...InputDevices.Windows.ModernUI_Linux.csproj | 136 ++ ...nputDevices.Windows.ModernUI_PSVita.csproj | 138 ++ .../ANX.RenderSystem.GL3_PSVita.csproj | 90 ++ Samples/AudioSample/AudioSample_Linux.csproj | 4 + Samples/AudioSample/AudioSample_PSVita.csproj | 4 + Samples/AudioSample/Game1.cs | 25 +- Samples/SimpleNoContent/Assets/Logo.png | Bin 0 -> 5379 bytes Samples/SimpleNoContent/Assets/SmallLogo.png | Bin 0 -> 558 bytes .../SimpleNoContent/Assets/SplashScreen.png | Bin 0 -> 11403 bytes Samples/SimpleNoContent/Assets/StoreLogo.png | Bin 0 -> 1059 bytes Samples/SimpleNoContent/Manifest.appxmanifest | 27 + .../SimpleNoContent/SimpleNoContent.csproj | 1 - .../SimpleNoContent_Linux.csproj | 87 + .../SimpleNoContent_PSVita.csproj | 90 ++ .../SimpleNoContent_WindowsMetro.csproj | 91 ++ Samples/WpfEditor/WpfEditor_Linux.csproj | 4 + Samples/WpfEditor/WpfEditor_PSVita.csproj | 4 + .../ANX.SoundSystem.OpenAL.csproj | 5 + .../ANX.SoundSystem.OpenAL_Linux.csproj | 5 + .../ANX.SoundSystem.OpenAL_PSVita.csproj | 5 + ...ANX.SoundSystem.OpenAL_WindowsMetro.csproj | 5 + .../ANX.SoundSystem.OpenAL/Creator.cs | 8 +- .../ANX.SoundSystem.OpenAL/OpenALSong.cs | 179 ++ .../ANX.SoundSystem.PsVita/Creator.cs | 6 + .../ANX.SoundSystem.Windows.XAudio.csproj | 8 + ...NX.SoundSystem.Windows.XAudio_Linux.csproj | 8 + ...X.SoundSystem.Windows.XAudio_PSVita.csproj | 8 + ...dSystem.Windows.XAudio_WindowsMetro.csproj | 8 + .../ANX.SoundSystem.Windows.XAudio/Creator.cs | 41 +- .../XAudioOggInputStream.cs | 44 + .../XAudioSong.cs | 155 ++ Support/OggUtils/OggInputStream.cs | 230 +++ Support/OggUtils/OggStreamingData.cs | 84 + Support/OggUtils/OggUtils.csproj | 89 + Support/OggUtils/OggUtils_Linux.csproj | 88 + Support/OggUtils/OggUtils_PSVita.csproj | 89 + Support/OggUtils/OggUtils_WindowsMetro.csproj | 94 ++ Support/OggUtils/Properties/AssemblyInfo.cs | 36 + Support/OggUtils/csogg/Buffer.cs | 302 ++++ Support/OggUtils/csogg/Packet.cs | 53 + Support/OggUtils/csogg/Page.cs | 140 ++ Support/OggUtils/csogg/StreamState.cs | 581 +++++++ Support/OggUtils/csogg/SyncState.cs | 289 ++++ Support/OggUtils/csvorbis/AllocChain.cs | 36 + Support/OggUtils/csvorbis/Block.cs | 205 +++ Support/OggUtils/csvorbis/CodeBook.cs | 627 +++++++ Support/OggUtils/csvorbis/Comment.cs | 308 ++++ Support/OggUtils/csvorbis/Drft.cs | 1313 +++++++++++++++ Support/OggUtils/csvorbis/DspState.cs | 445 +++++ .../csvorbis/EncodeAuxNearestMatch.cs | 40 + .../OggUtils/csvorbis/EncodeAuxThreshMatch.cs | 37 + Support/OggUtils/csvorbis/Floor0.cs | 405 +++++ Support/OggUtils/csvorbis/Floor1.cs | 721 +++++++++ Support/OggUtils/csvorbis/FuncFloor.cs | 45 + Support/OggUtils/csvorbis/FuncMapping.cs | 42 + Support/OggUtils/csvorbis/FuncResidue.cs | 46 + Support/OggUtils/csvorbis/FuncTime.cs | 43 + Support/OggUtils/csvorbis/Info.cs | 574 +++++++ Support/OggUtils/csvorbis/InfoMode.cs | 38 + Support/OggUtils/csvorbis/Lookup.cs | 161 ++ Support/OggUtils/csvorbis/Lpc.cs | 200 +++ Support/OggUtils/csvorbis/Lsp.cs | 133 ++ Support/OggUtils/csvorbis/Mapping0.cs | 456 ++++++ Support/OggUtils/csvorbis/Mdct.cs | 274 ++++ Support/OggUtils/csvorbis/PsyInfo.cs | 77 + Support/OggUtils/csvorbis/PsyLook.cs | 46 + Support/OggUtils/csvorbis/Residue0.cs | 415 +++++ Support/OggUtils/csvorbis/Residue1.cs | 59 + Support/OggUtils/csvorbis/Residue2.cs | 48 + Support/OggUtils/csvorbis/StaticCodeBook.cs | 542 +++++++ Support/OggUtils/csvorbis/Time0.cs | 41 + Support/OggUtils/csvorbis/VorbisFile.cs | 1434 +++++++++++++++++ Support/OggUtils/csvorbis/csorbisException.cs | 36 + .../WaveUtils/WaveUtils_WindowsMetro.csproj | 4 +- .../Platforms/MetroConverter.cs | 13 +- lib/GetLibraries.cmd | 5 + lib/packages.config | 15 + media/Test_TemporaryKey.pfx | Bin 0 -> 2512 bytes media/testmusic.ogg | Bin 0 -> 116691 bytes 103 files changed, 12390 insertions(+), 64 deletions(-) create mode 100644 ANX.Framework/Content/MediaTypeReaders/SongReader.cs create mode 100644 InputSystems/ANX.InputDevices.Windows.ModernUI/ANX.InputDevices.Windows.ModernUI_Linux.csproj create mode 100644 InputSystems/ANX.InputDevices.Windows.ModernUI/ANX.InputDevices.Windows.ModernUI_PSVita.csproj create mode 100644 RenderSystems/ANX.Framework.GL3/ANX.RenderSystem.GL3_PSVita.csproj create mode 100644 Samples/SimpleNoContent/Assets/Logo.png create mode 100644 Samples/SimpleNoContent/Assets/SmallLogo.png create mode 100644 Samples/SimpleNoContent/Assets/SplashScreen.png create mode 100644 Samples/SimpleNoContent/Assets/StoreLogo.png create mode 100644 Samples/SimpleNoContent/Manifest.appxmanifest create mode 100644 Samples/SimpleNoContent/SimpleNoContent_Linux.csproj create mode 100644 Samples/SimpleNoContent/SimpleNoContent_PSVita.csproj create mode 100644 Samples/SimpleNoContent/SimpleNoContent_WindowsMetro.csproj create mode 100644 SoundSystems/ANX.SoundSystem.OpenAL/OpenALSong.cs create mode 100644 SoundSystems/ANX.SoundSystem.Windows.XAudio/XAudioOggInputStream.cs create mode 100644 SoundSystems/ANX.SoundSystem.Windows.XAudio/XAudioSong.cs create mode 100644 Support/OggUtils/OggInputStream.cs create mode 100644 Support/OggUtils/OggStreamingData.cs create mode 100644 Support/OggUtils/OggUtils.csproj create mode 100644 Support/OggUtils/OggUtils_Linux.csproj create mode 100644 Support/OggUtils/OggUtils_PSVita.csproj create mode 100644 Support/OggUtils/OggUtils_WindowsMetro.csproj create mode 100644 Support/OggUtils/Properties/AssemblyInfo.cs create mode 100644 Support/OggUtils/csogg/Buffer.cs create mode 100644 Support/OggUtils/csogg/Packet.cs create mode 100644 Support/OggUtils/csogg/Page.cs create mode 100644 Support/OggUtils/csogg/StreamState.cs create mode 100644 Support/OggUtils/csogg/SyncState.cs create mode 100644 Support/OggUtils/csvorbis/AllocChain.cs create mode 100644 Support/OggUtils/csvorbis/Block.cs create mode 100644 Support/OggUtils/csvorbis/CodeBook.cs create mode 100644 Support/OggUtils/csvorbis/Comment.cs create mode 100644 Support/OggUtils/csvorbis/Drft.cs create mode 100644 Support/OggUtils/csvorbis/DspState.cs create mode 100644 Support/OggUtils/csvorbis/EncodeAuxNearestMatch.cs create mode 100644 Support/OggUtils/csvorbis/EncodeAuxThreshMatch.cs create mode 100644 Support/OggUtils/csvorbis/Floor0.cs create mode 100644 Support/OggUtils/csvorbis/Floor1.cs create mode 100644 Support/OggUtils/csvorbis/FuncFloor.cs create mode 100644 Support/OggUtils/csvorbis/FuncMapping.cs create mode 100644 Support/OggUtils/csvorbis/FuncResidue.cs create mode 100644 Support/OggUtils/csvorbis/FuncTime.cs create mode 100644 Support/OggUtils/csvorbis/Info.cs create mode 100644 Support/OggUtils/csvorbis/InfoMode.cs create mode 100644 Support/OggUtils/csvorbis/Lookup.cs create mode 100644 Support/OggUtils/csvorbis/Lpc.cs create mode 100644 Support/OggUtils/csvorbis/Lsp.cs create mode 100644 Support/OggUtils/csvorbis/Mapping0.cs create mode 100644 Support/OggUtils/csvorbis/Mdct.cs create mode 100644 Support/OggUtils/csvorbis/PsyInfo.cs create mode 100644 Support/OggUtils/csvorbis/PsyLook.cs create mode 100644 Support/OggUtils/csvorbis/Residue0.cs create mode 100644 Support/OggUtils/csvorbis/Residue1.cs create mode 100644 Support/OggUtils/csvorbis/Residue2.cs create mode 100644 Support/OggUtils/csvorbis/StaticCodeBook.cs create mode 100644 Support/OggUtils/csvorbis/Time0.cs create mode 100644 Support/OggUtils/csvorbis/VorbisFile.cs create mode 100644 Support/OggUtils/csvorbis/csorbisException.cs create mode 100644 lib/GetLibraries.cmd create mode 100644 lib/packages.config create mode 100644 media/Test_TemporaryKey.pfx create mode 100644 media/testmusic.ogg diff --git a/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_Linux.csproj b/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_Linux.csproj index 83e70c36..af1f193d 100644 --- a/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_Linux.csproj +++ b/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_Linux.csproj @@ -36,6 +36,7 @@ + diff --git a/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_PSVita.csproj b/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_PSVita.csproj index cc29aa64..0b2064cb 100644 --- a/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_PSVita.csproj +++ b/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_PSVita.csproj @@ -36,6 +36,7 @@ + diff --git a/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_WindowsMetro.csproj b/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_WindowsMetro.csproj index 0c973d6b..55c0f85a 100644 --- a/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_WindowsMetro.csproj +++ b/ANX.Framework.Content.Pipeline/ANX.Framework.Content.Pipeline_WindowsMetro.csproj @@ -19,7 +19,7 @@ true full false - bin\Debug\ + bin\Debug\ModernUI TRACE;DEBUG;WINDOWSMETRO; prompt 4 @@ -28,7 +28,7 @@ pdbonly true - bin\Release\ + bin\Release\ModernUI TRACE;WINDOWSMETRO; prompt 4 @@ -38,6 +38,7 @@ + diff --git a/ANX.Framework.ContentPipeline/ANX.Framework.ContentPipeline.Extensions_WindowsMetro.csproj b/ANX.Framework.ContentPipeline/ANX.Framework.ContentPipeline.Extensions_WindowsMetro.csproj index 914f2e32..14d01d18 100644 --- a/ANX.Framework.ContentPipeline/ANX.Framework.ContentPipeline.Extensions_WindowsMetro.csproj +++ b/ANX.Framework.ContentPipeline/ANX.Framework.ContentPipeline.Extensions_WindowsMetro.csproj @@ -17,7 +17,7 @@ true full false - ..\bin\Debug\ + ..\bin\Debug\ModernUI XNAEXT;DEBUG;TRACE;WINDOWSMETRO; prompt 4 @@ -26,7 +26,7 @@ pdbonly true - ..\bin\Release\ + ..\bin\Release\ModernUI XNAEXT;TRACE;WINDOWSMETRO; prompt 4 diff --git a/ANX.Framework.TestCenter/ANX.Framework.TestCenter_Linux.csproj b/ANX.Framework.TestCenter/ANX.Framework.TestCenter_Linux.csproj index 0dc61df7..6d5bde0f 100644 --- a/ANX.Framework.TestCenter/ANX.Framework.TestCenter_Linux.csproj +++ b/ANX.Framework.TestCenter/ANX.Framework.TestCenter_Linux.csproj @@ -62,6 +62,7 @@ + diff --git a/ANX.Framework.TestCenter/ANX.Framework.TestCenter_PSVita.csproj b/ANX.Framework.TestCenter/ANX.Framework.TestCenter_PSVita.csproj index 7b9a6ca3..78fda1c3 100644 --- a/ANX.Framework.TestCenter/ANX.Framework.TestCenter_PSVita.csproj +++ b/ANX.Framework.TestCenter/ANX.Framework.TestCenter_PSVita.csproj @@ -63,6 +63,7 @@ + diff --git a/ANX.Framework.TestCenter/ANX.Framework.TestCenter_WindowsMetro.csproj b/ANX.Framework.TestCenter/ANX.Framework.TestCenter_WindowsMetro.csproj index b1c019fd..35b23ef0 100644 --- a/ANX.Framework.TestCenter/ANX.Framework.TestCenter_WindowsMetro.csproj +++ b/ANX.Framework.TestCenter/ANX.Framework.TestCenter_WindowsMetro.csproj @@ -19,7 +19,7 @@ true full false - ..\bin\Debug\ + ..\bin\Debug\ModernUI TRACE;DEBUG;WINDOWSMETRO; prompt 4 @@ -28,7 +28,7 @@ pdbonly true - ..\bin\Release\ + ..\bin\Release\ModernUI TRACE;WINDOWSMETRO; prompt 4 @@ -64,6 +64,7 @@ + @@ -131,10 +132,6 @@ {6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35} ANX.Framework - - {60D08399-244F-46A3-91F1-4CFD26D961A3} - ANX.InputDevices.Windows.XInput - {49066074-3B7B-4A55-B122-6BD33AB73558} ANX.InputSystem.Standard diff --git a/ANX.Framework.sln b/ANX.Framework.sln index c7304283..50486112 100644 --- a/ANX.Framework.sln +++ b/ANX.Framework.sln @@ -197,6 +197,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.InputDevices.Windows.Mo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnlineStatusGenerator", "Tools\OnlineStatusGenerator\OnlineStatusGenerator.csproj", "{6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OggUtils", "Support\OggUtils\OggUtils.csproj", "{ABECEC14-6BF4-4432-833C-69714EB4E8E6}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleNoContent", "Samples\SimpleNoContent\SimpleNoContent.csproj", "{AA3DF4D7-F072-47B5-B88C-20140B5F704A}" EndProject Global @@ -998,6 +1000,20 @@ Global {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x64.ActiveCfg = Release|x86 {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x86.ActiveCfg = Release|x86 {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x86.Build.0 = Release|x86 + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|x64.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|x86.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Any CPU.Build.0 = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|ARM.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|x64.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|x86.ActiveCfg = Release|Any CPU {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Any CPU.Build.0 = Debug|Any CPU {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -1073,6 +1089,7 @@ Global {2B6D0EFF-7874-495F-9226-873ED9649C60} = {1436F7C9-29D3-4FEF-8914-10B45F13D142} {2CF3FE4D-586E-4B07-8BF0-1E84B670F0AD} = {1436F7C9-29D3-4FEF-8914-10B45F13D142} {1986B0ED-3D28-4FEE-82D0-BCC39C87C18C} = {3E29A6C6-9487-46A7-A161-D8DB84514933} + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} = {3E29A6C6-9487-46A7-A161-D8DB84514933} EndGlobalSection GlobalSection(SubversionScc) = preSolution Svn-Managed = True diff --git a/ANX.Framework/ANX.Framework.csproj b/ANX.Framework/ANX.Framework.csproj index c33deda5..74a11c0b 100644 --- a/ANX.Framework/ANX.Framework.csproj +++ b/ANX.Framework/ANX.Framework.csproj @@ -98,6 +98,7 @@ + diff --git a/ANX.Framework/ANX.Framework_Linux.csproj b/ANX.Framework/ANX.Framework_Linux.csproj index d722cdfd..c107ea52 100644 --- a/ANX.Framework/ANX.Framework_Linux.csproj +++ b/ANX.Framework/ANX.Framework_Linux.csproj @@ -98,6 +98,7 @@ + @@ -445,7 +446,9 @@ + + diff --git a/ANX.Framework/ANX.Framework_PSVita.csproj b/ANX.Framework/ANX.Framework_PSVita.csproj index 95e7c57d..e03ef844 100644 --- a/ANX.Framework/ANX.Framework_PSVita.csproj +++ b/ANX.Framework/ANX.Framework_PSVita.csproj @@ -100,6 +100,7 @@ + @@ -447,7 +448,9 @@ + + diff --git a/ANX.Framework/ANX.Framework_WindowsMetro.csproj b/ANX.Framework/ANX.Framework_WindowsMetro.csproj index 895552f8..9aaf8807 100644 --- a/ANX.Framework/ANX.Framework_WindowsMetro.csproj +++ b/ANX.Framework/ANX.Framework_WindowsMetro.csproj @@ -101,6 +101,7 @@ + diff --git a/ANX.Framework/Content/ContentManager.cs b/ANX.Framework/Content/ContentManager.cs index b6dc7348..bfa9ed37 100644 --- a/ANX.Framework/Content/ContentManager.cs +++ b/ANX.Framework/Content/ContentManager.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using ANX.Framework.NonXNA; using ANX.Framework.NonXNA.PlatformSystem; // This file is part of the ANX.Framework created by the diff --git a/ANX.Framework/Content/ContentReader.cs b/ANX.Framework/Content/ContentReader.cs index ce64d37d..1b535369 100644 --- a/ANX.Framework/Content/ContentReader.cs +++ b/ANX.Framework/Content/ContentReader.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Reflection; using ANX.Framework.Graphics; using ANX.Framework.NonXNA.Reflection; @@ -463,5 +464,27 @@ namespace ANX.Framework.Content } return device; } + + internal string GetAbsolutePathToReference(string referenceName) + { + referenceName = GetPathToReference(referenceName); + referenceName = Path.Combine(ContentManager.RootDirectory, referenceName); + + Assembly assembly = Assembly.GetEntryAssembly(); + if (assembly == null) + assembly = Assembly.GetCallingAssembly(); + string titleLocationPath = Path.GetDirectoryName(assembly.Location); + referenceName = Path.Combine(titleLocationPath, referenceName); + return TitleContainer.GetCleanPath(referenceName); + } + + private string GetPathToReference(string referenceName) + { + int num = AssetName.LastIndexOfAny(new[] { '\\', '/', Path.DirectorySeparatorChar }); + string path = ""; + if (num != -1) + path = AssetName.Substring(0, num); + return Path.Combine(path, referenceName); + } } } diff --git a/ANX.Framework/Content/MediaTypeReaders/SongReader.cs b/ANX.Framework/Content/MediaTypeReaders/SongReader.cs new file mode 100644 index 00000000..094f6f95 --- /dev/null +++ b/ANX.Framework/Content/MediaTypeReaders/SongReader.cs @@ -0,0 +1,23 @@ +using ANX.Framework.Media; +using ANX.Framework.NonXNA.Development; + +// This file is part of the ANX.Framework created by the +// "ANX.Framework developer group" and released under the Ms-PL license. +// For details see: http://anxframework.codeplex.com/license + +namespace ANX.Framework.Content +{ + [PercentageComplete(100)] + [Developer("AstrorEnales")] + [TestState(TestStateAttribute.TestState.Untested)] + internal class SongReader : ContentTypeReader + { + protected internal override Song Read(ContentReader input, Song existingInstance) + { + string text = input.ReadString(); + text = input.GetAbsolutePathToReference(text); + int duration = input.ReadObject(); + return new Song(input.AssetName, text, duration); + } + } +} diff --git a/ANX.Framework/Content/MediaTypeReaders/SoundEffectReader.cs b/ANX.Framework/Content/MediaTypeReaders/SoundEffectReader.cs index 928f456d..24053a86 100644 --- a/ANX.Framework/Content/MediaTypeReaders/SoundEffectReader.cs +++ b/ANX.Framework/Content/MediaTypeReaders/SoundEffectReader.cs @@ -2,9 +2,17 @@ using System.IO; using System.Runtime.InteropServices; using ANX.Framework.Audio; +using ANX.Framework.NonXNA.Development; + +// This file is part of the ANX.Framework created by the +// "ANX.Framework developer group" and released under the Ms-PL license. +// For details see: http://anxframework.codeplex.com/license namespace ANX.Framework.Content { + [PercentageComplete(100)] + [Developer("AstrorEnales")] + [TestState(TestStateAttribute.TestState.InProgress)] internal class SoundEffectReader : ContentTypeReader { private struct WaveFormatEx diff --git a/ANX.Framework/Media/MediaLibrary.cs b/ANX.Framework/Media/MediaLibrary.cs index 6de353bc..d614414b 100644 --- a/ANX.Framework/Media/MediaLibrary.cs +++ b/ANX.Framework/Media/MediaLibrary.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using ANX.Framework.NonXNA.Development; using ANX.Framework.NonXNA.PlatformSystem; // This file is part of the ANX.Framework created by the @@ -8,6 +9,9 @@ using ANX.Framework.NonXNA.PlatformSystem; namespace ANX.Framework.Media { + [PercentageComplete(100)] + [Developer("AstrorEnales")] + [TestState(TestStateAttribute.TestState.Untested)] public sealed class MediaLibrary : IDisposable { private INativeMediaLibrary nativeLibrary; diff --git a/ANX.Framework/Media/MediaPlayer.cs b/ANX.Framework/Media/MediaPlayer.cs index faf4a937..b6e92fc8 100644 --- a/ANX.Framework/Media/MediaPlayer.cs +++ b/ANX.Framework/Media/MediaPlayer.cs @@ -8,8 +8,8 @@ using ANX.Framework.NonXNA.Development; namespace ANX.Framework.Media { [PercentageComplete(100)] - [TestState(TestStateAttribute.TestState.Untested)] [Developer("AstrorEnales")] + [TestState(TestStateAttribute.TestState.Untested)] public static class MediaPlayer { #region Events @@ -61,7 +61,8 @@ namespace ANX.Framework.Media return; currentState = value; - MediaStateChanged(null, EventArgs.Empty); + if (MediaStateChanged != null) + MediaStateChanged(null, EventArgs.Empty); } } @@ -157,6 +158,8 @@ namespace ANX.Framework.Media return; } + Queue.ActiveSong.NativeSong.Update(); + State = Queue.ActiveSong.State; if (Queue.ActiveSong.State != MediaState.Stopped) return; @@ -164,7 +167,8 @@ namespace ANX.Framework.Media if (Queue.MoveNext(isRepeating)) State = MediaState.Playing; - ActiveSongChanged(null, EventArgs.Empty); + if (ActiveSongChanged != null) + ActiveSongChanged(null, EventArgs.Empty); } #endregion diff --git a/ANX.Framework/Media/MediaQueue.cs b/ANX.Framework/Media/MediaQueue.cs index 28e23d50..31b166f6 100644 --- a/ANX.Framework/Media/MediaQueue.cs +++ b/ANX.Framework/Media/MediaQueue.cs @@ -144,7 +144,7 @@ namespace ANX.Framework.Media } #region MoveNext - internal bool MoveNext(bool stopIfEnded) + internal bool MoveNext(bool isRepeating) { if (Count <= 0) return false; @@ -156,7 +156,7 @@ namespace ANX.Framework.Media else { ActiveSongIndex = 0; - if (stopIfEnded) + if (isRepeating == false) return false; } diff --git a/ANX.Framework/Media/Song.cs b/ANX.Framework/Media/Song.cs index 99ca374c..534fb66b 100644 --- a/ANX.Framework/Media/Song.cs +++ b/ANX.Framework/Media/Song.cs @@ -89,12 +89,21 @@ namespace ANX.Framework.Media #region Constructor internal Song(string setName, Uri uri) - { - NativeSong = AddInSystemFactory.Instance.GetDefaultCreator().CreateSong(this, uri); + { + var creator = AddInSystemFactory.Instance.GetDefaultCreator(); + NativeSong = creator.CreateSong(this, uri); Name = setName; IsDisposed = false; } + internal Song(string setName, string filename, int duration) + { + var creator = AddInSystemFactory.Instance.GetDefaultCreator(); + NativeSong = creator.CreateSong(this, filename, duration); + Name = setName; + IsDisposed = false; + } + ~Song() { Dispose(); @@ -108,15 +117,15 @@ namespace ANX.Framework.Media public bool Equals(Song other) { - throw new NotImplementedException(); + return other != null && Name == other.Name; } public override bool Equals(object obj) { - if (obj is Song) - return Equals(obj as Song); + if (ReferenceEquals(this, obj) == false) + return Equals((Song)obj); - return base.Equals(obj); + return base.Equals(obj); } public void Dispose() @@ -167,13 +176,13 @@ namespace ANX.Framework.Media #region Operator overloading public static bool operator ==(Song first, Song second) - { - return first != null && first.Equals(second); + { + return object.Equals(first, second); } public static bool operator !=(Song first, Song second) - { - return first == null || first.Equals(second) == false; + { + return !(first == second); } #endregion } diff --git a/ANX.Framework/NonXNA/SoundSystem/ISoundSystemCreator.cs b/ANX.Framework/NonXNA/SoundSystem/ISoundSystemCreator.cs index df710dad..47ff7210 100644 --- a/ANX.Framework/NonXNA/SoundSystem/ISoundSystemCreator.cs +++ b/ANX.Framework/NonXNA/SoundSystem/ISoundSystemCreator.cs @@ -36,6 +36,7 @@ namespace ANX.Framework.NonXNA.SoundSystem int GetDefaultMicrophone(ReadOnlyCollection allMicrophones); ISong CreateSong(Song parentSong, Uri uri); + ISong CreateSong(Song parentSong, string filepath, int duration); IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance(); } diff --git a/ANX.Framework_Linux.sln b/ANX.Framework_Linux.sln index c2034465..949ebd2e 100644 --- a/ANX.Framework_Linux.sln +++ b/ANX.Framework_Linux.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2010 +# Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.Framework", "ANX.Framework\ANX.Framework_Linux.csproj", "{6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.Framework.TestCenter", "ANX.Framework.TestCenter\ANX.Framework.TestCenter_Linux.csproj", "{7344BBEB-A1C7-43A8-B68E-D42B81973DA9}" @@ -195,6 +195,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.RenderSystem.Windows.DX EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.InputDevices.Windows.ModernUI", "InputSystems\ANX.InputDevices.Windows.ModernUI\ANX.InputDevices.Windows.ModernUI_Linux.csproj", "{628AB80A-B1B9-4878-A810-7A58D4840F60}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnlineStatusGenerator", "Tools\OnlineStatusGenerator\OnlineStatusGenerator.csproj", "{6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OggUtils", "Support\OggUtils\OggUtils_Linux.csproj", "{ABECEC14-6BF4-4432-833C-69714EB4E8E6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleNoContent", "Samples\SimpleNoContent\SimpleNoContent_Linux.csproj", "{AA3DF4D7-F072-47B5-B88C-20140B5F704A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -980,6 +986,48 @@ Global {628AB80A-B1B9-4878-A810-7A58D4840F60}.Release|x64.Build.0 = Release|x64 {628AB80A-B1B9-4878-A810-7A58D4840F60}.Release|x86.ActiveCfg = Release|x86 {628AB80A-B1B9-4878-A810-7A58D4840F60}.Release|x86.Build.0 = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|Any CPU.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|ARM.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|x64.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|x86.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|x86.Build.0 = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|Any CPU.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|ARM.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|Mixed Platforms.Build.0 = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x64.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x86.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x86.Build.0 = Release|x86 + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|x64.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|x86.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Any CPU.Build.0 = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|ARM.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|x64.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|x86.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|x64.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|x86.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Any CPU.Build.0 = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|ARM.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|x64.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -995,6 +1043,7 @@ Global {938D5F88-B888-4B04-BEEE-EE701FBA51EF} = {B24A8593-562A-4A25-BB08-46C163F10F3F} {14B39F89-C9B0-407E-877A-B515C985E96E} = {B24A8593-562A-4A25-BB08-46C163F10F3F} {45DD7B40-C498-4DD2-A16B-FD6C4E6991B3} = {B24A8593-562A-4A25-BB08-46C163F10F3F} + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01} = {B24A8593-562A-4A25-BB08-46C163F10F3F} {B30DE9C2-0926-46B6-8351-9AF276C472D5} = {D421509A-9AE3-4D7E-881B-EAFED598B028} {FF0AB665-2796-4354-9630-76C2751DB3C2} = {D421509A-9AE3-4D7E-881B-EAFED598B028} {2B71A7C2-0D18-4E3D-AE5A-320641D1162A} = {D421509A-9AE3-4D7E-881B-EAFED598B028} @@ -1018,6 +1067,7 @@ Global {4A048A8C-C31D-4FC8-AAF3-C387B9E0309B} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} {9259CC4E-AE6B-403C-8FAB-2408448C3935} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} {D810F12D-6CE9-4755-AC6A-5DFEC7D1C782} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} + {AA3DF4D7-F072-47B5-B88C-20140B5F704A} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} {DB88DDEB-7281-405D-8FCA-5681B6B2BD7A} = {7AD65E6B-2A48-437F-81D9-4CA9C9A85C64} {49066074-3B7B-4A55-B122-6BD33AB73558} = {7AD65E6B-2A48-437F-81D9-4CA9C9A85C64} {60D08399-244F-46A3-91F1-4CFD26D961A3} = {7AD65E6B-2A48-437F-81D9-4CA9C9A85C64} @@ -1039,6 +1089,7 @@ Global {2B6D0EFF-7874-495F-9226-873ED9649C60} = {1436F7C9-29D3-4FEF-8914-10B45F13D142} {2CF3FE4D-586E-4B07-8BF0-1E84B670F0AD} = {1436F7C9-29D3-4FEF-8914-10B45F13D142} {1986B0ED-3D28-4FEE-82D0-BCC39C87C18C} = {3E29A6C6-9487-46A7-A161-D8DB84514933} + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} = {3E29A6C6-9487-46A7-A161-D8DB84514933} EndGlobalSection GlobalSection(SubversionScc) = preSolution Svn-Managed = True diff --git a/ANX.Framework_PSVita.sln b/ANX.Framework_PSVita.sln index e96ff06e..bc5b9e57 100644 --- a/ANX.Framework_PSVita.sln +++ b/ANX.Framework_PSVita.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2010 +# Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.Framework", "ANX.Framework\ANX.Framework_PSVita.csproj", "{6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.Framework.TestCenter", "ANX.Framework.TestCenter\ANX.Framework.TestCenter_PSVita.csproj", "{7344BBEB-A1C7-43A8-B68E-D42B81973DA9}" @@ -195,6 +195,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.RenderSystem.Windows.DX EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.InputDevices.Windows.ModernUI", "InputSystems\ANX.InputDevices.Windows.ModernUI\ANX.InputDevices.Windows.ModernUI_PSVita.csproj", "{628AB80A-B1B9-4878-A810-7A58D4840F60}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnlineStatusGenerator", "Tools\OnlineStatusGenerator\OnlineStatusGenerator.csproj", "{6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OggUtils", "Support\OggUtils\OggUtils_PSVita.csproj", "{ABECEC14-6BF4-4432-833C-69714EB4E8E6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleNoContent", "Samples\SimpleNoContent\SimpleNoContent_PSVita.csproj", "{AA3DF4D7-F072-47B5-B88C-20140B5F704A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -980,6 +986,48 @@ Global {628AB80A-B1B9-4878-A810-7A58D4840F60}.Release|x64.Build.0 = Release|x64 {628AB80A-B1B9-4878-A810-7A58D4840F60}.Release|x86.ActiveCfg = Release|x86 {628AB80A-B1B9-4878-A810-7A58D4840F60}.Release|x86.Build.0 = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|Any CPU.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|ARM.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|x64.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|x86.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|x86.Build.0 = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|Any CPU.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|ARM.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|Mixed Platforms.Build.0 = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x64.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x86.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x86.Build.0 = Release|x86 + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|x64.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|x86.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Any CPU.Build.0 = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|ARM.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|x64.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|x86.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|x64.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|x86.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Any CPU.Build.0 = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|ARM.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|x64.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -995,6 +1043,7 @@ Global {938D5F88-B888-4B04-BEEE-EE701FBA51EF} = {B24A8593-562A-4A25-BB08-46C163F10F3F} {14B39F89-C9B0-407E-877A-B515C985E96E} = {B24A8593-562A-4A25-BB08-46C163F10F3F} {45DD7B40-C498-4DD2-A16B-FD6C4E6991B3} = {B24A8593-562A-4A25-BB08-46C163F10F3F} + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01} = {B24A8593-562A-4A25-BB08-46C163F10F3F} {B30DE9C2-0926-46B6-8351-9AF276C472D5} = {D421509A-9AE3-4D7E-881B-EAFED598B028} {FF0AB665-2796-4354-9630-76C2751DB3C2} = {D421509A-9AE3-4D7E-881B-EAFED598B028} {2B71A7C2-0D18-4E3D-AE5A-320641D1162A} = {D421509A-9AE3-4D7E-881B-EAFED598B028} @@ -1018,6 +1067,7 @@ Global {4A048A8C-C31D-4FC8-AAF3-C387B9E0309B} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} {9259CC4E-AE6B-403C-8FAB-2408448C3935} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} {D810F12D-6CE9-4755-AC6A-5DFEC7D1C782} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} + {AA3DF4D7-F072-47B5-B88C-20140B5F704A} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} {DB88DDEB-7281-405D-8FCA-5681B6B2BD7A} = {7AD65E6B-2A48-437F-81D9-4CA9C9A85C64} {49066074-3B7B-4A55-B122-6BD33AB73558} = {7AD65E6B-2A48-437F-81D9-4CA9C9A85C64} {60D08399-244F-46A3-91F1-4CFD26D961A3} = {7AD65E6B-2A48-437F-81D9-4CA9C9A85C64} @@ -1039,6 +1089,7 @@ Global {2B6D0EFF-7874-495F-9226-873ED9649C60} = {1436F7C9-29D3-4FEF-8914-10B45F13D142} {2CF3FE4D-586E-4B07-8BF0-1E84B670F0AD} = {1436F7C9-29D3-4FEF-8914-10B45F13D142} {1986B0ED-3D28-4FEE-82D0-BCC39C87C18C} = {3E29A6C6-9487-46A7-A161-D8DB84514933} + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} = {3E29A6C6-9487-46A7-A161-D8DB84514933} EndGlobalSection GlobalSection(SubversionScc) = preSolution Svn-Managed = True diff --git a/ANX.Framework_WindowsMetro.sln b/ANX.Framework_WindowsMetro.sln index d6f50888..de35c027 100644 --- a/ANX.Framework_WindowsMetro.sln +++ b/ANX.Framework_WindowsMetro.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2010 +# Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.Framework", "ANX.Framework\ANX.Framework_WindowsMetro.csproj", "{6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.Framework.TestCenter", "ANX.Framework.TestCenter\ANX.Framework.TestCenter_WindowsMetro.csproj", "{7344BBEB-A1C7-43A8-B68E-D42B81973DA9}" @@ -195,6 +195,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.RenderSystem.Windows.DX EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ANX.InputDevices.Windows.ModernUI", "InputSystems\ANX.InputDevices.Windows.ModernUI\ANX.InputDevices.Windows.ModernUI_WindowsMetro.csproj", "{628AB80A-B1B9-4878-A810-7A58D4840F60}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnlineStatusGenerator", "Tools\OnlineStatusGenerator\OnlineStatusGenerator.csproj", "{6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OggUtils", "Support\OggUtils\OggUtils_WindowsMetro.csproj", "{ABECEC14-6BF4-4432-833C-69714EB4E8E6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleNoContent", "Samples\SimpleNoContent\SimpleNoContent_WindowsMetro.csproj", "{AA3DF4D7-F072-47B5-B88C-20140B5F704A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -980,6 +986,48 @@ Global {628AB80A-B1B9-4878-A810-7A58D4840F60}.Release|x64.Build.0 = Release|x64 {628AB80A-B1B9-4878-A810-7A58D4840F60}.Release|x86.ActiveCfg = Release|x86 {628AB80A-B1B9-4878-A810-7A58D4840F60}.Release|x86.Build.0 = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|Any CPU.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|ARM.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|x64.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|x86.ActiveCfg = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Debug|x86.Build.0 = Debug|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|Any CPU.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|ARM.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|Mixed Platforms.Build.0 = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x64.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x86.ActiveCfg = Release|x86 + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01}.Release|x86.Build.0 = Release|x86 + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|x64.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Debug|x86.ActiveCfg = Debug|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Any CPU.Build.0 = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|ARM.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|x64.ActiveCfg = Release|Any CPU + {ABECEC14-6BF4-4432-833C-69714EB4E8E6}.Release|x86.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|x64.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Debug|x86.ActiveCfg = Debug|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Any CPU.Build.0 = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|ARM.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|x64.ActiveCfg = Release|Any CPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -995,6 +1043,7 @@ Global {938D5F88-B888-4B04-BEEE-EE701FBA51EF} = {B24A8593-562A-4A25-BB08-46C163F10F3F} {14B39F89-C9B0-407E-877A-B515C985E96E} = {B24A8593-562A-4A25-BB08-46C163F10F3F} {45DD7B40-C498-4DD2-A16B-FD6C4E6991B3} = {B24A8593-562A-4A25-BB08-46C163F10F3F} + {6119ADEE-7047-4E29-BEC2-00F8D6D0EA01} = {B24A8593-562A-4A25-BB08-46C163F10F3F} {B30DE9C2-0926-46B6-8351-9AF276C472D5} = {D421509A-9AE3-4D7E-881B-EAFED598B028} {FF0AB665-2796-4354-9630-76C2751DB3C2} = {D421509A-9AE3-4D7E-881B-EAFED598B028} {2B71A7C2-0D18-4E3D-AE5A-320641D1162A} = {D421509A-9AE3-4D7E-881B-EAFED598B028} @@ -1018,6 +1067,7 @@ Global {4A048A8C-C31D-4FC8-AAF3-C387B9E0309B} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} {9259CC4E-AE6B-403C-8FAB-2408448C3935} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} {D810F12D-6CE9-4755-AC6A-5DFEC7D1C782} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} + {AA3DF4D7-F072-47B5-B88C-20140B5F704A} = {9B0DD48B-3912-4F33-AF3F-691AF02B73F9} {DB88DDEB-7281-405D-8FCA-5681B6B2BD7A} = {7AD65E6B-2A48-437F-81D9-4CA9C9A85C64} {49066074-3B7B-4A55-B122-6BD33AB73558} = {7AD65E6B-2A48-437F-81D9-4CA9C9A85C64} {60D08399-244F-46A3-91F1-4CFD26D961A3} = {7AD65E6B-2A48-437F-81D9-4CA9C9A85C64} @@ -1039,6 +1089,7 @@ Global {2B6D0EFF-7874-495F-9226-873ED9649C60} = {1436F7C9-29D3-4FEF-8914-10B45F13D142} {2CF3FE4D-586E-4B07-8BF0-1E84B670F0AD} = {1436F7C9-29D3-4FEF-8914-10B45F13D142} {1986B0ED-3D28-4FEE-82D0-BCC39C87C18C} = {3E29A6C6-9487-46A7-A161-D8DB84514933} + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} = {3E29A6C6-9487-46A7-A161-D8DB84514933} EndGlobalSection GlobalSection(SubversionScc) = preSolution Svn-Managed = True diff --git a/InputSystems/ANX.InputDevices.Windows.ModernUI/ANX.InputDevices.Windows.ModernUI_Linux.csproj b/InputSystems/ANX.InputDevices.Windows.ModernUI/ANX.InputDevices.Windows.ModernUI_Linux.csproj new file mode 100644 index 00000000..79438585 --- /dev/null +++ b/InputSystems/ANX.InputDevices.Windows.ModernUI/ANX.InputDevices.Windows.ModernUI_Linux.csproj @@ -0,0 +1,136 @@ + + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {628AB80A-B1B9-4878-A810-7A58D4840F60} + Library + Properties + ANX.InputDevices.Windows.ModernUI + ANX.InputDevices.Windows.ModernUI + de-DE + 512 + + + true + full + false + ..\..\bin\Debug\ + NETFX_CORE;TRACE;DEBUG;LINUX; + prompt + 4 + + + pdbonly + true + ..\..\bin\Release\ + NETFX_CORE;TRACE;LINUX; + prompt + 4 + + + true + bin\ARM\Debug\ + NETFX_CORE;TRACE;DEBUG;LINUX; + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + NETFX_CORE;TRACE;LINUX; + true + ;2008 + pdbonly + ARM + false + prompt + true + + + true + bin\x64\Debug\ + NETFX_CORE;TRACE;DEBUG;LINUX; + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + NETFX_CORE;TRACE;LINUX; + true + ;2008 + pdbonly + x64 + false + prompt + true + + + true + bin\x86\Debug\ + NETFX_CORE;TRACE;DEBUG;LINUX; + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + NETFX_CORE;TRACE;LINUX; + true + ;2008 + pdbonly + x86 + false + prompt + true + + + + + + + + + + + + + + + ..\..\lib\SharpDX\Bin\Win8Metro\SharpDX.dll + + + ..\..\lib\SharpDX\Bin\Win8Metro\SharpDX.XInput.dll + + + + + {6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35} + ANX.Framework + + + + 11.0 + + + + \ No newline at end of file diff --git a/InputSystems/ANX.InputDevices.Windows.ModernUI/ANX.InputDevices.Windows.ModernUI_PSVita.csproj b/InputSystems/ANX.InputDevices.Windows.ModernUI/ANX.InputDevices.Windows.ModernUI_PSVita.csproj new file mode 100644 index 00000000..b0c83ea0 --- /dev/null +++ b/InputSystems/ANX.InputDevices.Windows.ModernUI/ANX.InputDevices.Windows.ModernUI_PSVita.csproj @@ -0,0 +1,138 @@ + + + + + Debug + AnyCPU + 10.0.0 + 2.0 + {628AB80A-B1B9-4878-A810-7A58D4840F60} + Library + Properties + ANX.InputDevices.Windows.ModernUI + ANX.InputDevices.Windows.ModernUI + de-DE + 512 + {69878862-DA7D-4DC6-B0A1-50D8FAB4242F};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + true + full + false + ..\..\bin\Debug\ + NETFX_CORE;TRACE;DEBUG;PSVITA; + prompt + 4 + + + pdbonly + true + ..\..\bin\Release\ + NETFX_CORE;TRACE;PSVITA; + prompt + 4 + + + true + bin\ARM\Debug\ + NETFX_CORE;TRACE;DEBUG;PSVITA; + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + NETFX_CORE;TRACE;PSVITA; + true + ;2008 + pdbonly + ARM + false + prompt + true + + + true + bin\x64\Debug\ + NETFX_CORE;TRACE;DEBUG;PSVITA; + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + NETFX_CORE;TRACE;PSVITA; + true + ;2008 + pdbonly + x64 + false + prompt + true + + + true + bin\x86\Debug\ + NETFX_CORE;TRACE;DEBUG;PSVITA; + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + NETFX_CORE;TRACE;PSVITA; + true + ;2008 + pdbonly + x86 + false + prompt + true + + + + + + + + + + + + + + + ..\..\lib\SharpDX\Bin\Win8Metro\SharpDX.dll + + + ..\..\lib\SharpDX\Bin\Win8Metro\SharpDX.XInput.dll + + + + + + {6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35} + ANX.Framework + + + + 11.0 + + + + \ No newline at end of file diff --git a/RenderSystems/ANX.Framework.GL3/ANX.RenderSystem.GL3_PSVita.csproj b/RenderSystems/ANX.Framework.GL3/ANX.RenderSystem.GL3_PSVita.csproj new file mode 100644 index 00000000..4cbc9428 --- /dev/null +++ b/RenderSystems/ANX.Framework.GL3/ANX.RenderSystem.GL3_PSVita.csproj @@ -0,0 +1,90 @@ + + + + Debug + AnyCPU + 10.0.0 + 2.0 + {EB8258E0-6741-4DB9-B756-1EBDF67B1ED6} + Library + Properties + ANX.RenderSystem.GL3 + ANX.RenderSystem.GL3 + 512 + {69878862-DA7D-4DC6-B0A1-50D8FAB4242F};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + true + full + false + ..\..\bin\Debug\ + XNAEXT;DEBUG;TRACE;PSVITA; + prompt + 4 + x86 + Auto + true + + + pdbonly + true + ..\bin\Release\ + XNAEXT;TRACE;PSVITA; + prompt + 4 + x86 + true + + + + ..\..\lib\OpenTK\OpenTK.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {6899f0c9-70b9-4eb0-9dd3-e598d4be3e35} + ANX.Framework + + + + + + + + \ No newline at end of file diff --git a/Samples/AudioSample/AudioSample_Linux.csproj b/Samples/AudioSample/AudioSample_Linux.csproj index 821552ed..bba3775b 100644 --- a/Samples/AudioSample/AudioSample_Linux.csproj +++ b/Samples/AudioSample/AudioSample_Linux.csproj @@ -89,6 +89,10 @@ {068EB2E9-963C-4E1B-8831-E25011F11FFE} ANX.PlatformSystem.Windows + + {5BE49183-2F6F-4527-AC90-D816911FCF90} + ANX.RenderSystem.Windows.DX10 + {14EF49AB-6D3F-458D-9D5C-D120B86EDD7A} ANX.SoundSystem.OpenAL diff --git a/Samples/AudioSample/AudioSample_PSVita.csproj b/Samples/AudioSample/AudioSample_PSVita.csproj index ac738f55..af1083aa 100644 --- a/Samples/AudioSample/AudioSample_PSVita.csproj +++ b/Samples/AudioSample/AudioSample_PSVita.csproj @@ -92,6 +92,10 @@ {068EB2E9-963C-4E1B-8831-E25011F11FFE} ANX.PlatformSystem.Windows + + {5BE49183-2F6F-4527-AC90-D816911FCF90} + ANX.RenderSystem.Windows.DX10 + {14EF49AB-6D3F-458D-9D5C-D120B86EDD7A} ANX.SoundSystem.OpenAL diff --git a/Samples/AudioSample/Game1.cs b/Samples/AudioSample/Game1.cs index 2d35a5b8..959855c9 100644 --- a/Samples/AudioSample/Game1.cs +++ b/Samples/AudioSample/Game1.cs @@ -1,5 +1,9 @@ +using System.IO; using ANX.Framework; using ANX.Framework.Audio; +using ANX.Framework.Media; +using System; +using ANX.Framework.Input; // This file is part of the ANX.Framework created by the // "ANX.Framework developer group" and released under the Ms-PL license. @@ -11,9 +15,12 @@ namespace AudioSample { private GraphicsDeviceManager graphics; private SoundEffect sound; + private Song song; private float timer; private float duration; + private const bool UseMusicPlayback = false; + public Game1() { graphics = new GraphicsDeviceManager(this); @@ -23,6 +30,8 @@ namespace AudioSample protected override void LoadContent() { sound = Content.Load("Sounds\\testsound"); + string testmusicPath = Path.GetFullPath("../../../../../media/testmusic.ogg"); + song = Song.FromUri(testmusicPath, new Uri(testmusicPath)); timer = duration = (float)sound.Duration.TotalSeconds; } @@ -36,7 +45,21 @@ namespace AudioSample if (timer >= duration) { timer -= duration; - sound.Play(1f, 1f, 0f); + if (UseMusicPlayback) + MediaPlayer.Play(song); + else + sound.Play(1f, 1f, 0f); + } + + if (UseMusicPlayback) + { + Window.Title = "PlayTime = " + MediaPlayer.PlayPosition; + + if (Keyboard.GetState().IsKeyDown(Keys.A)) + MediaPlayer.Pause(); + + if (Keyboard.GetState().IsKeyDown(Keys.S)) + MediaPlayer.Resume(); } base.Update(gameTime); diff --git a/Samples/SimpleNoContent/Assets/Logo.png b/Samples/SimpleNoContent/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ab28e66b22fe17ad5d356febc433704132f40284 GIT binary patch literal 5379 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 B6=DDY literal 0 HcmV?d00001 diff --git a/Samples/SimpleNoContent/Assets/SmallLogo.png b/Samples/SimpleNoContent/Assets/SmallLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c4a32ab037b8369cf919b3615e7ddfcc23ab4538 GIT binary patch literal 558 zcmV+}0@3}6P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv00046 z7R-1ocE#sg5o80<5(qwhK&8cS<=A|zipRG#cq|1PYEQsogfp>OOhEG+T)BV;kAqQy z8Anjp60rC=P~UYRJ_f{Ffp{qpPXXelIy@EwEKbA|%z^lW8CO8y7l&HRNWix} zAX82?3jhB)R~(GbwFtwqh%rnIoxa^8g1gRzTKtKaU`93==#GmZ$MA77z#W5bF;Myu zPH%%O29>|KEEYrr^IbHH!Diy}El3=1Sc5Fal`uf!K+QrR1Fm)m|Nk^w42*Y`3&IR# wg^8il^V9eUTRhsJr$-13Z1a{LK18F_N+u!(#~{-fz+KzUMvt`}^Z}&U4P!ab{fZ`?|0DbFJS`qM4}?HY``CeRB9G7a1HV`UER6J6s=9^003Y_cpEWtl!h*lOe-pt5eCE7% z-Y$TJg@^p}hqc|e%nkTbFwg)VXz7az3`Y20Widl|`UIXdHLw!L!cMB3R8mx2_Ag*z zkzF^|KWi1@#LVHW6|sI0H`7E7*duU9LYZsNJ*a_ra$IO`GN;7f2*ZPl%Dm$5^7m#L z?q$=@=ev*96ZS(4k+|PHDx~w6lv<1b4XV*c9e1(#F@Mqe>m+CM1q-sabsm}-)M(sP zZn?2-%G}N_*Wjc02_G6~VR!lcY$`|Fk!xPEfLnK-=m7SEuj_S_v70H_UUtlmTse}3 z9EZ5U3XR@4;%pIax4=gk;2W_Dzvx#ts)?JI zX)b+cyAVM+0MW77)L*cq^gvpywDREXs#McJSNUKOJLeO_UDb#UBwt9Yb6^~Yc&X8VA2WRCDg)bd6^EODkCCni(TMZ;>w zZ<~cXAf{HiDYksrIcKYIC%?v*i>{#!c8Gd{aO5RKC~?z1x7sZHJVG#B7jOB#;+j^~ zWySo9Y{vPLKvua=iN_TI2dH!(&K_+WXtF!iXAQhG9}Y(`MR==U+Rd| zNh`++c={$|+jo1IgvT)FyG>VIHwZr%O0#h6B~22M%y7kMo<(4Ysty}WtrQD-=%6~I zo)J3q-9c1NEKTUm-H93T*omG+4|U=P``lG4_(%EeOm>r7-v*@1p|a4j+?baq`x9)N zLdLVR2fCucgDkOH)>CO2!>W#+H19jO=NWi;NFT4I%ZZoC@pC~~@cu)FJPqI>^PqtC zh58lZT_BqhWPxPxgc_Zk@f=>vnbW;wCF|qK)4$#1rwnt2>3oqpTp|ayT(Q>}OfKk3 zxG?hwr-YG9%Z8o6`>@-5*SivYLtQ(Eo&Bq;F2z1rNpko>lFf%X;ZnWkqL--dS(4~v zMW}j>!=pr{ZJ8g{&09uuLpfo)yZ%tV^I^Sz%qpkuh$bcM@0YnZMro)eu)T9%69Pq_ zL<%x6g1s%;KQ@}oBuyhm?}Yi!$FOF=!tS=F#ZN_wo2Gec1>Ij*tCXf)gqr+7i@JDv?Mb8&5r5vlJN=vj*sMaD23R+OJ1Zhmilox- z9b=7p&&UEf=&C7s2Zu=8*MdOrZP=w~5HvJ8h7VkJdg!lWVE>`7Yw1MnRBN;LT_|Y~ zBY!Vjjs5L!J$2(*f6P~MZJZ9BBIy4V%b&rPDJi|Y__k04T1NVh6tiz=``T-xkWJ z|60r^6z?OumK}_J`_PQCk;v> z*K60Vu1Bvl*S6OXL$I;k(@$VFmGNAQM{o}@oVQbzyrHCfwRo z%Tbsgz#mkh9?~G0wvk#pNaaL~odkz0ln#S=*I8;QT~_=Q&x#AWn52@^d-<=5bNdBU z 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 literal 0 HcmV?d00001 diff --git a/Samples/SimpleNoContent/Assets/StoreLogo.png b/Samples/SimpleNoContent/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..55690e2837c12a9d74085bd6351def5f7ba6d8a0 GIT binary patch literal 1059 zcmV+;1l;?HP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000A$NklOsYeBKikB3PA*K;!zKZf)_og7YVq=UE8nn z-h^JK`)lc>8M@#*On1Gi_f^%a_g;@-nx@eRXb2LLh?Gdu$}!DInvs~gWLjE@EG^^z zWEzI|1NSrN=0yMx%nC3am;uZJx`5fh9H1MR2lN2*frY>#UQbE17{}?s}vEnA+pk97{4ZR@>buN`|~J7a#Au$A#qY=0~JYT zB%2@-5=>cBW7R~IR_}>~5dn#3G?7xmNJvINVg*a2X>SA~hn2G*z&&6$a2~ke1?fJ_ z+LIP+Yf>Rg>jmRPbXO`z%R_d=b|KC9fZfkD5jI-;6^UgbNr>80hJ?=aRF+8BaWY!c z-3Ss!D`{VLeV6^9(!#OhCljqR%E?-SNbv|s1h${hMA)+GQ$&!I&@#vb>X@>RW0pe# zGP0R*BD!)IECW*jDH%CLP6nER0+0jbaEWRB0fyy0<3kRZo*@b#@|AHi9=ag$kS5Yg zMk{V2di`Oodq|y(?1+0}tbKj=@Lqg%hjf?g9rqVg&T7&G+JO$BO4=V#_S;w@bXhg|brT=Y(!H1r$`#j_guL*|2I!fkaO zIbNnQR3&^Y55!K=&o%L%yH{ z+IJGcYNBda6ImVT$f6*hco-rWdN) zALH`gN(46*D&@Lcp;DBTCS}Z-<*W;Mb=^Ydt(T79Gkw4ej)jFtZVySsab)NjzE&|u zZdGk~b-BaVaSm)Kx^$dlYQMkStjgGZ!7QL*A@V3fSq)j7y!V<=K5OeZr8ieQLle0( zP!=LMB!rL}5xFlgL=Yxhq>pZDaZON1^onH~-~6KQ^&I0yLQqgDnn*YMF&bg|ZE>>Z z!wq*?4IOH;ZIqp*Oz3O~G1%Y55_!O6Lv-QbQq4(o-uUYk(L!$Yn^sLKUS$0;bgr*8 zcoVd;)ESXMENo_c#v{>Va*_1$F?2R+rIoaQpQ6ks{SPrp)Z!eIW+cw&MzNh{Budoc d9Mdov`3Ie$SuqvB&6)rJ002ovPDHLkV1mLB&aD6d literal 0 HcmV?d00001 diff --git a/Samples/SimpleNoContent/Manifest.appxmanifest b/Samples/SimpleNoContent/Manifest.appxmanifest new file mode 100644 index 00000000..e2b4fa18 --- /dev/null +++ b/Samples/SimpleNoContent/Manifest.appxmanifest @@ -0,0 +1,27 @@ + + + + + SimpleNoContent + ANX Developer Team + Assets\StoreLogo.png + + + 6.2.0 + 6.2.0 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/SimpleNoContent/SimpleNoContent.csproj b/Samples/SimpleNoContent/SimpleNoContent.csproj index e7c77924..90408b8e 100644 --- a/Samples/SimpleNoContent/SimpleNoContent.csproj +++ b/Samples/SimpleNoContent/SimpleNoContent.csproj @@ -1,6 +1,5 @@  - Debug AnyCPU diff --git a/Samples/SimpleNoContent/SimpleNoContent_Linux.csproj b/Samples/SimpleNoContent/SimpleNoContent_Linux.csproj new file mode 100644 index 00000000..25cc5986 --- /dev/null +++ b/Samples/SimpleNoContent/SimpleNoContent_Linux.csproj @@ -0,0 +1,87 @@ + + + + Debug + AnyCPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A} + Exe + Properties + SimpleNoContent + SimpleNoContent + v4.0 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + TRACE;DEBUG;LINUX; + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE;LINUX; + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + {6899f0c9-70b9-4eb0-9dd3-e598d4be3e35} + ANX.Framework + + + {60d08399-244f-46a3-91f1-4cfd26d961a3} + ANX.InputDevices.Windows.XInput + + + {49066074-3b7b-4a55-b122-6bd33ab73558} + ANX.InputSystem.Standard + + + {068eb2e9-963c-4e1b-8831-e25011f11ffe} + ANX.PlatformSystem.Windows + + + {b30de9c2-0926-46b6-8351-9af276c472d5} + ANX.RenderSystem.Windows.DX11 + + + {6a582788-c4d2-410c-96cd-177f75712d65} + ANX.SoundSystem.Windows.XAudio + + + + + \ No newline at end of file diff --git a/Samples/SimpleNoContent/SimpleNoContent_PSVita.csproj b/Samples/SimpleNoContent/SimpleNoContent_PSVita.csproj new file mode 100644 index 00000000..80c0ee70 --- /dev/null +++ b/Samples/SimpleNoContent/SimpleNoContent_PSVita.csproj @@ -0,0 +1,90 @@ + + + + Debug + AnyCPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A} + Exe + Properties + SimpleNoContent + SimpleNoContent + 512 + {69878862-DA7D-4DC6-B0A1-50D8FAB4242F};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0.0 + 2.0 + + + AnyCPU + true + full + false + bin\Debug\ + TRACE;DEBUG;PSVITA; + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE;PSVITA; + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + {6899f0c9-70b9-4eb0-9dd3-e598d4be3e35} + ANX.Framework + + + {60d08399-244f-46a3-91f1-4cfd26d961a3} + ANX.InputDevices.Windows.XInput + + + {49066074-3b7b-4a55-b122-6bd33ab73558} + ANX.InputSystem.Standard + + + {068eb2e9-963c-4e1b-8831-e25011f11ffe} + ANX.PlatformSystem.Windows + + + {b30de9c2-0926-46b6-8351-9af276c472d5} + ANX.RenderSystem.Windows.DX11 + + + {6a582788-c4d2-410c-96cd-177f75712d65} + ANX.SoundSystem.Windows.XAudio + + + + + \ No newline at end of file diff --git a/Samples/SimpleNoContent/SimpleNoContent_WindowsMetro.csproj b/Samples/SimpleNoContent/SimpleNoContent_WindowsMetro.csproj new file mode 100644 index 00000000..78a34946 --- /dev/null +++ b/Samples/SimpleNoContent/SimpleNoContent_WindowsMetro.csproj @@ -0,0 +1,91 @@ + + + + Debug + AnyCPU + {AA3DF4D7-F072-47B5-B88C-20140B5F704A} + AppContainerExe + Properties + SimpleNoContent + SimpleNoContent + 512 + {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + en-US + Test_TemporaryKey.pfx + + + AnyCPU + true + full + false + bin\Debug\ModernUI + TRACE;DEBUG;WINDOWSMETRO; + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ModernUI + TRACE;WINDOWSMETRO; + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + {6899f0c9-70b9-4eb0-9dd3-e598d4be3e35} + ANX.Framework + + + {49066074-3b7b-4a55-b122-6bd33ab73558} + ANX.InputSystem.Standard + + + {6a582788-c4d2-410c-96cd-177f75712d65} + ANX.SoundSystem.Windows.XAudio + + + + + + + + Designer + + + + + + + + 11.0 + + + \ No newline at end of file diff --git a/Samples/WpfEditor/WpfEditor_Linux.csproj b/Samples/WpfEditor/WpfEditor_Linux.csproj index 522ffcfd..2afffd48 100644 --- a/Samples/WpfEditor/WpfEditor_Linux.csproj +++ b/Samples/WpfEditor/WpfEditor_Linux.csproj @@ -105,6 +105,10 @@ {49066074-3B7B-4A55-B122-6BD33AB73558} ANX.InputSystem.Standard + + {EB8258E0-6741-4DB9-B756-1EBDF67B1ED6} + ANX.RenderSystem.GL3 + {5BE49183-2F6F-4527-AC90-D816911FCF90} ANX.RenderSystem.Windows.DX10 diff --git a/Samples/WpfEditor/WpfEditor_PSVita.csproj b/Samples/WpfEditor/WpfEditor_PSVita.csproj index 61034276..e1654dae 100644 --- a/Samples/WpfEditor/WpfEditor_PSVita.csproj +++ b/Samples/WpfEditor/WpfEditor_PSVita.csproj @@ -106,6 +106,10 @@ {49066074-3B7B-4A55-B122-6BD33AB73558} ANX.InputSystem.Standard + + {EB8258E0-6741-4DB9-B756-1EBDF67B1ED6} + ANX.RenderSystem.GL3 + {5BE49183-2F6F-4527-AC90-D816911FCF90} ANX.RenderSystem.Windows.DX10 diff --git a/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL.csproj b/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL.csproj index 9a52c707..f51aab4a 100644 --- a/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL.csproj +++ b/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL.csproj @@ -42,6 +42,7 @@ + @@ -52,6 +53,10 @@ {6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35} ANX.Framework + + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} + OggUtils + {1986B0ED-3D28-4FEE-82D0-BCC39C87C18C} WaveUtils diff --git a/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_Linux.csproj b/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_Linux.csproj index 99308950..af188c1b 100644 --- a/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_Linux.csproj +++ b/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_Linux.csproj @@ -42,6 +42,7 @@ + @@ -52,6 +53,10 @@ {6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35} ANX.Framework + + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} + OggUtils + {1986B0ED-3D28-4FEE-82D0-BCC39C87C18C} WaveUtils diff --git a/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_PSVita.csproj b/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_PSVita.csproj index 3aac1509..1ad2c24c 100644 --- a/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_PSVita.csproj +++ b/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_PSVita.csproj @@ -43,6 +43,7 @@ + @@ -53,6 +54,10 @@ {6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35} ANX.Framework + + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} + OggUtils + {1986B0ED-3D28-4FEE-82D0-BCC39C87C18C} WaveUtils diff --git a/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_WindowsMetro.csproj b/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_WindowsMetro.csproj index 4068f21e..198fa608 100644 --- a/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_WindowsMetro.csproj +++ b/SoundSystems/ANX.SoundSystem.OpenAL/ANX.SoundSystem.OpenAL_WindowsMetro.csproj @@ -44,6 +44,7 @@ + @@ -54,6 +55,10 @@ {6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35} ANX.Framework + + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} + OggUtils + {1986B0ED-3D28-4FEE-82D0-BCC39C87C18C} WaveUtils diff --git a/SoundSystems/ANX.SoundSystem.OpenAL/Creator.cs b/SoundSystems/ANX.SoundSystem.OpenAL/Creator.cs index 7fc76947..17dcb135 100644 --- a/SoundSystems/ANX.SoundSystem.OpenAL/Creator.cs +++ b/SoundSystems/ANX.SoundSystem.OpenAL/Creator.cs @@ -162,7 +162,13 @@ namespace ANX.SoundSystem.OpenAL public ISong CreateSong(Song parentSong, Uri uri) { PreventSystemChange(); - throw new NotImplementedException(); + return new OpenALSong(parentSong, uri); + } + + public ISong CreateSong(Song parentSong, string filepath, int duration) + { + PreventSystemChange(); + return new OpenALSong(parentSong, filepath, duration); } public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance() diff --git a/SoundSystems/ANX.SoundSystem.OpenAL/OpenALSong.cs b/SoundSystems/ANX.SoundSystem.OpenAL/OpenALSong.cs new file mode 100644 index 00000000..ae41779a --- /dev/null +++ b/SoundSystems/ANX.SoundSystem.OpenAL/OpenALSong.cs @@ -0,0 +1,179 @@ +using System; +using System.IO; +using ANX.Framework.Audio; +using ANX.Framework.Media; +using ANX.Framework.NonXNA.Development; +using ANX.Framework.NonXNA.SoundSystem; +using OggUtils; +using OpenTK.Audio.OpenAL; + +// This file is part of the ANX.Framework created by the +// "ANX.Framework developer group" and released under the Ms-PL license. +// For details see: http://anxframework.codeplex.com/license + +namespace ANX.SoundSystem.OpenAL +{ + [Developer("AstrorEnales")] + public class OpenALSong : ISong + { + private Song parent; + private FileStream oggFileStream; + private OggInputStream oggStream; + private int[] bufferHandles; + private int sourceHandle = InvalidHandle; + private const int InvalidHandle = -1; + private static readonly byte[] streamReadBuffer = new byte[4096 * 8]; + + public TimeSpan Duration { get; private set; } + public TimeSpan PlayPosition { get; private set; } + public MediaState State { get; private set; } + + public OpenALSong(Song setParent, Uri uri) + { + parent = setParent; + Init(uri.AbsolutePath); + // TODO: duration + } + + public OpenALSong(Song setParent, string filepath, int duration) + { + parent = setParent; + Init(filepath); + Duration = new TimeSpan(0, 0, 0, 0, duration); + } + + private void Init(string filepath) + { + PlayPosition = TimeSpan.Zero; + + State = MediaState.Stopped; + oggFileStream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + oggStream = new OggInputStream(oggFileStream); + bufferHandles = AL.GenBuffers(2); + sourceHandle = AL.GenSource(); + } + + public void Play() + { + if (State == MediaState.Playing) + return; + + if (State == MediaState.Stopped) + { + Rewind(); + if (Stream(bufferHandles[0]) == false || Stream(bufferHandles[1]) == false) + return; + + AL.SourceQueueBuffers(sourceHandle, bufferHandles.Length, bufferHandles); + } + + AL.SourcePlay(sourceHandle); + State = MediaState.Playing; + } + + public void Stop() + { + if (State == MediaState.Stopped) + return; + + State = MediaState.Stopped; + AL.SourceStop(sourceHandle); + AL.SourceUnqueueBuffers(sourceHandle, bufferHandles.Length); + } + + public void Pause() + { + if (State == MediaState.Paused) + return; + + State = MediaState.Paused; + AL.SourcePause(sourceHandle); + } + + public void Resume() + { + Play(); + } + + public void Update() + { + if (sourceHandle == InvalidHandle || State == MediaState.Paused) + return; + + int processed; + AL.GetSource(sourceHandle, ALGetSourcei.BuffersProcessed, out processed); + while (processed-- != 0) + { + int buffer = AL.SourceUnqueueBuffer(sourceHandle); + if (Stream(buffer) == false) + { + Stop(); + return; + } + + AL.SourceQueueBuffer(sourceHandle, buffer); + } + + int state; + AL.GetSource(sourceHandle, ALGetSourcei.SourceState, out state); + switch ((ALSourceState)state) + { + case ALSourceState.Stopped: + case ALSourceState.Initial: + State = MediaState.Stopped; + break; + case ALSourceState.Playing: + State = MediaState.Playing; + break; + default: + State = MediaState.Paused; + break; + } + } + + internal void Rewind() + { + PlayPosition = TimeSpan.Zero; + oggFileStream.Position = 0; + oggStream = new OggInputStream(oggFileStream); + } + + internal bool Stream(int bufferHandle) + { + int size = oggStream.Read(streamReadBuffer); + bool dataAvailable = size > 0; + if (dataAvailable) + { + var channels = (AudioChannels)oggStream.Channels; + PlayPosition = PlayPosition.Add(SoundEffect.GetSampleDuration(size, oggStream.SampleRate, channels)); + ALFormat format = oggStream.Channels > 1 ? ALFormat.Stereo16 : ALFormat.Mono16; + AL.BufferData(bufferHandle, format, streamReadBuffer, size, oggStream.SampleRate); + } + + return dataAvailable; + } + + public void GetVisualizationData(VisualizationData data) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + if (oggFileStream != null) + oggFileStream.Close(); + + oggFileStream = null; + oggStream = null; + + if (sourceHandle == InvalidHandle) + return; + + AL.SourceStop(sourceHandle); + AL.SourceUnqueueBuffers(sourceHandle, bufferHandles.Length); + AL.DeleteSource(sourceHandle); + sourceHandle = InvalidHandle; + AL.DeleteBuffers(bufferHandles); + } + } +} diff --git a/SoundSystems/ANX.SoundSystem.PsVita/Creator.cs b/SoundSystems/ANX.SoundSystem.PsVita/Creator.cs index cedac182..f97b51fc 100644 --- a/SoundSystems/ANX.SoundSystem.PsVita/Creator.cs +++ b/SoundSystems/ANX.SoundSystem.PsVita/Creator.cs @@ -172,6 +172,12 @@ namespace ANX.SoundSystem.PsVita throw new NotImplementedException(); } + public ISong CreateSong(Song parentSong, string filepath, int duration) + { + AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem); + throw new NotImplementedException(); + } + public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance() { AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem); diff --git a/SoundSystems/ANX.SoundSystem.Windows.XAudio/ANX.SoundSystem.Windows.XAudio.csproj b/SoundSystems/ANX.SoundSystem.Windows.XAudio/ANX.SoundSystem.Windows.XAudio.csproj index 8dafd82d..4b400d83 100644 --- a/SoundSystems/ANX.SoundSystem.Windows.XAudio/ANX.SoundSystem.Windows.XAudio.csproj +++ b/SoundSystems/ANX.SoundSystem.Windows.XAudio/ANX.SoundSystem.Windows.XAudio.csproj @@ -21,6 +21,7 @@ DEBUG;TRACE prompt 4 + true pdbonly @@ -29,6 +30,7 @@ TRACE prompt 4 + true @@ -42,6 +44,8 @@ + + @@ -52,6 +56,10 @@ {6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35} ANX.Framework + + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} + OggUtils + + \ No newline at end of file diff --git a/Support/OggUtils/OggUtils_Linux.csproj b/Support/OggUtils/OggUtils_Linux.csproj new file mode 100644 index 00000000..ef80d1da --- /dev/null +++ b/Support/OggUtils/OggUtils_Linux.csproj @@ -0,0 +1,88 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} + Library + Properties + OggUtils + OggUtils + v4.0 + 512 + + + true + full + false + bin\Debug\ + TRACE;DEBUG;LINUX; + prompt + 4 + x86 + true + + + pdbonly + true + bin\Release\ + TRACE;LINUX; + prompt + 4 + x86 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Support/OggUtils/OggUtils_PSVita.csproj b/Support/OggUtils/OggUtils_PSVita.csproj new file mode 100644 index 00000000..1e99088d --- /dev/null +++ b/Support/OggUtils/OggUtils_PSVita.csproj @@ -0,0 +1,89 @@ + + + + Debug + AnyCPU + 10.0.0 + 2.0 + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} + Library + Properties + OggUtils + OggUtils + 512 + {69878862-DA7D-4DC6-B0A1-50D8FAB4242F};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PSVITA; + prompt + 4 + x86 + true + + + pdbonly + true + bin\Release\ + TRACE;PSVITA; + prompt + 4 + x86 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Support/OggUtils/OggUtils_WindowsMetro.csproj b/Support/OggUtils/OggUtils_WindowsMetro.csproj new file mode 100644 index 00000000..f0ae0a1e --- /dev/null +++ b/Support/OggUtils/OggUtils_WindowsMetro.csproj @@ -0,0 +1,94 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {ABECEC14-6BF4-4432-833C-69714EB4E8E6} + Library + Properties + OggUtils + OggUtils + 512 + {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + en-US + Test_TemporaryKey.pfx + + + true + full + false + bin\Debug\ModernUI + TRACE;DEBUG;WINDOWSMETRO; + prompt + 4 + x86 + true + + + pdbonly + true + bin\Release\ModernUI + TRACE;WINDOWSMETRO; + prompt + 4 + x86 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 11.0 + + + \ No newline at end of file diff --git a/Support/OggUtils/Properties/AssemblyInfo.cs b/Support/OggUtils/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..b74f61ef --- /dev/null +++ b/Support/OggUtils/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die mit einer Assembly verknüpft sind. +[assembly: AssemblyTitle("OggUtils")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("ANX.Framework Team")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Copyright © ANX.Framework Team 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("774a9cc9-2e64-4bae-9038-c857edfe3e08")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.7.0.*")] +[assembly: AssemblyFileVersion("0.7.0.*")] diff --git a/Support/OggUtils/csogg/Buffer.cs b/Support/OggUtils/csogg/Buffer.cs new file mode 100644 index 00000000..41a04087 --- /dev/null +++ b/Support/OggUtils/csogg/Buffer.cs @@ -0,0 +1,302 @@ +/* csogg + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +using System; + +namespace csogg +{ + /// + /// Summary description for csBuffer. + /// + public class csBuffer + { + private static int BUFFER_INCREMENT = 256; + + private static uint[] mask={ + 0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, + 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, + 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, + 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, + 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, + 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, + 0x3fffffff,0x7fffffff,0xffffffff + }; + int ptr = 0; + byte[] buffer = null; + int endbit = 0; + int endbyte = 0; + int storage = 0; + + public void writeinit() + { + buffer = new byte[BUFFER_INCREMENT]; + ptr = 0; + buffer[0] = (byte)'\0'; + storage = BUFFER_INCREMENT; + } + + public void write(byte[] s) + { + for(int i = 0; i < s.Length; i++) + { + if(s[i] == 0) break; + write(s[i], 8); + } + } + + public void read (byte[] s, int bytes) + { + int i = 0; + while(bytes--!=0) + { + s[i++]=(byte)(read(8)); + } + } + + void reset() + { + ptr = 0; + buffer[0] = (byte)'\0'; + endbit = endbyte = 0; + } + + public void writeclear() + { + buffer = null; + } + + public void readinit(byte[] buf, int start, int bytes) + { + ptr = start; + buffer = buf; + endbit = endbyte = 0; + storage = bytes; + } + + public void write(int vvalue, int bits) + { + if(endbyte + 4 >= storage) + { + byte[] foo = new byte[storage + BUFFER_INCREMENT]; + Array.Copy(buffer, 0, foo, 0, storage); + buffer = foo; + storage += BUFFER_INCREMENT; + } + + vvalue = (int)((uint)vvalue & mask[bits]); + bits += endbit; + buffer[ptr] |= (byte)(vvalue << endbit); + + if(bits >= 8) + { + buffer[ptr+1] = (byte)((uint)vvalue >> (8-endbit)); + if(bits >= 16) + { + buffer[ptr+2] = (byte)((uint)vvalue >> (16-endbit)); + if (bits >= 24) + { + buffer[ptr+3] = (byte)((uint)vvalue >> (24-endbit)); + if(bits >= 32) + { + if(endbit > 0) + buffer[ptr+4] = (byte)((uint)vvalue >> (32-endbit)); + else + buffer[ptr+4]=0; + } + } + } + } + + endbyte += bits / 8; + ptr += bits/8; + endbit = bits & 7; + } + + public int look(int bits) + { + int ret; + uint m = mask[bits]; + + bits += endbit; + + if(endbyte + 4 >= storage) + { + if(endbyte+(bits-1)/8 >= storage) + return (-1); + } + + ret = ((buffer[ptr]) & 0xff) >> endbit; + + if(bits > 8) + { + ret |= ((buffer[ptr+1]) & 0xff) << (8 - endbit); + if(bits > 16) + { + ret |= ((buffer[ptr+2])&0xff) << (16-endbit); + if(bits > 24) + { + ret |= ((buffer[ptr+3])&0xff) << (24-endbit); + if((bits > 32) && (endbit != 0)) + { + ret |= ((buffer[ptr+4])&0xff) << (32-endbit); + } + } + } + } + ret = (int)(m & ret); + return (ret); + } + + public int look1() + { + if(endbyte >= storage) + return(-1); + return((buffer[ptr] >> endbit) & 1); + } + + public void adv(int bits) + { + bits += endbit; + ptr += bits / 8; + endbyte += bits / 8; + endbit = bits & 7; + } + + public void adv1() + { + ++endbit; + if(endbit > 7) + { + endbit = 0; + ptr++; + endbyte++; + } + } + + public int read(int bits) + { + int ret; + uint m=mask[bits]; + + bits += endbit; + + if(endbyte+4 >= storage) + { + ret = -1; + if(endbyte + (bits-1)/8 >= storage) + { + ptr += bits/8; + endbyte += bits/8; + endbit = bits&7; + return(ret); + } + } + + ret = ((buffer[ptr]) & 0xff) >> endbit; + if(bits > 8) + { + ret|=((buffer[ptr+1])&0xff)<<(8-endbit); + if(bits > 16) + { + ret|=((buffer[ptr+2])&0xff)<<(16-endbit); + if(bits > 24) + { + ret|=((buffer[ptr+3])&0xff)<<(24-endbit); + + if((bits > 32) && (endbit != 0)) + { + ret|=((buffer[ptr+4])&0xff)<<(32-endbit); + } + } + } + } + + ret &= (int)m; + + ptr += bits/8; + endbyte += bits/8; + endbit = bits&7; + return(ret); + } + + public int read1() + { + int ret; + if(endbyte>=storage) + { + ret = -1; + endbit++; + if(endbit > 7) + { + endbit = 0; + ptr++; + endbyte++; + } + return(ret); + } + + ret=(buffer[ptr] >> endbit) & 1; + + endbit++; + if(endbit > 7) + { + endbit = 0; + ptr++; + endbyte++; + } + return(ret); + } + + public int bytes() + { + return(endbyte+(endbit+7)/8); + } + + public int bits() + { + return(endbyte*8+endbit); + } + + public static int ilog(int v) + { + int ret=0; + while(v > 0) + { + ret++; + v >>= 1; + } + return(ret); + } + + public byte[] buf() + { + return(buffer); + } + + public csBuffer() + { + // Really a noop? + } + } +} diff --git a/Support/OggUtils/csogg/Packet.cs b/Support/OggUtils/csogg/Packet.cs new file mode 100644 index 00000000..6b14d708 --- /dev/null +++ b/Support/OggUtils/csogg/Packet.cs @@ -0,0 +1,53 @@ +/* csogg + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +using System; + +namespace csogg +{ + /// + /// Summary description for Packet. + /// + public class Packet + { + public byte[] packet_base; + public int packet; + public int bytes; + public int b_o_s; + public int e_o_s; + + public long granulepos; + + public long packetno; // sequence number for decode; the framing + // knows where there's a hole in the data, + // but we need coupling so that the codec + // (which is in a seperate abstraction + // layer) also knows about the gap + + public Packet() + { + // No constructor + } + } +} diff --git a/Support/OggUtils/csogg/Page.cs b/Support/OggUtils/csogg/Page.cs new file mode 100644 index 00000000..524fe3b5 --- /dev/null +++ b/Support/OggUtils/csogg/Page.cs @@ -0,0 +1,140 @@ +/* csogg + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +using System; + +namespace csogg +{ + /// + /// Summary description for Page. + /// + public class Page + { + private static uint[] crc_lookup=new uint[256]; + + private static uint crc_entry(uint index) + { + uint r = index << 24; + for(int i=0; i<8; i++) + { + if((r& 0x80000000)!=0) + { + r=(r << 1)^0x04c11db7; /* The same as the ethernet generator + polynomial, although we use an + unreflected alg and an init/final + of 0, not 0xffffffff */ + } + else + { + r <<= 1; + } + } + return (r & 0xffffffff); + } + + public byte[] header_base; + public int header; + public int header_len; + public byte[] body_base; + public int body; + public int body_len; + + internal int version() + { + return header_base[header+4]&0xff; + } + internal int continued() + { + return (header_base[header+5]&0x01); + } + public int bos() + { + return (header_base[header+5]&0x02); + } + public int eos() + { + return (header_base[header+5]&0x04); + } + public long granulepos() + { + long foo = header_base[header+13]&0xff; + foo = (foo<<8) | (uint)(header_base[header+12]&0xff); + foo = (foo<<8) | (uint)(header_base[header+11]&0xff); + foo = (foo<<8) | (uint)(header_base[header+10]&0xff); + foo = (foo<<8) | (uint)(header_base[header+9]&0xff); + foo = (foo<<8) | (uint)(header_base[header+8]&0xff); + foo = (foo<<8) | (uint)(header_base[header+7]&0xff); + foo = (foo<<8) | (uint)(header_base[header+6]&0xff); + return(foo); + } + public int serialno() + { + return (header_base[header+14]&0xff)| + ((header_base[header+15]&0xff)<<8)| + ((header_base[header+16]&0xff)<<16)| + ((header_base[header+17]&0xff)<<24); + } + internal int pageno() + { + return (header_base[header+18]&0xff)| + ((header_base[header+19]&0xff)<<8)| + ((header_base[header+20]&0xff)<<16)| + ((header_base[header+21]&0xff)<<24); + } + + internal void checksum() + { + uint crc_reg=0; + uint a, b; + + for(int i=0;i> 24) & 0xff; + crc_reg = (crc_reg<<8)^crc_lookup[a^b]; + //crc_reg = (crc_reg<<8)^(uint)(crc_lookup[((crc_reg >> 24)&0xff)^(header_base[header+i]&0xff)]); + } + for(int i=0;i> 24) & 0xff; + crc_reg = (crc_reg<<8)^crc_lookup[a^b]; + + //crc_reg = (crc_reg<<8)^(uint)(crc_lookup[((crc_reg >> 24)&0xff)^(body_base[body+i]&0xff)]); + } + header_base[header+22]=(byte)crc_reg/*&0xff*/; + header_base[header+23]=(byte)(crc_reg>>8)/*&0xff*/; + header_base[header+24]=(byte)(crc_reg>>16)/*&0xff*/; + header_base[header+25]=(byte)(crc_reg>>24)/*&0xff*/; + } + + public Page() + { + for(uint i=0; i + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +using System; +using System.Text; + +namespace csogg +{ + /// + /// Summary description for StreamState. + /// + public class StreamState + { + byte[] body_data; /* bytes from packet bodies */ + int body_storage; /* storage elements allocated */ + int body_fill; /* elements stored; fill mark */ + private int body_returned; /* elements of fill returned */ + + + int[] lacing_vals; /* The values that will go to the segment table */ + long[] granule_vals; /* pcm_pos values for headers. Not compact + this way, but it is simple coupled to the + lacing fifo */ + int lacing_storage; + int lacing_fill; + int lacing_packet; + int lacing_returned; + + byte[] header=new byte[282]; /* working space for header encode */ + int header_fill; + + public int e_o_s; /* set when we have buffered the last packet in the + logical bitstream */ + int b_o_s; /* set after we've written the initial page + of a logical bitstream */ + int serialno; + int pageno; + long packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a seperate abstraction + layer) also knows about the gap */ + long granulepos; + + StreamState(int serialno) : this() + { + init(serialno); + } + + public StreamState() + { + init(); + } + + void init() + { + body_storage=16*1024; + body_data=new byte[body_storage]; + lacing_storage=1024; + lacing_vals=new int[lacing_storage]; + granule_vals=new long[lacing_storage]; + } + public void init(int serialno) + { + if(body_data==null){ init(); } + else + { + for(int i=0; i255?255:lacing_fill); + int bytes=0; + int acc=0; + long granule_pos=granule_vals[0]; + + if(maxvals==0)return(0); + + /* construct a page */ + /* decide how many segments to include */ + + /* If this is the initial header case, the first page must only include + the initial header packet */ + if(b_o_s==0) + { /* 'initial header page' case */ + granule_pos=0; + for(vals=0;vals4096)break; + acc+=(lacing_vals[vals]&0x0ff); + granule_pos=granule_vals[vals]; + } + } + + /* construct the header in temp storage */ + + String oggs_str = "OggS"; + Encoding AE = Encoding.UTF8; + byte[] oggs_byt = AE.GetBytes(oggs_str); + Array.Copy(oggs_byt, 0, header, 0, oggs_byt.Length); + + /* stream structure version */ + header[4]=0x00; + + /* continued packet flag? */ + header[5]=0x00; + if((lacing_vals[0]&0x100)==0)header[5]|=0x01; + /* first page flag? */ + if(b_o_s==0) header[5]|=0x02; + /* last page flag? */ + if(e_o_s!=0 && lacing_fill==vals) header[5]|=0x04; + b_o_s=1; + + /* 64 bits of PCM position */ + for(i=6;i<14;i++) + { + header[i]=(byte)granule_pos; + granule_pos>>=8; + } + + /* 32 bits of stream serial number */ + { + int _serialno=serialno; + for(i=14;i<18;i++) + { + header[i]=(byte)_serialno; + _serialno>>=8; + } + } + + /* 32 bits of page counter (we have both counter and page header + because this val can roll over) */ + if(pageno==-1)pageno=0; /* because someone called + stream_reset; this would be a + strange thing to do in an + encode stream, but it has + plausible uses */ + { + int _pageno=pageno++; + for(i=18;i<22;i++) + { + header[i]=(byte)_pageno; + _pageno>>=8; + } + } + + /* zero for computation; filled in later */ + header[22]=0; + header[23]=0; + header[24]=0; + header[25]=0; + + /* segment table */ + header[26]=(byte)vals; + for(i=0;i 4096 || /* 'page nominal size' case */ + lacing_fill>=255 || /* 'segment table full' case */ + (lacing_fill!=0&&b_o_s==0)) + { /* 'initial header page' case */ + return flush(og); + } + return 0; + } + + public int eof() + { + return e_o_s; + } + + public int reset() + { + body_fill=0; + body_returned=0; + + lacing_fill=0; + lacing_packet=0; + lacing_returned=0; + + header_fill=0; + + e_o_s=0; + b_o_s=0; + pageno=-1; + packetno=0; + granulepos=0; + return(0); + } + } +} diff --git a/Support/OggUtils/csogg/SyncState.cs b/Support/OggUtils/csogg/SyncState.cs new file mode 100644 index 00000000..1e385982 --- /dev/null +++ b/Support/OggUtils/csogg/SyncState.cs @@ -0,0 +1,289 @@ +/* csogg + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +using System; + +namespace csogg +{ + /// + /// Summary description for SyncState. + /// + public class SyncState + { + public byte[] data; + int storage; + int fill; + int returned; + + int unsynced; + int headerbytes; + int bodybytes; + + public int clear() + { + data=null; + return(0); + } + + // !!!!!!!!!!!! + // byte[] buffer(int size){ + public int buffer(int size) + { + // first, clear out any space that has been previously returned + if(returned!=0) + { + fill-=returned; + if(fill>0) + { + Array.Copy(data, returned, data, 0, fill); + } + returned=0; + } + + if(size>storage-fill) + { + // We need to extend the internal buffer + int newsize=size+fill+4096; // an extra page to be nice + if(data!=null) + { + byte[] foo=new byte[newsize]; + Array.Copy(data, 0, foo, 0, data.Length); + data=foo; + } + else + { + data=new byte[newsize]; + } + storage=newsize; + } + + // expose a segment at least as large as requested at the fill mark + // return((char *)oy->data+oy->fill); + // return(data); + return(fill); + } + + public int wrote(int bytes) + { + if(fill+bytes>storage)return(-1); + fill+=bytes; + return(0); + } + + // sync the stream. This is meant to be useful for finding page + // boundaries. + // + // return values for this: + // -n) skipped n bytes + // 0) page not ready; more data (no bytes skipped) + // n) page synced at current location; page length n bytes + private Page pageseek_p=new Page(); + private byte[] chksum=new byte[4]; + public int pageseek(Page og) + { + int page=returned; + int next; + int bytes=fill-returned; + + if(headerbytes==0) + { + int _headerbytes,i; + if(bytes<27)return(0); // not enough for a header + + /* verify capture pattern */ + //!!!!!!!!!!! + if(data[page]!='O' || + data[page+1]!='g' || + data[page+2]!='g' || + data[page+3]!='S') + { + headerbytes=0; + bodybytes=0; + + // search for possible capture + next=0; + for(int ii=0; iibytes)return(0); + + // The whole test page is buffered. Verify the checksum + lock(chksum) + { + // Grab the checksum bytes, set the header field to zero + + Array.Copy(data, page+22, chksum, 0, 4); + data[page+22]=0; + data[page+23]=0; + data[page+24]=0; + data[page+25]=0; + + // set up a temp page struct and recompute the checksum + Page log=pageseek_p; + log.header_base=data; + log.header=page; + log.header_len=headerbytes; + + log.body_base=data; + log.body=page+headerbytes; + log.body_len=bodybytes; + log.checksum(); + + // Compare + if(chksum[0]!=data[page+22] || + chksum[1]!=data[page+23] || + chksum[2]!=data[page+24] || + chksum[3]!=data[page+25]) + { + // D'oh. Mismatch! Corrupt page (or miscapture and not a page at all) + // replace the computed checksum with the one actually read in + Array.Copy(chksum, 0, data, page+22, 4); + // Bad checksum. Lose sync */ + + headerbytes=0; + bodybytes=0; + // search for possible capture + next=0; + for(int ii=0; ii0) + { + // have a page + return(1); + } + if(ret==0) + { + // need more data + return(0); + } + + // head did not start a synced page... skipped some bytes + if(unsynced==0) + { + unsynced=1; + return(-1); + } + // loop. keep looking + } + } + + // clear things to an initial state. Good to call, eg, before seeking + public int reset() + { + fill=0; + returned=0; + unsynced=0; + headerbytes=0; + bodybytes=0; + return(0); + } + public void init(){} + + public SyncState() + { + // No constructor needed + } + } +} diff --git a/Support/OggUtils/csvorbis/AllocChain.cs b/Support/OggUtils/csvorbis/AllocChain.cs new file mode 100644 index 00000000..d074453f --- /dev/null +++ b/Support/OggUtils/csvorbis/AllocChain.cs @@ -0,0 +1,36 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* So, again, why is this here? Kill it soon */ + +using System; + +namespace csvorbis +{ + class AllocChain + { + //Object ptr; + //AllocChain next; + }; +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/Block.cs b/Support/OggUtils/csvorbis/Block.cs new file mode 100644 index 00000000..7185f223 --- /dev/null +++ b/Support/OggUtils/csvorbis/Block.cs @@ -0,0 +1,205 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + public class Block + { + ///necessary stream state for linking to the framing abstraction + internal float[][] pcm=new float[0][]; // this is a pointer into local storage + internal csBuffer opb=new csBuffer(); + + internal int lW; + internal int W; + internal int nW; + internal int pcmend; + internal int mode; + + internal int eofflag; + internal long granulepos; + internal long sequence; + internal DspState vd; // For read-only access of configuration + + // local storage to avoid remallocing; it's up to the mapping to + // structure it + //byte[] localstore; + //int localtop; + //int localalloc; + //int totaluse; + //AllocChain reap; + + // bitmetrics for the frame + internal int glue_bits; + internal int time_bits; + internal int floor_bits; + internal int res_bits; + + public Block(DspState vd) + { + this.vd=vd; + // localalloc=0; + // localstore=null; + if(vd.analysisp!=0) + { + opb.writeinit(); + } + } + + public void init(DspState vd) + { + this.vd=vd; + } + + // int alloc(int bytes){ + // bytes=(bytes+(8-1))&(~(8-1)); + // if(bytes+localtop>localalloc){ + // if(localstore!=null){ + // AllocChain link=new AllocChain(); + // totaluse+=localtop; + // link.next=reap; + // link.ptr=localstore; + // reap=link; + // } + // // highly conservative + // localalloc=bytes; + // localstore=new byte[localalloc]; + // localtop=0; + // } + // { + // int foo=localtop; + // //void *ret=(void *)(((char *)vb->localstore)+vb->localtop); + // localtop+=bytes; + // return foo; + // } + // } + + // reap the chain, pull the ripcord + // void ripcord(){ + // // reap the chain + // while(reap!=null){ + // AllocChain next=reap.next; + // //free(reap->ptr); + // reap.ptr=null; + // //memset(reap,0,sizeof(struct alloc_chain)); + // //free(reap); + // reap=next; + // } + // // consolidate storage + // if(totaluse!=0){ + // //vb->localstore=realloc(vb->localstore,vb->totaluse+vb->localalloc); + // byte[] foo=new byte[totaluse+localalloc]; + // Array.Copy(localstore, 0, foo, 0, localstore.length); + // localstore=foo; + // localalloc+=totaluse; + // totaluse=0; + // } + // // pull the ripcord + // localtop=0; + // reap=null; + // } + + public int clear() + { + if(vd!=null) + { + if(vd.analysisp!=0) + { + opb.writeclear(); + } + } + //ripcord(); + //if(localstore!=null) + // localstore=null; + //memset(vb,0,sizeof(vorbis_block)); + return(0); + } + + public int synthesis(Packet op) + { + Info vi=vd.vi; + + // first things first. Make sure decode is ready + // ripcord(); + opb.readinit(op.packet_base, op.packet, op.bytes); + + // Check the packet type + if(opb.read(1)!=0) + { + // Oops. This is not an audio data packet + return(-1); + } + + // read our mode and pre/post windowsize + int _mode=opb.read(vd.modebits); + if(_mode==-1)return(-1); + + mode=_mode; + W=vi.mode_param[mode].blockflag; + if(W!=0) + { + lW=opb.read(1); + nW=opb.read(1); + if(nW==-1) return(-1); + } + else + { + lW=0; + nW=0; + } + + // more setup + granulepos=op.granulepos; + sequence=op.packetno-3; // first block is third packet + eofflag=op.e_o_s; + + // alloc pcm passback storage + pcmend=vi.blocksizes[W]; + //pcm=alloc(vi.channels); + if(pcm.Length + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using System.Runtime.CompilerServices; +using csogg; + +namespace csvorbis +{ + class CodeBook + { + internal int dim; // codebook dimensions (elements per vector) + internal int entries; // codebook entries + internal StaticCodeBook c=new StaticCodeBook(); + + internal float[] valuelist; // list of dim*entries actual entry values + internal int[] codelist; // list of bitstream codewords for each entry + internal DecodeAux decode_tree; + + // returns the number of bits + internal int encode(int a, csBuffer b) + { + b.write(codelist[a], c.lengthlist[a]); + return(c.lengthlist[a]); + } + + // One the encode side, our vector writers are each designed for a + // specific purpose, and the encoder is not flexible without modification: + // + // The LSP vector coder uses a single stage nearest-match with no + // interleave, so no step and no error return. This is specced by floor0 + // and doesn't change. + // + // Residue0 encoding interleaves, uses multiple stages, and each stage + // peels of a specific amount of resolution from a lattice (thus we want + // to match by threshhold, not nearest match). Residue doesn't *have* to + // be encoded that way, but to change it, one will need to add more + // infrastructure on the encode side (decode side is specced and simpler) + + // floor0 LSP (single stage, non interleaved, nearest match) + // returns entry number and *modifies a* to the quantization value + internal int errorv(float[] a) + { + int bestt=best(a,1); + for(int k=0;k8) + { + for(i=0;i + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; + +namespace csvorbis +{ + class Drft + { + int n; + float[] trigcache; + int[] splitcache; + + internal void backward(float[] data) + { + if(n==1)return; + drftb1(n,data,trigcache,trigcache,n,splitcache); + } + + internal void init(int n) + { + this.n=n; + trigcache=new float[3*n]; + splitcache=new int[32]; + fdrffti(n, trigcache, splitcache); + } + + internal void clear() + { + if(trigcache!=null)trigcache=null; + if(splitcache!=null)splitcache=null; + } + + static int[] ntryh = { 4,2,3,5 }; + static float tpi = 6.28318530717958647692528676655900577f; + static float hsqt2 = .70710678118654752440084436210485f; + static float taui = .86602540378443864676372317075293618f; + static float taur = -.5f; + static float sqrt2 = 1.4142135623730950488016887242097f; + + static void drfti1(int n, float[] wa, int index, int[] ifac) + { + float arg,argh,argld,fi; + int ntry=0,i,j=-1; + int k1, l1, l2, ib; + int ld, ii, ip, iis, nq, nr; + int ido, ipm, nfm1; + int nl=n; + int nf=0; + + + L101: j++; + if (j < 4) + ntry=ntryh[j]; + else + ntry+=2; + + L104: nq=nl/ntry; + nr=nl-ntry*nq; + if(nr!=0) goto L101; + + nf++; + ifac[nf+1]=ntry; + nl=nq; + if(ntry!=2) goto L107; + if(nf==1) goto L107; + + for(i=1;i>1; + ipp2=ip; + idp2=ido; + nbd=(ido-1)>>1; + t0=l1*ido; + t10=ip*ido; + + if(ido==1) goto L119; + for(ik=0;ikl1) + { + for(j=1;j>1); + ipp2=ip; + ipph=(int)((uint)(ip+1)>>1); + if(idol1) goto L139; + + iis= -ido-1; + t1=0; + for(j=1;j + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; +using csvorbis; + +namespace csvorbis +{ + public class DspState + { + static float M_PI=3.1415926539f; + static int VI_TRANSFORMB=1; + static int VI_WINDOWB=1; + + internal int analysisp; + internal Info vi; + internal int modebits; + + float[][] pcm; + //float[][] pcmret; + int pcm_storage; + int pcm_current; + int pcm_returned; + + float[] multipliers; + int envelope_storage; + int envelope_current; + + int eofflag; + + int lW; + int W; + int nW; + int centerW; + + long granulepos; + public long sequence; + + long glue_bits; + long time_bits; + long floor_bits; + long res_bits; + + // local lookup storage + //!! Envelope ve=new Envelope(); // envelope + //float **window[2][2][2]; // block, leadin, leadout, type + internal float[][][][][] wnd; // block, leadin, leadout, type + //vorbis_look_transform **transform[2]; // block, type + internal Object[][] transform; + internal CodeBook[] fullbooks; + // backend lookups are tied to the mode, not the backend or naked mapping + internal Object[] mode; + + // local storage, only used on the encoding side. This way the + // application does not need to worry about freeing some packets' + // memory and not others'; packet storage is always tracked. + // Cleared next call to a _dsp_ function + byte[] header; + byte[] header1; + byte[] header2; + + public DspState() + { + transform=new Object[2][]; + wnd=new float[2][][][][]; + wnd[0]=new float[2][][][]; + wnd[0][0]=new float[2][][]; + wnd[0][1]=new float[2][][]; + wnd[0][0][0]=new float[2][]; + wnd[0][0][1]=new float[2][]; + wnd[0][1][0]=new float[2][]; + wnd[0][1][1]=new float[2][]; + wnd[1]=new float[2][][][]; + wnd[1][0]=new float[2][][]; + wnd[1][1]=new float[2][][]; + wnd[1][0][0]=new float[2][]; + wnd[1][0][1]=new float[2][]; + wnd[1][1][0]=new float[2][]; + wnd[1][1][1]=new float[2][]; + } + + private static int ilog2(int v) + { + int ret=0; + while(v>1) + { + ret++; + v = (int)((uint)v >> 1); + } + return(ret); + } + + internal static float[] window(int type, int wnd, int left, int right) + { + float[] ret=new float[wnd]; + switch(type) + { + case 0: + // The 'vorbis window' (window 0) is sin(sin(x)*sin(x)*2pi) + { + int leftbegin=wnd/4-left/2; + int rightbegin=wnd-wnd/4-right/2; + + for(int i=0;ivi.blocksizes[1]/2 && pcm_returned>8192) + { + // don't shift too much; we need to have a minimum PCM buffer of + // 1/2 long block + + int shiftPCM=centerW-vi.blocksizes[1]/2; + shiftPCM=(pcm_returnedpcm_storage) + { + // expand the storage + pcm_storage=endW+vi.blocksizes[1]; + for(int i=0;igranulepos. + // + // This is not foolproof! It will be confused if we begin + // decoding at the last page after a seek or hole. In that case, + // we don't have a starting point to judge where the last frame + // is. For this reason, vorbisfile will always try to make sure + // it reads the last two marked pages in proper sequence + + if(granulepos==-1) + { + granulepos=vb.granulepos; + } + else + { + granulepos+=(_centerW-centerW); + if(vb.granulepos!=-1 && granulepos!=vb.granulepos) + { + if(granulepos>vb.granulepos && vb.eofflag!=0) + { + // partial last frame. Strip the padding off + _centerW = _centerW - (int)(granulepos-vb.granulepos); + }// else{ Shouldn't happen *unless* the bitstream is out of + // spec. Either way, believe the bitstream } + granulepos=vb.granulepos; + } + } + + // Update, cleanup + + centerW=_centerW; + pcm_current=endW; + if(vb.eofflag!=0)eofflag=1; + } + return(0); + } + + // pcm==NULL indicates we just want the pending samples, no more + public int synthesis_pcmout(float[][][] _pcm, int[] index) + { + if(pcm_returnedcenterW)return(-1); + pcm_returned+=bytes; + return(0); + } + + public void clear() + { + } + } +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/EncodeAuxNearestMatch.cs b/Support/OggUtils/csvorbis/EncodeAuxNearestMatch.cs new file mode 100644 index 00000000..8e513a3f --- /dev/null +++ b/Support/OggUtils/csvorbis/EncodeAuxNearestMatch.cs @@ -0,0 +1,40 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; + +namespace csvorbis +{ + class EncodeAuxNearestMatch + { + internal int[] ptr0; + internal int[] ptr1; + + internal int[] p; // decision points (each is an entry) + internal int[] q; // decision points (each is an entry) + internal int aux; // number of tree entries + internal int alloc; + } +} diff --git a/Support/OggUtils/csvorbis/EncodeAuxThreshMatch.cs b/Support/OggUtils/csvorbis/EncodeAuxThreshMatch.cs new file mode 100644 index 00000000..933e5519 --- /dev/null +++ b/Support/OggUtils/csvorbis/EncodeAuxThreshMatch.cs @@ -0,0 +1,37 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; + +namespace csvorbis +{ + class EncodeAuxThreshMatch + { + internal float[] quantthresh; + internal int[] quantmap; + internal int quantvals; + internal int threshvals; + } +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/Floor0.cs b/Support/OggUtils/csvorbis/Floor0.cs new file mode 100644 index 00000000..d49bcc0d --- /dev/null +++ b/Support/OggUtils/csvorbis/Floor0.cs @@ -0,0 +1,405 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + class Floor0 : FuncFloor + { + + override public void pack(Object i, csBuffer opb) + { + InfoFloor0 info=(InfoFloor0)i; + opb.write(info.order,8); + opb.write(info.rate,16); + opb.write(info.barkmap,16); + opb.write(info.ampbits,6); + opb.write(info.ampdB,8); + opb.write(info.numbooks-1,4); + for(int j=0;j=vi.books) + { + //free_info(info); + return(null); + } + } + return(info); + // err_out: + // free_info(info); + // return(NULL); + } + override public Object look(DspState vd, InfoMode mi, Object i) + { + float scale; + + Info vi=vd.vi; + InfoFloor0 info=(InfoFloor0)i; + LookFloor0 look=new LookFloor0(); + look.m=info.order; + look.n=vi.blocksizes[mi.blockflag]/2; + look.ln=info.barkmap; + look.vi=info; + look.lpclook.init(look.ln,look.m); + + // we choose a scaling constant so that: + // floor(bark(rate/2-1)*C)=mapped-1 + // floor(bark(rate/2)*C)=mapped + scale = look.ln / (float)toBARK((float)(info.rate/2.0)); + + // the mapping from a linear scale to a smaller bark scale is + // straightforward. We do *not* make sure that the linear mapping + // does not skip bark-scale bins; the decoder simply skips them and + // the encoder may do what it wishes in filling them. They're + // necessary in some mapping combinations to keep the scale spacing + // accurate + look.linearmap=new int[look.n]; + + for(int j=0; j=look.ln) val=look.ln; // guard against the approximation + look.linearmap[j]=val; + } + return look; + } + + static double toBARK(float f) + { + double a,b,c; + a = 13.1 * Math.Atan(0.00074 * f); + b = 2.24 * Math.Atan(f * f * 1.85e-8); + c = 1.0e-4 * f; + + return (a + b + c); + } + + private object state(object i) + { + EchstateFloor0 state=new EchstateFloor0(); + InfoFloor0 info=(InfoFloor0)i; + + // a safe size if usually too big (dim==1) + state.codewords=new int[info.order]; + state.curve=new float[info.barkmap]; + state.frameno=-1; + return(state); + } + override public void free_info(Object i){} + override public void free_look(Object i){} + override public void free_state(Object vs){} + override public int forward(Block vb, Object i, float[] fin, float[] fout, Object vs){return 0;} + + float[] lsp=null; + int inverse(Block vb, Object i, float[] fout) + { + //System.err.println("Floor0.inverse "+i.getClass()+"]"); + LookFloor0 look=(LookFloor0)i; + InfoFloor0 info=look.vi; + int ampraw=vb.opb.read(info.ampbits); + if(ampraw>0) + { // also handles the -1 out of data case + int maxval=(1<m); + for(int j=0; jn); + for(int k=0; kn); + return(0); + } + + override public Object inverse1(Block vb, Object i, Object memo) + { + //System.err.println("Floor0.inverse "+i.getClass()+"]"); + LookFloor0 look=(LookFloor0)i; + InfoFloor0 info=look.vi; + float[] lsp=null; + if(memo is float[]) + { + lsp=(float[])memo; + } + + int ampraw=vb.opb.read(info.ampbits); + if(ampraw>0) + { // also handles the -1 out of data case + int maxval=(1<n); + for(int j=0; j> 1); + } + return(ret); + } + + static void lsp_to_lpc(float[] lsp, float[] lpc, int m) + { + int i,j,m2=m/2; + float[] O=new float[m2]; + float[] E=new float[m2]; + float A; + float[] Ae=new float[m2+1]; + float[] Ao=new float[m2+1]; + float B; + float[] Be=new float[m2]; + float[] Bo=new float[m2]; + float temp; + + // even/odd roots setup + for(i=0;im+1 must be less than l->ln, but guard in case we get a bad stream + float[] lcurve=new float[Math.Max(l.ln*2,l.m*2+2)]; + + if(amp==0) + { + //memset(curve,0,sizeof(float)*l->n); + for(int j=0; j + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + class Floor1 : FuncFloor + { + static int floor1_rangedb=140; + static int VIF_POSIT=63; + + override public void pack(Object i, csBuffer opb) + { + InfoFloor1 info=(InfoFloor1)i; + + int count=0; + int rangebits; + int maxposit=info.postlist[1]; + int maxclass=-1; + + /* save out partitions */ + opb.write(info.partitions,5); /* only 0 to 31 legal */ + for(int j=0;j=vi.books) + { + //goto err_out; + info.free(); + return(null); + } + for(int k=0;k<(1<=vi.books) + { + //goto err_out; + info.free(); + return(null); + } + } + } + + /* read the post list */ + info.mult=opb.read(2)+1; /* only 1,2,3,4 legal now */ + rangebits=opb.read(4); + + for(int j=0,k=0;j=(1<info.postlist[sortpointer[k]]) + { + foo=sortpointer[k]; + sortpointer[k]=sortpointer[j]; + sortpointer[j]=foo; + } + } + } + + /* points from sort order back to range number */ + for(int j=0;j<_n;j++) + { + look.forward_index[j]=sortpointer[j]; + } + /* points from range order to sorted position */ + for(int j=0;j<_n;j++) + { + look.reverse_index[look.forward_index[j]]=j; + } + /* we actually need the post values too */ + for(int j=0;j<_n;j++) + { + look.sorted_index[j]=info.postlist[look.forward_index[j]]; + } + + + /* quantize values to multiplier spec */ + switch(info.mult) + { + case 1: /* 1024 -> 256 */ + look.quant_q=256; + break; + case 2: /* 1024 -> 128 */ + look.quant_q=128; + break; + case 3: /* 1024 -> 86 */ + look.quant_q=86; + break; + case 4: /* 1024 -> 64 */ + look.quant_q=64; + break; + default: + look.quant_q=-1; + break; + } + + /* discover our neighbors for decode where we don't use fit flags + (that would push the neighbors outward) */ + for(int j=0;j<_n-2;j++) + { + int lo=0; + int hi=1; + int lx=0; + int hx=look.n; + int currentx=info.postlist[j+2]; + for(int k=0;klx && xcurrentx) + { + hi=k; + hx=x; + } + } + look.loneighbor[j]=lo; + look.hineighbor[j]=hi; + } + + return look; + } + + override public void free_info(Object i){} + override public void free_look(Object i){} + override public void free_state(Object vs){} + + override public int forward(Block vb, Object i, float[] fin, float[] fout, Object vs){return 0;} + + override public Object inverse1(Block vb, Object ii, Object memo) + { + LookFloor1 look=(LookFloor1)ii; + InfoFloor1 info=look.vi; + CodeBook[] books=vb.vd.fullbooks; + + /* unpack wrapped/predicted values from stream */ + if(vb.opb.read(1)==1) + { + int[] fit_value=null; + if(memo is int[]) + { + fit_value=(int[])memo; + } + if(fit_value==null || fit_value.Length> csubbits); + if(book>=0) + { + if((fit_value[j+k]=books[book].decode(vb.opb))==-1) + { + return(null); + } + } + else + { + fit_value[j+k]=0; + } + } + j+=cdim; + } + + /* unwrap positive values and reconsitute via linear interpolation */ + for(int i=2;i=room) + { + if(hiroom>loroom) + { + val = val-loroom; + } + else + { + val = -1-(val-hiroom); + } + } + else + { + if((val&1)!=0) + { + val= (int)(-((uint)(val+1) >> 1)); + } + else + { + val>>=1; + } + } + + fit_value[i]=val+predicted; + fit_value[look.loneighbor[i-2]]&=0x7fff; + fit_value[look.hineighbor[i-2]]&=0x7fff; + } + else + { + fit_value[i]=predicted|0x8000; + } + } + return(fit_value); + } + + // eop: + // return(NULL); + return(null); + } + + private static int render_point(int x0,int x1,int y0,int y1,int x) + { + y0&=0x7fff; /* mask off flag */ + y1&=0x7fff; + + { + int dy=y1-y0; + int adx=x1-x0; + int ady=Math.Abs(dy); + int err=ady*(x-x0); + + int off=(int)(err/adx); + if(dy<0)return(y0-off); + return(y0+off); + } + } + + override public int inverse2(Block vb, Object i, Object memo, float[] fout) + { + LookFloor1 look=(LookFloor1)i; + InfoFloor1 info=look.vi; + int n=vb.vd.vi.blocksizes[vb.mode]/2; + + if(memo!=null) + { + /* render the lines */ + int[] fit_value=(int[] )memo; + int hx=0; + int lx=0; + int ly=fit_value[0]*info.mult; + for(int j=1;j=adx) + { + err-=adx; + y+=sy; + } + else + { + y+=bbase; + } + d[x]*=FLOOR_fromdB_LOOKUP[y]; + } + } + + static int ilog(int v) + { + int ret=0; + while(v!=0) + { + ret++; + v = (int)((uint)v >> 1); + } + return(ret); + } + + private static int ilog2(int v) + { + int ret=0; + while(v>1) + { + ret++; + v = (int)((uint)v >> 1); + } + return(ret); + } + } + + class InfoFloor1 + { + const int VIF_POSIT=63; + const int VIF_CLASS=16; + const int VIF_PARTS=31; + + internal int partitions; /* 0 to 31 */ + internal int[] partitionclass=new int[VIF_PARTS]; /* 0 to 15 */ + + internal int[] class_dim=new int[VIF_CLASS]; /* 1 to 8 */ + internal int[] class_subs=new int[VIF_CLASS]; /* 0,1,2,3 (bits: 1< + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + abstract class FuncFloor + { + public static FuncFloor[] floor_P={new Floor0(),new Floor1()}; + + public abstract void pack(Object i, csBuffer opb); + public abstract Object unpack(Info vi, csBuffer opb); + public abstract Object look(DspState vd, InfoMode mi, Object i); + public abstract void free_info(Object i); + public abstract void free_look(Object i); + public abstract void free_state(Object vs); + public abstract int forward(Block vb, Object i, float[] fin, float[] fout, Object vs); + public abstract Object inverse1(Block vb, Object i, Object memo); + public abstract int inverse2(Block vb, Object i, Object memo, float[] fout); + } +} diff --git a/Support/OggUtils/csvorbis/FuncMapping.cs b/Support/OggUtils/csvorbis/FuncMapping.cs new file mode 100644 index 00000000..78ac0474 --- /dev/null +++ b/Support/OggUtils/csvorbis/FuncMapping.cs @@ -0,0 +1,42 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + abstract class FuncMapping + { + public static FuncMapping[] mapping_P={new Mapping0()}; + + public abstract void pack(Info info , Object imap, csBuffer buffer); + public abstract Object unpack(Info info , csBuffer buffer); + public abstract Object look(DspState vd, InfoMode vm, Object m); + public abstract void free_info(Object imap); + public abstract void free_look(Object imap); + public abstract int inverse(Block vd, Object lm); + } +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/FuncResidue.cs b/Support/OggUtils/csvorbis/FuncResidue.cs new file mode 100644 index 00000000..c3313145 --- /dev/null +++ b/Support/OggUtils/csvorbis/FuncResidue.cs @@ -0,0 +1,46 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + abstract class FuncResidue + { + public static FuncResidue[] residue_P={new Residue0(), + new Residue1(), + new Residue2()}; + + public abstract void pack(Object vr, csBuffer opb); + public abstract Object unpack(Info vi, csBuffer opb); + public abstract Object look(DspState vd, InfoMode vm, Object vr); + public abstract void free_info(Object i); + public abstract void free_look(Object i); + public abstract int forward(Block vb,Object vl, float[][] fin, int ch); + + public abstract int inverse(Block vb, Object vl, float[][] fin, int[] nonzero,int ch); + } +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/FuncTime.cs b/Support/OggUtils/csvorbis/FuncTime.cs new file mode 100644 index 00000000..11b2c424 --- /dev/null +++ b/Support/OggUtils/csvorbis/FuncTime.cs @@ -0,0 +1,43 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + abstract class FuncTime + { + public static FuncTime[] time_P={new Time0()}; + + public abstract void pack(Object i, csBuffer opb); + public abstract Object unpack(Info vi , csBuffer opb); + public abstract Object look(DspState vd, InfoMode vm, Object i); + public abstract void free_info(Object i); + public abstract void free_look(Object i); + public abstract int forward(Block vb, Object i); + public abstract int inverse(Block vb, Object i, float[] fin, float[] fout); + } +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/Info.cs b/Support/OggUtils/csvorbis/Info.cs new file mode 100644 index 00000000..cc1d3c47 --- /dev/null +++ b/Support/OggUtils/csvorbis/Info.cs @@ -0,0 +1,574 @@ +/* csvorbis +* Copyright (C) 2000 ymnk, JCraft,Inc. +* +* Written by: 2000 ymnk +* Ported to C# from JOrbis by: Mark Crichton +* +* Thanks go to the JOrbis team, for licencing the code under the +* LGPL, making my job a lot easier. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Library General Public License +* as published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Library General Public License for more details. +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +using System; +using System.Text; +using csogg; + +namespace csvorbis +{ + public class Info + { + private static int OV_EBADPACKET=-136; + private static int OV_ENOTAUDIO=-135; + private static string _vorbis="vorbis"; + private static int VI_TIMEB=1; + private static int VI_FLOORB=2; + private static int VI_RESB=3; + private static int VI_MAPB=1; + private static int VI_WINDOWB=1; + + public int version; + public int channels; + public int rate; + + // The below bitrate declarations are *hints*. + // Combinations of the three values carry the following implications: + // + // all three set to the same value: + // implies a fixed rate bitstream + // only nominal set: + // implies a VBR stream that averages the nominal bitrate. No hard + // upper/lower limit + // upper and or lower set: + // implies a VBR bitstream that obeys the bitrate limits. nominal + // may also be set to give a nominal rate. + // none set: + // the coder does not care to speculate. + + internal int bitrate_upper; + internal int bitrate_nominal; + internal int bitrate_lower; + + // Vorbis supports only short and long blocks, but allows the + // encoder to choose the sizes + + internal int[] blocksizes=new int[2]; + + // modes are the primary means of supporting on-the-fly different + // blocksizes, different channel mappings (LR or mid-side), + // different residue backends, etc. Each mode consists of a + // blocksize flag and a mapping (along with the mapping setup + + internal int modes; + internal int maps; + internal int times; + internal int floors; + internal int residues; + internal int books; + internal int psys; // encode only + + internal InfoMode[] mode_param=null; + + internal int[] map_type=null; + internal Object[] map_param=null; + + internal int[] time_type=null; + internal Object[] time_param=null; + + internal int[] floor_type=null; + internal Object[] floor_param=null; + + internal int[] residue_type=null; + internal Object[] residue_param=null; + + internal StaticCodeBook[] book_param=null; + + internal PsyInfo[] psy_param=new PsyInfo[64]; // encode only + + // for block long/sort tuning; encode only + //internal int envelopesa; + //internal float preecho_thresh; + //internal float preecho_clamp; + + // used by synthesis, which has a full, alloced vi + public void init() + { + rate=0; + //memset(vi,0,sizeof(vorbis_info)); + } + + public void clear() + { + for(int i=0;ibook_param)free(vi->book_param); + book_param=null; + + for(int i=0;ipsy_param)free(vi->psy_param); + //memset(vi,0,sizeof(vorbis_info)); + } + + // Header packing/unpacking + int unpack_info(csBuffer opb) + { + version=opb.read(32); + if(version!=0)return(-1); + + channels=opb.read(8); + rate=opb.read(32); + + bitrate_upper=opb.read(32); + bitrate_nominal=opb.read(32); + bitrate_lower=opb.read(32); + + blocksizes[0]=1<=VI_TIMEB) + { + //goto err_out; + clear(); + return(-1); + } + time_param[i]=FuncTime.time_P[time_type[i]].unpack(this, opb); + if(time_param[i]==null) + { + //goto err_out; + clear(); + return(-1); + } + } + + // floor backend settings + floors=opb.read(6)+1; + if(floor_type==null || floor_type.Length!=floors) + floor_type=new int[floors]; + if(floor_param==null || floor_param.Length!=floors) + floor_param=new Object[floors]; + + for(int i=0;i=VI_FLOORB) + { + //goto err_out; + clear(); + return(-1); + } + + floor_param[i]=FuncFloor.floor_P[floor_type[i]].unpack(this,opb); + if(floor_param[i]==null) + { + //goto err_out; + clear(); + return(-1); + } + } + + // residue backend settings + residues=opb.read(6)+1; + + if(residue_type==null || residue_type.Length!=residues) + residue_type=new int[residues]; + + if(residue_param==null || residue_param.Length!=residues) + residue_param=new Object[residues]; + + for(int i=0;i=VI_RESB) + { + // goto err_out; + clear(); + return(-1); + } + residue_param[i]=FuncResidue.residue_P[residue_type[i]].unpack(this,opb); + if(residue_param[i]==null) + { + // goto err_out; + clear(); + return(-1); + } + } + + // map backend settings + maps=opb.read(6)+1; + if(map_type==null || map_type.Length!=maps) map_type=new int[maps]; + if(map_param==null || map_param.Length!=maps) map_param=new Object[maps]; + for(int i=0;i=VI_MAPB) + { + // goto err_out; + clear(); + return(-1); + } + map_param[i]=FuncMapping.mapping_P[map_type[i]].unpack(this,opb); + if(map_param[i]==null) + { + // goto err_out; + clear(); + return(-1); + } + } + + // mode settings + modes=opb.read(6)+1; + if(mode_param==null || mode_param.Length!=modes) + mode_param=new InfoMode[modes]; + for(int i=0;i=VI_WINDOWB)|| + (mode_param[i].transformtype>=VI_WINDOWB)|| + (mode_param[i].mapping>=maps)) + { + // goto err_out; + clear(); + return(-1); + } + } + + if(opb.read(1)!=1) + { + //goto err_out; // top level EOP check + clear(); + return(-1); + } + + return(0); + // err_out: + // vorbis_info_clear(vi); + // return(-1); + } + + // The Vorbis header is in three packets; the initial small packet in + // the first page that identifies basic parameters, a second packet + // with bitstream comments and a third packet that holds the + // codebook. + + public int synthesis_headerin(Comment vc, Packet op) + { + csBuffer opb=new csBuffer(); + + if(op!=null) + { + opb.readinit(op.packet_base, op.packet, op.bytes); + + // Which of the three types of header is this? + // Also verify header-ness, vorbis + { + byte[] buffer=new byte[6]; + int packtype=opb.read(8); + //memset(buffer,0,6); + opb.read(buffer,6); + if(buffer[0]!='v' || buffer[1]!='o' || buffer[2]!='r' || + buffer[3]!='b' || buffer[4]!='i' || buffer[5]!='s') + { + // not a vorbis header + return(-1); + } + switch(packtype) + { + case 0x01: // least significant *bit* is read first + if(op.b_o_s==0) + { + // Not the initial packet + return(-1); + } + if(rate!=0) + { + // previously initialized info header + return(-1); + } + return(unpack_info(opb)); + case 0x03: // least significant *bit* is read first + if(rate==0) + { + // um... we didn't get the initial header + return(-1); + } + return(vc.unpack(opb)); + case 0x05: // least significant *bit* is read first + if(rate==0 || vc.vendor==null) + { + // um... we didn;t get the initial header or comments yet + return(-1); + } + return(unpack_books(opb)); + default: + // Not a valid vorbis header type + //return(-1); + break; + } + } + } + return(-1); + } + + // pack side + int pack_info(csBuffer opb) + { + Encoding AE = Encoding.UTF8; + byte[] _vorbis_byt = AE.GetBytes(_vorbis); + + // preamble + opb.write(0x01,8); + opb.write(_vorbis_byt); + + // basic information about the stream + opb.write(0x00,32); + opb.write(channels,8); + opb.write(rate,32); + + opb.write(bitrate_upper,32); + opb.write(bitrate_nominal,32); + opb.write(bitrate_lower,32); + + opb.write(ilog2(blocksizes[0]),4); + opb.write(ilog2(blocksizes[1]),4); + opb.write(1,1); + return(0); + } + + int pack_books(csBuffer opb) + { + Encoding AE = Encoding.UTF8; + byte[] _vorbis_byt = AE.GetBytes(_vorbis); + + opb.write(0x05,8); + opb.write(_vorbis_byt); + + // books + opb.write(books-1,8); + for(int i=0;icodec_setup; + csBuffer opb=new csBuffer(); + // synchronized(opb_blocksize){ + int mode; + + opb.readinit(op.packet_base, op.packet, op.bytes); + + /* Check the packet type */ + if(opb.read(1)!=0) + { + /* Oops. This is not an audio data packet */ + return(OV_ENOTAUDIO); + } + { + int modebits=0; + int v=modes; + while(v>1) + { + modebits++; + v = (int)((uint)v >> 1); + } + + /* read our mode and pre/post windowsize */ + mode=opb.read(modebits); + } + if(mode==-1)return(OV_EBADPACKET); + return(blocksizes[mode_param[mode].blockflag]); + // } + } + + private static int ilog2(int v) + { + int ret=0; + while(v>1) + { + ret++; + v = (int)((uint)v >> 1); + } + return(ret); + } + + public String toString() + { + return "version:"+ version.ToString() + + ", channels:"+ channels.ToString() + + ", rate:"+ rate.ToString() + + ", bitrate:"+ bitrate_upper.ToString() +","+ + bitrate_nominal.ToString() +","+ + bitrate_lower.ToString(); + } + } +} diff --git a/Support/OggUtils/csvorbis/InfoMode.cs b/Support/OggUtils/csvorbis/InfoMode.cs new file mode 100644 index 00000000..4450b2e7 --- /dev/null +++ b/Support/OggUtils/csvorbis/InfoMode.cs @@ -0,0 +1,38 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + class InfoMode + { + internal int blockflag; + internal int windowtype; + internal int transformtype; + internal int mapping; + } +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/Lookup.cs b/Support/OggUtils/csvorbis/Lookup.cs new file mode 100644 index 00000000..2a6f5f16 --- /dev/null +++ b/Support/OggUtils/csvorbis/Lookup.cs @@ -0,0 +1,161 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + class Lookup + { + static int COS_LOOKUP_SZ=128; + static float[] COS_LOOKUP={ + +1.0000000000000f,+0.9996988186962f,+0.9987954562052f,+0.9972904566787f, + +0.9951847266722f,+0.9924795345987f,+0.9891765099648f,+0.9852776423889f, + +0.9807852804032f,+0.9757021300385f,+0.9700312531945f,+0.9637760657954f, + +0.9569403357322f,+0.9495281805930f,+0.9415440651830f,+0.9329927988347f, + +0.9238795325113f,+0.9142097557035f,+0.9039892931234f,+0.8932243011955f, + +0.8819212643484f,+0.8700869911087f,+0.8577286100003f,+0.8448535652497f, + +0.8314696123025f,+0.8175848131516f,+0.8032075314806f,+0.7883464276266f, + +0.7730104533627f,+0.7572088465065f,+0.7409511253550f,+0.7242470829515f, + +0.7071067811865f,+0.6895405447371f,+0.6715589548470f,+0.6531728429538f, + +0.6343932841636f,+0.6152315905806f,+0.5956993044924f,+0.5758081914178f, + +0.5555702330196f,+0.5349976198871f,+0.5141027441932f,+0.4928981922298f, + +0.4713967368260f,+0.4496113296546f,+0.4275550934303f,+0.4052413140050f, + +0.3826834323651f,+0.3598950365350f,+0.3368898533922f,+0.3136817403989f, + +0.2902846772545f,+0.2667127574749f,+0.2429801799033f,+0.2191012401569f, + +0.1950903220161f,+0.1709618887603f,+0.1467304744554f,+0.1224106751992f, + +0.0980171403296f,+0.0735645635997f,+0.0490676743274f,+0.0245412285229f, + +0.0000000000000f,-0.0245412285229f,-0.0490676743274f,-0.0735645635997f, + -0.0980171403296f,-0.1224106751992f,-0.1467304744554f,-0.1709618887603f, + -0.1950903220161f,-0.2191012401569f,-0.2429801799033f,-0.2667127574749f, + -0.2902846772545f,-0.3136817403989f,-0.3368898533922f,-0.3598950365350f, + -0.3826834323651f,-0.4052413140050f,-0.4275550934303f,-0.4496113296546f, + -0.4713967368260f,-0.4928981922298f,-0.5141027441932f,-0.5349976198871f, + -0.5555702330196f,-0.5758081914178f,-0.5956993044924f,-0.6152315905806f, + -0.6343932841636f,-0.6531728429538f,-0.6715589548470f,-0.6895405447371f, + -0.7071067811865f,-0.7242470829515f,-0.7409511253550f,-0.7572088465065f, + -0.7730104533627f,-0.7883464276266f,-0.8032075314806f,-0.8175848131516f, + -0.8314696123025f,-0.8448535652497f,-0.8577286100003f,-0.8700869911087f, + -0.8819212643484f,-0.8932243011955f,-0.9039892931234f,-0.9142097557035f, + -0.9238795325113f,-0.9329927988347f,-0.9415440651830f,-0.9495281805930f, + -0.9569403357322f,-0.9637760657954f,-0.9700312531945f,-0.9757021300385f, + -0.9807852804032f,-0.9852776423889f,-0.9891765099648f,-0.9924795345987f, + -0.9951847266722f,-0.9972904566787f,-0.9987954562052f,-0.9996988186962f, + -1.0000000000000f, + }; + /* interpolated lookup based cos function, domain 0 to PI only */ + internal static float coslook(float a) + { + double d=a*(.31830989*(float)COS_LOOKUP_SZ); + int i=(int)d; + return COS_LOOKUP[i]+ ((float)(d-i))*(COS_LOOKUP[i+1]-COS_LOOKUP[i]); + } + + static int INVSQ_LOOKUP_SZ=32; + static float[] INVSQ_LOOKUP={ + 1.414213562373f,1.392621247646f,1.371988681140f,1.352246807566f, + 1.333333333333f,1.315191898443f,1.297771369046f,1.281025230441f, + 1.264911064067f,1.249390095109f,1.234426799697f,1.219988562661f, + 1.206045378311f,1.192569588000f,1.179535649239f,1.166919931983f, + 1.154700538379f,1.142857142857f,1.131370849898f,1.120224067222f, + 1.109400392450f,1.098884511590f,1.088662107904f,1.078719779941f, + 1.069044967650f,1.059625885652f,1.050451462878f,1.041511287847f, + 1.032795558989f,1.024295039463f,1.016001016002f,1.007905261358f, + 1.000000000000f, + }; + /* interpolated 1./sqrt(p) where .5 <= p < 1. */ + internal static float invsqlook(float a) + { + // System.out.println(a); + double d=a*(2.0f*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ; + int i=(int)d; + return INVSQ_LOOKUP[i]+ ((float)(d-i))*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]); + } + + static int INVSQ2EXP_LOOKUP_MIN=-32; + //static int INVSQ2EXP_LOOKUP_MAX=32; + static float[] INVSQ2EXP_LOOKUP={ + 65536.0f, 46340.95001f, 32768.0f, 23170.47501f, + 16384.0f, 11585.2375f, 8192.0f, 5792.618751f, + 4096.0f, 2896.309376f, 2048.0f, 1448.154688f, + 1024.0f, 724.0773439f, 512.0f, 362.038672f, + 256.0f, 181.019336f, 128.0f, 90.50966799f, + 64.0f, 45.254834f, 32.0f, 22.627417f, + 16.0f, 11.3137085f, 8.0f, 5.656854249f, + 4.0f, 2.828427125f, 2.0f, 1.414213562f, + 1.0f, 0.7071067812f, 0.5f, 0.3535533906f, + 0.25f, 0.1767766953f, 0.125f, 0.08838834765f, + 0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f, + 0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f, + 0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f, + 0.0009765625f, 0.000690533966f, 0.00048828125f, 0.000345266983f, + 0.000244140625f,0.0001726334915f,0.0001220703125f,8.631674575e-05f, + 6.103515625e-05f,4.315837288e-05f,3.051757812e-05f,2.157918644e-05f, + 1.525878906e-05f, + }; + /* interpolated 1./sqrt(p) where .5 <= p < 1. */ + internal static float invsq2explook(int a) + { + return INVSQ2EXP_LOOKUP[a-INVSQ2EXP_LOOKUP_MIN]; + } + + const int FROMdB_LOOKUP_SZ=35; + const int FROMdB2_LOOKUP_SZ=32; + const int FROMdB_SHIFT=5; + const int FROMdB2_SHIFT=3; + const int FROMdB2_MASK=31; + static float[] FROMdB_LOOKUP = { + 1.0f, 0.6309573445f, 0.3981071706f, 0.2511886432f, + 0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f, + 0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f, + 0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f, + 0.0006309573445f,0.0003981071706f,0.0002511886432f,0.0001584893192f, + 0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f, + 1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f, + 2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f, + 3.981071706e-07f,2.511886432e-07f,1.584893192e-07f, + }; + static float[] FROMdB2_LOOKUP = { + 0.9928302478f, 0.9786445908f, 0.9646616199f, 0.9508784391f, + 0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f, + 0.8848608897f, 0.8722179097f, 0.8597555737f, 0.8474713009f, + 0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f, + 0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f, + 0.7445176537f, 0.7338799116f, 0.7233941627f, 0.7130582353f, + 0.7028699885f, 0.6928273125f, 0.6829281272f, 0.6731703824f, + 0.6635520573f, 0.6540711597f, 0.6447257262f, 0.6355138211f, + }; + /* interpolated lookup based fromdB function, domain -140dB to 0dB only */ + internal static float fromdBlook(float a) + { + int i=(int)(a*((float)(-(1<=(FROMdB_LOOKUP_SZ<>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); + } + + } +} diff --git a/Support/OggUtils/csvorbis/Lpc.cs b/Support/OggUtils/csvorbis/Lpc.cs new file mode 100644 index 00000000..2cd9b4cf --- /dev/null +++ b/Support/OggUtils/csvorbis/Lpc.cs @@ -0,0 +1,200 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + class Lpc + { + Drft fft=new Drft(); + + int ln; + int m; + + // Autocorrelation LPC coeff generation algorithm invented by + // N. Levinson in 1947, modified by J. Durbin in 1959. + + // Input : n elements of time doamin data + // Output: m lpc coefficients, excitation energy + + static float lpc_from_data(float[] data, float[] lpc,int n,int m) + { + float[] aut=new float[m+1]; + float error; + int i,j; + + // autocorrelation, p+1 lag coefficients + + j=m+1; + while(j--!=0) + { + float d=0.0F; + for(i=j;iln*2); + for(int i=0; i + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using System.Runtime.InteropServices; +using csogg; + +namespace csvorbis +{ + /* + function: LSP (also called LSF) conversion routines + + The LSP generation code is taken (with minimal modification) from + "On the Computation of the LSP Frequencies" by Joseph Rothweiler + , available at: + + http://www2.xtdl.com/~rothwlr/lsfpaper/lsfpage.html + ********************************************************************/ + + class Lsp + { + + [StructLayout(LayoutKind.Explicit, Size=32, CharSet=CharSet.Ansi)] + struct FloatHack + { + [FieldOffset(0)] public float fh_float; + [FieldOffset(0)] public int fh_int; + } + static float M_PI=(float)(3.1415926539); + + internal static void lsp_to_curve(float[] curve, + int[] map, int n, int ln, + float[] lsp, int m, + float amp, float ampoffset) + { + int i; + float wdel=M_PI/ln; + for(i=0;i> 1); + + for(int j=0;j=0x7f800000||(ix==0)) + { + // 0,inf,nan + } + else + { + if(ix<0x00800000) + { // subnormal + q*=3.3554432000e+07F; // 0x4c000000 + fh.fh_float = q; + hx=fh.fh_int; + ix=0x7fffffff&hx; + qexp=-25; + } + qexp += (int)(((uint)ix >> 23)-126); + hx=(int)((hx&0x807fffff)|0x3f000000); + fh.fh_int = hx; + q=fh.fh_float; + } + + q=Lookup.fromdBlook(amp* + Lookup.invsqlook(q)* + Lookup.invsq2explook(qexp+m)-ampoffset); + + do{curve[i]*=q; i++;} + // do{curve[i++]=q;} + while(i + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +using System; +using csogg; + +namespace csvorbis +{ + class Mapping0 : FuncMapping + { + //static int seq=0; + override public void free_info(Object imap){} + override public void free_look(Object imap){} + + override public Object look(DspState vd, InfoMode vm, Object m) + { + Info vi=vd.vi; + LookMapping0 looks=new LookMapping0(); + InfoMapping0 info=looks.map=(InfoMapping0)m; + looks.mode=vm; + + looks.time_look=new Object[info.submaps]; + looks.floor_look=new Object[info.submaps]; + looks.residue_look=new Object[info.submaps]; + + looks.time_func=new FuncTime[info.submaps]; + looks.floor_func=new FuncFloor[info.submaps]; + looks.residue_func=new FuncResidue[info.submaps]; + + for(int i=0;i1) + { + opb.write(1,1); + opb.write(info.submaps-1,4); + } + else + { + opb.write(0,1); + } + + if(info.coupling_steps>0) + { + opb.write(1,1); + opb.write(info.coupling_steps-1,8); + for(int i=0;i1) + { + for(int i=0;i=vi.channels || + testA>=vi.channels) + { + //goto err_out; + info.free(); + return(null); + } + } + } + + if(opb.read(2)>0) + { /* 2,3:reserved */ + //goto err_out; + info.free(); + return(null); + } + + if(info.submaps>1) + { + for(int i=0;i=info.submaps) + { + //goto err_out; + info.free(); + return(null); + } + } + } + + for(int i=0;i=vi.times) + { + //goto err_out; + info.free(); + return(null); + } + info.floorsubmap[i]=opb.read(8); + if(info.floorsubmap[i]>=vi.floors) + { + //goto err_out; + info.free(); + return(null); + } + info.residuesubmap[i]=opb.read(8); + if(info.residuesubmap[i]>=vi.residues) + { + //goto err_out; + info.free(); + return(null); + } + } + return info; + //err_out: + //free_info(info); + //return(NULL); + } + + + float[][] pcmbundle=null; + int[] zerobundle=null; + int[] nonzero=null; + Object[] floormemo=null; + + override public int inverse(Block vb, Object l) + { + lock(this) + { + //System.err.println("Mapping0.inverse"); + DspState vd=vb.vd; + Info vi=vd.vi; + LookMapping0 look=(LookMapping0)l; + InfoMapping0 info=look.map; + InfoMode mode=look.mode; + int n=vb.pcmend=vi.blocksizes[vb.W]; + + float[] window=vd.wnd[vb.W][vb.lW][vb.nW][mode.windowtype]; + // float[][] pcmbundle=new float[vi.channels][]; + // int[] nonzero=new int[vi.channels]; + if(pcmbundle==null || pcmbundle.Length=0;i--) + { + float[] pcmM=vb.pcm[info.coupling_mag[i]]; + float[] pcmA=vb.pcm[info.coupling_ang[i]]; + + for(int j=0;j0) + { + if(ang>0) + { + pcmM[j]=mag; + pcmA[j]=mag-ang; + } + else + { + pcmA[j]=mag; + pcmM[j]=mag+ang; + } + } + else + { + if(ang>0) + { + pcmM[j]=mag; + pcmA[j]=mag+ang; + } + else + { + pcmA[j]=mag; + pcmM[j]=mag-ang; + } + } + } + } + + // /* compute and apply spectral envelope */ + + for(int i=0;i1) + { + ret++; + v = (int)((uint)v >> 1); + } + return(ret); + } + } + + class InfoMapping0 + { + internal int submaps; // <= 16 + internal int[] chmuxlist=new int[256]; // up to 256 channels in a Vorbis stream + + internal int[] timesubmap=new int[16]; // [mux] + internal int[] floorsubmap=new int[16]; // [mux] submap to floors + internal int[] residuesubmap=new int[16];// [mux] submap to residue + internal int[] psysubmap=new int[16]; // [mux]; encode only + + internal int coupling_steps; + internal int[] coupling_mag=new int[256]; + internal int[] coupling_ang=new int[256]; + + internal void free() + { + chmuxlist=null; + timesubmap=null; + floorsubmap=null; + residuesubmap=null; + psysubmap=null; + + coupling_mag=null; + coupling_ang=null; + } + } + + class LookMapping0 + { + internal InfoMode mode; + internal InfoMapping0 map; + internal Object[] time_look; + internal Object[] floor_look; + //Object[] floor_state; + internal Object[] residue_look; + //PsyLook[] psy_look; + + internal FuncTime[] time_func; + internal FuncFloor[] floor_func; + internal FuncResidue[] residue_func; + + internal int ch; + //float[][] decay; + //int lastframe; // if a different mode is called, we need to + // invalidate decay and floor state + } +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/Mdct.cs b/Support/OggUtils/csvorbis/Mdct.cs new file mode 100644 index 00000000..cacce9cc --- /dev/null +++ b/Support/OggUtils/csvorbis/Mdct.cs @@ -0,0 +1,274 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using System.Runtime.CompilerServices; +using csogg; + +namespace csvorbis +{ + class Mdct + { + + //static private float cPI3_8=0.38268343236508977175f; + //static private float cPI2_8=0.70710678118654752441f; + //static private float cPI1_8=0.92387953251128675613f; + + int n; + int log2n; + + float[] trig; + int[] bitrev; + + float scale; + + internal void init(int n) + { + bitrev=new int[n/4]; + trig=new float[n+n/4]; + + int n2=(int)((uint)n >> 1); + log2n=(int)Math.Round(Math.Log(n)/Math.Log(2)); + this.n=n; + + + int AE=0; + int AO=1; + int BE=AE+n/2; + int BO=BE+1; + int CE=BE+n/2; + int CO=CE+1; + // trig lookups... + for(int i=0;i> j) != 0; j++) + if(((((uint)msb>>j))&i) != 0) + acc |= 1 << j; + bitrev[i*2]=((~acc)&mask); + // bitrev[i*2]=((~acc)&mask)-1; + bitrev[i*2+1]=acc; + } + } + scale=4.0f/n; + } + + internal void clear() + { + } + + internal void forward(float[] fin, float[] fout) + { + } + + float[] _x=new float[1024]; + float[] _w=new float[1024]; + + + [MethodImpl(MethodImplOptions.Synchronized)] + internal void backward(float[] fin, float[] fout) + { + if(_x.Length < n/2){_x=new float[n/2];} + if(_w.Length < n/2){_w=new float[n/2];} + float[] x=_x; + float[] w=_w; + int n2=(int)((uint)n >> 1); + int n4=(int)((uint)n >> 2); + int n8=(int)((uint)n >> 3); + + // rotate + step 1 + { + int inO=1; + int xO=0; + int A=n2; + + int i; + for(i=0;i> (i+2)); + int k1=1 << (i+3); + int wbase=n2-2; + + A=0; + float[] temp; + + for(int r=0; r<((uint)k0>>2); r++) + { + int w1=wbase; + w2=w1-(k0>>1); + float AEv= trig[A],wA; + float AOv= trig[A+1],wB; + wbase-=2; + + k0++; + for(int s=0;s<(2< +* Ported to C# from JOrbis by: Mark Crichton +* +* Thanks go to the JOrbis team, for licencing the code under the +* LGPL, making my job a lot easier. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Library General Public License +* as published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Library General Public License for more details. +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +using System; +using csogg; + +namespace csvorbis +{ + // psychoacoustic setup + class PsyInfo + { + //int athp; + //int decayp; + //int smoothp; + //int noisefitp; + //int noisefit_subblock; + //float noisefit_threshdB; + + //float ath_att; + + //int tonemaskp; + float[] toneatt_125Hz=new float[5]; + float[] toneatt_250Hz=new float[5]; + float[] toneatt_500Hz=new float[5]; + float[] toneatt_1000Hz=new float[5]; + float[] toneatt_2000Hz=new float[5]; + float[] toneatt_4000Hz=new float[5]; + float[] toneatt_8000Hz=new float[5]; + + //int peakattp; + float[] peakatt_125Hz=new float[5]; + float[] peakatt_250Hz=new float[5]; + float[] peakatt_500Hz=new float[5]; + float[] peakatt_1000Hz=new float[5]; + float[] peakatt_2000Hz=new float[5]; + float[] peakatt_4000Hz=new float[5]; + float[] peakatt_8000Hz=new float[5]; + + //int noisemaskp; + float[] noiseatt_125Hz=new float[5]; + float[] noiseatt_250Hz=new float[5]; + float[] noiseatt_500Hz=new float[5]; + float[] noiseatt_1000Hz=new float[5]; + float[] noiseatt_2000Hz=new float[5]; + float[] noiseatt_4000Hz=new float[5]; + float[] noiseatt_8000Hz=new float[5]; + + //float max_curve_dB; + + //float attack_coeff; + //float decay_coeff; + + internal void free(){} + } +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/PsyLook.cs b/Support/OggUtils/csvorbis/PsyLook.cs new file mode 100644 index 00000000..9e1aa69f --- /dev/null +++ b/Support/OggUtils/csvorbis/PsyLook.cs @@ -0,0 +1,46 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +using System; +using csogg; + +namespace csvorbis +{ + class PsyLook + { + //int n; + //PsyInfo vi; + + //float[][][] tonecurves; + //float[][] peakatt; + //float[][][] noisecurves; + + //float[] ath; + //int[] octave; + + void init(PsyInfo vi, int n, int rate) + { + } + } +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/Residue0.cs b/Support/OggUtils/csvorbis/Residue0.cs new file mode 100644 index 00000000..203197e4 --- /dev/null +++ b/Support/OggUtils/csvorbis/Residue0.cs @@ -0,0 +1,415 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +using System; +using System.Runtime.CompilerServices; +using csogg; + +namespace csvorbis +{ + class Residue0 : FuncResidue + { + override public void pack(Object vr, csBuffer opb) + { + InfoResidue0 info=(InfoResidue0)vr; + int acc=0; + opb.write(info.begin,24); + opb.write(info.end,24); + + opb.write(info.grouping-1,24); /* residue vectors to group and + code with a partitioned book */ + opb.write(info.partitions-1,6); /* possible partition choices */ + opb.write(info.groupbook,8); /* group huffman book */ + + /* secondstages is a bitmask; as encoding progresses pass by pass, a + bitmask of one indicates this partition class has bits to write + this pass */ + for(int j=0;j3) + { + /* yes, this is a minor hack due to not thinking ahead */ + opb.write(info.secondstages[j],3); + opb.write(1,1); + opb.write(info.secondstages[j] >> 3,5); + } + else + { + opb.write(info.secondstages[j],4); /* trailing zero */ + } + acc+=icount(info.secondstages[j]); + } + for(int j=0;j=vi.books) + { + free_info(info); + return(null); + } + + for(int j=0;j=vi.books) + { + free_info(info); + return(null); + } + } + return(info); + // errout: + // free_info(info); + // return(NULL); + } + + override public Object look(DspState vd, InfoMode vm, Object vr) + { + InfoResidue0 info=(InfoResidue0)vr; + LookResidue0 look=new LookResidue0(); + int acc=0; + int dim; + int maxstage=0; + look.info=info; + look.map=vm.mapping; + + look.parts=info.partitions; + look.fullbooks=vd.fullbooks; + look.phrasebook=vd.fullbooks[info.groupbook]; + + dim=look.phrasebook.dim; + + look.partbooks=new int[look.parts][]; + + for(int j=0;jmaxstage)maxstage=stages; + look.partbooks[j]=new int[stages]; + for(int k=0; k> 1); + } + return(ret); + } + internal static int icount(int v) + { + int ret=0; + while(v!=0) + { + ret+=(v&1); + v = (int)((uint)v >> 1); + } + return(ret); + } + } + + class LookResidue0 + { + internal InfoResidue0 info; + internal int map; + + internal int parts; + internal int stages; + internal CodeBook[] fullbooks; + internal CodeBook phrasebook; + internal int[][] partbooks; + // CodeBook[][] partbooks; + + internal int partvals; + internal int[][] decodemap; + + //internal int postbits; + //internal int phrasebits; + // int[][] frames; + //internal int frames; + } + + class InfoResidue0 + { + // block-partitioned VQ coded straight residue + internal int begin; + internal int end; + + // first stage (lossless partitioning) + internal int grouping; // group n vectors per partition + internal int partitions; // possible codebooks for a partition + internal int groupbook; // huffbook for partitioning + internal int[] secondstages=new int[64]; // expanded out to pointers in lookup + internal int[] booklist=new int[256]; // list of second stage books + + // encode-only heuristic settings + internal float[] entmax=new float[64]; // book entropy threshholds + internal float[] ampmax=new float[64]; // book amp threshholds + internal int[] subgrp=new int[64]; // book heuristic subgroup size + internal int[] blimit=new int[64]; // subgroup position limits + } +} \ No newline at end of file diff --git a/Support/OggUtils/csvorbis/Residue1.cs b/Support/OggUtils/csvorbis/Residue1.cs new file mode 100644 index 00000000..f469e6be --- /dev/null +++ b/Support/OggUtils/csvorbis/Residue1.cs @@ -0,0 +1,59 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + class Residue1 : Residue0 + { + new int forward(Block vb,Object vl, float[][] fin, int ch) + { + return 0; + } + + override public int inverse(Block vb, Object vl, float[][] fin, int[] nonzero, int ch) + { + //System.err.println("Residue0.inverse"); + int used=0; + for(int i=0; i + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + class Residue2 : Residue0 + { + override public int forward(Block vb,Object vl, float[][] fin, int ch) + { + return 0; + } + + override public int inverse(Block vb, Object vl, float[][] fin, int[] nonzero, int ch) + { + //System.err.println("Residue0.inverse"); + int i=0; + for(i=0;i + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + class StaticCodeBook + { + internal int dim; // codebook dimensions (elements per vector) + internal int entries; // codebook entries + internal int[] lengthlist; // codeword lengths in bits + + // mapping + internal int maptype; // 0=none + // 1=implicitly populated values from map column + // 2=listed arbitrary values + + // The below does a linear, single monotonic sequence mapping. + internal int q_min; // packed 32 bit float; quant value 0 maps to minval + internal int q_delta; // packed 32 bit float; val 1 - val 0 == delta + internal int q_quant; // bits: 0 < quant <= 16 + internal int q_sequencep; // bitflag + + // additional information for log (dB) mapping; the linear mapping + // is assumed to actually be values in dB. encodebias is used to + // assign an error weight to 0 dB. We have two additional flags: + // zeroflag indicates if entry zero is to represent -Inf dB; negflag + // indicates if we're to represent negative linear values in a + // mirror of the positive mapping. + + internal int[] quantlist; // map == 1: (int)(entries/dim) element column map + // map == 2: list of dim*entries quantized entry vals + + // encode helpers + internal EncodeAuxNearestMatch nearest_tree; + internal EncodeAuxThreshMatch thresh_tree; + + internal StaticCodeBook(){} + internal StaticCodeBook(int dim, int entries, int[] lengthlist, + int maptype, int q_min, int q_delta, + int q_quant, int q_sequencep, int[] quantlist, + //EncodeAuxNearestmatch nearest_tree, + Object nearest_tree, + // EncodeAuxThreshmatch thresh_tree, + Object thresh_tree + ) : this() + { + this.dim=dim; this.entries=entries; this.lengthlist=lengthlist; + this.maptype=maptype; this.q_min=q_min; this.q_delta=q_delta; + this.q_quant=q_quant; this.q_sequencep=q_sequencep; + this.quantlist=quantlist; + } + + internal int pack(csBuffer opb) + { + int i; + bool ordered=false; + + opb.write(0x564342,24); + opb.write(dim, 16); + opb.write(entries, 24); + + // pack the codewords. There are two packings; length ordered and + // length random. Decide between the two now. + + for(i=1;i_last) + { + for(int j=_last;j<_this;j++) + { + opb.write(i-count,ilog(entries-count)); + count=i; + } + } + } + opb.write(i-count,ilog(entries-count)); + } + else + { + // length random. Again, we don't code the codeword itself, just + // the length. This time, though, we have to encode each length + opb.write(0,1); // unordered + + // algortihmic mapping has use for 'unused entries', which we tag + // here. The algorithmic mapping happens as usual, but the unused + // entry has no codeword. + for(i=0;ientries/c->dim) quantized values for + // building a full value list algorithmically (square lattice) + quantvals=maptype1_quantvals(); + break; + case 2: + // every value (c->entries*c->dim total) specified explicitly + quantvals=entries*dim; + break; + } + + // quantized values + for(i=0;ibim <= b->entries + // treat the above as an initial guess + while(true) + { + int acc=1; + int acc1=1; + for(int i=0;ientries){ return(vals); } + else + { + if(acc>entries){ vals--; } + else{ vals++; } + } + } + } + + internal void clear() + { + // if(quantlist!=null)free(b->quantlist); + // if(lengthlist!=null)free(b->lengthlist); + // if(nearest_tree!=null){ + // free(b->nearest_tree->ptr0); + // free(b->nearest_tree->ptr1); + // free(b->nearest_tree->p); + // free(b->nearest_tree->q); + // memset(b->nearest_tree,0,sizeof(encode_aux_nearestmatch)); + // free(b->nearest_tree); + // } + // if(thresh_tree!=null){ + // free(b->thresh_tree->quantthresh); + // free(b->thresh_tree->quantmap); + // memset(b->thresh_tree,0,sizeof(encode_aux_threshmatch)); + // free(b->thresh_tree); + // } + // memset(b,0,sizeof(static_codebook)); + } + + // unpack the quantized list of values for encode/decode + // we need to deal with two map types: in map type 1, the values are + // generated algorithmically (each column of the vector counts through + // the values in the quant vector). in map type 2, all the values came + // in in an explicit list. Both value lists must be unpacked + internal float[] unquantize() + { + + if(maptype==1 || maptype==2) + { + int quantvals; + float mindel=float32_unpack(q_min); + float delta=float32_unpack(q_delta); + float[] r=new float[entries*dim]; + + //System.err.println("q_min="+q_min+", mindel="+mindel); + + // maptype 1 and 2 both use a quantized value vector, but + // different sizes + switch(maptype) + { + case 1: + // most of the time, entries%dimensions == 0, but we need to be + // well defined. We define that the possible vales at each + // scalar is values == entries/dim. If entries%dim != 0, we'll + // have 'too few' values (values*dim "+val+" | ");} + val=Math.Abs(val)*delta+mindel+last; + if(q_sequencep!=0)last=val; + r[j*dim+k]=val; + //if((j*dim+k)==0){System.err.println(" $ r[0] -> "+r[0]+" | ");} + } + } + //System.err.println("\nr[0]="+r[0]); + break; + default: + break; + } + return(r); + } + return(null); + } + + internal static int ilog(int v) + { + int ret=0; + while(v!=0) + { + ret++; + v = (int)((uint)v >> 1); + } + return(ret); + } + + // 32 bit float (not IEEE; nonnormalized mantissa + + // biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm + // Why not IEEE? It's just not that important here. + + //static int VQ_FEXP=10; + static int VQ_FMAN=21; + static int VQ_FEXP_BIAS=768; // bias toward values smaller than 1. + + // doesn't currently guard under/overflow + internal static long float32_pack(float val) + { + uint sign=0; + int exp; + int mant; + if(val<0) + { + sign = 0x80000000; + val = -val; + } + exp=(int)Math.Floor(Math.Log(val)/Math.Log(2)); + mant=(int)Math.Round(Math.Pow(val,(VQ_FMAN-1)-exp)); + exp=(exp+VQ_FEXP_BIAS)<> VQ_FMAN; + //System.err.println("mant="+mant+", sign="+sign+", exp="+exp); + //if(sign!=0.0)mant= -mant; + if((val&0x80000000)!=0)mant= -mant; + //System.err.println("mant="+mant); + return(ldexp(mant,((int)exp)-(VQ_FMAN-1)-VQ_FEXP_BIAS)); + } + + internal static float ldexp(float foo, int e) + { + return (float)(foo*Math.Pow(2, e)); + } + } +} diff --git a/Support/OggUtils/csvorbis/Time0.cs b/Support/OggUtils/csvorbis/Time0.cs new file mode 100644 index 00000000..c17efdab --- /dev/null +++ b/Support/OggUtils/csvorbis/Time0.cs @@ -0,0 +1,41 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using csogg; + +namespace csvorbis +{ + class Time0 : FuncTime + { + override public void pack(Object i, csBuffer opb){} + override public Object unpack(Info vi , csBuffer opb){return "";} + override public Object look(DspState vd, InfoMode mi, Object i){return "";} + override public void free_info(Object i){} + override public void free_look(Object i){} + override public int forward(Block vb, Object i){return 0;} + override public int inverse(Block vb, Object i, float[] fin, float[] fout){return 0;} + } +} diff --git a/Support/OggUtils/csvorbis/VorbisFile.cs b/Support/OggUtils/csvorbis/VorbisFile.cs new file mode 100644 index 00000000..92e40033 --- /dev/null +++ b/Support/OggUtils/csvorbis/VorbisFile.cs @@ -0,0 +1,1434 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +using System; +using System.IO; +using csogg; + +namespace csvorbis +{ + public class VorbisFile + { + static int CHUNKSIZE=8500; + static int SEEK_SET=0; + static int SEEK_CUR=1; + static int SEEK_END=2; + + static int OV_FALSE=-1; + static int OV_EOF=-2; + static int OV_HOLE=-3; + + static int OV_EREAD=-128; + static int OV_EFAULT=-129; + static int OV_EIMPL=-130; + static int OV_EINVAL=-131; + static int OV_ENOTVORBIS=-132; + static int OV_EBADHEADER=-133; + static int OV_EVERSION=-134; + static int OV_ENOTAUDIO=-135; + static int OV_EBADPACKET=-136; + static int OV_EBADLINK=-137; + static int OV_ENOSEEK=-138; + + FileStream datasource; + bool skable=false; + long offset; + long end; + + SyncState oy=new SyncState(); + + int links; + long[] offsets; + long[] dataoffsets; + int[] serialnos; + long[] pcmlengths; + Info[] vi; + Comment[] vc; + + // Decoding working state local storage + long pcm_offset; + bool decode_ready=false; + int current_serialno; + int current_link; + + float bittrack; + float samptrack; + + StreamState os; + DspState vd; + Block vb; + + + private VorbisFile() + { + os=new StreamState(); // take physical pages, weld into a logical + // stream of packets + vd=new DspState(); // central working state for + // the packet->PCM decoder + vb=new Block(vd); // local working space for packet->PCM decode + } + + public VorbisFile(String file) : this() + { + FileStream inst=null; + + try{ inst=new FileStream(file, FileMode.Open, FileAccess.Read);} + catch(Exception e) + { + throw new csorbisException("VorbisFile: "+e.Message); + } + int ret=open(inst, null, 0); + if(ret==-1) + { + throw new csorbisException("VorbisFile: open return -1"); + } + } + + public VorbisFile(FileStream inst, byte[] initial, int ibytes) : this() + { + int ret=open(inst, initial, ibytes); + } + + private int get_data() + { + int index=oy.buffer(CHUNKSIZE); + byte[] buffer=oy.data; + // int bytes=callbacks.read_func(buffer, index, 1, CHUNKSIZE, datasource); + int bytes=0; + try + { + bytes=datasource.Read(buffer, index, CHUNKSIZE); + } + catch(Exception e) + { + Console.Error.WriteLine(e.Message); + return OV_EREAD; + } + oy.wrote(bytes); + if(bytes==-1) + { + bytes=0; + } + return bytes; + } + + private void seek_helper(long offst) + { + //callbacks.seek_func(datasource, offst, SEEK_SET); + fseek(datasource, offst, SEEK_SET); + this.offset=offst; + oy.reset(); + } + + private int get_next_page(Page page, long boundary) + { + if(boundary>0) boundary+=offset; + while(true) + { + int more; + if(boundary>0 && offset>=boundary)return OV_FALSE; + more=oy.pageseek(page); + if(more<0){offset-=more;} + else + { + if(more==0) + { + if(boundary==0)return OV_FALSE; + // if(get_data()<=0)return -1; + int ret=get_data(); + if(ret==0) return OV_EOF; + if(ret<0) return OV_EREAD; + } + else + { + int ret=(int)offset; //!!! + offset+=more; + return ret; + } + } + } + } + + private int get_prev_page(Page page) + { + long begin=offset; //!!! + int ret; + int offst=-1; + while(offst==-1) + { + begin-=CHUNKSIZE; + if(begin<0) + begin=0; + seek_helper(begin); + while(offset=0)next=ret; + } + else + { + searched=ret+page.header_len+page.body_len; + } + } + seek_helper(next); + ret=get_next_page(page, -1); + if(ret==OV_EREAD) return OV_EREAD; + + if(searched>=end || ret==-1) + { + links=m+1; + offsets=new long[m+2]; + offsets[m+1]=searched; + } + else + { + ret=bisect_forward_serialno(next, offset, end, page.serialno(), m+1); + if(ret==OV_EREAD)return OV_EREAD; + } + offsets[m]=begin; + return 0; + } + + // uses the local ogg_stream storage in vf; this is important for + // non-streaming input sources + int fetch_headers(Info vi, Comment vc, int[] serialno, Page og_ptr) + { + //System.err.println("fetch_headers"); + Page og=new Page(); + Packet op=new Packet(); + int ret; + + if(og_ptr==null) + { + ret=get_next_page(og, CHUNKSIZE); + if(ret==OV_EREAD)return OV_EREAD; + if(ret<0) return OV_ENOTVORBIS; + og_ptr=og; + } + + if(serialno!=null)serialno[0]=og_ptr.serialno(); + + os.init(og_ptr.serialno()); + + // extract the initial header from the first page and verify that the + // Ogg bitstream is in fact Vorbis data + + vi.init(); + vc.init(); + + int i=0; + while(i<3) + { + os.pagein(og_ptr); + while(i<3) + { + int result=os.packetout(op); + if(result==0)break; + if(result==-1) + { + Console.Error.WriteLine("Corrupt header in logical bitstream."); + //goto bail_header; + vi.clear(); + vc.clear(); + os.clear(); + return -1; + } + if(vi.synthesis_headerin(vc, op)!=0) + { + Console.Error.WriteLine("Illegal header in logical bitstream."); + //goto bail_header; + vi.clear(); + vc.clear(); + os.clear(); + return -1; + } + i++; + } + if(i<3) + if(get_next_page(og_ptr, 1)<0) + { + Console.Error.WriteLine("Missing header in logical bitstream."); + //goto bail_header; + vi.clear(); + vc.clear(); + os.clear(); + return -1; + } + } + return 0; + } + + // last step of the OggVorbis_File initialization; get all the + // vorbis_info structs and PCM positions. Only called by the seekable + // initialization (local stream storage is hacked slightly; pay + // attention to how that's done) + void prefetch_all_headers(Info first_i,Comment first_c, int dataoffset) + { + Page og=new Page(); + int ret; + + vi=new Info[links]; + vc=new Comment[links]; + dataoffsets=new long[links]; + pcmlengths=new long[links]; + serialnos=new int[links]; + + for(int i=0;ivi+i,first_i,sizeof(vorbis_info)); + vc[i]=first_c; + //memcpy(vf->vc+i,first_c,sizeof(vorbis_comment)); + dataoffsets[i]=dataoffset; + } + else + { + // seek to the location of the initial header + seek_helper(offsets[i]); //!!! + if(fetch_headers(vi[i], vc[i], null, null)==-1) + { + Console.Error.WriteLine("Error opening logical bitstream #"+(i+1)+"\n"); + dataoffsets[i]=-1; + } + else + { + dataoffsets[i]=offset; + os.clear(); + } + } + + // get the serial number and PCM length of this link. To do this, + // get the last page of the stream + long end=offsets[i+1]; //!!! + seek_helper(end); + + while(true) + { + ret=get_prev_page(og); + if(ret==-1) + { + // this should not be possible + Console.Error.WriteLine("Could not find last page of logical "+ + "bitstream #"+(i)+"\n"); + vi[i].clear(); + vc[i].clear(); + break; + } + if(og.granulepos()!=-1) + { + serialnos[i]=og.serialno(); + pcmlengths[i]=og.granulepos(); + break; + } + } + } + } + + int make_decode_ready() + { +#if NET_2_1 + if(decode_ready) throw new Exception ("make_decode_ready: 1"); +#else + if(decode_ready)Environment.Exit(1); +#endif + vd.synthesis_init(vi[0]); + vb.init(vd); + decode_ready=true; + return(0); + } + + int open_seekable() + { + Info initial_i=new Info(); + Comment initial_c=new Comment(); + int serialno; + long end; + int ret; + int dataoffset; + Page og=new Page(); + // is this even vorbis...? + int[] foo=new int[1]; + ret=fetch_headers(initial_i, initial_c, foo, null); + serialno=foo[0]; + dataoffset=(int)offset; //!! + os.clear(); + if(ret==-1)return(-1); + // we can seek, so set out learning all about this file + skable=true; + //(callbacks.seek_func)(datasource, 0, SEEK_END); + fseek(datasource, 0, SEEK_END); + //offset=end=(callbacks.tell_func)(datasource); + offset=ftell(datasource); + end=offset; + // We get the offset for the last page of the physical bitstream. + // Most OggVorbis files will contain a single logical bitstream + end=get_prev_page(og); + // moer than one logical bitstream? + if(og.serialno()!=serialno) + { + // Chained bitstream. Bisect-search each logical bitstream + // section. Do so based on serial number only + if(bisect_forward_serialno(0,0,end+1,serialno,0)<0) + { + clear(); + return OV_EREAD; + } + } + else + { + // Only one logical bitstream + if(bisect_forward_serialno(0,end,end+1,serialno,0)<0) + { + clear(); + return OV_EREAD; + } + } + prefetch_all_headers(initial_i, initial_c, dataoffset); + return(raw_seek(0)); + } + + int open_nonseekable() + { + //System.err.println("open_nonseekable"); + // we cannot seek. Set up a 'single' (current) logical bitstream entry + links=1; + vi=new Info[links]; vi[0]=new Info(); // ?? + vc=new Comment[links]; vc[0]=new Comment(); // ?? bug? + + // Try to fetch the headers, maintaining all the storage + int[]foo=new int[1]; + if(fetch_headers(vi[0], vc[0], foo, null)==-1)return(-1); + current_serialno=foo[0]; + make_decode_ready(); + return 0; + } + + // clear out the current logical bitstream decoder + void decode_clear() + { + os.clear(); + vd.clear(); + vb.clear(); + decode_ready=false; + bittrack=0.0f; + samptrack=0.0f; + } + + // fetch and process a packet. Handles the case where we're at a + // bitstream boundary and dumps the decoding machine. If the decoding + // machine is unloaded, it loads it. It also keeps pcm_offset up to + // date (seek and read both use this. seek uses a special hack with + // readp). + // + // return: -1) hole in the data (lost packet) + // 0) need more date (only if readp==0)/eof + // 1) got a packet + + int process_packet(int readp) + { + Page og=new Page(); + + // handle one packet. Try to fetch it from current stream state + // extract packets from page + while(true) + { + // process a packet if we can. If the machine isn't loaded, + // neither is a page + if(decode_ready) + { + Packet op=new Packet(); + int result=os.packetout(op); + long granulepos; + // if(result==-1)return(-1); // hole in the data. For now, swallow + // and go. We'll need to add a real + // error code in a bit. + if(result>0) + { + // got a packet. process it + granulepos=op.granulepos; + if(vb.synthesis(op)==0) + { // lazy check for lazy + // header handling. The + // header packets aren't + // audio, so if/when we + // submit them, + // vorbis_synthesis will + // reject them + // suck in the synthesis data and track bitrate + { + int oldsamples=vd.synthesis_pcmout(null, null); + vd.synthesis_blockin(vb); + samptrack+=vd.synthesis_pcmout(null, null)-oldsamples; + bittrack+=op.bytes*8; + } + + // update the pcm offset. + if(granulepos!=-1 && op.e_o_s==0) + { + int link=(skable?current_link:0); + int samples; + // this packet has a pcm_offset on it (the last packet + // completed on a page carries the offset) After processing + // (above), we know the pcm position of the *last* sample + // ready to be returned. Find the offset of the *first* + // + // As an aside, this trick is inaccurate if we begin + // reading anew right at the last page; the end-of-stream + // granulepos declares the last frame in the stream, and the + // last packet of the last page may be a partial frame. + // So, we need a previous granulepos from an in-sequence page + // to have a reference point. Thus the !op.e_o_s clause above + + samples=vd.synthesis_pcmout(null, null); + granulepos-=samples; + for(int i=0;icallbacks.close_func)(vf->datasource); + //memset(vf,0,sizeof(OggVorbis_File)); + return(0); + } + + static int fseek(FileStream fis, + //int64_t off, + long off, + int whence) + { + if(fis.CanSeek == true) + { + try + { + if(whence==SEEK_SET) + { + fis.Seek(off, 0); + } + else if(whence==SEEK_END) + { + fis.Seek(fis.Length - off, 0); + } + else + { + Console.Error.WriteLine("seek: "+whence+" is not supported"); + } + } + catch(Exception e) + { + Console.Error.WriteLine(e.Message); + } + return 0; + } + try + { + if(whence==0){ fis.Seek(0, 0); } + fis.Seek(off, 0); + } + catch(Exception e) + { + Console.Error.WriteLine(e.Message); + return -1; + } + return 0; + } + + static long ftell(FileStream fis) + { + try + { + if(fis.CanSeek == true) + { + return (fis.Position); + } + } + catch(Exception e) + { + Console.Error.WriteLine(e.Message); + } + return 0; + } + + // inspects the OggVorbis file and finds/documents all the logical + // bitstreams contained in it. Tries to be tolerant of logical + // bitstream sections that are truncated/woogie. + // + // return: -1) error + // 0) OK + + int open(FileStream iis, byte[] initial, int ibytes) + { + return open_callbacks(iis, initial, ibytes); + } + + int open_callbacks(FileStream iis, byte[] initial, int ibytes) + { + int ret; + datasource=iis; + //callbacks = _callbacks; + // init the framing state + oy.init(); + + // perhaps some data was previously read into a buffer for testing + // against other stream types. Allow initialization from this + // previously read data (as we may be reading from a non-seekable + // stream) + if(initial!=null) + { + int index=oy.buffer(ibytes); + Array.Copy(initial, 0, oy.data, index, ibytes); + oy.wrote(ibytes); + } + // can we seek? Stevens suggests the seek test was portable + if(iis.CanSeek == true){ ret=open_seekable(); } + else{ ret=open_nonseekable(); } + if(ret!=0) + { + datasource=null; + clear(); + } + return(ret); + } + + // How many logical bitstreams in this physical bitstream? + public int streams() + { + return links; + } + + // Is the FILE * associated with vf seekable? + public bool seekable() + { + return skable; + } + + // returns the bitrate for a given logical bitstream or the entire + // physical bitstream. If the file is open for random access, it will + // find the *actual* average bitrate. If the file is streaming, it + // returns the nominal bitrate (if set) else the average of the + // upper/lower bounds (if set) else -1 (unset). + // + // If you want the actual bitrate field settings, get them from the + // vorbis_info structs + + public int bitrate(int i) + { + if(i>=links)return(-1); + if(!skable && i!=0)return(bitrate(0)); + if(i<0) + { + long bits=0; + for(int j=0;j0) + { + return vi[i].bitrate_nominal; + } + else + { + if(vi[i].bitrate_upper>0) + { + if(vi[i].bitrate_lower>0) + { + return (vi[i].bitrate_upper+vi[i].bitrate_lower)/2; + } + else + { + return vi[i].bitrate_upper; + } + } + return(-1); + } + } + } + } + + // returns the actual bitrate since last call. returns -1 if no + // additional data to offer since last call (or at beginning of stream) + public int bitrate_instant() + { + int _link=(skable?current_link:0); + if(samptrack==0)return(-1); + int ret=(int)(bittrack/samptrack*vi[_link].rate+.5); + bittrack=0.0f; + samptrack=0.0f; + return(ret); + } + + public int serialnumber(int i) + { + if(i>=links)return(-1); + if(!skable && i>=0)return(serialnumber(-1)); + if(i<0) + { + return(current_serialno); + } + else + { + return(serialnos[i]); + } + } + + // returns: total raw (compressed) length of content if i==-1 + // raw (compressed) length of that logical bitstream for i==0 to n + // -1 if the stream is not seekable (we can't know the length) + + public long raw_total(int i) + { + if(!skable || i>=links)return(-1); + if(i<0) + { + long acc=0; // bug? + for(int j=0;j=links)return(-1); + if(i<0) + { + long acc=0; + for(int j=0;j=links)return(-1); + if(i<0) + { + float acc=0; + for(int j=0;joffsets[links]) + { + //goto seek_error; + pcm_offset=-1; + decode_clear(); + return -1; + } + + // clear out decoding machine state + pcm_offset=-1; + decode_clear(); + + // seek + seek_helper(pos); + + // we need to make sure the pcm_offset is set. We use the + // _fetch_packet helper to process one packet with readp set, then + // call it until it returns '0' with readp not set (the last packet + // from a page has the 'granulepos' field set, and that's how the + // helper updates the offset + + switch(process_packet(1)) + { + case 0: + // oh, eof. There are no packets remaining. Set the pcm offset to + // the end of file + pcm_offset=pcm_total(-1); + return(0); + case -1: + // error! missing data or invalid bitstream structure + //goto seek_error; + pcm_offset=-1; + decode_clear(); + return -1; + default: + // all OK + break; + } + while(true) + { + switch(process_packet(0)) + { + case 0: + // the offset is set. If it's a bogus bitstream with no offset + // information, it's not but that's not our fault. We still run + // gracefully, we're just missing the offset + return(0); + case -1: + // error! missing data or invalid bitstream structure + //goto seek_error; + pcm_offset=-1; + decode_clear(); + return -1; + default: + // continue processing packets + break; + } + } + + // seek_error: + // dump the machine so we're in a known state + //pcm_offset=-1; + //decode_clear(); + return -1; + } + + // seek to a sample offset relative to the decompressed pcm stream + // returns zero on success, nonzero on failure + + public int pcm_seek(long pos) + { + int link=-1; + long total=pcm_total(-1); + + if(!skable)return(-1); // don't dump machine if we can't seek + if(pos<0 || pos>total) + { + //goto seek_error; + pcm_offset=-1; + decode_clear(); + return -1; + } + + // which bitstream section does this pcm offset occur in? + for(link=links-1;link>=0;link--) + { + total-=pcmlengths[link]; + if(pos>=total)break; + } + + // search within the logical bitstream for the page with the highest + // pcm_pos preceeding (or equal to) pos. There is a danger here; + // missing pages or incorrect frame number information in the + // bitstream could make our task impossible. Account for that (it + // would be an error condition) + { + long target=pos-total; + long end=offsets[link+1]; + long begin=offsets[link]; + int best=(int)begin; + + Page og=new Page(); + while(begin=pos) + { + //goto seek_error; + pcm_offset=-1; + decode_clear(); + return -1; + } + if(pos>pcm_total(-1)) + { + //goto seek_error; + pcm_offset=-1; + decode_clear(); + return -1; + } + + // discard samples until we reach the desired position. Crossing a + // logical bitstream boundary with abandon is OK. + while(pcm_offsettarget)samples=target; + vd.synthesis_read(samples); + pcm_offset+=samples; + + if(samplestime_tot) + { + //goto seek_error; + pcm_offset=-1; + decode_clear(); + return -1; + } + + // which bitstream section does this time offset occur in? + for(link=links-1;link>=0;link--) + { + pcm_tot-=pcmlengths[link]; + time_tot-=time_total(link); + if(seconds>=time_tot)break; + } + + // enough information to convert time offset to pcm offset + { + long target=(long)(pcm_tot+(seconds-time_tot)*vi[link].rate); + return(pcm_seek(target)); + } + } + + // tell the current stream offset cursor. Note that seek followed by + // tell will likely not give the set offset due to caching + public long raw_tell() + { + return(offset); + } + + // return PCM offset (sample) of next PCM sample to be read + public long pcm_tell() + { + return(pcm_offset); + } + + // return time offset (seconds) of next PCM sample to be read + public float time_tell() + { + // translate time to PCM position and call pcm_seek + + int link=-1; + long pcm_tot=0; + float time_tot=0.0f; + + if(skable) + { + pcm_tot=pcm_total(-1); + time_tot=time_total(-1); + + // which bitstream section does this time offset occur in? + for(link=links-1;link>=0;link--) + { + pcm_tot-=pcmlengths[link]; + time_tot-=time_total(link); + if(pcm_offset>=pcm_tot)break; + } + } + + return((float)time_tot+(float)(pcm_offset-pcm_tot)/vi[link].rate); + } + + // link: -1) return the vorbis_info struct for the bitstream section + // currently being decoded + // 0-n) to request information for a specific bitstream section + // + // In the case of a non-seekable bitstream, any call returns the + // current bitstream. NULL in the case that the machine is not + // initialized + + public Info getInfo(int link) + { + if(skable) + { + if(link<0) + { + if(decode_ready) + { + return vi[current_link]; + } + else + { + return null; + } + } + else + { + if(link>=links) + { + return null; + } + else + { + return vi[link]; + } + } + } + else + { + if(decode_ready) + { + return vi[0]; + } + else + { + return null; + } + } + } + + public Comment getComment(int link) + { + if(skable) + { + if(link<0) + { + if(decode_ready){ return vc[current_link]; } + else{ return null; } + } + else + { + if(link>=links){ return null;} + else{ return vc[link]; } + } + } + else + { + if(decode_ready){ return vc[0]; } + else{ return null; } + } + } + + int host_is_big_endian() + { + return 0; + //the above isn't really right... + } + + // up to this point, everything could more or less hide the multiple + // logical bitstream nature of chaining from the toplevel application + // if the toplevel application didn't particularly care. However, at + // the point that we actually read audio back, the multiple-section + // nature must surface: Multiple bitstream sections do not necessarily + // have to have the same number of channels or sampling rate. + // + // read returns the sequential logical bitstream number currently + // being decoded along with the PCM data in order that the toplevel + // application can take action on channel/sample rate changes. This + // number will be incremented even for streamed (non-seekable) streams + // (for seekable streams, it represents the actual logical bitstream + // index within the physical bitstream. Note that the accessor + // functions above are aware of this dichotomy). + // + // input values: buffer) a buffer to hold packed PCM data for return + // length) the byte length requested to be placed into buffer + // bigendianp) should the data be packed LSB first (0) or + // MSB first (1) + // word) word size for output. currently 1 (byte) or + // 2 (16 bit short) + // + // return values: -1) error/hole in data + // 0) EOF + // n) number of bytes of PCM actually returned. The + // below works on a packet-by-packet basis, so the + // return length is not related to the 'length' passed + // in, just guaranteed to fit. + // + // *section) set to the logical bitstream number + + public int read(byte[] buffer,int length, + int bigendianp, int word, int sgned, int[] bitstream) + { + int host_endian = host_is_big_endian(); + int index=0; + + while(true) + { + if(decode_ready) + { + float[][] pcm; + float[][][] _pcm=new float[1][][]; + int[] _index=new int[getInfo(-1).channels]; + int samples=vd.synthesis_pcmout(_pcm, _index); + pcm=_pcm[0]; + if(samples!=0) + { + // yay! proceed to pack data into the byte buffer + int channels=getInfo(-1).channels; + int bytespersample=word * channels; + if(samples>length/bytespersample)samples=length/bytespersample; + + // a tight loop to pack each size + { + int val; + if(word==1) + { + int off=(sgned!=0?0:128); + for(int j=0;j127)val=127; + else if(val<-128)val=-128; + buffer[index++]=(byte)(val+off); + } + } + } + else + { + int off=(sgned!=0?0:32768); + + if(host_endian==bigendianp) + { + if(sgned!=0) + { + for(int i=0;i32767)val=32767; + else if(val<-32768)val=-32768; + buffer[dest]=(byte)(val); + buffer[dest+1]=(byte)((uint)val >> 8); + dest+=bytespersample; + } + } + } + else + { + for(int i=0;i32767)val=32767; + else if(val<-32768)val=-32768; + buffer[dest]=(byte)((uint)(val+off) >> 8); + buffer[dest+1]=(byte)(val+off); + dest+=channels*2; + } + } + } + } + else if(bigendianp!=0) + { + for(int j=0;j32767)val=32767; + else if(val<-32768)val=-32768; + val+=off; + buffer[index++]=(byte)((uint)val >> 8); + buffer[index++]=(byte)val; + } + } + } + else + { + //int val; + for(int j=0;j32767)val=32767; + else if(val<-32768)val=-32768; + val+=off; + buffer[index++]=(byte)val; + buffer[index++]=(byte)((uint)val >> 8); + } + } + } + } + } + + vd.synthesis_read(samples); + pcm_offset+=samples; + if(bitstream!=null)bitstream[0]=current_link; + return(samples*bytespersample); + } + } + + // suck in another packet + switch(process_packet(1)) + { + case 0: + return(0); + case -1: + return -1; + default: + break; + } + } + return -1; + } + + public Info[] getInfo(){return vi;} + public Comment[] getComment(){return vc;} + } +} diff --git a/Support/OggUtils/csvorbis/csorbisException.cs b/Support/OggUtils/csvorbis/csorbisException.cs new file mode 100644 index 00000000..0e039f08 --- /dev/null +++ b/Support/OggUtils/csvorbis/csorbisException.cs @@ -0,0 +1,36 @@ +/* csvorbis + * Copyright (C) 2000 ymnk, JCraft,Inc. + * + * Written by: 2000 ymnk + * Ported to C# from JOrbis by: Mark Crichton + * + * Thanks go to the JOrbis team, for licencing the code under the + * LGPL, making my job a lot easier. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +using System; + +namespace csvorbis +{ + public class csorbisException : Exception + { + public csorbisException () + :base(){} + public csorbisException (String s) + :base("csorbis: "+s){} + } +} diff --git a/Support/WaveUtils/WaveUtils_WindowsMetro.csproj b/Support/WaveUtils/WaveUtils_WindowsMetro.csproj index c4f2339d..f3dba06d 100644 --- a/Support/WaveUtils/WaveUtils_WindowsMetro.csproj +++ b/Support/WaveUtils/WaveUtils_WindowsMetro.csproj @@ -19,7 +19,7 @@ true full false - ..\..\bin\Debug\ + ..\..\bin\Debug\ModernUI TRACE;DEBUG;WINDOWSMETRO; prompt 4 @@ -28,7 +28,7 @@ pdbonly true - ..\..\bin\Release\ + ..\..\bin\Release\ModernUI TRACE;WINDOWSMETRO; prompt 4 diff --git a/Tools/ProjectConverter/Platforms/MetroConverter.cs b/Tools/ProjectConverter/Platforms/MetroConverter.cs index 83b7b8da..e1adfe25 100644 --- a/Tools/ProjectConverter/Platforms/MetroConverter.cs +++ b/Tools/ProjectConverter/Platforms/MetroConverter.cs @@ -17,15 +17,12 @@ namespace ProjectConverter.Platforms private bool isCurrentProjectExecutable; - public override string Postfix - { - get - { - return "WindowsMetro"; - } - } + public override string Postfix + { + get { return "WindowsMetro"; } + } - #region ConvertImport + #region ConvertImport protected override void ConvertImport(XElement element, XAttribute projectAttribute) { if (projectAttribute != null) diff --git a/lib/GetLibraries.cmd b/lib/GetLibraries.cmd new file mode 100644 index 00000000..df78869a --- /dev/null +++ b/lib/GetLibraries.cmd @@ -0,0 +1,5 @@ +@echo off + +"./NuGet/NuGet.exe" install packages.config + +pause \ No newline at end of file diff --git a/lib/packages.config b/lib/packages.config new file mode 100644 index 00000000..2aa76aaa --- /dev/null +++ b/lib/packages.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/media/Test_TemporaryKey.pfx b/media/Test_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..a7af833cb4b84397750b9d9d9e6fb72bb826761a GIT binary patch literal 2512 zcmY+Ec|6qH8^^!HY{tGNC83nvSjHsTXC&+R*^-g%<`QKu3Ne-;#=d8l6lt=r5wc{t z<3H=*Y9`l>;CaM&*ynR=Q-#6a~?E_sgD7|h$b;b!kHu@bR%|HAqYqw ziOC;IV)6yCCz=G?|5pjN1SP@dKs*C#3eNn$E*2DoA&&$-Mw6iXXaP9t{}?=+4T^Mv z@{s+0qn==3Kny@h(9u->2nYYoyK_bLdnK%4e32g5^woBDfibDyDXn(q$QWDvN5m{M ziyFlW*B-)>SbL*IRo+EC=kuc~HQ|EOIat%iOpy%gP;ZdmH$J1;$;REM!$N6~^`%<^ z5m1xlct0nPo8~>^l?`QY@CVpQQJvA6AHs1%o1Y!WZQqyIl?0fEm6S10a!!a{)DqlA zR@@ts6VSVK)d=@3`OYQdz60G03~7rn(}3awl{?XDr^^;H6*G6>1c~1|-y*C=GVUwP zE^`jLS*UAO9fctK(odfXxxgoDcC8cJgKB#inbQ=|TEP3QsN#jcQsX<=*=UjN!kY~M zF6Crfp$WgC$ZKt-V()S#m+*+H>*)=NI|h#p>xdIUcY=K>UTr%H=d4X}Y*X&f8@B4K zBe@)3-o4)WJ?Rtf-Gk|<2yzSY3RKri&x$GTnro#y!u5m| zbp+nHr>@;~K`cD->AakV9%UeQ?`2Ex5&=oCI#Pn0j?_^(Zfh>IM=lt(o|FUaCq#t zwJh+?^Q?FC8}qgT%E=3QcZrH;kROIE13)SmPb zjjRGeDJDp_XU92_TfWjJ2^s0ko=0Q5lZ-2DDwpx|FP8k|3lhncUJ}EGNfoDe6WNZ0 z2;|b=8MYeO8#LL7ThOpbKO{>zH8-+`B3e);UJ{{PBd<*PVz?i)d7Ag-78k9Iik^z` zGlB$`PC!302Cl67Zb@^%;rFCg+w*fq%EwL>Wrd+5dW1Dj*P7?P|WZ4ypS>&&F z?H|#wG{kmlOsUN1VzTZqtUxvOHMPqdRbZQieYv2V=#;IK60O6g8NYEus#+ie*i&yeXKN>uA%Q?nCGx zbPE)BN-yUKSG4L3YAejesKmd>l-jBv_fbryMH1VK8O3GHrxamhGJKMsj%1$eaO%6p zzTPPgxxN-^Wg;ZYX=a$W#jRyu>toNF_H$}eBh64&*hXyR=}I++O@@6ZP#De|r12QZ zO{O|fJ_b(y!LFw>WVAgs-Gch#N7$N)s9lO6eShn;7~xMYR}~-l7q;^|LB_MymYDk& zUx~hRqjpTR`Ai@yig|j?o}}lzLgGf{H?>RgwdV7xHw8&mT6;0BPNe}$hg5Erb3MBX zEyHOog~X_=rP#ngPZ@Na-R_vlA`IYt?kv*})1vLqHvMNn!|VpG zc4Q;c|7 z&m%F~fr!We0l;AXPX+R?kq`eh@`vx5tDp$cVZTOxFo{v@xrGf!GX3PcyYLw*K{ZCl zp_hRTFC;FWj=b9SR`ft{er z)7!1Q&|>{{0Y5yAaz8ks1?9_SF+O3zned*^nLjoYG1qoYk%ZG}cCpm1Vm)FN5hn&A_FWG`B1k>GG+-@}b#A*;n%5#dqii2by6 z%dfesyLnzQd}luIVCC$^1ZwR#jkvz#O_}eAeFoo_me{JNvnUr@ck{c5YPgcC6yJOo zi&an!sWgBqgdgR2Am!Nal_UuEp+&k-KmD02a+9C+O+<9zP8J{B#c*)HG?Y+-_B2I3 z>TKnzzO(M7f828K6x zZT?u9c&HhOG=|w6mLCL{M+EV+_|0;=em_2>oKxfS-3rZGx%|?pM}PC397mJa z*}BMF(B%TaM4+}`$M{~OME4FB_o@w4m*1zRM{Q;b=h8i~_=eb&J4TQs{Y#5f9&*PX zGMB|<&V6&_<^-HKMXkIZt+w7&`6S!2a%|6sJV;!3%?%0}=6E1*o8xeFF`m1==Lw)q zOW|CKaqJH=OZkvHi&jCOMI+!aNj64?Q&65enD{4hl3bIC3bacC2W;DA`3ZJVo)fIW Yg%erWAUq~@4dxI~{N6#*_}54KFLRZ7QUCw| literal 0 HcmV?d00001 diff --git a/media/testmusic.ogg b/media/testmusic.ogg new file mode 100644 index 0000000000000000000000000000000000000000..b9a5c53f2ecd05cf71338ad3afda1b1c1e0c17ee GIT binary patch literal 116691 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

>Q-zi2THkxw?pT`wTY39*HDAwo ztLpT7g_tv4&*?fg-2R@?jQ+mz!JFIM*cb--v~xSOjF=3>KQDAlA<%GWRvOjmwrz&1 zrwR)mBo}d>=XW`g0pgn%tku=8)Gy5Q5>}x z8?!o$60_W}!&9khKX@z2mCI+SwT6H0<%m>FctA!*j>G)(#iBLWZ`8-nqfCQCGH(Zf-UxL7+(GBL&FSRm>+a@dCb+_LBZkn-`33`^=TS|JsctRtP8uqQP0dOn z++LY=un79>lK3iT>zaC6kq_$pv{Y$qIZcAeQZAOBOE=}PD93%{L6QDhJL;qvscS~8 z$j~uO?(93)ip@^9e4)dhq?B$QJihXcXOIbj%rqa*$c*H7!3852#^1 z3v=EnyMCOUQ+0b^CwT3VxjR@DR=K3+r&~`zF!nKB1-&(@N}J#Y66-{9rVmXc&`QBU zfk%^mB9#6eO8^O2n8=He#IH6|LCf`Mt9lbw?Q$_8Wg&@$&{dIS>D=%VvW+@t&lS93xFNQKIDcR!q{PPQf3FPI8 zk53J$XJW)T+uje45^WC0--(4DLv`(yq(xcCiob2EJO1QfFbyunjS;k+syUghVSIla z*E>51n%D(Ezy&}+Z>=+f->SO9rFp89)SUKh;9IxVJg=u>KQ@ksJOf}M!MnUn$gTgFUtrc+I_Al)Mitmt)kMe<=|e}Wq&bqDEY6kk zE_~llwz`5UM#QzZ_)SPi7>NvWG7;LB>cxu~SxeixMvVNhJTnewoVVX&mv2rDG)FZu_I}H!=Zz~B zJmo4J6&5da*!R%-OOPRY)^0z~Y-=W4H#TM~$_;0~DY^-3<9&E?x+n7Gtxy!nMmUIX zshS+S-!nJe5i{TrmgqQO!JQ|b3NQ(Q0sy-W!LL?#s9eI8htkjKM&^Baf0UgPO1%6Z zj4B04^fVwm(aKSqXRpjVE&2gY?@j?k^Vi4iyKz5!_e_Gk(+ovPAI_dytz)8IlCoo0 zn1tm@o-zNS7cIwas*>qVn9W4_Hi z69!Z{W0`<#l4<5+)h5yES3IsyMiuwHitT{`yV`S;R6)|Oczq=`=MkEv$Ml9vhzF zwM+}{*en|OXz_L}BUCaZIt|+t&s{9f_3nVD21B^nTIrvML@|{yCO^`E2kx9Fq4}|% zwM6XhF>7+IWwnvE5^u})a$n6q5UPwEzW$voV5A_mecjhNah}CBwq{bV`YD;2+`{r9 z@Bz0MiWv%pCOfv0<7x_iUwIeMR6aHIb5# zqIU-E>&<1p&#yU2Z%9<#^!efnUZ#{}++4f(gFLwRc7^Q2!n9hPlX=hX3Drzn*Y2|7 z%iiH3Pkg_VVZ(=(^O~A<0>W(etbz>E*4J;>clV;QsrCO{#b?NnKp4_n(RZKx&gD1iohPh--+~(f5_q1@Pk%fE;*5CJq`sZV!yNO8Rx8D z$vR)U__RxLuN7FK_+>t-Fmo>r`ekXkA|7GiFi)|AcZ!k&`Kh}aNoewOa?VwsKlww> ze91jkBHH2u$62$=&ZJ`gtuGnF(u&nok%OS2N<5INsVKv}Jh7s*Uh8+J4|6KxXoVARcQ+R(!9ythEE&VCZCw$ zJrARK?QCHNe+%;!7(=HkL|im3#WKr;zR_@xg{->k!|cwKY$z1++hYA}{t^I48t0#MBOnE@%NUA55nN+aLYT&WkD9Ma+9WlZ#a!_3?_b9RjGv?vxm%a*SKoFj@z?kP1`8hlfy9JdsQXc zH(H?=wp2d2%EhlIcL$rj2x-0D`bWDDE3ctlvDd!Mq+Gnf#}(Vq&(5C9_1){5Ut(_? z94#^zUC2E5@vvHW@!l%nfrFP!FQW^}r>W!c^)rsP)VUsR{hUpzjGkVCBcpy5 zl}#LmxwX>{#y^Xs=O<5Qvk$F9v$sTC?RA;d6nC4x;q{EK&E@5m&Ff8F#E7jihtPSB z-npXl%I2Xd)9x25`E&0se>81p=>QA$macXp8Shx=04*yAcZWqJb*jA*_4IF%nhH%= zOARIQf3f0vn!lxSKyB{T(~oVQ^m;8lrY2<&hy8GNO+%0)_mr-pU2bk*takT8A#T?x zT=+UU^eZMMJSa>fj{~6*T&NAc=YVw<+0Ci^EZzBJ&#SeXivNBX_$fdHJ8I*#7E@W% z89$Q#F;I4|yFLA;{mS7u@sP6G^*%H{t$EC5vwS>KwACejrQ_+V7F@RS#Ufq zXvJVz%(|AMMM|HReLD+l)aJlCFjUa^02pUdSYZB6qvn-8@|)8I2l@RrkiqQ?45}E| z@}m|JNgZi@RoZd1GKj|G`AP<1B5PUz3^ge60Kn&(*=3%cPqsX_L(vHHa*Drzod?P= z&diVrMmk1{=zP=#*o5x%leuNKJ#i1A3%AkNt*f2*)zxC>;IxRhy5wc~afAQzZKunM z#Nll!?Vxa_!f%=-+cYGbhTLFx3@);;V}h)L(KJv@h4$On@Yk!G3yQd7dh||(&o*en z{RqgtbOVXyH8BAIKHTXkV!a0K5R9tQ4><;sZK_CsP?L3M}7)tlsR2Iysnk zsCOYy2;X6?!9oSCa4_BjGLkME5z=gTdS8CAkw0fS${Vh5m-70!nbj02QI=t^zwXQB zGZJm%fEcAHLBhy6N5T^?_d>oBrRaKi>!2$NAcc<@t3zqQ-An_9qc6f>$&R~^zc7>E3 zJDP4;T5t3e=L)=g?C<^ZZO!%wyrk$9v%-#uRxjQnJI{6ht)kON!X2C49SPd=VRNQc zjQc*3+55W*r^vy9QvZ!$->E4rc8V&W5P*Sz1Q1$(I3;CWXSYAgo)`>lc^g^xijMJt zG$8zk)(rqn>Uy~Ow_LldX>(+4zne+9Eb-hA(HSkzUaoT}pu~Y}YXi{BWd6%Sv3xFl6H)W>a z+U?z<{wu4pp?31M{hOYPh8Ym9y%`U_bDhDRze+{VDLL)xlcsUp%i_D7w^kvvoHcR7wS*rVbS`-Ehf^=_|L8l^`a?$ja+yIK{_Qh@o5^64UQNyV;|34X)_fj#LF zjedE<9X(h?a&O~ym<7(n%SU$KuQ^S#x9;EH$tkPWPkF9C$=3Sl+?KJ{^!e!F=FN&s zFcIF5&Rkjuq8xusCQ7EoQ>^} zUbkoyUGc5>rN*7Yq|Kg}pkiRJ>TmQ2b#)X?mi4Cq7LdPGgh1E4?M(Hn3R(VqU~zoi4O~TbF-3M=Q2?fw%D;?ct>uUbw^6AcINPZodeN5d%KIq4|hW4=j^%E_V5=k|sf?aH`-M*`)uw9fy;^VkP zjd)90MU}S1J9Y2Lfm}=Hjv~25d@RQXb5%rI`!E2@>BM|++cKaB>P7MdTHzVqyW?(1 zRa!(zcCH$H{4C^r-BVgI{c;G(Ey2ka+8RNRKsF;F+^#J89cZbUtAa-69W0C$G>H5#xr&Q% z!Fb51Ed4Z60uBP)hP|WrW3dY!CY%_%FfFGUBX9x6{$01iJ`J({c1CN{*T|JHlTQaa zOX5BBsmYS_#DTOb2biwx$l`KNi;;QqVm|)F_+|vi9jd}kJ2ZPtjDaRZGL5 zwoA*^eOcPORwg=N$>6{xP6%)$>nW#sho3y*Z)9?3Sm*xT8+ktxzbplf@bB7#$u??q zAXKBl>V{8ci&3Kyz3Mnc66EQ9vx{1|7pteo`^&_t<+ryn$ESy*Pg#o9>Zf~;P_cQ5 zL=3mFeQ)0TjB54p2Nj_f*S2YMO}|KTBfA_50`zo|oPWv*3^!Pm=uU|Vtr0|ai)>^# zn>9wSsI2RLfrI9hpJVlq1R*JKdpvI*;__wPdK{l zofwE4y|iB4j`vHQ=2#J#O3zOLmd}%^dnezFJIKem?a_g)22AEM!v1a5@`& zx-5M1Z*(FdBs$1qfI-&-n82?y-0u?L(P}d$oa)D)#20tCM-AACjg63zDcS?qCAz*f zsm4-WO*t?+Iq>Q%UmG4XnTs^Y>DoMMZG$UlYX`yI7DG;tU4J8*HPwCqz)$ zEqpQ%xF+%%MoWqQELM@?8S+V3Sgk0854JRjWtc2ooi(B4kcTx!e!$)nZEJu0$_^hA zxNV_o%y)jM2!*OjqQ2n9Qs{iB-BE4fmZ~0`ugu$MmW|KUqlv8jHA^M_*#VYg&~t^y zO?{RM5!R6o7OnsPED|j6V4>lEVj=k8Py9VPQS9ltvANmhxsJbMgA)_O6Mq+H!4VOm zb+=Dao8!w12|-8gRpH8>;)xgBMVY7CcYp4LeQ(4hP|yxxj9;~ z+1?9|X|i8l`|HN|vR^fGmSs1v>%!dd8%bj_OHaIz?H+Fb5nn+OgxQv5_$(seR}*212iI%FdmoX!)6l#Epe^P-F800>R@r z*C(m0e~vV&DXo;=GRAel8|?TejJ$%QOJ&UIc7PovQ3oRVlkx6 z!P~NOWz5kvU*xMK#8hK;Jzr_&^c${4>L-QeSmPIRdKPbmna~&=q}d7>V=-`y9t|4K zU>)2VuegnzBfwoBiG2k=7XBU-1dMP}Gc+fF%Q2~XN2f^Y=y2R^d0*>5B?rAP*SUDQ z9>l$V##z+w?8HY2Z}Sk%g#U>1eanKRnG!L*g;CxOmx^wLF#ZNkVe%)9K*>l_ z?)#fs`O+L(cvvAAjQlmc?ox5GtxjgH8`M5!7ltGcexdRPl=5OJd4j8&0iTusRn%EV zwHa>fHn)#9tZ zA#>H$-wcI)?(8b~#&$$_4z?;6ZU}@$zvFc;dhSU#-sD}yD?z+J+}n3&o}~RFqOm3S zPIJ9K4)H$O!*=bOwu(GSQTlj`+JTye?J0mYjCxG1NC`R^Gj0qA+z^-0+-66qKVSCs zlcLVL`<`wwZB*~l>doSIqXqm+%qv=)(X{`FsH7`j|1@0Q?RQ3~tp>pJGMfsGD9#^9 zCt&V~OxYVXk3;2h-bMXsU?%zJ`Fg;DpfMb%Gh$kvt`9Q%R^@-XS-`2Eno`V?|Lng>tcs7v18zbw>tp1z$8 zOyORt{b(vxR640&)BmV;``Gj4IYGn!b@ilDNKpUVZi6m5L3PzFBeNL& zHIBR89WkPmN=eE7xKA4P^2hN$_7`H)2J2x^sM+MS83X7*krW|AP@k!?MKsxO{$GFh z?&nX#s0S_uH4(EqrKN2W)eU%@A|emi1}L~A{rp|M+jOyarY3>r+?Wcd-J&Eo4f&~o z86@O?Aex74lnO{AS13fv6Zl2!H0b0pHvg=jTo}FEQvq5UGIB}R_d(H%@q>SVLG2HB z)I!Y$hV4z0%h~j6=@;SGojFSbm&JKs%@z@_D^}AzmVxQ=AE(l_sf)+=v2Mg4Kli8W z4WL7S=46KwbLV8231!LdOao;X-U`|=NC48D)V7wkZ%wSA=={`?byFaI&F?xtd#&@v)alKQp z7Ri%C%#09=s~>U99=JGvl{aJTyzw4#E~mqOfcIg`tOJNcmu{yNsnKrxN3ltO+T|P2 z9q)$|gA8qu6dQpwJQh~5=lBmjUJi}D;~pM}`;_yixyy^q$sS5riN`GJ+Imre2v8r&@5Pi8e$2!#k9YuleV>U8dZmIt$CrljBVa_KP5PPCxUIuuN+@L6qE(Y zLz&&WOVwD@SBiZu<|kXy3v(GyS>()ApwC;V`y?X{o$v=h!ucMF`|i)~2zMVKUaIxz zFX+n?2VOx1D#Mr%i_z_Un4tcXCE;jHzE9q#VQBH&x9Q!wra7)V(%x_5_`7_i?Qz=S z=Jl3;_H2ypabB^dWbM6-F@((Y&X@JmQ_#D&6G3z~)MCN&lk!Gl(u;fbgxHCc;^44z zG+bI9uA#;!^)|};26vwZo(+2MQcI;8T}ZrEm4*{ z4`pQ3Wh8To9z}ZNwtTmprE&L*gO`WT{bx@W2HHC!bQIFsybeCc{#$!-2@~WI${cgf zXP3b~kc-TUU{_4{wGAXXkd+dv=Sc!Yyry3ip72wPFE>0j*#UwxtsAT~_n~cSU`s@H z?#A=E;$2fzLLq*PgRk~NOwD&C8b283j=vGvLmfoG^YiK{v3LA4*!|{-n%v(?aihHr zPrt{UN4MX#@|`aZ#0QIlfdznS0zgm|C3E{^jt^#0N=+HWF^s3>aD}(A6E;YWE#6d7 zVR*sTauFqU5Z+Tb-J0JO%hGon8|LA5!CzUrXLeIdV?P@z9j}jtjtWjjoadxvv6z`X zhMP9GN#REKlkS+KX^&czjCpu?QOcilP9j4sn2YZ+Ie~#g^H5$EUaRW zX|I=fPCwNGm@K$(Q81Cdc3{yRJef2Z6;wB?=K`}x-8p|?{8|M{6jS7<)|e=CV-~pw ziMlWs!E`zCLT1H*D|h?gv9$4{CP(gSlZy|&6Y1um9fB55RG9$@)!)*X!Ea#%>JFCC zU&Vl?`)k$trCD(js5}g@Ku@pBmy{^!+-lkTwMvJ?)GS>F%o|{XgAN%>QKO6th5;A@ zrZ{mVkAH<3OVZ&%Gh)_5i*;Bja92~M)rRFmu}ET7m>}Sf5;oU(fz}l$&6?P8a4!#e;~96qkEu;ak49a29aC~2KG6UkuXNlz zq+EmC+9be}q<1ogi4#FK2Vuj;n%CN5Y(Zxl{DFA2_=NP=*uP8jE*G6kOD3oTIVs!C zFgf@WjfvqztsSqWMth0_s^KyXQ5L?O=iBvXsy&B)h1}$47#dZ^JhXtcn;N14Yfi5V z2ZRX)(>SZ#NDkDWcG$lFsMM7#z6ulZ*5pFPtSS{|L)VdBRHUi7eP{AwG#gq5R#X+F zJvGQ@{3GekXa3rQ>A=OZ$8;yZ(%&+46V;1bpun`zI;UN}`e;n#hN5X!B{u_M)IvOH zoRIXx;SPKxFH_nQdvw(jeGazgJcyf^f^J`!kHEbWTPuw2t2Fz6)>jr4dqKPB~v!$A}^0RH}IhPd%C|Hcanplx*h9nI|p& zS*v6vGsa9j9xYA)5#ut?ZX#uJ(zH2C7c4f9CBqTSI=;6uf1q!aPD*RXm3qLP$~)4* z{Ybi=Zl+U(iv(LcdL-Lx|N4M{mLqD-**~S9@nApWKAC!XSsNyDCA3IA2ti z3I$fSaMda`K6b`lK&=a7rp(&3z?rTc8Dx9NJRKqha*Yl?3Z_Fr&ZYa*K@-q%m1WJB zQR#g*;KjRc%F_i|{2=!x_dK+ohGiUK*0iA5fw;SOGYuN-u7;6a7E=_h~}gyPnCIO^ct`BiFu(q0rp0 zbJUrwbdMyJ^WY&#jg|`wwqyvWcF=#(0e7){t|MWygY=J`M0o**rI0bE9_LLUUSMlI z{jf+jZ{NQ$O+<8q%^GTYRT`b^587snwLt za=CGlCn~H-Q z(B$E{d2Cxw>-S?GXFgPwt9O#JJ6StZl~C zrGKInq&}&1EyfKRh>@!?Tyo8SsS6<73i`Fxb@&7YgA9No0_x_UZd_*%8TR#HBB@9A zor1@7|NX12Zt*IjJvJqxwvl0bid7eOmXNVm?h|u#F{55KTx*}4E%zfgXxJ4?tiO*JtC;-B4W*tbSUP~tS$rbO+#|? zaIJFrX%q5r3i>_TXxUaDk+ku>-Y+`o6}Lk@x8o1^Kc}sZ8QaFnhA9s0xrczS+pV<4 zOC)dg=Jl2e%%jsAXameiFIbA#lK`w)C>3rbXU@PV1Y&%gF6uA_7{ih1JFw2kla8V{1y3sppjY-|JKRJ_^O{yKCEXAF9n| zMQX+unZF`w#QlCqbhuN9F?gj}My5vQq*P!2O4AFabhM9%@PFxt-+$8&B1rnNS)g!> zGdMA|G&(&!G%?vf-rqYhKCv;gn4SLZ*+24)+xToxe8`AdxbCvRf~J2b7?zEj~%pDZjRTR+E3)M&`t z@*>q&z~`Y!goA>xKbI7tb@RzuEC0h+LYr|B@V1k}aZ&_P{?!*MD0Vj>m>YNjknVlW zJ|0wFGC2%uT8sSLw{IcT|1?%%YNx)bj#(Z5XbV9 zACOJitnlUbn^CVP`yq>?V}pf4%ntX>8LKAGkvHCW2e6hX#d9${5C2Zk0li?ERBzr! zaW>-;WH&ET{0GZjNqeL6rp!!;j=0Z`F#$-~lYKyu&>JJdeZJwEt{DdVmIVy8Iw`Ek z`|;0b&90qVtD?vxPs1)ViNa^2yXY+rqDVd(ZC&CulA){B`lY$#i)lLW20##Ls4UJCWVWKDl3?XK zNjTZT+c9rHB_)67#CT0CkduXMZ7nAD?tTZ|^^``|d)f2Dri5r2?sa3;B3&F$MfScf_P&zNBeq0DU<2d3O9P%8t!AlVgTT(%7vBd9v17 z{@k)!^J#}yDLdnUw6cS$ddD40itpQS$j3OY$zOz5lgKy(Y@oR^1=?38Ml_?fvuRm`7XLq84Q4JMV@g`3N&6U2o9yR2RB z3D{H0m;V^gh$$OAzh>|%{aP7SOC=r}b#dn15EC?KdbBs0ycsElVx|pdVZyz@Ub%p2 z-si{d;ynOWKB%B(-NK{*WS{|%Q_vnbf_-xX;8D@Y^nq&dMYz#==aNAJD+%Yb2r8Sj z`Ui&*F~`Q}J_^f)@Y&F5@vaL|E_!!xCI6#{7Ko==sIv0NGiqv6Od?o{NHHTbU%%N? zb@rL21#Vc{h~t+mj7`~$k|>*+tqv66dJ=Tq=6X!GJGiQZn2;}*>LjYxCy~_U^pn~f z#VwYu!tzH`RgBSDWXiKc(=>Ho(!67|;_ohgymp(vrp0GvDd+uc?7IKiHJ8S;M@lruO5q(+wBO>zXJ6a9xFlG!}}6Buh(5cmw*367O?p)Epe%-7a$b zH?I(N!wZ7fIx>ffcm0G2-#pdl)#4r5me|zm-(Pd~N9wdvtArg}o}Wi`$!788^R-$J z<(LzuVR$#$5g6dep^*MVJ7R*gg}(3fd#6jT`t3Z%eoj_Fd|<=q-$6AdDzY1%@PokD zL@IwW3|EERJ~cLsRh(F8eg+#nPW(9c+BdFsSRm}YFua)mHB&HV(q8L*E&rhg+MU$T zGOeimyu|aH+GP$t0rt=1a*j+|PVOfDiYD^e6VH-dYtre;?~|73eJOF%#Q8zBKt7&! ziRhz-yswPhtgc(-gI)(CZf_k~wf!ZPC|Rbs>OEEwyxcUEv=XtkbcjtPj!(3U@FN<_ zz!aVMbdq0Z>MeoLyZ~4k$XWH+?Hs&kJ>KPk0$abH@P74O3;vyk9jNt5!B2yNC~3(O zVu-uG(238qpd5)=tW4Een?UOsowSP_ax6*TBG~cfF0}Vs^{XOvX+uSGd#En&EX%DO zz~V^v!N8UHJ<&3@7)P&&fkM=P*XV2);vx>9I^Dsro3~FOwSe!ebYy6_(2WCulh`r7 zi3Zx;)yO_ZPNnhXDx{@=bAFL<(Z&7xwf(QeE)TKw48{Jw~a1@;hHW_G;ck9ewb?tjcvp5kyU&`NkH!sq=#M zP$f6rF7VbXII$M5xG=>*cG^DS2%%Z4@$_{H)OXTwkK8 zEVhd6J|z&&ObioAuOjZgrtk?myc%?zr^ADP*8dPn;X>^z-?JIcahznKrdRn~mtodZ zA5+~Ve-@%Q+or5-Gq@Z=Mpy)m(J|nYESAhK9>{)uP}P9>{Zzo#0XB5u{?EJ18 z3D_*vBVW(Sv6Yk9t`gkDBF8ahR&LU(#yvtK97081k%RIS(L}8rhXh zIVvWc4(ecT>-xRD;Bri7^7z@Ovb-1@S04KcZ8kuGZ16Lz186=4r1=uLKNgx{vPO8# zPp4{2$sG>30o68R<>YEHMc&NMzcwVGmr$w;hFWm9I5<=3Lvu~xserBw(PpZ;Epco4_s#Y(dm*C;bCD`OEvRe%K< zK;>+|@SrH1IUOV8y^2>Z6ZQi%u(G*qzgtjz4r7M0w(#QUIV>75P#tRI8D?Mf5ZKH7 zdfMHF7)`48wNP=3(WZa`8@$T^+CAmx7a)ldvMam7&_xakg5HK$dIMk*U;u_FkjV3l zaZC1zj|Q`THT7M-ep97m<+sY!V(R*oon z8h`}fUzvMZ2Bs%xR_pEX2#4~Z!|at$kUnVjnzOBd`%%|QaY#g>woUcY6j`I{71v})jTStJLdF!=t)mthbd!v-oqTS}h2d1f-% zF%t(Gz&A~cn3PFE#0gq?N~`(0Rh#fa$i!}nP1v2{8-w15BR6KlX{w@s8 zBIGwT1?q;tCyZLPbYiZ*IZ4JRq zU2P=TUsZm-e^7+Ry$TWjEJm4VOJZ_th|o-Yjg-ds=xEDyi0ZdAQ$}mloA#)EGnHQm zQk%KHcA@4Yi6QCDop0_7#4sBzWc>R@g3^`N=@_>?~VY-BZ!v`U_KKs||=(TYxPB^O2{31Oq6*Wm`cB5`#G1a(g z?s;M%O+U532s)m@L^l)~2`Hck0C^UVKwkViGX#&o&AZYWkwW1t;thLH_YTWejUtXD zE(L_~DL%MP_L-_UJH~DB;xVf>%hcnc^ws^doj1+|Y4%+8x_32UNT!=-J@@V2)ObpU z1rN{NC=E9ehkYa07+xqMkLsqK_36D!8k(w;yc%^fAAr$~O8!GBD>AaK+7^DO0${Fj zn_AbTLh3JvukMN5jQ)~A{Q+dmXU!J~o!k8M_1RijG2<4=wIe@yTF#%-Bt|jHxFB-w zP#)2wOEBeAAiS>+%wqr*z!+kMDpfq&@btjgz=rq_G#@``?E9l10F?tq-R+OK8p!H3 zA7QF4ErG$QoGj?*EI#HBDXmiY(^0io8DwuT>w1n$ZM?wRR#(48x0Nr8Ypg5CnjSGu zy5sTZUO!62#in(=*`bLE>kP3vWZ!vbVFCzp{YNe9+Z|(Ki`3!g5Op!QzBn}2^8Mib z2^i=0O50tjRRbp7!b`lg$S!RB>g3<&k1Ks1e4uC7$}8E{OMivK?6F!NhM8YB`L~IF zwfYp!>R!jV2bF@{pH>EC6#(e)O1c9_PnaiW!%%3}x4d!)M`w5{!>kHl=`#!(+ZTup z!BfBcBaaaLtu-UC?mfH96liU`dEQ>!&3u|&>-2GZ^qe_=8r*Fo*0Dz?Zs&9PDzrDa zM=MeD94RkU79lmhoe2lBUc^#=Q1f7@FQ|UjP*lm~O$6_F9$L@*`)2}d!BKBx!=k{6 zKbFk((%%@lR>c$5`iTA^Lf{_%s<_Nf1ABv1ienHyM%CC}fd=pIN!WRAxUzX_(Ky=@ zkFCcQY<>i7SlOFmR398S^A?vc$yy-1PlQ0R2|&OIfPa_cy7C`h$|P2HO1*2jjZLv6 z^l;2HlOd?IwY91vB!!gH+^Sa}1keK=Tt2*A+*#`{|J+;WYw6ZVvX#+S-==pir~4MJ z64qZ0$L#Qga-BJej@j&$m->tnNEaM&<4KM42pz4zo&HSoqH=SIIbG>*!T=p@(FoD# z&po$AWVoU=gy9ij$fAzieUrzu5vY zBwJw1(l5c8TpjNoo1a{rTbvl|9GMwh85y56Y*oDLtlKAPLCR$z6Nc5W8Y9-s(R;Y4`msB%-n`Q!>x~bEPFdDD-H+zf-*2 z*Jse_F;vZ~qO@)edg`T)nWzp!cWXFdH*l-7;a5`1Fx%edL;tZK2+cLyh4mGrp_XUti?A~IHHq_$Is8#yn+K-@~Ex1 z^Q@s^+@`t)C+4uFz_7m#F4p7rA>8}g7A=ZaoIf~EvR`)dn?0AqJ@pX-{T<~GK!?muL)HAcD2lWny`=^Q8WZJD`*l?n04apmCj-;hwTS)8hrg{ z5$tbvubEtz7_1F}(|;jIK8TIH#-c_v-&_v&Ze2%+jriQ|o6FN&u7RW3S|z`hR<8+1 zb?rI4(H;N9$Y#^U@j=|A8sECdv=)&LyX;@_!}>ysDp&;}VOwapVq6VCXcwkNLcHtA za0rQFu7`XKEYz4JCWxLaVm= z+Dclv%uvr&@P#Mm-zoh@>cl^lVZ(L%iXEb_)C$B@M18TIw;wxmvEw$OIiF3K4FnFG zD^vV&tN-Av3Vc5GGC0lgxnVj^0rm$tvjy6;^l#3vWltok-zW48I?$#i(SYy0`0hM( z%{VRXx)EPT1kmj&0}*7ppkiRxhv(k?)90eA5htwClFM|zJ%c5v(=Qdqb@~}>F12N5 zM3ZRfMP4X^q37mVREgwX&Fvd^Ez>}V)-T0id_WGUMamqm zxyO7qaT}M8mEX$l?2Fn#Ii%VoB7?R_gSLkP*tuT_>!E0PP~^5Jam>(gjA4>HfIGHh z$KOU?2i#H}U>|6DXY=`y#lKyL%&8l&SH5nDGsrub&&}MlYb~D?X1WvRe_86ropxP{ zQyosZ$Tm(h3WtltRgwwqQUYvZutFloj&#Vcn$D=bvJ3ywo_;$~mrU}C({*C-g`G7< zH7DWKA5pda!nR5@iEh^~pInReI12k=nJUFw$!qA$}h+?h+;DYsA@>I^H3>_v!D?uXQ1GE}hUxX*jb^NP7HT|rX;29}ne zR1rgqEDIL=GTrf`#=Ga-Y*ehf9=!hu4^wQDut^=h^DTe4KXbS z_x*mATO%hB6Ga=x9TgQHrAoXjz(tgJy(Idov!VD}f7X#>XkE|Y>?2BLNAW!kuedZU zxK1%LCROd#A9ZQ(z*hUNPHy5u^JPb12L^B7($Q7=;oWn3t@HisvWd1ap2dtvl+RfT zsIZlxIoHG$rr2dBHvLvk@|)dbb$x^jZ%Tlon+RzP2){293h?7+KU8GV{z3rX zp3;55OJ4{QgS=VT`vo09Ra?3?RF$L+KclApi6lT_75xY3XqnsVEKYJooG`Q;Q+< z2QuazV=)aj*Ad=e8u(1}HL6klzm&uR*b=u-2Kuz zB@K#RigM@q-l4Dr5%$gsa7?<>D7)69vR27^WsD{+64D3MPdgV!+#PS0F32~#U(o6% zEN5UsV3qOxPN~A2hxhqRsJlyIHM6g%-u?Tbn>{;(GWbpBV>4BAPp+j1xim`)w|#hC zZ8Z2OQ>fPEO&DU*X_sf=(U)f1{jIgVO8%W=F|maZ=UzoesUi^<{?Zt` z^ta-QU4wqTd%i=@u{l<$dbkR>^BoVpUj1{RtY%fi>^r$Jq;_kaDCK{s2Q@S^x!04S8Ws`@}!Q8d`>6Z@aSLg1hQX5? z_89dmpE^i??tnL-e`D8)kpqydAOal}r8n>yFi8HzA5~)3T^$0N$zZ!`bdDHcbOO<< z%0@tr>lpF3@97fEp;DlY4A!WBWahtZ7&Bid(-MhuvE;#J>&%z5zz&Zocha7vy{RQh z)!#o=s5MhO=KM~qtR`{55}+M31ECmC2Q9lls8DgbDwWaO_6{@lYP?{YU2E7A8Z8H6 z#SA&tqkcResSRcIG7Kt1M)sJ#$|?0K?L=m034CY@K_6r~1x#Jgn5Ii(z0H~L0a6H} zTN9!gM@$bDfEe%zLh(oRd$GUiOdG4Z6dG?LFCKL<`>@R63wzC)Hx;yi>ZCi$qmaBu z7Z1N?+Mie84y68EM)P6u9(|;m$u<0AoMmav8*+*CJXc@bSiJGI@kd%7Ak-?ZfO@s3 zrRWwbJTg`}?Iz(dSIy0K^ajX}$E>ASR?ncCp#cECQb<3E&F&ynyuP0AoIvG8j*@TK z*FTDEh^b3OFn=r9(VoA;&lsYiHt-w8Bt#XiaEb;`OlLpRutB?; zwwADH{2i5^4It>E0*FGB&_V*0JxGa=)ND0jkAvg6cYG^i|9wy621s-)`tO7df>d3i zeUD{>zsHwuR4YiZ@j5DgE$_LLn;UM`e0>H>&-$92A}tW_JnUY5DdTY(?4jWP6UbIC zH5W;kvp?D-w29;Gw0KqieY`KToBx`H*!ViEPJDrQ#e&8~7c)IL9(kR7&ri@<8eJo* z{igPCF;xNodn5Mf%-7M<7nfh9XhDq1q?kJ3`@OP;x4Mg+zrqwDJY6uM3-6a$|AdBS zadMqNe?lO>GQ$@p$oS~DQOTCil%}u6)oeO_4~x@lg1w_sZq9`^3>G$o!91sOLyI@7%*#T(E|=P4_l?TFY+4h4 zL|Yd5Uzp_3u|)X-0g+u$@S*@5;S;8}4XK{yE8(E6@AR+xiWx&0uLadYq=FV(rS>_< z^m~wnlsyqX107MW$)lo9x7SMP2gN}e>7OhorDQD4)%Ax*Q;&<&TCs^uK!lx>yWOd`GJUnf@yD;&nP@2@sU0V4L=87o5|mjdW& zO8J(UPnkabj2xcSHAHMjRGJ!84nm=rH&c)CWmLh+Q~e5#r&0clJq-TIu<=YOw!nY% zy}z(wWo!XO-u`gptkeY5Eq&%IEyw~=8?-MJGqRTp)!a>Qh-cwecF9y-EOTJ17Qh*?}Y*tk?TPy9>Ha^9_Q9HB6x?{SeE&&HnG z_E!-OSvv7N|!rrt@FVgwa z2O*K48Rq>6oW(n3dLGWHV{R#9OLFwon9mTpnX;|$KK^N$rRCs0W>JCu!&d|Yxp=<8 zny0;DFY^T0&Rnu59t%^|FI&Kf z*Xhm;L2rGnWjLHD>_1?Xf%t6*xs$I@AU$OiE9=rbU zn6`<*Z96Y_Dt$Y#Ks0bR3d6*5YBtHMt9cBg{)QbLAtvCT$}%A|?q0~JYMx~^TAZgK8PWGTMUy}DbTo;v2`!tfq%`PrFWb-CBU32ZxHPF{4*?Jc zDjX9^eo+j0VcM|*4%AK3vpN#hO1nw z(=U#5jTviPXR8)@ z0X%~cI_Tg|H!QrI@YYFau1qxK-u&%vHotGDs8f=)t^P|bfm*^@;DBqNniz`^>q~Kp!&&*AYwWd&cj9S?DIunTml*+UWaLdxt zm~Qyhm7&UIEYbDPCmb@$j=%ygtzinLh3aqIeXYx4O$)ZIO3wn~QfLM?xeKyzrfEKy zKWkNKxa^8q$6u%Nw(7Uz)Av9KQU}`)(@~~}r;+v}>zD4q&OThBhqxv`KZvneVPTm8 z5ilfS{HO$(6i{@5C;(wYT`uPvPSs%f7Cty6Hr@O)eNv`EIKR)lD%B#F11gtif3mCZyAHDZTK9G8JwoTnVl9? zSg(H$jqN$K^ChSFLOS8W8M|_9n3(F)x{{d2fg{uRqOI$SLy|A4D6%71mTsn28QGI4 zwo*+RdsN)a)nw$YwQVjHoTiKwt|2kkvD$7{teqBVw}a!0~R8A`?Qx*}wLQn3xnG&Y| z$o`!Ode-?ojmrmn4N#Nf!62tdXVnhmQn5lKnvvtBe~-Mo>y+R?yIMk&IiD+i_-JV7 zYfVvhMTP|l-u^wLr7i*cJ~}&TjV`McyL_F0h&Ol}_pNsE{LRDv{eIuy@56PwL$yamS7WbXd7-g_0?Fj$O6Jt-u!v(Oz6Y`?7N{kjYAaelW;eb}?xJYO!W z-8-|f-St=2r+a`e*=qtbSLMji@qufTNFu3F$%!wC#i3P1iJ+j~TcUUTBZ{?mXHW&b zG6x*4y0TEEe#gVHI0Geh!0QNxwpOC*WEQ>wRy0$3Q` z3!xL=B<$F$iJw#HQ+*0?d_cg*kSQjd)Ou%$Z;T$vF=2g{EzhLxcJE^hYcFRqZ`Sl| zcKcBw!RX7roMI6dg*+^>dYq=x> zDgUZ5elS?V{k%0N7xsLm7UX96n~NIp4xvN7SO_fkmd(pZZ=a9?-D8i=45G^&UFLF( zaoA3d?M!2RdD=Qf^kZ9uKOeMhkhOr>7wLqP4SO$j!kQ;B8X4G)98lr)@U9fsKsPbA zS7-r|!)MrGoC7KHRQZYYLyxd(rL=h!iM5#w+T>8}PS-;LYfD%P>g0P;_=O8&t zz44}FDhyWc*J2)U3x4^5q7W3&A4%F?lBid-?}Im#m&aDJMC~lTr8K&yRpBDaB+tMz z(Gvgbj*HnMX{^?SnZK5`_bMrx?Njp`a5WOL4>1om*>%Y{isls5;nVZpXe zAi;324nT#{`;0?WiEexP*G-2q&Kw;dd#U?&9K^MGn8fm-4)*TVD10qwh}j?jZ-X(J z$_@i*9VLJ2USVIa79Iv!YU|y&{#1E9U`?0z`pP#ftSrSy`%^+E5&GRhS^&xo1n97t zd+#huvbzpOQ7RvObv<7Dft5XmLym5!1rvr8(Kn$diQ4UYA8XcXz-dJ*?gADX`=jk& zxX!UoOq%lgw)Jb~E&3$e7X5TQ_sPlRbkJ9Cf2O_mFy@e44K-pB)G#sqCtqTa*@km> z5&mS6(t2K583}-LT0%m4X2`AcgXGYfAp)C`q`Dfb&7AT#Lh9cZ4t5#%>Efho@?`S^ zDPOe6Ac5cQb^7nByLi}h4_YXjq4!zTybAPP4#T9GjBaG2!l~N4u$(3VupqKc$o93N z?%cU!PQvG>H9HigfYFLVcg!IiIUmf$<57#h7 zNOg4Ob>~ci!WXCOZYrCV!5zns0SKr|N0(Q0W41poZF!baqzTAdj4ImWa4hip>vu2b zclzKW;G!@?#o36NAr4!`F!+$Pt=uIfx+w!=Pk2D0PZC;?l+?I9olp1z50#i56lxH` z;Y3acg&PD71@Mz5y-;q~WAz%U7A14jU#AC}+4Ug3=^+AfDoR#(<#Zs$*8hHt$CZ3P zuIsMe-LFkwo!u&zhaEPQg^j-NUkytyLB;?(^?iB#U$>_ZmReI{Kc*cW*L`Cyo-b7e zZ;RTid|akmuXZ2