diff --git a/Documentation/input/reference/property/playtripletfeel.cshtml b/Documentation/input/reference/property/playtripletfeel.cshtml new file mode 100644 index 000000000..22dfa7ebb --- /dev/null +++ b/Documentation/input/reference/property/playtripletfeel.cshtml @@ -0,0 +1,57 @@ +Title: PlayTripletFeel +JsName: playTripletFeel +DataAttribute: data-play-triplet-feel +Category: Core +Description: Gets or sets whether in the triplet feel should be applied during playback. +Since: 0.9.5 +ShowInSideBar: false +--- + +

Description

+

+ If this setting is enabled alphaTab will consider the triplet feel during playback not only for display above the notation. +

+ +

Types

+ + + + + + + +
bool
+ +

Default Value

+ +true + +

Example - C#

+ +
+
+var settings = Settings.Defaults; 
+settings.PlayTripletFeel = false;
+
+
+ + +

Example - JavaScript

+ +
+
+var settings = {
+    playTripletFeel: false
+};
+var api = new alphaTab.platform.javaScript.AlphaTabApi(document.querySelector('#alphaTab'), settings);
+var japi = $('#alphaTab').alphaTab(settings);
+
+
+ +

Example - HTML

+ +
+
+<div id="alphaTab" data-play-triplet-feel="true"></div>
+
+
\ No newline at end of file diff --git a/Phase/Compiler/CopyNewCompiler.bat b/Phase/Compiler/CopyNewCompiler.bat index 16780a76e..09f3a4adb 100644 --- a/Phase/Compiler/CopyNewCompiler.bat +++ b/Phase/Compiler/CopyNewCompiler.bat @@ -1,2 +1,2 @@ taskkill /im:msbuild.exe /f -xcopy D:\Dev\C#\Projects\Phase.netstandard\Phase.MsBuild\bin\Debug\net471\* . /Y \ No newline at end of file +xcopy D:\Dev\CSharp\Phase.netstandard\Phase.MsBuild\bin\Debug\net48\* . /Y \ No newline at end of file diff --git a/Phase/Compiler/Microsoft.Build.Framework.dll b/Phase/Compiler/Microsoft.Build.Framework.dll index 9c692f202..85b367d63 100644 Binary files a/Phase/Compiler/Microsoft.Build.Framework.dll and b/Phase/Compiler/Microsoft.Build.Framework.dll differ diff --git a/Phase/Compiler/Microsoft.Build.Tasks.Core.dll b/Phase/Compiler/Microsoft.Build.Tasks.Core.dll index fac36f857..6ba793726 100644 Binary files a/Phase/Compiler/Microsoft.Build.Tasks.Core.dll and b/Phase/Compiler/Microsoft.Build.Tasks.Core.dll differ diff --git a/Phase/Compiler/Microsoft.Build.Utilities.Core.dll b/Phase/Compiler/Microsoft.Build.Utilities.Core.dll index 19d33c69d..692696825 100644 Binary files a/Phase/Compiler/Microsoft.Build.Utilities.Core.dll and b/Phase/Compiler/Microsoft.Build.Utilities.Core.dll differ diff --git a/Phase/Compiler/Microsoft.Build.dll b/Phase/Compiler/Microsoft.Build.dll index 5b50c7eff..628a3cdab 100644 Binary files a/Phase/Compiler/Microsoft.Build.dll and b/Phase/Compiler/Microsoft.Build.dll differ diff --git a/Phase/Compiler/Microsoft.CodeAnalysis.CSharp.Workspaces.dll b/Phase/Compiler/Microsoft.CodeAnalysis.CSharp.Workspaces.dll index 4308c3953..59af42257 100644 Binary files a/Phase/Compiler/Microsoft.CodeAnalysis.CSharp.Workspaces.dll and b/Phase/Compiler/Microsoft.CodeAnalysis.CSharp.Workspaces.dll differ diff --git a/Phase/Compiler/Microsoft.CodeAnalysis.CSharp.dll b/Phase/Compiler/Microsoft.CodeAnalysis.CSharp.dll index c48d7ceb6..e4c8010fe 100644 Binary files a/Phase/Compiler/Microsoft.CodeAnalysis.CSharp.dll and b/Phase/Compiler/Microsoft.CodeAnalysis.CSharp.dll differ diff --git a/Phase/Compiler/Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll b/Phase/Compiler/Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll index c861a3a80..b912e4834 100644 Binary files a/Phase/Compiler/Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll and b/Phase/Compiler/Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll differ diff --git a/Phase/Compiler/Microsoft.CodeAnalysis.VisualBasic.dll b/Phase/Compiler/Microsoft.CodeAnalysis.VisualBasic.dll index 8ebb96232..14421135d 100644 Binary files a/Phase/Compiler/Microsoft.CodeAnalysis.VisualBasic.dll and b/Phase/Compiler/Microsoft.CodeAnalysis.VisualBasic.dll differ diff --git a/Phase/Compiler/Microsoft.CodeAnalysis.Workspaces.dll b/Phase/Compiler/Microsoft.CodeAnalysis.Workspaces.dll index 545bc452a..a5a5140a9 100644 Binary files a/Phase/Compiler/Microsoft.CodeAnalysis.Workspaces.dll and b/Phase/Compiler/Microsoft.CodeAnalysis.Workspaces.dll differ diff --git a/Phase/Compiler/Microsoft.CodeAnalysis.dll b/Phase/Compiler/Microsoft.CodeAnalysis.dll index 6bde7b728..4761ae95d 100644 Binary files a/Phase/Compiler/Microsoft.CodeAnalysis.dll and b/Phase/Compiler/Microsoft.CodeAnalysis.dll differ diff --git a/Phase/Compiler/Mono.Cecil.Mdb.dll b/Phase/Compiler/Mono.Cecil.Mdb.dll index 5ecf070ec..18887bcf3 100644 Binary files a/Phase/Compiler/Mono.Cecil.Mdb.dll and b/Phase/Compiler/Mono.Cecil.Mdb.dll differ diff --git a/Phase/Compiler/Mono.Cecil.Pdb.dll b/Phase/Compiler/Mono.Cecil.Pdb.dll index e176614a0..680524c21 100644 Binary files a/Phase/Compiler/Mono.Cecil.Pdb.dll and b/Phase/Compiler/Mono.Cecil.Pdb.dll differ diff --git a/Phase/Compiler/Mono.Cecil.Rocks.dll b/Phase/Compiler/Mono.Cecil.Rocks.dll index 5d300e844..ddad3a715 100644 Binary files a/Phase/Compiler/Mono.Cecil.Rocks.dll and b/Phase/Compiler/Mono.Cecil.Rocks.dll differ diff --git a/Phase/Compiler/Mono.Cecil.dll b/Phase/Compiler/Mono.Cecil.dll index d6e42868c..56b01e9b3 100644 Binary files a/Phase/Compiler/Mono.Cecil.dll and b/Phase/Compiler/Mono.Cecil.dll differ diff --git a/Phase/Compiler/NLog.dll b/Phase/Compiler/NLog.dll index 89afd0c5f..9682bd69a 100644 Binary files a/Phase/Compiler/NLog.dll and b/Phase/Compiler/NLog.dll differ diff --git a/Phase/Compiler/Newtonsoft.Json.dll b/Phase/Compiler/Newtonsoft.Json.dll index d0aaed9c6..e4a63399d 100644 Binary files a/Phase/Compiler/Newtonsoft.Json.dll and b/Phase/Compiler/Newtonsoft.Json.dll differ diff --git a/Phase/Compiler/Phase.Core.dll b/Phase/Compiler/Phase.Core.dll index c5c639471..0518eb479 100644 Binary files a/Phase/Compiler/Phase.Core.dll and b/Phase/Compiler/Phase.Core.dll differ diff --git a/Phase/Compiler/Phase.Core.pdb b/Phase/Compiler/Phase.Core.pdb index 9c13816c5..d81a52831 100644 Binary files a/Phase/Compiler/Phase.Core.pdb and b/Phase/Compiler/Phase.Core.pdb differ diff --git a/Phase/Compiler/Phase.MsBuild.dll b/Phase/Compiler/Phase.MsBuild.dll index 1d01dadd8..32f737427 100644 Binary files a/Phase/Compiler/Phase.MsBuild.dll and b/Phase/Compiler/Phase.MsBuild.dll differ diff --git a/Phase/Compiler/Phase.MsBuild.pdb b/Phase/Compiler/Phase.MsBuild.pdb index 0fdb26450..11da7f720 100644 Binary files a/Phase/Compiler/Phase.MsBuild.pdb and b/Phase/Compiler/Phase.MsBuild.pdb differ diff --git a/Phase/Compiler/Phase.Translator.dll b/Phase/Compiler/Phase.Translator.dll index c429828fc..30c31e903 100644 Binary files a/Phase/Compiler/Phase.Translator.dll and b/Phase/Compiler/Phase.Translator.dll differ diff --git a/Phase/Compiler/Phase.Translator.pdb b/Phase/Compiler/Phase.Translator.pdb index afeab1b80..abd5b3537 100644 Binary files a/Phase/Compiler/Phase.Translator.pdb and b/Phase/Compiler/Phase.Translator.pdb differ diff --git a/Phase/Compiler/System.Buffers.dll b/Phase/Compiler/System.Buffers.dll new file mode 100644 index 000000000..b6d9c7782 Binary files /dev/null and b/Phase/Compiler/System.Buffers.dll differ diff --git a/Phase/Compiler/System.Collections.Immutable.dll b/Phase/Compiler/System.Collections.Immutable.dll index 049149f17..900b5ca37 100644 Binary files a/Phase/Compiler/System.Collections.Immutable.dll and b/Phase/Compiler/System.Collections.Immutable.dll differ diff --git a/Phase/Compiler/System.Memory.dll b/Phase/Compiler/System.Memory.dll new file mode 100644 index 000000000..bdfc501e9 Binary files /dev/null and b/Phase/Compiler/System.Memory.dll differ diff --git a/Phase/Compiler/System.Numerics.Vectors.dll b/Phase/Compiler/System.Numerics.Vectors.dll new file mode 100644 index 000000000..ce46d5be8 Binary files /dev/null and b/Phase/Compiler/System.Numerics.Vectors.dll differ diff --git a/Phase/Compiler/System.Resources.Extensions.dll b/Phase/Compiler/System.Resources.Extensions.dll new file mode 100644 index 000000000..73e49c80a Binary files /dev/null and b/Phase/Compiler/System.Resources.Extensions.dll differ diff --git a/Phase/Compiler/System.Runtime.CompilerServices.Unsafe.dll b/Phase/Compiler/System.Runtime.CompilerServices.Unsafe.dll new file mode 100644 index 000000000..315623926 Binary files /dev/null and b/Phase/Compiler/System.Runtime.CompilerServices.Unsafe.dll differ diff --git a/Phase/Compiler/System.Text.Encoding.CodePages.dll b/Phase/Compiler/System.Text.Encoding.CodePages.dll index 1e7cf1a9b..d0f7adf9e 100644 Binary files a/Phase/Compiler/System.Text.Encoding.CodePages.dll and b/Phase/Compiler/System.Text.Encoding.CodePages.dll differ diff --git a/Phase/Compiler/System.Threading.Tasks.Dataflow.dll b/Phase/Compiler/System.Threading.Tasks.Dataflow.dll index 7567471e1..a6816d4a8 100644 Binary files a/Phase/Compiler/System.Threading.Tasks.Dataflow.dll and b/Phase/Compiler/System.Threading.Tasks.Dataflow.dll differ diff --git a/Phase/Compiler/System.Threading.Tasks.Extensions.dll b/Phase/Compiler/System.Threading.Tasks.Extensions.dll index a1234ce81..e059050bb 100644 Binary files a/Phase/Compiler/System.Threading.Tasks.Extensions.dll and b/Phase/Compiler/System.Threading.Tasks.Extensions.dll differ diff --git a/Samples/CSharp/AlphaTab.Samples.Player/AlphaTab.Samples.Player.csproj b/Samples/CSharp/AlphaTab.Samples.Player/AlphaTab.Samples.Player.csproj index 7801c3c94..f801d99c6 100644 --- a/Samples/CSharp/AlphaTab.Samples.Player/AlphaTab.Samples.Player.csproj +++ b/Samples/CSharp/AlphaTab.Samples.Player/AlphaTab.Samples.Player.csproj @@ -1,6 +1,6 @@  - net472 + net48 Exe @@ -15,4 +15,4 @@ - \ No newline at end of file + diff --git a/Samples/CSharp/AlphaTab.Samples.PngDump/AlphaTab.Samples.PngDump.csproj b/Samples/CSharp/AlphaTab.Samples.PngDump/AlphaTab.Samples.PngDump.csproj index 5176de37f..580721b70 100644 --- a/Samples/CSharp/AlphaTab.Samples.PngDump/AlphaTab.Samples.PngDump.csproj +++ b/Samples/CSharp/AlphaTab.Samples.PngDump/AlphaTab.Samples.PngDump.csproj @@ -1,6 +1,6 @@  - net472 + net48 Exe diff --git a/Samples/CSharp/AlphaTab.Samples.ScoreDump/AlphaTab.Samples.ScoreDump.csproj b/Samples/CSharp/AlphaTab.Samples.ScoreDump/AlphaTab.Samples.ScoreDump.csproj index 5176de37f..580721b70 100644 --- a/Samples/CSharp/AlphaTab.Samples.ScoreDump/AlphaTab.Samples.ScoreDump.csproj +++ b/Samples/CSharp/AlphaTab.Samples.ScoreDump/AlphaTab.Samples.ScoreDump.csproj @@ -1,6 +1,6 @@  - net472 + net48 Exe diff --git a/Samples/CSharp/AlphaTab.Samples.WinForms/AlphaTab.Samples.WinForms.csproj b/Samples/CSharp/AlphaTab.Samples.WinForms/AlphaTab.Samples.WinForms.csproj index 4753f4ab9..7e259c9b0 100644 --- a/Samples/CSharp/AlphaTab.Samples.WinForms/AlphaTab.Samples.WinForms.csproj +++ b/Samples/CSharp/AlphaTab.Samples.WinForms/AlphaTab.Samples.WinForms.csproj @@ -1,6 +1,6 @@  - net472 + net48 WinExe true @@ -20,4 +20,4 @@ - \ No newline at end of file + diff --git a/Samples/CSharp/AlphaTab.Samples.Wpf/AlphaTab.Samples.Wpf.csproj b/Samples/CSharp/AlphaTab.Samples.Wpf/AlphaTab.Samples.Wpf.csproj index 3e08635e9..a8d14dc15 100644 --- a/Samples/CSharp/AlphaTab.Samples.Wpf/AlphaTab.Samples.Wpf.csproj +++ b/Samples/CSharp/AlphaTab.Samples.Wpf/AlphaTab.Samples.Wpf.csproj @@ -1,6 +1,6 @@  - net472 + net48 WinExe true @@ -12,7 +12,7 @@ - + @@ -37,4 +37,4 @@ - \ No newline at end of file + diff --git a/Source/AlphaTab.CSharp/AlphaTab.CSharp.csproj b/Source/AlphaTab.CSharp/AlphaTab.CSharp.csproj index ad5ff8c6c..ccf66ef6b 100644 --- a/Source/AlphaTab.CSharp/AlphaTab.CSharp.csproj +++ b/Source/AlphaTab.CSharp/AlphaTab.CSharp.csproj @@ -3,13 +3,13 @@ AlphaTab AlphaTab AlphaTab - netstandard2.0;net472 + netstandard2.0;net48 true $(OutDir)$(AssemblyName).xml $(NoWarn);0162 - + true true true @@ -28,7 +28,7 @@ - + @@ -61,4 +61,4 @@ - \ No newline at end of file + diff --git a/Source/AlphaTab.CSharp/Environment.cs b/Source/AlphaTab.CSharp/Environment.cs index 506551850..b15c8696c 100644 --- a/Source/AlphaTab.CSharp/Environment.cs +++ b/Source/AlphaTab.CSharp/Environment.cs @@ -8,7 +8,7 @@ internal partial class Environment private static void PlatformInit() { RenderEngines["svg"] = new RenderEngineFactory(true, () => new CssFontSvgCanvas()); -#if NET472 +#if NET48 RenderEngines["gdi"] = new RenderEngineFactory(true, () => new GdiCanvas()); #endif RenderEngines["skia"] = new RenderEngineFactory(true, () => new SkiaCanvas()); diff --git a/Source/AlphaTab.CSharp/IO/ZipFile.cs b/Source/AlphaTab.CSharp/IO/ZipFile.cs index a621e555e..5426c8dcb 100644 --- a/Source/AlphaTab.CSharp/IO/ZipFile.cs +++ b/Source/AlphaTab.CSharp/IO/ZipFile.cs @@ -11,7 +11,7 @@ internal partial class ZipFile /// public void Load(IReadable s) { -#if NET472 || NETSTANDARD2_0 +#if NET48 || NETSTANDARD2_0 using (var zipArchive = new System.IO.Compression.ZipArchive(ReadableStream.Create(s), System.IO.Compression.ZipArchiveMode.Read)) { @@ -57,7 +57,7 @@ public void Load(IReadable s) } } } - + } #endif } diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/GdiCanvas.cs b/Source/AlphaTab.CSharp/Platform/CSharp/GdiCanvas.cs index b608bde9b..152f9b90b 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/GdiCanvas.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/GdiCanvas.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using AlphaTab.Rendering; using AlphaTab.Rendering.Glyphs; using AlphaTab.Rendering.Utils; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/AlphaTabControl.cs b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/AlphaTabControl.cs index d8027e785..d5382f387 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/AlphaTabControl.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/AlphaTabControl.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System; using System.Collections.Generic; using System.Collections.Specialized; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/AlphaTabLayoutPanel.cs b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/AlphaTabLayoutPanel.cs index 7878fd8d8..7fcf25728 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/AlphaTabLayoutPanel.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/AlphaTabLayoutPanel.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System.ComponentModel; using System.Diagnostics; using System.Drawing; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/ControlContainer.cs b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/ControlContainer.cs index c1b35facc..d102f22f2 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/ControlContainer.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/ControlContainer.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System; using System.Drawing; using System.Windows.Forms; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/SkiaUtil.cs b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/SkiaUtil.cs index 18e3c01d2..bbbf2dfe1 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/SkiaUtil.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/SkiaUtil.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System.Drawing; using System.Drawing.Imaging; using SkiaSharp; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsMouseEventArgs.cs b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsMouseEventArgs.cs index 75bf967bd..a63b0182f 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsMouseEventArgs.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsMouseEventArgs.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System.Windows.Forms; using AlphaTab.UI; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsUiFacade.cs b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsUiFacade.cs index 7c37b7bb8..0b5a52539 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsUiFacade.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/WinForms/WinFormsUiFacade.cs @@ -1,7 +1,7 @@  using AlphaTab.Importer; using AlphaTab.Model; -#if NET472 +#if NET48 using System; using System.Collections.Concurrent; using System.Drawing; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/AlphaTab.cs b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/AlphaTab.cs index 87fa723c7..d84b946a9 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/AlphaTab.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/AlphaTab.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System; using System.Collections.Generic; using System.Collections.Specialized; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/AlphaTabLayoutPanel.cs b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/AlphaTabLayoutPanel.cs index ca36ce0c7..805930321 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/AlphaTabLayoutPanel.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/AlphaTabLayoutPanel.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System.Windows; using System.Windows.Controls; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/FrameworkElementContainer.cs b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/FrameworkElementContainer.cs index b53c32c3b..75900c85c 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/FrameworkElementContainer.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/FrameworkElementContainer.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System; using System.Windows; using System.Windows.Controls; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/GdiImageSource.cs b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/GdiImageSource.cs index e665b9c63..b8eb53a9f 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/GdiImageSource.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/GdiImageSource.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System.Drawing; using System.Drawing.Imaging; using System.Windows.Media; @@ -6,7 +6,7 @@ namespace AlphaTab.Platform.CSharp.Wpf { - internal class GdiImageSource + internal class GdiImageSource { public static BitmapSource Create(Bitmap image) { diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/NAudioSynthOutput.cs b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/NAudioSynthOutput.cs index fa075eec5..581e9e76a 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/NAudioSynthOutput.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/NAudioSynthOutput.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System; using AlphaTab.Audio.Synth; using AlphaTab.Audio.Synth.Ds; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/SkImageSource.cs b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/SkImageSource.cs index 5fb54ffcc..f026bb23d 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/SkImageSource.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/SkImageSource.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; @@ -6,7 +6,7 @@ namespace AlphaTab.Platform.CSharp.Wpf { - internal class SkImageSource + internal class SkImageSource { public static BitmapSource Create(object data) { diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfMouseEventArgs.cs b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfMouseEventArgs.cs index 51e7e3c5e..285beb3b5 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfMouseEventArgs.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfMouseEventArgs.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System.Windows.Input; using AlphaTab.UI; diff --git a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfUiFacade.cs b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfUiFacade.cs index 67abfc6c7..a13209b7b 100644 --- a/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfUiFacade.cs +++ b/Source/AlphaTab.CSharp/Platform/CSharp/Wpf/WpfUiFacade.cs @@ -1,4 +1,4 @@ -#if NET472 +#if NET48 using System; using System.Collections.Concurrent; using System.IO; diff --git a/Source/AlphaTab.JavaScript/AlphaTab.JavaScript.csproj b/Source/AlphaTab.JavaScript/AlphaTab.JavaScript.csproj index 5285910e6..b37bd7d1c 100644 --- a/Source/AlphaTab.JavaScript/AlphaTab.JavaScript.csproj +++ b/Source/AlphaTab.JavaScript/AlphaTab.JavaScript.csproj @@ -3,7 +3,7 @@ AlphaTab.JavaScript AlphaTab AlphaTab.JavaScript - net472 + net48 $(NoWarn);0626;0824 $(DefineConstants);JavaScript @@ -21,4 +21,4 @@ - \ No newline at end of file + diff --git a/Source/AlphaTab.JavaScript/Settings.cs b/Source/AlphaTab.JavaScript/Settings.cs index 94ebb3650..f40beeade 100644 --- a/Source/AlphaTab.JavaScript/Settings.cs +++ b/Source/AlphaTab.JavaScript/Settings.cs @@ -151,6 +151,7 @@ public dynamic ToJson() json.includeNoteBounds = IncludeNoteBounds; + json.playTripletFeel = PlayTripletFeel; json.vibrato = Platform.Platform.NewObject(); json.noteSlightAmplitude = Vibrato.NoteSlightAmplitude; json.noteWideAmplitude = Vibrato.NoteWideAmplitude; @@ -521,6 +522,15 @@ public static void FillFromJson(Settings settings, dynamic json, FastDictionary< settings.IncludeNoteBounds = (bool)dataAttributes["includeNoteBounds"]; } + if (Platform.Platform.JsonExists(json, "playTripletFeel")) + { + settings.PlayTripletFeel = json.playTripletFeel; + } + else if (dataAttributes != null && dataAttributes.ContainsKey("playTripletFeel")) + { + settings.PlayTripletFeel = (bool)dataAttributes["playTripletFeel"]; + } + if (Platform.Platform.JsonExists(json, "vibrato")) { var vibrato = json.vibrato; diff --git a/Source/AlphaTab.Test.CSharp/AlphaTab.Test.CSharp.csproj b/Source/AlphaTab.Test.CSharp/AlphaTab.Test.CSharp.csproj index 5344faa42..441628015 100644 --- a/Source/AlphaTab.Test.CSharp/AlphaTab.Test.CSharp.csproj +++ b/Source/AlphaTab.Test.CSharp/AlphaTab.Test.CSharp.csproj @@ -2,7 +2,7 @@ AlphaTab.Test.CSharp AlphaTab.Test.CSharp - net472 + net48 AlphaTab.Test.CSharp $(NoWarn);0626;0824 true @@ -36,4 +36,4 @@ - \ No newline at end of file + diff --git a/Source/AlphaTab.Test.Js/AlphaTab.Test.Js.csproj b/Source/AlphaTab.Test.Js/AlphaTab.Test.Js.csproj index 2b6d44bc0..39c75aeee 100644 --- a/Source/AlphaTab.Test.Js/AlphaTab.Test.Js.csproj +++ b/Source/AlphaTab.Test.Js/AlphaTab.Test.Js.csproj @@ -2,7 +2,7 @@ AlphaTab.Test.Js AlphaTab.Test.Js - net472 + net48 $(NoWarn);0626;0824 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} @@ -37,4 +37,4 @@ - \ No newline at end of file + diff --git a/Source/AlphaTab.Test.Js/test/alphaTab.tests.specs.js b/Source/AlphaTab.Test.Js/test/alphaTab.tests.specs.js index 6eadf257f..d9afaf41b 100644 --- a/Source/AlphaTab.Test.Js/test/alphaTab.tests.specs.js +++ b/Source/AlphaTab.Test.Js/test/alphaTab.tests.specs.js @@ -31,6 +31,11 @@ describe("alphaTab.test.audio.MidiFileGeneratorTest", function() { __instance.testBendMultiPoint(); done(); }); + it("testTripletFeel", function(done) { + alphaTab.test.TestPlatform.Done = done; + __instance.testTripletFeel(); + done(); + }); }); describe("alphaTab.test.audio.MidiPlaybackControllerTest", function() { var __instance = new alphaTab.test.audio.MidiPlaybackControllerTest(); diff --git a/Source/AlphaTab.Test/Audio/MidiFileGeneratorTest.cs b/Source/AlphaTab.Test/Audio/MidiFileGeneratorTest.cs index 2bd62bf88..bd3c96d50 100644 --- a/Source/AlphaTab.Test/Audio/MidiFileGeneratorTest.cs +++ b/Source/AlphaTab.Test/Audio/MidiFileGeneratorTest.cs @@ -60,7 +60,6 @@ public void TestBend() { var tex = ":4 15.6{b(0 4)} 15.6"; var score = ParseTex(tex); - Assert.AreEqual(1, score.Tracks.Count); Assert.AreEqual(1, score.Tracks[0].Staves[0].Bars.Count); Assert.AreEqual(1, score.Tracks[0].Staves[0].Bars[0].Voices.Count); @@ -369,5 +368,90 @@ public void TestBendMultiPoint() Assert.AreEqual(expectedEvents.Length, handler.MidiEvents.Count); } + + [TestMethod] + public void TestTripletFeel() + { + var tex = "\\ts 2 4 \\tf t8 3.2.8*4 | \\tf t16 3.2.16*8 | \\tf d8 3.2.8*4 | \\tf d16 3.2.16*8 | \\tf s8 3.2.8*4 | \\tf s16 3.2.16*8"; + var score = ParseTex(tex); + + var expectedPlaybackStartTimes = new FastList + { + // @formatter:off + 0, 480, 960, 1440, + 0, 240, 480, 720, 960, 1200, 1440, 1680, + 0, 480, 960, 1440, + 0, 240, 480, 720, 960, 1200, 1440, 1680, + 0, 480, 960, 1440, + 0, 240, 480, 720, 960, 1200, 1440, 1680 + // @formatter:on + }; + var expectedPlaybackDurations = new FastList + { + // @formatter:off + 480, 480, 480, 480, + 240, 240, 240, 240, 240, 240, 240, 240, + 480, 480, 480, 480, + 240, 240, 240, 240, 240, 240, 240, 240, + 480, 480, 480, 480, + 240, 240, 240, 240, 240, 240, 240, 240 + // @formatter:on + }; + var actualPlaybackStartTimes = new FastList(); + var actualPlaybackDurations = new FastList(); + + var beat = score.Tracks[0].Staves[0].Bars[0].Voices[0].Beats[0]; + while (beat != null) + { + actualPlaybackStartTimes.Add(beat.PlaybackStart); + actualPlaybackDurations.Add(beat.PlaybackDuration); + beat = beat.NextBeat; + } + + Assert.AreEqual(string.Join(",", expectedPlaybackStartTimes), string.Join(",", actualPlaybackStartTimes)); + Assert.AreEqual(string.Join(",", expectedPlaybackDurations), string.Join(",", actualPlaybackDurations)); + + var expectedMidiStartTimes = new FastList + { + // @formatter:off + 0, 640, 960, 1600, + 1920, 2240, 2400, 2720, 2880, 3200, 3360, 3680, + 3840, 4560, 4800, 5520, + 5760, 6120, 6240, 6600, 6720, 7080, 7200, 7560, + 7680, 7920, 8640, 8880, + 9600, 9720, 10080, 10200, 10560, 10680, 11040, 11160 + // @formatter:on + }; + var expectedMidiDurations = new FastList + { + // @formatter:off + 640, 320, 640, 320, + 320, 160, 320, 160, 320, 160, 320 ,160, + 720, 240, 720, 240, + 360, 120, 360, 120, 360, 120, 360, 120, + 240, 720, 240, 720, + 120, 360, 120, 360, 120, 360, 120, 360 + // @formatter:on + }; + var actualMidiStartTimes = new FastList(); + var actualMidiDurations = new FastList(); + + var handler = new FlatMidiEventGenerator(); + var generator = new MidiFileGenerator(score, null, handler); + generator.Generate(); + + foreach (var midiEvent in handler.MidiEvents) + { + if (midiEvent is FlatMidiEventGenerator.NoteEvent) + { + var noteEvent = (FlatMidiEventGenerator.NoteEvent)midiEvent; + actualMidiStartTimes.Add(noteEvent.Tick); + actualMidiDurations.Add(noteEvent.Length); + } + } + + Assert.AreEqual(string.Join(",", expectedMidiStartTimes), string.Join(",", actualMidiStartTimes)); + Assert.AreEqual(string.Join(",", expectedMidiDurations), string.Join(",", actualMidiDurations)); + } } } diff --git a/Source/AlphaTab/Audio/Generator/MidiFileGenerator.cs b/Source/AlphaTab/Audio/Generator/MidiFileGenerator.cs index 01e7d77e4..b35a74046 100644 --- a/Source/AlphaTab/Audio/Generator/MidiFileGenerator.cs +++ b/Source/AlphaTab/Audio/Generator/MidiFileGenerator.cs @@ -229,13 +229,36 @@ private void GenerateVoice(Voice voice, int barStartTick, Bar realBar) } } + private TripletFeelDurations _currentTripletFeel; + private void GenerateBeat(Beat beat, int barStartTick, Bar realBar) { // TODO: take care of tripletfeel var beatStart = beat.PlaybackStart; - var audioDuration = beat.Voice.Bar.IsEmpty - ? beat.Voice.Bar.MasterBar.CalculateDuration() - : beat.PlaybackDuration; + var audioDuration = beat.PlaybackDuration; + + if (beat.Voice.Bar.IsEmpty) + { + audioDuration = beat.Voice.Bar.MasterBar.CalculateDuration(); + } + else if (beat.Voice.Bar.MasterBar.TripletFeel != TripletFeel.NoTripletFeel && (_settings == null || _settings.PlayTripletFeel)) + { + if (_currentTripletFeel != null) + { + beatStart -= _currentTripletFeel.SecondBeatStartOffset; + audioDuration = _currentTripletFeel.SecondBeatDuration; + _currentTripletFeel = null; + } + else + { + _currentTripletFeel = CalculateTripletFeelInfo(beatStart, audioDuration, beat); + if (_currentTripletFeel != null) + { + audioDuration = _currentTripletFeel.FirstBeatDuration; + } + } + } + var beatLookup = new BeatTickLookup(); beatLookup.Start = barStartTick + beatStart; @@ -316,6 +339,92 @@ private void GenerateBeat(Beat beat, int barStartTick, Bar realBar) } } + private class TripletFeelDurations + { + public int FirstBeatDuration { get; set; } + public int SecondBeatStartOffset { get; set; } + public int SecondBeatDuration { get; set; } + } + + private TripletFeelDurations CalculateTripletFeelInfo(int beatStart, int audioDuration, Beat beat) + { + Duration initialDuration; + switch (beat.Voice.Bar.MasterBar.TripletFeel) + { + case TripletFeel.Triplet8th: + case TripletFeel.Dotted8th: + case TripletFeel.Scottish8th: + initialDuration = Duration.Eighth; + break; + case TripletFeel.Triplet16th: + case TripletFeel.Dotted16th: + case TripletFeel.Scottish16th: + initialDuration = Duration.Sixteenth; + break; + default: + // not possible + return null; + } + + var interval = initialDuration.ToTicks(); + + // it must be a plain note with the expected duration + // without dots, triplets, grace notes etc. + if (audioDuration != interval) + { + return null; + } + + // check if the beat is aligned in respect to the duration + // e.g. the eighth notes on a 4/4 time signature must start exactly on the following + // times to get a triplet feel applied + // 0 480 960 1440 1920 2400 2880 3360 + if ((beatStart % interval) != 0) + { + return null; + } + + // ensure next beat matches spec + if (beat.NextBeat == null || beat.NextBeat.Voice != beat.Voice || beat.PlaybackDuration != interval) + { + return null; + } + + // looks like we have a triplet feel combination start here! + var durations = new TripletFeelDurations(); + switch (beat.Voice.Bar.MasterBar.TripletFeel) + { + case TripletFeel.Triplet8th: + durations.FirstBeatDuration = MidiUtils.ApplyTuplet(Duration.Quarter.ToTicks(), 3, 2); + durations.SecondBeatDuration = MidiUtils.ApplyTuplet(Duration.Eighth.ToTicks(), 3, 2); + break; + case TripletFeel.Dotted8th: + durations.FirstBeatDuration = MidiUtils.ApplyDot(Duration.Eighth.ToTicks(), false); + durations.SecondBeatDuration = Duration.Sixteenth.ToTicks(); + break; + case TripletFeel.Scottish8th: + durations.FirstBeatDuration = Duration.Sixteenth.ToTicks(); + durations.SecondBeatDuration = MidiUtils.ApplyDot(Duration.Eighth.ToTicks(), false); + break; + case TripletFeel.Triplet16th: + durations.FirstBeatDuration = MidiUtils.ApplyTuplet(Duration.Eighth.ToTicks(), 3, 2); + durations.SecondBeatDuration = MidiUtils.ApplyTuplet(Duration.Sixteenth.ToTicks(), 3, 2); + break; + case TripletFeel.Dotted16th: + durations.FirstBeatDuration = MidiUtils.ApplyDot(Duration.Sixteenth.ToTicks(), false); + durations.SecondBeatDuration = Duration.ThirtySecond.ToTicks(); + break; + case TripletFeel.Scottish16th: + durations.FirstBeatDuration = Duration.ThirtySecond.ToTicks(); + durations.SecondBeatDuration = MidiUtils.ApplyDot(Duration.Sixteenth.ToTicks(), false); + break; + } + + // calculate the number of ticks the second beat can start earlier + durations.SecondBeatStartOffset = audioDuration - durations.FirstBeatDuration; + return durations; + } + private void GenerateNote(Note note, int beatStart, int beatDuration, int[] brushInfo) { var track = note.Beat.Voice.Bar.Staff.Track; @@ -916,7 +1025,7 @@ private void GenerateWhammy(Beat beat, int noteStart, MidiNoteDuration noteDurat break; case BendStyle.Fast: var whammyDuration = Math.Min(duration, - MidiUtils.MillisToTicks(_settings.SongBookBendDuration, _currentTempo)); + MidiUtils.MillisToTicks(_settings.SongBookBendDuration, _currentTempo)); GenerateSongBookWhammyOrBend(noteStart, channel, duration, @@ -944,7 +1053,7 @@ private void GenerateWhammy(Beat beat, int noteStart, MidiNoteDuration noteDurat break; case BendStyle.Fast: var whammyDuration = Math.Min(duration, - MidiUtils.MillisToTicks(_settings.SongBookDipDuration, _currentTempo)); + MidiUtils.MillisToTicks(_settings.SongBookDipDuration, _currentTempo)); GenerateSongBookWhammyOrBend(noteStart, channel, duration, @@ -981,7 +1090,7 @@ private void GenerateWhammy(Beat beat, int noteStart, MidiNoteDuration noteDurat _handler.AddBend(track.Index, noteStart, (byte)channel, (int)preDiveValue); var whammyDuration = Math.Min(duration, - MidiUtils.MillisToTicks(_settings.SongBookBendDuration, _currentTempo)); + MidiUtils.MillisToTicks(_settings.SongBookBendDuration, _currentTempo)); GenerateSongBookWhammyOrBend(noteStart, channel, duration, diff --git a/Source/AlphaTab/Settings.cs b/Source/AlphaTab/Settings.cs index 9c1e60cf8..24784662a 100644 --- a/Source/AlphaTab/Settings.cs +++ b/Source/AlphaTab/Settings.cs @@ -126,6 +126,11 @@ public partial class Settings /// public VibratoPlaybackSettings Vibrato { get; set; } + /// + /// Gets or sets whether the triplet feel should be applied/played during audio playback. + /// + public bool PlayTripletFeel { get; set; } + /// /// Gets or sets the height for slurs. The factor is multiplied with the a logarithmic distance /// between slur start and end. @@ -275,6 +280,8 @@ public static Settings Defaults settings.Vibrato.BeatSlightLength = 240; settings.Vibrato.BeatWideLength = 240; + settings.PlayTripletFeel = true; + settings.SongBookBendDuration = 75; settings.SongBookDipDuration = 150; settings.IncludeNoteBounds = false;