diff --git a/Output/Licenses/NAudio/LICENSE.txt b/Output/Licenses/NAudio/LICENSE.txt
new file mode 100644
index 00000000..82ddf14c
--- /dev/null
+++ b/Output/Licenses/NAudio/LICENSE.txt
@@ -0,0 +1,8 @@
+Copyright 2020 Mark Heath
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/Output/Licenses/NAudio/SourceAndVersion.txt b/Output/Licenses/NAudio/SourceAndVersion.txt
new file mode 100644
index 00000000..b653f3fa
--- /dev/null
+++ b/Output/Licenses/NAudio/SourceAndVersion.txt
@@ -0,0 +1,7 @@
+https://github.com/naudio/NAudio
+
+Version: NAudio.Wasapi 2.2.1, NAudio.Core 2.2.1 (NuGet, netstandard2.0)
+
+Files:
+NAudio.Wasapi.dll
+NAudio.Core.dll
diff --git a/Output/Licenses/SlimDx/License.txt b/Output/Licenses/SlimDx/License.txt
deleted file mode 100644
index a976ec46..00000000
--- a/Output/Licenses/SlimDx/License.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2007-2012 SlimDX Group
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
\ No newline at end of file
diff --git a/Output/Licenses/SlimDx/SourceAndVersion.txt b/Output/Licenses/SlimDx/SourceAndVersion.txt
deleted file mode 100644
index 7ad52997..00000000
--- a/Output/Licenses/SlimDx/SourceAndVersion.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-http://slimdx.org/download.php
-
-SVN r2171 (Feb 4, 2012) -> Equal to Jan 12 release but recompiled with VS2012
-
-Files:
-x86/SlimDx.dll
-x64/SlimDx.dll
\ No newline at end of file
diff --git a/Output/Licenses/Vortice/LICENSE.txt b/Output/Licenses/Vortice/LICENSE.txt
new file mode 100644
index 00000000..eb9a6fa0
--- /dev/null
+++ b/Output/Licenses/Vortice/LICENSE.txt
@@ -0,0 +1,48 @@
+Vortice.Direct3D9, Vortice.Mathematics
+MIT License
+
+Copyright (c) Amer Koleci and Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+----------------------------------------------------------------------
+
+SharpGen.Runtime, SharpGen.Runtime.COM
+MIT License
+
+Copyright (c) 2010-2017 Alexandre Mutel, 2017-2018 Jeremy Koritzinsky
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Output/Licenses/Vortice/SourceAndVersion.txt b/Output/Licenses/Vortice/SourceAndVersion.txt
new file mode 100644
index 00000000..b5791bd0
--- /dev/null
+++ b/Output/Licenses/Vortice/SourceAndVersion.txt
@@ -0,0 +1,12 @@
+https://github.com/amerkoleci/Vortice.Windows
+https://github.com/amerkoleci/Vortice.Mathematics
+https://github.com/SharpGenTools/SharpGenTools
+
+Version: Vortice.Direct3D9 2.4.2 (NuGet, netstandard2.0), Vortice.Mathematics 1.4.25,
+SharpGen.Runtime 2.0.0-beta.13, SharpGen.Runtime.COM 2.0.0-beta.13
+
+Files:
+Vortice.Direct3D9.dll
+Vortice.Mathematics.dll
+SharpGen.Runtime.dll
+SharpGen.Runtime.COM.dll
diff --git a/Output/Readme.txt b/Output/Readme.txt
index 6fe2d6b1..baf3519e 100644
--- a/Output/Readme.txt
+++ b/Output/Readme.txt
@@ -26,7 +26,11 @@ Supported Operating Systems / Requirements:
- Windows 7, Windows 8, Windows 8.1, Windows 10 and Windows 11 with .NET 4.0
- Linux (no official support)
- 1 GHz CPU, 512 MB RAM, Graphics card with OpenGL 2.1 or DirectX 9.0 support
-- Visual C++ Redistributable Package 2010 (Nightly builds additionally require VC++ 2015–2022)
+- Visual C++ Redistributable Package 2010
+
+ Nightly Builds:
+ - Windows 10 (version 20H2 or later) and Windows 11 with .NET Framework 4.8.1
+ - Visual C++ Redistributable 2015–2022
=================================
diff --git a/README.md b/README.md
index b41d6452..837714b3 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,11 @@ Supported Operating Systems / Requirements:
- Windows 7, Windows 8, Windows 8.1, Windows 10 and Windows 11 with .NET 4.0
- *Linux* (no official support)
- 1 GHz CPU, 512 MB RAM, Graphics card with OpenGL 2.1 or DirectX 9.0 support
-- Visual C++ Redistributable Package 2010 (Nightly builds additionally require VC++ 2015–2022)
+- Visual C++ Redistributable Package 2010
+
+ Nightly Builds:
+ - Windows 10 (version 20H2 or later) and Windows 11 with .NET Framework 4.8.1
+ - Visual C++ Redistributable 2015–2022
## 2. Download
diff --git a/Vocaluxe/Base/CDraw.cs b/Vocaluxe/Base/CDraw.cs
index 4bf3e730..9f0d2b6f 100644
--- a/Vocaluxe/Base/CDraw.cs
+++ b/Vocaluxe/Base/CDraw.cs
@@ -125,8 +125,7 @@ namespace Vocaluxe.Base
}
catch (Exception e)
{
- CLog.Fatal(e, "Error in initializing of Direct3D. Please check if your DirectX redistributables and graphic card drivers are up to date. You can " +
- "download the DirectX runtimes at https://www.microsoft.com/en-us/download/details.aspx?id=8109");
+ CLog.Fatal(e, "Error in initializing of Direct3D. Please check whether your graphic card drivers are up to date.");
return false;
}
diff --git a/Vocaluxe/Base/CRecord.cs b/Vocaluxe/Base/CRecord.cs
index 00f065d1..b05bca33 100644
--- a/Vocaluxe/Base/CRecord.cs
+++ b/Vocaluxe/Base/CRecord.cs
@@ -20,7 +20,7 @@ using Vocaluxe.Lib.Sound.Record;
using Vocaluxe.Lib.Sound.Record.PortAudio;
using VocaluxeLib;
#if WIN
-using Vocaluxe.Lib.Sound.Record.DirectSound;
+using Vocaluxe.Lib.Sound.Record.NAudio;
#endif
namespace Vocaluxe.Base
@@ -39,8 +39,8 @@ namespace Vocaluxe.Base
switch (CConfig.Config.Sound.RecordLib)
{
#if WIN
- case ERecordLib.DirectSound:
- _Record = new CDirectSoundRecord();
+ case ERecordLib.NAudio:
+ _Record = new CNAudioRecord();
break;
#endif
diff --git a/Vocaluxe/CProgrammHelper.cs b/Vocaluxe/CProgrammHelper.cs
index 1413da92..8dd187bd 100644
--- a/Vocaluxe/CProgrammHelper.cs
+++ b/Vocaluxe/CProgrammHelper.cs
@@ -17,7 +17,6 @@
using System.IO;
using System.Reflection;
-using System.Security;
using Microsoft.Win32;
using Vocaluxe.Base;
using VocaluxeLib.Log;
@@ -29,69 +28,6 @@ namespace Vocaluxe
///
static class CProgrammHelper
{
- private static bool _CheckUninstallKey(string name, string key)
- {
- using (var rk = Registry.LocalMachine.OpenSubKey(key))
- {
- if (rk == null)
- {
- throw new SecurityException();
- }
-
- foreach (var skName in rk.GetSubKeyNames())
- {
- using (var sk = rk.OpenSubKey(skName))
- {
- if (sk == null || sk.GetValue("DisplayName") == null)
- {
- continue;
- }
-
- var displayName = sk.GetValue("DisplayName").ToString().ToLower();
- if (displayName.Equals(name) || displayName.StartsWith(name) || name.StartsWith(displayName))
- {
- return true;
- }
- }
- }
- }
-
- return false;
- }
-
- private static bool _KeyExists(string key)
- {
- using (var rk = Registry.LocalMachine.OpenSubKey(key))
- {
- if (rk != null)
- {
- return true;
- }
- }
-
- return false;
- }
-
- ///
- /// Checks if a given program is installed by checking the Uninstall registry key.
- ///
- /// Name of the programm. Got to equal the displayname in the key or one needs to be the start of the other one. NOT case sensitive.
- ///
- private static bool _IsProgramInstalled(string name)
- {
- const string baseKey = @"SOFTWARE\";
- const string baseKey64 = @"SOFTWARE\WoW6432Node\";
- const string uninstallKey = @"Microsoft\Windows\CurrentVersion\Uninstall";
- name = name.ToLower();
- return _CheckUninstallKey(name, baseKey + uninstallKey) || (_KeyExists(baseKey64) && _CheckUninstallKey(name, baseKey64 + uninstallKey));
- }
-
- private static bool _IsVC2010Installed()
- {
- //Note: Maybe check for x64 or x86
- return _IsProgramInstalled("Microsoft Visual C++ 2010");
- }
-
private static bool _IsVC2015To2022Installed()
{
const string baseKey = @"SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\";
@@ -154,13 +90,6 @@ namespace Vocaluxe
public static bool CheckRequirements()
{
#if WIN
- if (!_IsVC2010Installed())
- {
- CLog.Fatal(
- "VC++ 2010 Redistributables are missing. Please install them first.\r\nDownload: https://www.microsoft.com/download/details.aspx?id=26999");
- return false;
- }
-
if (!_IsVC2015To2022Installed())
{
CLog.Fatal(
diff --git a/Vocaluxe/Lib/Draw/CDirect3D.cs b/Vocaluxe/Lib/Draw/CDirect3D.cs
index 0a7ace7c..75652838 100644
--- a/Vocaluxe/Lib/Draw/CDirect3D.cs
+++ b/Vocaluxe/Lib/Draw/CDirect3D.cs
@@ -20,11 +20,11 @@ using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
+using System.Numerics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
-using SlimDX;
-using SlimDX.Direct3D9;
-using SlimDX.Windows;
+using SharpGen.Runtime;
+using Vortice.Direct3D9;
using Vocaluxe.Base;
using VocaluxeLib;
using VocaluxeLib.Draw;
@@ -32,12 +32,28 @@ using VocaluxeLib.Log;
namespace Vocaluxe.Lib.Draw
{
- class CRenderFormHook : RenderForm, IFormHook
+ class CRenderFormHook : Form, IFormHook
{
+ private const int _WmMenuChar = 0x0120;
+ private const int _MncClose = 1;
+
public MessageEventHandler OnMessage { private get; set; }
+ public CRenderFormHook()
+ {
+ SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.Opaque, true);
+ }
+
+ protected override void OnPaintBackground(PaintEventArgs e) { }
+
protected override void WndProc(ref Message m)
{
+ if (m.Msg == _WmMenuChar)
+ {
+ m.Result = new IntPtr(_MncClose << 16);
+ return;
+ }
+
if (OnMessage == null || OnMessage(ref m))
{
base.WndProc(ref m);
@@ -47,15 +63,15 @@ namespace Vocaluxe.Lib.Draw
class CD3DTexture : CTextureBase
{
- public readonly Texture D3DTexture;
+ public readonly IDirect3DTexture9 D3DTexture;
- public CD3DTexture(Device device, Size dataSize, int texWidth = 0, int texHeight = 0) : base(dataSize, new Size(texWidth, texHeight))
+ public CD3DTexture(IDirect3DDevice9 device, Size dataSize, int texWidth = 0, int texHeight = 0) : base(dataSize, new Size(texWidth, texHeight))
{
var noMips = texWidth >= 1280 || texHeight >= 720;
var usage = noMips ? Usage.None : Usage.AutoGenerateMipMap;
var levels = noMips ? 1 : 0;
- D3DTexture = device == null ? null : new Texture(device, texWidth, texHeight, levels, usage, Format.A8R8G8B8, Pool.Managed);
+ D3DTexture = device?.CreateTexture(texWidth, texHeight, levels, usage, Format.A8R8G8B8, Pool.Managed);
}
public override bool IsLoaded
@@ -80,18 +96,21 @@ namespace Vocaluxe.Lib.Draw
class CDirect3D : CDrawBaseWindows, IDraw
{
- private readonly Direct3D _D3D;
- private readonly Device _Device;
- private readonly PresentParameters _PresentParameters;
+ private const int _D3DErrDeviceLost = unchecked((int)0x88760868);
+ private const int _D3DErrDeviceNotReset = unchecked((int)0x88760869);
- private VertexBuffer _VertexBuffer;
- private IndexBuffer _IndexBuffer;
+ private readonly IDirect3D9 _D3D;
+ private readonly IDirect3DDevice9 _Device;
+ private PresentParameters _PresentParameters;
+
+ private IDirect3DVertexBuffer9 _VertexBuffer;
+ private IDirect3DIndexBuffer9 _IndexBuffer;
private CTextureRef _BlankTexture;
private readonly Queue _Vertices = new Queue();
- private readonly Queue _VerticesTextures = new Queue();
- private readonly Queue _VerticesRotationMatrices = new Queue();
+ private readonly Queue _VerticesTextures = new Queue();
+ private readonly Queue _VerticesRotationMatrices = new Queue();
///
/// Creates a new Instance of the CDirect3D Class
@@ -102,11 +121,17 @@ namespace Vocaluxe.Lib.Draw
try
{
- _D3D = new Direct3D();
+ _D3D = D3D9.Direct3DCreate9();
}
- catch (Direct3DX9NotFoundException e)
+ catch (Exception e)
{
- CLog.Error(e, "No DirectX runtimes were found, please download and install them from http://www.microsoft.com/download/en/details.aspx?id=8109");
+ CLog.Error(e, "Direct3D 9 could not be initialized, please check if your graphic card drivers are up to date.");
+ }
+
+ if (_D3D == null)
+ {
+ CLog.Fatal("Direct3D 9 is not available on this system.");
+ return;
}
_Form.KeyDown += _OnKeyDown;
@@ -121,15 +146,22 @@ namespace Vocaluxe.Lib.Draw
_Form.MouseLeave += _OnMouseLeave;
_Form.MouseEnter += _OnMouseEnter;
+ const int adapter = 0;
+ var displayFormat = _D3D.GetAdapterDisplayMode(adapter).Format;
+
+ var depthFormat = _D3D.CheckDepthStencilMatch(adapter, DeviceType.Hardware, displayFormat, displayFormat, Format.D24X8).Success ? Format.D24X8 : Format.D16;
+
_PresentParameters = new PresentParameters
{
Windowed = true,
SwapEffect = SwapEffect.Discard,
BackBufferHeight = CConfig.Config.Graphics.ScreenH,
BackBufferWidth = CConfig.Config.Graphics.ScreenW * CConfig.Config.Graphics.NumScreens,
- BackBufferFormat = _D3D.Adapters.DefaultAdapter.CurrentDisplayMode.Format,
- Multisample = MultisampleType.None,
- MultisampleQuality = 0
+ BackBufferFormat = displayFormat,
+ EnableAutoDepthStencil = true,
+ AutoDepthStencilFormat = depthFormat,
+ MultiSampleType = MultisampleType.None,
+ MultiSampleQuality = 0
};
//Apply antialiasing and check if antialiasing mode is supported
@@ -157,24 +189,22 @@ namespace Vocaluxe.Lib.Draw
break;
}
- if (
- !_D3D.CheckDeviceMultisampleType(_D3D.Adapters.DefaultAdapter.Adapter, DeviceType.Hardware, _D3D.Adapters.DefaultAdapter.CurrentDisplayMode.Format, false, msType,
- out quality))
+ if (_D3D.CheckDeviceMultiSampleType(adapter, DeviceType.Hardware, displayFormat, false, msType, out quality).Failure)
{
CLog.Error("[Direct3D] This AAMode is not supported by this device or driver, fallback to no AA");
msType = MultisampleType.None;
quality = 1;
}
- _PresentParameters.Multisample = msType;
- _PresentParameters.MultisampleQuality = quality - 1;
+ _PresentParameters.MultiSampleType = msType;
+ _PresentParameters.MultiSampleQuality = quality - 1;
#endregion Antialiasing
//Apply the VSync configuration
_PresentParameters.PresentationInterval = CConfig.Config.Graphics.VSync == EOffOn.TR_CONFIG_ON ? PresentInterval.Default : PresentInterval.Immediate;
//GMA 950 graphics devices can only process vertices in software mode
- var caps = _D3D.GetDeviceCaps(_D3D.Adapters.DefaultAdapter.Adapter, DeviceType.Hardware);
+ var caps = _D3D.GetDeviceCaps(adapter, DeviceType.Hardware);
var flags = (caps.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0 ? CreateFlags.HardwareVertexProcessing : CreateFlags.SoftwareVertexProcessing;
//Check if Pow2 textures are needed
@@ -185,7 +215,7 @@ namespace Vocaluxe.Lib.Draw
try
{
- _Device = new Device(_D3D, _D3D.Adapters.DefaultAdapter.Adapter, DeviceType.Hardware, _Form.Handle, flags, _PresentParameters);
+ _Device = _D3D.CreateDevice(adapter, DeviceType.Hardware, _Form.Handle, flags, _PresentParameters);
}
catch (Exception e)
{
@@ -193,10 +223,9 @@ namespace Vocaluxe.Lib.Draw
}
finally
{
- if (_Device == null || _Device.Disposed)
+ if (_Device == null)
{
- CLog.Fatal(
- "Something went wrong during device creating, please check if your DirectX redistributables and grafic card drivers are up to date. You can download the DirectX runtimes at http://www.microsoft.com/download/en/details.aspx?id=8109");
+ CLog.Fatal("Something went wrong during device creating, please check if your grafic card drivers are up to date.");
}
}
}
@@ -235,9 +264,6 @@ namespace Vocaluxe.Lib.Draw
_ClearScreen();
//To set new PresentParameters the device has to be resetted
_Reset();
- //All configurations got flushed due to Reset(), so apply them again
- _InitDevice();
- _Device.Viewport = new Viewport(_X, _Y, _W, _H);
}
//Store size so it can get restored after the window gets minimized
@@ -271,7 +297,7 @@ namespace Vocaluxe.Lib.Draw
return false;
}
- if (_Device.Disposed)
+ if (_Device == null)
{
return false;
}
@@ -294,88 +320,36 @@ namespace Vocaluxe.Lib.Draw
{
_AdjustNewBorders();
- _VertexBuffer = new VertexBuffer(_Device, CSettings.VertexBufferElements * 4 * Marshal.SizeOf(typeof(STexturedColoredVertex)), Usage.WriteOnly | Usage.Dynamic,
+ var vertexSize = Marshal.SizeOf(typeof(STexturedColoredVertex));
+ _VertexBuffer = _Device.CreateVertexBuffer(CSettings.VertexBufferElements * 4 * vertexSize, Usage.WriteOnly | Usage.Dynamic,
VertexFormat.Position | VertexFormat.Texture1 | VertexFormat.Diffuse, Pool.Default);
- if (_Device.SetStreamSource(0, _VertexBuffer, 0, Marshal.SizeOf(typeof(STexturedColoredVertex))).IsFailure)
- {
- CLog.Error("Failed to set stream source");
- }
-
+ _Device.SetStreamSource(0, _VertexBuffer, 0, vertexSize);
_Device.VertexDeclaration = STexturedColoredVertex.GetDeclaration(_Device);
- if (_Device.SetRenderState(RenderState.CullMode, Cull.None).IsFailure)
+ _Device.SetRenderState(RenderState.CullMode, (int)Cull.None);
+ _Device.SetRenderState(RenderState.ZEnable, (int)ZBufferType.UseZBuffer);
+ _Device.SetRenderState(RenderState.ZFunc, (int)Compare.LessEqual);
+ _Device.SetRenderState(RenderState.ZWriteEnable, true);
+ _Device.SetRenderState(RenderState.AlphaBlendEnable, true);
+ _Device.SetRenderState(RenderState.Lighting, false);
+ _Device.SetRenderState(RenderState.DestinationBlend, (int)Blend.InverseSourceAlpha);
+ _Device.SetRenderState(RenderState.SourceBlend, (int)Blend.SourceAlpha);
+
+ if (_PresentParameters.MultiSampleType != MultisampleType.None)
{
- CLog.Error("Failed to set cull mode");
+ _Device.SetRenderState(RenderState.MultisampleAntialias, true);
}
- if (_Device.SetRenderState(RenderState.AlphaBlendEnable, true).IsFailure)
- {
- CLog.Error("Failed to enable alpha blending");
- }
+ _Device.SetSamplerState(0, SamplerState.MinFilter, (int)TextureFilter.Linear);
+ _Device.SetSamplerState(0, SamplerState.MagFilter, (int)TextureFilter.Linear);
+ _Device.SetSamplerState(0, SamplerState.MipFilter, (int)TextureFilter.Linear);
+ _Device.SetSamplerState(0, SamplerState.AddressU, (int)TextureAddress.Clamp);
+ _Device.SetSamplerState(0, SamplerState.AddressV, (int)TextureAddress.Clamp);
- if (_Device.SetRenderState(RenderState.Lighting, false).IsFailure)
- {
- CLog.Error("Failed to disable lighting");
- }
-
- if (_Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha).IsFailure)
- {
- CLog.Error("Failed to set destination blend");
- }
-
- if (_Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha).IsFailure)
- {
- CLog.Error("Failed to set source blend");
- }
-
- if (_PresentParameters.Multisample != MultisampleType.None)
- {
- if (_Device.SetRenderState(RenderState.MultisampleAntialias, true).IsFailure)
- {
- CLog.Error("Failed to set antialiasing");
- }
- }
-
- if (_Device.SetSamplerState(0, SamplerState.MinFilter, TextureFilter.Linear).IsFailure)
- {
- CLog.Error("Failed to set min filter");
- }
-
- if (_Device.SetSamplerState(0, SamplerState.MagFilter, TextureFilter.Linear).IsFailure)
- {
- CLog.Error("Failed to set mag filter");
- }
-
- if (_Device.SetSamplerState(0, SamplerState.MipFilter, TextureFilter.Linear).IsFailure)
- {
- CLog.Error("Failed to set mip filter");
- }
-
- if (_Device.SetSamplerState(0, SamplerState.AddressU, TextureAddress.Clamp).IsFailure)
- {
- CLog.Error("Failed to set clamping on u");
- }
-
- if (_Device.SetSamplerState(0, SamplerState.AddressV, TextureAddress.Clamp).IsFailure)
- {
- CLog.Error("Failed to set claming on v");
- }
-
- if (_Device.SetTextureStageState(0, TextureStage.AlphaArg1, TextureArgument.Texture).IsFailure)
- {
- CLog.Error("Failed to set alpha argument 1");
- }
-
- if (_Device.SetTextureStageState(0, TextureStage.AlphaArg2, TextureArgument.Diffuse).IsFailure)
- {
- CLog.Error("Failed to set alpha argument 2");
- }
-
- if (_Device.SetTextureStageState(0, TextureStage.AlphaOperation, TextureOperation.Modulate).IsFailure)
- {
- CLog.Error("Failed to set alpha operation");
- }
+ _Device.SetTextureStageState(0, TextureStage.AlphaArg1, (int)TextureArgument.Texture);
+ _Device.SetTextureStageState(0, TextureStage.AlphaArg2, (int)TextureArgument.Diffuse);
+ _Device.SetTextureStageState(0, TextureStage.AlphaOperation, (int)TextureOperation.Modulate);
var indices = new Int16[6];
indices[0] = 0;
@@ -385,85 +359,123 @@ namespace Vocaluxe.Lib.Draw
indices[4] = 2;
indices[5] = 3;
- _IndexBuffer = new IndexBuffer(_Device, 6 * sizeof(Int16), Usage.WriteOnly, Pool.Managed, true);
+ _IndexBuffer = _Device.CreateIndexBuffer(6 * sizeof(Int16), Usage.WriteOnly, true, Pool.Managed);
- var stream = _IndexBuffer.Lock(0, 0, LockFlags.Discard);
- stream.WriteRange(indices);
+ var indexData = _IndexBuffer.Lock(0, 6 * sizeof(Int16), LockFlags.Discard);
+ MemoryMarshal.AsBytes(indices.AsSpan()).CopyTo(indexData);
_IndexBuffer.Unlock();
_Device.Indices = _IndexBuffer;
}
protected override void _OnBeforeDraw()
{
- if (_Device.BeginScene().IsFailure)
+ try
{
- CLog.Error("Failed to begin scene");
+ _Device.BeginScene();
+ }
+ catch (SharpGenException e)
+ {
+ CLog.Error(e, "Failed to begin scene");
}
}
protected override void _OnAfterDraw()
{
_RenderVertexBuffer();
- if (_Device.EndScene().IsFailure)
- {
- CLog.Error("Failed to end scene");
- }
-
try
{
- //Now push the frame to the Viewport
- _Device.Present();
+ _Device.EndScene();
}
- catch (Direct3D9Exception)
+ catch (SharpGenException e)
+ {
+ CLog.Error(e, "Failed to end scene");
+ }
+
+ //Now push the frame to the Viewport
+ var result = _Device.Present();
+ if (result.Failure)
{
//In Direct3D devices can get lost.
//This happens for example when opening the Task Manager in Vista/Windows 7 or if a UAC message is opening
//We need to reset the device to get it to workable state again
//After a reset Init() needs to be called because all data in the Direct3D default pool are lost and need to be recreated
- if (_Device.TestCooperativeLevel() == ResultCode.DeviceNotReset)
+ if (_GetCooperativeLevel() == _D3DErrDeviceNotReset)
{
_Reset();
- _InitDevice();
+ }
+ else if (result.Code != _D3DErrDeviceLost)
+ {
+ CLog.Error("Failed to present the frame: " + result);
}
}
Application.DoEvents();
}
+ private int _GetCooperativeLevel()
+ {
+ try
+ {
+ _Device.TestCooperativeLevel();
+ return 0;
+ }
+ catch (SharpGenException e)
+ {
+ return e.ResultCode.Code;
+ }
+ }
+
///
/// Resets the device, all objects in the Direct3D default pool get flushed and need to be recreated
///
private void _Reset()
{
//Dispose all objects in the default pool, those need to be recreated
- STexturedColoredVertex.GetDeclaration(_Device).Dispose();
- _VertexBuffer.Dispose();
- _IndexBuffer.Dispose();
- if (_Device.Reset(_PresentParameters).IsFailure)
+ _DisposeDeviceResources();
+ try
{
- CLog.Error("Failed to reset the device");
+ _Device.Reset(ref _PresentParameters);
+ //All configurations got flushed due to Reset(), so apply them again
+ _InitDevice();
+ _Device.Viewport = new Viewport { X = _X, Y = _Y, Width = _W, Height = _H, MinZ = 0f, MaxZ = 1f };
}
+ catch (SharpGenException e)
+ {
+ CLog.Error(e, "Failed to reset the device");
+ _DisposeDeviceResources();
+ }
+ }
+
+ private void _DisposeDeviceResources()
+ {
+ STexturedColoredVertex.DisposeDeclaration();
+ _VertexBuffer?.Dispose();
+ _VertexBuffer = null;
+ _IndexBuffer?.Dispose();
+ _IndexBuffer = null;
}
protected override void _AdjustNewBorders()
{
const float dx = (float)CSettings.RenderW / 2;
const float dy = (float)CSettings.RenderH / 2;
- var translate = Matrix.Translation(new Vector3(-dx, dy, 0));
- var projection = Matrix.OrthoOffCenterLH(
+ var translate = Matrix4x4.CreateTranslation(-dx, dy, 0);
+ var projection = _CreateOrthoOffCenterLH(
-dx - _BorderLeft, CSettings.RenderW * CConfig.Config.Graphics.NumScreens - dx + _BorderRight,
-dy - _BorderBottom, dy + _BorderTop,
CSettings.ZNear, CSettings.ZFar);
- if (_Device.SetTransform(TransformState.Projection, projection).IsFailure)
- {
- CLog.Error("Failed to set orthogonal matrix");
- }
+ _Device.SetTransform(TransformState.Projection, projection);
+ _Device.SetTransform(0, translate);
+ }
- if (_Device.SetTransform(TransformState.World, translate).IsFailure)
- {
- CLog.Error("Failed to set translation matrix");
- }
+ private static Matrix4x4 _CreateOrthoOffCenterLH(float left, float right, float bottom, float top, float zNear, float zFar)
+ {
+ return new Matrix4x4(
+ 2f / (right - left), 0f, 0f, 0f,
+ 0f, 2f / (top - bottom), 0f, 0f,
+ 0f, 0f, 1f / (zFar - zNear), 0f,
+ (left + right) / (left - right), (top + bottom) / (bottom - top), zNear / (zNear - zFar), 1f);
}
///
@@ -473,11 +485,9 @@ namespace Vocaluxe.Lib.Draw
public override void Close()
{
base.Close();
- STexturedColoredVertex.DisposeDeclaration();
- _VertexBuffer.Dispose();
- _IndexBuffer.Dispose();
- _Device.Dispose();
- _D3D.Dispose();
+ _DisposeDeviceResources();
+ _Device?.Dispose();
+ _D3D?.Dispose();
}
///
@@ -540,7 +550,7 @@ namespace Vocaluxe.Lib.Draw
/// A TexturedColoredVertex array containg 4 vertices
/// The texture the vertex should be textured with
/// The vertices' rotation
- private void _AddToVertexBuffer(STexturedColoredVertex[] vertices, Texture tex, Matrix rotation)
+ private void _AddToVertexBuffer(STexturedColoredVertex[] vertices, IDirect3DTexture9 tex, Matrix4x4 rotation)
{
//The vertexbuffer is full, so we need to flush it before we can continue
if (_Vertices.Count >= CSettings.VertexBufferElements)
@@ -566,30 +576,31 @@ namespace Vocaluxe.Lib.Draw
return;
}
- //The vertex buffer locks are slow actions, its better to lock once per frame and write all vertices to the buffer at once
- var stream = _VertexBuffer.Lock(0, _Vertices.Count * Marshal.SizeOf(typeof(STexturedColoredVertex)), LockFlags.Discard);
- stream.WriteRange(_Vertices.ToArray());
- _VertexBuffer.Unlock();
- stream.Dispose();
-
- for (var i = 0; i < _Vertices.Count; i += 4)
+ if (_VertexBuffer != null)
{
- //Apply rotation
- if (_Device.SetTransform(TransformState.World, _VerticesRotationMatrices.Dequeue()).IsFailure)
+ try
{
- CLog.Error("Failed to set world transformation");
- }
+ //The vertex buffer locks are slow actions, its better to lock once per frame and write all vertices to the buffer at once
+ var vertexData = MemoryMarshal.AsBytes(_Vertices.ToArray().AsSpan());
+ var bufferData = _VertexBuffer.Lock(0, vertexData.Length, LockFlags.Discard);
+ vertexData.CopyTo(bufferData);
+ _VertexBuffer.Unlock();
- //Apply texture
- if (_Device.SetTexture(0, _VerticesTextures.Dequeue()).IsFailure)
- {
- CLog.Error("Failed to set texture");
- }
+ for (var i = 0; i < _Vertices.Count; i += 4)
+ {
+ //Apply rotation
+ _Device.SetTransform(0, _VerticesRotationMatrices.Dequeue());
- //Draw 2 triangles from vertexbuffer
- if (_Device.DrawIndexedPrimitives(PrimitiveType.TriangleList, i, 0, 4, 0, 2).IsFailure)
+ //Apply texture
+ _Device.SetTexture(0, _VerticesTextures.Dequeue());
+
+ //Draw 2 triangles from vertexbuffer
+ _Device.DrawIndexedPrimitive(PrimitiveType.TriangleList, i, 0, 4, 0, 2);
+ }
+ }
+ catch (SharpGenException e)
{
- CLog.Error("Failed to draw quad");
+ CLog.Error(e, "Failed to render the vertex buffer");
}
}
@@ -605,9 +616,94 @@ namespace Vocaluxe.Lib.Draw
///
protected override void _ClearScreen()
{
- if (_Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0).IsFailure)
+ try
{
- CLog.Error("Failed to clear the backbuffer");
+ _Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, new Vortice.Mathematics.Color(0, 0, 0, 255), 1.0f, 0);
+ }
+ catch (SharpGenException e)
+ {
+ CLog.Error(e, "Failed to clear the backbuffer");
+ }
+ }
+
+ private int[] _ReadBackBuffer(out int width, out int height)
+ {
+ width = 0;
+ height = 0;
+ try
+ {
+ using (var backBuffer = _Device.GetBackBuffer(0, 0))
+ {
+ var desc = backBuffer.Description;
+ if (desc.Format != Format.X8R8G8B8 && desc.Format != Format.A8R8G8B8)
+ {
+ CLog.Error("Reading the backbuffer is not supported for format " + desc.Format);
+ return null;
+ }
+
+ width = desc.Width;
+ height = desc.Height;
+ var rect = new Rect(0, 0, width, height);
+
+ using (var renderTarget = _Device.CreateRenderTarget(width, height, desc.Format, MultisampleType.None, 0, false))
+ using (var sysMemSurface = _Device.CreateOffscreenPlainSurface(width, height, desc.Format, Pool.SystemMemory))
+ {
+ _Device.StretchRect(backBuffer, rect, renderTarget, rect, TextureFilter.None);
+ _Device.GetRenderTargetData(renderTarget, sysMemSurface);
+
+ var pixels = new int[width * height];
+ var locked = sysMemSurface.LockRect(LockFlags.ReadOnly);
+ try
+ {
+ for (var y = 0; y < height; y++)
+ {
+ Marshal.Copy(IntPtr.Add(locked.DataPointer, y * locked.Pitch), pixels, y * width, width);
+ }
+ }
+ finally
+ {
+ sysMemSurface.UnlockRect();
+ }
+
+ for (var i = 0; i < pixels.Length; i++)
+ {
+ pixels[i] |= unchecked((int)0xFF000000);
+ }
+
+ return pixels;
+ }
+ }
+ }
+ catch (SharpGenException e)
+ {
+ CLog.Error(e, "Failed to read the backbuffer");
+ return null;
+ }
+ }
+
+ private void _CopyBackBufferToTexture(CD3DTexture texture)
+ {
+ int bufferWidth, bufferHeight;
+ var pixels = _ReadBackBuffer(out bufferWidth, out bufferHeight);
+ if (pixels == null)
+ {
+ return;
+ }
+
+ var width = Math.Min(Math.Min(_W, bufferWidth), texture.Size.Width);
+ var height = Math.Min(Math.Min(_H, bufferHeight), texture.Size.Height);
+
+ var locked = texture.D3DTexture.LockRect(0, LockFlags.Discard);
+ try
+ {
+ for (var y = 0; y < height; y++)
+ {
+ Marshal.Copy(pixels, y * bufferWidth, IntPtr.Add(locked.DataPointer, y * locked.Pitch), width);
+ }
+ }
+ finally
+ {
+ texture.D3DTexture.UnlockRect(0);
}
}
@@ -618,10 +714,7 @@ namespace Vocaluxe.Lib.Draw
public CTextureRef CopyScreen()
{
var tex = _CreateTexture(new Size(_W, _H));
- var backbufferSurface = _Device.GetBackBuffer(0, 0);
- var textureSurface = tex.D3DTexture.GetSurfaceLevel(0);
- Surface.FromSurface(textureSurface, backbufferSurface, Filter.Default, 0, new Rectangle(0, 0, _W, _H), new Rectangle(0, 0, _W, _H));
- backbufferSurface.Dispose();
+ _CopyBackBufferToTexture(tex);
return _GetTextureReference(_W, _H, tex);
}
@@ -640,10 +733,7 @@ namespace Vocaluxe.Lib.Draw
}
else
{
- var backbufferSurface = _Device.GetBackBuffer(0, 0);
- var textureSurface = texture.D3DTexture.GetSurfaceLevel(0);
- Surface.FromSurface(textureSurface, backbufferSurface, Filter.Default, 0);
- backbufferSurface.Dispose();
+ _CopyBackBufferToTexture(texture);
}
}
@@ -654,12 +744,29 @@ namespace Vocaluxe.Lib.Draw
{
var file = CHelper.GetUniqueFileName(Path.Combine(CSettings.DataFolder, CSettings.FolderNameScreenshots), "Screenshot.png");
- //create a surface of the frame
- using (var surface = _Device.GetBackBuffer(0, 0))
+ int width, height;
+ var pixels = _ReadBackBuffer(out width, out height);
+ if (pixels == null)
{
- var screen = new Bitmap(Surface.ToStream(surface, ImageFileFormat.Png));
+ return;
+ }
+
+ using (var screen = new Bitmap(width, height, PixelFormat.Format32bppArgb))
+ {
+ var bmpData = screen.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
+ try
+ {
+ for (var y = 0; y < height; y++)
+ {
+ Marshal.Copy(pixels, y * width, IntPtr.Add(bmpData.Scan0, y * bmpData.Stride), width);
+ }
+ }
+ finally
+ {
+ screen.UnlockBits(bmpData);
+ }
+
screen.Save(file, ImageFormat.Png);
- screen.Dispose();
}
}
@@ -697,11 +804,11 @@ namespace Vocaluxe.Lib.Draw
protected override void _WriteDataToTexture(CD3DTexture texture, byte[] data)
{
- var rect = texture.D3DTexture.LockRectangle(0, LockFlags.Discard);
+ var rect = texture.D3DTexture.LockRect(0, LockFlags.Discard);
try
{
var rowWidth = 4 * texture.DataSize.Width;
- var dst = rect.Data.DataPointer;
+ var dst = rect.DataPointer;
if (rowWidth == rect.Pitch)
Marshal.Copy(data, 0, dst, data.Length);
else
@@ -711,21 +818,21 @@ namespace Vocaluxe.Lib.Draw
Marshal.Copy(data, y * rowWidth, IntPtr.Add(dst, y * rect.Pitch), rowWidth);
}
}
- finally { texture.D3DTexture.UnlockRectangle(0); }
+ finally { texture.D3DTexture.UnlockRect(0); }
}
- private static Matrix _CalculateRotationMatrix(float rot, float rx1, float rx2, float ry1, float ry2)
+ private static Matrix4x4 _CalculateRotationMatrix(float rot, float rx1, float rx2, float ry1, float ry2)
{
- var originTranslation = Matrix.Translation(new Vector3(-(float)CSettings.RenderW / 2, (float)CSettings.RenderH / 2, 0));
+ var originTranslation = Matrix4x4.CreateTranslation(-(float)CSettings.RenderW / 2, (float)CSettings.RenderH / 2, 0);
if (Math.Abs(rot) > float.Epsilon)
{
var rotation = rot * (float)Math.PI / 180;
var centerX = (rx1 + rx2) / 2f;
var centerY = -(ry1 + ry2) / 2f;
- var translationA = Matrix.Translation(-centerX, -centerY, 0);
- var rotationMat = Matrix.RotationZ(-rotation);
- var translationB = Matrix.Translation(centerX, centerY, 0);
+ var translationA = Matrix4x4.CreateTranslation(-centerX, -centerY, 0);
+ var rotationMat = Matrix4x4.CreateRotationZ(-rotation);
+ var translationB = Matrix4x4.CreateTranslation(centerX, centerY, 0);
//Multiplicate the matrices to get the real world matrix,
//First shift the texture into the center
@@ -740,7 +847,7 @@ namespace Vocaluxe.Lib.Draw
private struct STexturedColoredVertex
{
- private static VertexDeclaration _Declaration;
+ private static IDirect3DVertexDeclaration9 _Declaration;
private static readonly VertexElement[] _Elements =
{
new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
@@ -762,11 +869,11 @@ namespace Vocaluxe.Lib.Draw
_Color = color;
}
- public static VertexDeclaration GetDeclaration(Device device)
+ public static IDirect3DVertexDeclaration9 GetDeclaration(IDirect3DDevice9 device)
{
- if (_Declaration == null || _Declaration.Disposed)
+ if (_Declaration == null)
{
- _Declaration = new VertexDeclaration(device, _Elements);
+ _Declaration = device.CreateVertexDeclaration(_Elements);
}
return _Declaration;
@@ -774,7 +881,7 @@ namespace Vocaluxe.Lib.Draw
public static void DisposeDeclaration()
{
- if (_Declaration != null && !_Declaration.Disposed)
+ if (_Declaration != null)
{
_Declaration.Dispose();
_Declaration = null;
diff --git a/Vocaluxe/Lib/Sound/Record/DirectSound/CDirectSoundRecord.cs b/Vocaluxe/Lib/Sound/Record/DirectSound/CDirectSoundRecord.cs
deleted file mode 100644
index 316ce10a..00000000
--- a/Vocaluxe/Lib/Sound/Record/DirectSound/CDirectSoundRecord.cs
+++ /dev/null
@@ -1,133 +0,0 @@
-#region license
-// This file is part of Vocaluxe.
-//
-// Vocaluxe is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Vocaluxe 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Vocaluxe. If not, see .
-#endregion
-
-using System.Collections.Generic;
-using System.Linq;
-using SlimDX.DirectSound;
-
-namespace Vocaluxe.Lib.Sound.Record.DirectSound
-{
- class CDirectSoundRecord : CRecordBase, IRecord
- {
- private bool _Initialized;
-
- private List _Sources;
-
- public override bool Init()
- {
- if (!base.Init())
- {
- return false;
- }
-
- _Sources = new List();
-
- var devices = DirectSoundCapture.GetDevices();
-
- foreach (var dev in devices)
- {
- using (var ds = new DirectSoundCapture(dev.DriverGuid))
- {
- var device = new CRecordDevice(_Devices.Count, dev.Description, dev.DriverGuid.ToString(), ds.Capabilities.Channels);
-
- _Devices.Add(device);
- }
- }
-
- _Initialized = true;
-
- return true;
- }
-
- public override void Close()
- {
- Stop();
- _Initialized = false;
- base.Close();
- }
-
- public bool Start()
- {
- if (!_Initialized)
- {
- return false;
- }
-
- foreach (var buffer in _Buffer)
- {
- buffer.Reset();
- }
-
- foreach (var device in _Devices)
- {
- var usingDevice = false;
- for (var ch = 0; ch < device.Channels; ++ch)
- {
- if (device.PlayerChannel[ch] > 0)
- {
- usingDevice = true;
- }
- }
-
- if (usingDevice)
- {
- var source = new CSoundCardSource(device.Driver, (short)device.Channels) { SampleRateKhz = 44.1 };
- source.SampleDataReady += _OnDataReady;
- source.Start();
-
- _Sources.Add(source);
- }
- }
-
- return true;
- }
-
- public bool Stop()
- {
- if (!_Initialized)
- {
- return false;
- }
-
- foreach (var source in _Sources)
- {
- source.Stop();
- source.Dispose();
- }
-
- _Sources.Clear();
-
- return true;
- }
-
- private void _OnDataReady(object sender, CSampleDataEventArgs e)
- {
- if (!_Initialized)
- {
- return;
- }
-
- var dev = _Devices.FirstOrDefault(device => device.Driver == e.Guid);
- if (dev == null)
- {
- return;
- }
-
- _HandleData(dev, e.Data);
- }
- }
-}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Sound/Record/DirectSound/CSampleDataEventArgs.cs b/Vocaluxe/Lib/Sound/Record/DirectSound/CSampleDataEventArgs.cs
deleted file mode 100644
index b52911e4..00000000
--- a/Vocaluxe/Lib/Sound/Record/DirectSound/CSampleDataEventArgs.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-#region license
-// This file is part of Vocaluxe.
-//
-// Vocaluxe is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Vocaluxe 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Vocaluxe. If not, see .
-#endregion
-
-using System;
-
-namespace Vocaluxe.Lib.Sound.Record.DirectSound
-{
- public class CSampleDataEventArgs : EventArgs
- {
- public readonly byte[] Data;
- public readonly string Guid;
-
- public CSampleDataEventArgs(byte[] data, string guid)
- {
- Data = data;
- Guid = guid;
- }
- }
-}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Sound/Record/DirectSound/CSoundCardSource.cs b/Vocaluxe/Lib/Sound/Record/DirectSound/CSoundCardSource.cs
deleted file mode 100644
index 988a98db..00000000
--- a/Vocaluxe/Lib/Sound/Record/DirectSound/CSoundCardSource.cs
+++ /dev/null
@@ -1,202 +0,0 @@
-#region license
-// This file is part of Vocaluxe.
-//
-// Vocaluxe is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Vocaluxe 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Vocaluxe. If not, see .
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using SlimDX.DirectSound;
-using SlimDX.Multimedia;
-
-namespace Vocaluxe.Lib.Sound.Record.DirectSound
-{
- public class CSoundCardSource : IDisposable
- {
- private volatile bool _Running;
- private readonly int _BufferSize;
- private CaptureBuffer _CaptureBuffer;
- private CaptureBufferDescription _BufferDescription;
- private DirectSoundCapture _CaptureDevice;
- private readonly WaveFormat _WaveFormat;
- private Thread _CaptureThread;
- private List _Notifications;
- private int _BufferPortionCount;
- private int _BufferPortionSize;
- private WaitHandle[] _WaitHandles;
- private double _SampleRate;
- private readonly string _Guid;
- private readonly short _Channels;
-
- public CSoundCardSource(string guid, short channels)
- {
- _Guid = guid;
- _Channels = channels;
- _WaveFormat = new WaveFormat();
- SampleRateKhz = 44.1;
- _BufferSize = 2048;
- }
-
- public event EventHandler SampleDataReady = delegate { };
-
- public double SampleRateKhz
- {
- get { return _SampleRate; }
-
- set
- {
- _SampleRate = value;
-
- if (_Running)
- {
- Restart();
- }
- }
- }
-
- public void Start()
- {
- if (_Running)
- {
- throw new InvalidOperationException();
- }
-
- if (_CaptureDevice == null)
- {
- _CaptureDevice = new DirectSoundCapture(new Guid(_Guid));
- }
-
- _WaveFormat.FormatTag = WaveFormatTag.Pcm; // Change to WaveFormatTag.IeeeFloat for float
- _WaveFormat.BitsPerSample = 16; // Set this to 32 for float
- _WaveFormat.BlockAlignment = (short)(_Channels * (_WaveFormat.BitsPerSample / 8));
- _WaveFormat.Channels = _Channels;
- _WaveFormat.SamplesPerSecond = (int)(SampleRateKhz * 1000D);
- _WaveFormat.AverageBytesPerSecond =
- _WaveFormat.SamplesPerSecond *
- _WaveFormat.BlockAlignment;
-
- _BufferPortionCount = 2;
-
- _BufferDescription.BufferBytes = _BufferSize * sizeof(short) * _BufferPortionCount * _Channels;
- _BufferDescription.Format = _WaveFormat;
- _BufferDescription.WaveMapped = false;
-
- _CaptureBuffer = new CaptureBuffer(_CaptureDevice, _BufferDescription);
-
- _BufferPortionSize = _CaptureBuffer.SizeInBytes / _BufferPortionCount;
- _Notifications = new List();
-
- for (var i = 0; i < _BufferPortionCount; i++)
- {
- var notification = new NotificationPosition { Offset = _BufferPortionCount - 1 + _BufferPortionSize * i, Event = new AutoResetEvent(false) };
- _Notifications.Add(notification);
- }
-
- _CaptureBuffer.SetNotificationPositions(_Notifications.ToArray());
- _WaitHandles = new WaitHandle[_Notifications.Count];
-
- for (var i = 0; i < _Notifications.Count; i++)
- {
- _WaitHandles[i] = _Notifications[i].Event;
- }
-
- _CaptureThread = new Thread(_DoCapture) { Name = "DirectSoundCapture", IsBackground = true };
-
- _Running = true;
- _CaptureThread.Start();
- }
-
- public void Stop()
- {
- _Running = false;
-
- if (_CaptureThread != null)
- {
- _CaptureThread.Join();
- _CaptureThread = null;
- }
-
- if (_CaptureBuffer != null)
- {
- _CaptureBuffer.Dispose();
- _CaptureBuffer = null;
- }
-
- if (_Notifications != null)
- {
- foreach (var notification in _Notifications)
- {
- notification.Event.Close();
- }
-
- _Notifications.Clear();
- _Notifications = null;
- }
- }
-
- public void Restart()
- {
- Stop();
- Start();
- }
-
- private void _DoCapture()
- {
- var bufferPortionSamples = _BufferPortionSize / sizeof(byte);
-
- // Buffer type must match this.waveFormat.FormatTag and this.waveFormat.BitsPerSample
- var bufferPortion = new byte[bufferPortionSamples];
-
- _CaptureBuffer.Start(true);
-
- while (_Running)
- {
- var bufferPortionIndex = WaitHandle.WaitAny(_WaitHandles);
-
- _CaptureBuffer.Read(
- bufferPortion,
- 0,
- bufferPortionSamples,
- _BufferPortionSize * Math.Abs((bufferPortionIndex - 1) % _BufferPortionCount));
-
- SampleDataReady(this, new CSampleDataEventArgs(bufferPortion, _Guid));
- }
-
- _CaptureBuffer.Stop();
- }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- // ReSharper disable InconsistentNaming
- protected void Dispose(bool disposing)
- // ReSharper restore InconsistentNaming
- {
- if (disposing)
- {
- Stop();
-
- if (_CaptureDevice != null)
- {
- _CaptureDevice.Dispose();
- _CaptureDevice = null;
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Sound/Record/NAudio/CNAudioRecord.cs b/Vocaluxe/Lib/Sound/Record/NAudio/CNAudioRecord.cs
new file mode 100644
index 00000000..08b51ed0
--- /dev/null
+++ b/Vocaluxe/Lib/Sound/Record/NAudio/CNAudioRecord.cs
@@ -0,0 +1,198 @@
+#region license
+// This file is part of Vocaluxe.
+//
+// Vocaluxe is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Vocaluxe 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Vocaluxe. If not, see .
+#endregion
+
+using System;
+using System.Collections.Generic;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
+using VocaluxeLib.Log;
+
+namespace Vocaluxe.Lib.Sound.Record.NAudio
+{
+ class CNAudioRecord : CRecordBase, IRecord
+ {
+ private const int _SampleRate = 44100;
+ private const int _BitsPerSample = 16;
+ private const int _BufferMilliseconds = 20;
+
+ private bool _Initialized;
+ private MMDeviceEnumerator _Enumerator;
+ private readonly List _Captures = new List();
+
+ public override bool Init()
+ {
+ if (!base.Init())
+ {
+ return false;
+ }
+
+ try
+ {
+ _Enumerator = new MMDeviceEnumerator();
+ foreach (var device in _Enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active))
+ {
+ try
+ {
+ using (device)
+ using (var client = device.AudioClient)
+ {
+ _Devices.Add(new CRecordDevice(_Devices.Count, device.FriendlyName, device.ID, client.MixFormat.Channels));
+ }
+ }
+ catch (Exception e)
+ {
+ CLog.Error(e, "Error initializing NAudio record device:");
+ }
+ }
+
+ _Initialized = true;
+ }
+ catch (Exception e)
+ {
+ CLog.Error(e, "Error initializing NAudio (WASAPI) recording:");
+ Close();
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool Start()
+ {
+ if (!_Initialized)
+ {
+ return false;
+ }
+
+ Stop();
+
+ foreach (var buffer in _Buffer)
+ {
+ buffer.Reset();
+ }
+
+ var success = true;
+ foreach (var dev in _Devices)
+ {
+ var usingDevice = false;
+ for (var ch = 0; ch < dev.Channels; ++ch)
+ {
+ if (dev.PlayerChannel[ch] > 0)
+ {
+ usingDevice = true;
+ }
+ }
+
+ if (!usingDevice)
+ {
+ continue;
+ }
+
+ WasapiCapture capture = null;
+ try
+ {
+ using (var mmDevice = _Enumerator.GetDevice(dev.Driver))
+ {
+ capture = new WasapiCapture(mmDevice, true, _BufferMilliseconds)
+ {
+ WaveFormat = new WaveFormat(_SampleRate, _BitsPerSample, dev.Channels)
+ };
+ }
+
+ var device = dev;
+ capture.DataAvailable += (sender, e) => _OnDataAvailable(device, e);
+ capture.RecordingStopped += (sender, e) => _OnRecordingStopped(device, e);
+ capture.StartRecording();
+ _Captures.Add(capture);
+ }
+ catch (Exception e)
+ {
+ CLog.Error(e, "Error starting NAudio record device " + dev.Name + ":");
+ capture?.Dispose();
+ success = false;
+ }
+ }
+
+ return success;
+ }
+
+ public bool Stop()
+ {
+ if (!_Initialized)
+ {
+ return false;
+ }
+
+ foreach (var capture in _Captures)
+ {
+ try
+ {
+ capture.Dispose();
+ }
+ catch (Exception e)
+ {
+ CLog.Error(e, "Error stopping NAudio record device:");
+ }
+ }
+
+ _Captures.Clear();
+
+ return true;
+ }
+
+ public override void Close()
+ {
+ Stop();
+ _Initialized = false;
+
+ if (_Enumerator != null)
+ {
+ _Enumerator.Dispose();
+ _Enumerator = null;
+ }
+
+ base.Close();
+ }
+
+ private static void _OnRecordingStopped(CRecordDevice device, StoppedEventArgs e)
+ {
+ if (e.Exception != null)
+ {
+ CLog.Error(e.Exception, "NAudio record device " + device.Name + " stopped:");
+ }
+ }
+
+ private void _OnDataAvailable(CRecordDevice device, WaveInEventArgs e)
+ {
+ if (e.BytesRecorded <= 0)
+ {
+ return;
+ }
+
+ try
+ {
+ var recbuffer = new byte[e.BytesRecorded];
+ Array.Copy(e.Buffer, recbuffer, e.BytesRecorded);
+ _HandleData(device, recbuffer);
+ }
+ catch (Exception ex)
+ {
+ CLog.Error(ex, "Error on NAudio record callback:");
+ }
+ }
+ }
+}
diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj
index 44d84c57..dd64b1dd 100644
--- a/Vocaluxe/Vocaluxe.csproj
+++ b/Vocaluxe/Vocaluxe.csproj
@@ -198,7 +198,10 @@
-
+
+
+
+
@@ -280,8 +283,6 @@
-
-
@@ -317,11 +318,11 @@
-
+
diff --git a/VocaluxeLib/Enums.cs b/VocaluxeLib/Enums.cs
index 9f0046ac..4ec534a1 100644
--- a/VocaluxeLib/Enums.cs
+++ b/VocaluxeLib/Enums.cs
@@ -189,10 +189,10 @@ namespace VocaluxeLib
public enum ERecordLib
{
+ PortAudio,
#if WIN
- DirectSound,
+ NAudio
#endif
- PortAudio
}
public enum EVideoDecoder