diff --git a/.editorconfig b/.editorconfig index a219353e4..ece23f437 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,124 +1,124 @@ # To learn more about .editorconfig see https://aka.ms/editorconfigdocs -############################### -# Core EditorConfig Options # -############################### -# All files -[*] -indent_style = space -# Code files -[*.{cs,csx,vb,vbx}] -indent_size = 4 -insert_final_newline = true -charset = utf-8-bom -guidelines = 100 -############################### -# .NET Coding Conventions # -############################### -[*.{cs,vb}] -# Organize usings -dotnet_sort_system_directives_first = true -# this. preferences -dotnet_style_qualification_for_field = false:silent -dotnet_style_qualification_for_property = false:silent -dotnet_style_qualification_for_method = false:silent -dotnet_style_qualification_for_event = false:silent -# Language keywords vs BCL types preferences -dotnet_style_predefined_type_for_locals_parameters_members = true:silent -dotnet_style_predefined_type_for_member_access = true:silent -# Parentheses preferences -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent -# Modifier preferences -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent -dotnet_style_readonly_field = true:suggestion -# Expression-level preferences -dotnet_style_object_initializer = true:suggestion -dotnet_style_collection_initializer = true:suggestion -dotnet_style_explicit_tuple_names = true:suggestion -dotnet_style_null_propagation = true:suggestion -dotnet_style_coalesce_expression = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent -dotnet_prefer_inferred_tuple_names = true:suggestion -dotnet_prefer_inferred_anonymous_type_member_names = true:suggestion -dotnet_style_prefer_auto_properties = true:silent -dotnet_style_prefer_conditional_expression_over_assignment = true:silent -dotnet_style_prefer_conditional_expression_over_return = true:silent -############################### -# Naming Conventions # -############################### -# Style Definitions -dotnet_naming_style.pascal_case_style.capitalization = pascal_case -# Use PascalCase for constant fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style -dotnet_naming_symbols.constant_fields.applicable_kinds = field -dotnet_naming_symbols.constant_fields.applicable_accessibilities = * -dotnet_naming_symbols.constant_fields.required_modifiers = const -############################### -# C# Coding Conventions # -############################### -[*.cs] -# var preferences -csharp_style_var_for_built_in_types = true:silent -csharp_style_var_when_type_is_apparent = true:silent -csharp_style_var_elsewhere = true:silent -# Expression-bodied members -csharp_style_expression_bodied_methods = false:silent -csharp_style_expression_bodied_constructors = false:silent -csharp_style_expression_bodied_operators = false:silent -csharp_style_expression_bodied_properties = true:silent -csharp_style_expression_bodied_indexers = true:silent -csharp_style_expression_bodied_accessors = true:silent -# Pattern matching preferences -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion -# Null-checking preferences -csharp_style_throw_expression = true:suggestion -csharp_style_conditional_delegate_call = true:suggestion -# Modifier preferences -csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion -# Expression-level preferences -csharp_prefer_braces = true:silent -csharp_style_deconstructed_variable_declaration = true:suggestion -csharp_prefer_simple_default_expression = true:suggestion -csharp_style_pattern_local_over_anonymous_function = true:suggestion -csharp_style_inlined_variable_declaration = true:suggestion -############################### -# C# Formatting Rules # -############################### -# New line preferences -csharp_new_line_before_open_brace = none -csharp_new_line_before_else = false -csharp_new_line_before_catch = false -csharp_new_line_before_finally = false -csharp_new_line_before_members_in_object_initializers = false -csharp_new_line_before_members_in_anonymous_types = false -csharp_new_line_between_query_expression_clauses = false -# Indentation preferences -csharp_indent_case_contents = true -csharp_indent_switch_labels = true -csharp_indent_labels = flush_left -# Space preferences -csharp_space_after_cast = false -csharp_space_after_keywords_in_control_flow_statements = true -csharp_space_between_method_call_parameter_list_parentheses = false -csharp_space_between_method_declaration_parameter_list_parentheses = false -csharp_space_between_parentheses = false -csharp_space_before_colon_in_inheritance_clause = true -csharp_space_after_colon_in_inheritance_clause = true -csharp_space_around_binary_operators = before_and_after -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -csharp_space_between_method_call_name_and_opening_parenthesis = false -csharp_space_between_method_call_empty_parameter_list_parentheses = false -# Wrapping preferences -csharp_preserve_single_line_statements = true -csharp_preserve_single_line_blocks = true -############################### -# VB Coding Conventions # -############################### -[*.vb] -# Modifier preferences -visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion +############################### +# Core EditorConfig Options # +############################### +# All files +[*] +indent_style = space +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 +insert_final_newline = true +charset = utf-8-bom +guidelines = 100 +############################### +# .NET Coding Conventions # +############################### +[*.{cs,vb}] +# Organize usings +dotnet_sort_system_directives_first = true +# this. preferences +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_readonly_field = true:suggestion +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent +dotnet_prefer_inferred_tuple_names = true:suggestion +dotnet_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +############################### +# Naming Conventions # +############################### +# Style Definitions +dotnet_naming_style.pascal_case_style.capitalization = pascal_case +# Use PascalCase for constant fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.applicable_accessibilities = * +dotnet_naming_symbols.constant_fields.required_modifiers = const +############################### +# C# Coding Conventions # +############################### +[*.cs] +# var preferences +csharp_style_var_for_built_in_types = true:silent +csharp_style_var_when_type_is_apparent = true:silent +csharp_style_var_elsewhere = true:silent +# Expression-bodied members +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +# Pattern matching preferences +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +# Null-checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion +# Expression-level preferences +csharp_prefer_braces = true:silent +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +############################### +# C# Formatting Rules # +############################### +# New line preferences +csharp_new_line_before_open_brace = none +csharp_new_line_before_else = false +csharp_new_line_before_catch = false +csharp_new_line_before_finally = false +csharp_new_line_before_members_in_object_initializers = false +csharp_new_line_before_members_in_anonymous_types = false +csharp_new_line_between_query_expression_clauses = false +# Indentation preferences +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left +# Space preferences +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +# Wrapping preferences +csharp_preserve_single_line_statements = true +csharp_preserve_single_line_blocks = true +############################### +# VB Coding Conventions # +############################### +[*.vb] +# Modifier preferences +visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion diff --git a/.github/workflows/pr-test.yml b/.github/workflows/pr-test.yml index 881809f78..392091415 100644 --- a/.github/workflows/pr-test.yml +++ b/.github/workflows/pr-test.yml @@ -37,3 +37,6 @@ jobs: - name: test run: dotnet test OpenUtau.Test + + - name: check format + run: dotnet format --verify-no-changes diff --git a/OpenUtau.Core/Analysis/Some.cs b/OpenUtau.Core/Analysis/Some.cs index 95e8a71df..a171e7249 100644 --- a/OpenUtau.Core/Analysis/Some.cs +++ b/OpenUtau.Core/Analysis/Some.cs @@ -8,7 +8,7 @@ using OpenUtau.Core.Ustx; namespace OpenUtau.Core.Analysis.Some { - public static class AudioSlicer{ + public static class AudioSlicer { static int sample_rate = 44100; static float threshold = 0.02f; static int hop_size = 441; @@ -17,93 +17,93 @@ public static class AudioSlicer{ static int min_interval = 30; static int max_sil_kept = 50; - public struct Chunk{ + public struct Chunk { public double offsetMs;//position of this slice in the audio file in milliseconds public float[] samples; - public Chunk(double offsetMs, float[] samples){ + public Chunk(double offsetMs, float[] samples) { this.offsetMs = offsetMs; this.samples = samples; } - public Chunk(float[] originalSamples, int startIndex, int endIndex){ + public Chunk(float[] originalSamples, int startIndex, int endIndex) { samples = originalSamples[startIndex..endIndex]; offsetMs = (double)startIndex * (1000.0 / sample_rate); } } static double[] get_rms( - float[] samples, - int frame_length = 2048, + float[] samples, + int frame_length = 2048, int hop_length = 512 - ){ + ) { //reference: https://github.com/openvpi/audio-slicer/blob/main/slicer2.py#L5 //y = np.pad(samples, padding, mode="constant") float[] y = new float[samples.Length + frame_length]; Array.Copy(samples, 0, y, frame_length / 2, samples.Length); - for(int i=0; i Math.Sqrt(y[(i*hop_length)..(i*hop_length+frame_length)].Average())) + .Select(i => Math.Sqrt(y[(i * hop_length)..(i * hop_length + frame_length)].Average())) .ToArray(); } - static int argmin(this double[] array){ + static int argmin(this double[] array) { //numpy's argmin function return Array.IndexOf(array, array.Min()); } - public static List Slice(float[] samples){ + public static List Slice(float[] samples) { //reference: https://github.com/openvpi/audio-slicer/blob/main/slicer2.py#L68 - if((samples.Length + hop_size - 1) / hop_size <= min_length){ - return new List{new Chunk(0, samples)}; + if ((samples.Length + hop_size - 1) / hop_size <= min_length) { + return new List { new Chunk(0, samples) }; } var rms_list = get_rms( samples, frame_length: win_size, hop_length: hop_size ); - var sil_tags = new List>(); + var sil_tags = new List>(); int silence_start = -1;//here -1 means none int clip_start = 0; - foreach(int i in Enumerable.Range(0, rms_list.Length)){ + foreach (int i in Enumerable.Range(0, rms_list.Length)) { var rms = rms_list[i]; //Keep looping while frame is silent. - if(rms < threshold){ + if (rms < threshold) { //Record start of silent frames. - if(silence_start < 0){ + if (silence_start < 0) { silence_start = i; } continue; } //Keep looping while frame is not silent and silence start has not been recorded. - if(silence_start < 0){ + if (silence_start < 0) { continue; } //Clear recorded silence start if interval is not enough or clip is too short var is_leading_silence = silence_start == 0 && i > max_sil_kept; var need_slice_middle = i - silence_start >= min_interval && i - clip_start >= min_length; - if(!is_leading_silence && !need_slice_middle){ + if (!is_leading_silence && !need_slice_middle) { silence_start = -1; continue; } //Need slicing. Record the range of silent frames to be removed. - if(i - silence_start <= max_sil_kept){ - var pos = rms_list[silence_start..(i+1)].argmin() + silence_start; - if(silence_start == 0){ - sil_tags.Add(Tuple.Create(0,pos)); + if (i - silence_start <= max_sil_kept) { + var pos = rms_list[silence_start..(i + 1)].argmin() + silence_start; + if (silence_start == 0) { + sil_tags.Add(Tuple.Create(0, pos)); } else { sil_tags.Add(Tuple.Create(pos, pos)); } clip_start = pos; - } else if(i - silence_start <= max_sil_kept * 2){ + } else if (i - silence_start <= max_sil_kept * 2) { var pos = rms_list[(i - max_sil_kept)..(silence_start + max_sil_kept + 1)].argmin(); pos += i - max_sil_kept; var pos_l = rms_list[silence_start..(silence_start + max_sil_kept + 1)].argmin() + silence_start; - var pos_r = rms_list[(i - max_sil_kept)..(i+1)].argmin() + i - max_sil_kept; - if(silence_start == 0){ + var pos_r = rms_list[(i - max_sil_kept)..(i + 1)].argmin() + i - max_sil_kept; + if (silence_start == 0) { sil_tags.Add(Tuple.Create(0, pos_r)); clip_start = pos_r; } else { @@ -112,8 +112,8 @@ public static List Slice(float[] samples){ } } else { var pos_l = rms_list[silence_start..(silence_start + max_sil_kept + 1)].argmin() + silence_start; - var pos_r = rms_list[(i - max_sil_kept)..(i+1)].argmin() + i - max_sil_kept; - if(silence_start == 0){ + var pos_r = rms_list[(i - max_sil_kept)..(i + 1)].argmin() + i - max_sil_kept; + if (silence_start == 0) { sil_tags.Add(Tuple.Create(0, pos_r)); } else { sil_tags.Add(Tuple.Create(pos_l, pos_r)); @@ -124,31 +124,31 @@ public static List Slice(float[] samples){ } //Deal with trailing silence. var total_frames = rms_list.Length; - if(silence_start >= 0 && total_frames - silence_start >= min_interval){ + if (silence_start >= 0 && total_frames - silence_start >= min_interval) { var silence_end = Math.Min(total_frames, silence_start + max_sil_kept); var pos = rms_list[silence_start..(silence_end + 1)].argmin() + silence_start; sil_tags.Add(Tuple.Create(pos, total_frames + 1)); } //Apply and return slices. - if(sil_tags.Count == 0){ - return new List{new Chunk(0, samples)}; + if (sil_tags.Count == 0) { + return new List { new Chunk(0, samples) }; } else { var chunks = new List(); - if(sil_tags[0].Item1 > 0){ + if (sil_tags[0].Item1 > 0) { chunks.Add(new Chunk( - samples, - 0, + samples, + 0, sil_tags[0].Item1 * hop_size )); } - foreach(var i in Enumerable.Range(0, sil_tags.Count - 1)){ + foreach (var i in Enumerable.Range(0, sil_tags.Count - 1)) { chunks.Add(new Chunk( - samples, - sil_tags[i].Item2 * hop_size, - sil_tags[i+1].Item1 * hop_size + samples, + sil_tags[i].Item2 * hop_size, + sil_tags[i + 1].Item1 * hop_size )); } - if(sil_tags[^1].Item2 < total_frames){ + if (sil_tags[^1].Item2 < total_frames) { chunks.Add(new Chunk( samples, sil_tags[^1].Item2 * hop_size, @@ -160,24 +160,24 @@ public static List Slice(float[] samples){ } } - class SomeConfig{ + class SomeConfig { public string model = "model.onnx"; public int sample_rate = 44100; } - public class Some: IDisposable { + public class Some : IDisposable { InferenceSession session; string Location; private bool disposedValue; - struct SomeResult{ + struct SomeResult { //midi number of each note public float[] note_midi; //whether each note is a rest public bool[] note_rest; //duration of each note in seconds public float[] note_dur; - } + } public Some() { Location = Path.Combine(PathManager.Inst.DependencyPath, "some"); @@ -216,28 +216,28 @@ SomeResult Analyze(float[] samples) { .First() .AsTensor() .ToArray(); - return new SomeResult{ + return new SomeResult { note_midi = note_midi, note_rest = note_rest, note_dur = note_dur }; } - private float[] ToMono(float[] stereoSamples, int channels){ - if(channels == 1){ + private float[] ToMono(float[] stereoSamples, int channels) { + if (channels == 1) { return stereoSamples; } float[] monoSamples = new float[stereoSamples.Length / channels]; - for(int i = 0; i < monoSamples.Length; i++){ - monoSamples[i] = stereoSamples[(i*channels)..((i+1)*channels-1)].Average(); + for (int i = 0; i < monoSamples.Length; i++) { + monoSamples[i] = stereoSamples[(i * channels)..((i + 1) * channels - 1)].Average(); } return monoSamples; } - public UVoicePart Transcribe(UProject project, UWavePart wavePart, Action progress){ + public UVoicePart Transcribe(UProject project, UWavePart wavePart, Action progress) { //Run SOME model with the audio part user selected to extract note information //convert samples to mono and slice - + var monoSamples = ToMono(wavePart.Samples, wavePart.channels); var chunks = AudioSlicer.Slice(monoSamples); var part = new UVoicePart(); @@ -248,7 +248,7 @@ public UVoicePart Transcribe(UProject project, UWavePart wavePart, Action p double currMs = partOffsetMs; int wavPosS = 0;//position of current slice in seconds - foreach(var chunk in chunks){ + foreach (var chunk in chunks) { wavPosS = (int)(chunk.offsetMs / 1000); progress.Invoke(wavPosS); var someResult = Analyze(chunk.samples); @@ -258,9 +258,9 @@ public UVoicePart Transcribe(UProject project, UWavePart wavePart, Action p //Put the notes into a new voice part double chunkOffsetMs = chunk.offsetMs + partOffsetMs; currMs = chunkOffsetMs; - foreach(int index in Enumerable.Range(0, note_midi.Length)){ + foreach (int index in Enumerable.Range(0, note_midi.Length)) { var noteDurMs = note_dur[index] * 1000; - if(!note_rest[index]){ + if (!note_rest[index]) { var posTick = timeAxis.MsPosToTickPos(currMs); var durTick = timeAxis.MsPosToTickPos(currMs + noteDurMs) - posTick; var note = project.CreateNote( @@ -274,7 +274,7 @@ public UVoicePart Transcribe(UProject project, UWavePart wavePart, Action p } } var endTick = timeAxis.MsPosToTickPos(currMs); - if(endTick > part.End){ + if (endTick > part.End) { part.Duration = endTick - part.position; } return part; diff --git a/OpenUtau.Core/Api/G2pDictionary.cs b/OpenUtau.Core/Api/G2pDictionary.cs index fd9f89592..fdfecd9f0 100644 --- a/OpenUtau.Core/Api/G2pDictionary.cs +++ b/OpenUtau.Core/Api/G2pDictionary.cs @@ -75,7 +75,7 @@ internal Builder() { /// public Builder AddSymbol(string symbol, string type) { phonemeSymbols[symbol] = type == "vowel"; - if(type == "semivowel" || type == "liquid") { + if (type == "semivowel" || type == "liquid") { glideSymbols.Add(symbol); } else { glideSymbols.Remove(symbol); @@ -128,7 +128,7 @@ public Builder Load(TextReader textReader) { return Load(data); } - public Builder Load(G2pDictionaryData data){ + public Builder Load(G2pDictionaryData data) { if (data.symbols != null) { foreach (var symbolData in data.symbols) { AddSymbol(symbolData.symbol, symbolData.type); diff --git a/OpenUtau.Core/Api/PhonemizerInstaller.cs b/OpenUtau.Core/Api/PhonemizerInstaller.cs index 88ec02b27..8195a6edc 100644 --- a/OpenUtau.Core/Api/PhonemizerInstaller.cs +++ b/OpenUtau.Core/Api/PhonemizerInstaller.cs @@ -1,10 +1,8 @@ -using System.IO; +using System.IO; using System.Threading.Tasks; -namespace OpenUtau.Core.Api -{ - public class PhonemizerInstaller - { +namespace OpenUtau.Core.Api { + public class PhonemizerInstaller { public static void Install(string filePath) { string fileName = Path.GetFileName(filePath); string destName = Path.Combine(PathManager.Inst.PluginsPath, fileName); @@ -15,4 +13,4 @@ public static void Install(string filePath) { }).Start(DocManager.Inst.MainScheduler); } } -} \ No newline at end of file +} diff --git a/OpenUtau.Core/Classic/ClassicRenderer.cs b/OpenUtau.Core/Classic/ClassicRenderer.cs index cd601558e..bfff754f8 100644 --- a/OpenUtau.Core/Classic/ClassicRenderer.cs +++ b/OpenUtau.Core/Classic/ClassicRenderer.cs @@ -68,7 +68,7 @@ public Task RenderInternal(RenderPhrase phrase, Progress progress, if (!(item.resampler is WorldlineResampler)) { VoicebankFiles.Inst.CopySourceTemp(item.inputFile, item.inputTemp); } - if(!item.phone.direct){ + if (!item.phone.direct) { lock (Renderers.GetCacheLock(item.outputFile)) { item.resampler.DoResamplerReturnsFile(item, Log.Logger); } @@ -138,7 +138,7 @@ public RenderPitchResult LoadRenderedPitch(RenderPhrase phrase) { } public UExpressionDescriptor[] GetSuggestedExpressions(USinger singer, URenderSettings renderSettings) { - var manifest= renderSettings.Resampler.Manifest; + var manifest = renderSettings.Resampler.Manifest; if (manifest == null) { return new UExpressionDescriptor[] { }; } diff --git a/OpenUtau.Core/Classic/ExeResampler.cs b/OpenUtau.Core/Classic/ExeResampler.cs index e17557513..2f0ed861e 100644 --- a/OpenUtau.Core/Classic/ExeResampler.cs +++ b/OpenUtau.Core/Classic/ExeResampler.cs @@ -8,8 +8,8 @@ using NAudio.Wave; using OpenUtau.Core; using OpenUtau.Core.Format; -using OpenUtau.Core.Util; using OpenUtau.Core.Ustx; +using OpenUtau.Core.Util; using Serilog; namespace OpenUtau.Classic { @@ -45,7 +45,7 @@ void FixMoreConfig(string moreConfigPath) { } for (int i = 0; i < lines.Count; i++) { if (lines[i].StartsWith("resampler-compatibility")) { - if(lines[i] == "resampler-compatibility on"){ + if (lines[i] == "resampler-compatibility on") { //moreconfig.txt is correct return; } else { @@ -72,13 +72,13 @@ public ExeResampler(string filePath, string basePath) { //Load Resampler Manifest Manifest = LoadManifest(); //Make moresampler happy - try{ - if(Path.GetFileNameWithoutExtension(filePath) == "moresampler"){ + try { + if (Path.GetFileNameWithoutExtension(filePath) == "moresampler") { //Load moreconfig.txt under the same folder with filePath var moreConfigPath = Path.Combine(Path.GetDirectoryName(filePath), "moreconfig.txt"); FixMoreConfig(moreConfigPath); } - } catch (Exception ex){ + } catch (Exception ex) { Log.Error($"Failed fixing moreconfig.txt for {filePath}: {ex}"); } } @@ -122,7 +122,7 @@ public void CheckPermissions() { } public bool SupportsFlag(string abbr) { - if(Manifest == null || !Manifest.expressionFilter){ + if (Manifest == null || !Manifest.expressionFilter) { return true; } return Manifest.expressions.ContainsKey(abbr); diff --git a/OpenUtau.Core/Classic/ExeWavtool.cs b/OpenUtau.Core/Classic/ExeWavtool.cs index 90b12a85f..7cec2c332 100644 --- a/OpenUtau.Core/Classic/ExeWavtool.cs +++ b/OpenUtau.Core/Classic/ExeWavtool.cs @@ -1,15 +1,15 @@ +using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Text; +using System.Text.RegularExpressions; using System.Threading; using NAudio.Wave; using OpenUtau.Core; using OpenUtau.Core.Render; using OpenUtau.Core.Util; using Serilog; -using System.Text.RegularExpressions; -using System; namespace OpenUtau.Classic { class ExeWavtool : IWavtool { @@ -37,8 +37,8 @@ public float[] Concatenate(List resamplerItems, string tempPath, } //The builtin worldline resampler can't be called from bat script, //so we need to call it directly from C# - foreach(var item in resamplerItems){ - if(!(item.resampler is ExeResampler) && !cancellation.IsCancellationRequested && !File.Exists(item.outputFile)){ + foreach (var item in resamplerItems) { + if (!(item.resampler is ExeResampler) && !cancellation.IsCancellationRequested && !File.Exists(item.outputFile)) { lock (Renderers.GetCacheLock(item.outputFile)) { item.resampler.DoResamplerReturnsFile(item, Log.Logger); } @@ -132,7 +132,7 @@ void WriteItem(StreamWriter writer, ResamplerItem item, int index, int total) { string dur = $"{item.phone.duration:G999}@{item.phone.adjustedTempo:G999}{(item.durCorrection >= 0 ? "+" : "")}{item.durCorrection}"; string relInputTemp = Path.GetRelativePath(PathManager.Inst.CachePath, item.inputTemp); writer.WriteLine($"@echo {MakeProgressBar(index + 1, total)}"); - if(item.phone.direct){ + if (item.phone.direct) { writer.WriteLine($"@\"%tool%\" \"%output%\" \"%oto%\\{ConvertIfNeeded(relInputTemp)}\" {item.offset} {item.phone.durationMs:F1} %env%"); } else { writer.WriteLine($"@call %helper% \"%oto%\\{ConvertIfNeeded(relInputTemp)}\" {toneName} {dur} {item.preutter} {item.offset} {item.durRequired} {item.consonant} {item.cutoff} {index}"); @@ -162,8 +162,7 @@ private static string EscapeFlags(string flag) { // Remove "https://" case-insensitively if (flag.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { flag = flag.Substring(8); - } - else if (flag.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) { + } else if (flag.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) { flag = flag.Substring(7); } return flag; @@ -198,15 +197,15 @@ void WriteTearDown(StreamWriter writer) { string ConvertIfNeeded(string path) { if (!OS.IsWindows()) return ConvertToWindowsPath(path); else return path; - } + } - string ConvertToWindowsPath (string linuxPath) { + string ConvertToWindowsPath(string linuxPath) { List path = new List(linuxPath.ToCharArray()); bool absolutePath = false; if (path[0] == '/') absolutePath = true; for (int i = path.Count - 1; i > 0; i--) { - if (path[i] == ' ' && path[i-1] == '\\') { - path.RemoveAt(i-1); + if (path[i] == ' ' && path[i - 1] == '\\') { + path.RemoveAt(i - 1); i--; } } diff --git a/OpenUtau.Core/Classic/Frq.cs b/OpenUtau.Core/Classic/Frq.cs index fec75a3b8..9c01f0fc8 100644 --- a/OpenUtau.Core/Classic/Frq.cs +++ b/OpenUtau.Core/Classic/Frq.cs @@ -22,7 +22,7 @@ public OtoFrq(UOto oto, Dictionary dict) { } } - if(frq != null) { + if (frq != null) { hopSize = frq.hopSize; int offset = ConvertMsToFrqLength(frq, oto.Offset); int consonant = ConvertMsToFrqLength(frq, oto.Offset + oto.Consonant); diff --git a/OpenUtau.Core/Classic/IResampler.cs b/OpenUtau.Core/Classic/IResampler.cs index 11fb34f91..3faf0e0cf 100644 --- a/OpenUtau.Core/Classic/IResampler.cs +++ b/OpenUtau.Core/Classic/IResampler.cs @@ -7,7 +7,7 @@ public interface IResampler { float[] DoResampler(ResamplerItem args, ILogger logger); string DoResamplerReturnsFile(ResamplerItem args, ILogger logger); void CheckPermissions(); - ResamplerManifest Manifest { get; } + ResamplerManifest Manifest { get; } bool SupportsFlag(string abbr); } } diff --git a/OpenUtau.Core/Classic/Plugin.cs b/OpenUtau.Core/Classic/Plugin.cs index 3846616c8..939246bac 100644 --- a/OpenUtau.Core/Classic/Plugin.cs +++ b/OpenUtau.Core/Classic/Plugin.cs @@ -19,11 +19,11 @@ public void Run(string tempFile) { } string winePath = Preferences.Default.WinePath; string ext = Path.GetExtension(tempFile).ToLower(); - bool useWine = !OS.IsWindows() && !string.IsNullOrEmpty(winePath) && ( ext == "exe" || ext == "bat"); + bool useWine = !OS.IsWindows() && !string.IsNullOrEmpty(winePath) && (ext == "exe" || ext == "bat"); var startInfo = new ProcessStartInfo() { FileName = useWine ? winePath : Executable, Arguments = useWine ? $"\"{Executable}\" \"{tempFile}\"" : $"\"{tempFile}\"", - Environment = {{"LANG", "ja_JP.utf8"}}, + Environment = { { "LANG", "ja_JP.utf8" } }, WorkingDirectory = Path.GetDirectoryName(Executable), UseShellExecute = UseShell, }; diff --git a/OpenUtau.Core/Classic/PluginLoader.cs b/OpenUtau.Core/Classic/PluginLoader.cs index 0922a8217..1ecdc97e0 100644 --- a/OpenUtau.Core/Classic/PluginLoader.cs +++ b/OpenUtau.Core/Classic/PluginLoader.cs @@ -49,7 +49,7 @@ private static Plugin ParsePluginTxt(string filePath, Encoding encoding) { plugin.AllNotes = true; } else if (s[0] == "shell" && s[1] == "use") { plugin.UseShell = true; - } else if (s[0] == "encoding"){ + } else if (s[0] == "encoding") { plugin.Encoding = s[1]; } else { otherLines.Add(line); diff --git a/OpenUtau.Core/Classic/Presamp.cs b/OpenUtau.Core/Classic/Presamp.cs index 825d68703..b95f4f317 100644 --- a/OpenUtau.Core/Classic/Presamp.cs +++ b/OpenUtau.Core/Classic/Presamp.cs @@ -231,7 +231,7 @@ public void ReadPresampIni(string dirPath, Encoding textFileEncoding) { } } } - + } catch (Exception e) { Log.Error(e, "failed to load presamp.ini"); } @@ -322,7 +322,7 @@ public string[] ParseAlias(string lyric) { preVowel = split[0]; phoneme = split[1]; } - if(phoneme == "") { + if (phoneme == "") { return new string[] { preVowel, phoneme, suffix }; } @@ -334,21 +334,21 @@ public string[] ParseAlias(string lyric) { var split = phoneme.Split(n); suffix = new Regex(split[0]).Replace(phoneme, "", 1) + suffix; phoneme = split[0]; - }; + } }); Appends.ForEach(a => { if (phoneme.Contains(a)) { var split = phoneme.Split(a); suffix = new Regex(split[0]).Replace(phoneme, "", 1) + suffix; phoneme = split[0]; - }; + } }); Pitches.ForEach(p => { if (phoneme.Contains(p)) { var split = phoneme.Split(p); suffix = new Regex(split[0]).Replace(phoneme, "", 1) + suffix; phoneme = split[0]; - }; + } }); if (phoneme.Contains("_")) { var split = phoneme.Split("_"); diff --git a/OpenUtau.Core/Classic/SharpWavtool.cs b/OpenUtau.Core/Classic/SharpWavtool.cs index ee4149ee9..df3293cd1 100644 --- a/OpenUtau.Core/Classic/SharpWavtool.cs +++ b/OpenUtau.Core/Classic/SharpWavtool.cs @@ -46,7 +46,7 @@ public float[] Concatenate(List resamplerItems, string tempPath, var segments = new List(); foreach (var item in resamplerItems) { var segment = new Segment(); - if(item.phone.direct){ + if (item.phone.direct) { using (var waveStream = Wave.OpenFile(item.inputFile)) { float[] samples = Wave.GetSamples(waveStream.ToSampleProvider().ToMono(1, 0)); int offset = (int)(item.phone.oto.Offset / 1000 * 44100); @@ -54,7 +54,7 @@ public float[] Concatenate(List resamplerItems, string tempPath, int length = cutoff >= 0 ? (samples.Length - offset - cutoff) : -cutoff; segment.samples = samples.Skip(offset).Take(length).ToArray(); } - } else { + } else { if (!File.Exists(item.outputFile)) { continue; } diff --git a/OpenUtau.Core/Classic/ToolsManager.cs b/OpenUtau.Core/Classic/ToolsManager.cs index 5ffa07b19..aca1e03b2 100644 --- a/OpenUtau.Core/Classic/ToolsManager.cs +++ b/OpenUtau.Core/Classic/ToolsManager.cs @@ -40,7 +40,7 @@ IResampler LoadResampler(string filePath, string basePath) { string ext = Path.GetExtension(filePath).ToLower(); if ((OS.IsWindows() || !string.IsNullOrEmpty(Preferences.Default.WinePath)) && (ext == ".exe" || ext == ".bat")) { return new ExeResampler(filePath, basePath); - } + } if (!OS.IsWindows() && (ext == ".sh" || string.IsNullOrEmpty(ext))) { return new ExeResampler(filePath, basePath); } @@ -54,7 +54,7 @@ IWavtool LoadWavtool(string filePath, string basePath) { string ext = Path.GetExtension(filePath).ToLower(); if ((OS.IsWindows() || !string.IsNullOrEmpty(Preferences.Default.WinePath)) && (ext == ".exe" || ext == ".bat")) { return new ExeWavtool(filePath, basePath); - } + } if (!OS.IsWindows() && (ext == ".sh" || string.IsNullOrEmpty(ext))) { return new ExeWavtool(filePath, basePath); } diff --git a/OpenUtau.Core/Classic/Ust.cs b/OpenUtau.Core/Classic/Ust.cs index 529e7849a..60541cced 100644 --- a/OpenUtau.Core/Classic/Ust.cs +++ b/OpenUtau.Core/Classic/Ust.cs @@ -463,7 +463,7 @@ public static (List, List) ParsePlugin( .ToList(); return (toRemove, toAdd); } - + public static void WriteForSetParam(UProject project, string filePath, List otos) { using (var writer = new StreamWriter(filePath, false, Encoding.GetEncoding("shift_jis"))) { writer.WriteLine("[#SETTING]"); diff --git a/OpenUtau.Core/Classic/UstNote.cs b/OpenUtau.Core/Classic/UstNote.cs index 47551c381..7db2bdce6 100644 --- a/OpenUtau.Core/Classic/UstNote.cs +++ b/OpenUtau.Core/Classic/UstNote.cs @@ -278,7 +278,7 @@ void ParseEnvelope(string ust, IniLine ustLine) { } void ParsePitchBend(string pbs, string pbw, string pby, string pbm) { - var pitch = this.pitch != null ? this.pitch.Clone() : new UPitch() ; + var pitch = this.pitch != null ? this.pitch.Clone() : new UPitch(); var points = pitch.data; // PBS @@ -286,7 +286,7 @@ void ParsePitchBend(string pbs, string pbw, string pby, string pbm) { var parts = pbs.Contains(';') ? pbs.Split(';') : pbs.Split(','); float pbsX = parts.Length >= 1 && ParseFloat(parts[0], out pbsX) ? pbsX : 0; float pbsY = parts.Length >= 2 && ParseFloat(parts[1], out pbsY) ? pbsY : 0; - if(points.Count > 0) { + if (points.Count > 0) { points[0] = new PitchPoint(pbsX, pbsY); } else { points.Add(new PitchPoint(pbsX, pbsY)); diff --git a/OpenUtau.Core/Classic/VoicebankPublisher.cs b/OpenUtau.Core/Classic/VoicebankPublisher.cs index 4feee7ac5..ea5974491 100644 --- a/OpenUtau.Core/Classic/VoicebankPublisher.cs +++ b/OpenUtau.Core/Classic/VoicebankPublisher.cs @@ -1,10 +1,9 @@ -using Ignore; -using System; +using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; - +using Ignore; using OpenUtau.Core.Ustx; namespace OpenUtau.Classic { @@ -14,7 +13,7 @@ public class VoicebankPublisher { public VoicebankPublisher(Action progress, string? gitIgnore) { this.progress = progress; - if(gitIgnore != null) { + if (gitIgnore != null) { ignore = new Ignore.Ignore(); ignore.Add(gitIgnore.Split("\n")); } @@ -37,12 +36,11 @@ private static void ModifyConfig(USinger singer, Action modify) } } - private bool IsIgnored(string relativePath){ + private bool IsIgnored(string relativePath) { return ignore?.IsIgnored(relativePath.Replace('\\', '/')) ?? false; } - private List GetFilesToPack(string singerPath) - { + private List GetFilesToPack(string singerPath) { List fileList = Directory.EnumerateFiles(singerPath, "*.*", SearchOption.AllDirectories).ToList(); List packList = fileList.FindAll(x => !IsIgnored(System.IO.Path.GetRelativePath(singerPath, x))); return packList; @@ -54,23 +52,21 @@ private List GetFilesToPack(string singerPath) ///including utau, enunu and diffsinger. ///Vogen voicebanks aren't supported. /// - public void Publish(USinger singer, string outputFile){ + public void Publish(USinger singer, string outputFile) { var location = singer.Location; - if(!Directory.Exists(location)){ + if (!Directory.Exists(location)) { return; } progress.Invoke(0, $"Publishing {singer.Name}"); //Write singer type into character.yaml try { ModifyConfig(singer, config => config.SingerType = singer.SingerType.ToString().ToLower()); - } catch (Exception e) { } + } catch (Exception e) { } var packList = GetFilesToPack(location); int index = 0; int fileCount = packList.Count(); - using(ZipArchive archive = new ZipArchive(File.Create(outputFile), ZipArchiveMode.Create)) - { - foreach (var absFilePath in packList) - { + using (ZipArchive archive = new ZipArchive(File.Create(outputFile), ZipArchiveMode.Create)) { + foreach (var absFilePath in packList) { index++; progress.Invoke(100.0 * index / fileCount, $"Compressing {absFilePath}"); string reFilePath = Path.GetRelativePath(location, absFilePath).Replace('\\', '/'); diff --git a/OpenUtau.Core/Classic/WorldlineRenderer.cs b/OpenUtau.Core/Classic/WorldlineRenderer.cs index 39f5e4f44..a1cd2a73f 100644 --- a/OpenUtau.Core/Classic/WorldlineRenderer.cs +++ b/OpenUtau.Core/Classic/WorldlineRenderer.cs @@ -79,13 +79,13 @@ public Task Render(RenderPhrase phrase, Progress progress, int tra try { phraseSynth.AddRequest(item, posMs, skipMs, lengthMs, fadeInMs, fadeOutMs); } catch (SynthRequestError e) { - if(e is CutOffExceedDurationError cee) { + if (e is CutOffExceedDurationError cee) { throw new MessageCustomizableException( $"Failed to render\n Oto error: cutoff exceeds audio duration \n{item.phone.phoneme}", $"\n{item.phone.phoneme}", e); } - if(e is CutOffBeforeOffsetError cbe) { + if (e is CutOffBeforeOffsetError cbe) { throw new MessageCustomizableException( $"Failed to render\n Oto error: cutoff before offset \n{item.phone.phoneme}", $"\n{item.phone.phoneme}", diff --git a/OpenUtau.Core/Commands/ExpCommands.cs b/OpenUtau.Core/Commands/ExpCommands.cs index c8e0dae9a..7bad90038 100644 --- a/OpenUtau.Core/Commands/ExpCommands.cs +++ b/OpenUtau.Core/Commands/ExpCommands.cs @@ -259,9 +259,9 @@ public SetPitchPointsCommand(UVoicePart part, IEnumerable notes, UPitch p newPitch = pitch; } public override string ToString() => "Set pitch points"; - public override void Execute(){ + public override void Execute() { lock (Part) { - for (var i=0; i diff --git a/OpenUtau.Core/DependencyInstaller.cs b/OpenUtau.Core/DependencyInstaller.cs index 87d7073d7..63d9fbdb4 100644 --- a/OpenUtau.Core/DependencyInstaller.cs +++ b/OpenUtau.Core/DependencyInstaller.cs @@ -26,7 +26,7 @@ public static void Install(string archivePath) { dependencyConfig = Core.Yaml.DefaultDeserializer.Deserialize(reader); } string name = dependencyConfig.name; - if(string.IsNullOrEmpty(name)){ + if (string.IsNullOrEmpty(name)) { throw new ArgumentException("missing name in oudep.yaml"); } var basePath = Path.Combine(PathManager.Inst.DependencyPath, name); diff --git a/OpenUtau.Core/DiffSinger/DiffSingerBasePhonemizer.cs b/OpenUtau.Core/DiffSinger/DiffSingerBasePhonemizer.cs index 82d6d0e33..21f00f3d2 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerBasePhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerBasePhonemizer.cs @@ -3,21 +3,18 @@ using System.IO; using System.Linq; using K4os.Hash.xxHash; -using Serilog; using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; - using OpenUtau.Api; using OpenUtau.Core.Ustx; using OpenUtau.Core.Util; +using Serilog; -namespace OpenUtau.Core.DiffSinger -{ - public abstract class DiffSingerBasePhonemizer : MachineLearningPhonemizer - { +namespace OpenUtau.Core.DiffSinger { + public abstract class DiffSingerBasePhonemizer : MachineLearningPhonemizer { USinger singer; DsConfig dsConfig; - DictionarylanguageIds = new Dictionary(); + Dictionary languageIds = new Dictionary(); string rootPath; float frameMs; ulong linguisticHash; @@ -29,8 +26,8 @@ public abstract class DiffSingerBasePhonemizer : MachineLearningPhonemizer DiffSingerSpeakerEmbedManager speakerEmbedManager; string defaultPause = "SP"; - protected virtual string GetDictionaryName()=>"dsdict.yaml"; - public virtual string GetLangCode()=>String.Empty;//The language code of the language the phonemizer is made for + protected virtual string GetDictionaryName() => "dsdict.yaml"; + public virtual string GetLangCode() => String.Empty;//The language code of the language the phonemizer is made for private bool _singerLoaded; @@ -49,7 +46,7 @@ private bool _executeSetSinger(USinger singer) { if (singer == null) { return false; } - if(singer.Location == null){ + if (singer.Location == null) { Log.Error("Singer location is null"); return false; } @@ -63,7 +60,7 @@ private bool _executeSetSinger(USinger singer) { try { var configTxt = File.ReadAllText(configPath); dsConfig = Yaml.DefaultDeserializer.Deserialize(configTxt); - } catch(Exception e) { + } catch (Exception e) { Log.Error(e, $"failed to load dsconfig from {configPath}"); return false; } @@ -114,10 +111,10 @@ protected virtual IG2p LoadG2p(string rootPath, bool useLangId = false) { //If this dictionary exists, load it. //If not, load dsdict.yaml. var g2ps = new List(); - var dictionaryNames = new string[] {GetDictionaryName(), "dsdict.yaml"}; + var dictionaryNames = new string[] { GetDictionaryName(), "dsdict.yaml" }; // Load dictionary from singer folder. G2pDictionary.Builder g2pBuilder = new G2pDictionary.Builder(); - foreach(var dictionaryName in dictionaryNames){ + foreach (var dictionaryName in dictionaryNames) { string dictionaryPath = Path.Combine(rootPath, dictionaryName); if (File.Exists(dictionaryPath)) { try { @@ -137,14 +134,14 @@ protected virtual IG2p LoadG2p(string rootPath, bool useLangId = false) { //Check if the phoneme is supported. If unsupported, return an empty string. //And apply language prefix to phoneme - string ValidatePhoneme(string phoneme){ - if(g2p.IsValidSymbol(phoneme) && phonemeTokens.ContainsKey(phoneme)){ + string ValidatePhoneme(string phoneme) { + if (g2p.IsValidSymbol(phoneme) && phonemeTokens.ContainsKey(phoneme)) { return phoneme; } var langCode = GetLangCode(); - if(langCode != String.Empty){ + if (langCode != String.Empty) { var phonemeWithLanguage = langCode + "/" + phoneme; - if(g2p.IsValidSymbol(phonemeWithLanguage) && phonemeTokens.ContainsKey(phonemeWithLanguage)){ + if (g2p.IsValidSymbol(phonemeWithLanguage) && phonemeTokens.ContainsKey(phonemeWithLanguage)) { return phonemeWithLanguage; } } @@ -171,7 +168,7 @@ string[] GetSymbols(Note note) { // User has not provided hint, query g2p dictionary. var g2presult = g2p.Query(note.lyric) ?? g2p.Query(note.lyric.ToLowerInvariant()); - if(g2presult != null) { + if (g2presult != null) { return g2presult; } //not found in g2p dictionary, treat lyric as phonetic hint @@ -182,12 +179,12 @@ string[] GetSymbols(Note note) { return new string[] { }; } - string GetSpeakerAtIndex(Note note, int index){ + string GetSpeakerAtIndex(Note note, int index) { var attr = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == index) ?? default; var speaker = singer.Subbanks .Where(subbank => subbank.Color == attr.voiceColor && subbank.toneSet.Contains(note.tone)) .FirstOrDefault(); - if(speaker is null) { + if (speaker is null) { return ""; } return speaker.Suffix; @@ -200,7 +197,7 @@ protected bool IsSyllableVowelExtensionNote(Note note) { /// /// distribute phonemes to each note inside the group /// - List ProcessWord(Note[] notes, string[] symbols){ + List ProcessWord(Note[] notes, string[] symbols) { //Check if all phonemes are defined in dsdict.yaml (for their types) foreach (var symbol in symbols) { if (!g2p.IsValidSymbol(symbol)) { @@ -216,17 +213,17 @@ List ProcessWord(Note[] notes, string[] symbols){ .ToArray(); var isVowel = dsPhonemes.Select(s => g2p.IsVowel(s.Symbol)).ToArray(); var isGlide = dsPhonemes.Select(s => g2p.IsGlide(s.Symbol)).ToArray(); - var nonExtensionNotes = notes.Where(n=>!IsSyllableVowelExtensionNote(n)).ToArray(); + var nonExtensionNotes = notes.Where(n => !IsSyllableVowelExtensionNote(n)).ToArray(); var isStart = new bool[dsPhonemes.Length]; - if(isVowel.All(b=>!b)){ + if (isVowel.All(b => !b)) { isStart[0] = true; } - for(int i=0; i=2 && isGlide[i-1] && !isVowel[i-2]){ - isStart[i-1] = true; - }else{ + if (i >= 2 && isGlide[i - 1] && !isVowel[i - 2]) { + isStart[i - 1] = true; + } else { isStart[i] = true; } } @@ -245,8 +242,8 @@ List ProcessWord(Note[] notes, string[] symbols){ } int framesBetweenTickPos(double tickPos1, double tickPos2) { - return (int)(timeAxis.TickPosToMsPos(tickPos2)/frameMs) - - (int)(timeAxis.TickPosToMsPos(tickPos1)/frameMs); + return (int)(timeAxis.TickPosToMsPos(tickPos2) / frameMs) + - (int)(timeAxis.TickPosToMsPos(tickPos1) / frameMs); } public static IEnumerable CumulativeSum(IEnumerable sequence, double start = 0) { @@ -275,28 +272,28 @@ public List stretch(IList source, double ratio, double endPos) { result.RemoveAt(result.Count - 1); return result; } - - public DiffSingerSpeakerEmbedManager getSpeakerEmbedManager(){ - if(speakerEmbedManager is null) { + + public DiffSingerSpeakerEmbedManager getSpeakerEmbedManager() { + if (speakerEmbedManager is null) { speakerEmbedManager = new DiffSingerSpeakerEmbedManager(dsConfig, rootPath); } return speakerEmbedManager; } - int PhonemeTokenize(string phoneme){ + int PhonemeTokenize(string phoneme) { bool success = phonemeTokens.TryGetValue(phoneme, out int token); - if(!success){ + if (!success) { throw new Exception($"Phoneme \"{phoneme}\" isn't supported by timing model. Please check {Path.Combine(rootPath, dsConfig.phonemes)}"); } return token; } - + protected override void ProcessPart(Note[][] phrase) { float padding = 500f;//Padding time for consonants at the beginning of a sentence, ms float frameMs = dsConfig.frameMs(); var startMs = timeAxis.TickPosToMsPos(phrase[0][0].position) - padding; var lastNote = phrase[^1][^1]; - var endTick = lastNote.position+lastNote.duration; + var endTick = lastNote.position + lastNote.duration; //[(Tick position of note, [phonemes])] //The first item of this list is for the consonants before the first note. var phrasePhonemes = new List{ @@ -316,19 +313,19 @@ protected override void ProcessPart(Note[][] phrase) { var wordPhonemes = ProcessWord(word, symbols); phrasePhonemes[^1].Phonemes.AddRange(wordPhonemes[0].Phonemes); phrasePhonemes.AddRange(wordPhonemes.Skip(1)); - notePhIndex.Add(notePhIndex[^1]+wordPhonemes.SelectMany(n=>n.Phonemes).Count()); + notePhIndex.Add(notePhIndex[^1] + wordPhonemes.SelectMany(n => n.Phonemes).Count()); } - - phrasePhonemes.Add(new phonemesPerNote(endTick,lastNote.tone)); + + phrasePhonemes.Add(new phonemesPerNote(endTick, lastNote.tone)); phrasePhonemes[0].Position = timeAxis.MsPosToTickPos( - timeAxis.TickPosToMsPos(phrasePhonemes[1].Position)-padding + timeAxis.TickPosToMsPos(phrasePhonemes[1].Position) - padding ); //Linguistic Encoder var tokens = phrasePhonemes .SelectMany(n => n.Phonemes) .Select(p => (Int64)PhonemeTokenize(p.Symbol)) .ToArray(); - var word_div = phrasePhonemes.Take(phrasePhonemes.Count-1) + var word_div = phrasePhonemes.Take(phrasePhonemes.Count - 1) .Select(n => (Int64)n.Phonemes.Count) .ToArray(); //Pairwise(phrasePhonemes) @@ -347,7 +344,7 @@ protected override void ProcessPart(Note[][] phrase) { new DenseTensor(word_dur, new int[] { word_dur.Length }, false) .Reshape(new int[] { 1, word_dur.Length }))); //Language id - if(dsConfig.use_lang_id){ + if (dsConfig.use_lang_id) { var langIdByPhone = phrasePhonemes .SelectMany(n => n.Phonemes) .Select(p => (long)languageIds.GetValueOrDefault(p.Language(), 0)) @@ -375,7 +372,7 @@ protected override void ProcessPart(Note[][] phrase) { .AsTensor(); //Duration Predictor var ph_midi = phrasePhonemes - .SelectMany(n=>Enumerable.Repeat((Int64)n.Tone, n.Phonemes.Count)) + .SelectMany(n => Enumerable.Repeat((Int64)n.Tone, n.Phonemes.Count)) .ToArray(); //Call Diffsinger Duration Predictor model var durationInputs = new List(); @@ -385,9 +382,9 @@ protected override void ProcessPart(Note[][] phrase) { new DenseTensor(ph_midi, new int[] { ph_midi.Length }, false) .Reshape(new int[] { 1, ph_midi.Length }))); //Speaker - if(dsConfig.speakers != null){ + if (dsConfig.speakers != null) { var speakerEmbedManager = getSpeakerEmbedManager(); - var speakersByPhone = phrasePhonemes + var speakersByPhone = phrasePhonemes .SelectMany(n => n.Phonemes) .Select(p => p.Speaker) .ToArray(); @@ -403,18 +400,18 @@ protected override void ProcessPart(Note[][] phrase) { durationOutputs = durationModel.Run(durationInputs).Cast().ToList(); durationCache?.Save(durationOutputs); } - List durationFrames = durationOutputs.First().AsTensor().Select(x=>(double)x).ToList(); - + List durationFrames = durationOutputs.First().AsTensor().Select(x => (double)x).ToList(); + //Alignment //(the index of the phoneme to be aligned, the Ms position of the phoneme) var phAlignPoints = new List>(); phAlignPoints = CumulativeSum(phrasePhonemes.Select(n => n.Phonemes.Count).ToList(), 0) - .Zip(phrasePhonemes.Skip(1), + .Zip(phrasePhonemes.Skip(1), (a, b) => new Tuple(a, timeAxis.TickPosToMsPos(b.Position))) .ToList(); var positions = new List(); List alignGroup = durationFrames.GetRange(1, phAlignPoints[0].Item1 - 1); - + var phs = phrasePhonemes.SelectMany(n => n.Phonemes).ToList(); //The starting consonant's duration keeps unchanged positions.AddRange(stretch(alignGroup, frameMs, phAlignPoints[0].Item2)); @@ -432,7 +429,7 @@ protected override void ProcessPart(Note[][] phrase) { foreach (int wordIndex in Enumerable.Range(0, phrase.Length)) { Note[] word = phrase[wordIndex]; var noteResult = new List>(); - if (!wordFound[wordIndex]){ + if (!wordFound[wordIndex]) { //partResult[word[0].position] = noteResult; continue; } @@ -451,34 +448,32 @@ protected override void ProcessPart(Note[][] phrase) { } } - struct dsPhoneme{ + struct dsPhoneme { public string Symbol; public string Speaker; - public dsPhoneme(string symbol, string speaker){ + public dsPhoneme(string symbol, string speaker) { Symbol = symbol; Speaker = speaker; } - public string Language(){ + public string Language() { return DiffSingerUtils.PhonemeLanguage(Symbol); } } - class phonemesPerNote{ + class phonemesPerNote { public int Position; public int Tone; public List Phonemes; - public phonemesPerNote(int position, int tone, List phonemes) - { + public phonemesPerNote(int position, int tone, List phonemes) { Position = position; Tone = tone; Phonemes = phonemes; } - public phonemesPerNote(int position, int tone) - { + public phonemesPerNote(int position, int tone) { Position = position; Tone = tone; Phonemes = new List(); diff --git a/OpenUtau.Core/DiffSinger/DiffSingerCache.cs b/OpenUtau.Core/DiffSinger/DiffSingerCache.cs index 36f462b13..ae89f7192 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerCache.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerCache.cs @@ -88,81 +88,81 @@ private static void SerializeNamedOnnxValue(BinaryWriter writer, NamedOnnxValue } // name writer.Write(namedOnnxValue.Name); - var tensorBase = (TensorBase) namedOnnxValue.Value; + var tensorBase = (TensorBase)namedOnnxValue.Value; var elementType = tensorBase.GetTypeInfo().ElementType; // dtype writer.Write((int)elementType); switch (elementType) { case TensorElementType.Float: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.UInt8: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.Int8: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.UInt16: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.Int16: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.Int32: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.Int64: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.String: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.Bool: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.Float16: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.Double: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.UInt32: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.UInt64: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.BFloat16: { - var tensor = namedOnnxValue.AsTensor(); - SerializeTensor(writer, tensor); - break; - } + var tensor = namedOnnxValue.AsTensor(); + SerializeTensor(writer, tensor); + break; + } case TensorElementType.Complex64: case TensorElementType.Complex128: case TensorElementType.DataTypeMax: @@ -216,80 +216,80 @@ private static NamedOnnxValue DeserializeNamedOnnxValue(BinaryReader reader) { NamedOnnxValue namedOnnxValue; switch (dtype) { case TensorElementType.Float: { - var tensor = DeserializeTensor(reader, size, sizeof(float), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(float), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.UInt8: { - var tensor = DeserializeTensor(reader, size, sizeof(byte), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(byte), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.Int8: { - var tensor = DeserializeTensor(reader, size, sizeof(sbyte), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(sbyte), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.UInt16: { - var tensor = DeserializeTensor(reader, size, sizeof(ushort), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(ushort), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.Int16: { - var tensor = DeserializeTensor(reader, size, sizeof(short), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(short), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.Int32: { - var tensor = DeserializeTensor(reader, size, sizeof(int), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(int), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.Int64: { - var tensor = DeserializeTensor(reader, size, sizeof(long), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(long), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.String: { - // string tensor - Tensor tensor = new DenseTensor(size); - for (var i = 0; i < size; ++i) { - tensor[i] = reader.ReadString(); + // string tensor + Tensor tensor = new DenseTensor(size); + for (var i = 0; i < size; ++i) { + tensor[i] = reader.ReadString(); + } + tensor = tensor.Reshape(shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; } - tensor = tensor.Reshape(shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } case TensorElementType.Bool: { - var tensor = DeserializeTensor(reader, size, sizeof(bool), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(bool), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.Float16: { - var tensor = DeserializeTensor(reader, size, sizeof(ushort), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(ushort), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.Double: { - var tensor = DeserializeTensor(reader, size, sizeof(double), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(double), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.UInt32: { - var tensor = DeserializeTensor(reader, size, sizeof(uint), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(uint), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.UInt64: { - var tensor = DeserializeTensor(reader, size, sizeof(ulong), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(ulong), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.BFloat16: { - var tensor = DeserializeTensor(reader, size, sizeof(ushort), shape); - namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); - break; - } + var tensor = DeserializeTensor(reader, size, sizeof(ushort), shape); + namedOnnxValue = NamedOnnxValue.CreateFromTensor(name, tensor); + break; + } case TensorElementType.Complex64: case TensorElementType.Complex128: case TensorElementType.DataTypeMax: @@ -300,8 +300,7 @@ private static NamedOnnxValue DeserializeNamedOnnxValue(BinaryReader reader) { return namedOnnxValue; } - private static Tensor DeserializeTensor(BinaryReader reader, int size, int typeSize, ReadOnlySpan shape) - { + private static Tensor DeserializeTensor(BinaryReader reader, int size, int typeSize, ReadOnlySpan shape) { var bytes = reader.ReadBytes(size * typeSize); var data = new T[size]; Buffer.BlockCopy(bytes, 0, data, 0, bytes.Length); diff --git a/OpenUtau.Core/DiffSinger/DiffSingerPitch.cs b/OpenUtau.Core/DiffSinger/DiffSingerPitch.cs index 3c39cc3fd..cb9a17304 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerPitch.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerPitch.cs @@ -11,10 +11,8 @@ using OpenUtau.Core.Util; using Serilog; -namespace OpenUtau.Core.DiffSinger -{ - public class DsPitch : IDisposable - { +namespace OpenUtau.Core.DiffSinger { + public class DsPitch : IDisposable { string rootPath; DsConfig dsConfig; Dictionary languageIds = new Dictionary(); @@ -29,18 +27,17 @@ public class DsPitch : IDisposable const float tailMs = DiffSingerUtils.tailMs; const string PEXP = DiffSingerUtils.PEXP; - public DsPitch(string rootPath) - { + public DsPitch(string rootPath) { this.rootPath = rootPath; dsConfig = Core.Yaml.DefaultDeserializer.Deserialize( File.ReadAllText(Path.Combine(rootPath, "dsconfig.yaml"), System.Text.Encoding.UTF8)); - if(dsConfig.pitch == null){ + if (dsConfig.pitch == null) { throw new Exception("This voicebank doesn't contain a pitch model"); } //Load language id if needed - if(dsConfig.use_lang_id){ - if(dsConfig.languages == null) { + if (dsConfig.use_lang_id) { + if (dsConfig.languages == null) { throw new Exception("\"languages\" field is not specified in dsconfig.yaml"); } var langIdPath = Path.Join(rootPath, dsConfig.languages); @@ -75,7 +72,7 @@ public DsPitch(string rootPath) protected IG2p LoadG2p(string rootPath) { // Load dictionary from singer folder. string file = Path.Combine(rootPath, "dsdict.yaml"); - if(!File.Exists(file)){ + if (!File.Exists(file)) { throw new Exception($"File not found: {file}"); } var g2pBuilder = G2pDictionary.NewBuilder().Load(File.ReadAllText(file)); @@ -85,28 +82,28 @@ protected IG2p LoadG2p(string rootPath) { return g2pBuilder.Build(); } - public DiffSingerSpeakerEmbedManager getSpeakerEmbedManager(){ - if(speakerEmbedManager is null) { + public DiffSingerSpeakerEmbedManager getSpeakerEmbedManager() { + if (speakerEmbedManager is null) { speakerEmbedManager = new DiffSingerSpeakerEmbedManager(dsConfig, rootPath); } return speakerEmbedManager; } - void SetRange(T[] list, T value, int startIndex, int endIndex){ - for(int i=startIndex;i(T[] list, T value, int startIndex, int endIndex) { + for (int i = startIndex; i < endIndex; i++) { list[i] = value; } } - int PhonemeTokenize(string phoneme){ + int PhonemeTokenize(string phoneme) { bool success = phonemeTokens.TryGetValue(phoneme, out int token); - if(!success){ + if (!success) { throw new Exception($"Phoneme \"{phoneme}\" isn't supported by pitch model. Please check {Path.Combine(rootPath, dsConfig.phonemes)}"); } return token; } - - public RenderPitchResult Process(RenderPhrase phrase){ + + public RenderPitchResult Process(RenderPhrase phrase) { var startMs = Math.Min(phrase.notes[0].positionMs, phrase.phones[0].positionMs) - headMs; var endMs = phrase.notes[^1].endMs + tailMs; int headFrames = (int)Math.Round(headMs / frameMs); @@ -127,7 +124,7 @@ public RenderPitchResult Process(RenderPhrase phrase){ .Select(x => (Int64)PhonemeTokenize(x)) .ToArray(); var ph_dur = phrase.phones - .Select(p=>(int)Math.Round(p.endMs/frameMs) - (int)Math.Round(p.positionMs/frameMs)) + .Select(p => (int)Math.Round(p.endMs / frameMs) - (int)Math.Round(p.positionMs / frameMs)) .Prepend(headFrames) .Append(tailFrames) .ToArray(); @@ -135,22 +132,22 @@ public RenderPitchResult Process(RenderPhrase phrase){ linguisticInputs.Add(NamedOnnxValue.CreateFromTensor("tokens", new DenseTensor(tokens, new int[] { tokens.Length }, false) .Reshape(new int[] { 1, tokens.Length }))); - if(dsConfig.predict_dur){ + if (dsConfig.predict_dur) { //if predict_dur is true, use word encode mode - var vowelIds = Enumerable.Range(0,phrase.phones.Length) - .Where(i=>g2p.IsVowel(phrase.phones[i].phoneme)) + var vowelIds = Enumerable.Range(0, phrase.phones.Length) + .Where(i => g2p.IsVowel(phrase.phones[i].phoneme)) .ToArray(); - if(vowelIds.Length == 0){ - vowelIds = new int[]{phrase.phones.Length-1}; + if (vowelIds.Length == 0) { + vowelIds = new int[] { phrase.phones.Length - 1 }; } - var word_div = vowelIds.Zip(vowelIds.Skip(1),(a,b)=>(Int64)(b-a)) + var word_div = vowelIds.Zip(vowelIds.Skip(1), (a, b) => (Int64)(b - a)) .Prepend(vowelIds[0] + 1) .Append(phrase.phones.Length - vowelIds[^1] + 1) .ToArray(); var word_dur = vowelIds.Zip(vowelIds.Skip(1), - (a,b)=>(Int64)(phrase.phones[b-1].endMs/frameMs) - (Int64)(phrase.phones[a].positionMs/frameMs)) - .Prepend((Int64)(phrase.phones[vowelIds[0]].positionMs/frameMs) - (Int64)(phrase.phones[0].positionMs/frameMs) + headFrames) - .Append((Int64)(phrase.notes[^1].endMs/frameMs) - (Int64)(phrase.phones[vowelIds[^1]].positionMs/frameMs) + tailFrames) + (a, b) => (Int64)(phrase.phones[b - 1].endMs / frameMs) - (Int64)(phrase.phones[a].positionMs / frameMs)) + .Prepend((Int64)(phrase.phones[vowelIds[0]].positionMs / frameMs) - (Int64)(phrase.phones[0].positionMs / frameMs) + headFrames) + .Append((Int64)(phrase.notes[^1].endMs / frameMs) - (Int64)(phrase.phones[vowelIds[^1]].positionMs / frameMs) + tailFrames) .ToArray(); linguisticInputs.Add(NamedOnnxValue.CreateFromTensor("word_div", new DenseTensor(word_div, new int[] { word_div.Length }, false) @@ -161,14 +158,14 @@ public RenderPitchResult Process(RenderPhrase phrase){ } else { //if predict_dur is false, use phoneme encode mode linguisticInputs.Add(NamedOnnxValue.CreateFromTensor("ph_dur", - new DenseTensor(ph_dur.Select(x=>(Int64)x).ToArray(), new int[] { ph_dur.Length }, false) + new DenseTensor(ph_dur.Select(x => (Int64)x).ToArray(), new int[] { ph_dur.Length }, false) .Reshape(new int[] { 1, ph_dur.Length }))); } //Language id - if(dsConfig.use_lang_id){ + if (dsConfig.use_lang_id) { var langIdByPhone = phrase.phones .Select(p => (long)languageIds.GetValueOrDefault( - DiffSingerUtils.PhonemeLanguage(p.phoneme),0 + DiffSingerUtils.PhonemeLanguage(p.phoneme), 0 )) .Prepend(0) .Append(0) @@ -196,19 +193,19 @@ public RenderPitchResult Process(RenderPhrase phrase){ .Where(o => o.Name == "x_masks") .First() .AsTensor(); - + //Pitch Predictor - var note_rest = new List{true}; + var note_rest = new List { true }; bool prevNoteRest = true; int phIndex = 0; - foreach(var note in phrase.notes) { + foreach (var note in phrase.notes) { //Slur notes follow the previous note's rest status - if(note.lyric.StartsWith("+")) { + if (note.lyric.StartsWith("+")) { note_rest.Add(prevNoteRest); continue; } //find all the phonemes in the note's time range - while(phIndex(float)n.tone) + .Select(n => (float)n.tone) .Prepend((float)phrase.notes[0].tone) .ToArray(); //get the index of groups of consecutive rest notes - var restGroups = new List>(); + var restGroups = new List>(); for (var i = 0; i < note_rest.Count; ++i) { if (!note_rest[i]) continue; var j = i + 1; @@ -237,27 +234,27 @@ public RenderPitchResult Process(RenderPhrase phrase){ i = j; } //Set tone for each rest group - foreach(var restGroup in restGroups){ - if(restGroup.Item1 == 0 && restGroup.Item2 == note_rest.Count){ + foreach (var restGroup in restGroups) { + if (restGroup.Item1 == 0 && restGroup.Item2 == note_rest.Count) { //If All the notes are rest notes, don't set tone break; } - if(restGroup.Item1 == 0){ + if (restGroup.Item1 == 0) { //If the first note is a rest note, set the tone to the tone of the first non-rest note SetRange(note_midi, note_midi[restGroup.Item2], 0, restGroup.Item2); - } else if(restGroup.Item2 == note_rest.Count){ + } else if (restGroup.Item2 == note_rest.Count) { //If the last note is a rest note, set the tone to the tone of the last non-rest note - SetRange(note_midi, note_midi[restGroup.Item1-1], restGroup.Item1, note_rest.Count); + SetRange(note_midi, note_midi[restGroup.Item1 - 1], restGroup.Item1, note_rest.Count); } else { //If the first and last notes are non-rest notes, set the tone to the nearest non-rest note - SetRange(note_midi, - note_midi[restGroup.Item1-1], - restGroup.Item1, - (restGroup.Item1 + restGroup.Item2 + 1)/2 + SetRange(note_midi, + note_midi[restGroup.Item1 - 1], + restGroup.Item1, + (restGroup.Item1 + restGroup.Item2 + 1) / 2 ); - SetRange(note_midi, - note_midi[restGroup.Item2], - (restGroup.Item1 + restGroup.Item2 + 1)/2, + SetRange(note_midi, + note_midi[restGroup.Item2], + (restGroup.Item1 + restGroup.Item2 + 1) / 2, restGroup.Item2 ); } @@ -266,11 +263,11 @@ public RenderPitchResult Process(RenderPhrase phrase){ //use the delta of the positions of the next note and the current note //to prevent incorrect timing when there is a small space between two notes var note_dur = phrase.notes.Zip(phrase.notes.Skip(1), - (curr,next)=> (int)Math.Round(next.positionMs/frameMs) - (int)Math.Round(curr.positionMs/frameMs)) - .Prepend((int)Math.Round(phrase.notes[0].positionMs/frameMs) - (int)Math.Round(startMs/frameMs)) + (curr, next) => (int)Math.Round(next.positionMs / frameMs) - (int)Math.Round(curr.positionMs / frameMs)) + .Prepend((int)Math.Round(phrase.notes[0].positionMs / frameMs) - (int)Math.Round(startMs / frameMs)) .Append(0) .ToList(); - note_dur[^1]=totalFrames-note_dur.Sum(); + note_dur[^1] = totalFrames - note_dur.Sum(); var pitch = Enumerable.Repeat(60f, totalFrames).ToArray(); var retake = Enumerable.Repeat(true, totalFrames).ToArray(); var pitchInputs = new List(); @@ -279,10 +276,10 @@ public RenderPitchResult Process(RenderPhrase phrase){ new DenseTensor(note_midi, new int[] { note_midi.Length }, false) .Reshape(new int[] { 1, note_midi.Length }))); pitchInputs.Add(NamedOnnxValue.CreateFromTensor("note_dur", - new DenseTensor(note_dur.Select(x=>(Int64)x).ToArray(), new int[] { note_dur.Count }, false) + new DenseTensor(note_dur.Select(x => (Int64)x).ToArray(), new int[] { note_dur.Count }, false) .Reshape(new int[] { 1, note_dur.Count }))); pitchInputs.Add(NamedOnnxValue.CreateFromTensor("ph_dur", - new DenseTensor(ph_dur.Select(x=>(Int64)x).ToArray(), new int[] { ph_dur.Length }, false) + new DenseTensor(ph_dur.Select(x => (Int64)x).ToArray(), new int[] { ph_dur.Length }, false) .Reshape(new int[] { 1, ph_dur.Length }))); pitchInputs.Add(NamedOnnxValue.CreateFromTensor("pitch", new DenseTensor(pitch, new int[] { pitch.Length }, false) @@ -301,7 +298,7 @@ public RenderPitchResult Process(RenderPhrase phrase){ speedup--; } pitchInputs.Add(NamedOnnxValue.CreateFromTensor("speedup", - new DenseTensor(new long[] { speedup }, new int[] { 1 },false))); + new DenseTensor(new long[] { speedup }, new int[] { 1 }, false))); } //expressiveness @@ -321,14 +318,14 @@ public RenderPitchResult Process(RenderPhrase phrase){ } //Speaker - if(dsConfig.speakers != null) { + if (dsConfig.speakers != null) { var speakerEmbedManager = getSpeakerEmbedManager(); var spkEmbedTensor = speakerEmbedManager.PhraseSpeakerEmbedByFrame(phrase, ph_dur, frameMs, totalFrames, headFrames, tailFrames); pitchInputs.Add(NamedOnnxValue.CreateFromTensor("spk_embed", spkEmbedTensor)); } //Melody encoder - if(dsConfig.use_note_rest) { + if (dsConfig.use_note_rest) { pitchInputs.Add(NamedOnnxValue.CreateFromTensor("note_rest", new DenseTensor(note_rest.ToArray(), new int[] { note_rest.Count }, false) .Reshape(new int[] { 1, note_rest.Count }))); @@ -338,18 +335,18 @@ public RenderPitchResult Process(RenderPhrase phrase){ var pitchOutputs = pitchModel.Run(pitchInputs); var pitch_out = pitchOutputs.First().AsTensor().ToArray(); var pitchEnd = phrase.timeAxis.MsPosToTickPos(startMs + (totalFrames - 1) * frameMs) - phrase.position; - if(pitchEnd<=phrase.duration){ - return new RenderPitchResult{ - ticks = Enumerable.Range(0,totalFrames) - .Select(i=>(float)phrase.timeAxis.MsPosToTickPos(startMs + i*frameMs) - phrase.position) + if (pitchEnd <= phrase.duration) { + return new RenderPitchResult { + ticks = Enumerable.Range(0, totalFrames) + .Select(i => (float)phrase.timeAxis.MsPosToTickPos(startMs + i * frameMs) - phrase.position) .Append((float)phrase.duration + 1) .ToArray(), tones = pitch_out.Append(pitch_out[^1]).ToArray() }; - }else{ - return new RenderPitchResult{ - ticks = Enumerable.Range(0,totalFrames) - .Select(i=>(float)phrase.timeAxis.MsPosToTickPos(startMs + i*frameMs) - phrase.position) + } else { + return new RenderPitchResult { + ticks = Enumerable.Range(0, totalFrames) + .Select(i => (float)phrase.timeAxis.MsPosToTickPos(startMs + i * frameMs) - phrase.position) .ToArray(), tones = pitch_out }; @@ -357,7 +354,7 @@ public RenderPitchResult Process(RenderPhrase phrase){ } private bool disposedValue; - + protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { diff --git a/OpenUtau.Core/DiffSinger/DiffSingerRenderer.cs b/OpenUtau.Core/DiffSinger/DiffSingerRenderer.cs index 5078a3e57..3ab418184 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerRenderer.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerRenderer.cs @@ -56,7 +56,8 @@ public class DiffSingerRenderer : IRenderer { public bool IsVoiceColorCurve(string abbr, out int subBankId) { subBankId = 0; - if (abbr.StartsWith(VoiceColorHeader) && int.TryParse(abbr.Substring(2), out subBankId)) {; + if (abbr.StartsWith(VoiceColorHeader) && int.TryParse(abbr.Substring(2), out subBankId)) { + ; subBankId -= 1; return true; } else { @@ -65,7 +66,7 @@ public bool IsVoiceColorCurve(string abbr, out int subBankId) { } public bool SupportsExpression(UExpressionDescriptor descriptor) { - return supportedExp.Contains(descriptor.abbr) || + return supportedExp.Contains(descriptor.abbr) || (descriptor.abbr.StartsWith(VoiceColorHeader) && int.TryParse(descriptor.abbr.Substring(2), out int _)); } @@ -89,7 +90,7 @@ public Task Render(RenderPhrase phrase, Progress progress, int tra var result = Layout(phrase); // calculate real depth - var singer = (DiffSingerSinger) phrase.singer; + var singer = (DiffSingerSinger)phrase.singer; double depth; int steps = Preferences.Default.DiffSingerSteps; if (singer.dsConfig.useVariableDepth) { @@ -139,9 +140,9 @@ public Task Render(RenderPhrase phrase, Progress progress, int tra float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, CancellationTokenSource cancellation) { var singer = phrase.singer as DiffSingerSinger; //Check if dsconfig.yaml is correct - if(String.IsNullOrEmpty(singer.dsConfig.vocoder) || + if (String.IsNullOrEmpty(singer.dsConfig.vocoder) || String.IsNullOrEmpty(singer.dsConfig.acoustic) || - String.IsNullOrEmpty(singer.dsConfig.phonemes)){ + String.IsNullOrEmpty(singer.dsConfig.phonemes)) { throw new Exception("Invalid dsconfig.yaml. Please ensure that dsconfig.yaml contains keys \"vocoder\", \"acoustic\" and \"phonemes\"."); } @@ -166,19 +167,19 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat $"Mel scale must be \"slaney\" or \"htk\", but got \"{singer.dsConfig.mel_scale}\" from acoustic model"); } //mel specification matching checks - if(vocoder.sample_rate != singer.dsConfig.sample_rate) { + if (vocoder.sample_rate != singer.dsConfig.sample_rate) { throw new Exception( $"Vocoder and acoustic model has mismatching sample rate ({vocoder.sample_rate} != {singer.dsConfig.sample_rate})"); } - if(vocoder.hop_size != singer.dsConfig.hop_size){ + if (vocoder.hop_size != singer.dsConfig.hop_size) { throw new Exception( $"Vocoder and acoustic model has mismatching hop size ({vocoder.hop_size} != {singer.dsConfig.hop_size})"); } - if(vocoder.win_size != singer.dsConfig.win_size){ + if (vocoder.win_size != singer.dsConfig.win_size) { throw new Exception( $"Vocoder and acoustic model has mismatching win size ({vocoder.win_size} != {singer.dsConfig.win_size})"); } - if(vocoder.fft_size != singer.dsConfig.fft_size){ + if (vocoder.fft_size != singer.dsConfig.fft_size) { throw new Exception( $"Vocoder and acoustic model has mismatching FFT size ({vocoder.fft_size} != {singer.dsConfig.fft_size})"); } @@ -228,19 +229,19 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat .Append(tailFrames) .ToList(); int totalFrames = durations.Sum(); - float[] f0 = DiffSingerUtils.SampleCurve(phrase, phrase.pitches, 0, frameMs, totalFrames, headFrames, tailFrames, + float[] f0 = DiffSingerUtils.SampleCurve(phrase, phrase.pitches, 0, frameMs, totalFrames, headFrames, tailFrames, x => MusicMath.ToneToFreq(x * 0.01)) .Select(f => (float)f).ToArray(); float[] shiftedF0 = f0.Zip(DiffSingerUtils.SampleCurve(phrase, phrase.toneShift, 0, frameMs, totalFrames, headFrames, tailFrames, x => x), - (x, d) => x * (float) Math.Pow(2, d / 1200)).ToArray(); + (x, d) => x * (float)Math.Pow(2, d / 1200)).ToArray(); var acousticInputs = new List(); acousticInputs.Add(NamedOnnxValue.CreateFromTensor("tokens", - new DenseTensor(tokens.ToArray(), new int[] { tokens.Count },false) + new DenseTensor(tokens.ToArray(), new int[] { tokens.Count }, false) .Reshape(new int[] { 1, tokens.Count }))); acousticInputs.Add(NamedOnnxValue.CreateFromTensor("durations", - new DenseTensor(durations.Select(x=>(long)x).ToArray(), new int[] { durations.Count }, false) + new DenseTensor(durations.Select(x => (long)x).ToArray(), new int[] { durations.Count }, false) .Reshape(new int[] { 1, durations.Count }))); var f0Tensor = new DenseTensor(f0, new int[] { f0.Length }) .Reshape(new int[] { 1, f0.Length }); @@ -256,14 +257,14 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat if (singer.dsConfig.useContinuousAcceleration) { if (singer.dsConfig.useVariableDepth) { acousticInputs.Add(NamedOnnxValue.CreateFromTensor("depth", - new DenseTensor(new float[] {(float)depth}, new int[] { 1 }, false))); + new DenseTensor(new float[] { (float)depth }, new int[] { 1 }, false))); } acousticInputs.Add(NamedOnnxValue.CreateFromTensor("steps", new DenseTensor(new long[] { steps }, new int[] { 1 }, false))); } else { long speedup; if (singer.dsConfig.useVariableDepth) { - long int64Depth = (long) Math.Round(depth * 1000); + long int64Depth = (long)Math.Round(depth * 1000); speedup = Math.Max(1, int64Depth / steps); int64Depth = int64Depth / speedup * speedup; // make sure depth can be divided by speedup acousticInputs.Add(NamedOnnxValue.CreateFromTensor("depth", @@ -279,10 +280,10 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat new DenseTensor(new long[] { speedup }, new int[] { 1 }, false))); } //Language id - if(singer.dsConfig.use_lang_id){ + if (singer.dsConfig.use_lang_id) { var langIdByPhone = phrase.phones .Select(p => (long)singer.languageIds.GetValueOrDefault( - DiffSingerUtils.PhonemeLanguage(p.phoneme),0 + DiffSingerUtils.PhonemeLanguage(p.phoneme), 0 )) .Prepend(0) .Append(0) @@ -292,7 +293,7 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat acousticInputs.Add(NamedOnnxValue.CreateFromTensor("languages", langIdTensor)); } //speaker - if(singer.dsConfig.speakers != null) { + if (singer.dsConfig.speakers != null) { var speakerEmbedManager = singer.getSpeakerEmbedManager(); var spkEmbedTensor = speakerEmbedManager.PhraseSpeakerEmbedByFrame(phrase, durations, frameMs, totalFrames, headFrames, tailFrames); acousticInputs.Add(NamedOnnxValue.CreateFromTensor("spk_embed", spkEmbedTensor)); @@ -301,11 +302,11 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat //Definition of GENC: 100 = 12 semitones of formant shift, positive GENC means shift down if (singer.dsConfig.useKeyShiftEmbed) { var range = singer.dsConfig.augmentationArgs.randomPitchShifting.range; - var positiveScale = (range[1]==0) ? 0 : (12/range[1]/100); - var negativeScale = (range[0]==0) ? 0 : (-12/range[0]/100); + var positiveScale = (range[1] == 0) ? 0 : (12 / range[1] / 100); + var negativeScale = (range[0] == 0) ? 0 : (-12 / range[0] / 100); float[] gender = DiffSingerUtils.SampleCurve(phrase, phrase.gender, 0, frameMs, totalFrames, headFrames, tailFrames, - x=> (x<0)?(-x * positiveScale):(-x * negativeScale)) + x => (x < 0) ? (-x * positiveScale) : (-x * negativeScale)) .Select(f => (float)f).ToArray(); var genderTensor = new DenseTensor(gender, new int[] { gender.Length }) .Reshape(new int[] { 1, gender.Length }); @@ -332,28 +333,28 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat } //Variance: Energy, Breathiness, Voicing and Tension - if( + if ( singer.dsConfig.useBreathinessEmbed || singer.dsConfig.useEnergyEmbed || singer.dsConfig.useVoicingEmbed || singer.dsConfig.useTensionEmbed) { var variancePredictor = singer.getVariancePredictor(); VarianceResult varianceResult; - lock(variancePredictor){ - if(cancellation.IsCancellationRequested) { + lock (variancePredictor) { + if (cancellation.IsCancellationRequested) { return null; } varianceResult = singer.getVariancePredictor().Process(phrase); } //TODO: let user edit variance curves - if(singer.dsConfig.useEnergyEmbed){ + if (singer.dsConfig.useEnergyEmbed) { var energyCurve = phrase.curves.FirstOrDefault(curve => curve.Item1 == ENE); IEnumerable userEnergy; - if(energyCurve!=null){ + if (energyCurve != null) { userEnergy = DiffSingerUtils.SampleCurve(phrase, energyCurve.Item2, 0, frameMs, totalFrames, headFrames, tailFrames, - x => x).Select(x => (float) x); - } else{ + x => x).Select(x => (float)x); + } else { userEnergy = Enumerable.Repeat(0f, totalFrames); } if (varianceResult.energy == null) { @@ -366,10 +367,10 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat new DenseTensor(energy, new int[] { energy.Length }) .Reshape(new int[] { 1, energy.Length }))); } - if(singer.dsConfig.useBreathinessEmbed){ + if (singer.dsConfig.useBreathinessEmbed) { var userBreathiness = DiffSingerUtils.SampleCurve(phrase, phrase.breathiness, 0, frameMs, totalFrames, headFrames, tailFrames, - x => x).Select(x => (float) x); + x => x).Select(x => (float)x); if (varianceResult.breathiness == null) { throw new KeyNotFoundException( "The parameter \"breathiness\" required by acoustic model is not found in variance predictions."); @@ -380,10 +381,10 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat new DenseTensor(breathiness, new int[] { breathiness.Length }) .Reshape(new int[] { 1, breathiness.Length }))); } - if(singer.dsConfig.useVoicingEmbed){ + if (singer.dsConfig.useVoicingEmbed) { var userVoicing = DiffSingerUtils.SampleCurve(phrase, phrase.voicing, 0, frameMs, totalFrames, headFrames, tailFrames, - x => x).Select(x => (float) x); + x => x).Select(x => (float)x); if (varianceResult.voicing == null) { throw new KeyNotFoundException( "The parameter \"voicing\" required by acoustic model is not found in variance predictions."); @@ -394,10 +395,10 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat new DenseTensor(voicing, new int[] { voicing.Length }) .Reshape(new int[] { 1, voicing.Length }))); } - if(singer.dsConfig.useTensionEmbed){ + if (singer.dsConfig.useTensionEmbed) { var userTension = DiffSingerUtils.SampleCurve(phrase, phrase.tension, 0, frameMs, totalFrames, headFrames, tailFrames, - x => x).Select(x => (float) x); + x => x).Select(x => (float)x); if (varianceResult.tension == null) { throw new KeyNotFoundException( "The parameter \"tension\" required by acoustic model is not found in variance predictions."); @@ -415,8 +416,8 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat : null; var acousticOutputs = acousticCache?.Load(); if (acousticOutputs is null) { - lock(acousticModel){ - if(cancellation.IsCancellationRequested) { + lock (acousticModel) { + if (cancellation.IsCancellationRequested) { return null; } acousticOutputs = acousticModel.Run(acousticInputs).Cast().ToList(); @@ -430,8 +431,7 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat float k; if (vocoder.mel_base == "e" && singer.dsConfig.mel_base == "10") { k = 2.30259f; - } - else if (vocoder.mel_base == "10" && singer.dsConfig.mel_base == "e") { + } else if (vocoder.mel_base == "10" && singer.dsConfig.mel_base == "e") { k = 0.434294f; } else { // this should never happen @@ -449,14 +449,14 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat //waveform = session.run(['waveform'], {'mel': mel, 'f0': f0})[0] var vocoderInputs = new List(); vocoderInputs.Add(NamedOnnxValue.CreateFromTensor("mel", mel)); - vocoderInputs.Add(NamedOnnxValue.CreateFromTensor("f0",f0Tensor)); + vocoderInputs.Add(NamedOnnxValue.CreateFromTensor("f0", f0Tensor)); var vocoderCache = Preferences.Default.DiffSingerTensorCache ? new DiffSingerCache(vocoder.hash, vocoderInputs) : null; var vocoderOutputs = vocoderCache?.Load(); if (vocoderOutputs is null) { - lock(vocoder){ - if(cancellation.IsCancellationRequested) { + lock (vocoder) { + if (cancellation.IsCancellationRequested) { return null; } vocoderOutputs = vocoder.session.Run(vocoderInputs).Cast().ToList(); @@ -467,7 +467,7 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat Tensor samplesTensor = vocoderOutputs.First().AsTensor(); //Check the size of samplesTensor int[] expectedShape = new int[] { 1, -1 }; - if(!DiffSingerUtils.ValidateShape(samplesTensor, expectedShape)){ + if (!DiffSingerUtils.ValidateShape(samplesTensor, expectedShape)) { throw new Exception($"The shape of vocoder output should be (1, length), but the actual shape is {DiffSingerUtils.ShapeString(samplesTensor)}"); } var samples = samplesTensor.ToArray(); @@ -475,7 +475,7 @@ float[] InvokeDiffsinger(RenderPhrase phrase, double depth, int steps, Cancellat } public RenderPitchResult LoadRenderedPitch(RenderPhrase phrase) { - DiffSingerSinger singer = (DiffSingerSinger) phrase.singer; + DiffSingerSinger singer = (DiffSingerSinger)phrase.singer; if (!singer.HasPitchPredictor) { throw new Exception("This singer has no pitch predictor."); } @@ -489,7 +489,7 @@ public List LoadRenderedRealCurves(RenderPhrase phrase) { if (!Preferences.Default.DiffSingerTensorCache) { throw new Exception("Please enable DiffSinger tensor cache and re-render the phrase to display correct base curves."); } - DiffSingerSinger singer = (DiffSingerSinger) phrase.singer; + DiffSingerSinger singer = (DiffSingerSinger)phrase.singer; if (!singer.HasVariancePredictor) { return new List(0); } @@ -571,18 +571,18 @@ public UExpressionDescriptor[] GetSuggestedExpressions(USinger singer, URenderSe }; //speakers var dsSinger = singer as DiffSingerSinger; - if(dsSinger!=null && dsSinger.dsConfig.speakers != null) { + if (dsSinger != null && dsSinger.dsConfig.speakers != null) { result.AddRange(Enumerable.Zip( dsSinger.Subbanks, Enumerable.Range(1, dsSinger.Subbanks.Count), - (subbank,index)=>new UExpressionDescriptor { - name=$"voice color {subbank.Color}", - abbr=VoiceColorHeader+index.ToString("D2"), - type=UExpressionType.Curve, - min=0, - max=100, - defaultValue=0, - isFlag=false, + (subbank, index) => new UExpressionDescriptor { + name = $"voice color {subbank.Color}", + abbr = VoiceColorHeader + index.ToString("D2"), + type = UExpressionType.Curve, + min = 0, + max = 100, + defaultValue = 0, + isFlag = false, })); } diff --git a/OpenUtau.Core/DiffSinger/DiffSingerScript.cs b/OpenUtau.Core/DiffSinger/DiffSingerScript.cs index 9b86555b1..c56e11033 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerScript.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerScript.cs @@ -8,7 +8,7 @@ using OpenUtau.Core.Ustx; namespace OpenUtau.Core.DiffSinger { - public class DiffSingerScript{ + public class DiffSingerScript { public double offsetMs; public string[] text; public string[] ph_seq; @@ -21,17 +21,17 @@ public class DiffSingerScript{ public double frameMs; public double[]? gender = null; public double[]? velocity = null; - + //if v2 is true, export diffsinger script for diffsinger's refactor-v2 branch public DiffSingerScript(RenderPhrase phrase, bool v2 = false, bool exportPitch = true) { const float headMs = DiffSingerUtils.headMs; const float tailMs = DiffSingerUtils.tailMs; - + var notes = phrase.notes; var phones = phrase.phones; - + text = notes.Select(n => n.lyric) - .Where(s=>!s.StartsWith("+")) + .Where(s => !s.StartsWith("+")) .Prepend("SP") .Append("SP") .ToArray(); @@ -56,8 +56,8 @@ public DiffSingerScript(RenderPhrase phrase, bool v2 = false, bool exportPitch = int prevNotePhId = 0; int phId = 0; int phCount = phones.Length; - foreach(var note in notes.Where(n=>!n.lyric.StartsWith("+"))) { - while(phId < phCount && phones[phId].position < note.position-ep){ + foreach (var note in notes.Where(n => !n.lyric.StartsWith("+"))) { + while (phId < phCount && phones[phId].position < note.position - ep) { ++phId; } phNumList.Add(phId - prevNotePhId); @@ -68,13 +68,13 @@ public DiffSingerScript(RenderPhrase phrase, bool v2 = false, bool exportPitch = ++phNumList[0];//head AP ph_num = phNumList.ToArray(); - if(v2){ + if (v2) { noteSeq = notes .Select(n => (n.lyric == "SP" || n.lyric == "AP") ? 0 : n.tone) .Prepend(0) .Append(0) .ToArray(); - }else{ + } else { noteSeq = phones .Select(p => (p.phoneme == "SP" || p.phoneme == "AP") ? 0 : p.tone) .Prepend(0) @@ -83,37 +83,37 @@ public DiffSingerScript(RenderPhrase phrase, bool v2 = false, bool exportPitch = } noteDurMs = notes .Select(n => n.durationMs) - .Prepend(headMs+(notes[0].positionMs-phones[0].positionMs)) + .Prepend(headMs + (notes[0].positionMs - phones[0].positionMs)) .Append(tailMs) .ToArray(); - + frameMs = 10; - + int headFrames = (int)(headMs / frameMs); int tailFrames = (int)(tailMs / frameMs); var totalFrames = (int)(phDurMs.Sum() / frameMs); //f0 - if(exportPitch){ - f0_seq = DiffSingerUtils.SampleCurve(phrase, phrase.pitches, - 0, frameMs, totalFrames, headFrames, tailFrames, + if (exportPitch) { + f0_seq = DiffSingerUtils.SampleCurve(phrase, phrase.pitches, + 0, frameMs, totalFrames, headFrames, tailFrames, x => MusicMath.ToneToFreq(x * 0.01)); } //velc var velocityCurve = phrase.curves.FirstOrDefault(curve => curve.Item1 == DiffSingerUtils.VELC); if (velocityCurve != null) { - velocity = DiffSingerUtils.SampleCurve(phrase, velocityCurve.Item2, + velocity = DiffSingerUtils.SampleCurve(phrase, velocityCurve.Item2, 0, frameMs, totalFrames, headFrames, tailFrames, - x=>Math.Pow(2, (x - 100) / 100)); + x => Math.Pow(2, (x - 100) / 100)); } //voicebank specific features DiffSingerSinger singer = null; - if (phrase.singer != null) { - singer = phrase.singer as DiffSingerSinger; + if (phrase.singer != null) { + singer = phrase.singer as DiffSingerSinger; } - if(singer != null) { + if (singer != null) { //gender if (singer.dsConfig.useKeyShiftEmbed) { var range = singer.dsConfig.augmentationArgs.randomPitchShifting.range; @@ -127,7 +127,7 @@ public DiffSingerScript(RenderPhrase phrase, bool v2 = false, bool exportPitch = offsetMs = phrase.phones[0].positionMs - headMs; } - + public RawDiffSingerScript toRaw() { return new RawDiffSingerScript(this); } @@ -141,7 +141,7 @@ static public void SavePart(UProject project, UVoicePart part, string filePath, new UTF8Encoding(false)); } } - + public class RawDiffSingerScript { public double offset; public string text; @@ -166,21 +166,21 @@ public RawDiffSingerScript(DiffSingerScript script) { text = String.Join(" ", script.text); ph_seq = String.Join(" ", script.ph_seq); ph_num = String.Join(" ", script.ph_num); - note_seq = String.Join(" ", + note_seq = String.Join(" ", script.noteSeq .Select(x => x <= 0 ? "rest" : MusicMath.GetToneName(x))); - ph_dur = String.Join(" ",script.phDurMs.Select(x => (x/1000).ToString("f4"))); - note_dur = String.Join(" ",script.noteDurMs.Select(x => (x/1000).ToString("f4"))); + ph_dur = String.Join(" ", script.phDurMs.Select(x => (x / 1000).ToString("f4"))); + note_dur = String.Join(" ", script.noteDurMs.Select(x => (x / 1000).ToString("f4"))); note_dur_seq = ph_dur; note_slur = String.Join(" ", script.note_slur); is_slur_seq = String.Join(" ", script.ph_seq.Select(x => "0")); - - if(script.f0_seq!=null){ + + if (script.f0_seq != null) { f0_seq = String.Join(" ", script.f0_seq.Select(x => x.ToString("f1"))); } f0_timestep = (script.frameMs / 1000).ToString(); - if(script.gender != null) { + if (script.gender != null) { gender_timestep = f0_timestep; gender = String.Join(" ", script.gender.Select(x => x.ToString("f3"))); } @@ -191,4 +191,4 @@ public RawDiffSingerScript(DiffSingerScript script) { } } } -} \ No newline at end of file +} diff --git a/OpenUtau.Core/DiffSinger/DiffSingerSinger.cs b/OpenUtau.Core/DiffSinger/DiffSingerSinger.cs index b7fc50018..d93255b4c 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerSinger.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerSinger.cs @@ -4,10 +4,10 @@ using System.Linq; using System.Text; using K4os.Hash.xxHash; +using Microsoft.ML.OnnxRuntime; using OpenUtau.Classic; using OpenUtau.Core.Ustx; using Serilog; -using Microsoft.ML.OnnxRuntime; namespace OpenUtau.Core.DiffSinger { class DiffSingerSinger : USinger { @@ -52,7 +52,7 @@ class DiffSingerSinger : USinger { public DiffSingerSpeakerEmbedManager speakerEmbedManager = null; public DsVariance variancePredictor = null; public bool HasPitchPredictor => File.Exists(Path.Join(Location, "dspitch", "dsconfig.yaml")); - public bool HasVariancePredictor => File.Exists(Path.Join(Location,"dsvariance", "dsconfig.yaml")); + public bool HasVariancePredictor => File.Exists(Path.Join(Location, "dsvariance", "dsconfig.yaml")); public DiffSingerSinger(Voicebank voicebank) { this.voicebank = voicebank; @@ -80,7 +80,7 @@ public DiffSingerSinger(Voicebank voicebank) { //Load diffsinger config of a voicebank string configPath = Path.Combine(Location, "dsconfig.yaml"); - if(configPath != null && File.Exists(configPath)){ + if (configPath != null && File.Exists(configPath)) { try { dsConfig = Core.Yaml.DefaultDeserializer.Deserialize( File.ReadAllText(configPath, Encoding.UTF8)); @@ -95,11 +95,11 @@ public DiffSingerSinger(Voicebank voicebank) { //Load phoneme list string phonemesPath = Path.Combine(Location, dsConfig.phonemes); - if(phonemesPath != null && File.Exists(phonemesPath)){ + if (phonemesPath != null && File.Exists(phonemesPath)) { try { phonemeTokens = DiffSingerUtils.LoadPhonemes(phonemesPath); phonemes = phonemeTokens.Keys.ToList(); - } catch (Exception e){ + } catch (Exception e) { Log.Error(e, $"Failed to load phoneme list for {Name} from {phonemesPath}"); } } else { @@ -107,11 +107,11 @@ public DiffSingerSinger(Voicebank voicebank) { } //Load language Id if needed - if(dsConfig.use_lang_id){ - if(dsConfig.languages == null){ + if (dsConfig.use_lang_id) { + if (dsConfig.languages == null) { Log.Error("\"languages\" field is not specified in dsconfig.yaml"); } else { - var langIdPath = Path.Join(Location, dsConfig.languages); + var langIdPath = Path.Join(Location, dsConfig.languages); try { languageIds = DiffSingerUtils.LoadLanguageIds(langIdPath); } catch (Exception e) { @@ -172,8 +172,8 @@ public InferenceSession getAcousticSession() { } public DsVocoder getVocoder() { - if(vocoder is null) { - if(File.Exists(Path.Join(Location, "dsvocoder", "vocoder.yaml"))) { + if (vocoder is null) { + if (File.Exists(Path.Join(Location, "dsvocoder", "vocoder.yaml"))) { vocoder = new DsVocoder(Path.Join(Location, "dsvocoder")); return vocoder; } @@ -182,61 +182,61 @@ public DsVocoder getVocoder() { return vocoder; } - public DsPitch? getPitchPredictor(){ - if(pitchPredictor is null) { - if(HasPitchPredictor){ + public DsPitch? getPitchPredictor() { + if (pitchPredictor is null) { + if (HasPitchPredictor) { pitchPredictor = new DsPitch(Path.Join(Location, "dspitch")); } } return pitchPredictor; } - - public DiffSingerSpeakerEmbedManager getSpeakerEmbedManager(){ - if(speakerEmbedManager is null) { + + public DiffSingerSpeakerEmbedManager getSpeakerEmbedManager() { + if (speakerEmbedManager is null) { speakerEmbedManager = new DiffSingerSpeakerEmbedManager(dsConfig, Location); } return speakerEmbedManager; } - public DsVariance? getVariancePredictor(){ - if(variancePredictor is null) { - if(HasVariancePredictor){ + public DsVariance? getVariancePredictor() { + if (variancePredictor is null) { + if (HasVariancePredictor) { variancePredictor = new DsVariance(Path.Join(Location, "dsvariance")); } } return variancePredictor; } - public int PhonemeTokenize(string phoneme){ + public int PhonemeTokenize(string phoneme) { bool success = phonemeTokens.TryGetValue(phoneme, out int token); - if(!success){ + if (!success) { throw new Exception($"Phoneme \"{phoneme}\" isn't supported by acoustic model. Please check {Path.Combine(Location, dsConfig.phonemes)}"); } return token; } - public override void FreeMemory(){ + public override void FreeMemory() { Log.Information($"Freeing memory for singer {Id}"); - if(acousticSession != null) { - lock(acousticSession) { + if (acousticSession != null) { + lock (acousticSession) { acousticSession?.Dispose(); } acousticSession = null; } - if(vocoder != null) { - lock(vocoder) { + if (vocoder != null) { + lock (vocoder) { vocoder?.Dispose(); } vocoder = null; } - if(pitchPredictor != null) { - lock(pitchPredictor) { + if (pitchPredictor != null) { + lock (pitchPredictor) { pitchPredictor?.Dispose(); } pitchPredictor = null; } - if(variancePredictor != null){ - lock(variancePredictor) { + if (variancePredictor != null) { + lock (variancePredictor) { variancePredictor?.Dispose(); } variancePredictor = null; diff --git a/OpenUtau.Core/DiffSinger/DiffSingerSpeakerEmbedManager.cs b/OpenUtau.Core/DiffSinger/DiffSingerSpeakerEmbedManager.cs index 979d49dd7..aec236efa 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerSpeakerEmbedManager.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerSpeakerEmbedManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -8,10 +8,8 @@ using OpenUtau.Core.Render; -namespace OpenUtau.Core.DiffSinger -{ - public class DiffSingerSpeakerEmbedManager - { +namespace OpenUtau.Core.DiffSinger { + public class DiffSingerSpeakerEmbedManager { DsConfig dsConfig; string rootPath; public NDArray speakerEmbeds = null; @@ -23,7 +21,7 @@ public DiffSingerSpeakerEmbedManager(DsConfig dsConfig, string rootPath) { } public NDArray loadSpeakerEmbed(string speaker) { string path = Path.Join(rootPath, speaker + ".emb"); - if(File.Exists(path)) { + if (File.Exists(path)) { var reader = new BinaryReader(File.OpenRead(path)); return np.array(Enumerable.Range(0, dsConfig.hiddenSize) .Select(i => reader.ReadSingle())); @@ -33,12 +31,12 @@ public NDArray loadSpeakerEmbed(string speaker) { } public NDArray getSpeakerEmbeds() { - if(speakerEmbeds == null) { - if(dsConfig.speakers == null) { + if (speakerEmbeds == null) { + if (dsConfig.speakers == null) { return null; } else { var embeds = np.zeros(dsConfig.hiddenSize, dsConfig.speakers.Count); - foreach(var spkId in Enumerable.Range(0, dsConfig.speakers.Count)) { + foreach (var spkId in Enumerable.Range(0, dsConfig.speakers.Count)) { embeds[":", spkId] = loadSpeakerEmbed(dsConfig.speakers[spkId]); } speakerEmbeds = embeds; @@ -49,7 +47,8 @@ public NDArray getSpeakerEmbeds() { public bool IsVoiceColorCurve(string abbr, out int subBankId) { subBankId = 0; - if (abbr.StartsWith(VoiceColorHeader) && int.TryParse(abbr.Substring(2), out subBankId)) {; + if (abbr.StartsWith(VoiceColorHeader) && int.TryParse(abbr.Substring(2), out subBankId)) { + ; subBankId -= 1; return true; } else { @@ -57,33 +56,33 @@ public bool IsVoiceColorCurve(string abbr, out int subBankId) { } } - public int getSpeakerIndexBySuffix(string suffix){ + public int getSpeakerIndexBySuffix(string suffix) { var speakerIndex = dsConfig.speakers.IndexOf(suffix); - if(speakerIndex == -1){ + if (speakerIndex == -1) { speakerIndex = 0; } return speakerIndex; } //used by phonemizer (duration model) - public Tensor PhraseSpeakerEmbedByPhone(string[] speakerByPhone){ + public Tensor PhraseSpeakerEmbedByPhone(string[] speakerByPhone) { var hiddenSize = dsConfig.hiddenSize; var speakerEmbeds = getSpeakerEmbeds(); var totalPhones = speakerByPhone.Length; NDArray spkCurves = np.zeros(totalPhones, dsConfig.speakers.Count); - foreach(int phoneId in Enumerable.Range(0,totalPhones)) { + foreach (int phoneId in Enumerable.Range(0, totalPhones)) { var spkId = getSpeakerIndexBySuffix(speakerByPhone[phoneId]); spkCurves[phoneId, spkId] = 1; } var spkEmbedResult = np.dot(spkCurves, speakerEmbeds.T); - var spkEmbedTensor = new DenseTensor(spkEmbedResult.ToArray(), + var spkEmbedTensor = new DenseTensor(spkEmbedResult.ToArray(), new int[] { totalPhones, hiddenSize }) .Reshape(new int[] { 1, totalPhones, hiddenSize }); return spkEmbedTensor; } //used by variance, pitch and acoustic - public Tensor PhraseSpeakerEmbedByFrame(RenderPhrase phrase, IList durations, float frameMs, int totalFrames, int headFrames, int tailFrames){ + public Tensor PhraseSpeakerEmbedByFrame(RenderPhrase phrase, IList durations, float frameMs, int totalFrames, int headFrames, int tailFrames) { var singer = phrase.singer; var hiddenSize = dsConfig.hiddenSize; var speakerEmbeds = getSpeakerEmbeds(); @@ -92,19 +91,19 @@ public Tensor PhraseSpeakerEmbedByFrame(RenderPhrase phrase, IList d var tailDefaultSpk = getSpeakerIndexBySuffix(phrase.phones[^1].suffix); var defaultSpkByFrame = Enumerable.Repeat(headDefaultSpk, headFrames).ToList(); defaultSpkByFrame.AddRange(Enumerable.Range(0, phrase.phones.Length) - .SelectMany(phIndex => Enumerable.Repeat(getSpeakerIndexBySuffix(phrase.phones[phIndex].suffix), durations[phIndex+1]))); + .SelectMany(phIndex => Enumerable.Repeat(getSpeakerIndexBySuffix(phrase.phones[phIndex].suffix), durations[phIndex + 1]))); defaultSpkByFrame.AddRange(Enumerable.Repeat(tailDefaultSpk, tailFrames)); //get speaker curves NDArray spkCurves = np.zeros(totalFrames, dsConfig.speakers.Count); - foreach(var curve in phrase.curves) { - if(IsVoiceColorCurve(curve.Item1,out int subBankId) && subBankId < singer.Subbanks.Count) { + foreach (var curve in phrase.curves) { + if (IsVoiceColorCurve(curve.Item1, out int subBankId) && subBankId < singer.Subbanks.Count) { var spkId = getSpeakerIndexBySuffix(singer.Subbanks[subBankId].Suffix); - spkCurves[":", spkId] += DiffSingerUtils.SampleCurve(phrase, curve.Item2, 0, + spkCurves[":", spkId] += DiffSingerUtils.SampleCurve(phrase, curve.Item2, 0, frameMs, totalFrames, headFrames, tailFrames, x => x * 0.01f) .Select(f => (float)f).ToArray(); } } - foreach(int frameId in Enumerable.Range(0,totalFrames)) { + foreach (int frameId in Enumerable.Range(0, totalFrames)) { //standarization var spkSum = spkCurves[frameId, ":"].ToArray().Sum(); if (spkSum > 1) { @@ -114,7 +113,7 @@ public Tensor PhraseSpeakerEmbedByFrame(RenderPhrase phrase, IList d } } var spkEmbedResult = np.dot(spkCurves, speakerEmbeds.T); - var spkEmbedTensor = new DenseTensor(spkEmbedResult.ToArray(), + var spkEmbedTensor = new DenseTensor(spkEmbedResult.ToArray(), new int[] { totalFrames, hiddenSize }) .Reshape(new int[] { 1, totalFrames, hiddenSize }); return spkEmbedTensor; diff --git a/OpenUtau.Core/DiffSinger/DiffSingerUtils.cs b/OpenUtau.Core/DiffSinger/DiffSingerUtils.cs index 19876e2ed..9fa882fdc 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerUtils.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerUtils.cs @@ -41,7 +41,7 @@ public static double[] SampleCurve(RenderPhrase phrase, float[] curve, double de //MusicMath.Linear, but float numbers are used instead of double public static float LinearF(float x0, float x1, float y0, float y1, float x) { const float ep = 0.001f; - if(x1 - x0 < ep){ + if (x1 - x0 < ep) { return y1; } return y0 + (y1 - y0) * (x - x0) / (x1 - x0); @@ -57,11 +57,11 @@ public static float[] ResampleCurve(float[] curve, int length) { if (curve == null || curve.Length == 0) { return null; } - if(length == curve.Length){ + if (length == curve.Length) { return curve; } - if(length == 1){ - return new float[]{curve[0]}; + if (length == 1) { + return new float[] { curve[0] }; } float[] result = new float[length]; for (int i = 0; i < length; i++) { @@ -82,26 +82,26 @@ public static float[] ResampleCurve(float[] curve, int length) { /// Tensor to be validated /// Expected shape of the tensor, -1 means the length of the axis is dynamic /// - public static bool ValidateShape(Tensor tensor, int[] expectedShape){ + public static bool ValidateShape(Tensor tensor, int[] expectedShape) { var shape = tensor.Dimensions; - if(shape.Length != expectedShape.Length){ + if (shape.Length != expectedShape.Length) { return false; } for (int i = 0; i < shape.Length; i++) { - if(shape[i] != expectedShape[i] && expectedShape[i] != -1){ + if (shape[i] != expectedShape[i] && expectedShape[i] != -1) { return false; } } return true; } - public static string ShapeString(Tensor tensor){ + public static string ShapeString(Tensor tensor) { var shape = tensor.Dimensions; return "(" + string.Join(", ", shape.ToArray()) + ")"; } - public static Dictionary LoadPhonemes(string filePath){ - switch(Path.GetExtension(filePath).ToLower()){ + public static Dictionary LoadPhonemes(string filePath) { + switch (Path.GetExtension(filePath).ToLower()) { case ".json": return LoadPhonemesFromJson(filePath); default: @@ -109,12 +109,12 @@ public static Dictionary LoadPhonemes(string filePath){ } } - static Dictionary LoadPhonemesFromJson(string filePath){ + static Dictionary LoadPhonemesFromJson(string filePath) { var json = File.ReadAllText(filePath, Encoding.UTF8); return JsonConvert.DeserializeObject>(json); } - static Dictionary LoadPhonemesFromTxt(string filePath){ + static Dictionary LoadPhonemesFromTxt(string filePath) { var lines = File.ReadAllLines(filePath, Encoding.UTF8); var result = new Dictionary(); for (int i = 0; i < lines.Length; i++) { @@ -123,13 +123,13 @@ static Dictionary LoadPhonemesFromTxt(string filePath){ return result; } - public static Dictionary LoadLanguageIds(string filePath){ + public static Dictionary LoadLanguageIds(string filePath) { var json = File.ReadAllText(filePath, Encoding.UTF8); return JsonConvert.DeserializeObject>(json); } - public static string PhonemeLanguage(string phoneme){ - if(phoneme.Contains("/")){ + public static string PhonemeLanguage(string phoneme) { + if (phoneme.Contains("/")) { return phoneme.Split("/")[0]; } return ""; diff --git a/OpenUtau.Core/DiffSinger/DiffSingerVariance.cs b/OpenUtau.Core/DiffSinger/DiffSingerVariance.cs index bd53d7f18..f34fd608e 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerVariance.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerVariance.cs @@ -4,22 +4,21 @@ using System.Linq; using System.Text; using K4os.Hash.xxHash; -using Serilog; using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; - using OpenUtau.Api; using OpenUtau.Core.Render; using OpenUtau.Core.Util; +using Serilog; -namespace OpenUtau.Core.DiffSinger{ - public struct VarianceResult{ +namespace OpenUtau.Core.DiffSinger { + public struct VarianceResult { public float[]? energy; public float[]? breathiness; public float[]? voicing; public float[]? tension; } - public class DsVariance : IDisposable{ + public class DsVariance : IDisposable { string rootPath; DsConfig dsConfig; Dictionary languageIds = new Dictionary(); @@ -36,18 +35,17 @@ public class DsVariance : IDisposable{ public float FrameMs => frameMs; - public DsVariance(string rootPath) - { + public DsVariance(string rootPath) { this.rootPath = rootPath; dsConfig = Yaml.DefaultDeserializer.Deserialize( File.ReadAllText(Path.Combine(rootPath, "dsconfig.yaml"), Encoding.UTF8)); - if(dsConfig.variance == null){ + if (dsConfig.variance == null) { throw new Exception("This voicebank doesn't contain a variance model"); } //Load language id if needed - if(dsConfig.use_lang_id){ - if(dsConfig.languages == null){ + if (dsConfig.use_lang_id) { + if (dsConfig.languages == null) { throw new Exception("\"languages\" field is not specified in dsconfig.yaml"); } var langIdPath = Path.Join(rootPath, dsConfig.languages); @@ -84,32 +82,32 @@ public DsVariance(string rootPath) protected IG2p LoadG2p(string rootPath) { // Load dictionary from singer folder. string file = Path.Combine(rootPath, "dsdict.yaml"); - if(!File.Exists(file)){ + if (!File.Exists(file)) { throw new Exception($"File not found: {file}"); } var g2pBuilder = G2pDictionary.NewBuilder().Load(File.ReadAllText(file)); //SP and AP should always be vowel g2pBuilder.AddSymbol("SP", true); g2pBuilder.AddSymbol("AP", true); - return g2pBuilder.Build(); + return g2pBuilder.Build(); } - public DiffSingerSpeakerEmbedManager getSpeakerEmbedManager(){ - if(speakerEmbedManager is null) { + public DiffSingerSpeakerEmbedManager getSpeakerEmbedManager() { + if (speakerEmbedManager is null) { speakerEmbedManager = new DiffSingerSpeakerEmbedManager(dsConfig, rootPath); } return speakerEmbedManager; } - int PhonemeTokenize(string phoneme){ + int PhonemeTokenize(string phoneme) { bool success = phonemeTokens.TryGetValue(phoneme, out int token); - if(!success){ + if (!success) { throw new Exception($"Phoneme \"{phoneme}\" isn't supported by variance model. Please check {Path.Combine(rootPath, dsConfig.phonemes)}"); } return token; } - public VarianceResult Process(RenderPhrase phrase){ + public VarianceResult Process(RenderPhrase phrase) { int headFrames = (int)Math.Round(headMs / frameMs); int tailFrames = (int)Math.Round(tailMs / frameMs); if (dsConfig.predict_dur) { @@ -137,22 +135,22 @@ public VarianceResult Process(RenderPhrase phrase){ linguisticInputs.Add(NamedOnnxValue.CreateFromTensor("tokens", new DenseTensor(tokens, new int[] { tokens.Length }, false) .Reshape(new int[] { 1, tokens.Length }))); - if(dsConfig.predict_dur){ + if (dsConfig.predict_dur) { //if predict_dur is true, use word encode mode - var vowelIds = Enumerable.Range(0,phrase.phones.Length) - .Where(i=>g2p.IsVowel(phrase.phones[i].phoneme)) + var vowelIds = Enumerable.Range(0, phrase.phones.Length) + .Where(i => g2p.IsVowel(phrase.phones[i].phoneme)) .ToArray(); - if(vowelIds.Length == 0){ - vowelIds = new int[]{phrase.phones.Length-1}; + if (vowelIds.Length == 0) { + vowelIds = new int[] { phrase.phones.Length - 1 }; } - var word_div = vowelIds.Zip(vowelIds.Skip(1),(a,b)=>(Int64)(b-a)) + var word_div = vowelIds.Zip(vowelIds.Skip(1), (a, b) => (Int64)(b - a)) .Prepend(vowelIds[0] + 1) .Append(phrase.phones.Length - vowelIds[^1] + 1) .ToArray(); var word_dur = vowelIds.Zip(vowelIds.Skip(1), - (a,b)=>(Int64)(phrase.phones[b-1].endMs/frameMs) - (Int64)(phrase.phones[a].positionMs/frameMs)) - .Prepend((Int64)(phrase.phones[vowelIds[0]].positionMs/frameMs) - (Int64)(phrase.phones[0].positionMs/frameMs) + headFrames) - .Append((Int64)(phrase.notes[^1].endMs/frameMs) - (Int64)(phrase.phones[vowelIds[^1]].positionMs/frameMs) + tailFrames) + (a, b) => (Int64)(phrase.phones[b - 1].endMs / frameMs) - (Int64)(phrase.phones[a].positionMs / frameMs)) + .Prepend((Int64)(phrase.phones[vowelIds[0]].positionMs / frameMs) - (Int64)(phrase.phones[0].positionMs / frameMs) + headFrames) + .Append((Int64)(phrase.notes[^1].endMs / frameMs) - (Int64)(phrase.phones[vowelIds[^1]].positionMs / frameMs) + tailFrames) .ToArray(); linguisticInputs.Add(NamedOnnxValue.CreateFromTensor("word_div", new DenseTensor(word_div, new int[] { word_div.Length }, false) @@ -160,17 +158,17 @@ public VarianceResult Process(RenderPhrase phrase){ linguisticInputs.Add(NamedOnnxValue.CreateFromTensor("word_dur", new DenseTensor(word_dur, new int[] { word_dur.Length }, false) .Reshape(new int[] { 1, word_dur.Length }))); - }else{ + } else { //if predict_dur is false, use phoneme encode mode linguisticInputs.Add(NamedOnnxValue.CreateFromTensor("ph_dur", - new DenseTensor(ph_dur.Select(x=>(Int64)x).ToArray(), new int[] { ph_dur.Length }, false) + new DenseTensor(ph_dur.Select(x => (Int64)x).ToArray(), new int[] { ph_dur.Length }, false) .Reshape(new int[] { 1, ph_dur.Length }))); } //Language id - if(dsConfig.use_lang_id){ + if (dsConfig.use_lang_id) { var langIdByPhone = phrase.phones .Select(p => (long)languageIds.GetValueOrDefault( - DiffSingerUtils.PhonemeLanguage(p.phoneme),0 + DiffSingerUtils.PhonemeLanguage(p.phoneme), 0 )) .Prepend(0) .Append(0) @@ -196,7 +194,7 @@ public VarianceResult Process(RenderPhrase phrase){ .AsTensor(); //Variance Predictor - var pitch = DiffSingerUtils.SampleCurve(phrase, phrase.pitches, 0, frameMs, totalFrames, headFrames, tailFrames, + var pitch = DiffSingerUtils.SampleCurve(phrase, phrase.pitches, 0, frameMs, totalFrames, headFrames, tailFrames, x => x * 0.01).Select(f => (float)f).ToArray(); var toneShift = DiffSingerUtils.SampleCurve(phrase, phrase.toneShift, 0, frameMs, totalFrames, headFrames, tailFrames, x => x * 0.01).Select(f => (float)f).ToArray(); @@ -205,7 +203,7 @@ public VarianceResult Process(RenderPhrase phrase){ var varianceInputs = new List(); varianceInputs.Add(NamedOnnxValue.CreateFromTensor("encoder_out", encoder_out)); varianceInputs.Add(NamedOnnxValue.CreateFromTensor("ph_dur", - new DenseTensor(ph_dur.Select(x=>(Int64)x).ToArray(), new int[] { ph_dur.Length }, false) + new DenseTensor(ph_dur.Select(x => (Int64)x).ToArray(), new int[] { ph_dur.Length }, false) .Reshape(new int[] { 1, ph_dur.Length }))); varianceInputs.Add(NamedOnnxValue.CreateFromTensor("pitch", new DenseTensor(pitch, new int[] { pitch.Length }, false) @@ -256,10 +254,10 @@ public VarianceResult Process(RenderPhrase phrase){ speedup--; } varianceInputs.Add(NamedOnnxValue.CreateFromTensor("speedup", - new DenseTensor(new long[] { speedup }, new int[] { 1 },false))); + new DenseTensor(new long[] { speedup }, new int[] { 1 }, false))); } //Speaker - if(dsConfig.speakers != null) { + if (dsConfig.speakers != null) { var speakerEmbedManager = getSpeakerEmbedManager(); var spkEmbedTensor = speakerEmbedManager.PhraseSpeakerEmbedByFrame(phrase, ph_dur, frameMs, totalFrames, headFrames, tailFrames); varianceInputs.Add(NamedOnnxValue.CreateFromTensor("spk_embed", spkEmbedTensor)); @@ -298,7 +296,7 @@ public VarianceResult Process(RenderPhrase phrase){ .First() .AsTensor() : null; - return new VarianceResult{ + return new VarianceResult { energy = energy_pred?.ToArray(), breathiness = breathiness_pred?.ToArray(), voicing = voicing_pred?.ToArray(), diff --git a/OpenUtau.Core/DiffSinger/DiffSingerVocoder.cs b/OpenUtau.Core/DiffSinger/DiffSingerVocoder.cs index a56cd1ce9..5b229d865 100644 --- a/OpenUtau.Core/DiffSinger/DiffSingerVocoder.cs +++ b/OpenUtau.Core/DiffSinger/DiffSingerVocoder.cs @@ -30,8 +30,7 @@ public DsVocoder(string name) { File.ReadAllText(Path.Combine(Location, "vocoder.yaml"), System.Text.Encoding.UTF8)); model = File.ReadAllBytes(Path.Combine(Location, config.model)); - } - catch (Exception ex) { + } catch (Exception ex) { throw new MessageCustomizableException( $"Error loading vocoder \"{name}\"", $"", diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerARPAPlusEnglishPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerARPAPlusEnglishPhonemizer.cs index 0777a5b1d..b0384c59e 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerARPAPlusEnglishPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerARPAPlusEnglishPhonemizer.cs @@ -116,7 +116,7 @@ private bool ShouldReplacePhoneme(string phoneme, Note? prev, Note? next, Note? return true; } - return false; + return false; } } diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerChinesePhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerChinesePhonemizer.cs index 42a013619..a41f51c74 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerChinesePhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerChinesePhonemizer.cs @@ -5,8 +5,8 @@ namespace OpenUtau.Core.DiffSinger { [Phonemizer("DiffSinger Chinese Phonemizer", "DIFFS ZH", language: "ZH")] public class DiffSingerChinesePhonemizer : DiffSingerBasePhonemizer { - protected override string GetDictionaryName()=>"dsdict-zh.yaml"; - public override string GetLangCode()=>"zh"; + protected override string GetDictionaryName() => "dsdict-zh.yaml"; + public override string GetLangCode() => "zh"; protected override string[] Romanize(IEnumerable lyrics) { return BaseChinesePhonemizer.Romanize(lyrics); } diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerEnglishPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerEnglishPhonemizer.cs index de968c363..e400820f9 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerEnglishPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerEnglishPhonemizer.cs @@ -1,22 +1,20 @@ -using OpenUtau.Api; +using OpenUtau.Api; using OpenUtau.Core.G2p; -namespace OpenUtau.Core.DiffSinger -{ +namespace OpenUtau.Core.DiffSinger { [Phonemizer("DiffSinger English Phonemizer", "DIFFS EN", language: "EN")] - public class DiffSingerEnglishPhonemizer : DiffSingerG2pPhonemizer - { - protected override string GetDictionaryName()=>"dsdict-en.yaml"; - public override string GetLangCode()=>"en"; + public class DiffSingerEnglishPhonemizer : DiffSingerG2pPhonemizer { + protected override string GetDictionaryName() => "dsdict-en.yaml"; + public override string GetLangCode() => "en"; protected override IG2p LoadBaseG2p() => new ArpabetG2p(); protected override string[] GetBaseG2pVowels() => new string[] { - "aa", "ae", "ah", "ao", "aw", "ay", "eh", "er", + "aa", "ae", "ah", "ao", "aw", "ay", "eh", "er", "ey", "ih", "iy", "ow", "oy", "uh", "uw" }; protected override string[] GetBaseG2pConsonants() => new string[] { - "b", "ch", "d", "dh", "f", "g", "hh", "jh", "k", "l", "m", "n", + "b", "ch", "d", "dh", "f", "g", "hh", "jh", "k", "l", "m", "n", "ng", "p", "r", "s", "sh", "t", "th", "v", "w", "y", "z", "zh" }; } -} \ No newline at end of file +} diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerG2pPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerG2pPhonemizer.cs index c1648c335..1fb9415c9 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerG2pPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerG2pPhonemizer.cs @@ -1,25 +1,23 @@ -using Serilog; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; - using OpenUtau.Api; using OpenUtau.Classic; +using Serilog; -namespace OpenUtau.Core.DiffSinger -{ - class DiffSingerG2pDictionaryData : G2pDictionaryData{ - public struct Replacement{ +namespace OpenUtau.Core.DiffSinger { + class DiffSingerG2pDictionaryData : G2pDictionaryData { + public struct Replacement { public string from; public string to; } public Replacement[]? replacements; - public Dictionary replacementsDict(){ + public Dictionary replacementsDict() { var dict = new Dictionary(); - if(replacements!=null){ - foreach(var r in replacements){ + if (replacements != null) { + foreach (var r in replacements) { dict[r.from] = r.to; } } @@ -30,12 +28,11 @@ public Dictionary replacementsDict(){ /// /// Base class for DiffSinger phonemizers based on OpenUtau's builtin G2p. /// - public abstract class DiffSingerG2pPhonemizer : DiffSingerBasePhonemizer - { - protected virtual IG2p LoadBaseG2p()=>null; + public abstract class DiffSingerG2pPhonemizer : DiffSingerBasePhonemizer { + protected virtual IG2p LoadBaseG2p() => null; //vowels and consonants of BaseG2p - protected virtual string[] GetBaseG2pVowels()=>new string[]{}; - protected virtual string[] GetBaseG2pConsonants()=>new string[]{}; + protected virtual string[] GetBaseG2pVowels() => new string[] { }; + protected virtual string[] GetBaseG2pConsonants() => new string[] { }; private Dictionary phonemeSymbols = new Dictionary(); protected bool HasPhoneme(string phoneme) { @@ -46,13 +43,13 @@ protected override IG2p LoadG2p(string rootPath, bool useLangId = false) { //Each phonemizer has a delicated dictionary name, such as dsdict-en.yaml, dsdict-ru.yaml. //If this dictionary exists, load it. //If not, load dsdict.yaml. - var dictionaryNames = new string[] {GetDictionaryName(), "dsdict.yaml"}; + var dictionaryNames = new string[] { GetDictionaryName(), "dsdict.yaml" }; var g2ps = new List(); // Load dictionary from singer folder. G2pDictionary.Builder g2pBuilder = new G2pDictionary.Builder(); - var replacements = new Dictionary(); - foreach(var dictionaryName in dictionaryNames){ + var replacements = new Dictionary(); + foreach (var dictionaryName in dictionaryNames) { string dictionaryPath = Path.Combine(rootPath, dictionaryName); if (File.Exists(dictionaryPath)) { try { @@ -80,31 +77,31 @@ protected override IG2p LoadG2p(string rootPath, bool useLangId = false) { // Load base g2p. var baseG2p = LoadBaseG2p(); - if(baseG2p == null){ + if (baseG2p == null) { return new G2pFallbacks(g2ps.ToArray()); } - foreach(var v in GetBaseG2pVowels()){ - phonemeSymbols[v]=true; + foreach (var v in GetBaseG2pVowels()) { + phonemeSymbols[v] = true; } - foreach(var c in GetBaseG2pConsonants()){ - phonemeSymbols[c]=false; + foreach (var c in GetBaseG2pConsonants()) { + phonemeSymbols[c] = false; } - if(useLangId){ + if (useLangId) { //For diffsinger multi dict voicebanks, the replacements of g2p phonemes default to the / var langCode = GetLangCode(); - foreach(var ph in GetBaseG2pVowels().Concat(GetBaseG2pConsonants())){ - if(!replacements.ContainsKey(ph)){ - replacements[ph]=langCode + "/" + ph; + foreach (var ph in GetBaseG2pVowels().Concat(GetBaseG2pConsonants())) { + if (!replacements.ContainsKey(ph)) { + replacements[ph] = langCode + "/" + ph; } } } - foreach(var from in replacements.Keys){ + foreach (var from in replacements.Keys) { var to = replacements[from]; - if(baseG2p.IsValidSymbol(to)){ - if(baseG2p.IsVowel(to)){ - phonemeSymbols[from]=true; - }else{ - phonemeSymbols[from]=false; + if (baseG2p.IsValidSymbol(to)) { + if (baseG2p.IsVowel(to)) { + phonemeSymbols[from] = true; + } else { + phonemeSymbols[from] = false; } } } diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerGermanPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerGermanPhonemizer.cs index 3b1b531d0..3fde5ac00 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerGermanPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerGermanPhonemizer.cs @@ -1,13 +1,11 @@ -using OpenUtau.Api; +using OpenUtau.Api; using OpenUtau.Core.G2p; -namespace OpenUtau.Core.DiffSinger -{ +namespace OpenUtau.Core.DiffSinger { [Phonemizer("DiffSinger German Phonemizer", "DIFFS DE", language: "DE")] - public class DiffSingerGermanPhonemizer : DiffSingerG2pPhonemizer - { - protected override string GetDictionaryName()=>"dsdict-de.yaml"; - public override string GetLangCode()=>"de"; + public class DiffSingerGermanPhonemizer : DiffSingerG2pPhonemizer { + protected override string GetDictionaryName() => "dsdict-de.yaml"; + public override string GetLangCode() => "de"; protected override IG2p LoadBaseG2p() => new GermanG2p(); protected override string[] GetBaseG2pVowels() => new string[] { "aa", "ae", "ah", "ao", "aw", "ax", "ay", "ee", "eh", "er", "ex", "ih", "iy", "oe", "ohh", "ooh", "oy", "ue", "uh", "uw", "yy" diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerItalianPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerItalianPhonemizer.cs index 68500a16a..502a1b820 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerItalianPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerItalianPhonemizer.cs @@ -5,7 +5,7 @@ namespace OpenUtau.Core.DiffSinger { [Phonemizer("DiffSinger Italian Phonemizer", "DIFFS IT", language: "IT")] public class DiffSingerItalianPhonemizer : DiffSingerG2pPhonemizer { protected override string GetDictionaryName() => "dsdict-it.yaml"; - public override string GetLangCode()=>"it"; + public override string GetLangCode() => "it"; protected override IG2p LoadBaseG2p() => new ItalianG2p(); protected override string[] GetBaseG2pVowels() => new string[] { "a", "a1", "e", "e1", "EE", "i", "i1", "o", "o1", "OO", "u", "u1" diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanG2PPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanG2PPhonemizer.cs index 6ab2d8b5c..0fc272083 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanG2PPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanG2PPhonemizer.cs @@ -1,13 +1,11 @@ using OpenUtau.Api; using OpenUtau.Core.G2p; -namespace OpenUtau.Core.DiffSinger -{ +namespace OpenUtau.Core.DiffSinger { [Phonemizer("DiffSinger Korean G2P Phonemizer", "DIFFS KO", language: "KO", author: "Cardroid6")] - public class DiffSingerKoreanG2PPhonemizer : DiffSingerG2pPhonemizer - { + public class DiffSingerKoreanG2PPhonemizer : DiffSingerG2pPhonemizer { protected override string GetDictionaryName() => "dsdict-ko.yaml"; - public override string GetLangCode()=>"ko"; + public override string GetLangCode() => "ko"; protected override IG2p LoadBaseG2p() => new KoreanG2p(); protected override string[] GetBaseG2pVowels() => new string[] { "a", "e", "eo", "eu", "i", "o", "u", "w", "y" diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanPhonemizer.cs index e28cd1d46..ee36bc973 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerKoreanPhonemizer.cs @@ -1,15 +1,13 @@ +using System.Collections.Generic; +using System.Linq; using OpenUtau.Api; using OpenUtau.Core.Ustx; -using System.Collections.Generic; -using System.Linq; -namespace OpenUtau.Core.DiffSinger -{ - [Phonemizer("DiffSinger Korean Phonemizer", "DIFFS KO","EX3", language:"KO")] - public class DiffSingerKoreanPhonemizer : DiffSingerBasePhonemizer - { - protected override string GetDictionaryName()=>"dsdict-ko.yaml"; - public override string GetLangCode()=>"ko"; +namespace OpenUtau.Core.DiffSinger { + [Phonemizer("DiffSinger Korean Phonemizer", "DIFFS KO", "EX3", language: "KO")] + public class DiffSingerKoreanPhonemizer : DiffSingerBasePhonemizer { + protected override string GetDictionaryName() => "dsdict-ko.yaml"; + public override string GetLangCode() => "ko"; public override void SetUp(Note[][] groups, UProject project, UTrack track) { if (groups.Length == 0) { diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerPhonemizer.cs index 762dd7b2a..59ca0b89f 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerPhonemizer.cs @@ -1,9 +1,7 @@ -using OpenUtau.Api; +using OpenUtau.Api; -namespace OpenUtau.Core.DiffSinger -{ +namespace OpenUtau.Core.DiffSinger { [Phonemizer("DiffSinger Phonemizer", "DIFFS")] - public class DiffSingerPhonemizer : DiffSingerBasePhonemizer - { + public class DiffSingerPhonemizer : DiffSingerBasePhonemizer { } } diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerPortuguesePhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerPortuguesePhonemizer.cs index 8d5a148ee..15f1f36c7 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerPortuguesePhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerPortuguesePhonemizer.cs @@ -1,20 +1,18 @@ -using OpenUtau.Api; +using OpenUtau.Api; using OpenUtau.Core.G2p; -namespace OpenUtau.Core.DiffSinger -{ +namespace OpenUtau.Core.DiffSinger { [Phonemizer("DiffSinger Portuguese Phonemizer", "DIFFS PT", language: "PT")] - public class DiffSingerPortuguesePhonemizer : DiffSingerG2pPhonemizer - { - protected override string GetDictionaryName()=>"dsdict-pt.yaml"; - public override string GetLangCode()=>"pt"; + public class DiffSingerPortuguesePhonemizer : DiffSingerG2pPhonemizer { + protected override string GetDictionaryName() => "dsdict-pt.yaml"; + public override string GetLangCode() => "pt"; protected override IG2p LoadBaseG2p() => new PortugueseG2p(); protected override string[] GetBaseG2pVowels() => new string[] { "E", "O", "a", "a~", "e", "e~", "i", "i~", "o", "o~", "u", "u~" }; protected override string[] GetBaseG2pConsonants() => new string[] { - "J", "L", "R", "S", "X", "Z", "b", "d", "dZ", "f", "g", "j", "j~", + "J", "L", "R", "S", "X", "Z", "b", "d", "dZ", "f", "g", "j", "j~", "k", "l", "m", "n", "p", "r", "s", "t", "tS", "v", "w", "w~", "z" }; } diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerRhythmizerPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerRhythmizerPhonemizer.cs index fc6133d38..5431fa847 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerRhythmizerPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerRhythmizerPhonemizer.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; -using System.IO; using OpenUtau.Api; using OpenUtau.Core.Ustx; -using System.Text; -using System.Linq; namespace OpenUtau.Core.DiffSinger { @@ -68,7 +68,7 @@ public class DiffSingerRhythmizerPhonemizer : MachineLearningPhonemizer { USinger singer; DsRhythmizer rhythmizer; Dictionary phoneDict; - + public override void SetSinger(USinger singer) { if (this.singer == singer) { return; @@ -81,9 +81,9 @@ public override void SetSinger(USinger singer) { try { //if rhythmizer is packed within the voicebank var packedRhythmizerPath = Path.Combine(singer.Location, "rhythmizer"); - if(Directory.Exists(packedRhythmizerPath)) { + if (Directory.Exists(packedRhythmizerPath)) { rhythmizer = new DsRhythmizer(packedRhythmizerPath); - } else { + } else { string rhythmizerName; string rhythmizerYamlPath = Path.Combine(singer.Location, "dsrhythmizer.yaml"); if (File.Exists(rhythmizerYamlPath)) { @@ -92,7 +92,7 @@ public override void SetSinger(USinger singer) { } else { rhythmizerName = DsRhythmizer.DefaultRhythmizer; } - rhythmizer = DsRhythmizer.FromName(rhythmizerName); + rhythmizer = DsRhythmizer.FromName(rhythmizerName); } //Load pinyin to phoneme dictionary from rhythmizer package phoneDict = rhythmizer.phoneDict; @@ -110,17 +110,17 @@ protected override void ProcessPart(Note[][] phrase) { var midi_dur = new List { padding };//List of parent note duration for each phoneme var is_slur = new List { false };//Whether the phoneme is slur List ph_dur;//Phoneme durations output by the model - var notePhIndex = new List{ 1 };//The position of the first phoneme of each note in the phoneme list + var notePhIndex = new List { 1 };//The position of the first phoneme of each note in the phoneme list var phAlignPoints = new List>();//Phoneme alignment position, s, absolute time double offsetMs = timeAxis.TickPosToMsPos(phrase[0][0].position); //Convert note list to phoneme list - foreach (int groupIndex in Enumerable.Range(0,phrase.Length)) { + foreach (int groupIndex in Enumerable.Range(0, phrase.Length)) { string[] notePhonemes; Note[] group = phrase[groupIndex]; if (group[0].phoneticHint is null) { var lyric = group[0].lyric; - + if (phoneDict.ContainsKey(lyric)) { notePhonemes = phoneDict[lyric]; } else { @@ -130,7 +130,7 @@ protected override void ProcessPart(Note[][] phrase) { notePhonemes = group[0].phoneticHint.Split(" "); } is_slur.AddRange(Enumerable.Repeat(false, notePhonemes.Length)); - phAlignPoints.Add(new Tuple( + phAlignPoints.Add(new Tuple( phonemes.Count + (notePhonemes.Length > 1 ? 1 : 0),//TODO timeAxis.TickPosToMsPos(group[0].position) / 1000 )); @@ -177,23 +177,23 @@ protected override void ProcessPart(Note[][] phrase) { //The other phonemes are scaled according to the ratio of the time difference //between the two alignment points and the duration of the phoneme //pairwise(alignGroups) - foreach(var pair in phAlignPoints.Zip(phAlignPoints.Skip(1), (a, b) => Tuple.Create(a, b))){ + foreach (var pair in phAlignPoints.Zip(phAlignPoints.Skip(1), (a, b) => Tuple.Create(a, b))) { var currAlignPoint = pair.Item1; var nextAlignPoint = pair.Item2; alignGroup = ph_dur.GetRange(currAlignPoint.Item1, nextAlignPoint.Item1 - currAlignPoint.Item1); - double ratio = (nextAlignPoint.Item2 - currAlignPoint.Item2)/alignGroup.Sum(); + double ratio = (nextAlignPoint.Item2 - currAlignPoint.Item2) / alignGroup.Sum(); positions.AddRange(stretch(alignGroup, ratio, nextAlignPoint.Item2)); } //Convert the position sequence to tick and fill into the result list int index = 1; - foreach(int groupIndex in Enumerable.Range(0, phrase.Length)) { + foreach (int groupIndex in Enumerable.Range(0, phrase.Length)) { Note[] group = phrase[groupIndex]; var noteResult = new List>(); if (group[0].lyric.StartsWith("+")) { continue; } double notePos = timeAxis.TickPosToMsPos(group[0].position);//音符起点位置,单位ms - for(int phIndex = notePhIndex[groupIndex]; phIndex < notePhIndex[groupIndex + 1]; ++phIndex) { + for (int phIndex = notePhIndex[groupIndex]; phIndex < notePhIndex[groupIndex + 1]; ++phIndex) { noteResult.Add(Tuple.Create(phonemes[phIndex], timeAxis.TicksBetweenMsPos( notePos, positions[phIndex] * 1000))); } @@ -208,7 +208,7 @@ public static IEnumerable CumulativeSum(IEnumerable sequence, do yield return sum; } } - + //Stretch phoneme duration sequence with a certain ratio public List stretch(IList source, double ratio, double endPos) { //source: phoneme duration sequence, unit: s @@ -216,7 +216,7 @@ public List stretch(IList source, double ratio, double endPos) { //endPos: target end time, unit: s //output: scaled phoneme position, unit: s double startPos = endPos - source.Sum() * ratio; - var result = CumulativeSum(source.Select(x => x * ratio).Prepend(0),startPos).ToList(); + var result = CumulativeSum(source.Select(x => x * ratio).Prepend(0), startPos).ToList(); result.RemoveAt(result.Count - 1); return result; } diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerRussianPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerRussianPhonemizer.cs index 788a8ac3a..ff0b5414e 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerRussianPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerRussianPhonemizer.cs @@ -1,13 +1,11 @@ -using OpenUtau.Api; +using OpenUtau.Api; using OpenUtau.Core.G2p; -namespace OpenUtau.Core.DiffSinger -{ +namespace OpenUtau.Core.DiffSinger { [Phonemizer("DiffSinger Russian Phonemizer", "DIFFS RU", language: "RU")] - public class DiffSingerRussianPhonemizer : DiffSingerG2pPhonemizer - { - protected override string GetDictionaryName()=>"dsdict-ru.yaml"; - public override string GetLangCode()=>"ru"; + public class DiffSingerRussianPhonemizer : DiffSingerG2pPhonemizer { + protected override string GetDictionaryName() => "dsdict-ru.yaml"; + public override string GetLangCode() => "ru"; protected override IG2p LoadBaseG2p() => new RussianG2p(); protected override string[] GetBaseG2pVowels() => new string[] { "a", "aa", "ay", "ee", "i", "ii", "ja", "je", "jo", "ju", "oo", @@ -16,7 +14,7 @@ public class DiffSingerRussianPhonemizer : DiffSingerG2pPhonemizer protected override string[] GetBaseG2pConsonants() => new string[] { "b", "bb", "c", "ch", "d", "dd", "f", "ff", "g", "gg", "h", "hh", - "j", "k", "kk", "l", "ll", "m", "mm", "n", "nn", "p", "pp", "r", + "j", "k", "kk", "l", "ll", "m", "mm", "n", "nn", "p", "pp", "r", "rr", "s", "sch", "sh", "ss", "t", "tt", "v", "vv", "z", "zh", "zz" }; } diff --git a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerSpanishPhonemizer.cs b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerSpanishPhonemizer.cs index 7ec68e3cb..c13e52538 100644 --- a/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerSpanishPhonemizer.cs +++ b/OpenUtau.Core/DiffSinger/Phonemizers/DiffSingerSpanishPhonemizer.cs @@ -1,13 +1,11 @@ -using OpenUtau.Api; +using OpenUtau.Api; using OpenUtau.Core.G2p; -namespace OpenUtau.Core.DiffSinger -{ +namespace OpenUtau.Core.DiffSinger { [Phonemizer("DiffSinger Spanish Phonemizer", "DIFFS ES", language: "ES")] - public class DiffSingerSpanishPhonemizer : DiffSingerG2pPhonemizer - { - protected override string GetDictionaryName()=>"dsdict-es.yaml"; - public override string GetLangCode()=>"es"; + public class DiffSingerSpanishPhonemizer : DiffSingerG2pPhonemizer { + protected override string GetDictionaryName() => "dsdict-es.yaml"; + public override string GetLangCode() => "es"; protected override IG2p LoadBaseG2p() => new SpanishG2p(); protected override string[] GetBaseG2pVowels() => new string[] { "a", "e", "i", "o", "u" diff --git a/OpenUtau.Core/Editing/LyricBatchEdits.cs b/OpenUtau.Core/Editing/LyricBatchEdits.cs index 0d7676c32..ade08c998 100644 --- a/OpenUtau.Core/Editing/LyricBatchEdits.cs +++ b/OpenUtau.Core/Editing/LyricBatchEdits.cs @@ -30,8 +30,8 @@ public class RomajiToHiragana : SingleNoteLyricEdit { private WanaKanaOptions option = new WanaKanaOptions() { CustomKanaMapping = mapping }; public override string Name => "pianoroll.menu.lyrics.romajitohiragana"; protected override string Transform(string lyric) { - string hiragana = WanaKana.ToHiragana(lyric, option).Replace('ゔ','ヴ'); - if(Regex.IsMatch(hiragana, "[ぁ-んァ-ヴ]")) { + string hiragana = WanaKana.ToHiragana(lyric, option).Replace('ゔ', 'ヴ'); + if (Regex.IsMatch(hiragana, "[ぁ-んァ-ヴ]")) { return hiragana; } else { return lyric; @@ -112,7 +112,7 @@ public void Run(UProject project, UVoicePart part, List selectedNotes, Do string value = Regex.Replace(subbank.Suffix.Replace("_", ""), "[A-G](#|b)?[1-7]", ""); for (int i = 0; i < colors[clrIndex].Length && i < value.Length; i++) { - if(colors[clrIndex][i] == value[i]) { + if (colors[clrIndex][i] == value[i]) { suffix += value[i]; } else { break; @@ -171,7 +171,7 @@ protected override string Transform(string lyric) { } } - public class InsertSlur : BatchEdit{ + public class InsertSlur : BatchEdit { public virtual string Name => name; private string name; @@ -180,15 +180,15 @@ public InsertSlur() { } public void Run(UProject project, UVoicePart part, List selectedNotes, DocManager docManager) { - if(selectedNotes.Count == 0){ + if (selectedNotes.Count == 0) { return; } var startPos = selectedNotes.First().position; Queue lyricsQueue = new Queue(); docManager.StartUndoGroup(true); - foreach(var note in part.notes.Where(n => n.position >= startPos)){ + foreach (var note in part.notes.Where(n => n.position >= startPos)) { lyricsQueue.Enqueue(note.lyric); - if(selectedNotes.Contains(note)){ + if (selectedNotes.Contains(note)) { docManager.ExecuteCmd(new ChangeNoteLyricCommand(part, note, "+~")); } else { docManager.ExecuteCmd(new ChangeNoteLyricCommand(part, note, lyricsQueue.Dequeue())); diff --git a/OpenUtau.Core/Editing/NoteBatchEdits.cs b/OpenUtau.Core/Editing/NoteBatchEdits.cs index 3ee01ba96..415ea9543 100644 --- a/OpenUtau.Core/Editing/NoteBatchEdits.cs +++ b/OpenUtau.Core/Editing/NoteBatchEdits.cs @@ -316,7 +316,7 @@ public void RunAsync( var renderer = project.tracks[part.trackNo].RendererSettings.Renderer; if (renderer == null || !renderer.SupportsRenderPitch) { var e = new MessageCustomizableException( - "Current renderer doesn't support generating pitch curve", + "Current renderer doesn't support generating pitch curve", $"", new Exception()); DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(e)); diff --git a/OpenUtau.Core/Editing/ResetBatchEdits.cs b/OpenUtau.Core/Editing/ResetBatchEdits.cs index c6c4e9331..b3e269da9 100644 --- a/OpenUtau.Core/Editing/ResetBatchEdits.cs +++ b/OpenUtau.Core/Editing/ResetBatchEdits.cs @@ -5,38 +5,38 @@ using OpenUtau.Core.Util; namespace OpenUtau.Core.Editing { - class TickRange{ + class TickRange { public int start; public int end; - public TickRange(int start, int end){ + public TickRange(int start, int end) { this.start = start; this.end = end; } - public TickRange copy(){ + public TickRange copy() { return new TickRange(start, end); } } - static class SelectionUtils{ + static class SelectionUtils { /// /// Simplify the time selection by merging overlapping ranges. /// /// Time selection to be simplified /// - public static List SimplifyTimeSelection(List ranges){ + public static List SimplifyTimeSelection(List ranges) { var result = new List(); - if(ranges.Count == 0){ + if (ranges.Count == 0) { return result; } ranges.Sort((a, b) => a.start - b.start); var current = ranges[0].copy(); - for(int i = 1; i < ranges.Count; i++){ + for (int i = 1; i < ranges.Count; i++) { var next = ranges[i]; - if(next.start <= current.end){ + if (next.start <= current.end) { current.end = Math.Max(current.end, next.end); - }else{ + } else { result.Add(current); current = next; } @@ -44,20 +44,20 @@ public static List SimplifyTimeSelection(List ranges){ result.Add(current); return result; } - - public static Dictionary> NotePhonemes(UVoicePart part){ + + public static Dictionary> NotePhonemes(UVoicePart part) { var result = new Dictionary>(); - foreach(var phoneme in part.phonemes){ + foreach (var phoneme in part.phonemes) { var note = phoneme.Parent; - if(result.ContainsKey(note)){ + if (result.ContainsKey(note)) { result[note].Add(phoneme); - }else{ - result[note] = new List(){phoneme}; + } else { + result[note] = new List() { phoneme }; } } return result; } - + /// /// Get the tick ranges of the selected notes, relative to the beginning of the part. /// @@ -68,10 +68,10 @@ public static List SelectedTickRanges(UVoicePart part, List se var notePhonemes = NotePhonemes(part); var result = selectedNotes.Select(note => { int start = note.position; - if(note.Prev.End < note.position - && notePhonemes.TryGetValue(note, out var phonemes) + if (note.Prev.End < note.position + && notePhonemes.TryGetValue(note, out var phonemes) && phonemes.Count > 0 - ){ + ) { start = Math.Min(start, phonemes[0].position); } int end = note.End; @@ -120,23 +120,22 @@ public void Run(UProject project, UVoicePart part, List selectedNotes, Do } //reset curve expressions var curveAbbrs = part.curves.Select(c => c.abbr).ToArray(); - foreach (var abbr in curveAbbrs) { - if(notes.Count == part.notes.Count){ + foreach (var abbr in curveAbbrs) { + if (notes.Count == part.notes.Count) { //All notes are selected docManager.ExecuteCmd(new ClearCurveCommand(part, abbr)); - } - else{ + } else { var selectedTickRanges = SelectionUtils.SelectedTickRanges(part, notes); int defaultValue = (int)part.curves.First(c => c.abbr == abbr).descriptor.defaultValue; - foreach(var range in selectedTickRanges){ - docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, + foreach (var range in selectedTickRanges) { + docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, range.start, defaultValue, range.start, defaultValue)); - docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, - range.end, defaultValue, + docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, + range.end, defaultValue, range.end, defaultValue)); - docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, - range.start, defaultValue, + docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, + range.start, defaultValue, range.end, defaultValue)); } } @@ -285,23 +284,22 @@ public void Run(UProject project, UVoicePart part, List selectedNotes, Do } //curve expressions var curveAbbrs = part.curves.Select(c => c.abbr).ToArray(); - foreach (var abbr in curveAbbrs) { - if(notes.Count == part.notes.Count){ + foreach (var abbr in curveAbbrs) { + if (notes.Count == part.notes.Count) { //All notes are selected docManager.ExecuteCmd(new ClearCurveCommand(part, abbr)); - } - else{ + } else { var selectedTickRanges = SelectionUtils.SelectedTickRanges(part, notes); int defaultValue = (int)part.curves.First(c => c.abbr == abbr).descriptor.defaultValue; - foreach(var range in selectedTickRanges){ - docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, + foreach (var range in selectedTickRanges) { + docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, range.start, defaultValue, range.start, defaultValue)); - docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, - range.end, defaultValue, + docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, + range.end, defaultValue, range.end, defaultValue)); - docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, - range.start, defaultValue, + docManager.ExecuteCmd(new SetCurveCommand(project, part, abbr, + range.start, defaultValue, range.end, defaultValue)); } } diff --git a/OpenUtau.Core/Enunu/EnunuClient.cs b/OpenUtau.Core/Enunu/EnunuClient.cs index e939e0e3a..d5fd0f4ec 100644 --- a/OpenUtau.Core/Enunu/EnunuClient.cs +++ b/OpenUtau.Core/Enunu/EnunuClient.cs @@ -9,7 +9,7 @@ class EnunuClient : Util.SingletonBase { internal T SendRequest(string[] args) { return SendRequest(args, "15555"); } - internal T SendRequest(string[] args, string port,int second = 300 ) { + internal T SendRequest(string[] args, string port, int second = 300) { using (var client = new RequestSocket()) { client.Connect($"tcp://localhost:{port}"); string request = JsonConvert.SerializeObject(args); diff --git a/OpenUtau.Core/Enunu/EnunuConfig.cs b/OpenUtau.Core/Enunu/EnunuConfig.cs index 773a79632..851db7022 100644 --- a/OpenUtau.Core/Enunu/EnunuConfig.cs +++ b/OpenUtau.Core/Enunu/EnunuConfig.cs @@ -191,7 +191,7 @@ private void ParseEnunuStyleFormat(Dictionary enunuSty if (kvp.Key is string key) { if (kvp.Value is Dictionary innerDict) { foreach (var item in innerDict) { - if(item.Key is string key2) { + if (item.Key is string key2) { if (key2.Equals("format") && item.Value is string format) { dict.format = format; flag = true; diff --git a/OpenUtau.Core/Enunu/EnunuEnglishPhonemizer.cs b/OpenUtau.Core/Enunu/EnunuEnglishPhonemizer.cs index b53f67fc4..112baa44c 100644 --- a/OpenUtau.Core/Enunu/EnunuEnglishPhonemizer.cs +++ b/OpenUtau.Core/Enunu/EnunuEnglishPhonemizer.cs @@ -6,12 +6,12 @@ using K4os.Hash.xxHash; using OpenUtau.Api; using OpenUtau.Core.Editing; -using OpenUtau.Core.Ustx; using OpenUtau.Core.G2p; +using OpenUtau.Core.Ustx; using Serilog; namespace OpenUtau.Core.Enunu { - [Phonemizer("Enunu English Phonemizer", "ENUNU EN", "O3", language:"EN")] + [Phonemizer("Enunu English Phonemizer", "ENUNU EN", "O3", language: "EN")] public class EnunuEnglishPhonemizer : EnunuPhonemizer { readonly string PhonemizerType = "ENUNU EN"; @@ -23,7 +23,7 @@ protected IG2p LoadG2p() { var g2ps = new List(); // Load dictionary from plugin folder. - + string path = Path.Combine(PluginDir, "arpasing.yaml"); /* if (!File.Exists(path)) { @@ -76,7 +76,7 @@ string[] GetSymbols(Note note) { .ToArray(); } - protected EnunuNote[] MakeSimpleResult(string lyric,int length, int noteNum) { + protected EnunuNote[] MakeSimpleResult(string lyric, int length, int noteNum) { return new EnunuNote[]{new EnunuNote { lyric = lyric, length = length, @@ -107,7 +107,7 @@ protected EnunuNote[] ProcessWord(Note[] notes, int noteIndex) { // - "+n" manually aligns to n-th phoneme. alignments.Clear(); //notes except those whose lyrics start witn "+*" or "+~" - var nonExtensionNotes = notes.Where(n=>!IsSyllableVowelExtensionNote(n)).ToArray(); + var nonExtensionNotes = notes.Where(n => !IsSyllableVowelExtensionNote(n)).ToArray(); for (int i = 0; i < symbols.Length; i++) { if (isVowel[i] && alignments.Count < nonExtensionNotes.Length) { alignments.Add(Tuple.Create(i, nonExtensionNotes[alignments.Count].position - notes[0].position, false)); @@ -145,21 +145,21 @@ protected EnunuNote[] ProcessWord(Note[] notes, int noteIndex) { foreach (var alignment in alignments) { // Distributes phonemes between two aligment points. - EnunuNote enunuNote= new EnunuNote { + EnunuNote enunuNote = new EnunuNote { lyric = "", - length = alignment.Item2-startTick, + length = alignment.Item2 - startTick, noteNum = note.tone, noteIndex = noteIndex, }; - endIndex= alignment.Item1; + endIndex = alignment.Item1; - for(int index = startIndex; index < endIndex; index++) { + for (int index = startIndex; index < endIndex; index++) { enunuNote.lyric += symbols[index] + " "; } enunuNotes.Add(enunuNote); startIndex = endIndex; - + startTick = alignment.Item2; } alignments.Clear(); @@ -193,9 +193,9 @@ protected override EnunuNote[] NoteGroupsToEnunu(Note[][] notes) { if (lyric.Length > 0 && PinyinHelper.IsChinese(lyric[0])) { lyric = PinyinHelper.GetPinyin(lyric).ToLowerInvariant(); }*/ - var wordEnunuNotes = ProcessWord(notes[index],index); + var wordEnunuNotes = ProcessWord(notes[index], index); result.AddRange(wordEnunuNotes); - foreach(var enunuNote in wordEnunuNotes) { + foreach (var enunuNote in wordEnunuNotes) { position += enunuNote.length; } index++; diff --git a/OpenUtau.Core/Enunu/EnunuKoreanPhonemizer.cs b/OpenUtau.Core/Enunu/EnunuKoreanPhonemizer.cs index e7acd5481..38757f50f 100644 --- a/OpenUtau.Core/Enunu/EnunuKoreanPhonemizer.cs +++ b/OpenUtau.Core/Enunu/EnunuKoreanPhonemizer.cs @@ -10,13 +10,13 @@ using Serilog; namespace OpenUtau.Core.Enunu { - [Phonemizer("Enunu Korean Phonemizer", "ENUNU KO", "EX3", language:"KO")] + [Phonemizer("Enunu Korean Phonemizer", "ENUNU KO", "EX3", language: "KO")] public class EnunuKoreanPhonemizer : EnunuPhonemizer { readonly string PhonemizerType = "ENUNU KO"; public string semivowelSep; private KoreanENUNUSetting koreanENUNUSetting; // Manages Settings private bool isSeparateSemiVowels; // Nanages n y a or ny a - + /// /// Default KO ENUNU first consonants table /// @@ -166,7 +166,7 @@ public class EnunuKoreanPhonemizer : EnunuPhonemizer { {" ", new string[3]{"", "", BatchimType.NO_END.ToString()}}, {"null", new string[3]{"", "", BatchimType.PHONEME_IS_NULL.ToString()}} // 뒤 글자가 없을 때를 대비 }; - + struct TimingResult { public string path_full_timing; public string path_mono_timing; @@ -177,12 +177,12 @@ struct TimingResponse { public TimingResult result; } public override void SetSinger(USinger singer) { - if (singer.SingerType != USingerType.Enunu) {return;} + if (singer.SingerType != USingerType.Enunu) { return; } this.singer = singer as EnunuSinger; koreanENUNUSetting = new KoreanENUNUSetting("jamo_dict.yaml"); - + koreanENUNUSetting.Initialize(singer, "ko-ENUNU.ini", new Hashtable(){ { "SETTING", new Hashtable(){ @@ -193,7 +193,7 @@ public override void SetSinger(USinger singer) { ); isSeparateSemiVowels = koreanENUNUSetting.isSeparateSemiVowels; - semivowelSep = isSeparateSemiVowels ? " ": ""; + semivowelSep = isSeparateSemiVowels ? " " : ""; // Modify Phoneme Tables // First Consonants @@ -217,7 +217,7 @@ public override void SetSinger(USinger singer) { FirstConsonants["ㅍ"][0] = $"{koreanENUNUSetting.GetFirstConsonantPhoneme("ㅍ")}"; FirstConsonants["ㅎ"][0] = $"{koreanENUNUSetting.GetFirstConsonantPhoneme("ㅎ")}"; - + // Vowels MiddleVowels["ㅑ"][1] = koreanENUNUSetting.GetSemiVowelPhoneme("y"); MiddleVowels["ㅒ"][1] = koreanENUNUSetting.GetSemiVowelPhoneme("y"); @@ -253,8 +253,8 @@ public override void SetSinger(USinger singer) { MiddleVowels["ㅡ"][2] = $"{koreanENUNUSetting.GetPlainVowelPhoneme("ㅡ")}"; MiddleVowels["ㅢ"][2] = $"{koreanENUNUSetting.GetPlainVowelPhoneme("ㅣ")}"; // ㅢ는 ㅣ로 발음 MiddleVowels["ㅣ"][2] = $"{koreanENUNUSetting.GetPlainVowelPhoneme("ㅣ")}"; - - // final consonants + + // final consonants LastConsonants["ㄱ"][0] = $" {koreanENUNUSetting.GetFinalConsonantPhoneme("ㄱ")}"; LastConsonants["ㄲ"][0] = $" {koreanENUNUSetting.GetFinalConsonantPhoneme("ㄱ")}"; LastConsonants["ㄳ"][0] = $" {koreanENUNUSetting.GetFinalConsonantPhoneme("ㄱ")}"; @@ -284,7 +284,7 @@ public override void SetSinger(USinger singer) { LastConsonants["ㅎ"][0] = $" {koreanENUNUSetting.GetFinalConsonantPhoneme("ㄷ")}"; } - private class KoreanENUNUSetting : KoreanPhonemizerUtil.BaseIniManager{ + private class KoreanENUNUSetting : KoreanPhonemizerUtil.BaseIniManager { // uses KO-ENUNU.ini, jamo_dict.yaml public bool isSeparateSemiVowels; public string yamlFileName; @@ -296,21 +296,20 @@ protected override void IniSetUp(Hashtable iniFile) { // ko-ENUNU.ini + jamo_dict.yaml SetOrReadThisValue("SETTING", "Separate semivowels, like 'n y a'(otherwise 'ny a')", false, out var resultValue); // 반자음 떼기 유무 - 기본값 false isSeparateSemiVowels = resultValue; - + try { jamoDict = Yaml.DefaultDeserializer.Deserialize(File.ReadAllText(Path.Combine(singer.Location, yamlFileName))); if (jamoDict == null) { throw new IOException("yaml file is null"); } - } - catch (IOException e) { + } catch (IOException e) { Log.Error(e, $"Failed to read {Path.Combine(singer.Location, yamlFileName)}"); jamoDict = new KoreanPhonemizerUtil.JamoDictionary(firstDefaultConsonants.ToArray(), plainDefaultVowels.ToArray(), semiDefaultVowels.ToArray(), finalDefaultConsonants.ToArray()); File.WriteAllText(Path.Combine(singer.Location, yamlFileName), Yaml.DefaultSerializer.Serialize(jamoDict)); } - + } @@ -340,7 +339,7 @@ public string GetSemiVowelPhoneme(string Phoneme) { } return result.Trim(); } - + public string GetFinalConsonantPhoneme(string Phoneme) { KoreanPhonemizerUtil.JamoDictionary.FinalConsonantData results = jamoDict.finalConsonants.ToList().Find(c => c.grapheme == Phoneme); string result = results.phoneme; @@ -351,49 +350,49 @@ public string GetFinalConsonantPhoneme(string Phoneme) { } } - public enum ConsonantType{ - /// 예사소리 - NORMAL, - /// 거센소리 - ASPIRATE, - /// 된소리 - FORTIS, - /// 마찰음 - FRICATIVE, - /// 비음 - NASAL, - /// 유음 - LIQUID, - /// - H, - /// 자음의 음소값 없음(ㅇ) - NOCONSONANT, - /// 음소 자체가 없음 - PHONEME_IS_NULL - } - - /// - /// Last Consonant's type. - /// - public enum BatchimType{ - /// 예사소리 받침 - NORMAL_END, - /// 비음 받침 - NASAL_END, - /// 유음 받침 - LIQUID_END, - /// ㅇ받침 - NG_END, - /// ㅎ받침 - H_END, - /// 받침이 없음 - NO_END, - /// 음소 자체가 없음 - PHONEME_IS_NULL - } - + public enum ConsonantType { + /// 예사소리 + NORMAL, + /// 거센소리 + ASPIRATE, + /// 된소리 + FORTIS, + /// 마찰음 + FRICATIVE, + /// 비음 + NASAL, + /// 유음 + LIQUID, + /// + H, + /// 자음의 음소값 없음(ㅇ) + NOCONSONANT, + /// 음소 자체가 없음 + PHONEME_IS_NULL + } + + /// + /// Last Consonant's type. + /// + public enum BatchimType { + /// 예사소리 받침 + NORMAL_END, + /// 비음 받침 + NASAL_END, + /// 유음 받침 + LIQUID_END, + /// ㅇ받침 + NG_END, + /// ㅎ받침 + H_END, + /// 받침이 없음 + NO_END, + /// 음소 자체가 없음 + PHONEME_IS_NULL + } + Dictionary partResult = new Dictionary(); - + public override void SetUp(Note[][] notes, UProject project, UTrack track) { partResult.Clear(); if (notes.Length == 0 || singer == null || !singer.Found) { @@ -426,7 +425,7 @@ public override void SetUp(Note[][] notes, UProject project, UTrack track) { } }); } - + ulong HashNoteGroups(Note[][] notes, double bpm) { using (var stream = new MemoryStream()) { using (var writer = new BinaryWriter(stream)) { @@ -436,8 +435,8 @@ ulong HashNoteGroups(Note[][] notes, double bpm) { foreach (var ns in notes) { foreach (var n in ns) { writer.Write(n.lyric); - if(n.phoneticHint!= null) { - writer.Write("["+n.phoneticHint+"]"); + if (n.phoneticHint != null) { + writer.Write("[" + n.phoneticHint + "]"); } writer.Write(n.position); writer.Write(n.duration); @@ -488,7 +487,7 @@ protected override EnunuNote[] NoteGroupsToEnunu(Note[][] notes) { var result = new List(); int position = 0; int index = 0; - + while (index < notes.Length) { if (position < notes[index][0].position) { result.Add(new EnunuNote { @@ -516,10 +515,10 @@ protected override EnunuNote[] NoteGroupsToEnunu(Note[][] notes) { public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevs) { if (partResult.TryGetValue(notes, out var phonemes)) { var phonemes_ = phonemes.Select(p => { - double posMs = p.position * 0.1; - p.position = MsToTick(posMs) - notes[0].position; - return p; - }).ToArray(); + double posMs = p.position * 0.1; + p.position = MsToTick(posMs) - notes[0].position; + return p; + }).ToArray(); return new Result { phonemes = phonemes_, diff --git a/OpenUtau.Core/Enunu/EnunuPhonemizer.cs b/OpenUtau.Core/Enunu/EnunuPhonemizer.cs index ca56f492b..b7aaa0ae1 100644 --- a/OpenUtau.Core/Enunu/EnunuPhonemizer.cs +++ b/OpenUtau.Core/Enunu/EnunuPhonemizer.cs @@ -51,7 +51,7 @@ public override void SetUp(Note[][] notes, UProject project, UTrack track) { if (!File.Exists(scorePath) || !File.Exists(timingPath)) { Log.Information(this.singer.Name + ":" + voicebankNameHash); EnunuUtils.WriteUst(enunuNotes, bpm, singer, ustPath); - var response = EnunuClient.Inst.SendRequest(new string[] { "timing", ustPath,"", voicebankNameHash, "600" }, port); + var response = EnunuClient.Inst.SendRequest(new string[] { "timing", ustPath, "", voicebankNameHash, "600" }, port); if (response.error != null) { throw new Exception(response.error); } @@ -78,8 +78,8 @@ ulong HashNoteGroups(Note[][] notes, double bpm) { foreach (var ns in notes) { foreach (var n in ns) { writer.Write(n.lyric); - if(n.phoneticHint!= null) { - writer.Write("["+n.phoneticHint+"]"); + if (n.phoneticHint != null) { + writer.Write("[" + n.phoneticHint + "]"); } writer.Write(n.position); writer.Write(n.duration); diff --git a/OpenUtau.Core/Enunu/EnunuRenderer.cs b/OpenUtau.Core/Enunu/EnunuRenderer.cs index fdf634ab7..dded6af29 100644 --- a/OpenUtau.Core/Enunu/EnunuRenderer.cs +++ b/OpenUtau.Core/Enunu/EnunuRenderer.cs @@ -273,7 +273,7 @@ static EnunuNote[] PhraseToEnunuNotes(RenderPhrase phrase, EnunuConfig config) { datas.Add(matchingFlag.Item2.ToString()); } } - if (i > 2 && datas.Count == (i-1)) { + if (i > 2 && datas.Count == (i - 1)) { part += String.Format(styleFormats.format, datas.ToArray()); } else { Log.Warning($"Invalid format for {key}: {styleFormats.format}"); diff --git a/OpenUtau.Core/Enunu/EnunuSinger.cs b/OpenUtau.Core/Enunu/EnunuSinger.cs index eaf488f6c..1c39b9953 100644 --- a/OpenUtau.Core/Enunu/EnunuSinger.cs +++ b/OpenUtau.Core/Enunu/EnunuSinger.cs @@ -105,7 +105,7 @@ void Load() { subbanks.Clear(); if (voicebank.Subbanks == null || voicebank.Subbanks.Count == 0 || - voicebank.Subbanks.Count == 1 && string.IsNullOrEmpty(voicebank.Subbanks[0].Color) + voicebank.Subbanks.Count == 1 && string.IsNullOrEmpty(voicebank.Subbanks[0].Color) && !enuconfig.unLoadSubBanks) { subbanks.Add(new USubbank(new Subbank() { Prefix = string.Empty, diff --git a/OpenUtau.Core/Enunu/EnunuUtils.cs b/OpenUtau.Core/Enunu/EnunuUtils.cs index b7963fe97..972e2920e 100644 --- a/OpenUtau.Core/Enunu/EnunuUtils.cs +++ b/OpenUtau.Core/Enunu/EnunuUtils.cs @@ -58,12 +58,12 @@ internal static void WriteUst(IList notes, double tempo, USinger sing } internal static string SetPortNum() { - var ver_response = EnunuClient.Inst.SendRequest(new string[] { "ver_check" }, "15556", 1); - if (ver_response.error != null) { - Log.Error(ver_response.error); - } else if (ver_response.result.name != null) { - return "15556"; - } + var ver_response = EnunuClient.Inst.SendRequest(new string[] { "ver_check" }, "15556", 1); + if (ver_response.error != null) { + Log.Error(ver_response.error); + } else if (ver_response.result.name != null) { + return "15556"; + } return "15555"; } } diff --git a/OpenUtau.Core/Format/Formats.cs b/OpenUtau.Core/Format/Formats.cs index 672fa1f84..65d444bf8 100644 --- a/OpenUtau.Core/Format/Formats.cs +++ b/OpenUtau.Core/Format/Formats.cs @@ -48,7 +48,7 @@ public static ProjectFormats DetectProjectFormat(string file) { /// Read project from files to a new UProject object, used by LoadProject and ImportTracks. /// /// Names of the files to be loaded - public static UProject? ReadProject(string[] files){ + public static UProject? ReadProject(string[] files) { if (files.Length < 1) { return null; } @@ -97,7 +97,7 @@ public static void LoadProject(string[] files) { /// /// Names of the files to be loaded /// - public static UProject[] ReadProjects(string[] files){ + public static UProject[] ReadProjects(string[] files) { if (files == null || files.Length < 1) { return new UProject[0]; } @@ -122,7 +122,7 @@ public static void RecoveryProject(string[] files) { project.FilePath = string.Empty; project.Saved = false; } - + DocManager.Inst.ExecuteCmd(new LoadProjectNotification(project)); } } diff --git a/OpenUtau.Core/Format/MidiWriter.cs b/OpenUtau.Core/Format/MidiWriter.cs index e2681b3ba..b1c944c58 100644 --- a/OpenUtau.Core/Format/MidiWriter.cs +++ b/OpenUtau.Core/Format/MidiWriter.cs @@ -1,13 +1,13 @@ -using Melanchall.DryWetMidi.Common; -using System.Collections.Generic; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Melanchall.DryWetMidi.Common; using Melanchall.DryWetMidi.Core; using Melanchall.DryWetMidi.Interaction; using OpenUtau.Core.Ustx; using OpenUtau.Core.Util; -using System.Text; -using System.IO; using UtfUnknown; -using System.Linq; namespace OpenUtau.Core.Format { public class EncodingDetector { @@ -16,9 +16,9 @@ public class EncodingDetector { public void ReadFile(string file) { var ReadingSettings = MidiWriter.BaseReadingSettings(); - + ReadingSettings.DecodeTextCallback = new DecodeTextCallback(AddText); - var midi = MidiFile.Read(file,ReadingSettings); + var midi = MidiFile.Read(file, ReadingSettings); } string AddText(byte[] bytes, ReadingSettings settings) { @@ -72,7 +72,7 @@ static public UProject LoadProject(string file) { TrackNo = project.tracks.Count }; part.trackNo = track.TrackNo; - if(part.name != "New Part"){ + if (part.name != "New Part") { track.TrackName = part.name; } part.AfterLoad(project, track); @@ -98,7 +98,7 @@ public static ReadingSettings BaseReadingSettings() { }; } - + //Import tracks to an existing project static public List Load(string file, UProject project) { // Detects lyric encoding @@ -106,7 +106,7 @@ static public List Load(string file, UProject project) { var encodingDetector = new EncodingDetector(); encodingDetector.ReadFile(file); var encodingResult = encodingDetector.Detect(); - if(encodingResult != null) { + if (encodingResult != null) { lyricEncoding = encodingResult; } //Get midifile resolution @@ -189,7 +189,7 @@ static List ParseParts(MidiFile midi, short PPQ, UProject project) { //{position of lyric: lyric text} Dictionary lyrics = events.Where(e => e.Event is LyricEvent) .GroupBy(e => e.Time) - .ToDictionary(g=> g.Key, g => ((LyricEvent)g.First().Event).Text); + .ToDictionary(g => g.Key, g => ((LyricEvent)g.First().Event).Text); var trackName = events.Where(e => e.Event is SequenceTrackNameEvent) .Select(e => ((SequenceTrackNameEvent)e.Event).Text).FirstOrDefault(); if (trackName != null) { @@ -243,7 +243,7 @@ static public void Save(string filePath, UProject project) { lastUTimeSignature = uTimeSignature; lastTime = time; } - foreach(UTempo uTempo in project.tempos){ + foreach (UTempo uTempo in project.tempos) { tempoMapManager.SetTempo(uTempo.position, Tempo.FromBeatsPerMinute(uTempo.bpm)); } } @@ -265,7 +265,7 @@ static public void Save(string filePath, UProject project) { var events = objectsManager.Objects; foreach (UNote note in voicePart.notes) { //Ignore notes whose pitch is out of midi range - if(note.tone < 0 || note.tone > 127){ + if (note.tone < 0 || note.tone > 127) { continue; } string lyric = note.lyric; @@ -279,14 +279,14 @@ static public void Save(string filePath, UProject project) { } } } - - foreach(TrackChunk trackChunk in trackChunks) { + + foreach (TrackChunk trackChunk in trackChunks) { midiFile.Chunks.Add(trackChunk); } - midiFile.Write(filePath,true,settings: new WritingSettings { + midiFile.Write(filePath, true, settings: new WritingSettings { TextEncoding = System.Text.Encoding.UTF8, - }) ; + }); } } } diff --git a/OpenUtau.Core/Format/MusicXML.cs b/OpenUtau.Core/Format/MusicXML.cs index 1cba81577..8c7c39dc9 100644 --- a/OpenUtau.Core/Format/MusicXML.cs +++ b/OpenUtau.Core/Format/MusicXML.cs @@ -1,20 +1,17 @@ -using System; +using System; +using System.Collections.Generic; +using System.IO; using System.Text; using System.Xml; using System.Xml.Serialization; -using System.IO; -using System.Collections.Generic; using OpenUtau.Core; using OpenUtau.Core.Ustx; using Serilog; using UtfUnknown; -namespace OpenUtau.Core.Format -{ - public static class MusicXML - { - static public UProject LoadProject(string file) - { +namespace OpenUtau.Core.Format { + public static class MusicXML { + static public UProject LoadProject(string file) { UProject uproject = new UProject(); Ustx.AddDefaultExpressions(uproject); @@ -25,8 +22,7 @@ static public UProject LoadProject(string file) var score = ReadXMLScore(file); - foreach (var part in score.Part) - { + foreach (var part in score.Part) { var utrack = new UTrack(uproject); utrack.TrackNo = uproject.tracks.Count; uproject.tracks.Add(utrack); @@ -38,8 +34,7 @@ static public UProject LoadProject(string file) int divisions = (int)part.Measure[0].Attributes[0].Divisions; int currPosTick = 0; - foreach (var measure in part.Measure) - { + foreach (var measure in part.Measure) { // BPM double? bpm; if ((bpm = MeasureBPM(measure)).HasValue) { @@ -62,13 +57,12 @@ static public UProject LoadProject(string file) } // Note - foreach(var note in measure.Note) { + foreach (var note in measure.Note) { int durTick = (int)note.Duration * uproject.resolution / divisions; if (note.Rest != null) { // pass - } - else { + } else { var pitch = note.Pitch.Step.ToString() + note.Pitch.Octave.ToString(); int tone = MusicMath.NameToTone(pitch) + (int)note.Pitch.Alter; UNote unote = uproject.CreateNote(tone, currPosTick, durTick); @@ -83,10 +77,10 @@ static public UProject LoadProject(string file) } upart.Duration = upart.GetMinDurTick(uproject); } - if(uproject.tempos.Count == 0){ + if (uproject.tempos.Count == 0) { uproject.tempos.Add(new UTempo(0, 120)); } - if(uproject.tempos[0].position > 0){ + if (uproject.tempos[0].position > 0) { uproject.tempos[0].position = 0; } uproject.AfterLoad(); @@ -94,28 +88,24 @@ static public UProject LoadProject(string file) return uproject; } - static public Encoding DetectXMLEncoding(string file) - { + static public Encoding DetectXMLEncoding(string file) { Encoding xmlEncoding = Encoding.UTF8; var detectionResult = CharsetDetector.DetectFromFile(file); - if (detectionResult.Detected != null && detectionResult.Detected.Confidence > 0.5) - { + if (detectionResult.Detected != null && detectionResult.Detected.Confidence > 0.5) { xmlEncoding = detectionResult.Detected.Encoding; } return xmlEncoding; } - static public double? MeasureBPM(MusicXMLSchema.ScorePartwisePartMeasure measure) - { + static public double? MeasureBPM(MusicXMLSchema.ScorePartwisePartMeasure measure) { foreach (var direction in measure.Direction) { if (direction.Sound != null) { return (double)direction.Sound.Tempo; } } return null; } - static public MusicXMLSchema.ScorePartwise ReadXMLScore(string xmlFile) - { + static public MusicXMLSchema.ScorePartwise ReadXMLScore(string xmlFile) { Log.Information($"MusicXML Character Encoding: {DetectXMLEncoding(xmlFile)}"); XmlReaderSettings settings = new XmlReaderSettings(); @@ -123,8 +113,7 @@ static public MusicXMLSchema.ScorePartwise ReadXMLScore(string xmlFile) settings.MaxCharactersFromEntities = 1024; using (var fs = new FileStream(xmlFile, FileMode.Open)) - using (var xmlReader = XmlReader.Create(fs, settings)) - { + using (var xmlReader = XmlReader.Create(fs, settings)) { XmlSerializer s = new XmlSerializer(typeof(MusicXMLSchema.ScorePartwise)); var score = s.Deserialize(xmlReader) as MusicXMLSchema.ScorePartwise; diff --git a/OpenUtau.Core/Format/Ufdata.cs b/OpenUtau.Core/Format/Ufdata.cs index e581918c0..b167a87aa 100644 --- a/OpenUtau.Core/Format/Ufdata.cs +++ b/OpenUtau.Core/Format/Ufdata.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using System.Linq; using System.Text; using Newtonsoft.Json; @@ -7,8 +7,7 @@ //reference: https://github.com/sdercolin/utaformatix-data/blob/main/lib/csharp/UtaFormatix.Data -namespace OpenUtau.Core.Format -{ +namespace OpenUtau.Core.Format { /// Note model. /// /// Semitone value of the note's key (Center C = 60). @@ -16,7 +15,7 @@ namespace OpenUtau.Core.Format /// Tick position of the note's end. /// Lyric of the note. /// Phoneme of the note (if available). - public struct UfNote{ + public struct UfNote { public int key; public int tickOn; public int tickOff; @@ -33,7 +32,7 @@ public struct UfNote{ /// In this case, it represents the end of the previous value's lasting. /// True if the semitone value is absolute, /// otherwise it's relative to the note's key. - public struct UfPitch{ + public struct UfPitch { public int[] ticks; public double?[] values; public bool isAbsolute; @@ -43,7 +42,7 @@ public struct UfPitch{ /// /// Tick position of the tempo label. /// Tempo in beats-per-minute. - public struct UfTempo{ + public struct UfTempo { public int tickPosition; public double bpm; } @@ -53,9 +52,9 @@ public struct UfTempo{ /// Measure (bar) position of the time signature. /// Beats per measure. /// Note value per beat. - public struct UfTimeSignature{ - public int measurePosition; - public int numerator; + public struct UfTimeSignature { + public int measurePosition; + public int numerator; public int denominator; } @@ -64,9 +63,9 @@ public struct UfTimeSignature{ /// Track name. /// Notes in the track. /// Pitch data bound to the track (if any). - public struct UfTrack{ - public string name; - public UfNote[] notes; + public struct UfTrack { + public string name; + public UfNote[] notes; public UfPitch? pitch; } @@ -78,26 +77,25 @@ public struct UfTrack{ /// List of tempo labels in the project. /// Count of measure prefixes (measures that cannot /// contain notes, restricted by some editors). - public struct UfProject{ - public string name; - public UfTrack[] tracks; - public UfTimeSignature[]? timeSignatures; - public UfTempo[] tempos; + public struct UfProject { + public string name; + public UfTrack[] tracks; + public UfTimeSignature[]? timeSignatures; + public UfTempo[] tempos; public int measurePrefix; } - public struct UfFile{ + public struct UfFile { public UfProject project; public int formatVersion; } - public static class Ufdata - { + public static class Ufdata { static UVoicePart ParsePart(UfTrack ufTrack, UProject project) { var part = new UVoicePart(); part.name = ufTrack.name; part.position = 0; - foreach(var ufNote in ufTrack.notes){ + foreach (var ufNote in ufTrack.notes) { var note = project.CreateNote( ufNote.key, ufNote.tickOn, @@ -110,25 +108,25 @@ static UVoicePart ParsePart(UfTrack ufTrack, UProject project) { return part; } - public static UProject Load(string file){ + public static UProject Load(string file) { UProject project = new UProject(); Ustx.AddDefaultExpressions(project); project.FilePath = file; - var ufProject = JsonConvert.DeserializeObject(File.ReadAllText(file,Encoding.UTF8)).project; - + var ufProject = JsonConvert.DeserializeObject(File.ReadAllText(file, Encoding.UTF8)).project; + //parse tempo - project.tempos=ufProject.tempos + project.tempos = ufProject.tempos .Select(t => new UTempo(t.tickPosition, t.bpm)) .ToList(); //parse timeSignature - project.timeSignatures=ufProject.timeSignatures + project.timeSignatures = ufProject.timeSignatures .Select(t => new UTimeSignature(t.measurePosition, t.numerator, t.denominator)) .ToList(); //parse tracks var parts = ufProject.tracks - .Where(tr=>tr.notes.Length>0) - .Select(tr=>ParsePart(tr,project)) + .Where(tr => tr.notes.Length > 0) + .Select(tr => ParsePart(tr, project)) .ToList(); foreach (var part in parts) { var track = new UTrack(project); @@ -138,9 +136,9 @@ public static UProject Load(string file){ project.tracks.Add(track); project.parts.Add(part); } - + project.ValidateFull(); return project; } } -} \ No newline at end of file +} diff --git a/OpenUtau.Core/Format/VSQx.cs b/OpenUtau.Core/Format/VSQx.cs index 7337e4376..55deebae7 100644 --- a/OpenUtau.Core/Format/VSQx.cs +++ b/OpenUtau.Core/Format/VSQx.cs @@ -1,9 +1,8 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml; -using System.Collections.Generic; - using OpenUtau.Core.Ustx; namespace OpenUtau.Core.Format { diff --git a/OpenUtau.Core/G2p/JapaneseMonophoneG2p.cs b/OpenUtau.Core/G2p/JapaneseMonophoneG2p.cs index 222245127..5f6a3c793 100644 --- a/OpenUtau.Core/G2p/JapaneseMonophoneG2p.cs +++ b/OpenUtau.Core/G2p/JapaneseMonophoneG2p.cs @@ -95,7 +95,7 @@ protected Tuple LoadPack( prepGrapheme(parts[0]), parts[1].Split().Select(symbol => prepPhoneme(symbol)))); var dict = builder.Build(); - return Tuple.Create((IG2p) dict, session); + return Tuple.Create((IG2p)dict, session); } public JapaneseMonophoneG2p() { diff --git a/OpenUtau.Core/KoreanPhonemizerUtil.cs b/OpenUtau.Core/KoreanPhonemizerUtil.cs index 436e29c91..a7e82f9f2 100644 --- a/OpenUtau.Core/KoreanPhonemizerUtil.cs +++ b/OpenUtau.Core/KoreanPhonemizerUtil.cs @@ -5,11 +5,11 @@ using System.IO; using System.Linq; using System.Text; -using OpenUtau.Core.Ustx; +using OpenUtau.Api; using OpenUtau.Classic; +using OpenUtau.Core.Ustx; using Serilog; using static OpenUtau.Api.Phonemizer; -using OpenUtau.Api; namespace OpenUtau.Core { /// @@ -183,18 +183,15 @@ public static bool IsHangeul(string? character) { // Prevents error when user uses ! as a phonetic symbol. unicodeIndex = Convert.ToUInt16(character.TrimStart('!')[0]); isHangeul = !(unicodeIndex < HANGEUL_UNICODE_START || unicodeIndex > HANGEUL_UNICODE_END); - } - else if (character != null) { + } else if (character != null) { try { unicodeIndex = Convert.ToUInt16(character[0]); isHangeul = !(unicodeIndex < HANGEUL_UNICODE_START || unicodeIndex > HANGEUL_UNICODE_END); - } - catch { + } catch { isHangeul = false; } - } - else { + } else { isHangeul = false; } @@ -228,7 +225,7 @@ public static bool IsKoreanRomaji(string lyric) { /// (ex) 린 /// public static string? TryParseKoreanRomaji(string? romaji) { - + if (string.IsNullOrEmpty(romaji)) { return null; } @@ -345,26 +342,26 @@ public static string[] SeparateRomaji(string character) { var part = character.Split(vowel); if (!(part[1] == "")) { // 글자에 초성, 중성, 종성이 전부 있는 경우 separatedCharacter = new string[] { part[0], vowel, part[1] }; - } else if (part == new string[] {"", ""}) { // 글자에 중성만 존재하는 경우 + } else if (part == new string[] { "", "" }) { // 글자에 중성만 존재하는 경우 separatedCharacter = new string[] { "", vowel, "" }; } else if (part.Length == 2) { // 글자에 초성, 중성만 존재 하는 경우 separatedCharacter = new string[] { part[0], vowel, "" }; } - break; - } + break; + } - if (separatedCharacter.Length == 0) { // 무엇도 해당하지 않을경우 빈 문자열 3개만 담음 - separatedCharacter = new string[] { "", "", ""}; - } + if (separatedCharacter.Length == 0) { // 무엇도 해당하지 않을경우 빈 문자열 3개만 담음 + separatedCharacter = new string[] { "", "", "" }; + } - return separatedCharacter; + return separatedCharacter; } } catch (Exception e) { Log.Error(e, "SeparateRomaji Method Error!"); - return new string[] {"", "", ""}; + return new string[] { "", "", "" }; } - - return new string[] {"", "", ""}; + + return new string[] { "", "", "" }; } /// @@ -373,8 +370,8 @@ public static string[] SeparateRomaji(string character) { /// /// separated Hangeul. /// Returns complete Hangeul Character. - public static string Merge(Hashtable separatedHangeul, int offset = 0){ - + public static string Merge(Hashtable separatedHangeul, int offset = 0) { + int firstConsonantIndex; // (ex) 2 int middleVowelIndex; // (ex) 2 int lastConsonantIndex; // (ex) 21 @@ -383,14 +380,14 @@ public static string Merge(Hashtable separatedHangeul, int offset = 0){ char middleVowel = ((string)separatedHangeul[offset + 1])[0]; // (ex) "ㅑ" char lastConsonant = ((string)separatedHangeul[offset + 2])[0]; // (ex) "ㅇ" - if (firstConsonant == ' ') {firstConsonant = 'ㅇ';} + if (firstConsonant == ' ') { firstConsonant = 'ㅇ'; } firstConsonantIndex = FIRST_CONSONANTS.IndexOf(firstConsonant); // 초성 인덱스 middleVowelIndex = MIDDLE_VOWELS.IndexOf(middleVowel); // 중성 인덱스 lastConsonantIndex = LAST_CONSONANTS.IndexOf(lastConsonant); // 종성 인덱스 - + int mergedCode = HANGEUL_UNICODE_START + (firstConsonantIndex * 21 + middleVowelIndex) * 28 + lastConsonantIndex; - + string result = Convert.ToChar(mergedCode).ToString(); //Debug.Print("Hangeul merged: " + $"{firstConsonant} + {middleVowel} + {lastConsonant} = " + result); return result; @@ -437,56 +434,44 @@ private static Hashtable Variate(Hashtable firstCharSeparated, Hashtable nextCha } } - if (nextFirstConsonant.Equals("ㅇ") && (! firstLastConsonant.Equals(" "))) { + if (nextFirstConsonant.Equals("ㅇ") && (!firstLastConsonant.Equals(" "))) { // ㄳ ㄵ ㄶ ㄺ ㄻ ㄼ ㄽ ㄾ ㄿ ㅀ ㅄ 일 경우에도 분기해서 연음 적용 if (firstLastConsonant.Equals("ㄳ")) { firstLastConsonant = "ㄱ"; nextFirstConsonant = "ㅅ"; - } - else if (firstLastConsonant.Equals("ㄵ")) { + } else if (firstLastConsonant.Equals("ㄵ")) { firstLastConsonant = "ㄴ"; nextFirstConsonant = "ㅈ"; - } - else if (firstLastConsonant.Equals("ㄶ")) { + } else if (firstLastConsonant.Equals("ㄶ")) { firstLastConsonant = "ㄴ"; nextFirstConsonant = "ㅎ"; - } - else if (firstLastConsonant.Equals("ㄺ")) { + } else if (firstLastConsonant.Equals("ㄺ")) { firstLastConsonant = "ㄹ"; nextFirstConsonant = "ㄱ"; - } - else if (firstLastConsonant.Equals("ㄼ")) { + } else if (firstLastConsonant.Equals("ㄼ")) { firstLastConsonant = "ㄹ"; nextFirstConsonant = "ㅂ"; - } - else if (firstLastConsonant.Equals("ㄽ")) { + } else if (firstLastConsonant.Equals("ㄽ")) { firstLastConsonant = "ㄹ"; nextFirstConsonant = "ㅅ"; - } - else if (firstLastConsonant.Equals("ㄾ")) { + } else if (firstLastConsonant.Equals("ㄾ")) { firstLastConsonant = "ㄹ"; nextFirstConsonant = "ㅌ"; - } - else if (firstLastConsonant.Equals("ㄿ")) { + } else if (firstLastConsonant.Equals("ㄿ")) { firstLastConsonant = "ㄹ"; nextFirstConsonant = "ㅍ"; - } - else if (firstLastConsonant.Equals("ㅀ")) { + } else if (firstLastConsonant.Equals("ㅀ")) { firstLastConsonant = "ㄹ"; nextFirstConsonant = "ㅎ"; - } - else if (firstLastConsonant.Equals("ㅄ")) { + } else if (firstLastConsonant.Equals("ㅄ")) { firstLastConsonant = "ㅂ"; nextFirstConsonant = "ㅅ"; - } - else if (firstLastConsonant.Equals("ㄻ")) { + } else if (firstLastConsonant.Equals("ㄻ")) { firstLastConsonant = "ㄹ"; nextFirstConsonant = "ㅁ"; - } - else if (firstLastConsonant.Equals("ㅇ") && nextFirstConsonant.Equals("ㅇ")) { + } else if (firstLastConsonant.Equals("ㅇ") && nextFirstConsonant.Equals("ㅇ")) { // Do nothing - } - else { + } else { // 겹받침 아닐 때 연음 nextFirstConsonant = firstLastConsonant; firstLastConsonant = " "; @@ -495,21 +480,18 @@ private static Hashtable Variate(Hashtable firstCharSeparated, Hashtable nextCha // 1. 유기음화 및 ㅎ탈락 1 - if (firstLastConsonant.Equals("ㅎ") && (! nextFirstConsonant.Equals("ㅅ")) && basicSounds.Contains(nextFirstConsonant)) { + if (firstLastConsonant.Equals("ㅎ") && (!nextFirstConsonant.Equals("ㅅ")) && basicSounds.Contains(nextFirstConsonant)) { // ㅎ으로 끝나고 다음 소리가 ㄱㄷㅂㅈ이면 / ex) 낳다 = 나타 firstLastConsonant = " "; nextFirstConsonant = (string)aspirateSounds[basicSounds[nextFirstConsonant]]; - } - else if (firstLastConsonant.Equals("ㅎ") && (!nextFirstConsonant.Equals("ㅅ")) && nextFirstConsonant.Equals("ㅇ")) { + } else if (firstLastConsonant.Equals("ㅎ") && (!nextFirstConsonant.Equals("ㅅ")) && nextFirstConsonant.Equals("ㅇ")) { // ㅎ으로 끝나고 다음 소리가 없으면 / ex) 낳아 = 나아 firstLastConsonant = " "; - } - else if (firstLastConsonant.Equals("ㄶ") && (! nextFirstConsonant.Equals("ㅅ")) && basicSounds.Contains(nextFirstConsonant)) { + } else if (firstLastConsonant.Equals("ㄶ") && (!nextFirstConsonant.Equals("ㅅ")) && basicSounds.Contains(nextFirstConsonant)) { // ㄶ으로 끝나고 다음 소리가 ㄱㄷㅂㅈ이면 / ex) 많다 = 만타 firstLastConsonant = "ㄴ"; nextFirstConsonant = (string)aspirateSounds[basicSounds[nextFirstConsonant]]; - } - else if (firstLastConsonant.Equals("ㅀ") && (! nextFirstConsonant.Equals("ㅅ")) && basicSounds.Contains(nextFirstConsonant)) { + } else if (firstLastConsonant.Equals("ㅀ") && (!nextFirstConsonant.Equals("ㅅ")) && basicSounds.Contains(nextFirstConsonant)) { // ㅀ으로 끝나고 다음 소리가 ㄱㄷㅂㅈ이면 / ex) 끓다 = 끌타 firstLastConsonant = "ㄹ"; nextFirstConsonant = (string)aspirateSounds[basicSounds[nextFirstConsonant]]; @@ -557,8 +539,7 @@ private static Hashtable Variate(Hashtable firstCharSeparated, Hashtable nextCha // ㅅ은 미리 평파열음화가 진행된 것으로 보고 ㄷ으로 간주한다 nextFirstConsonant = (string)aspirateSounds[basicSounds[firstLastConsonant]]; firstLastConsonant = " "; - } - else if (nextFirstConsonant.Equals("ㅎ")) { + } else if (nextFirstConsonant.Equals("ㅎ")) { nextFirstConsonant = "ㅇ"; } @@ -647,20 +628,15 @@ public static Hashtable Variate(string character) { if (separated[2].Equals("ㄽ") || separated[2].Equals("ㄾ") || separated[2].Equals("ㄼ") || separated[2].Equals("ㅀ")) { separated[2] = "ㄹ"; - } - else if (separated[2].Equals("ㄵ") || separated[2].Equals("ㅅ") || separated[2].Equals("ㅆ") || separated[2].Equals("ㅈ") || separated[2].Equals("ㅉ") || separated[2].Equals("ㅊ")) { + } else if (separated[2].Equals("ㄵ") || separated[2].Equals("ㅅ") || separated[2].Equals("ㅆ") || separated[2].Equals("ㅈ") || separated[2].Equals("ㅉ") || separated[2].Equals("ㅊ")) { separated[2] = "ㄷ"; - } - else if (separated[2].Equals("ㅃ") || separated[2].Equals("ㅍ") || separated[2].Equals("ㄿ") || separated[2].Equals("ㅄ")) { + } else if (separated[2].Equals("ㅃ") || separated[2].Equals("ㅍ") || separated[2].Equals("ㄿ") || separated[2].Equals("ㅄ")) { separated[2] = "ㅂ"; - } - else if (separated[2].Equals("ㄲ") || separated[2].Equals("ㅋ") || separated[2].Equals("ㄺ") || separated[2].Equals("ㄳ")) { + } else if (separated[2].Equals("ㄲ") || separated[2].Equals("ㅋ") || separated[2].Equals("ㄺ") || separated[2].Equals("ㄳ")) { separated[2] = "ㄱ"; - } - else if (separated[2].Equals("ㄻ")) { + } else if (separated[2].Equals("ㄻ")) { separated[2] = "ㅁ"; - } - else if (separated[2].Equals("ㄶ")) { + } else if (separated[2].Equals("ㄶ")) { separated[2] = "ㄴ"; } @@ -682,20 +658,15 @@ private static Hashtable Variate(Hashtable separated) { if (separated[2].Equals("ㄽ") || separated[2].Equals("ㄾ") || separated[2].Equals("ㄼ") || separated[2].Equals("ㅀ")) { separated[2] = "ㄹ"; - } - else if (separated[2].Equals("ㄵ") || separated[2].Equals("ㅅ") || separated[2].Equals("ㅆ") || separated[2].Equals("ㅈ") || separated[2].Equals("ㅉ") || separated[2].Equals("ㅊ")) { + } else if (separated[2].Equals("ㄵ") || separated[2].Equals("ㅅ") || separated[2].Equals("ㅆ") || separated[2].Equals("ㅈ") || separated[2].Equals("ㅉ") || separated[2].Equals("ㅊ")) { separated[2] = "ㄷ"; - } - else if (separated[2].Equals("ㅃ") || separated[2].Equals("ㅍ") || separated[2].Equals("ㄿ") || separated[2].Equals("ㅄ")) { + } else if (separated[2].Equals("ㅃ") || separated[2].Equals("ㅍ") || separated[2].Equals("ㄿ") || separated[2].Equals("ㅄ")) { separated[2] = "ㅂ"; - } - else if (separated[2].Equals("ㄲ") || separated[2].Equals("ㅋ") || separated[2].Equals("ㄺ") || separated[2].Equals("ㄳ")) { + } else if (separated[2].Equals("ㄲ") || separated[2].Equals("ㅋ") || separated[2].Equals("ㄺ") || separated[2].Equals("ㄳ")) { separated[2] = "ㄱ"; - } - else if (separated[2].Equals("ㄻ")) { + } else if (separated[2].Equals("ㄻ")) { separated[2] = "ㅁ"; - } - else if (separated[2].Equals("ㄶ")) { + } else if (separated[2].Equals("ㄶ")) { separated[2] = "ㄴ"; } @@ -728,7 +699,7 @@ private static Hashtable Variate(Hashtable separated) { /// private static Hashtable Variate(string firstChar, string nextChar, int returnCharIndex = 0) { // 글자 넣어도 쓸 수 있음 - + Hashtable firstCharSeparated = Separate(firstChar); Hashtable nextCharSeparated = Separate(nextChar); return Variate(firstCharSeparated, nextCharSeparated, returnCharIndex); @@ -773,25 +744,25 @@ public static Hashtable Variate(Note? prevNeighbour, Note note, Note? nextNeighb if (!IsHangeul(lyrics[0])) { // 앞노트 한국어 아니거나 null일 경우 null처리 - if (lyrics[0] != null) {lyrics[0] = null;} + if (lyrics[0] != null) { lyrics[0] = null; } } else if (!IsHangeul(lyrics[2])) { // 뒤노트 한국어 아니거나 null일 경우 null처리 - if (lyrics[2] != null) {lyrics[2] = null;} + if (lyrics[2] != null) { lyrics[2] = null; } } if ((lyrics[0] != null) && lyrics[0].StartsWith('!')) { /// 앞노트 ! 기호로 시작함 ex) [!냥]냥냥 - if (lyrics[0] != null) {lyrics[0] = null;} // 0번가사 없는 걸로 간주함 null냥냥 + if (lyrics[0] != null) { lyrics[0] = null; } // 0번가사 없는 걸로 간주함 null냥냥 } if ((lyrics[1] != null) && lyrics[1].StartsWith('!')) { /// 중간노트 ! 기호로 시작함 ex) 냥[!냥]냥 /// 음운변동 미적용 lyrics[1] = lyrics[1].TrimStart('!'); - if (lyrics[0] != null) {lyrics[0] = null;} // 0번가사 없는 걸로 간주함 null[!냥]냥 - if (lyrics[2] != null) {lyrics[2] = null;} // 2번가사도 없는 걸로 간주함 null[!냥]null + if (lyrics[0] != null) { lyrics[0] = null; } // 0번가사 없는 걸로 간주함 null[!냥]냥 + if (lyrics[2] != null) { lyrics[2] = null; } // 2번가사도 없는 걸로 간주함 null[!냥]null } if ((lyrics[2] != null) && lyrics[2].StartsWith('!')) { /// 뒤노트 ! 기호로 시작함 ex) 냥냥[!냥] - if (lyrics[2] != null) {lyrics[2] = null;} // 2번가사 없는 걸로 간주함 냥냥b + if (lyrics[2] != null) { lyrics[2] = null; } // 2번가사 없는 걸로 간주함 냥냥b } if ((lyrics[0] != null) && lyrics[0].EndsWith('.')) { @@ -833,8 +804,7 @@ public static Hashtable Variate(Note? prevNeighbour, Note note, Note? nextNeighb result.Add(8, thisNoteSeparated[5]); return result; - } - else { + } else { Hashtable result = new Hashtable() { [0] = "null", // 앞 글자 없음 [1] = "null", @@ -843,31 +813,29 @@ public static Hashtable Variate(Note? prevNeighbour, Note note, Note? nextNeighb if (IsHangeul(lyrics[2])) { Hashtable thisNoteSeparated = Variate(lyrics[1], lyrics[2], -1); // 현글자 뒤글자 - + result.Add(3, thisNoteSeparated[0]); // 현 글자 result.Add(4, thisNoteSeparated[1]); result.Add(5, thisNoteSeparated[2]); - result.Add(6, thisNoteSeparated[3]); + result.Add(6, thisNoteSeparated[3]); result.Add(7, thisNoteSeparated[4]); result.Add(8, thisNoteSeparated[5]); - } - else { + } else { Hashtable thisNoteSeparated = Variate(lyrics[1]); result.Add(3, thisNoteSeparated[0]); // 현 글자 result.Add(4, thisNoteSeparated[1]); result.Add(5, thisNoteSeparated[2]); - result.Add(6, "null"); + result.Add(6, "null"); result.Add(7, "null"); result.Add(8, "null"); } - + return result; } - } - else if ((lyrics[0] != null) && (lyrics[2] == null)) { + } else if ((lyrics[0] != null) && (lyrics[2] == null)) { /// 앞이 있고 뒤는 없음 /// 냥[냥]null if (whereYeonEum == 1) { @@ -884,8 +852,7 @@ public static Hashtable Variate(Note? prevNeighbour, Note note, Note? nextNeighb result.Add(8, "null"); return result; - } - else if (whereYeonEum == 0) { + } else if (whereYeonEum == 0) { // 앞 노트에서 단어가 끝났다고 가정 Hashtable result = Variate(Variate(lyrics[0]), Separate(lyrics[1]), 0); // 첫 글자 Hashtable thisNoteSeparated = Variate(Variate(Variate(lyrics[0]), Separate(lyrics[1]), 1)); // 첫 글자와 현 글자 / 앞글자를 끝글자처럼 음운변동시켜서 음원변동 한 번 더 하기 @@ -899,8 +866,7 @@ public static Hashtable Variate(Note? prevNeighbour, Note note, Note? nextNeighb result.Add(8, "null"); return result; - } - else { + } else { Hashtable result = Variate(lyrics[0], lyrics[1], 0); // 첫 글자 Hashtable thisNoteSeparated = Variate(Variate(lyrics[0], lyrics[1], 1)); // 첫 글자와 현 글자 / 뒷글자 없으니까 글자 혼자 있는걸로 음운변동 한 번 더 시키기 @@ -914,8 +880,7 @@ public static Hashtable Variate(Note? prevNeighbour, Note note, Note? nextNeighb return result; } - } - else if ((lyrics[0] != null) && (lyrics[2] != null)) { + } else if ((lyrics[0] != null) && (lyrics[2] != null)) { /// 앞도 있고 뒤도 있음 /// 냥[냥]냥 if (whereYeonEum == 1) { @@ -932,8 +897,7 @@ public static Hashtable Variate(Note? prevNeighbour, Note note, Note? nextNeighb result.Add(8, thisNoteSeparated[5]); return result; - } - else if (whereYeonEum == 0) { + } else if (whereYeonEum == 0) { // 앞 노트에서 단어가 끝났다고 가정 / 릎. [위] 놓 Hashtable result = Variate(Variate(lyrics[0]), Separate(lyrics[1]), 0); // 첫 글자 Hashtable thisNoteSeparated = Variate(Variate(Variate(lyrics[0]), Separate(lyrics[1]), 1), Separate(lyrics[2]), -1); // 현 글자와 뒤 글자 / 앞글자 끝글자처럼 음운변동시켜서 음원변동 한 번 더 하기 @@ -947,8 +911,7 @@ public static Hashtable Variate(Note? prevNeighbour, Note note, Note? nextNeighb result.Add(8, thisNoteSeparated[5]); return result; - } - else { + } else { Hashtable result = Variate(lyrics[0], lyrics[1], 0); Hashtable thisNoteSeparated = Variate(Variate(lyrics[0], lyrics[1], 1), Separate(lyrics[2]), -1); @@ -962,8 +925,7 @@ public static Hashtable Variate(Note? prevNeighbour, Note note, Note? nextNeighb return result; } - } - else { + } else { /// 앞이 없고 뒤도 없음 /// null[냥]null @@ -1025,29 +987,29 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei /// 1 : 현재 노트를 연음하지 않음 int whereYeonEum = -1; - string?[] lyrics = new string?[] { prevNeighbour, note, nextNeighbour}; + string?[] lyrics = new string?[] { prevNeighbour, note, nextNeighbour }; if (!IsHangeul(lyrics[0])) { // 앞노트 한국어 아니거나 null일 경우 null처리 - if (lyrics[0] != null) {lyrics[0] = null;} + if (lyrics[0] != null) { lyrics[0] = null; } } else if (!IsHangeul(lyrics[2])) { // 뒤노트 한국어 아니거나 null일 경우 null처리 - if (lyrics[2] != null) {lyrics[2] = null;} + if (lyrics[2] != null) { lyrics[2] = null; } } if ((lyrics[0] != null) && lyrics[0].StartsWith('!')) { /// 앞노트 ! 기호로 시작함 ex) [!냥]냥냥 - if (lyrics[0] != null) {lyrics[0] = null;} // 0번가사 없는 걸로 간주함 null냥냥 + if (lyrics[0] != null) { lyrics[0] = null; } // 0번가사 없는 걸로 간주함 null냥냥 } if ((lyrics[1] != null) && lyrics[1].StartsWith('!')) { /// 중간노트 ! 기호로 시작함 ex) 냥[!냥]냥 /// 음운변동 미적용 lyrics[1] = lyrics[1].TrimStart('!'); - if (lyrics[0] != null) {lyrics[0] = null;} // 0번가사 없는 걸로 간주함 null[!냥]냥 - if (lyrics[2] != null) {lyrics[2] = null;} // 2번가사도 없는 걸로 간주함 null[!냥]null + if (lyrics[0] != null) { lyrics[0] = null; } // 0번가사 없는 걸로 간주함 null[!냥]냥 + if (lyrics[2] != null) { lyrics[2] = null; } // 2번가사도 없는 걸로 간주함 null[!냥]null } if ((lyrics[2] != null) && lyrics[2].StartsWith('!')) { /// 뒤노트 ! 기호로 시작함 ex) 냥냥[!냥] - if (lyrics[2] != null) {lyrics[2] = null;} // 2번가사 없는 걸로 간주함 냥냥b + if (lyrics[2] != null) { lyrics[2] = null; } // 2번가사 없는 걸로 간주함 냥냥b } if ((lyrics[0] != null) && lyrics[0].EndsWith('.')) { @@ -1088,12 +1050,12 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(7, thisNoteSeparated[4]); result.Add(8, thisNoteSeparated[5]); - return Merge(new Hashtable{ - [0] = (string)result[3], - [1] = (string)result[4], - [2] = (string)result[5]}); - } - else { + return Merge(new Hashtable { + [0] = (string)result[3], + [1] = (string)result[4], + [2] = (string)result[5] + }); + } else { Hashtable result = new Hashtable() { [0] = "null", // 앞 글자 없음 [1] = "null", @@ -1112,8 +1074,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei return Merge(result, 3); } - } - else if ((lyrics[0] != null) && (lyrics[2] == null)) { + } else if ((lyrics[0] != null) && (lyrics[2] == null)) { /// 앞이 있고 뒤는 없음 /// 냥[냥]null if (whereYeonEum == 1) { @@ -1130,8 +1091,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(8, "null"); return Merge(result, 3); - } - else if (whereYeonEum == 0) { + } else if (whereYeonEum == 0) { // 앞 노트에서 단어가 끝났다고 가정 Hashtable result = Variate(Variate(lyrics[0]), Separate(lyrics[1]), 0); // 첫 글자 Hashtable thisNoteSeparated = Variate(Variate(Variate(lyrics[0]), Separate(lyrics[1]), 1)); // 첫 글자와 현 글자 / 앞글자를 끝글자처럼 음운변동시켜서 음원변동 한 번 더 하기 @@ -1145,8 +1105,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(8, "null"); return Merge(result, 3); - } - else { + } else { Hashtable result = Variate(lyrics[0], lyrics[1], 0); // 첫 글자 Hashtable thisNoteSeparated = Variate(Variate(lyrics[0], lyrics[1], 1)); // 첫 글자와 현 글자 / 뒷글자 없으니까 글자 혼자 있는걸로 음운변동 한 번 더 시키기 @@ -1160,8 +1119,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei return Merge(result, 3); } - } - else if ((lyrics[0] != null) && (lyrics[2] != null)) { + } else if ((lyrics[0] != null) && (lyrics[2] != null)) { /// 앞도 있고 뒤도 있음 /// 냥[냥]냥 if (whereYeonEum == 1) { @@ -1178,8 +1136,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(8, thisNoteSeparated[5]); return Merge(result, 3); - } - else if (whereYeonEum == 0) { + } else if (whereYeonEum == 0) { // 앞 노트에서 단어가 끝났다고 가정 / 릎. [위] 놓 Hashtable result = Variate(Variate(lyrics[0]), Separate(lyrics[1]), 0); // 첫 글자 Hashtable thisNoteSeparated = Variate(Variate(Variate(lyrics[0]), Separate(lyrics[1]), 1), Separate(lyrics[2]), -1); // 현 글자와 뒤 글자 / 앞글자 끝글자처럼 음운변동시켜서 음원변동 한 번 더 하기 @@ -1193,8 +1150,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei result.Add(8, thisNoteSeparated[5]); return Merge(result, 3); - } - else { + } else { Hashtable result = Variate(lyrics[0], lyrics[1], 0); Hashtable thisNoteSeparated = Variate(Variate(lyrics[0], lyrics[1], 1), Separate(lyrics[2]), -1); @@ -1208,8 +1164,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei return Merge(result, 3); } - } - else { + } else { /// 앞이 없고 뒤도 없음 /// null[냥]null Hashtable result = new Hashtable() { @@ -1233,7 +1188,7 @@ public static String Variate(String? prevNeighbour, String note, String? nextNei return Merge(result, 3); } } - + public static Note[] ChangeLyric(Note[] group, string lyric) { // for ENUNU Phonemizer var oldNote = group[0]; @@ -1248,44 +1203,42 @@ public static Note[] ChangeLyric(Note[] group, string lyric) { return group; } - public static void ModifyLyrics(Hashtable lyricSeparated,string lyric, Dictionary firstConsonants, Dictionary vowels, Dictionary lastConsonants, string semivowelSeparator){ + public static void ModifyLyrics(Hashtable lyricSeparated, string lyric, Dictionary firstConsonants, Dictionary vowels, Dictionary lastConsonants, string semivowelSeparator) { lyric += firstConsonants[(string)lyricSeparated[3]][0]; - if (vowels[(string)lyricSeparated[4]][1] != "") { - // this vowel contains semivowel - lyric += semivowelSeparator + vowels[(string)lyricSeparated[4]][1] + vowels[(string)lyricSeparated[4]][2]; - } - else{ - lyric += " " + vowels[(string)lyricSeparated[4]][2]; - } - - lyric += lastConsonants[(string)lyricSeparated[5]][0]; + if (vowels[(string)lyricSeparated[4]][1] != "") { + // this vowel contains semivowel + lyric += semivowelSeparator + vowels[(string)lyricSeparated[4]][1] + vowels[(string)lyricSeparated[4]][2]; + } else { + lyric += " " + vowels[(string)lyricSeparated[4]][2]; + } + + lyric += lastConsonants[(string)lyricSeparated[5]][0]; } - + public static void RomanizeNotes(Note[][] groups, bool _modifyLyrics = false, Dictionary firstConsonants = null, Dictionary vowels = null, Dictionary lastConsonants = null, string semivowelSeparator = " ") { // for ENUNU & DIFFS Phonemizer int noteIdx = 0; string lyric; bool modifyLyrics = (!_modifyLyrics || firstConsonants == null || vowels == null || lastConsonants == null) ? false : true; - + Note[] currentNote; Note[]? prevNote = null; Note[]? nextNote; - + Note? prevNote_; Note? nextNote_; List ResultLyrics = new List(); - foreach (Note[] group in groups){ + foreach (Note[] group in groups) { currentNote = groups[noteIdx]; string originalLyric; // uses this when no variation needed originalLyric = currentNote[0].lyric; if (groups.Length > noteIdx + 1 && IsHangeul(groups[noteIdx + 1][0].lyric)) { nextNote = groups[noteIdx + 1]; - } - else { + } else { nextNote = null; } @@ -1294,284 +1247,264 @@ public static void RomanizeNotes(Note[][] groups, bool _modifyLyrics = false, Di if (prevNote[0].position + prevNote.Sum(note => note.duration) != currentNote[0].position) { prevNote_ = null; } - } - else {prevNote_ = null;} + } else { prevNote_ = null; } if (nextNote != null) { nextNote_ = nextNote[0]; - + if (nextNote[0].position != currentNote[0].position + currentNote.Sum(note => note.duration)) { nextNote_ = null; } - } - else{nextNote_ = null;} - + } else { nextNote_ = null; } + lyric = originalLyric; - if (! IsHangeul(currentNote[0].lyric)){ + if (!IsHangeul(currentNote[0].lyric)) { ResultLyrics.Add(currentNote[0].lyric); - prevNote = currentNote; + prevNote = currentNote; noteIdx++; continue; } - - Hashtable lyricSeparated = Variate(prevNote_, currentNote[0], nextNote_); - if (modifyLyrics) { - ModifyLyrics(lyricSeparated, lyric, firstConsonants, vowels, lastConsonants, semivowelSeparator); - } - else { - lyric = Merge(lyricSeparated, 3); - } - - ResultLyrics.Add(lyric.Trim()); + Hashtable lyricSeparated = Variate(prevNote_, currentNote[0], nextNote_); - prevNote = currentNote; - - noteIdx++; + if (modifyLyrics) { + ModifyLyrics(lyricSeparated, lyric, firstConsonants, vowels, lastConsonants, semivowelSeparator); + } else { + lyric = Merge(lyricSeparated, 3); + } + + ResultLyrics.Add(lyric.Trim()); + + prevNote = currentNote; + + noteIdx++; } Enumerable.Zip(groups, ResultLyrics.ToArray(), ChangeLyric).Last(); } - /// - /// abstract class for Ini Management - /// To use, child phonemizer should implement this class(BaseIniManager) with its own setting values! - /// - public abstract class BaseIniManager { - protected USinger singer; - protected Hashtable iniSetting = new Hashtable(); - protected string iniFileName; - protected string filePath; - protected List blocks; - - public BaseIniManager() { } - /// - /// if no [iniFileName] in Singer Directory, it makes new [iniFileName] with [iniFile]]. + /// abstract class for Ini Management + /// To use, child phonemizer should implement this class(BaseIniManager) with its own setting values! /// - /// - /// - /// - public void Initialize(USinger singer, string iniFileName, Hashtable defaultIniSetting) { - this.singer = singer; - this.iniFileName = iniFileName; - iniSetting = defaultIniSetting; - filePath = Path.Combine(singer.Location, iniFileName); - try { - using (StreamReader reader = new StreamReader(filePath, Encoding.UTF8)){ - List blocks = Ini.ReadBlocks(reader, filePath, @"\[\w+\]"); - if (blocks.Count == 0) { - throw new IOException($"[{iniFileName}] is empty."); + public abstract class BaseIniManager { + protected USinger singer; + protected Hashtable iniSetting = new Hashtable(); + protected string iniFileName; + protected string filePath; + protected List blocks; + + public BaseIniManager() { } + + /// + /// if no [iniFileName] in Singer Directory, it makes new [iniFileName] with [iniFile]]. + /// + /// + /// + /// + public void Initialize(USinger singer, string iniFileName, Hashtable defaultIniSetting) { + this.singer = singer; + this.iniFileName = iniFileName; + iniSetting = defaultIniSetting; + filePath = Path.Combine(singer.Location, iniFileName); + try { + using (StreamReader reader = new StreamReader(filePath, Encoding.UTF8)) { + List blocks = Ini.ReadBlocks(reader, filePath, @"\[\w+\]"); + if (blocks.Count == 0) { + throw new IOException($"[{iniFileName}] is empty."); + } + this.blocks = blocks; + IniSetUp(iniSetting); // you can override IniSetUp() to use. } - this.blocks = blocks; - IniSetUp(iniSetting); // you can override IniSetUp() to use. - }; - } - catch (IOException e) { - Log.Error(e, $"failed to read {iniFileName}, Making new {iniFileName}..."); - using (StreamWriter writer = new StreamWriter(filePath, false, Encoding.UTF8)){ - iniSetting = defaultIniSetting; - try{ - writer.Write(ConvertSettingsToString()); - writer.Close(); + } catch (IOException e) { + Log.Error(e, $"failed to read {iniFileName}, Making new {iniFileName}..."); + using (StreamWriter writer = new StreamWriter(filePath, false, Encoding.UTF8)) { + iniSetting = defaultIniSetting; + try { + writer.Write(ConvertSettingsToString()); + writer.Close(); + } catch (IOException e_) { + Log.Error(e_, $"[{iniFileName}] Failed to Write new {iniFileName}."); + } } - catch (IOException e_){ - Log.Error(e_, $"[{iniFileName}] Failed to Write new {iniFileName}."); + using (StreamReader reader = new StreamReader(filePath, Encoding.UTF8)) { + List blocks = Ini.ReadBlocks(reader, filePath, @"\[\w+\]"); + this.blocks = blocks; } - }; - using (StreamReader reader = new StreamReader(filePath, Encoding.UTF8)){ - List blocks = Ini.ReadBlocks(reader, filePath, @"\[\w+\]"); - this.blocks = blocks; - }; + } } - } - /// - /// you can override this method with your own values. - /// !! when implement this method, you have to use [SetOrReadThisValue(string sectionName, string keyName, bool/string/int/double value)] when setting or reading values. - /// (ex) - /// SetOrReadThisValue("sectionName", "keyName", true); - /// - protected virtual void IniSetUp(Hashtable iniSetting) { - } + /// + /// you can override this method with your own values. + /// !! when implement this method, you have to use [SetOrReadThisValue(string sectionName, string keyName, bool/string/int/double value)] when setting or reading values. + /// (ex) + /// SetOrReadThisValue("sectionName", "keyName", true); + /// + protected virtual void IniSetUp(Hashtable iniSetting) { + } - /// - /// for file writing, converts iniSetting to string. - /// - /// - protected string ConvertSettingsToString(){ - string result = ""; - foreach (DictionaryEntry section in iniSetting) { - result += $"[{section.Key}]\n"; - foreach (DictionaryEntry key in (Hashtable)iniSetting[section.Key]){ - result += $"{key.Key}={key.Value}\n"; + /// + /// for file writing, converts iniSetting to string. + /// + /// + protected string ConvertSettingsToString() { + string result = ""; + foreach (DictionaryEntry section in iniSetting) { + result += $"[{section.Key}]\n"; + foreach (DictionaryEntry key in (Hashtable)iniSetting[section.Key]) { + result += $"{key.Key}={key.Value}\n"; + } } + return result; } - return result; - } - /// - /// section's name in .ini config file. - /// key's name in .ini config file's [sectionName] section. - /// default value to overwrite if there's no valid value in config file. - /// inputs section name & key name & default value. If there's valid bool vaule, nothing happens. But if there's no valid bool value, overwrites current value with default value. - /// 섹션과 키 이름을 입력받고, bool 값이 존재하면 넘어가고 존재하지 않으면 defaultValue 값으로 덮어씌운다 - /// /// - protected void SetOrReadThisValue(string sectionName, string keyName, bool defaultValue, out bool resultValue) { - List iniLines = blocks.Find(block => block.header == $"[{sectionName}]").lines; - if (! iniSetting.ContainsKey(sectionName)){ + /// + /// section's name in .ini config file. + /// key's name in .ini config file's [sectionName] section. + /// default value to overwrite if there's no valid value in config file. + /// inputs section name & key name & default value. If there's valid bool vaule, nothing happens. But if there's no valid bool value, overwrites current value with default value. + /// 섹션과 키 이름을 입력받고, bool 값이 존재하면 넘어가고 존재하지 않으면 defaultValue 값으로 덮어씌운다 + /// /// + protected void SetOrReadThisValue(string sectionName, string keyName, bool defaultValue, out bool resultValue) { + List iniLines = blocks.Find(block => block.header == $"[{sectionName}]").lines; + if (!iniSetting.ContainsKey(sectionName)) { iniSetting.Add(sectionName, new Hashtable()); } - if (iniLines != null) { - string result = iniLines.Find(l => l.line.Trim().Split("=")[0] == keyName).line.Trim().Split("=")[1]; - if (result != null) { - try{ - ((Hashtable)iniSetting[sectionName]).Add(keyName, result); - } - catch (ArgumentException){ - ((Hashtable)iniSetting[sectionName])[keyName] = result; - } - - resultValue = result.ToLower() == "true" ? true : false; - } - else { - try{ - ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue.ToString()); + if (iniLines != null) { + string result = iniLines.Find(l => l.line.Trim().Split("=")[0] == keyName).line.Trim().Split("=")[1]; + if (result != null) { + try { + ((Hashtable)iniSetting[sectionName]).Add(keyName, result); + } catch (ArgumentException) { + ((Hashtable)iniSetting[sectionName])[keyName] = result; + } + + resultValue = result.ToLower() == "true" ? true : false; + } else { + try { + ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue.ToString()); + } catch (ArgumentException) { + ((Hashtable)iniSetting[sectionName])[keyName] = defaultValue.ToString(); + } + resultValue = defaultValue; } - catch (ArgumentException){ - ((Hashtable)iniSetting[sectionName])[keyName] = defaultValue.ToString(); + } else { + using (StreamWriter writer = new StreamWriter(filePath)) { + ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue.ToString().ToLower()); + resultValue = defaultValue; + try { + writer.Write(ConvertSettingsToString()); + } catch (IOException e) { + Log.Error(e, $"[{iniFileName}] Failed to Write new {iniFileName}."); + } + + Log.Information($"[{iniFileName}] failed to parse setting '{keyName}', modified {defaultValue} as default value."); } - resultValue = defaultValue; } } - else{ - using (StreamWriter writer = new StreamWriter(filePath)) { - ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue.ToString().ToLower()); - resultValue = defaultValue; - try{ - writer.Write(ConvertSettingsToString()); - } - catch (IOException e){ - Log.Error(e, $"[{iniFileName}] Failed to Write new {iniFileName}."); - } - - Log.Information($"[{iniFileName}] failed to parse setting '{keyName}', modified {defaultValue} as default value."); - }; - } - } - - /// - /// section's name in .ini config file. - /// key's name in .ini config file's [sectionName] section. - /// default value to overwrite if there's no valid value in config file. - /// inputs section name & key name & default value. If there's valid string vaule, nothing happens. But if there's no valid string value, overwrites current value with default value. - /// 섹션과 키 이름을 입력받고, string 값이 존재하면 넘어가고 존재하지 않으면 defaultValue 값으로 덮어씌운다 - /// - protected string SetOrReadThisValue(string sectionName, string keyName, string defaultValue) { - string resultValue; - List iniLines = blocks.Find(block => block.header == $"[{sectionName}]").lines; - if (! iniSetting.ContainsKey(sectionName)){ + + /// + /// section's name in .ini config file. + /// key's name in .ini config file's [sectionName] section. + /// default value to overwrite if there's no valid value in config file. + /// inputs section name & key name & default value. If there's valid string vaule, nothing happens. But if there's no valid string value, overwrites current value with default value. + /// 섹션과 키 이름을 입력받고, string 값이 존재하면 넘어가고 존재하지 않으면 defaultValue 값으로 덮어씌운다 + /// + protected string SetOrReadThisValue(string sectionName, string keyName, string defaultValue) { + string resultValue; + List iniLines = blocks.Find(block => block.header == $"[{sectionName}]").lines; + if (!iniSetting.ContainsKey(sectionName)) { iniSetting.Add(sectionName, new Hashtable()); } - if (iniLines != null) { - string result = iniLines.Find(l => l.line.Trim().Split("=")[0] == keyName).line.Trim().Split("=")[1]; - if (result != null) { - try{ - ((Hashtable)iniSetting[sectionName]).Add(keyName, result); - } - catch (ArgumentException){ - ((Hashtable)iniSetting[sectionName])[keyName] = result; - } - resultValue = result; - } - else { - try{ - ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue); - } - catch (ArgumentException){ - ((Hashtable)iniSetting[sectionName])[keyName] = defaultValue; + if (iniLines != null) { + string result = iniLines.Find(l => l.line.Trim().Split("=")[0] == keyName).line.Trim().Split("=")[1]; + if (result != null) { + try { + ((Hashtable)iniSetting[sectionName]).Add(keyName, result); + } catch (ArgumentException) { + ((Hashtable)iniSetting[sectionName])[keyName] = result; + } + resultValue = result; + } else { + try { + ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue); + } catch (ArgumentException) { + ((Hashtable)iniSetting[sectionName])[keyName] = defaultValue; + } + resultValue = defaultValue; } + } else { + StreamWriter writer = new StreamWriter(filePath); + ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue); resultValue = defaultValue; + try { + writer.Write(ConvertSettingsToString()); + writer.Close(); + } catch (IOException e) { + Log.Error(e, $"[{iniFileName}] Failed to Write new {iniFileName}."); + } + Log.Information($"[{iniFileName}] failed to parse setting '{keyName}', modified {defaultValue} as default value."); } + return resultValue; } - else{ - StreamWriter writer = new StreamWriter(filePath); - ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue); - resultValue = defaultValue; - try{ - writer.Write(ConvertSettingsToString()); - writer.Close(); - } - catch (IOException e){ - Log.Error(e, $"[{iniFileName}] Failed to Write new {iniFileName}."); - } - Log.Information($"[{iniFileName}] failed to parse setting '{keyName}', modified {defaultValue} as default value."); - } - return resultValue; - } - - /// - /// - /// section's name in .ini config file. - /// key's name in .ini config file's [sectionName] section. - /// default value to overwrite if there's no valid value in config file. - /// inputs section name & key name & default value. If there's valid int vaule, nothing happens. But if there's no valid int value, overwrites current value with default value. - /// 섹션과 키 이름을 입력받고, int 값이 존재하면 넘어가고 존재하지 않으면 defaultValue 값으로 덮어씌운다 - /// - protected void SetOrReadThisValue(string sectionName, string keyName, int defaultValue, out int resultValue) { - List iniLines = blocks.Find(block => block.header == $"[{sectionName}]").lines; - if (! iniSetting.ContainsKey(sectionName)){ + + /// + /// + /// section's name in .ini config file. + /// key's name in .ini config file's [sectionName] section. + /// default value to overwrite if there's no valid value in config file. + /// inputs section name & key name & default value. If there's valid int vaule, nothing happens. But if there's no valid int value, overwrites current value with default value. + /// 섹션과 키 이름을 입력받고, int 값이 존재하면 넘어가고 존재하지 않으면 defaultValue 값으로 덮어씌운다 + /// + protected void SetOrReadThisValue(string sectionName, string keyName, int defaultValue, out int resultValue) { + List iniLines = blocks.Find(block => block.header == $"[{sectionName}]").lines; + if (!iniSetting.ContainsKey(sectionName)) { iniSetting.Add(sectionName, new Hashtable()); } - if (iniLines != null) { - string result = iniLines.Find(l => l.line.Trim().Split("=")[0] == keyName).line.Trim().Split("=")[1]; - if (result != null && int.TryParse(result, out var resultInt)) { - try{ - ((Hashtable)iniSetting[sectionName]).Add(keyName, result); - } - catch (ArgumentException){ - ((Hashtable)iniSetting[sectionName])[keyName] = result; - } - resultValue = resultInt; - } - else { - try{ - ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue.ToString()); - } - catch (ArgumentException){ - ((Hashtable)iniSetting[sectionName])[keyName] = defaultValue.ToString(); + if (iniLines != null) { + string result = iniLines.Find(l => l.line.Trim().Split("=")[0] == keyName).line.Trim().Split("=")[1]; + if (result != null && int.TryParse(result, out var resultInt)) { + try { + ((Hashtable)iniSetting[sectionName]).Add(keyName, result); + } catch (ArgumentException) { + ((Hashtable)iniSetting[sectionName])[keyName] = result; + } + resultValue = resultInt; + } else { + try { + ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue.ToString()); + } catch (ArgumentException) { + ((Hashtable)iniSetting[sectionName])[keyName] = defaultValue.ToString(); + } + resultValue = defaultValue; } + } else { + StreamWriter writer = new StreamWriter(filePath); + ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue); resultValue = defaultValue; + try { + writer.Write(ConvertSettingsToString()); + writer.Close(); + } catch (IOException e) { + Log.Error(e, $"[{iniFileName}] Failed to Write new {iniFileName}."); + } + Log.Information($"[{iniFileName}] failed to parse setting '{keyName}', modified {defaultValue} as default value."); } } - else{ - StreamWriter writer = new StreamWriter(filePath); - ((Hashtable)iniSetting[sectionName]).Add(keyName, defaultValue); - resultValue = defaultValue; - try{ - writer.Write(ConvertSettingsToString()); - writer.Close(); - } - catch (IOException e){ - Log.Error(e, $"[{iniFileName}] Failed to Write new {iniFileName}."); - } - Log.Information($"[{iniFileName}] failed to parse setting '{keyName}', modified {defaultValue} as default value."); - } - } - } + } /// /// Data class used to deserialize yaml dictionary. /// (for user-defined Korean jamo dictionary) /// - public class JamoDictionary{ + public class JamoDictionary { public FirstConsonantData[] firstConsonants; public PlainVowelData[] plainVowels; public SemivowelData[] semivowels; public FinalConsonantData[] finalConsonants; public JamoDictionary() { } - public JamoDictionary(FirstConsonantData[] firstConsonants, PlainVowelData[] plainVowels, SemivowelData[] semivowels, FinalConsonantData[] finalConsonants){ + public JamoDictionary(FirstConsonantData[] firstConsonants, PlainVowelData[] plainVowels, SemivowelData[] semivowels, FinalConsonantData[] finalConsonants) { this.firstConsonants = firstConsonants; this.plainVowels = plainVowels; this.semivowels = semivowels; @@ -1615,5 +1548,5 @@ public FinalConsonantData(string grapheme, string phoneme) { } } } - + } diff --git a/OpenUtau.Core/MachineLearningPhonemizer.cs b/OpenUtau.Core/MachineLearningPhonemizer.cs index a7c56dc2f..70a36eaed 100644 --- a/OpenUtau.Core/MachineLearningPhonemizer.cs +++ b/OpenUtau.Core/MachineLearningPhonemizer.cs @@ -6,8 +6,7 @@ using Serilog; namespace OpenUtau.Core { - public abstract class MachineLearningPhonemizer : Phonemizer - { + public abstract class MachineLearningPhonemizer : Phonemizer { //The results of the timing model are stored in partResult //key: tick position of each note. //value: a list of phonemes and their positions in the note @@ -31,9 +30,9 @@ public override void SetUp(Note[][] groups, UProject project, UTrack track) { phrase.Add(groups[i]); } else { //If the previous and current notes are not connected, process the current sentence and start the next sentence - try{ + try { ProcessPart(phrase.ToArray()); - }catch(Exception e){ + } catch (Exception e) { var sentenceLyrics = string.Join(" ", phrase.Select(group => group[0].lyric)); Log.Error($"Failed to phonemize sentence {sentenceLyrics}: {e.Message}"); } @@ -68,7 +67,7 @@ public override void CleanUp() { protected abstract void ProcessPart(Note[][] phrase); //Romanize lyrics for Mandarin and Yue Chinese - protected virtual string[] Romanize(IEnumerable lyrics){ + protected virtual string[] Romanize(IEnumerable lyrics) { return lyrics.ToArray(); } diff --git a/OpenUtau.Core/Render/IRenderer.cs b/OpenUtau.Core/Render/IRenderer.cs index 2122aa47b..f8b7b521d 100644 --- a/OpenUtau.Core/Render/IRenderer.cs +++ b/OpenUtau.Core/Render/IRenderer.cs @@ -70,7 +70,7 @@ public interface IRenderer { RenderResult Layout(RenderPhrase phrase); Task Render(RenderPhrase phrase, Progress progress, int trackNo, CancellationTokenSource cancellation, bool isPreRender = false); RenderPitchResult LoadRenderedPitch(RenderPhrase phrase); - List LoadRenderedRealCurves(RenderPhrase phrase) { return new List(0);} + List LoadRenderedRealCurves(RenderPhrase phrase) { return new List(0); } UExpressionDescriptor[] GetSuggestedExpressions(USinger singer, URenderSettings renderSettings); } } diff --git a/OpenUtau.Core/Render/RenderPhrase.cs b/OpenUtau.Core/Render/RenderPhrase.cs index d85bc3081..cf526b7e2 100644 --- a/OpenUtau.Core/Render/RenderPhrase.cs +++ b/OpenUtau.Core/Render/RenderPhrase.cs @@ -369,7 +369,7 @@ double Fade(double diff, int pit) { } return diff; } - } catch(Exception e) { + } catch (Exception e) { Log.Error(e, "Failed to compute mod plus."); } } @@ -386,8 +386,8 @@ double Fade(double diff, int pit) { var curves = new List>(); - foreach(var descriptor in project.expressions.Values) { - if(descriptor.type != UExpressionType.Curve) { + foreach (var descriptor in project.expressions.Values) { + if (descriptor.type != UExpressionType.Curve) { continue; } var curve = part.curves.FirstOrDefault(c => c.abbr == descriptor.abbr); @@ -405,14 +405,14 @@ double Fade(double diff, int pit) { var curveSampled = SampleCurve(curve, pitchStart, pitches.Length, convert); switch (curve.abbr) { case Format.Ustx.PITD: break; - case Format.Ustx.DYN : dynamics = curveSampled; break; + case Format.Ustx.DYN: dynamics = curveSampled; break; case Format.Ustx.SHFC: toneShift = curveSampled; break; case Format.Ustx.GENC: gender = curveSampled; break; case Format.Ustx.TENC: tension = curveSampled; break; case Format.Ustx.BREC: breathiness = curveSampled; break; case Format.Ustx.VOIC: voicing = curveSampled; break; default: - curves.Add(Tuple.Create(curve.abbr,curveSampled)); + curves.Add(Tuple.Create(curve.abbr, curveSampled)); break; } } @@ -476,9 +476,9 @@ private ulong Hash(bool postEffect) { } } } - foreach(var curve in curves) { + foreach (var curve in curves) { writer.Write(curve.Item1); - foreach(var v in curve.Item2) { + foreach (var v in curve.Item2) { writer.Write(v); } } diff --git a/OpenUtau.Core/ThirdParty/Deque.cs b/OpenUtau.Core/ThirdParty/Deque.cs index 3ab1a9f6a..8e36b9cda 100644 --- a/OpenUtau.Core/ThirdParty/Deque.cs +++ b/OpenUtau.Core/ThirdParty/Deque.cs @@ -4,16 +4,14 @@ using System.Linq; using System.Text; -namespace OpenUtau.Core.Lib -{ +namespace OpenUtau.Core.Lib { /// /// A double-ended queue (deque), which provides O(1) indexed access, O(1) removals from the front and back, amortized O(1) insertions to the front and back, and O(N) insertions and removals anywhere else (with the operations getting slower as the index approaches the middle). /// /// The type of elements contained in the deque. [DebuggerDisplay("Count = {Count}, Capacity = {Capacity}")] [DebuggerTypeProxy(typeof(Deque<>.DebugView))] - internal sealed class Deque : IList, System.Collections.IList - { + internal sealed class Deque : IList, System.Collections.IList { /// /// The default capacity. /// @@ -33,8 +31,7 @@ internal sealed class Deque : IList, System.Collections.IList /// Initializes a new instance of the class with the specified capacity. /// /// The initial capacity. Must be greater than 0. - public Deque(int capacity) - { + public Deque(int capacity) { if (capacity < 1) throw new ArgumentOutOfRangeException("capacity", "Capacity must be greater than 0."); buffer = new T[capacity]; @@ -44,16 +41,12 @@ public Deque(int capacity) /// Initializes a new instance of the class with the elements from the specified collection. /// /// The collection. - public Deque(IEnumerable collection) - { + public Deque(IEnumerable collection) { int count = collection.Count(); - if (count > 0) - { + if (count > 0) { buffer = new T[count]; DoInsertRange(0, collection, count); - } - else - { + } else { buffer = new T[DefaultCapacity]; } } @@ -62,8 +55,7 @@ public Deque(IEnumerable collection) /// Initializes a new instance of the class. /// public Deque() - : this(DefaultCapacity) - { + : this(DefaultCapacity) { } #region GenericListImplementations @@ -72,8 +64,7 @@ public Deque() /// Gets a value indicating whether this list is read-only. This implementation always returns false. /// /// true if this list is read-only; otherwise, false. - bool ICollection.IsReadOnly - { + bool ICollection.IsReadOnly { get { return false; } } @@ -83,16 +74,13 @@ bool ICollection.IsReadOnly /// The index of the item to get or set. /// is not a valid index in this list. /// This property is set and the list is read-only. - public T this[int index] - { - get - { + public T this[int index] { + get { CheckExistingIndexArgument(this.Count, index); return DoGetItem(index); } - set - { + set { CheckExistingIndexArgument(this.Count, index); DoSetItem(index, value); } @@ -109,8 +97,7 @@ public T this[int index] /// /// This list is read-only. /// - public void Insert(int index, T item) - { + public void Insert(int index, T item) { CheckNewIndexArgument(Count, index); DoInsert(index, item); } @@ -125,8 +112,7 @@ public void Insert(int index, T item) /// /// This list is read-only. /// - public void RemoveAt(int index) - { + public void RemoveAt(int index) { CheckExistingIndexArgument(Count, index); DoRemoveAt(index); } @@ -136,12 +122,10 @@ public void RemoveAt(int index) /// /// The object to locate in this list. /// The index of if found in this list; otherwise, -1. - public int IndexOf(T item) - { + public int IndexOf(T item) { var comparer = EqualityComparer.Default; int ret = 0; - foreach (var sourceItem in this) - { + foreach (var sourceItem in this) { if (comparer.Equals(item, sourceItem)) return ret; ++ret; @@ -157,8 +141,7 @@ public int IndexOf(T item) /// /// This list is read-only. /// - void ICollection.Add(T item) - { + void ICollection.Add(T item) { DoInsert(Count, item); } @@ -169,8 +152,7 @@ void ICollection.Add(T item) /// /// true if is found in this list; otherwise, false. /// - bool ICollection.Contains(T item) - { + bool ICollection.Contains(T item) { return this.Contains(item, null); } @@ -190,15 +172,13 @@ bool ICollection.Contains(T item) /// -or- /// The number of elements in the source is greater than the available space from to the end of the destination . /// - void ICollection.CopyTo(T[] array, int arrayIndex) - { + void ICollection.CopyTo(T[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array", "Array is null"); int count = this.Count; CheckRangeArguments(array.Length, arrayIndex, count); - for (int i = 0; i != count; ++i) - { + for (int i = 0; i != count; ++i) { array[arrayIndex + i] = this[i]; } } @@ -213,8 +193,7 @@ void ICollection.CopyTo(T[] array, int arrayIndex) /// /// This list is read-only. /// - public bool Remove(T item) - { + public bool Remove(T item) { int index = IndexOf(item); if (index == -1) return false; @@ -229,11 +208,9 @@ public bool Remove(T item) /// /// A that can be used to iterate through the collection. /// - public IEnumerator GetEnumerator() - { + public IEnumerator GetEnumerator() { int count = this.Count; - for (int i = 0; i != count; ++i) - { + for (int i = 0; i != count; ++i) { yield return DoGetItem(i); } } @@ -244,8 +221,7 @@ public IEnumerator GetEnumerator() /// /// An object that can be used to iterate through the collection. /// - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } @@ -257,15 +233,12 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() /// /// The item to test. /// true if the item is appropriate to store in this container; otherwise, false. - private bool ObjectIsT(object item) - { - if (item is T) - { + private bool ObjectIsT(object item) { + if (item is T) { return true; } - if (item == null) - { + if (item == null) { var type = typeof(T); if (type.IsClass && !type.IsPointer) return true; // classes, arrays, and delegates @@ -278,93 +251,76 @@ private bool ObjectIsT(object item) return false; } - int System.Collections.IList.Add(object value) - { + int System.Collections.IList.Add(object value) { if (!ObjectIsT(value)) throw new ArgumentException("Item is not of the correct type.", "value"); AddToBack((T)value); return Count - 1; } - bool System.Collections.IList.Contains(object value) - { + bool System.Collections.IList.Contains(object value) { if (!ObjectIsT(value)) throw new ArgumentException("Item is not of the correct type.", "value"); return this.Contains((T)value); } - int System.Collections.IList.IndexOf(object value) - { + int System.Collections.IList.IndexOf(object value) { if (!ObjectIsT(value)) throw new ArgumentException("Item is not of the correct type.", "value"); return IndexOf((T)value); } - void System.Collections.IList.Insert(int index, object value) - { + void System.Collections.IList.Insert(int index, object value) { if (!ObjectIsT(value)) throw new ArgumentException("Item is not of the correct type.", "value"); Insert(index, (T)value); } - bool System.Collections.IList.IsFixedSize - { + bool System.Collections.IList.IsFixedSize { get { return false; } } - bool System.Collections.IList.IsReadOnly - { + bool System.Collections.IList.IsReadOnly { get { return false; } } - void System.Collections.IList.Remove(object value) - { + void System.Collections.IList.Remove(object value) { if (!ObjectIsT(value)) throw new ArgumentException("Item is not of the correct type.", "value"); Remove((T)value); } - object System.Collections.IList.this[int index] - { - get - { + object System.Collections.IList.this[int index] { + get { return this[index]; } - set - { + set { if (!ObjectIsT(value)) throw new ArgumentException("Item is not of the correct type.", "value"); this[index] = (T)value; } } - void System.Collections.ICollection.CopyTo(Array array, int index) - { + void System.Collections.ICollection.CopyTo(Array array, int index) { if (array == null) throw new ArgumentNullException("array", "Destination array cannot be null."); CheckRangeArguments(array.Length, index, Count); - for (int i = 0; i != Count; ++i) - { - try - { + for (int i = 0; i != Count; ++i) { + try { array.SetValue(this[i], index + i); - } - catch (InvalidCastException ex) - { + } catch (InvalidCastException ex) { throw new ArgumentException("Destination array is of incorrect type.", ex); } } } - bool System.Collections.ICollection.IsSynchronized - { + bool System.Collections.ICollection.IsSynchronized { get { return false; } } - object System.Collections.ICollection.SyncRoot - { + object System.Collections.ICollection.SyncRoot { get { return this; } } @@ -377,10 +333,8 @@ object System.Collections.ICollection.SyncRoot /// The length of the source. This parameter is not checked for validity. /// The index into the source. /// is not a valid index to an insertion point for the source. - private static void CheckNewIndexArgument(int sourceLength, int index) - { - if (index < 0 || index > sourceLength) - { + private static void CheckNewIndexArgument(int sourceLength, int index) { + if (index < 0 || index > sourceLength) { throw new ArgumentOutOfRangeException("index", "Invalid new index " + index + " for source length " + sourceLength); } } @@ -391,10 +345,8 @@ private static void CheckNewIndexArgument(int sourceLength, int index) /// The length of the source. This parameter is not checked for validity. /// The index into the source. /// is not a valid index to an existing element for the source. - private static void CheckExistingIndexArgument(int sourceLength, int index) - { - if (index < 0 || index >= sourceLength) - { + private static void CheckExistingIndexArgument(int sourceLength, int index) { + if (index < 0 || index >= sourceLength) { throw new ArgumentOutOfRangeException("index", "Invalid existing index " + index + " for source length " + sourceLength); } } @@ -407,20 +359,16 @@ private static void CheckExistingIndexArgument(int sourceLength, int index) /// The number of elements in the range. /// Either or is less than 0. /// The range [offset, offset + count) is not within the range [0, sourceLength). - private static void CheckRangeArguments(int sourceLength, int offset, int count) - { - if (offset < 0) - { + private static void CheckRangeArguments(int sourceLength, int offset, int count) { + if (offset < 0) { throw new ArgumentOutOfRangeException("offset", "Invalid offset " + offset); } - if (count < 0) - { + if (count < 0) { throw new ArgumentOutOfRangeException("count", "Invalid count " + count); } - if (sourceLength - offset < count) - { + if (sourceLength - offset < count) { throw new ArgumentException("Invalid offset (" + offset + ") or count + (" + count + ") for source length " + sourceLength); } } @@ -430,26 +378,22 @@ private static void CheckRangeArguments(int sourceLength, int offset, int count) /// /// Gets a value indicating whether this instance is empty. /// - private bool IsEmpty - { + private bool IsEmpty { get { return Count == 0; } } /// /// Gets a value indicating whether this instance is at full capacity. /// - private bool IsFull - { + private bool IsFull { get { return Count == Capacity; } } /// /// Gets a value indicating whether the buffer is "split" (meaning the beginning of the view is at a later index in than the end). /// - private bool IsSplit - { - get - { + private bool IsSplit { + get { // Overflow-safe version of "(offset + Count) > Capacity" return offset > (Capacity - Count); } @@ -459,15 +403,12 @@ private bool IsSplit /// Gets or sets the capacity for this deque. This value must always be greater than zero, and this property cannot be set to a value less than . /// /// Capacity cannot be set to a value less than . - public int Capacity - { - get - { + public int Capacity { + get { return buffer.Length; } - set - { + set { if (value < 1) throw new ArgumentOutOfRangeException("value", "Capacity must be greater than 0."); @@ -479,15 +420,12 @@ public int Capacity // Create the new buffer and copy our existing range. T[] newBuffer = new T[value]; - if (IsSplit) - { + if (IsSplit) { // The existing buffer is split, so we have to copy it in parts int length = Capacity - offset; Array.Copy(buffer, offset, newBuffer, 0, length); Array.Copy(buffer, 0, newBuffer, length, Count - length); - } - else - { + } else { // The existing buffer is whole Array.Copy(buffer, offset, newBuffer, 0, Count); } @@ -503,14 +441,13 @@ public int Capacity /// /// The number of elements contained in this deque. public int Count { get; private set; } - + /// /// Applies the offset to , resulting in a buffer index. /// /// The deque index. /// The buffer index. - private int DequeIndexToBufferIndex(int index) - { + private int DequeIndexToBufferIndex(int index) { return (index + offset) % Capacity; } @@ -519,8 +456,7 @@ private int DequeIndexToBufferIndex(int index) /// /// The zero-based view index of the element to get. This index is guaranteed to be valid. /// The element at the specified index. - private T DoGetItem(int index) - { + private T DoGetItem(int index) { return buffer[DequeIndexToBufferIndex(index)]; } @@ -529,8 +465,7 @@ private T DoGetItem(int index) /// /// The zero-based view index of the element to get. This index is guaranteed to be valid. /// The element to store in the list. - private void DoSetItem(int index, T item) - { + private void DoSetItem(int index, T item) { buffer[DequeIndexToBufferIndex(index)] = item; } @@ -539,17 +474,13 @@ private void DoSetItem(int index, T item) /// /// The zero-based view index at which the element should be inserted. This index is guaranteed to be valid. /// The element to store in the list. - private void DoInsert(int index, T item) - { + private void DoInsert(int index, T item) { EnsureCapacityForOneElement(); - if (index == 0) - { + if (index == 0) { DoAddToFront(item); return; - } - else if (index == Count) - { + } else if (index == Count) { DoAddToBack(item); return; } @@ -561,15 +492,11 @@ private void DoInsert(int index, T item) /// Removes an element at the specified view index. /// /// The zero-based view index of the element to remove. This index is guaranteed to be valid. - private void DoRemoveAt(int index) - { - if (index == 0) - { + private void DoRemoveAt(int index) { + if (index == 0) { DoRemoveFromFront(); return; - } - else if (index == Count - 1) - { + } else if (index == Count - 1) { DoRemoveFromBack(); return; } @@ -582,8 +509,7 @@ private void DoRemoveAt(int index) /// /// The value by which to increase . May not be negative. /// The value of after it was incremented. - private int PostIncrement(int value) - { + private int PostIncrement(int value) { int ret = offset; offset += value; offset %= Capacity; @@ -595,8 +521,7 @@ private int PostIncrement(int value) /// /// The value by which to reduce . May not be negative or greater than . /// The value of before it was decremented. - private int PreDecrement(int value) - { + private int PreDecrement(int value) { offset -= value; if (offset < 0) offset += Capacity; @@ -607,8 +532,7 @@ private int PreDecrement(int value) /// Inserts a single element to the back of the view. must be false when this method is called. /// /// The element to insert. - private void DoAddToBack(T value) - { + private void DoAddToBack(T value) { buffer[DequeIndexToBufferIndex(Count)] = value; ++Count; } @@ -617,8 +541,7 @@ private void DoAddToBack(T value) /// Inserts a single element to the front of the view. must be false when this method is called. /// /// The element to insert. - private void DoAddToFront(T value) - { + private void DoAddToFront(T value) { buffer[PreDecrement(1)] = value; ++Count; } @@ -627,8 +550,7 @@ private void DoAddToFront(T value) /// Removes and returns the last element in the view. must be false when this method is called. /// /// The former last element. - private T DoRemoveFromBack() - { + private T DoRemoveFromBack() { T ret = buffer[DequeIndexToBufferIndex(Count - 1)]; --Count; return ret; @@ -638,8 +560,7 @@ private T DoRemoveFromBack() /// Removes and returns the first element in the view. must be false when this method is called. /// /// The former first element. - private T DoRemoveFromFront() - { + private T DoRemoveFromFront() { --Count; return buffer[PostIncrement(1)]; } @@ -650,11 +571,9 @@ private T DoRemoveFromFront() /// The index into the view at which the elements are to be inserted. /// The elements to insert. /// The number of elements in . Must be greater than zero, and the sum of and must be less than or equal to . - private void DoInsertRange(int index, IEnumerable collection, int collectionCount) - { + private void DoInsertRange(int index, IEnumerable collection, int collectionCount) { // Make room in the existing list - if (index < Count / 2) - { + if (index < Count / 2) { // Inserting into the first half of the list // Move lower items down: [0, index) -> [Capacity - collectionCount, Capacity - collectionCount + index) @@ -667,9 +586,7 @@ private void DoInsertRange(int index, IEnumerable collection, int collectionC // Rotate to the new view this.PreDecrement(collectionCount); - } - else - { + } else { // Inserting into the second half of the list // Move higher items up: [index, count) -> [index + collectionCount, collectionCount + count) @@ -681,8 +598,7 @@ private void DoInsertRange(int index, IEnumerable collection, int collectionC // Copy new items into place int i = index; - foreach (T item in collection) - { + foreach (T item in collection) { buffer[DequeIndexToBufferIndex(i)] = item; ++i; } @@ -696,24 +612,19 @@ private void DoInsertRange(int index, IEnumerable collection, int collectionC /// /// The index into the view at which the range begins. /// The number of elements in the range. This must be greater than 0 and less than or equal to . - private void DoRemoveRange(int index, int collectionCount) - { - if (index == 0) - { + private void DoRemoveRange(int index, int collectionCount) { + if (index == 0) { // Removing from the beginning: rotate to the new view this.PostIncrement(collectionCount); Count -= collectionCount; return; - } - else if (index == Count - collectionCount) - { + } else if (index == Count - collectionCount) { // Removing from the ending: trim the existing view Count -= collectionCount; return; } - if ((index + (collectionCount / 2)) < Count / 2) - { + if ((index + (collectionCount / 2)) < Count / 2) { // Removing from first half of list // Move lower items up: [0, index) -> [collectionCount, collectionCount + index) @@ -724,9 +635,7 @@ private void DoRemoveRange(int index, int collectionCount) // Rotate to new view this.PostIncrement(collectionCount); - } - else - { + } else { // Removing from second half of list // Move higher items down: [index + collectionCount, count) -> [index, count - collectionCount) @@ -743,10 +652,8 @@ private void DoRemoveRange(int index, int collectionCount) /// /// Doubles the capacity if necessary to make room for one more element. When this method returns, is false. /// - private void EnsureCapacityForOneElement() - { - if (this.IsFull) - { + private void EnsureCapacityForOneElement() { + if (this.IsFull) { this.Capacity = this.Capacity * 2; } } @@ -755,8 +662,7 @@ private void EnsureCapacityForOneElement() /// Inserts a single element at the back of this deque. /// /// The element to insert. - public void AddToBack(T value) - { + public void AddToBack(T value) { EnsureCapacityForOneElement(); DoAddToBack(value); } @@ -765,8 +671,7 @@ public void AddToBack(T value) /// Inserts a single element at the front of this deque. /// /// The element to insert. - public void AddToFront(T value) - { + public void AddToFront(T value) { EnsureCapacityForOneElement(); DoAddToFront(value); } @@ -777,19 +682,16 @@ public void AddToFront(T value) /// The index at which the collection is inserted. /// The collection of elements to insert. /// is not a valid index to an insertion point for the source. - public void InsertRange(int index, IEnumerable collection) - { + public void InsertRange(int index, IEnumerable collection) { int collectionCount = collection.Count(); CheckNewIndexArgument(Count, index); // Overflow-safe check for "this.Count + collectionCount > this.Capacity" - if (collectionCount > Capacity - Count) - { + if (collectionCount > Capacity - Count) { this.Capacity = checked(Count + collectionCount); } - if (collectionCount == 0) - { + if (collectionCount == 0) { return; } @@ -803,12 +705,10 @@ public void InsertRange(int index, IEnumerable collection) /// The number of elements to remove. /// Either or is less than 0. /// The range [, + ) is not within the range [0, ). - public void RemoveRange(int offset, int count) - { + public void RemoveRange(int offset, int count) { CheckRangeArguments(Count, offset, count); - if (count == 0) - { + if (count == 0) { return; } @@ -820,8 +720,7 @@ public void RemoveRange(int offset, int count) /// /// The former last element. /// The deque is empty. - public T RemoveFromBack() - { + public T RemoveFromBack() { if (this.IsEmpty) throw new InvalidOperationException("The deque is empty."); @@ -833,8 +732,7 @@ public T RemoveFromBack() /// /// The former first element. /// The deque is empty. - public T RemoveFromFront() - { + public T RemoveFromFront() { if (this.IsEmpty) throw new InvalidOperationException("The deque is empty."); @@ -844,27 +742,22 @@ public T RemoveFromFront() /// /// Removes all items from this deque. /// - public void Clear() - { + public void Clear() { this.offset = 0; this.Count = 0; } [DebuggerNonUserCode] - private sealed class DebugView - { + private sealed class DebugView { private readonly Deque deque; - public DebugView(Deque deque) - { + public DebugView(Deque deque) { this.deque = deque; } [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] - public T[] Items - { - get - { + public T[] Items { + get { var array = new T[deque.Count]; ((ICollection)deque).CopyTo(array, 0); return array; diff --git a/OpenUtau.Core/ThirdParty/F0Smoother.cs b/OpenUtau.Core/ThirdParty/F0Smoother.cs index 0f063ecbc..9587f476c 100644 --- a/OpenUtau.Core/ThirdParty/F0Smoother.cs +++ b/OpenUtau.Core/ThirdParty/F0Smoother.cs @@ -124,7 +124,7 @@ private List ReduceIndices(List indices) { private List GetAdjustedWidths(List f0List, List rapidF0ChangeIndices) { var adjustedWidths = new List(); int len = f0List.Count; - for(int i = 0;i< rapidF0ChangeIndices.Count;i++) { + for (int i = 0; i < rapidF0ChangeIndices.Count; i++) { var idx = rapidF0ChangeIndices[i]; int width = SmoothenWidthList[idx]; while ((idx - width) < 0 || (idx + width + 1) > len) diff --git a/OpenUtau.Core/Ustx/UPart.cs b/OpenUtau.Core/Ustx/UPart.cs index 45a755cf8..eb50e2408 100644 --- a/OpenUtau.Core/Ustx/UPart.cs +++ b/OpenUtau.Core/Ustx/UPart.cs @@ -66,7 +66,7 @@ public override int GetMinDurTick(UProject project) { project.timeAxis.TickPosToBarBeat(endTicks, out int bar, out int beat, out int remainingTicks); return project.timeAxis.BarBeatToTickPos(bar, beat + 1) - position; } - + public override int GetMaxPosiTick(UProject project) { int maxStartTick = position + (notes.FirstOrDefault()?.position ?? Duration); project.timeAxis.TickPosToBarBeat(maxStartTick, out int bar, out int beat, out int remainingTicks); diff --git a/OpenUtau.Core/Ustx/UTrack.cs b/OpenUtau.Core/Ustx/UTrack.cs index 841d0d707..166e511aa 100644 --- a/OpenUtau.Core/Ustx/UTrack.cs +++ b/OpenUtau.Core/Ustx/UTrack.cs @@ -255,7 +255,7 @@ public void AfterLoad(UProject project) { if (Singer != null && Singer.Found) { if (string.IsNullOrEmpty(RendererSettings.renderer)) { RendererSettings.renderer = Renderers.GetDefaultRenderer(Singer.SingerType); - }; + } } TrackNo = project.tracks.IndexOf(this); if (!Solo && Mute) { diff --git a/OpenUtau.Core/Util/Base64.cs b/OpenUtau.Core/Util/Base64.cs index b2b7f7419..827bcf512 100644 --- a/OpenUtau.Core/Util/Base64.cs +++ b/OpenUtau.Core/Util/Base64.cs @@ -5,31 +5,22 @@ using Serilog; namespace OpenUtau.Core.Util { - public static class Base64 - { - public static string Base64EncodeInt12(int[] data) - { + public static class Base64 { + public static string Base64EncodeInt12(int[] data) { List l = new List(); - foreach (int d in data) - { + foreach (int d in data) { l.Add(Base64EncodeInt12(d)); } StringBuilder base64 = new StringBuilder(); string last = string.Empty; int dups = 0; - foreach (string b in l) - { - if (last == b) - { + foreach (string b in l) { + if (last == b) { dups++; - } - else if (dups == 0) - { + } else if (dups == 0) { base64.Append(b); - } - else - { + } else { base64.Append('#'); base64.Append(dups); base64.Append('#'); @@ -38,8 +29,7 @@ public static string Base64EncodeInt12(int[] data) } last = b; } - if (dups != 0) - { + if (dups != 0) { base64.Append('#'); base64.Append(dups); base64.Append('#'); @@ -49,10 +39,8 @@ public static string Base64EncodeInt12(int[] data) private const string intToBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - private static string Base64EncodeInt12(int data) - { - if (data < 0) - { + private static string Base64EncodeInt12(int data) { + if (data < 0) { data += 4096; } @@ -62,7 +50,7 @@ private static string Base64EncodeInt12(int data) return new string(base64); } - public static void Base64ToFile(string base64str,string filePath) { + public static void Base64ToFile(string base64str, string filePath) { try { byte[] bytes = Convert.FromBase64String(base64str); diff --git a/OpenUtau.Core/Util/IniFileClass.cs b/OpenUtau.Core/Util/IniFileClass.cs index 96e9d5499..a967ee2b0 100644 --- a/OpenUtau.Core/Util/IniFileClass.cs +++ b/OpenUtau.Core/Util/IniFileClass.cs @@ -6,17 +6,14 @@ using System.Text; using System.Threading.Tasks; -namespace OpenUtau.Core.Util -{ +namespace OpenUtau.Core.Util { /// /// ini文件操作类 /// - class IniFileClass - { + class IniFileClass { public IniFileClass() { } - public IniFileClass(string szPath) - { + public IniFileClass(string szPath) { m_Path = szPath; } #region 段信息的获取 @@ -60,8 +57,7 @@ private static extern int getKeyValue(string section, string key, string lpDefau /// /// ini文件路径 /// - private string Path - { + private string Path { set { m_Path = value; } get { return m_Path; } } @@ -69,14 +65,11 @@ private string Path /// /// 读取所有段名 /// - public string[] SectionNames - { - get - { + public string[] SectionNames { + get { string buffer = new string('\0', 32768); int nlen = getSectionNames(buffer, 32768 - 1, m_Path) - 1; - if (nlen > 0) - { + if (nlen > 0) { return buffer.Substring(0, nlen).Split(sept); } return null; @@ -89,18 +82,15 @@ public string[] SectionNames /// 段名 /// 读取的数据大小(字节) /// 成功则不为null - public string[] SectionValues(string section, int bufferSize) - { + public string[] SectionValues(string section, int bufferSize) { string buffer = new string('\0', bufferSize); int nlen = getSectionValues(section, buffer, bufferSize, m_Path) - 1; - if (nlen > 0) - { + if (nlen > 0) { return buffer.Substring(0, nlen).Split(sept); } return null; } - public string[] SectionValues(string section) - { + public string[] SectionValues(string section) { return SectionValues(section, 32768); } @@ -110,20 +100,15 @@ public string[] SectionValues(string section) /// 段名 /// 读取的数据大小(字节) /// 成功则不为null - public Dictionary SectionValuesEx(string section, int bufferSize) - { + public Dictionary SectionValuesEx(string section, int bufferSize) { string[] sztmp = SectionValues(section, bufferSize); - if (sztmp != null) - { + if (sztmp != null) { int ArrayLen = sztmp.Length; - if (ArrayLen > 0) - { + if (ArrayLen > 0) { Dictionary dtRet = new Dictionary(); - for (int i = 0; i < ArrayLen; i++) - { + for (int i = 0; i < ArrayLen; i++) { int pos1 = sztmp[i].IndexOf('='); - if (pos1 > 1) - { + if (pos1 > 1) { int nlen = sztmp[i].Length; // 取键名,键值 pos1++; @@ -136,8 +121,7 @@ public Dictionary SectionValuesEx(string section, int bufferSize } return null; } - public Dictionary SectionValuesEx(string section) - { + public Dictionary SectionValuesEx(string section) { return SectionValuesEx(section, 32768); } @@ -147,8 +131,7 @@ public Dictionary SectionValuesEx(string section) /// /// 段的数据(如果为null则删除这个段) /// 成功则为true - public bool setSectionValue(string section, string szValue) - { + public bool setSectionValue(string section, string szValue) { return setSectionValue(section, szValue, m_Path); } @@ -158,8 +141,7 @@ public bool setSectionValue(string section, string szValue) /// /// /// 成功则不为-1 - public int getKeyIntValue(string section, string key) - { + public int getKeyIntValue(string section, string key) { return getKeyIntValue(section, key, -1, m_Path); } @@ -170,8 +152,7 @@ public int getKeyIntValue(string section, string key) /// /// /// 成功则为true - public bool setKeyIntValue(string section, string key, int dwValue) - { + public bool setKeyIntValue(string section, string key, int dwValue) { return setKeyValue(section, key, dwValue.ToString(), m_Path); } @@ -181,8 +162,7 @@ public bool setKeyIntValue(string section, string key, int dwValue) /// /// /// 成功则不为null - public string getKeyValue(string section, string key) - { + public string getKeyValue(string section, string key) { string szBuffer = new string('0', 256); int nlen = getKeyValue(section, key, string.Empty, szBuffer, 256, m_Path); string ret = szBuffer.Substring(0, nlen); @@ -196,8 +176,7 @@ public string getKeyValue(string section, string key) /// /// /// 成功则为true - public bool setKeyValue(string Section, string key, string szValue) - { + public bool setKeyValue(string Section, string key, string szValue) { return setKeyValue(Section, key, szValue, m_Path); } }//end class CIni diff --git a/OpenUtau.Core/Util/LocalizedSort.cs b/OpenUtau.Core/Util/LocalizedSort.cs index 709ff19b6..f15af28d8 100644 --- a/OpenUtau.Core/Util/LocalizedSort.cs +++ b/OpenUtau.Core/Util/LocalizedSort.cs @@ -20,10 +20,10 @@ public static class LocalizedSort { public static IEnumerable LocalizedOrderBy(this IEnumerable source, Func selector) { var sortingOrder = Preferences.Default.SortingOrder; CultureInfo culture; - if(sortingOrder == null) { + if (sortingOrder == null) { //Follow the display language culture = CultureInfo.GetCultureInfo(Preferences.Default.Language); - } else if(sortingOrder == String.Empty){ + } else if (sortingOrder == String.Empty) { //Don't translate culture = CultureInfo.InvariantCulture; } else { diff --git a/OpenUtau.Core/Util/MusicMath.cs b/OpenUtau.Core/Util/MusicMath.cs index f8123bd9a..7ec93abfb 100644 --- a/OpenUtau.Core/Util/MusicMath.cs +++ b/OpenUtau.Core/Util/MusicMath.cs @@ -32,7 +32,7 @@ public enum KeyColor { White, Black } { "B", 11 }, }; - public static readonly string[] Solfeges = { + public static readonly string[] Solfeges = { "do", "", "re", @@ -121,7 +121,7 @@ public static double getZoomRatio(double quarterWidth, int beatPerBar, int beatU const double ep = 0.001; public static double SinEasingInOut(double x0, double x1, double y0, double y1, double x) { - if(x1 - x0 < ep){ + if (x1 - x0 < ep) { return y1; } return y0 + (y1 - y0) * (1 - Math.Cos((x - x0) / (x1 - x0) * Math.PI)) / 2; @@ -132,7 +132,7 @@ public static double SinEasingInOutX(double x0, double x1, double y0, double y1, } public static double SinEasingIn(double x0, double x1, double y0, double y1, double x) { - if(x1 - x0 < ep){ + if (x1 - x0 < ep) { return y1; } return y0 + (y1 - y0) * (1 - Math.Cos((x - x0) / (x1 - x0) * Math.PI / 2)); @@ -143,7 +143,7 @@ public static double SinEasingInX(double x0, double x1, double y0, double y1, do } public static double SinEasingOut(double x0, double x1, double y0, double y1, double x) { - if(x1 - x0 < ep){ + if (x1 - x0 < ep) { return y1; } return y0 + (y1 - y0) * Math.Sin((x - x0) / (x1 - x0) * Math.PI / 2); @@ -154,7 +154,7 @@ public static double SinEasingOutX(double x0, double x1, double y0, double y1, d } public static double Linear(double x0, double x1, double y0, double y1, double x) { - if(x1 - x0 < ep){ + if (x1 - x0 < ep) { return y1; } return y0 + (y1 - y0) * (x - x0) / (x1 - x0); diff --git a/OpenUtau.Core/Util/NotePresets.cs b/OpenUtau.Core/Util/NotePresets.cs index 7a46e715b..f918600bb 100644 --- a/OpenUtau.Core/Util/NotePresets.cs +++ b/OpenUtau.Core/Util/NotePresets.cs @@ -72,7 +72,7 @@ public class PortamentoPreset { public int PortamentoLength = 80; public int PortamentoStart = -40; - public PortamentoPreset (string name, int length, int start) { + public PortamentoPreset(string name, int length, int start) { Name = name; PortamentoLength = length; PortamentoStart = start; diff --git a/OpenUtau.Core/Util/Onnx.cs b/OpenUtau.Core/Util/Onnx.cs index dd80a138e..2b895811f 100644 --- a/OpenUtau.Core/Util/Onnx.cs +++ b/OpenUtau.Core/Util/Onnx.cs @@ -37,15 +37,15 @@ public static List getGpuInfo() { List gpuList = new List(); if (OS.IsWindows()) { DXGI.CreateDXGIFactory1(out IDXGIFactory1 factory); - for(int deviceId = 0; deviceId < 32; deviceId++) { + for (int deviceId = 0; deviceId < 32; deviceId++) { factory.EnumAdapters1(deviceId, out IDXGIAdapter1 adapterOut); - if(adapterOut is null) { + if (adapterOut is null) { break; } gpuList.Add(new GpuInfo { deviceId = deviceId, description = adapterOut.Description.Description - }) ; + }); } } if (gpuList.Count == 0) { @@ -56,7 +56,7 @@ public static List getGpuInfo() { return gpuList; } - private static SessionOptions getOnnxSessionOptions(){ + private static SessionOptions getOnnxSessionOptions() { SessionOptions options = new SessionOptions(); List runnerOptions = getRunnerOptions(); string runner = Preferences.Default.OnnxRunner; @@ -66,7 +66,7 @@ private static SessionOptions getOnnxSessionOptions(){ if (!runnerOptions.Contains(runner)) { runner = "CPU"; } - switch(runner){ + switch (runner) { case "DirectML": options.AppendExecutionProvider_DML(Preferences.Default.OnnxGpu); break; @@ -78,11 +78,11 @@ private static SessionOptions getOnnxSessionOptions(){ } public static InferenceSession getInferenceSession(byte[] model) { - return new InferenceSession(model,getOnnxSessionOptions()); + return new InferenceSession(model, getOnnxSessionOptions()); } public static InferenceSession getInferenceSession(string modelPath) { - return new InferenceSession(modelPath,getOnnxSessionOptions()); + return new InferenceSession(modelPath, getOnnxSessionOptions()); } public static void VerifyInputNames(InferenceSession session, IEnumerable inputs) { diff --git a/OpenUtau.Core/Util/Preferences.cs b/OpenUtau.Core/Util/Preferences.cs index 20f15b763..8de43935a 100644 --- a/OpenUtau.Core/Util/Preferences.cs +++ b/OpenUtau.Core/Util/Preferences.cs @@ -40,26 +40,26 @@ public static void SetSingerSearchPaths(List paths) { Save(); } - public static void AddRecentFileIfEnabled(string filePath){ + public static void AddRecentFileIfEnabled(string filePath) { //Users can choose adding .ust, .vsqx and .mid files to recent files or not string ext = Path.GetExtension(filePath); - switch(ext){ + switch (ext) { case ".ustx": AddRecentFile(filePath); break; case ".mid": case ".midi": - if(Preferences.Default.RememberMid){ + if (Preferences.Default.RememberMid) { AddRecentFile(filePath); } break; case ".ust": - if(Preferences.Default.RememberUst){ + if (Preferences.Default.RememberUst) { AddRecentFile(filePath); } break; case ".vsqx": - if(Preferences.Default.RememberVsqx){ + if (Preferences.Default.RememberVsqx) { AddRecentFile(filePath); } break; @@ -89,7 +89,7 @@ private static void Load() { if (File.Exists(PathManager.Inst.PrefsFilePath)) { Default = JsonConvert.DeserializeObject( File.ReadAllText(PathManager.Inst.PrefsFilePath, Encoding.UTF8)); - if(Default == null) { + if (Default == null) { Reset(); return; } diff --git a/OpenUtau.Core/Util/ProcessRunner.cs b/OpenUtau.Core/Util/ProcessRunner.cs index b599de30d..95757ff07 100644 --- a/OpenUtau.Core/Util/ProcessRunner.cs +++ b/OpenUtau.Core/Util/ProcessRunner.cs @@ -14,7 +14,7 @@ public static void Run(string file, string args, ILogger logger, string workDir var threadId = Thread.CurrentThread.ManagedThreadId; using (var proc = new Process()) { proc.StartInfo = new ProcessStartInfo(file, args) { - Environment = {{"LANG", "ja_JP.utf8"}}, + Environment = { { "LANG", "ja_JP.utf8" } }, UseShellExecute = false, RedirectStandardOutput = DebugSwitch, RedirectStandardError = true, diff --git a/OpenUtau.Core/Util/SplitLyrics.cs b/OpenUtau.Core/Util/SplitLyrics.cs index caa193118..9245aa22e 100644 --- a/OpenUtau.Core/Util/SplitLyrics.cs +++ b/OpenUtau.Core/Util/SplitLyrics.cs @@ -12,7 +12,7 @@ public static class SplitLyrics { static Regex contracted = new Regex(@"[ゃゅょぁぃぅぇぉャュョァィゥェォ]"); public static List Split(string? text) { - if(text == null){ + if (text == null) { return new List(); } var lyrics = new List(); diff --git a/OpenUtau.Core/Util/TimeAxis.cs b/OpenUtau.Core/Util/TimeAxis.cs index d7523ecd8..4e4b03547 100644 --- a/OpenUtau.Core/Util/TimeAxis.cs +++ b/OpenUtau.Core/Util/TimeAxis.cs @@ -51,7 +51,7 @@ public void BuildSegments(UProject project) { posTick = timeSigSegments.Last().tickPos + timeSigSegments.Last().ticksPerBar * (timesig.barPosition - lastBarPos); } else { - if(timesig.barPosition != 0) { + if (timesig.barPosition != 0) { throw new Exception("First time signature must be at bar 0."); } } @@ -78,7 +78,7 @@ public void BuildSegments(UProject project) { for (var i = 0; i < project.tempos.Count; ++i) { var tempo = project.tempos[i]; if (i == 0) { - if(tempo.position != 0) { + if (tempo.position != 0) { throw new Exception("First tempo must be at tick 0."); } } @@ -155,7 +155,7 @@ public double MsBetweenTickPos(double tickPos, double tickEnd) { /// Duration in ticks public int MsToTickAt(double offsetMs, int refTickPos) { return TicksBetweenMsPos( - TickPosToMsPos(refTickPos), + TickPosToMsPos(refTickPos), TickPosToMsPos(refTickPos) + offsetMs); } diff --git a/OpenUtau.Core/VocalShaper/Complex.cs b/OpenUtau.Core/VocalShaper/Complex.cs index 9a4eb3e61..4657f85ee 100644 --- a/OpenUtau.Core/VocalShaper/Complex.cs +++ b/OpenUtau.Core/VocalShaper/Complex.cs @@ -1,78 +1,55 @@ using System; -namespace VocalShaper -{ - internal struct Complex - { +namespace VocalShaper { + internal struct Complex { double a; double b; - public double Real - { + public double Real { get { return a; } set { a = value; } } - public double Imaginary - { + public double Imaginary { get { return b; } set { b = value; } } public double Norm => Math.Sqrt(a * a + b * b); - public Complex(double a, double b) - { + public Complex(double a, double b) { this.a = a; this.b = b; } - public Complex Conjugate() - { + public Complex Conjugate() { return new Complex(a, -b); } - public static Complex operator +(Complex c1, Complex c2) - { + public static Complex operator +(Complex c1, Complex c2) { return new Complex(c1.a + c2.a, c1.b + c2.b); } - public static Complex operator -(Complex c1, Complex c2) - { + public static Complex operator -(Complex c1, Complex c2) { return new Complex(c1.a - c2.a, c1.b - c2.b); } - public static Complex operator *(Complex c1, Complex c2) - { + public static Complex operator *(Complex c1, Complex c2) { return new Complex(c1.a * c2.a - c1.b * c2.b, c1.b * c2.a + c1.a * c2.b); } - public static Complex operator *(float d, Complex c2) - { + public static Complex operator *(float d, Complex c2) { return new Complex(d * c2.a, d * c2.b); } - public static Complex operator *(Complex c2, double d) - { + public static Complex operator *(Complex c2, double d) { return new Complex(d * c2.a, d * c2.b); } - public static Complex operator /(Complex c1, Complex c2) - { + public static Complex operator /(Complex c1, Complex c2) { return c1 * c2.Conjugate(); } - public static Complex operator ^(Complex c, int n) - { - if (n < -1) - { + public static Complex operator ^(Complex c, int n) { + if (n < -1) { return c.Conjugate() ^ (-n); - } - else if (n == -1) - { + } else if (n == -1) { return c.Conjugate(); - } - else if (n == 0) - { + } else if (n == 0) { return new Complex(1, 0); - } - else if (n == 1) - { + } else if (n == 1) { return c; - } - else - { + } else { Complex tmp = c; - for (int i = 2; i <= n; i++) - { + for (int i = 2; i <= n; i++) { tmp *= c; } return tmp; diff --git a/OpenUtau.Core/VocalShaper/VSMath.cs b/OpenUtau.Core/VocalShaper/VSMath.cs index ed99199c0..187fbc16f 100644 --- a/OpenUtau.Core/VocalShaper/VSMath.cs +++ b/OpenUtau.Core/VocalShaper/VSMath.cs @@ -1,21 +1,17 @@ using System; using System.Collections.Generic; -namespace VocalShaper -{ - internal static class VSMath - { +namespace VocalShaper { + internal static class VSMath { /// /// 获取不大于n的最大2的N次方的整数 /// /// /// - public static int Max2N(int n) - { + public static int Max2N(int n) { int tmp = -1; - do - { + do { tmp++; } while (Math.Pow(2, tmp) <= n); @@ -27,11 +23,9 @@ public static int Max2N(int n) /// /// /// - public static int Min2N(int n) - { + public static int Min2N(int n) { int tmp = 0; - while (Math.Pow(2, tmp) < n) - { + while (Math.Pow(2, tmp) < n) { tmp++; } return (int)Math.Pow(2, tmp); @@ -44,8 +38,7 @@ public static int Min2N(int n) /// /// /// - public static double LineLerp(double y1, double y2, double ratio) - { + public static double LineLerp(double y1, double y2, double ratio) { return y1 + (y2 - y1) * ratio; } @@ -54,11 +47,9 @@ public static double LineLerp(double y1, double y2, double ratio) /// /// /// - internal static double[] BlackmanWin(int length) - { + internal static double[] BlackmanWin(int length) { double[] tmp = new double[length]; - for (int i = 0; i < length; i++) - { + for (int i = 0; i < length; i++) { tmp[i] = 0.42f - 0.5f * Math.Cos(2 * Math.PI * i / (length - 1)) + 0.08f * Math.Cos(4 * Math.PI * i / (length - 1)); } return tmp; @@ -69,57 +60,47 @@ internal static double[] BlackmanWin(int length) /// /// /// - internal static double[] CosWin(int length) - { + internal static double[] CosWin(int length) { double[] tmp = new double[length]; - for (int i = 0; i < length; i++) - { + for (int i = 0; i < length; i++) { tmp[i] = 0.5f - 0.5f * Math.Cos(2 * Math.PI * i / (length - 1)); } return tmp; } - internal static Complex[] FFT(IList data, Complex[] W) - { + internal static Complex[] FFT(IList data, Complex[] W) { int n = data.Count; Complex[] output = new Complex[n]; double[] rlist = new double[n]; int total_m = 0; - int Rpos(int num) - { + int Rpos(int num) { int outNum = 0; int bits = 0; int _i = n; int dataNum = num; - while (_i != 0) - { + while (_i != 0) { _i /= 2; bits++; } - for (int i = 0; i < bits - 1; i++) - { + for (int i = 0; i < bits - 1; i++) { outNum = outNum << 1; outNum = outNum | ((dataNum >> i) & 1); } total_m = bits - 1; return outNum; } - for (int _ = 0; _ < n; _++) - { + for (int _ = 0; _ < n; _++) { rlist[_] = data[Rpos(_)]; output[_] = new Complex(rlist[_], 0); } int split; int numeach; Complex temp, temp2; - for (int m = 0; m < total_m; m++) - { + for (int m = 0; m < total_m; m++) { split = n / (int)Math.Pow(2, m + 1); numeach = n / split; - for (int _ = 0; _ < split; _++) - { - for (int __ = 0; __ < numeach / 2; __++) - { + for (int _ = 0; _ < split; _++) { + for (int __ = 0; __ < numeach / 2; __++) { temp = output[_ * numeach + __]; temp2 = output[_ * numeach + __ + numeach / 2] * W[__ * (int)Math.Pow(2, total_m - m - 1)]; output[_ * numeach + __] = temp + temp2; @@ -130,47 +111,39 @@ int Rpos(int num) return output; } - internal static double[] IFFT(Complex[] data, Complex[] _W) - { + internal static double[] IFFT(Complex[] data, Complex[] _W) { int n = data.Length; Complex[] output = new Complex[n]; Complex[] rlist = new Complex[n]; int total_m = 0; - int Rpos(int num) - { + int Rpos(int num) { int outNum = 0; int bits = 0; int _i = n; int dataNum = num; - while (_i != 0) - { + while (_i != 0) { _i = _i / 2; bits++; } - for (int i = 0; i < bits - 1; i++) - { + for (int i = 0; i < bits - 1; i++) { outNum = outNum << 1; outNum = outNum | ((dataNum >> i) & 1); } total_m = bits - 1; return outNum; } - for (int _ = 0; _ < n; _++) - { + for (int _ = 0; _ < n; _++) { rlist[_] = data[Rpos(_)]; output[_] = rlist[_]; } int split; int numeach; Complex temp, temp2; - for (int m = 0; m < total_m; m++) - { + for (int m = 0; m < total_m; m++) { split = n / (int)Math.Pow(2, m + 1); numeach = n / split; - for (int _ = 0; _ < split; _++) - { - for (int __ = 0; __ < numeach / 2; __++) - { + for (int _ = 0; _ < split; _++) { + for (int __ = 0; __ < numeach / 2; __++) { temp = output[_ * numeach + __]; temp2 = output[_ * numeach + __ + numeach / 2] * _W[__ * (int)Math.Pow(2, total_m - m - 1)]; output[_ * numeach + __] = temp + temp2; @@ -179,14 +152,10 @@ int Rpos(int num) } } double[] outputN = new double[n]; - for (int i = 0; i < n; i++) - { - if (output[i].Real > -output[i].Imaginary) - { + for (int i = 0; i < n; i++) { + if (output[i].Real > -output[i].Imaginary) { outputN[i] = output[i].Norm / n; - } - else - { + } else { outputN[i] = -output[i].Norm / n; } } @@ -199,13 +168,11 @@ int Rpos(int num) /// /// /// - internal static double[] Noise(double g, int length) - { + internal static double[] Noise(double g, int length) { double[] noise = new double[length]; Random random = new Random(); - for (int i = 0; i < length; i++) - { - noise[i]=(float)(random.NextDouble() - 0.5) * 2 * g; + for (int i = 0; i < length; i++) { + noise[i] = (float)(random.NextDouble() - 0.5) * 2 * g; } return noise; } diff --git a/OpenUtau.Core/VocalShaper/VSVocoder.cs b/OpenUtau.Core/VocalShaper/VSVocoder.cs index b0df57655..c358a3ce0 100644 --- a/OpenUtau.Core/VocalShaper/VSVocoder.cs +++ b/OpenUtau.Core/VocalShaper/VSVocoder.cs @@ -1,9 +1,7 @@ using System; -namespace VocalShaper -{ - public class VSVocoder - { +namespace VocalShaper { + public class VSVocoder { //采样率 readonly int samplesPerSec; //采样率的一半 @@ -24,8 +22,7 @@ public class VSVocoder /// 合成数据前面多出来的长度 /// /// - public int LerpLen() - { + public int LerpLen() { return hopSize; } @@ -35,8 +32,7 @@ public int LerpLen() /// 合成目标采样率 /// 帧长度/毫秒 /// 预合成噪声长度/秒 - public VSVocoder(int fs, double frameMs, double noiseTimeSec = 5) - { + public VSVocoder(int fs, double frameMs, double noiseTimeSec = 5) { samplesPerSec = fs; halfSameplesPerSec = samplesPerSec / 2; hopSize = (int)(frameMs / 1000 * samplesPerSec); @@ -48,32 +44,27 @@ public VSVocoder(int fs, double frameMs, double noiseTimeSec = 5) //初始化sin sin = new double[samplesPerSec]; - for (int i = 0; i < samplesPerSec; i++) - { + for (int i = 0; i < samplesPerSec; i++) { sin[i] = 0.125 * Math.Sqrt(2) * Math.Sin(2 * Math.PI * i / samplesPerSec); } //初始化旋转因子 W = new Complex[winLen]; - for (int _ = 0; _ < winLen; _++) - { + for (int _ = 0; _ < winLen; _++) { W[_] = new Complex(Math.Cos(2 * Math.PI / winLen), -Math.Sin(2 * Math.PI / winLen)) ^ _; } _W = new Complex[winLen]; - for (int _ = 0; _ < winLen; _++) - { + for (int _ = 0; _ < winLen; _++) { _W[_] = new Complex(Math.Cos(2 * Math.PI / winLen), -Math.Sin(2 * Math.PI / winLen)) ^ (-_); } //初始化窗函数 BlackmanWindow = VSMath.BlackmanWin(winLen); Blackman2FrameTriangleWin = new double[frameSize]; - for (int i = 0; i < hopSize; i++) - { + for (int i = 0; i < hopSize; i++) { Blackman2FrameTriangleWin[i] = (double)i / hopSize / BlackmanWindow[i + ifftOffset]; } - for (int i = hopSize; i < frameSize; i++) - { + for (int i = hopSize; i < frameSize; i++) { Blackman2FrameTriangleWin[i] = (double)(frameSize - i) / hopSize / BlackmanWindow[i + ifftOffset]; } @@ -82,12 +73,10 @@ public VSVocoder(int fs, double frameMs, double noiseTimeSec = 5) int noiseLen = noiseCount * hopSize; var noiseData = VSMath.Noise(Math.Sqrt(3), noiseLen); Noises = new Complex[noiseCount][]; - for (int i = 0; i < noiseCount; i++) - { + for (int i = 0; i < noiseCount; i++) { double[] x = new double[winLen]; int offset = i * hopSize; - for (int j = 0; j < winLen; j++) - { + for (int j = 0; j < winLen; j++) { x[j] = BlackmanWindow[j] * noiseData[(j + offset) % noiseLen]; } Noises[i] = VSMath.FFT(x, W); @@ -119,8 +108,7 @@ public VSVocoder(int fs, double frameMs, double noiseTimeSec = 5) double[] voicing, double[] gender, double phase = 0, - int noiseIndex = 0) - { + int noiseIndex = 0) { //初始化 int frameCount = f0.Length; int resultLen = frameCount * hopSize; @@ -129,8 +117,7 @@ public VSVocoder(int fs, double frameMs, double noiseTimeSec = 5) double lastf; double nextf; //合成 - for (int i = 0; i < frameCount - 2; i++) - { + for (int i = 0; i < frameCount - 2; i++) { int offset = i * hopSize; double f = f0[i + 1]; @@ -195,9 +182,8 @@ public VSVocoder(int fs, double frameMs, double noiseTimeSec = 5) double[] genN = Gender(gender[i + 1], unitFrequency, halfWinLen); Complex[] noise = new Complex[winLen]; while (noiseIndex >= Noises.Length) noiseIndex -= Noises.Length; - noise[0] = new Complex(0,0); //Noises[noiseIndex][0]; - for (int h = 1; h < halfWinLen; h++) - { + noise[0] = new Complex(0, 0); //Noises[noiseIndex][0]; + for (int h = 1; h < halfWinLen; h++) { double y = NoiseEnvelope(i + 1, genN[h - 1]); int mirrorIndex = winLen - h; noise[h] = Noises[noiseIndex][h] * y; @@ -205,8 +191,7 @@ public VSVocoder(int fs, double frameMs, double noiseTimeSec = 5) } noise[halfWinLen] = new Complex(0, 0); //Noises[noiseIndex][halfWinLen]; var ifft = VSMath.IFFT(noise, _W); - for (int j = 0; j < frameSize; j++) - { + for (int j = 0; j < frameSize; j++) { result[offset + j] += ifft[ifftOffset + j] * Blackman2FrameTriangleWin[j] * bre; } @@ -229,8 +214,7 @@ public VSVocoder(int fs, double frameMs, double noiseTimeSec = 5) /// /// 相位与采样率的乘积 /// - double Sin(double x) - { + double Sin(double x) { return sin[(int)(x % samplesPerSec)]; } @@ -251,32 +235,23 @@ double Sin(double x) /// /// /// - double[] Tension(double v, double f0) - { + double[] Tension(double v, double f0) { int n = (int)(halfSameplesPerSec / f0);//int n = Math.Min((int)(samplesPerSec / 2 / f0), MaxHarmonicCount); double[] ten = new double[n]; v = (v - 0.5) * 2; - if (v == 0) - { - for (int i = 0; i < n; i++) - { + if (v == 0) { + for (int i = 0; i < n; i++) { ten[i] = 1; } - } - else if (v < 0) - { + } else if (v < 0) { ten[0] = Math.Pow(10, -v * tenBaseSensitivity / 20); - for (int i = 1; i < n; i++) - { + for (int i = 1; i < n; i++) { ten[i] = Math.Pow(10, -v * (tenN2Gain + tenNStep * (i - 1)) / 20); } - } - else - { + } else { ten[0] = Math.Pow(10, -v * tenBaseSensitivity / 20); - for (int i = 1; i < n; i++) - { + for (int i = 1; i < n; i++) { ten[i] = Math.Pow(10, v * Math.Log10(Math.Max(0.5, tenPb - tenPk * Math.Abs(i - 10)))); } } @@ -290,8 +265,7 @@ double[] Tension(double v, double f0) /// /// /// - double Breathiness(double v) - { + double Breathiness(double v) { return Math.Pow(10, (v - 0.5) * 2 * breathinessSensitivity / 20); } @@ -300,8 +274,7 @@ double Breathiness(double v) /// /// /// - double Voicing(double v) - { + double Voicing(double v) { return v; } @@ -314,45 +287,35 @@ double Voicing(double v) /// /// /// - double[] Gender(double v, double f0, int n) - { + double[] Gender(double v, double f0, int n) { double[] gen = new double[n]; double fn = 0; int i = 0; v = (v - 0.5) * 2; - if (v == 0) - { - for (; i < n; i++) - { + if (v == 0) { + for (; i < n; i++) { fn += f0; gen[i] = fn; } - } - else - { - for (; i < n; i++) - { + } else { + for (; i < n; i++) { fn += f0; if (fn < genLow) gen[i] = fn * Math.Pow(genR, v); - else - { + else { fn -= f0; break; } } - for (; i < n; i++) - { + for (; i < n; i++) { fn += f0; - if (fn > genHigh) - { + if (fn > genHigh) { fn -= f0; break; } gen[i] = genHigh - (genHigh - Math.Pow(genR, v) * genLow) / (genHigh - genLow) * (genHigh - fn); } - for (; i < n; i++) - { + for (; i < n; i++) { fn += f0; gen[i] = fn; } diff --git a/OpenUtau.Core/VocalShaper/World.cs b/OpenUtau.Core/VocalShaper/World.cs index 65146d5e3..52de7c73c 100644 --- a/OpenUtau.Core/VocalShaper/World.cs +++ b/OpenUtau.Core/VocalShaper/World.cs @@ -1,9 +1,7 @@ using System; -namespace VocalShaper.World -{ - public static class World - { +namespace VocalShaper.World { + public static class World { /// /// 合成 /// @@ -33,19 +31,16 @@ public static (double, int) Synthesis(this VSVocoder vsVocoder, double[] voicing, double[] gender, double phase = 0, - int noiseIndex = 0) - { + int noiseIndex = 0) { double f2i = (double)fftSize / fs; return vsVocoder.Synthesis(out result, - (i, f) => - { + (i, f) => { double fi = f * f2i; int floorIndex = (int)fi; int ceillingIndex = floorIndex + 1; return Math.Sqrt(VSMath.LineLerp(sp[i, floorIndex], sp[i, ceillingIndex], fi - floorIndex)); }, - (i, f) => - { + (i, f) => { double fi = f * f2i; int floorIndex = (int)fi; int ceillingIndex = floorIndex + 1; diff --git a/OpenUtau.Core/Vogen/VogenBasePhonemizer.cs b/OpenUtau.Core/Vogen/VogenBasePhonemizer.cs index 747530f9a..6e1bfd238 100644 --- a/OpenUtau.Core/Vogen/VogenBasePhonemizer.cs +++ b/OpenUtau.Core/Vogen/VogenBasePhonemizer.cs @@ -24,12 +24,12 @@ public VogenBasePhonemizer() { public override void SetSinger(USinger singer) { } //Merge slur notes into their previous lyrical note - private void AddGroup(List phrase, Note[] group){ - if(group.Length==1){ + private void AddGroup(List phrase, Note[] group) { + if (group.Length == 1) { phrase.Add(group[0]); return; } - phrase.Add(new Note{ + phrase.Add(new Note { lyric = group[0].lyric, phoneticHint = group[0].phoneticHint, tone = group[0].tone, @@ -41,7 +41,7 @@ public override void SetUp(Note[][] groups, UProject project, UTrack track) { if (groups.Length == 0) { return; } - var phrase = new List() {}; + var phrase = new List() { }; AddGroup(phrase, groups[0]); for (int i = 1; i < groups.Length; ++i) { if (groups[i - 1][^1].position + groups[i - 1][^1].duration == groups[i][0].position) { diff --git a/OpenUtau.Core/Vogen/VogenYuePhonemizer.cs b/OpenUtau.Core/Vogen/VogenYuePhonemizer.cs index bb2d1c954..c5489d8d5 100644 --- a/OpenUtau.Core/Vogen/VogenYuePhonemizer.cs +++ b/OpenUtau.Core/Vogen/VogenYuePhonemizer.cs @@ -1,6 +1,6 @@ -using Microsoft.ML.OnnxRuntime; +using System; +using Microsoft.ML.OnnxRuntime; using OpenUtau.Api; -using System; namespace OpenUtau.Core.Vogen { [Phonemizer("Vogen Chinese Yue Phonemizer", "VOGEN ZH-YUE", language: "ZH-YUE")] diff --git a/OpenUtau.Core/Voicevox/VoicevoxConfig.cs b/OpenUtau.Core/Voicevox/VoicevoxConfig.cs index 06307595d..a6f31db61 100644 --- a/OpenUtau.Core/Voicevox/VoicevoxConfig.cs +++ b/OpenUtau.Core/Voicevox/VoicevoxConfig.cs @@ -163,7 +163,7 @@ public void SaveLicenses(string location) { File.WriteAllText(filePath, terms_of_service); } foreach (var item in dependency_licenses) { - item.name = item.name.Replace("\"",""); + item.name = item.name.Replace("\"", ""); filePath = Path.Join(licenseDirectory, $"{item.name}_License.txt"); if (!string.IsNullOrEmpty(item.text)) { File.WriteAllText(filePath, $"license:{item.license}\nversion:{item.version}\n\n" + item.text); diff --git a/OpenUtau.Core/Voicevox/VoicevoxSinger.cs b/OpenUtau.Core/Voicevox/VoicevoxSinger.cs index 6388784d9..597c74cb7 100644 --- a/OpenUtau.Core/Voicevox/VoicevoxSinger.cs +++ b/OpenUtau.Core/Voicevox/VoicevoxSinger.cs @@ -74,8 +74,8 @@ void Load() { if (voicevoxConfig.version.Equals("1.15.0")) { Log.Error("It differs from the supported version."); } - if(voicevoxConfig.style_infos == null) { - voicevoxConfig.LoadInfo(voicevoxConfig,this.Location); + if (voicevoxConfig.style_infos == null) { + voicevoxConfig.LoadInfo(voicevoxConfig, this.Location); } phonemes.Clear(); table.Clear(); @@ -155,7 +155,7 @@ void Load() { } public override bool TryGetOto(string phoneme, out UOto oto) { - if(phoneme != null) { + if (phoneme != null) { var parts = phoneme.Split(); if (parts.All(p => phonemes.Contains(p))) { oto = UOto.OfDummy(phoneme); diff --git a/OpenUtau.Core/Voicevox/VoicevoxUtils.cs b/OpenUtau.Core/Voicevox/VoicevoxUtils.cs index ef24a7d4c..712acf70a 100644 --- a/OpenUtau.Core/Voicevox/VoicevoxUtils.cs +++ b/OpenUtau.Core/Voicevox/VoicevoxUtils.cs @@ -253,7 +253,7 @@ public static VoicevoxQueryMain NoteGroupsToVQuery(VoicevoxNote[] vNotes, TimeAx } public static List QueryToF0(VoicevoxQueryMain vqMain, VoicevoxSynthParams vsParams, string id) { - VoicevoxQueryParams vqParams = new VoicevoxQueryParams() { score = vqMain, frame_audio_query = vsParams }; + VoicevoxQueryParams vqParams = new VoicevoxQueryParams() { score = vqMain, frame_audio_query = vsParams }; var queryurl = new VoicevoxURL() { method = "POST", path = "/sing_frame_f0", query = new Dictionary { { "speaker", id } }, body = JsonConvert.SerializeObject(vqParams) }; var response = VoicevoxClient.Inst.SendRequest(queryurl); List f0s = new List(); diff --git a/OpenUtau.Plugin.Builtin/ArpasingPlusPhonemizer.cs b/OpenUtau.Plugin.Builtin/ArpasingPlusPhonemizer.cs index 263812ce3..2f2ae58f1 100644 --- a/OpenUtau.Plugin.Builtin/ArpasingPlusPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/ArpasingPlusPhonemizer.cs @@ -93,7 +93,7 @@ public class ArpasingPlusPhonemizer : SyllableBasedPhonemizer { {"ey","eh"}, {"oy","ao"}, }; - + private readonly Dictionary vvExceptions = new Dictionary() { {"aw","w"}, @@ -268,7 +268,7 @@ public override void SetSinger(USinger singer) { Log.Error($"Failed to load fallbacks from arpasing.yaml: {ex.Message}"); } } catch (Exception ex) { - Log.Error($"Failed to parse arpasing.yaml: {ex.Message}"); + Log.Error($"Failed to parse arpasing.yaml: {ex.Message}"); } } ReadDictionaryAndInit(); diff --git a/OpenUtau.Plugin.Builtin/BaseKoreanPhonemizer.cs b/OpenUtau.Plugin.Builtin/BaseKoreanPhonemizer.cs index 029394c33..b0c1db5ca 100644 --- a/OpenUtau.Plugin.Builtin/BaseKoreanPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/BaseKoreanPhonemizer.cs @@ -15,19 +15,19 @@ namespace OpenUtau.Plugin.Builtin { /// 4. Can generate phonemes according to Phoneme hints. /// public abstract class BaseKoreanPhonemizer : Phonemizer { - + protected USinger singer; protected int vcLengthShort = 90; - protected static readonly string[] PLAIN_VOWELS = new string[]{"ㅏ", "ㅣ", "ㅜ", "ㅔ", "ㅗ", "ㅡ", "ㅓ", "ㅢ"}; - protected static readonly string[] SOFT_BATCHIMS = new string[]{"ㄴ", "ㄹ", "ㅇ"}; - protected static readonly string[] HARD_BATCHIMS = new string[]{"ㄱ", "ㄷ", "ㅂ", "ㅁ"}; + protected static readonly string[] PLAIN_VOWELS = new string[] { "ㅏ", "ㅣ", "ㅜ", "ㅔ", "ㅗ", "ㅡ", "ㅓ", "ㅢ" }; + protected static readonly string[] SOFT_BATCHIMS = new string[] { "ㄴ", "ㄹ", "ㅇ" }; + protected static readonly string[] HARD_BATCHIMS = new string[] { "ㄱ", "ㄷ", "ㅂ", "ㅁ" }; // this phonemizer will call ConvertPhonemes() when lyric is hanguel or additionalTest is true . (override to use) protected virtual bool additionalTest(string lyric) { return false; - } + } public override void SetSinger(USinger singer) => this.singer = singer; public static string? FindInOto(USinger singer, string phoneme, Note note, bool nullIfNotFound = false) { // 음소와 노트를 입력받고, 다음계 및 보이스컬러 에일리어스를 적용한다. @@ -38,27 +38,23 @@ protected virtual bool additionalTest(string lyric) { string color = attr.voiceColor ?? string.Empty; int toneShift = 0; int? alt = null; - if (phoneme.Equals("")) {return phoneme;} + if (phoneme.Equals("")) { return phoneme; } if (singer.TryGetMappedOto(phoneme + alt, note.tone + toneShift, color, out var otoAlt)) { phonemeToReturn = otoAlt.Alias; - } - else if (singer.TryGetMappedOto(phoneme, note.tone + toneShift, color, out var oto)) { + } else if (singer.TryGetMappedOto(phoneme, note.tone + toneShift, color, out var oto)) { phonemeToReturn = oto.Alias; - } - else if (singer.TryGetMappedOto(phoneme, note.tone, color, out oto)) { + } else if (singer.TryGetMappedOto(phoneme, note.tone, color, out oto)) { phonemeToReturn = oto.Alias; - } - else if (nullIfNotFound) { + } else if (nullIfNotFound) { phonemeToReturn = null; - } - else { + } else { phonemeToReturn = phoneme; } return phonemeToReturn; } - + /// /// All child Korean Phonemizer have to do is implementing this (1). /// This Function manages phoneme conversion at Notes that are not in last position. @@ -106,7 +102,7 @@ public virtual Result GenerateEndSound(Note[] notes, Note? prev, Note? next, Not /// /// /// - public Result GenerateResult(String firstPhoneme, String secondPhoneme, int totalDuration, int secondPhonemePosition, int totalDurationDivider=3){ + public Result GenerateResult(String firstPhoneme, String secondPhoneme, int totalDuration, int secondPhonemePosition, int totalDurationDivider = 3) { return new Result() { phonemes = new Phoneme[] { new Phoneme { phoneme = firstPhoneme }, @@ -123,7 +119,7 @@ public Result GenerateResult(String firstPhoneme, String secondPhoneme, int tota /// /// /// - public Result GenerateResult(String firstPhoneme, String secondPhoneme, int totalDuration, int totalDurationDivider=3){ + public Result GenerateResult(String firstPhoneme, String secondPhoneme, int totalDuration, int totalDurationDivider = 3) { return new Result() { phonemes = new Phoneme[] { new Phoneme { phoneme = firstPhoneme }, @@ -131,13 +127,13 @@ public Result GenerateResult(String firstPhoneme, String secondPhoneme, int tota position = totalDuration - totalDuration / totalDurationDivider}, } }; - + } /// /// Returns Result with one input Phonemes. /// - public Result GenerateResult(String firstPhoneme){ + public Result GenerateResult(String firstPhoneme) { return new Result() { phonemes = new Phoneme[] { new Phoneme { phoneme = firstPhoneme }, @@ -157,7 +153,7 @@ public Result GenerateResult(String firstPhoneme){ /// /// /// Result - public Result GenerateResult(String firstPhoneme, String secondPhoneme, String thirdPhoneme, int totalDuration, int secondPhonemePosition, int secondTotalDurationDivider=3, int thirdTotalDurationDivider=8){ + public Result GenerateResult(String firstPhoneme, String secondPhoneme, String thirdPhoneme, int totalDuration, int secondPhonemePosition, int secondTotalDurationDivider = 3, int thirdTotalDurationDivider = 8) { return new Result() { phonemes = new Phoneme[] { new Phoneme { phoneme = firstPhoneme}, @@ -221,7 +217,7 @@ public class ProcessResult { }; } - + } } return new ProcessResult { @@ -241,7 +237,7 @@ public class ProcessResult { /// /// /// Result? - public Result? RenderPhoneticHint(USinger singer, Note note, int totalDuration) { + public Result? RenderPhoneticHint(USinger singer, Note note, int totalDuration) { var phoneticHint = note.phoneticHint; if (phoneticHint != null) { @@ -278,16 +274,14 @@ public class ProcessResult { if (i == 0) { // first syllable phonemes[i] = new Phoneme { phoneme = alias }; - } - else if ((i == phoneticHintsLength - 1) && ((phoneticHints[i].Trim().EndsWith('-')) || phoneticHints[i].Trim().EndsWith('R'))) { + } else if ((i == phoneticHintsLength - 1) && ((phoneticHints[i].Trim().EndsWith('-')) || phoneticHints[i].Trim().EndsWith('R'))) { // 마지막 음소이고 끝음소(ex: a -, a R)일 경우, VCLengthShort에 맞춰 음소를 배치 phonemes[i] = new Phoneme { phoneme = alias, position = totalDuration - Math.Min(vcLengthShort, totalDuration / 8) // 8등분한 길이로 끝에 숨소리 음소 배치, n등분했을 때의 음소 길이가 이보다 작다면 n등분했을 때의 길이로 간다 }; - } - else if (phoneticHintsLength == 2) { + } else if (phoneticHintsLength == 2) { // 입력되는 발음힌트가 2개일 경우, 2등분되어 음소가 배치된다. // 이 경우 부자연스러우므로 3등분해서 음소 배치하게 조정 phonemes[i] = new Phoneme { @@ -295,8 +289,7 @@ public class ProcessResult { position = totalDuration - totalDuration / 3 // 3등분해서 음소가 배치됨 }; - } - else { + } else { phonemes[i] = new Phoneme { phoneme = alias, position = totalDuration - ((totalDuration / phoneticHintsLength) * (phoneticHintsLength - i)) @@ -313,8 +306,7 @@ public class ProcessResult { position = totalDuration - totalDuration / 3 // 3등분해서 음소가 배치됨 }; - } - else { + } else { phonemes[i] = new Phoneme { phoneme = FindInOto(singer, VVdictionary[phoneticHints[i].Trim()], note), position = totalDuration - ((totalDuration / phoneticHintsLength) * (phoneticHintsLength - i)) @@ -350,7 +342,7 @@ public class ProcessResult { /// /// /// Result - public Result GenerateResult(String firstPhoneme, String secondPhoneme, String thirdPhoneme, int totalDuration, int secondTotalDurationDivider=3, int thirdTotalDurationDivider=8){ + public Result GenerateResult(String firstPhoneme, String secondPhoneme, String thirdPhoneme, int totalDuration, int secondTotalDurationDivider = 3, int thirdTotalDurationDivider = 8) { return new Result() { phonemes = new Phoneme[] { new Phoneme { phoneme = firstPhoneme}, @@ -378,7 +370,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN var phoneticHint = RenderPhoneticHint(singer, note, totalDuration); if (phoneticHint != null) { - return (Result) phoneticHint; + return (Result)phoneticHint; } var romaji2Korean = ConvertRomajiNoteToHangeul(notes, prevNeighbour, nextNeighbour); @@ -388,17 +380,16 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN if (KoreanPhonemizerUtil.IsHangeul(lyric) || !KoreanPhonemizerUtil.IsHangeul(lyric) && additionalTest(lyric)) { return ConvertPhonemes(notes, prev, next, prevNeighbour, nextNeighbour, prevNeighbours); - } - else { + } else { return GenerateEndSound(notes, prev, next, prevNeighbour, nextNeighbour, prevNeighbours); } } - + /// /// abstract class for Ini Management /// To use, child phonemizer should implement this class(BaseIniManager) with its own setting values! /// - public abstract class BaseIniManager : KoreanPhonemizerUtil.BaseIniManager{} + public abstract class BaseIniManager : KoreanPhonemizerUtil.BaseIniManager { } } } diff --git a/OpenUtau.Plugin.Builtin/BrazilianPortugueseCVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/BrazilianPortugueseCVCPhonemizer.cs index 5e4be1972..5521a8643 100644 --- a/OpenUtau.Plugin.Builtin/BrazilianPortugueseCVCPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/BrazilianPortugueseCVCPhonemizer.cs @@ -5,7 +5,7 @@ using OpenUtau.Core.G2p; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("Brazilian Portuguese CVC Phonemizer", "PT-BR CVC", "HAI-D", language:"PT")] + [Phonemizer("Brazilian Portuguese CVC Phonemizer", "PT-BR CVC", "HAI-D", language: "PT")] public class BrazilianPortugueseCVCPhonemizer : SyllableBasedPhonemizer { /// @@ -44,8 +44,7 @@ protected override List ProcessSyllable(Syllable syllable) { var phonemes = new List(); if (syllable.IsStartingV) { basePhoneme = $"- {v}"; - } - else if (syllable.IsVV) { // if VV + } else if (syllable.IsVV) { // if VV if (!CanMakeAliasExtension(syllable)) { //try VV basePhoneme = $"{prevV} {v}"; @@ -63,14 +62,12 @@ protected override List ProcessSyllable(Syllable syllable) { // the previous alias will be extended basePhoneme = null; } - } - else if (syllable.IsStartingCV) { + } else if (syllable.IsStartingCV) { basePhoneme = $"-{cc.Last()} {v}"; for (var i = 0; i < cc.Length - 1; i++) { phonemes.Add($"- {cc[i]}"); } - } - else { // VCV + } else { // VCV if (cc.Length == 1 || IsShort(syllable) || cc.Last() == "`") { basePhoneme = $"{cc.Last()} {v}"; } else { @@ -94,8 +91,7 @@ protected override List ProcessEnding(Ending ending) { var phonemes = new List(); if (ending.IsEndingV) { phonemes.Add($"{v} -"); - } - else { + } else { phonemes.Add($"{v} {cc[0]}-"); for (var i = 1; i < cc.Length; i++) { var cr = $"{cc[i]} -"; diff --git a/OpenUtau.Plugin.Builtin/ChineseCVVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/ChineseCVVCPhonemizer.cs index 77c267155..345dd3fd9 100644 --- a/OpenUtau.Plugin.Builtin/ChineseCVVCPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/ChineseCVVCPhonemizer.cs @@ -23,7 +23,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN if (vowels.TryGetValue(prevLyric, out var vowel)) { prevVowel = vowel; } - }; + } var attr0 = notes[0].phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default; var attr1 = notes[0].phonemeAttributes?.FirstOrDefault(attr => attr.index == 1) ?? default; var attr2 = notes[0].phonemeAttributes?.FirstOrDefault(attr => attr.index == 2) ?? default; @@ -222,7 +222,7 @@ public override void SetSinger(USinger singer) { Log.Error(e, "failed to load presamp.ini"); } } - + public static Note[] ChangeLyric(Note[] group, string lyric) { var oldNote = group[0]; group[0] = new Note { diff --git a/OpenUtau.Plugin.Builtin/ChineseCVVPhonemizer.cs b/OpenUtau.Plugin.Builtin/ChineseCVVPhonemizer.cs index 625398e75..bb83addbd 100644 --- a/OpenUtau.Plugin.Builtin/ChineseCVVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/ChineseCVVPhonemizer.cs @@ -13,16 +13,15 @@ namespace OpenUtau.Plugin.Builtin { /// It works by spliting "duang" to "duang" + "_ang", to produce the proper tail sound. /// [Phonemizer("Chinese CVV (十月式整音扩张) Phonemizer", "ZH CVV", language: "ZH")] - public class ChineseCVVMonophonePhonemizer : MonophonePhonemizer - { + public class ChineseCVVMonophonePhonemizer : MonophonePhonemizer { static readonly string pinyins = "a,ai,an,ang,ao,ba,bai,ban,bang,bao,bei,ben,beng,bi,bian,biao,bie,bin,bing,bo,bu,ca,cai,can,cang,cao,ce,cei,cen,ceng,cha,chai,chan,chang,chao,che,chen,cheng,chi,chong,chou,chu,chua,chuai,chuan,chuang,chui,chun,chuo,ci,cong,cou,cu,cuan,cui,cun,cuo,da,dai,dan,dang,dao,de,dei,den,deng,di,dia,dian,diao,die,ding,diu,dong,dou,du,duan,dui,dun,duo,e,ei,en,eng,er,fa,fan,fang,fei,fen,feng,fo,fou,fu,ga,gai,gan,gang,gao,ge,gei,gen,geng,gong,gou,gu,gua,guai,guan,guang,gui,gun,guo,ha,hai,han,hang,hao,he,hei,hen,heng,hong,hou,hu,hua,huai,huan,huang,hui,hun,huo,ji,jia,jian,jiang,jiao,jie,jin,jing,jiong,jiu,ju,jv,juan,jvan,jue,jve,jun,jvn,ka,kai,kan,kang,kao,ke,kei,ken,keng,kong,kou,ku,kua,kuai,kuan,kuang,kui,kun,kuo,la,lai,lan,lang,lao,le,lei,leng,li,lia,lian,liang,liao,lie,lin,ling,liu,lo,long,lou,lu,luan,lun,luo,lv,lve,ma,mai,man,mang,mao,me,mei,men,meng,mi,mian,miao,mie,min,ming,miu,mo,mou,mu,na,nai,nan,nang,nao,ne,nei,nen,neng,ni,nian,niang,niao,nie,nin,ning,niu,nong,nou,nu,nuan,nun,nuo,nv,nve,o,ou,pa,pai,pan,pang,pao,pei,pen,peng,pi,pian,piao,pie,pin,ping,po,pou,pu,qi,qia,qian,qiang,qiao,qie,qin,qing,qiong,qiu,qu,qv,quan,qvan,que,qve,qun,qvn,ran,rang,rao,re,ren,reng,ri,rong,rou,ru,rua,ruan,rui,run,ruo,sa,sai,san,sang,sao,se,sen,seng,sha,shai,shan,shang,shao,she,shei,shen,sheng,shi,shou,shu,shua,shuai,shuan,shuang,shui,shun,shuo,si,song,sou,su,suan,sui,sun,suo,ta,tai,tan,tang,tao,te,tei,teng,ti,tian,tiao,tie,ting,tong,tou,tu,tuan,tui,tun,tuo,wa,wai,wan,wang,wei,wen,weng,wo,wu,xi,xia,xian,xiang,xiao,xie,xin,xing,xiong,xiu,xu,xv,xuan,xvan,xue,xve,xun,xvn,ya,yan,yang,yao,ye,yi,yin,ying,yo,yong,you,yu,yv,yuan,yvan,yue,yve,yun,yvn,za,zai,zan,zang,zao,ze,zei,zen,zeng,zha,zhai,zhan,zhang,zhao,zhe,zhei,zhen,zheng,zhi,zhong,zhou,zhu,zhua,zhuai,zhuan,zhuang,zhui,zhun,zhuo,zi,zong,zou,zu,zuan,zui,zun"; static readonly string tails = "_vn,_ing,_ong,_an,_ou,_er,_ao,_eng,_ang,_en,_en2,_ai,_iong,_in,_ei"; - + static readonly string[] pinyinList = pinyins.Split(','); static readonly string[] tailList = tails.Split(','); public ChineseCVVMonophonePhonemizer() { - ConsonantLength = 120; + ConsonantLength = 120; } protected override IG2p LoadG2p() { @@ -59,8 +58,8 @@ public override void SetUp(Note[][] groups, UProject project, UTrack track) { BaseChinesePhonemizer.RomanizeNotes(groups); } } - - class ChineseCVVG2p : IG2p{ + + class ChineseCVVG2p : IG2p { /// /// The consonant table. /// @@ -72,7 +71,7 @@ class ChineseCVVG2p : IG2p{ static HashSet cSet; static Dictionary vDict; - + static ChineseCVVG2p() { cSet = new HashSet(consonants.Split(',')); vDict = vowels.Split(',') @@ -80,15 +79,15 @@ static ChineseCVVG2p() { .ToDictionary(a => a[0], a => a[1]); } - public bool IsVowel(string phoneme){ + public bool IsVowel(string phoneme) { return !phoneme.StartsWith("_"); } - public bool IsGlide(string phoneme){ + public bool IsGlide(string phoneme) { return false; } - public string[] Query(string lyric){ + public string[] Query(string lyric) { // The overall logic is: // 1. Remove consonant: "duang" -> "uang". // 2. Lookup the trailing sound in vowel table: "uang" -> "_ang". @@ -113,14 +112,14 @@ public string[] Query(string lyric){ if ((vowel == "an") && (consonant == "y")) { vowel = "ian"; } - if(vDict.TryGetValue(vowel, out var tail)){ + if (vDict.TryGetValue(vowel, out var tail)) { return new string[] { lyric, tail }; - }else{ + } else { return new string[] { lyric }; } - + } - public bool IsValidSymbol(string symbol){ + public bool IsValidSymbol(string symbol) { return true; } diff --git a/OpenUtau.Plugin.Builtin/ChineseCVVPlusPhonemizer.cs b/OpenUtau.Plugin.Builtin/ChineseCVVPlusPhonemizer.cs index e6e3ee21f..53774b1a3 100644 --- a/OpenUtau.Plugin.Builtin/ChineseCVVPlusPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/ChineseCVVPlusPhonemizer.cs @@ -5,10 +5,10 @@ using OpenUtau.Api; using OpenUtau.Core; using OpenUtau.Core.Ustx; +using Serilog; using YamlDotNet.Core; using YamlDotNet.Serialization; using YamlDotNet.Serialization.EventEmitters; -using Serilog; namespace OpenUtau.Plugin.Builtin { /// @@ -274,7 +274,7 @@ void CreateConfigChineseCVVPlus(string configPath) { public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) { try { - + int totalDuration = notes.Sum(n => n.duration); string phoneme = notes[0].lyric; string? lryicVowel = GetLyricVowel(notes[0].lyric); @@ -287,7 +287,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN foreach (var phoneticHint in phoneticHints.Select((hint, index) => (hint, index))) { phonemes[phoneticHint.index] = new Phoneme { - phoneme = GetOtoAlias(singer, phoneticHint.hint.Trim(), notes[0]) , + phoneme = GetOtoAlias(singer, phoneticHint.hint.Trim(), notes[0]), // The position is evenly divided into n parts. position = totalDuration - ((totalDuration / phoneticHints.Length) * (phoneticHints.Length - phoneticHint.index)), }; @@ -301,7 +301,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN // If the note is an End Breath note if (Config.SupportedTailBreath.Contains(phoneme) && prev != null) { phoneme = GetOtoAlias(singer, $"{GetLyricVowel(prev?.lyric)} {phoneme}", notes[0]); - + return new Result { // Output in the form "Basic vowel shape + End Breath written with lyrics" phonemes = new Phoneme[] { new Phoneme { phoneme = phoneme } } @@ -348,7 +348,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } }; } - }; + } // If it does not match any of the above if statements, return new Result { @@ -358,13 +358,13 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } } }; - } catch (Exception e) { + } catch (Exception e) { Log.Error(e, "An error occurred during the phoneme processing in zh cvv+ module."); // Logging return new Result { phonemes = new Phoneme[] { new Phoneme() { - phoneme = "ERROR", + phoneme = "ERROR", } } }; diff --git a/OpenUtau.Plugin.Builtin/ENtoJAPhonemizer.cs b/OpenUtau.Plugin.Builtin/ENtoJAPhonemizer.cs index 911aac120..792d61df9 100644 --- a/OpenUtau.Plugin.Builtin/ENtoJAPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/ENtoJAPhonemizer.cs @@ -403,7 +403,7 @@ protected override List ProcessEnding(Ending ending) { prevV = WanaKana.ToRomaji(solo).Last().ToString(); } - + if (ending.IsEndingV) { TryAddPhoneme(phonemes, ending.tone, $"{prevV} R", $"{prevV} -", $"{prevV}-"); } @@ -429,7 +429,7 @@ protected override List ProcessEnding(Ending ending) { var vc = $"{vowel} {cons}"; var altVc = $"{vowel} {cons[0]}"; - + if (HasOto(vc, tone)) { phonemes.Add(vc); } else if (HasOto(altVc, tone)) { diff --git a/OpenUtau.Plugin.Builtin/EStoJAPhonemizer.cs b/OpenUtau.Plugin.Builtin/EStoJAPhonemizer.cs index 8fe5cca1d..f073bdd9e 100644 --- a/OpenUtau.Plugin.Builtin/EStoJAPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/EStoJAPhonemizer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using OpenUtau.Api; @@ -296,7 +296,7 @@ public class EStoJAPhonemizer : SyllableBasedPhonemizer { {"wu", "u" }, {"wi", "uli" }, {"we", "ule" }, - {"wo", "ulo" }, + {"wo", "ulo" }, }; private Dictionary ConditionalAlt => conditionalAlt; @@ -340,7 +340,7 @@ public class EStoJAPhonemizer : SyllableBasedPhonemizer { {"sula", new [] { "su", "wa" } }, {"sui", new [] { "su", "uli" } }, {"sule", new [] { "su", "ule" } }, - {"sulo", new [] { "su", "ulo" } }, + {"sulo", new [] { "su", "ulo" } }, {"je", new [] { "ji", "e" } }, {"jya", new [] { "ji", "ya" } }, {"jye", new [] { "ji", "e" } }, diff --git a/OpenUtau.Plugin.Builtin/EnXSampaPhonemizer.cs b/OpenUtau.Plugin.Builtin/EnXSampaPhonemizer.cs index 2a4164358..676a941b1 100644 --- a/OpenUtau.Plugin.Builtin/EnXSampaPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/EnXSampaPhonemizer.cs @@ -41,7 +41,7 @@ public class EnXSampaPhonemizer : SyllableBasedPhonemizer { .ToDictionary(parts => parts[0], parts => parts[1]); protected override string[] GetVowels() => vowels; - protected override string[] GetConsonants() => consonants; + protected override string[] GetConsonants() => consonants; protected override string GetDictionaryName() => ""; protected override Dictionary GetDictionaryPhonemesReplacement() => dictionaryReplacements; @@ -359,7 +359,7 @@ protected override List ProcessSyllable(Syllable syllable) { var lastC = cc.Length - 1; var firstC = 0; var rv = $"- {v}"; - + // Switch between phonetic systems, depending on certain aliases in the bank if (replacements.ContainsKey(syllable.v) || replacements.ContainsKey(syllable.prevV)) { isReplacements = true; diff --git a/OpenUtau.Plugin.Builtin/EnglishCpVPhonemizer.cs b/OpenUtau.Plugin.Builtin/EnglishCpVPhonemizer.cs index f2cbc7e35..21c1e690f 100644 --- a/OpenUtau.Plugin.Builtin/EnglishCpVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/EnglishCpVPhonemizer.cs @@ -79,7 +79,7 @@ public class EnglishCpVPhonemizer : SyllableBasedPhonemizer { {"oa", "oa"}, {"ua", "ua"} }; - + // Final consonants private static readonly string[] FinalConsonants = { "w", "y", "r", "l", "m", "n", "ng" }; @@ -279,7 +279,7 @@ protected override IG2p LoadBaseDictionary() { return new G2pFallbacks(g2ps.ToArray()); } - public override void SetSinger(USinger singer) { + public override void SetSinger(USinger singer) { if (this.singer != singer) { string file; if (singer != null && singer.Found && singer.Loaded && !string.IsNullOrEmpty(singer.Location)) { @@ -342,7 +342,7 @@ public override void SetSinger(USinger singer) { } } catch (Exception ex) { - Log.Error($"Failed to parse en-cPv.yaml: {ex.Message}"); + Log.Error($"Failed to parse en-cPv.yaml: {ex.Message}"); } } ReadDictionaryAndInit(); @@ -657,7 +657,7 @@ protected override List ProcessEnding(Ending ending) { } /// add additional c to those consonants on the top } else if (c_cR.Contains(cc.Last())) { - if (HasOto(vc, ending.tone) || HasOto(ValidateAlias(vc), ending.tone)) { + if (HasOto(vc, ending.tone) || HasOto(ValidateAlias(vc), ending.tone)) { TryAddPhoneme(phonemes, ending.tone, vc); //TryAddPhoneme(phonemes, ending.tone, AliasFormat($"{cc[0]}", "cc1_mix", ending.tone, "")); TryAddPhoneme(phonemes, ending.tone, AliasFormat($"{cc[0]}", "cc_mix", ending.tone, "")); diff --git a/OpenUtau.Plugin.Builtin/EnglishVCCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/EnglishVCCVPhonemizer.cs index 63c1a1383..0a83e198f 100644 --- a/OpenUtau.Plugin.Builtin/EnglishVCCVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/EnglishVCCVPhonemizer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.Design; using System.IO; @@ -30,7 +30,7 @@ public class EnglishVCCVPhonemizer : SyllableBasedPhonemizer { .Where(parts => parts.Length == 2) .Where(parts => parts[0] != parts[1]) .ToDictionary(parts => parts[0], parts => parts[1]); - + private readonly Dictionary replacements = "ax=x".Split(';') .Select(entry => entry.Split('=')) .Where(parts => parts.Length == 2) @@ -113,7 +113,7 @@ public class EnglishVCCVPhonemizer : SyllableBasedPhonemizer { //spl, shr, skr, spr, str, thr, skw, thw, sky, spy private readonly string[] ccNoParsing = { "sk", "sm", "sn", "sp", "st", "hhy" }; private readonly string[] stopCs = { "b", "d", "g", "k", "p", "t" }; - private readonly string[] ucvCs = { "r", "l", "w", "y", "f"}; + private readonly string[] ucvCs = { "r", "l", "w", "y", "f" }; private readonly string[] starlightccs = { "rl", "ll", "nn", "mm" }; protected override string[] GetVowels() => vowels; @@ -214,7 +214,7 @@ public override void SetSinger(USinger singer) { } } catch (Exception ex) { - Log.Error($"Failed to parse envccv.yaml: {ex.Message}"); + Log.Error($"Failed to parse envccv.yaml: {ex.Message}"); } } ReadDictionaryAndInit(); @@ -470,205 +470,205 @@ protected override List ProcessSyllable(Syllable syllable) { if (!HasOto(parsingVCC, syllable.vowelTone)) { parsingVCC = CheckVCExceptions(parsingVCC); } - if (!HasOto(parsingVCC, syllable.vowelTone)) { - parsingVCC = $"{prevV} {cc[0]}"; - } + if (!HasOto(parsingVCC, syllable.vowelTone)) { + parsingVCC = $"{prevV} {cc[0]}"; + } - // sp fix - if ($"{cc[0]}" == "s" && $"{cc[1]}" == "p") { - parsingVCC = $"{prevV} sp"; - } - phonemes.Add(parsingVCC); - phonemes.Add(parsingCC); - } else { - // backpack [@k] + [p@] - - // sp fix - if ($"{cc[0]}" == "s" && $"{cc[1]}" == "p") { - parsingVCC = $"{prevV} sp"; - } else - parsingVCC = $"{prevV}{cc[0]}"; - phonemes.Add(parsingVCC); + // sp fix + if ($"{cc[0]}" == "s" && $"{cc[1]}" == "p") { + parsingVCC = $"{prevV} sp"; } + phonemes.Add(parsingVCC); + phonemes.Add(parsingCC); + } else { + // backpack [@k] + [p@] + + // sp fix + if ($"{cc[0]}" == "s" && $"{cc[1]}" == "p") { + parsingVCC = $"{prevV} sp"; + } else + parsingVCC = $"{prevV}{cc[0]}"; + phonemes.Add(parsingVCC); } } } + } - // LOGIC FOR MORE THAN 2 CONSONANTS - if (cc.Length > 2 && phonemes.Count == 0) { - // also [VC CC] exceptions - var vccExceptions = $"{prevV}{cc[0]}{cc[1]} {cc[2]}"; - var startingC = 2; - // 1nks exception - bool ing = false; - if (exIng || ex1ng || ex1nk) { - vccExceptions = $"1ng {cc[1]}"; - ing = true; - startingC = 1; - if (lastCPrevWord == 2) { - vccExceptions = $"1ng{cc[1]}"; - } - if ($"{cc[1]}" == "k" && lastCPrevWord >= 2) { - vccExceptions = $"1nk"; - startingC = 2; - if ($"{cc[2]}" == "s" && lastCPrevWord == 3) { - vccExceptions = $"1nks"; - startingC = 3; - } + // LOGIC FOR MORE THAN 2 CONSONANTS + if (cc.Length > 2 && phonemes.Count == 0) { + // also [VC CC] exceptions + var vccExceptions = $"{prevV}{cc[0]}{cc[1]} {cc[2]}"; + var startingC = 2; + // 1nks exception + bool ing = false; + if (exIng || ex1ng || ex1nk) { + vccExceptions = $"1ng {cc[1]}"; + ing = true; + startingC = 1; + if (lastCPrevWord == 2) { + vccExceptions = $"1ng{cc[1]}"; + } + if ($"{cc[1]}" == "k" && lastCPrevWord >= 2) { + vccExceptions = $"1nk"; + startingC = 2; + if ($"{cc[2]}" == "s" && lastCPrevWord == 3) { + vccExceptions = $"1nks"; + startingC = 3; } } + } - var ccNoParse = $"{cc[cc.Length - 3]}{cc[cc.Length - 2]}{cc[cc.Length - 1]}"; - bool dontParse = false; - var lastCforLoop = cc.Length - 1; - - // str exceptions - if (cccExceptions.Contains($"{ccNoParse}") && cc.Length - 3 >= lastCPrevWord) { - var vc = $"{prevV}{cc[0]}-"; - if (cc.Length == 3) { - var vccE = vcccExceptions[ccNoParse]; - vc = $"{prevV} {vccE}"; - } - if (cc.Length == 4) { - vc = $"{prevV}{cc[0]}"; - } + var ccNoParse = $"{cc[cc.Length - 3]}{cc[cc.Length - 2]}{cc[cc.Length - 1]}"; + bool dontParse = false; + var lastCforLoop = cc.Length - 1; + + // str exceptions + if (cccExceptions.Contains($"{ccNoParse}") && cc.Length - 3 >= lastCPrevWord) { + var vc = $"{prevV}{cc[0]}-"; + if (cc.Length == 3) { + var vccE = vcccExceptions[ccNoParse]; + vc = $"{prevV} {vccE}"; + } + if (cc.Length == 4) { + vc = $"{prevV}{cc[0]}"; + } - if (vc == "ing") - vc = "1ng"; + if (vc == "ing") + vc = "1ng"; - phonemes.Add(vc); - startingC = 0; - lastCforLoop -= 2; - } else { - ccNoParse = $"{cc[cc.Length - 2]}{cc[cc.Length - 1]}"; - var ccSP = $"{cc[0]}{cc[1]}"; - - // sk, sm, sn, sp & st exceptions - if (cc.Length - lastCPrevWord > 1) { - for (int i = 0; i < ccNoParsing.Length; i++) { - if (ccNoParsing.Contains(ccNoParse)) { - dontParse = true; - break; - } + phonemes.Add(vc); + startingC = 0; + lastCforLoop -= 2; + } else { + ccNoParse = $"{cc[cc.Length - 2]}{cc[cc.Length - 1]}"; + var ccSP = $"{cc[0]}{cc[1]}"; + + // sk, sm, sn, sp & st exceptions + if (cc.Length - lastCPrevWord > 1) { + for (int i = 0; i < ccNoParsing.Length; i++) { + if (ccNoParsing.Contains(ccNoParse)) { + dontParse = true; + break; } } - if (dontParse) { + } + if (dontParse) { - basePhoneme = $"{cc[cc.Length - 2]}{cc[cc.Length - 1]}{v}"; + basePhoneme = $"{cc[cc.Length - 2]}{cc[cc.Length - 1]}{v}"; + vccExceptions = $"1ng {cc[1]}{cc[2]}"; + + if (ing && HasOto(vccExceptions, syllable.vowelTone)) { vccExceptions = $"1ng {cc[1]}{cc[2]}"; + phonemes.Add(vccExceptions); + startingC = 2; + } else { - if (ing && HasOto(vccExceptions, syllable.vowelTone)) { - vccExceptions = $"1ng {cc[1]}{cc[2]}"; - phonemes.Add(vccExceptions); + vccExceptions = $"{prevV}{cc[0]}-"; + + if (vccExceptions == "ing-") { + vccExceptions = "1ng-"; + } + phonemes.Add(vccExceptions); + if (HasOto($"{cc[0]} {cc[1]}{cc[2]}", syllable.vowelTone)) { + phonemes.Add($"{cc[0]} {cc[1]}{cc[2]}"); startingC = 2; } else { - - vccExceptions = $"{prevV}{cc[0]}-"; - - if (vccExceptions == "ing-") { - vccExceptions = "1ng-"; - } - phonemes.Add(vccExceptions); - if (HasOto($"{cc[0]} {cc[1]}{cc[2]}", syllable.vowelTone)) { - phonemes.Add($"{cc[0]} {cc[1]}{cc[2]}"); - startingC = 2; - } else { - basePhoneme = $"-{cc[cc.Length - 2]}{cc[cc.Length - 1]}{v}"; - startingC = 0; - } + basePhoneme = $"-{cc[cc.Length - 2]}{cc[cc.Length - 1]}{v}"; + startingC = 0; } } + } - if (phonemes.Count == 0) { + if (phonemes.Count == 0) { - if (HasOto(vccExceptions, syllable.vowelTone)) { - phonemes.Add(vccExceptions); - } else { startingC = 0; } + if (HasOto(vccExceptions, syllable.vowelTone)) { + phonemes.Add(vccExceptions); + } else { startingC = 0; } - if (phonemes.Count == 0) { - parsingVCC = $"{prevV}{cc[0]}-"; + if (phonemes.Count == 0) { + parsingVCC = $"{prevV}{cc[0]}-"; + if (!HasOto(parsingVCC, syllable.vowelTone)) { + parsingVCC = CheckVCExceptions($"{prevV}{cc[0]}") + "-"; if (!HasOto(parsingVCC, syllable.vowelTone)) { - parsingVCC = CheckVCExceptions($"{prevV}{cc[0]}") + "-"; - if (!HasOto(parsingVCC, syllable.vowelTone)) { - parsingVCC = $"{prevV} {cc[0]}"; - } - } - if (lastCPrevWord == 1 && stopCs.Contains($"{cc[0]}")) { - parsingVCC = $"{prevV}{cc[0]}"; + parsingVCC = $"{prevV} {cc[0]}"; } + } + if (lastCPrevWord == 1 && stopCs.Contains($"{cc[0]}")) { + parsingVCC = $"{prevV}{cc[0]}"; + } - if (ccSP == "sp") { - parsingVCC = $"{prevV} sp"; - } + if (ccSP == "sp") { + parsingVCC = $"{prevV} sp"; + } - phonemes.Add(parsingVCC); - } + phonemes.Add(parsingVCC); } } + } - for (int i = startingC; i < lastCforLoop; i++) { - parsingCC = $"{cc[i]}{cc[i + 1]}-"; + for (int i = startingC; i < lastCforLoop; i++) { + parsingCC = $"{cc[i]}{cc[i + 1]}-"; - if (dontParse && i == cc.Length - 3) { - parsingCC = $"{cc[i]} {cc[i + 1]}{cc[i + 2]}"; - } + if (dontParse && i == cc.Length - 3) { + parsingCC = $"{cc[i]} {cc[i + 1]}{cc[i + 2]}"; + } - if (i == lastCPrevWord - 1) { - parsingCC = $"{cc[i]} {cc[i + 1]}"; - } + if (i == lastCPrevWord - 1) { + parsingCC = $"{cc[i]} {cc[i + 1]}"; + } - if (i == lastCPrevWord - 2) { - parsingCC = $"{cc[i]}{cc[i + 1]}"; + if (i == lastCPrevWord - 2) { + parsingCC = $"{cc[i]}{cc[i + 1]}"; + if (!HasOto(parsingCC, syllable.vowelTone)) { + parsingCC = $"{cc[i]}{cc[i + 1]}-"; if (!HasOto(parsingCC, syllable.vowelTone)) { - parsingCC = $"{cc[i]}{cc[i + 1]}-"; - if (!HasOto(parsingCC, syllable.vowelTone)) { - parsingCC = $"{cc[i]} {cc[i + 1]}-"; - } + parsingCC = $"{cc[i]} {cc[i + 1]}-"; } } - if (!HasOto(parsingCC, syllable.vowelTone) && i != lastCPrevWord - 1) { - - parsingCC = $"{cc[i]}{cc[i + 1]}"; - } - - //if (i + 1 != lastCforLoop - 1) { - // parsingCC = $"{cc[i]}{cc[i + 1]}"; - if (dontParse && i == cc.Length - 2) { - parsingCC = ""; - } - //} + } + if (!HasOto(parsingCC, syllable.vowelTone) && i != lastCPrevWord - 1) { - //ng to nk exception - if ($"{cc[i]}" == "ng" && $"{cc[i + 1]}" == "th" && i + 1 != lastCPrevWord) { - parsingCC = $"nkth"; - } + parsingCC = $"{cc[i]}{cc[i + 1]}"; + } - if (parsingCC != "" && HasOto(parsingCC, syllable.vowelTone)) { - phonemes.Add(parsingCC); - } + //if (i + 1 != lastCforLoop - 1) { + // parsingCC = $"{cc[i]}{cc[i + 1]}"; + if (dontParse && i == cc.Length - 2) { + parsingCC = ""; } + //} - if (cc.Length - lastCPrevWord - 1 > 0 && !dontParse) { - basePhoneme = $"_{cc.Last()}{v}"; + //ng to nk exception + if ($"{cc[i]}" == "ng" && $"{cc[i + 1]}" == "th" && i + 1 != lastCPrevWord) { + parsingCC = $"nkth"; } - //if (ccNoParse == "str") { - if (cccExceptions.Contains($"{ccNoParse}")) { - phonemes.Add(ccNoParse); + if (parsingCC != "" && HasOto(parsingCC, syllable.vowelTone)) { + phonemes.Add(parsingCC); } } + if (cc.Length - lastCPrevWord - 1 > 0 && !dontParse) { + basePhoneme = $"_{cc.Last()}{v}"; + } + + //if (ccNoParse == "str") { + if (cccExceptions.Contains($"{ccNoParse}")) { + phonemes.Add(ccNoParse); + } } - } - if (!HasOto(basePhoneme, syllable.vowelTone)) { basePhoneme = $"{cc.Last()}{v}"; } - phonemes.Add(basePhoneme); - return phonemes; + } } + if (!HasOto(basePhoneme, syllable.vowelTone)) { basePhoneme = $"{cc.Last()}{v}"; } + phonemes.Add(basePhoneme); + return phonemes; + } + protected override List ProcessEnding(Ending ending) { string[] cc = ending.cc.Select(ReplacePhoneme).ToArray(); string v = ReplacePhoneme(ending.prevV); @@ -781,7 +781,7 @@ protected override List ProcessEnding(Ending ending) { } } - + } } @@ -808,7 +808,7 @@ protected override string ValidateAlias(string alias) { } foreach (var consonant in new[] { "6r" }) { alias = alias.Replace(consonant, "3"); - } + } return alias; } diff --git a/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuConfig.cs b/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuConfig.cs index 675f401e9..f1ec64828 100644 --- a/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuConfig.cs +++ b/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuConfig.cs @@ -18,7 +18,7 @@ class EnunuConfig { public static EnunuConfig Load(string configPath, Encoding encoding = null) { encoding = encoding ?? Encoding.UTF8; - var configTxt = File.ReadAllText(configPath,encoding); + var configTxt = File.ReadAllText(configPath, encoding); RawEnunuConfig config = Yaml.DefaultDeserializer.Deserialize(configTxt); return config.Convert(); } diff --git a/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxConfig.cs b/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxConfig.cs index ae6197ea1..867e4df56 100644 --- a/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxConfig.cs +++ b/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxConfig.cs @@ -15,14 +15,14 @@ public struct RedirectionData { } class EnunuOnnxConfig { - + public RedirectionData[] redirections; public static EnunuOnnxConfig Load(string configPath, Encoding encoding = null) { encoding = encoding ?? Encoding.UTF8; var configTxt = File.ReadAllText(configPath, encoding); EnunuOnnxConfig config = Yaml.DefaultDeserializer.Deserialize(configTxt); - if(config.redirections == null) { + if (config.redirections == null) { config.redirections = new RedirectionData[] { }; } return config; @@ -40,12 +40,12 @@ public RedirectionDict(RedirectionData[] datas) { return; } //sort redirection keys from long to short - Array.Sort(datas, (x1,x2)=>- x1.from.Length.CompareTo(x2.from.Length)); + Array.Sort(datas, (x1, x2) => -x1.from.Length.CompareTo(x2.from.Length)); StringBuilder regexBuilder = new StringBuilder("("); - foreach(var line in datas) { + foreach (var line in datas) { string key = string.Join("\n", line.from); - replacements[key] = line.to + new string('\n',line.from.Length - 1); - regexBuilder.Append(Regex.Escape(key)+"|"); + replacements[key] = line.to + new string('\n', line.from.Length - 1); + regexBuilder.Append(Regex.Escape(key) + "|"); } regexBuilder[^1] = ')'; regex = new Regex(regexBuilder.ToString()); diff --git a/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxEnglishPhonemizer.cs b/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxEnglishPhonemizer.cs index 8614f8968..d86672f3c 100644 --- a/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxEnglishPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxEnglishPhonemizer.cs @@ -7,7 +7,7 @@ using Serilog; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("Enunu Onnx English Phonemizer", "ENUNU X EN", language:"EN")] + [Phonemizer("Enunu Onnx English Phonemizer", "ENUNU X EN", language: "EN")] public class EnunuOnnxEnglishPhonemizer : EnunuOnnxPhonemizer { protected override IG2p LoadG2p(string rootPath) { var g2ps = new List(); diff --git a/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxPhonemizer.cs b/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxPhonemizer.cs index 8c3b74a07..7d785bfae 100644 --- a/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/EnunuOnnx/EnunuOnnxPhonemizer.cs @@ -42,7 +42,7 @@ public class EnunuOnnxPhonemizer : Phonemizer { int[] pitchIndices = new int[] { }; Scaler durationInScaler = new Scaler(); Scaler durationOutScaler = new Scaler(); - + //information used by openutau phonemizer protected IG2p g2p; EnunuOnnxConfig enunuOnnxConfig; @@ -70,7 +70,7 @@ public override void SetSinger(USinger singer) { var configTxt = File.ReadAllText(configPath); RawEnunuConfig config = Yaml.DefaultDeserializer.Deserialize(configTxt); enuconfig = config.Convert(); - } catch(Exception e) { + } catch (Exception e) { Log.Error(e, $"failed to load enuconfig from {configPath}"); return; } @@ -124,13 +124,11 @@ public override void SetSinger(USinger singer) { } //Load g2p from enunux.yaml //g2p dict should be load after enunu dict - try - { + try { this.g2p = LoadG2p(rootPath); - } - catch (Exception e) { + } catch (Exception e) { Log.Error(e, "failed to load g2p dictionary"); - return; + return; } } @@ -149,7 +147,7 @@ protected virtual IG2p LoadG2p(string rootPath) { builder.AddSymbol(symbolData.symbol, symbolData.type); } } - foreach(var grapheme in phoneDict.Keys) { + foreach (var grapheme in phoneDict.Keys) { builder.AddEntry(grapheme, phoneDict[grapheme]); } if (data.entries != null) { @@ -161,7 +159,7 @@ protected virtual IG2p LoadG2p(string rootPath) { Log.Error(e, $"Failed to load Dictionary"); } } - foreach(var entry in phoneDict.Keys) { + foreach (var entry in phoneDict.Keys) { builder.AddEntry(entry, phoneDict[entry]); } g2ps.Add(builder.Build()); @@ -265,7 +263,7 @@ string[] GetSymbols(Note note) { } // User has not provided hint, query g2p dictionary. var g2presult = g2p.Query(note.lyric.ToLowerInvariant()); - if(g2presult != null) { + if (g2presult != null) { return g2presult; } //not founded in g2p dictionary, treat lyric as phonetic hint @@ -383,7 +381,7 @@ protected virtual Note[] HandleExcessNotes(Note[] notes, List vowelIds) { } if (notes.Length < vowelIds.Count) { notes = HandleNotEnoughNotes(notes, vowelIds); - } else if(notes.Length > vowelIds.Count) { + } else if (notes.Length > vowelIds.Count) { notes = HandleExcessNotes(notes, vowelIds); } return (symbols, vowelIds.ToArray(), notes); @@ -434,7 +432,7 @@ protected virtual HTSNote[] MakeSyllables(Note[] inputNotes, int startTick) { } } syllables[^1].symbols.AddRange(ccs); - return syllables.Select(x=>makeHtsNote(x.symbols.ToArray(),x.notes,startTick)).ToArray(); + return syllables.Select(x => makeHtsNote(x.symbols.ToArray(), x.notes, startTick)).ToArray(); } HTSPhoneme[] HTSNoteToPhonemes(HTSNote htsNote) { @@ -489,7 +487,7 @@ void ProcessPart(Note[][] phrase) { //Alignment for (int noteIndex = 0; noteIndex < phrase.Length; ++noteIndex) { - HTSNote[] Syllables = MakeSyllables(phrase[noteIndex],offsetTick); + HTSNote[] Syllables = MakeSyllables(phrase[noteIndex], offsetTick); htsNotes.AddRange(Syllables); foreach (var htsNote in Syllables) { var notePhonemes = HTSNoteToPhonemes(htsNote); @@ -536,9 +534,9 @@ void ProcessPart(Note[][] phrase) { numericDict ); //log_f0_conditioning - float lastMidi = 60; - foreach(int idx in pitchIndices) { - foreach(var line in linguistic_features) { + float lastMidi = 60; + foreach (int idx in pitchIndices) { + foreach (var line in linguistic_features) { if (line[idx] > 0) { lastMidi = line[idx]; } diff --git a/OpenUtau.Plugin.Builtin/EnunuOnnx/HTS.cs b/OpenUtau.Plugin.Builtin/EnunuOnnx/HTS.cs index ffe0750b6..68f6a6e02 100644 --- a/OpenUtau.Plugin.Builtin/EnunuOnnx/HTS.cs +++ b/OpenUtau.Plugin.Builtin/EnunuOnnx/HTS.cs @@ -56,11 +56,11 @@ public static int NameToTone(string name) { //write integer with "p" as positive and "n" as negative. 0 is "p0" public static string WriteInt(int integer) { - return (integer >= 0 ? "p":"m" )+Math.Abs(integer).ToString(); + return (integer >= 0 ? "p" : "m") + Math.Abs(integer).ToString(); } } - - public class HTSPhoneme{ + + public class HTSPhoneme { public string symbol; //Links to this phoneme's neighbors and parent @@ -87,7 +87,7 @@ public HTSPhoneme(string phoneme, HTSNote note) { public HTSPhoneme? beforePrev { get { - if (prev == null) { return null; } else { return prev.prev;} + if (prev == null) { return null; } else { return prev.prev; } } } @@ -113,14 +113,14 @@ public string dump() { + string.Format( "/E:{0}]{1}^{2}={3}~{4}!{5}@{6}#{7}+{8}]{9}${10}|{11}[{12}&{13}]{14}={15}^{16}~{17}#{18}_{19};{20}${21}&{22}%{23}[{24}|{25}]{26}-{27}^{28}+{29}~{30}={31}@{32}${33}!{34}%{35}#{36}|{37}|{38}-{39}&{40}&{41}+{42}[{43};{44}]{45};{46}~{47}~{48}^{49}^{50}@{51}[{52}#{53}={54}!{55}~{56}+{57}!{58}^{59}", e()) - +string.Format("/F:{0}#{1}#{2}-{3}${4}${5}+{6}%{7};{8}",f()) + + string.Format("/F:{0}#{1}#{2}-{3}${4}${5}+{6}%{7};{8}", f()) + "/G:xx_xx/H:xx_xx/I:xx_xx/J:xx~xx@1" ; return result; } public string[] p() { - var result = Enumerable.Repeat("xx",16).ToArray(); + var result = Enumerable.Repeat("xx", 16).ToArray(); result[0] = type; result[1] = (beforePrev == null) ? "xx" : beforePrev.symbol; result[2] = (prev == null) ? "xx" : prev.symbol; @@ -149,7 +149,7 @@ public string[] c() { public string[] d() { return parent.d(); } - + public string[] e() { return parent.e(); } @@ -175,7 +175,7 @@ public class HTSNote { public HTSNote? prev; public HTSNote? next; - public HTSNote(string[] symbols, int tone, int startms,int endms,int positionTicks, int durationTicks) { + public HTSNote(string[] symbols, int tone, int startms, int endms, int positionTicks, int durationTicks) { this.startMs = startms; this.endMs = endms; this.tone = tone; @@ -239,7 +239,7 @@ public string[] e() { } public string[] d() { - if(prev == null) { + if (prev == null) { return Enumerable.Repeat("xx", 60).ToArray(); } else { return prev.e(); diff --git a/OpenUtau.Plugin.Builtin/EnunuOnnx/HTSLabelFile.cs b/OpenUtau.Plugin.Builtin/EnunuOnnx/HTSLabelFile.cs index 87fd0028a..917a2c10b 100644 --- a/OpenUtau.Plugin.Builtin/EnunuOnnx/HTSLabelFile.cs +++ b/OpenUtau.Plugin.Builtin/EnunuOnnx/HTSLabelFile.cs @@ -1,9 +1,9 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; -using System.Collections; -using System.IO; using System.Text.RegularExpressions; using OpenUtau.Plugin.Builtin.EnunuOnnx.nnmnkwii.python; //reference: https://github.com/r9y9/nnmnkwii/blob/master/nnmnkwii/io/hts.py diff --git a/OpenUtau.Plugin.Builtin/EnunuOnnx/Merlin.cs b/OpenUtau.Plugin.Builtin/EnunuOnnx/Merlin.cs index cfb874872..109bfa9bb 100644 --- a/OpenUtau.Plugin.Builtin/EnunuOnnx/Merlin.cs +++ b/OpenUtau.Plugin.Builtin/EnunuOnnx/Merlin.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Text.RegularExpressions; using System.Linq; +using System.Text.RegularExpressions; using OpenUtau.Plugin.Builtin.EnunuOnnx.nnmnkwii.io.hts; //reference: https://github.com/r9y9/nnmnkwii/blob/master/nnmnkwii/frontend/merlin.py @@ -60,7 +60,7 @@ public static List pattern_matching_binary( public static float[] pattern_matching_continous_position( Dictionary> numeric_dict, string label) { int dict_size = numeric_dict.Count; - var lab_continuous_vector = Enumerable.Repeat(0f,dict_size).ToArray(); + var lab_continuous_vector = Enumerable.Repeat(0f, dict_size).ToArray(); foreach (int i in Enumerable.Range(0, dict_size)) { //ignored code: Always true //if isinstance(current_compiled, tuple): @@ -81,7 +81,7 @@ public static float[] pattern_matching_continous_position( var ms = current_compiled.Match(label); if (ms.Success) { string note = ms.Groups[1].Value; - if (HTS.NameToTone(note)>0) { + if (HTS.NameToTone(note) > 0) { continuous_value = HTS.NameToTone(note); } else if (note.StartsWith("p")) { continuous_value = int.Parse(note[1..]); @@ -90,7 +90,7 @@ public static float[] pattern_matching_continous_position( } else if (float.TryParse(note, out float num)) { continuous_value = num; } - + } lab_continuous_vector[i] = continuous_value; } diff --git a/OpenUtau.Plugin.Builtin/EnunuOnnx/Scaler.cs b/OpenUtau.Plugin.Builtin/EnunuOnnx/Scaler.cs index 6201fcfe5..ae2081dd3 100644 --- a/OpenUtau.Plugin.Builtin/EnunuOnnx/Scaler.cs +++ b/OpenUtau.Plugin.Builtin/EnunuOnnx/Scaler.cs @@ -19,7 +19,7 @@ public void inverse_transform(IList xs) { public class Scaler : List { - public static Scaler load(string path,Encoding encoding = null) { + public static Scaler load(string path, Encoding encoding = null) { //Encoding is UTF-8 by default if (encoding == null) { encoding = Encoding.UTF8; @@ -30,15 +30,15 @@ public static Scaler load(string path,Encoding encoding = null) { public void transform(IList x) { //In-place transform a vector - for(int i = 0; i < this.Count; i++) { + for (int i = 0; i < this.Count; i++) { x[i] = (x[i] - this[i].xmin) * this[i].scale; } } - + public void transform(IEnumerable> xs) { //In-place transform a bunch of vectors - foreach(IList x in xs) { + foreach (IList x in xs) { transform(x); } } diff --git a/OpenUtau.Plugin.Builtin/FILtoJAPhonemizer.cs b/OpenUtau.Plugin.Builtin/FILtoJAPhonemizer.cs index 02e2e62b1..6aee5cd0b 100644 --- a/OpenUtau.Plugin.Builtin/FILtoJAPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/FILtoJAPhonemizer.cs @@ -456,7 +456,7 @@ protected override List ProcessEnding(Ending ending) { prevV = WanaKana.ToRomaji(solo).Last().ToString(); } - + if (ending.IsEndingV) { TryAddPhoneme(phonemes, ending.tone, $"{prevV} R", $"{prevV} -", $"{prevV}-"); } @@ -482,7 +482,7 @@ protected override List ProcessEnding(Ending ending) { var vc = $"{vowel} {cons}"; var altVc = $"{vowel} {cons[0]}"; - + if (HasOto(vc, tone)) { phonemes.Add(vc); } else if (HasOto(altVc, tone)) { diff --git a/OpenUtau.Plugin.Builtin/FilipinoPhonemizer.cs b/OpenUtau.Plugin.Builtin/FilipinoPhonemizer.cs index 386031bb3..2684e06ad 100644 --- a/OpenUtau.Plugin.Builtin/FilipinoPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/FilipinoPhonemizer.cs @@ -36,7 +36,7 @@ public class FilipinoPhonemizer : SyllableBasedPhonemizer { // Store the merging replacements private List mergingReplacements = new List(); - string[] diphthongs = new[] { "ay", "ey", "oy", "uy", "aw", "ew", "ow", "iw" }; + string[] diphthongs = new[] { "ay", "ey", "oy", "uy", "aw", "ew", "ow", "iw" }; // For banks with missing vowels private readonly Dictionary missingVphonemes = "ax=a".Split(',') @@ -67,7 +67,7 @@ public class FilipinoPhonemizer : SyllableBasedPhonemizer { {"uy","u"}, {"ew","e"}, }; - + private readonly Dictionary vvExceptions = new Dictionary() { {"aw","w"}, @@ -327,7 +327,7 @@ public override void SetSinger(USinger singer) { Log.Error($"Failed to load fallbacks from filipino.yaml: {ex.Message}"); } } catch (Exception ex) { - Log.Error($"Failed to parse filipino.yaml: {ex.Message}, content: {File.ReadAllText(file)}, Exception Type: {ex.GetType()}"); + Log.Error($"Failed to parse filipino.yaml: {ex.Message}, content: {File.ReadAllText(file)}, Exception Type: {ex.GetType()}"); } } ReadDictionaryAndInit(); diff --git a/OpenUtau.Plugin.Builtin/FrenchCMUSphinxPhonemizer.cs b/OpenUtau.Plugin.Builtin/FrenchCMUSphinxPhonemizer.cs index 32adeb4e9..59d446719 100644 --- a/OpenUtau.Plugin.Builtin/FrenchCMUSphinxPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/FrenchCMUSphinxPhonemizer.cs @@ -9,7 +9,7 @@ namespace OpenUtau.Plugin.Builtin { /// /// A French diphone phonemizer that uses CMUSphinx dictionary. /// - [Phonemizer("French CMUSphinx Phonemizer", "FR SPHINX", language:"FR")] + [Phonemizer("French CMUSphinx Phonemizer", "FR SPHINX", language: "FR")] public class FrenchCMUSphinxPhonemizer : LatinDiphonePhonemizer { public FrenchCMUSphinxPhonemizer() { try { diff --git a/OpenUtau.Plugin.Builtin/FrenchCVVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/FrenchCVVCPhonemizer.cs index 973907a1f..75dd4f5bf 100644 --- a/OpenUtau.Plugin.Builtin/FrenchCVVCPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/FrenchCVVCPhonemizer.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using OpenUtau.Api; -using System.Linq; namespace OpenUtau.Plugin.Builtin { diff --git a/OpenUtau.Plugin.Builtin/FrenchVCCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/FrenchVCCVPhonemizer.cs index 15a36996e..2a6bf7cad 100644 --- a/OpenUtau.Plugin.Builtin/FrenchVCCVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/FrenchVCCVPhonemizer.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using OpenUtau.Api; -using System.Linq; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("French VCCV m2RUg Phonemizer", "FR VCCV", "Mim", language:"FR")] + [Phonemizer("French VCCV m2RUg Phonemizer", "FR VCCV", "Mim", language: "FR")] public class FrenchVCCVPhonemizer : SyllableBasedPhonemizer { @@ -50,8 +50,8 @@ protected override List ProcessSyllable(Syllable syllable) { basePhoneme = $"- {v}"; } else if (syllable.IsVV) { // if VV - //if (!CanMakeAliasExtension(syllable)) { - basePhoneme = $"{prevV} {v}"; + //if (!CanMakeAliasExtension(syllable)) { + basePhoneme = $"{prevV} {v}"; //} else { // // the previous alias will be extended // basePhoneme = null; @@ -60,7 +60,7 @@ protected override List ProcessSyllable(Syllable syllable) { } else if (syllable.IsStartingCVWithOneConsonant) { basePhoneme = $"- {cc[0]}{v}"; - if(!HasOto(basePhoneme,syllable.tone)) { + if (!HasOto(basePhoneme, syllable.tone)) { TryAddPhoneme(phonemes, syllable.tone, $"- {cc[0]}"); basePhoneme = $"{cc[0]}{v}"; } @@ -75,8 +75,8 @@ protected override List ProcessSyllable(Syllable syllable) { basePhoneme = $"{cc.Last()}{v}"; // CC + CCV support - var ccv = $"{cc[cc.Length-2]}{cc.Last()}{v}"; - if (HasOto(ccv,syllable.tone)) { + var ccv = $"{cc[cc.Length - 2]}{cc.Last()}{v}"; + if (HasOto(ccv, syllable.tone)) { basePhoneme = ccv; for (int i = 0; i < cc.Length - 2; i++) { @@ -87,7 +87,7 @@ protected override List ProcessSyllable(Syllable syllable) { } if (!HasOto(cci, syllable.tone)) { cci = $"{cc[i]}{cc[i + 1]}_"; - if (i+1 == cc.Length-2 && HasOto($"_{ccv}",syllable.tone)) { + if (i + 1 == cc.Length - 2 && HasOto($"_{ccv}", syllable.tone)) { basePhoneme = $"_{ccv}"; } } @@ -101,7 +101,7 @@ protected override List ProcessSyllable(Syllable syllable) { if (i == 0) { cci = $"- {cc[i]}{cc[i + 1]}_"; - if (!HasOto(cci,syllable.tone)) { + if (!HasOto(cci, syllable.tone)) { cci = $"{cc[i]}{cc[i + 1]}_"; } } @@ -175,7 +175,7 @@ protected override List ProcessSyllable(Syllable syllable) { } // convert 'n + j' to 'J' - if($"{cc.Last()}" == "j" && $"{cc[cc.Length-2]}" == "n") { + if ($"{cc.Last()}" == "j" && $"{cc[cc.Length - 2]}" == "n") { basePhoneme = $"J{v}"; } @@ -201,7 +201,7 @@ protected override List ProcessEnding(Ending ending) { // try 'VC -' else 'V C' + 'C -' var vc = $"{v}{cc[0]} -"; - if(HasOto(vc,ending.tone)) { + if (HasOto(vc, ending.tone)) { phonemes.Add(vc); } else { vc = $"{v} {cc[0]}"; @@ -210,7 +210,7 @@ protected override List ProcessEnding(Ending ending) { var cE = $"{cc[0]} -"; phonemes.Add(cE); } - + } else { @@ -223,11 +223,11 @@ protected override List ProcessEnding(Ending ending) { for (int i = 0; i < cc.Length - 1; i++) { var cci = $"{cc[i]} {cc[i + 1]}"; - if(i == cc.Length - 2) { + if (i == cc.Length - 2) { cci = $"{cc[i]}{cc[i + 1]} -"; hasEnding = true; } - if (!HasOto(cci,ending.tone)) { + if (!HasOto(cci, ending.tone)) { cci = $"{cc[i]}{cc[i + 1]}_"; hasEnding = false; } diff --git a/OpenUtau.Plugin.Builtin/GermanDiphonePhonemizer.cs b/OpenUtau.Plugin.Builtin/GermanDiphonePhonemizer.cs index 2c41603d6..5388f282c 100644 --- a/OpenUtau.Plugin.Builtin/GermanDiphonePhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/GermanDiphonePhonemizer.cs @@ -14,7 +14,7 @@ namespace OpenUtau.Plugin.Builtin { /// [Phonemizer("German Diphone Phonemizer", "DE DIPHONE", "Lotte V", language: "DE")] public class GermanDiphonePhonemizer : LatinDiphonePhonemizer { - + public GermanDiphonePhonemizer() { try { Initialize(); diff --git a/OpenUtau.Plugin.Builtin/GermanVCCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/GermanVCCVPhonemizer.cs index f4a9d24e9..ec137e4f3 100644 --- a/OpenUtau.Plugin.Builtin/GermanVCCVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/GermanVCCVPhonemizer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -432,4 +432,4 @@ protected override double GetTransitionBasicLengthMs(string alias = "") { return base.GetTransitionBasicLengthMs(); } } -} \ No newline at end of file +} diff --git a/OpenUtau.Plugin.Builtin/ItalianSyllableBasedPhonemizer.cs b/OpenUtau.Plugin.Builtin/ItalianSyllableBasedPhonemizer.cs index cdea78214..b92ba39e3 100644 --- a/OpenUtau.Plugin.Builtin/ItalianSyllableBasedPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/ItalianSyllableBasedPhonemizer.cs @@ -1,13 +1,13 @@ -using System; +using System; using System.Collections.Generic; +using System.Linq; using System.Text; using OpenUtau.Api; using OpenUtau.Core.G2p; -using System.Linq; using Serilog; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("Italian Syllable-Based Phonemizer", "IT SYL", "Lotte V", language:"IT")] + [Phonemizer("Italian Syllable-Based Phonemizer", "IT SYL", "Lotte V", language: "IT")] public class ItalianSyllableBasedPhonemizer : SyllableBasedPhonemizer { /// /// Italian syllable-based phonemizer. @@ -32,8 +32,7 @@ public class ItalianSyllableBasedPhonemizer : SyllableBasedPhonemizer { protected override IG2p LoadBaseDictionary() => new ItalianG2p(); - protected override List ProcessSyllable(Syllable syllable) - { + protected override List ProcessSyllable(Syllable syllable) { string prevV = syllable.prevV; string[] cc = syllable.cc; string v = syllable.v; @@ -82,20 +81,17 @@ protected override List ProcessSyllable(Syllable syllable) } } else { basePhoneme = cc.Last() + v; - // try CCV - if (cc.Length - firstC > 1) - { - for (var i = firstC; i < cc.Length; i++) - { - var ccv = $"{string.Join("", cc.Skip(i))}{v}"; - if (HasOto(ccv, syllable.vowelTone) && !ccv.Contains("bre")) - { - lastC = i; - basePhoneme = ccv; - break; - } + // try CCV + if (cc.Length - firstC > 1) { + for (var i = firstC; i < cc.Length; i++) { + var ccv = $"{string.Join("", cc.Skip(i))}{v}"; + if (HasOto(ccv, syllable.vowelTone) && !ccv.Contains("bre")) { + lastC = i; + basePhoneme = ccv; + break; } } + } phonemes.Add($"{prevV} {cc[0]}"); } for (var i = firstC; i < lastC; i++) { @@ -117,7 +113,7 @@ protected override List ProcessSyllable(Syllable syllable) if (i + 1 < lastC) { var cc2 = $"{string.Join("", cc.Take(i))}"; if (!HasOto(cc2, syllable.tone)) { - cc2 = $"{cc[i + 1]}{cc[i + 2]}"; + cc2 = $"{cc[i + 1]}{cc[i + 2]}"; } if (!HasOto($"{cc[i + 1]}{cc[i + 2]}", syllable.tone) && !HasOto($"{string.Join("", cc.Skip(i))}", syllable.tone)) { cc2 = $"{cc[i + 1]} {cc[i + 2]}"; @@ -135,7 +131,7 @@ protected override List ProcessSyllable(Syllable syllable) // like [V C1] [C1 C2-] [C3 ..] } } else { - // like [V C1] [C1 C2] [C2 ..] or like [V C1] [C1 -] [C3 ..] + // like [V C1] [C1 C2] [C2 ..] or like [V C1] [C1 -] [C3 ..] TryAddPhoneme(phonemes, syllable.tone, cc1); } } @@ -144,8 +140,7 @@ protected override List ProcessSyllable(Syllable syllable) return phonemes; } - protected override List ProcessEnding(Ending ending) - { + protected override List ProcessEnding(Ending ending) { string[] cc = ending.cc; string v = ending.prevV; @@ -161,11 +156,9 @@ protected override List ProcessEnding(Ending ending) } } else if (ending.IsEndingVCWithMoreThanOneConsonant) { phonemes.Add($"{v} {cc[0]}"); - for (var i = 0; i < cc.Length - 1; i++) - { + for (var i = 0; i < cc.Length - 1; i++) { var cc1 = $"{cc[i]}{cc[i + 1]}-"; - if (HasOto(cc1, ending.tone)) - { + if (HasOto(cc1, ending.tone)) { phonemes.Add(cc1); } } diff --git a/OpenUtau.Plugin.Builtin/JapaneseCVVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/JapaneseCVVCPhonemizer.cs index 8034d1db1..862c09759 100644 --- a/OpenUtau.Plugin.Builtin/JapaneseCVVCPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/JapaneseCVVCPhonemizer.cs @@ -6,9 +6,9 @@ using Serilog; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("Japanese CVVC Phonemizer (legacy)", "JA CVVC", "TUBS",language:"JA")] + [Phonemizer("Japanese CVVC Phonemizer (legacy)", "JA CVVC", "TUBS", language: "JA")] public class JapaneseCVVCPhonemizer : Phonemizer { - static readonly string[] plainVowels = new string[] {"あ","い","う","え","お","を","ん","ン"}; + static readonly string[] plainVowels = new string[] { "あ", "い", "う", "え", "お", "を", "ん", "ン" }; static readonly string[] nonVowels = new string[]{"息","吸","R","-","k","ky","g","gy", "s","sh","z","j","t","ch","ty","ts", "d","dy","n","ny","h","hy","f","b", @@ -66,7 +66,7 @@ public class JapaneseCVVCPhonemizer : Phonemizer { }; // in case voicebank is missing certain symbols - static readonly string[] substitution = new string[] { + static readonly string[] substitution = new string[] { "ty,ch,ts=t", "j,dy=d", "gy=g", "ky=k", "py=p", "ny=n", "ry=r", "my=m", "hy,f=h", "by,v=b", "dz=z", "l=r", "ly=l" }; @@ -189,14 +189,14 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN if (vowelLookup.TryGetValue(prevLyric.LastOrDefault().ToString() ?? string.Empty, out var vow)) { var vowLyric = $"{vow} {currentLyric}"; // try vowlyric before cflyric, if both fail try currentlyric - string[] tests = new string[] {vowLyric, cfLyric, currentLyric}; - if (checkOtoUntilHit(tests, note, out var oto)){ + string[] tests = new string[] { vowLyric, cfLyric, currentLyric }; + if (checkOtoUntilHit(tests, note, out var oto)) { currentLyric = oto.Alias; } } } else { - string[] tests = new string[] {cfLyric, currentLyric}; - if (checkOtoUntilHit(tests, note, out var oto)){ + string[] tests = new string[] { cfLyric, currentLyric }; + if (checkOtoUntilHit(tests, note, out var oto)) { currentLyric = oto.Alias; } } @@ -240,10 +240,10 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } var vcPhoneme = $"{vowel} {consonant}"; - var vcPhonemes = new string[] {vcPhoneme, ""}; + var vcPhonemes = new string[] { vcPhoneme, "" }; // find potential substitute symbol - if (substituteLookup.TryGetValue(consonant ?? string.Empty, out con)){ - vcPhonemes[1] = $"{vowel} {con}"; + if (substituteLookup.TryGetValue(consonant ?? string.Empty, out con)) { + vcPhonemes[1] = $"{vowel} {con}"; } //if (singer.TryGetMappedOto(vcPhoneme, note.tone + attr0.toneShift, attr0.voiceColor, out var oto1)) { if (checkOtoUntilHitVc(vcPhonemes, note, out var oto1)) { diff --git a/OpenUtau.Plugin.Builtin/JapanesePresampPhonemizer.cs b/OpenUtau.Plugin.Builtin/JapanesePresampPhonemizer.cs index d83d21e86..e8e99ad1a 100644 --- a/OpenUtau.Plugin.Builtin/JapanesePresampPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/JapanesePresampPhonemizer.cs @@ -209,7 +209,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN result.Insert(0, new Phoneme() { phoneme = cOto.Alias, - position = Convert.ToInt32(- cLength), + position = Convert.ToInt32(-cLength), index = 2, expressions = new List() }); diff --git a/OpenUtau.Plugin.Builtin/JapaneseVCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/JapaneseVCVPhonemizer.cs index 40ba76adc..b8c825715 100644 --- a/OpenUtau.Plugin.Builtin/JapaneseVCVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/JapaneseVCVPhonemizer.cs @@ -54,7 +54,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } // The alias for no previous neighbour note. For example, "- な" for "な". - string[] tests = new string[] { $"- {currentLyric}" , currentLyric}; + string[] tests = new string[] { $"- {currentLyric}", currentLyric }; if (prevNeighbour != null) { // If there is a previous neighbour note, first get its hint or lyric. var prevLyric = prevNeighbour.Value.lyric.Normalize(); diff --git a/OpenUtau.Plugin.Builtin/KOtoJAPhonemizer.cs b/OpenUtau.Plugin.Builtin/KOtoJAPhonemizer.cs index f05e18a7d..5871db17e 100644 --- a/OpenUtau.Plugin.Builtin/KOtoJAPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/KOtoJAPhonemizer.cs @@ -458,7 +458,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN phoneme = currPhoneme } } - }; + }; } else prevIMF = GetIMFFromHint(prevNeighbour.Value.phoneticHint); if (string.IsNullOrEmpty(prevIMF[2])) { diff --git a/OpenUtau.Plugin.Builtin/KoreanCBNNPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanCBNNPhonemizer.cs index 008f86847..37ad1533d 100644 --- a/OpenUtau.Plugin.Builtin/KoreanCBNNPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/KoreanCBNNPhonemizer.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.Linq; using OpenUtau.Api; -using OpenUtau.Core.Ustx; using OpenUtau.Core; +using OpenUtau.Core.Ustx; namespace OpenUtau.Plugin.Builtin { /// Phonemizer for 'KOR CBNN' /// @@ -13,11 +13,11 @@ namespace OpenUtau.Plugin.Builtin { public class KoreanCBNNPhonemizer : BaseKoreanPhonemizer { public override void SetSinger(USinger singer) { - if (this.singer == singer) {return;} + if (this.singer == singer) { return; } this.singer = singer; - if (this.singer == null) {return;} + if (this.singer == null) { return; } - if (this.singer.SingerType != USingerType.Classic){return;} + if (this.singer.SingerType != USingerType.Classic) { return; } } @@ -43,7 +43,7 @@ public override void SetSinger(USinger singer) { {"ㅎ", "h"}, {"null", ""} // 뒤 글자가 없을 때를 대비 }; - + static readonly Dictionary MIDDLE_VOWELS = new Dictionary(){ {"ㅏ", new string[3]{"a", "", "a"}}, {"ㅐ", new string[3]{"e", "", "e"}}, @@ -100,12 +100,12 @@ public override void SetSinger(USinger singer) { {" ", new string[]{"", ""}}, // no batchim {"null", new string[]{"", ""}} // 뒤 글자가 없을 때를 대비 }; - + private Result ConvertForCBNN(Note[] notes, string[] prevLyric, string[] thisLyric, string[] nextLyric, Note? nextNeighbour) { string thisMidVowelHead; string thisMidVowelTail; - + int totalDuration = notes.Sum(n => n.duration); Note note = notes[0]; @@ -123,19 +123,18 @@ private Result ConvertForCBNN(Note[] notes, string[] prevLyric, string[] thisLyr bool isItNeedsEndSound; isItNeedsVV = prevLyric[2] == " " && thisLyric[0] == "ㅇ" && PLAIN_VOWELS.Contains(thisLyric[1]); - + isItNeedsFrontCV = prevLyric[0] == "null" || prevLyric[1] == "null" || (prevLyric[2] != "null" && HARD_BATCHIMS.Contains(prevLyric[2]) && prevLyric[2] != "ㅁ"); isRelaxedVC = nextLyric[0] == "null" || nextLyric[1] == "null" || ((thisLyric[2] == nextLyric[0]) && (KoreanPhonemizerUtil.nasalSounds.ContainsKey(thisLyric[2]) || thisLyric[2] == "ㄹ")); isItNeedsEndSound = (nextLyric[0] == "null" || nextLyric[1] == "null") && nextNeighbour == null; if (thisLyric.All(part => part == null)) { return GenerateResult(FindInOto(note.lyric, note)); - } - else { + } else { thisMidVowelHead = $"{MIDDLE_VOWELS[thisLyric[1]][1]}"; thisMidVowelTail = $"{MIDDLE_VOWELS[thisLyric[1]][2]}"; } - - string CV = $"{FIRST_CONSONANTS[thisLyric[0]]}{thisMidVowelHead}{thisMidVowelTail}{LAST_CONSONANTS[thisLyric[2]][1]}"; + + string CV = $"{FIRST_CONSONANTS[thisLyric[0]]}{thisMidVowelHead}{thisMidVowelTail}{LAST_CONSONANTS[thisLyric[2]][1]}"; if (FindInOto(CV, note, true) == null) { CV = CV.Substring(0, CV.Length - 1); } @@ -164,61 +163,60 @@ private Result ConvertForCBNN(Note[] notes, string[] prevLyric, string[] thisLyr } } - if (isItNeedsVV) {CV = VV;} - + if (isItNeedsVV) { CV = VV; } + if (thisLyric[2] == " " && isItNeedsVC) { // no batchim, needs VC - if (isItNeedsFrontCV){ + if (isItNeedsFrontCV) { return GenerateResult(FindInOto(frontCV, note), FindInOto(VC, note), totalDuration, 120, 3); } return GenerateResult(FindInOto(CV, note), FindInOto(VC, note), totalDuration, 120, 3); } if (thisLyric[2] == " " && isItNeedsVSv) { // no batchim, needs VSv - if (isItNeedsFrontCV){ + if (isItNeedsFrontCV) { return GenerateResult(FindInOto(frontCV, note), FindInOto(VSv, note), totalDuration, 120, 3); } return GenerateResult(FindInOto(CV, note), FindInOto(VSv, note), totalDuration, 120, 3); } if (thisLyric[2] == " ") { // no batchim, doesn't need VC - if (isItNeedsFrontCV){ - return isItNeedsEndSound ? + if (isItNeedsFrontCV) { + return isItNeedsEndSound ? GenerateResult(FindInOto(frontCV, note), FindInOto(endSound, note), totalDuration, 8) : GenerateResult(FindInOto(frontCV, note)); } - return isItNeedsEndSound ? + return isItNeedsEndSound ? GenerateResult(FindInOto(CV, note), FindInOto(endSound, note), totalDuration, 8) : GenerateResult(FindInOto(CV, note)); } - + batchim = $"{thisMidVowelTail}{LAST_CONSONANTS[thisLyric[2]][0]}"; - - - if (thisLyric[2] == "ㅁ" || ! HARD_BATCHIMS.Contains(thisLyric[2])) { // batchim ㅁ + ㄴ ㄹ ㅇ - if (isItNeedsFrontCV){ - return isRelaxedVC ? + + + if (thisLyric[2] == "ㅁ" || !HARD_BATCHIMS.Contains(thisLyric[2])) { // batchim ㅁ + ㄴ ㄹ ㅇ + if (isItNeedsFrontCV) { + return isRelaxedVC ? GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 120, 8) : GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), FindInOto(endSound, note), totalDuration, 120, 2, 3); } - return isRelaxedVC ? + return isRelaxedVC ? GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), totalDuration, 120, 8) : GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), FindInOto(endSound, note), totalDuration, 120, 2, 3); - } - else { - if (isItNeedsFrontCV){ - return isRelaxedVC ? + } else { + if (isItNeedsFrontCV) { + return isRelaxedVC ? GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 120, 8) : GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 120, 5); } - return isRelaxedVC ? + return isRelaxedVC ? GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), totalDuration, 120, 8) : GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), totalDuration, 120, 5); } - + } - private string? FindInOto(String phoneme, Note note, bool nullIfNotFound=false){ + private string? FindInOto(String phoneme, Note note, bool nullIfNotFound = false) { return BaseKoreanPhonemizer.FindInOto(singer, phoneme, note, nullIfNotFound); } @@ -228,29 +226,29 @@ public override Result ConvertPhonemes(Note[] notes, Note? prev, Note? next, Not Hashtable lyrics = KoreanPhonemizerUtil.Variate(prevNeighbour, note, nextNeighbour); string[] prevLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - (string)lyrics[0], - (string)lyrics[1], + (string)lyrics[0], + (string)lyrics[1], (string)lyrics[2] }; string[] thisLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - (string)lyrics[3], - (string)lyrics[4], + (string)lyrics[3], + (string)lyrics[4], (string)lyrics[5] }; string[] nextLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - (string)lyrics[6], - (string)lyrics[7], + (string)lyrics[6], + (string)lyrics[7], (string)lyrics[8] }; - if (thisLyric[0] == "null") { + if (thisLyric[0] == "null") { return GenerateResult(FindInOto(notes[0].lyric, notes[0])); } - + return ConvertForCBNN(notes, prevLyric, thisLyric, nextLyric, nextNeighbour); } - + public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) { Note note = notes[0]; @@ -262,8 +260,8 @@ public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, No Hashtable lyrics = KoreanPhonemizerUtil.Separate(prevNeighbour_.lyric); string[] prevLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - (string)lyrics[0], - (string)lyrics[1], + (string)lyrics[0], + (string)lyrics[1], (string)lyrics[2] }; @@ -272,14 +270,14 @@ public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, No string prevMidVowel; prevMidVowel = MIDDLE_VOWELS.ContainsKey(soundBeforeEndSound) ? MIDDLE_VOWELS[soundBeforeEndSound][2] : LAST_CONSONANTS[soundBeforeEndSound][0]; - + if (FindInOto($"{prevMidVowel} {endSound}", note, true) == null) { if (FindInOto($"{prevMidVowel}{endSound}", note, true) == null) { return GenerateResult(FindInOto($"{endSound}", note)); } return GenerateResult(FindInOto($"{prevMidVowel}{endSound}", note, true)); } - return GenerateResult(FindInOto($"{prevMidVowel} {endSound}", note)); + return GenerateResult(FindInOto($"{prevMidVowel} {endSound}", note)); } } -} \ No newline at end of file +} diff --git a/OpenUtau.Plugin.Builtin/KoreanCVCCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanCVCCVPhonemizer.cs index d42470b77..fc5652def 100644 --- a/OpenUtau.Plugin.Builtin/KoreanCVCCVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/KoreanCVCCVPhonemizer.cs @@ -8,7 +8,7 @@ using static OpenUtau.Api.Phonemizer; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("Korean CVCCV Phonemizer", "KO CVCCV", "RYUUSEI", language:"KO")] + [Phonemizer("Korean CVCCV Phonemizer", "KO CVCCV", "RYUUSEI", language: "KO")] public class KoreanCVCCVPhonemizer : BaseKoreanPhonemizer { static readonly string initialConsonantsTable = "ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ"; static readonly string vowelsTable = "ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ"; @@ -282,10 +282,10 @@ static KoreanCVCCVPhonemizer() { private USinger singer; public override void SetSinger(USinger singer) => this.singer = singer; - + // Legacy mapping. Might adjust later to new mapping style. - public override bool LegacyMapping => true; - + public override bool LegacyMapping => true; + public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevs) { var prevLyric = prevNeighbour?.lyric; var nextLyric = nextNeighbour?.lyric; @@ -295,10 +295,10 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN int totalDuration = notes.Sum(n => n.duration); int vcLength = 120; - + var phoneticHint = RenderPhoneticHint(singer, notes[0], totalDuration); if (phoneticHint != null) { - return (Result) phoneticHint; + return (Result)phoneticHint; } var romaji2Korean = ConvertRomajiNoteToHangeul(notes, prevNeighbour, nextNeighbour); @@ -306,10 +306,10 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN notes = romaji2Korean.KoreanLyricNotes; prevNeighbour = romaji2Korean.KoreanLyricPrevNote; nextNeighbour = romaji2Korean.KoreanLyricNextNote; - + prevLyric = prevNeighbour?.lyric; nextLyric = nextNeighbour?.lyric; - } + } List phonemesArr = new List(); @@ -324,9 +324,10 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN return new Result { phonemes = new Phoneme[] { new Phoneme { - phoneme = currentLyric, + phoneme = currentLyric, + } } - }}; + }; } if (prevLyric != null && prevLyric[0] >= '가' && prevLyric[0] <= '힣') { @@ -377,7 +378,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN phoneme = $"{currentCCVConsonants}{currentVowel}", } ); - + break; case TYPE_FLAG.VC_NCV: @@ -517,7 +518,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } ); } - + break; case TYPE_FLAG.VC_CCV: @@ -631,7 +632,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN case TYPE_FLAG.CV: break; - }; + } } else { // 뒷글자 없음 diff --git a/OpenUtau.Plugin.Builtin/KoreanCVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanCVCPhonemizer.cs index 6c1fa2afd..4d7d8a66b 100644 --- a/OpenUtau.Plugin.Builtin/KoreanCVCPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/KoreanCVCPhonemizer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using OpenUtau.Api; @@ -6,7 +6,7 @@ using OpenUtau.Core.Ustx; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("KoreanCVCPhonemizer", "KO CVC", "NANA", language:"KO")] + [Phonemizer("KoreanCVCPhonemizer", "KO CVC", "NANA", language: "KO")] public class KoreanCVCPhonemizer : BaseKoreanPhonemizer { @@ -100,29 +100,13 @@ public override void SetUp(Note[][] groups, UProject project, UTrack track) { KoreanPhonemizerUtil.RomanizeNotes(groups, false); } + static readonly string[] alphaConsonants = new string[] { + "gg", "dd", "bb", "ss", "f", "v", "z", "th", "rr", + "g", "n", "d", "r", "m", "b", "s", "j", "ch", + "k", "t", "p", "h" + }; bool isAlphaCon(string str) { - if (str == "gg") { return true; } - else if (str == "dd") { return true; } - else if (str == "bb") { return true; } - else if (str == "ss") { return true; } - else if (str == "f") { return true; } - else if (str == "v") { return true; } - else if (str == "z") { return true; } - else if (str == "th") { return true; } - else if (str == "rr") { return true; } - else if (str == "g") { return true; } - else if (str == "n") { return true; } - else if (str == "d") { return true; } - else if (str == "r") { return true; } - else if (str == "m") { return true; } - else if (str == "b") { return true; } - else if (str == "s") { return true; } - else if (str == "j") { return true; } - else if (str == "ch") { return true; } - else if (str == "k") { return true; } - else if (str == "t") { return true; } - else if (str == "p") { return true; } - else if (str == "h") { return true; }else { return false; } + return alphaConsonants.Contains(str); } static KoreanCVCPhonemizer() { @@ -148,21 +132,21 @@ static KoreanCVCPhonemizer() { public override void SetSinger(USinger singer) => this.singer = singer; // make it quicker to check multiple oto occurrences at once rather than spamming if else if - private bool checkOtoUntilHit(string[] input, Note note, out UOto oto){ - oto = default; + private bool checkOtoUntilHit(string[] input, Note note, out UOto oto) { + oto = default; - var attr0 = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default; - var attr1 = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 1) ?? default; + var attr0 = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default; + var attr1 = note.phonemeAttributes?.FirstOrDefault(attr => attr.index == 1) ?? default; - foreach (string test in input){ - if (singer.TryGetMappedOto(test, note.tone + attr0.toneShift, attr0.voiceColor, out oto)){ - return true; - } + foreach (string test in input) { + if (singer.TryGetMappedOto(test, note.tone + attr0.toneShift, attr0.voiceColor, out oto)) { + return true; } - - return false; } + return false; + } + public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) { var note = notes[0]; var currentUnicode = ToUnicodeElements(note.lyric); // 현재 가사의 유니코드 @@ -216,7 +200,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN var phoneticHint = RenderPhoneticHint(singer, notes[0], totalDuration); if (phoneticHint != null) { - return (Result) phoneticHint; + return (Result)phoneticHint; } @@ -312,60 +296,233 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN if (prevExist && prevHangeul && (CLconsonant == 11) && (TPLfinal != "")) { int temp = PLfinal; - if (temp == 1) { TCLtemp = naConsonants[0].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 2) { TCLtemp = naConsonants[1].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 3) { TCLtemp = naConsonants[10].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 4) { TCLtemp = naConsonants[2].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 5) { TCLtemp = naConsonants[12].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 6) { TCLtemp = naConsonants[18].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 7) { TCLtemp = naConsonants[3].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 8) { TCLtemp = naConsonants[5].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 9) { TCLtemp = naConsonants[0].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 10) { TCLtemp = naConsonants[6].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 11) { TCLtemp = naConsonants[7].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 12) { TCLtemp = naConsonants[9].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 13) { TCLtemp = naConsonants[16].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 14) { TCLtemp = naConsonants[17].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 15) { TCLtemp = naConsonants[18].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 16) { TCLtemp = naConsonants[6].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 17) { TCLtemp = naConsonants[7].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 18) { TCLtemp = naConsonants[9].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 19) { TCLtemp = naConsonants[9].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 20) { TCLtemp = naConsonants[10].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 21) { tempTCLconsonant = ""; yeoneum = true; } - else if (temp == 22) { TCLtemp = naConsonants[12].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 23) { TCLtemp = naConsonants[14].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 24) { TCLtemp = naConsonants[15].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 25) { TCLtemp = naConsonants[16].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 26) { TCLtemp = naConsonants[17].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } - else if (temp == 27) { TCLtemp = naConsonants[18].Split(":"); tempTCLconsonant = TCLtemp[1]; yeoneum = true; } + if (temp == 1) { + TCLtemp = naConsonants[0].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 2) { + TCLtemp = naConsonants[1].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 3) { + TCLtemp = naConsonants[10].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 4) { + TCLtemp = naConsonants[2].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 5) { + TCLtemp = naConsonants[12].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 6) { + TCLtemp = naConsonants[18].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 7) { + TCLtemp = naConsonants[3].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 8) { + TCLtemp = naConsonants[5].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 9) { + TCLtemp = naConsonants[0].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 10) { + TCLtemp = naConsonants[6].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 11) { + TCLtemp = naConsonants[7].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 12) { + TCLtemp = naConsonants[9].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 13) { + TCLtemp = naConsonants[16].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 14) { + TCLtemp = naConsonants[17].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 15) { + TCLtemp = naConsonants[18].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 16) { + TCLtemp = naConsonants[6].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 17) { + TCLtemp = naConsonants[7].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 18) { + TCLtemp = naConsonants[9].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 19) { + TCLtemp = naConsonants[9].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 20) { + TCLtemp = naConsonants[10].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 21) { + tempTCLconsonant = ""; + yeoneum = true; + } else if (temp == 22) { + TCLtemp = naConsonants[12].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 23) { + TCLtemp = naConsonants[14].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 24) { + TCLtemp = naConsonants[15].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 25) { + TCLtemp = naConsonants[16].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 26) { + TCLtemp = naConsonants[17].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } else if (temp == 27) { + TCLtemp = naConsonants[18].Split(":"); + tempTCLconsonant = TCLtemp[1]; + yeoneum = true; + } } if (nextExist && nextHangeul && (TCLfinal != "") && (TNLconsonant == "")) { int temp = CLfinal; - if (temp == 1) { TCLtemp = naConsonants[0].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } - else if (temp == 2) { TCLtemp = naConsonants[1].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } - else if (temp == 3) { TCLfinal = "k"; yeoneum2 = true; } - else if (temp == 4) { TCLtemp = naConsonants[2].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } - else if (temp == 5) { TCLfinal = "n"; yeoneum2 = true; } - else if (temp == 6) { TCLfinal = "n"; yeoneum2 = true; } - else if (temp == 7) { TCLtemp = naConsonants[3].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } - else if (temp == 8) { TCLtemp = naConsonants[5].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } - else if (temp == 9) { TCLfinal = "l"; yeoneum2 = true; } - else if (temp == 10) { TCLfinal = "l"; yeoneum2 = true; } - else if (temp == 11) { TCLfinal = "l"; yeoneum2 = true; } - else if (temp == 12) { TCLfinal = "l"; yeoneum2 = true; } - else if (temp == 13) { TCLfinal = "l"; yeoneum2 = true; } - else if (temp == 14) { TCLfinal = "l"; yeoneum2 = true; } - else if (temp == 15) { TCLfinal = "l"; yeoneum2 = true; } - else if (temp == 16) { TCLtemp = naConsonants[6].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } - else if (temp == 17) { TCLtemp = naConsonants[7].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } - else if (temp == 18) { TCLfinal = "p"; yeoneum2 = true; } - else if (temp == 19) { TCLtemp = naConsonants[9].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } - else if (temp == 20) { TCLtemp = naConsonants[10].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } - //else if (temp == 21) { TCLtemp = naConsonants[11].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } - else if (temp == 22) { TCLtemp = naConsonants[12].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } else if (temp == 23) { TCLtemp = naConsonants[14].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } else if (temp == 24) { TCLtemp = naConsonants[15].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } else if (temp == 25) { TCLtemp = naConsonants[16].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } else if (temp == 26) { TCLtemp = naConsonants[17].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } else if (temp == 27) { TCLtemp = naConsonants[18].Split(":"); tempTCLfinal = TCLtemp[1]; TCLfinal = ""; yeoneum2 = true; } + if (temp == 1) { + TCLtemp = naConsonants[0].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 2) { + TCLtemp = naConsonants[1].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 3) { + TCLfinal = "k"; + yeoneum2 = true; + } else if (temp == 4) { + TCLtemp = naConsonants[2].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 5) { + TCLfinal = "n"; + yeoneum2 = true; + } else if (temp == 6) { + TCLfinal = "n"; + yeoneum2 = true; + } else if (temp == 7) { + TCLtemp = naConsonants[3].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 8) { + TCLtemp = naConsonants[5].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 9) { + TCLfinal = "l"; + yeoneum2 = true; + } else if (temp == 10) { + TCLfinal = "l"; + yeoneum2 = true; + } else if (temp == 11) { + TCLfinal = "l"; + yeoneum2 = true; + } else if (temp == 12) { + TCLfinal = "l"; + yeoneum2 = true; + } else if (temp == 13) { + TCLfinal = "l"; + yeoneum2 = true; + } else if (temp == 14) { + TCLfinal = "l"; + yeoneum2 = true; + } else if (temp == 15) { + TCLfinal = "l"; + yeoneum2 = true; + } else if (temp == 16) { + TCLtemp = naConsonants[6].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 17) { + TCLtemp = naConsonants[7].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 18) { + TCLfinal = "p"; + yeoneum2 = true; + } else if (temp == 19) { + TCLtemp = naConsonants[9].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 20) { + TCLtemp = naConsonants[10].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + // } else if (temp == 21) { + // TCLtemp = naConsonants[11].Split(":"); + // tempTCLfinal = TCLtemp[1]; + // TCLfinal = ""; + // yeoneum2 = true; + } else if (temp == 22) { + TCLtemp = naConsonants[12].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 23) { + TCLtemp = naConsonants[14].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 24) { + TCLtemp = naConsonants[15].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 25) { + TCLtemp = naConsonants[16].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 26) { + TCLtemp = naConsonants[17].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } else if (temp == 27) { + TCLtemp = naConsonants[18].Split(":"); + tempTCLfinal = TCLtemp[1]; + TCLfinal = ""; + yeoneum2 = true; + } } if (yeoneum) { TCLconsonant = tempTCLconsonant; } @@ -374,16 +531,82 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN // 2. 격음화/유기음화/거센소리되기 if (prevExist && prevHangeul && (TPLfinal != "")) { - if (((PLfinal == 27) && (CLconsonant == 0)) || ((PLfinal == 6) && (CLconsonant == 0)) || ((PLfinal == 15) && (CLconsonant == 0))) { TCLconsonant = "k"; } else if (((PLfinal == 27) && (CLconsonant == 3)) || ((PLfinal == 6) && (CLconsonant == 3)) || ((PLfinal == 15) && (CLconsonant == 3))) { TCLconsonant = "t"; } else if (((PLfinal == 27) && (CLconsonant == 12)) || ((PLfinal == 6) && (CLconsonant == 12)) || ((PLfinal == 15) && (CLconsonant == 12))) { TCLconsonant = "ch"; } else if (((PLfinal == 27) && (CLconsonant == 9)) || ((PLfinal == 6) && (CLconsonant == 9)) || ((PLfinal == 15) && (CLconsonant == 9))) { TCLconsonant = "ss"; } + if (((PLfinal == 27) && (CLconsonant == 0)) || ((PLfinal == 6) && (CLconsonant == 0)) || ((PLfinal == 15) && (CLconsonant == 0))) { + TCLconsonant = "k"; + } else if (((PLfinal == 27) && (CLconsonant == 3)) || ((PLfinal == 6) && (CLconsonant == 3)) || ((PLfinal == 15) && (CLconsonant == 3))) { + TCLconsonant = "t"; + } else if (((PLfinal == 27) && (CLconsonant == 12)) || ((PLfinal == 6) && (CLconsonant == 12)) || ((PLfinal == 15) && (CLconsonant == 12))) { + TCLconsonant = "ch"; + } else if (((PLfinal == 27) && (CLconsonant == 9)) || ((PLfinal == 6) && (CLconsonant == 9)) || ((PLfinal == 15) && (CLconsonant == 9))) { + TCLconsonant = "ss"; + } - if ((PLfinal == 1) && (CLconsonant == 18)) { TCLconsonant = "k"; } else if ((PLfinal == 7) && (CLconsonant == 18)) { TCLconsonant = "t"; } else if ((PLfinal == 17) && (CLconsonant == 18)) { TCLconsonant = "p"; } else if ((PLfinal == 22) && (CLconsonant == 18)) { TCLconsonant = "ch"; } + if ((PLfinal == 1) && (CLconsonant == 18)) { + TCLconsonant = "k"; + } else if ((PLfinal == 7) && (CLconsonant == 18)) { + TCLconsonant = "t"; + } else if ((PLfinal == 17) && (CLconsonant == 18)) { + TCLconsonant = "p"; + } else if ((PLfinal == 22) && (CLconsonant == 18)) { + TCLconsonant = "ch"; + } } if (nextExist && nextHangeul && (TCLfinal != "")) { - if ((NLconsonant == 0) && (CLfinal == 27)) { TCLfinal = ""; TNLconsonant = "k"; } else if ((NLconsonant == 0) && (CLfinal == 6)) { TCLfinal = "n"; TNLconsonant = "k"; } else if ((NLconsonant == 0) && (CLfinal == 15)) { TCLfinal = "l"; TNLconsonant = "k"; } else if ((NLconsonant == 3) && (CLfinal == 27)) { TCLfinal = ""; TNLconsonant = "t"; } else if ((NLconsonant == 3) && (CLfinal == 6)) { TCLfinal = "n"; TNLconsonant = "t"; } else if ((NLconsonant == 3) && (CLfinal == 15)) { TCLfinal = "l"; TNLconsonant = "t"; } else if ((NLconsonant == 12) && (CLfinal == 27)) { TCLfinal = ""; TNLconsonant = "ch"; } else if ((NLconsonant == 12) && (CLfinal == 6)) { TCLfinal = "n"; TNLconsonant = "ch"; } else if ((NLconsonant == 12) && (CLfinal == 15)) { TCLfinal = "l"; TNLconsonant = "ch"; } else if ((NLconsonant == 9) && (CLfinal == 27)) { TCLfinal = ""; TNLconsonant = "ss"; } else if ((NLconsonant == 9) && (CLfinal == 6)) { TCLfinal = "n"; TNLconsonant = "ss"; } else if ((NLconsonant == 9) && (CLfinal == 15)) { TCLfinal = "l"; TNLconsonant = "ss"; } + if ((NLconsonant == 0) && (CLfinal == 27)) { + TCLfinal = ""; + TNLconsonant = "k"; + } else if ((NLconsonant == 0) && (CLfinal == 6)) { + TCLfinal = "n"; + TNLconsonant = "k"; + } else if ((NLconsonant == 0) && (CLfinal == 15)) { + TCLfinal = "l"; + TNLconsonant = "k"; + } else if ((NLconsonant == 3) && (CLfinal == 27)) { + TCLfinal = ""; + TNLconsonant = "t"; + } else if ((NLconsonant == 3) && (CLfinal == 6)) { + TCLfinal = "n"; + TNLconsonant = "t"; + } else if ((NLconsonant == 3) && (CLfinal == 15)) { + TCLfinal = "l"; + TNLconsonant = "t"; + } else if ((NLconsonant == 12) && (CLfinal == 27)) { + TCLfinal = ""; + TNLconsonant = "ch"; + } else if ((NLconsonant == 12) && (CLfinal == 6)) { + TCLfinal = "n"; + TNLconsonant = "ch"; + } else if ((NLconsonant == 12) && (CLfinal == 15)) { + TCLfinal = "l"; + TNLconsonant = "ch"; + } else if ((NLconsonant == 9) && (CLfinal == 27)) { + TCLfinal = ""; + TNLconsonant = "ss"; + } else if ((NLconsonant == 9) && (CLfinal == 6)) { + TCLfinal = "n"; + TNLconsonant = "ss"; + } else if ((NLconsonant == 9) && (CLfinal == 15)) { + TCLfinal = "l"; + TNLconsonant = "ss"; + } - if ((NLconsonant == 2) && (CLfinal == 27)) { TCLfinal = "n"; } + if ((NLconsonant == 2) && (CLfinal == 27)) { + TCLfinal = "n"; + } - if ((NLconsonant == 18) && (CLfinal == 1)) { TCLfinal = ""; TNLconsonant = "k"; } else if ((NLconsonant == 18) && (CLfinal == 7)) { TCLfinal = ""; TNLconsonant = "t"; } else if ((NLconsonant == 18) && (CLfinal == 17)) { TCLfinal = ""; TNLconsonant = "p"; } else if ((NLconsonant == 18) && (CLfinal == 22)) { TCLfinal = ""; TNLconsonant = "ch"; } + if ((NLconsonant == 18) && (CLfinal == 1)) { + TCLfinal = ""; + TNLconsonant = "k"; + } else if ((NLconsonant == 18) && (CLfinal == 7)) { + TCLfinal = ""; + TNLconsonant = "t"; + } else if ((NLconsonant == 18) && (CLfinal == 17)) { + TCLfinal = ""; + TNLconsonant = "p"; + } else if ((NLconsonant == 18) && (CLfinal == 22)) { + TCLfinal = ""; + TNLconsonant = "ch"; + } } @@ -401,7 +624,17 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN // 4. 경음화/된소리되기 if (prevExist && prevHangeul && TPLfinal != "") { // ㄱㄷㅂ + ㄱㄷㅂㅅㅈ = ㄲㄸㅃㅆㅉ - if (((TPLfinal == "k") && (CLconsonant == 0)) || ((TPLfinal == "t") && (CLconsonant == 0)) || ((TPLfinal == "p") && (CLconsonant == 0))) { TCLconsonant = "gg"; } else if (((TPLfinal == "k") && (CLconsonant == 3)) || ((TPLfinal == "t") && (CLconsonant == 3)) || ((TPLfinal == "p") && (CLconsonant == 3))) { TCLconsonant = "dd"; } else if (((TPLfinal == "k") && (CLconsonant == 7)) || ((TPLfinal == "t") && (CLconsonant == 7)) || ((TPLfinal == "p") && (CLconsonant == 7))) { TCLconsonant = "bb"; } else if (((TPLfinal == "k") && (CLconsonant == 9)) || ((TPLfinal == "t") && (CLconsonant == 9)) || ((TPLfinal == "p") && (CLconsonant == 9))) { TCLconsonant = "ss"; } else if (((TPLfinal == "k") && (CLconsonant == 12)) || ((TPLfinal == "t") && (CLconsonant == 12)) || ((TPLfinal == "p") && (CLconsonant == 12))) { TCLconsonant = "jj"; } + if (((TPLfinal == "k") && (CLconsonant == 0)) || ((TPLfinal == "t") && (CLconsonant == 0)) || ((TPLfinal == "p") && (CLconsonant == 0))) { + TCLconsonant = "gg"; + } else if (((TPLfinal == "k") && (CLconsonant == 3)) || ((TPLfinal == "t") && (CLconsonant == 3)) || ((TPLfinal == "p") && (CLconsonant == 3))) { + TCLconsonant = "dd"; + } else if (((TPLfinal == "k") && (CLconsonant == 7)) || ((TPLfinal == "t") && (CLconsonant == 7)) || ((TPLfinal == "p") && (CLconsonant == 7))) { + TCLconsonant = "bb"; + } else if (((TPLfinal == "k") && (CLconsonant == 9)) || ((TPLfinal == "t") && (CLconsonant == 9)) || ((TPLfinal == "p") && (CLconsonant == 9))) { + TCLconsonant = "ss"; + } else if (((TPLfinal == "k") && (CLconsonant == 12)) || ((TPLfinal == "t") && (CLconsonant == 12)) || ((TPLfinal == "p") && (CLconsonant == 12))) { + TCLconsonant = "jj"; + } /* // 용언 어간 받침 ㄴㅁ + ㄱㄷㅅㅈ = ㄲㄸㅆㅉ @@ -412,10 +645,24 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN */ // 관형사형 어미ㄹ / 한자어 ㄹ + ㄷㅅㅈ = ㄸㅆㅉ - if ((PLfinal == 8) && (CLconsonant == 3)) { TCLconsonant = "dd"; } else if ((PLfinal == 8) && (CLconsonant == 9)) { TCLconsonant = "ss"; } else if ((PLfinal == 8) && (CLconsonant == 12)) { TCLconsonant = "jj"; } + if ((PLfinal == 8) && (CLconsonant == 3)) { + TCLconsonant = "dd"; + } else if ((PLfinal == 8) && (CLconsonant == 9)) { + TCLconsonant = "ss"; + } else if ((PLfinal == 8) && (CLconsonant == 12)) { + TCLconsonant = "jj"; + } // 어간 받침 ㄼㄾ + ㄱㄷㅅㅈ = ㄲㄸㅆㅉ - if (((PLfinal == 11) && (CLconsonant == 0)) || ((PLfinal == 13) && (CLconsonant == 0))) { TCLconsonant = "gg"; } else if (((PLfinal == 11) && (CLconsonant == 3)) || ((PLfinal == 13) && (CLconsonant == 3))) { TCLconsonant = "dd"; } else if (((PLfinal == 11) && (CLconsonant == 9)) || ((PLfinal == 13) && (CLconsonant == 9))) { TCLconsonant = "ss"; } else if (((PLfinal == 11) && (CLconsonant == 12)) || ((PLfinal == 13) && (CLconsonant == 12))) { TCLconsonant = "jj"; } + if (((PLfinal == 11) && (CLconsonant == 0)) || ((PLfinal == 13) && (CLconsonant == 0))) { + TCLconsonant = "gg"; + } else if (((PLfinal == 11) && (CLconsonant == 3)) || ((PLfinal == 13) && (CLconsonant == 3))) { + TCLconsonant = "dd"; + } else if (((PLfinal == 11) && (CLconsonant == 9)) || ((PLfinal == 13) && (CLconsonant == 9))) { + TCLconsonant = "ss"; + } else if (((PLfinal == 11) && (CLconsonant == 12)) || ((PLfinal == 13) && (CLconsonant == 12))) { + TCLconsonant = "jj"; + } } @@ -488,7 +735,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN VC = TCLplainvowel + "p"; } else if (nextExist && (TCLfinal == "") && nextHangeul && (TNLconsonant != "gg" || TNLconsonant != "dd" || TNLconsonant != "bb")) { VC = TCLplainvowel + " " + TNLconsonant; - } + } string FC = ""; if (TCLfinal != "") { FC = TCLplainvowel + TCLfinal; } @@ -501,8 +748,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN if (checkOtoUntilHit(tests, note, out var oto)) { CV = oto.Alias; } - } - else if (!prevExist && TCLconsonant != "r") { + } else if (!prevExist && TCLconsonant != "r") { string[] tests = new string[] { $"- {CV}", CV, currentLyric }; if (checkOtoUntilHit(tests, note, out var oto)) { CV = oto.Alias; @@ -515,7 +761,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN CV = oto.Alias; } } - + if (prevExist && TCLconsonant == "" && TPLfinal == "ng") { string[] tests = new string[] { $"ng{CV}", CV, currentLyric }; if (checkOtoUntilHit(tests, note, out var oto)) { @@ -575,8 +821,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } else if ((!isAlphaCon(consonant))) { consonant = con; } } else if (nextExist && nextHangeul) { consonant = TNLconsonant; - } else if (nextLyric.StartsWith("ch")) { consonant = "ch"; } - else if (nextLyric.StartsWith("l")) { + } else if (nextLyric.StartsWith("ch")) { consonant = "ch"; } else if (nextLyric.StartsWith("l")) { consonant = "l"; } @@ -616,10 +861,15 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN if (nextExist) { if ((nextNeighbour?.lyric)[0] == 'ㄹ') { VC = TCLplainvowel + "l"; } } if ((VC != "") && (TNLconsonant != "")) { int vcLength = 60; - if ((TNLconsonant == "r") || (TNLconsonant == "h")) { vcLength = 30; } - else if (TNLconsonant == "s") { vcLength = totalDuration/3; } - else if ((TNLconsonant == "k") || (TNLconsonant == "t") || (TNLconsonant == "p") || (TNLconsonant == "ch")) { vcLength = totalDuration / 2; } - else if ((TNLconsonant == "gg") || (TNLconsonant == "dd") || (TNLconsonant == "bb") || (TNLconsonant == "ss") || (TNLconsonant == "jj")) { vcLength = totalDuration / 2; } + if ((TNLconsonant == "r") || (TNLconsonant == "h")) { + vcLength = 30; + } else if (TNLconsonant == "s") { + vcLength = totalDuration / 3; + } else if ((TNLconsonant == "k") || (TNLconsonant == "t") || (TNLconsonant == "p") || (TNLconsonant == "ch")) { + vcLength = totalDuration / 2; + } else if ((TNLconsonant == "gg") || (TNLconsonant == "dd") || (TNLconsonant == "bb") || (TNLconsonant == "ss") || (TNLconsonant == "jj")) { + vcLength = totalDuration / 2; + } vcLength = Math.Min(totalDuration / 2, vcLength); if (singer.TryGetMappedOto(CV, note.tone + attr0.toneShift, attr0.voiceColor, out var oto1) && singer.TryGetMappedOto(VC, note.tone + attr0.toneShift, attr0.voiceColor, out var oto2)) { @@ -644,7 +894,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN var nextLyric = string.Join("", nextUnicode); if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + nextAttr.toneShift, nextAttr.voiceColor, out var oto0)) { vcLength = MsToTick(oto0.Preutter); - + } vcLength = Math.Min(totalDuration / 2, vcLength); @@ -687,7 +937,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN endBreath = $"{TPLplainfinal} R"; } - if (singer.TryGetMappedOto(endBreath, note.tone + attr0.toneShift, attr0.voiceColor, out var oto)){ + if (singer.TryGetMappedOto(endBreath, note.tone + attr0.toneShift, attr0.voiceColor, out var oto)) { endBreath = oto.Alias; return new Result { phonemes = new Phoneme[] { @@ -707,9 +957,9 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN if (prevNeighbour == null) { // Use "- V" or "- CV" if present in voicebank var initial = $"- {currentLyric}"; - string[] tests = new string[] {initial, currentLyric}; + string[] tests = new string[] { initial, currentLyric }; // try [- XX] before trying plain lyric - if (checkOtoUntilHit(tests, note, out var oto)){ + if (checkOtoUntilHit(tests, note, out var oto)) { currentLyric = oto.Alias; } } else if (plainVowels.Contains(currentLyric) || plainDiphthongs.Contains(currentLyric)) { @@ -789,8 +1039,8 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } } } else { - string[] tests = new string[] {currentLyric}; - if (checkOtoUntilHit(tests, note, out var oto)){ + string[] tests = new string[] { currentLyric }; + if (checkOtoUntilHit(tests, note, out var oto)) { currentLyric = oto.Alias; } } @@ -834,15 +1084,15 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN consonant = "t"; } if ((!isAlphaCon(consonant))) { consonant = con; } - } else if (nextLyric.StartsWith("gg")) { + } else if (nextLyric.StartsWith("gg")) { consonant = "k"; - } else if (nextLyric.StartsWith("dd")) { + } else if (nextLyric.StartsWith("dd")) { consonant = "t"; - } else if (nextLyric.StartsWith("bb")) { + } else if (nextLyric.StartsWith("bb")) { consonant = "p"; - } else if (nextLyric.StartsWith("l")) { + } else if (nextLyric.StartsWith("l")) { consonant = "l"; - } else if (nextExist && nextHangeul) { + } else if (nextExist && nextHangeul) { consonant = TNLconsonant; if (TNLconsonant == "gg") { consonant = "k"; @@ -877,7 +1127,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } else { vcPhoneme = $"{vowel} {consonant}"; } - var vcPhonemes = new string[] {vcPhoneme, ""}; + var vcPhonemes = new string[] { vcPhoneme, "" }; if (checkOtoUntilHit(vcPhonemes, note, out var oto1)) { vcPhoneme = oto1.Alias; } else { @@ -889,16 +1139,21 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN }, }; } - + int vcLength = 60; var nextAttr = nextNeighbour.Value.phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default; if (singer.TryGetMappedOto(nextLyric, nextNeighbour.Value.tone + nextAttr.toneShift, nextAttr.voiceColor, out var oto)) { vcLength = MsToTick(oto.Preutter); - } else if ((TNLconsonant == "r") || (TNLconsonant == "h")) { vcLength = 30; } - else if (TNLconsonant == "s") { vcLength = totalDuration / 3; } - else if ((TNLconsonant == "k") || (TNLconsonant == "t") || (TNLconsonant == "p") || (TNLconsonant == "ch")) { vcLength = totalDuration / 2; } - else if ((TNLconsonant == "gg") || (TNLconsonant == "dd") || (TNLconsonant == "bb") || (TNLconsonant == "ss") || (TNLconsonant == "jj")) { vcLength = totalDuration / 2; } - vcLength = Math.Min(totalDuration / 2, vcLength); + } else if ((TNLconsonant == "r") || (TNLconsonant == "h")) { + vcLength = 30; + } else if (TNLconsonant == "s") { + vcLength = totalDuration / 3; + } else if ((TNLconsonant == "k") || (TNLconsonant == "t") || (TNLconsonant == "p") || (TNLconsonant == "ch")) { + vcLength = totalDuration / 2; + } else if ((TNLconsonant == "gg") || (TNLconsonant == "dd") || (TNLconsonant == "bb") || (TNLconsonant == "ss") || (TNLconsonant == "jj")) { + vcLength = totalDuration / 2; + } + vcLength = Math.Min(totalDuration / 2, vcLength); return new Result { phonemes = new Phoneme[] { diff --git a/OpenUtau.Plugin.Builtin/KoreanCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanCVPhonemizer.cs index cd94fb123..1bd28acec 100644 --- a/OpenUtau.Plugin.Builtin/KoreanCVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/KoreanCVPhonemizer.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.Linq; using OpenUtau.Api; -using OpenUtau.Core.Ustx; using OpenUtau.Core; +using OpenUtau.Core.Ustx; namespace OpenUtau.Plugin.Builtin { /// Phonemizer for 'KOR CV' /// @@ -18,11 +18,11 @@ public class KoreanCVPhonemizer : BaseKoreanPhonemizer { public bool isUsingShi, isUsing_aX, isUsingCV_L, isUsing_i, isRentan, isUsingBatchimSpace, isUsingTanBatchim; public override void SetSinger(USinger singer) { - if (this.singer == singer) {return;} + if (this.singer == singer) { return; } this.singer = singer; - if (this.singer == null) {return;} + if (this.singer == null) { return; } - if (this.singer.SingerType != USingerType.Classic){return;} + if (this.singer.SingerType != USingerType.Classic) { return; } koreanCVIniSetting = new KoreanCVIniSetting(); koreanCVIniSetting.Initialize(singer, "ko-CV.ini", new Hashtable(){ @@ -48,7 +48,7 @@ public override void SetSinger(USinger singer) { isRentan = koreanCVIniSetting.isRentan; } - private class KoreanCVIniSetting : BaseIniManager{ + private class KoreanCVIniSetting : BaseIniManager { public bool isRentan; public bool isUsingShi; public bool isUsing_aX; @@ -61,13 +61,13 @@ protected override void IniSetUp(Hashtable iniSetting) { // ko-CV.ini SetOrReadThisValue("CV", "Use rentan", false, out var resultValue); // 연단음 사용 유무 - 기본값 false isRentan = resultValue; - + SetOrReadThisValue("CV", "Use 'shi' for '시'(otherwise 'si')", false, out resultValue); // 시를 [shi]로 표기할 지 유무 - 기본값 false isUsingShi = resultValue; SetOrReadThisValue("CV", "Use 'i' for '의'(otherwise 'eui')", false, out resultValue); // 의를 [i]로 표기할 지 유무 - 기본값 false isUsing_i = resultValue; - + SetOrReadThisValue("CV", "Use replace the batchim 'L' with 'l' when followed by 'r'", false, out resultValue); // 받침 ㄹ 뒤에 오는 ㄹ 가사를 l로 치환 유무 - 기본값 false(= r 사용) isUsingCV_L = resultValue; @@ -81,7 +81,7 @@ protected override void IniSetUp(Hashtable iniSetting) { isUsingBatchimSpace = resultValue; } } - + static readonly Dictionary FIRST_CONSONANTS = new Dictionary(){ {"ㄱ", "g"}, {"ㄲ", "gg"}, @@ -104,7 +104,7 @@ protected override void IniSetUp(Hashtable iniSetting) { {"ㅎ", "h"}, {"null", ""} // 뒤 글자가 없을 때를 대비 }; - + static readonly Dictionary MIDDLE_VOWELS = new Dictionary(){ {"ㅏ", new string[3]{"a", "", "a"}}, {"ㅐ", new string[3]{"e", "", "e"}}, @@ -161,7 +161,7 @@ protected override void IniSetUp(Hashtable iniSetting) { {" ", new string[]{""}}, // no batchim {"null", new string[]{"", ""}} // 뒤 글자가 없을 때를 대비 }; - + private Result ConvertForCV(Note[] notes, string[] prevLyric, string[] thisLyric, string[] nextLyric) { string thisMidVowelHead; string thisMidVowelTail; @@ -175,24 +175,21 @@ private Result ConvertForCV(Note[] notes, string[] prevLyric, string[] thisLyric if (thisLyric.All(part => part == null)) { return GenerateResult(FindInOto(note.lyric, note)); - } - else if (thisLyric[1] == "ㅢ") { + } else if (thisLyric[1] == "ㅢ") { if (isUsing_i) { thisMidVowelHead = $"{MIDDLE_VOWELS["ㅣ"][1]}"; thisMidVowelTail = $"{MIDDLE_VOWELS["ㅣ"][2]}"; - } - else { + } else { thisMidVowelHead = $"{MIDDLE_VOWELS["ㅢ"][1]}"; thisMidVowelTail = $"{MIDDLE_VOWELS["ㅢ"][2]}"; } - } - else { + } else { thisMidVowelHead = $"{MIDDLE_VOWELS[thisLyric[1]][1]}"; thisMidVowelTail = $"{MIDDLE_VOWELS[thisLyric[1]][2]}"; } - - - string CV = $"{FIRST_CONSONANTS[thisLyric[0]]}{thisMidVowelHead}{thisMidVowelTail}"; + + + string CV = $"{FIRST_CONSONANTS[thisLyric[0]]}{thisMidVowelHead}{thisMidVowelTail}"; string frontCV; string batchim; @@ -201,7 +198,7 @@ private Result ConvertForCV(Note[] notes, string[] prevLyric, string[] thisLyric CV = $"l{thisMidVowelHead}{thisMidVowelTail}"; // 초성을 l로 변경 } } - + if (isRentan) { frontCV = $"- {CV}"; if (FindInOto(frontCV, note, true) == null) { @@ -210,55 +207,52 @@ private Result ConvertForCV(Note[] notes, string[] prevLyric, string[] thisLyric frontCV = CV; } } - } - else { + } else { frontCV = CV; } - + if (thisLyric[2] == " ") { // no batchim - if (isItNeedsFrontCV){ + if (isItNeedsFrontCV) { return GenerateResult(FindInOto(frontCV, note)); } return GenerateResult(FindInOto(CV, note)); } - + if (isUsing_aX) { batchim = $"{thisMidVowelTail}{LAST_CONSONANTS[thisLyric[2]][0]}"; - } - else if (isUsingTanBatchim) { + } else if (isUsingTanBatchim) { batchim = $"{LAST_CONSONANTS[thisLyric[2]][0]}"; - } - else { + } else { batchim = $"{thisMidVowelTail} {LAST_CONSONANTS[thisLyric[2]][0]}"; } - - if (thisLyric[2] == "ㅁ" || ! HARD_BATCHIMS.Contains(thisLyric[2])) { // batchim ㅁ + ㄴ ㄹ ㅇ + + if (thisLyric[2] == "ㅁ" || !HARD_BATCHIMS.Contains(thisLyric[2])) { // batchim ㅁ + ㄴ ㄹ ㅇ if (isItNeedsFrontCV) { - return isRelaxedVC ? - GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 120, 8) - : (isUsingBatchimSpace ? - GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), "", totalDuration, 120, 3, 5) - : GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 120, 8)); + return isRelaxedVC ? + GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 120, 8) + : (isUsingBatchimSpace ? + GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), "", totalDuration, 120, 3, 5) + : GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 120, 8)); } - return isRelaxedVC ? - GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), totalDuration, 120, 8) - : (isUsingBatchimSpace ? - GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), "", totalDuration, 120, 3, 5) + return isRelaxedVC ? + GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), totalDuration, 120, 8) + : (isUsingBatchimSpace ? + GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), "", totalDuration, 120, 3, 5) : GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), totalDuration, 120, 8)); } else { - if (isItNeedsFrontCV){ - return isRelaxedVC ? + if (isItNeedsFrontCV) { + return isRelaxedVC ? GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 120, 8) : GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 120, 5); } - return isRelaxedVC ? + return isRelaxedVC ? GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), totalDuration, 120, 8) : GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), totalDuration, 120, 5); } - + } - private string? FindInOto(String phoneme, Note note, bool nullIfNotFound=false){ + private string? FindInOto(String phoneme, Note note, bool nullIfNotFound = false) { return BaseKoreanPhonemizer.FindInOto(singer, phoneme, note, nullIfNotFound); } @@ -268,29 +262,29 @@ public override Result ConvertPhonemes(Note[] notes, Note? prev, Note? next, Not Hashtable lyrics = KoreanPhonemizerUtil.Variate(prevNeighbour, note, nextNeighbour); string[] prevLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - (string)lyrics[0], - (string)lyrics[1], + (string)lyrics[0], + (string)lyrics[1], (string)lyrics[2] }; string[] thisLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - (string)lyrics[3], - (string)lyrics[4], + (string)lyrics[3], + (string)lyrics[4], (string)lyrics[5] }; string[] nextLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - (string)lyrics[6], - (string)lyrics[7], + (string)lyrics[6], + (string)lyrics[7], (string)lyrics[8] }; - if (thisLyric[0] == "null") { + if (thisLyric[0] == "null") { return GenerateResult(FindInOto(notes[0].lyric, notes[0])); } - + return ConvertForCV(notes, prevLyric, thisLyric, nextLyric); } - + public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) { Note note = notes[0]; @@ -302,8 +296,8 @@ public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, No Hashtable lyrics = KoreanPhonemizerUtil.Separate(prevNeighbour_.lyric); string[] prevLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - (string)lyrics[0], - (string)lyrics[1], + (string)lyrics[0], + (string)lyrics[1], (string)lyrics[2] }; @@ -311,27 +305,25 @@ public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, No string endSound = note.lyric; string prevMidVowel; - + if (prevLyric[1] == "ㅢ") { if (isUsing_i) { prevMidVowel = $"{MIDDLE_VOWELS["ㅣ"][0]}"; - } - else { + } else { prevMidVowel = $"{MIDDLE_VOWELS["ㅢ"][0]}"; } - } - else{ + } else { prevMidVowel = MIDDLE_VOWELS.ContainsKey(soundBeforeEndSound) ? MIDDLE_VOWELS[soundBeforeEndSound][2] : LAST_CONSONANTS[soundBeforeEndSound][0]; } - + if (FindInOto($"{prevMidVowel} {endSound}", note, true) == null) { if (FindInOto($"{prevMidVowel}{endSound}", note, true) == null) { return GenerateResult(FindInOto($"{endSound}", note)); } return GenerateResult(FindInOto($"{prevMidVowel}{endSound}", note, true)); } - return GenerateResult(FindInOto($"{prevMidVowel} {endSound}", note)); + return GenerateResult(FindInOto($"{prevMidVowel} {endSound}", note)); } } -} \ No newline at end of file +} diff --git a/OpenUtau.Plugin.Builtin/KoreanCVVCStandardPronunciationPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanCVVCStandardPronunciationPhonemizer.cs index c1f5e560a..97333b0d0 100644 --- a/OpenUtau.Plugin.Builtin/KoreanCVVCStandardPronunciationPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/KoreanCVVCStandardPronunciationPhonemizer.cs @@ -3,19 +3,19 @@ using System.Collections.Generic; using System.Linq; using OpenUtau.Api; -using OpenUtau.Core.Ustx; using OpenUtau.Core; +using OpenUtau.Core.Ustx; namespace OpenUtau.Plugin.Builtin { /// Phonemizer for 'KOR CVVC' /// [Phonemizer("Korean CVVC Phonemizer", "KO CVVC", "RYUUSEI & EX3", language: "KO")] public class KoreanCVVCPhonemizer : BaseKoreanPhonemizer { public override void SetSinger(USinger singer) { - if (this.singer == singer) {return;} + if (this.singer == singer) { return; } this.singer = singer; - if (this.singer == null) {return;} + if (this.singer == null) { return; } - if (this.singer.SingerType != USingerType.Classic){return;} + if (this.singer.SingerType != USingerType.Classic) { return; } } protected override bool additionalTest(string lyric) { @@ -49,7 +49,7 @@ protected override bool additionalTest(string lyric) { {"f", "f"}, {"rr", "rr"} }; - + static readonly Dictionary MIDDLE_VOWELS = new Dictionary(){ {"ㅏ", new string[3]{"a", "", "a"}}, {"ㅐ", new string[3]{"e", "", "e"}}, @@ -70,7 +70,7 @@ protected override bool additionalTest(string lyric) { {"ㅟ", new string[3]{"wi", "w", "i"}}, {"ㅠ", new string[3]{"yu", "y", "u"}}, {"ㅡ", new string[3]{"eu", "", "eu"}}, - {"ㅢ", new string[3]{"eui", "", "i"}}, + {"ㅢ", new string[3]{"eui", "", "i"}}, {"ㅣ", new string[3]{"i", "", "i"}}, {"null", new string[3]{"", "", ""}} // 뒤 글자가 없을 때를 대비 }; @@ -117,7 +117,7 @@ protected override bool additionalTest(string lyric) { {"ng", "ㅇ"}, {"n", "ㄴ"}, {"l", "ㄹ"}, - {"m", "ㅁ"}, + {"m", "ㅁ"}, }; static readonly string[][] EN_PHONEMES = { @@ -142,7 +142,7 @@ protected override bool additionalTest(string lyric) { private Result ConvertForCVVC(Note[] notes, string[] prevLyric, string[] thisLyric, string[] nextLyric, Note? nextNeighbour) { string thisMidVowelHead; string thisMidVowelTail; - + int totalDuration = notes.Sum(n => n.duration); Note note = notes[0]; @@ -157,23 +157,21 @@ private Result ConvertForCVVC(Note[] notes, string[] prevLyric, string[] thisLyr bool isItNeedsVV; bool isItNeedsVSv; // V + Semivowel, example) a y, a w bool isItNeedsEndSound; - + isItNeedsFrontCV = prevLyric[0] == "null" || prevLyric[1] == "null"; isItNeedsEndSound = (nextLyric[0] == "null" || nextLyric[1] == "null") && nextNeighbour == null; if (thisLyric.All(part => part == null)) { return GenerateResult(FindInOto(note.lyric, note)); - } - else { + } else { thisMidVowelHead = $"{MIDDLE_VOWELS[thisLyric[1]][1]}"; thisMidVowelTail = $"{MIDDLE_VOWELS[thisLyric[1]][2]}"; } - + string CV; - if (thisLyric[0] == "ㄹ" && prevLyric[2] == "ㄹ"){ // ㄹㄹ = l - CV = $"l{MIDDLE_VOWELS[thisLyric[1]][0]}"; - } - else { - CV = $"{FIRST_CONSONANTS[thisLyric[0]]}{MIDDLE_VOWELS[thisLyric[1]][0]}"; + if (thisLyric[0] == "ㄹ" && prevLyric[2] == "ㄹ") { // ㄹㄹ = l + CV = $"l{MIDDLE_VOWELS[thisLyric[1]][0]}"; + } else { + CV = $"{FIRST_CONSONANTS[thisLyric[0]]}{MIDDLE_VOWELS[thisLyric[1]][0]}"; } string frontCV; @@ -185,12 +183,12 @@ private Result ConvertForCVVC(Note[] notes, string[] prevLyric, string[] thisLyr isItNeedsVV = prevLyric[2] == " " && thisLyric[0] == "ㅇ"; if (prevLyric[2] == "ㅇ" && thisLyric[0] == "ㅇ") { // - isItNeedsVV = true; + isItNeedsVV = true; VV = $"{LAST_CONSONANTS["ㅇ"][0]} {thisMidVowelHead}{thisMidVowelTail}"; } isItNeedsVSv = thisLyric[2] == " " && nextLyric[0] == "ㅇ" && !PLAIN_VOWELS.Contains(nextLyric[1]) && FindInOto(VSv, note, true) != null; isItNeedsVC = thisLyric[2] == " " && nextLyric[0] != "ㅇ" && nextLyric[0] != "null"; - + frontCV = $"- {CV}"; if (FindInOto(frontCV, note, true) == null) { frontCV = $"-{CV}"; @@ -214,47 +212,47 @@ private Result ConvertForCVVC(Note[] notes, string[] prevLyric, string[] thisLyr isItNeedsVSv = false; } } - + if (thisLyric[2] == " " && isItNeedsVC) { // no batchim, needs VC - if (isItNeedsFrontCV){ + if (isItNeedsFrontCV) { return GenerateResult(FindInOto(frontCV, note), FindInOto(VC, note), totalDuration, 120, 3); } return GenerateResult(FindInOto(CV, note), FindInOto(VC, note), totalDuration, 120, 3); } if (thisLyric[2] == " " && isItNeedsVSv) { // no batchim, needs VSv - if (isItNeedsFrontCV){ + if (isItNeedsFrontCV) { return GenerateResult(FindInOto(frontCV, note), FindInOto(VSv, note), totalDuration, 120, 3); } return GenerateResult(FindInOto(CV, note), FindInOto(VSv, note), totalDuration, 120, 3); } if (thisLyric[2] == " ") { // no batchim, doesn't need VC - if (isItNeedsFrontCV){ - return isItNeedsEndSound ? + if (isItNeedsFrontCV) { + return isItNeedsEndSound ? GenerateResult(FindInOto(frontCV, note), FindInOto(endSound, note), totalDuration, 8) : GenerateResult(FindInOto(frontCV, note)); } - return isItNeedsEndSound ? + return isItNeedsEndSound ? GenerateResult(FindInOto(CV, note), FindInOto(endSound, note), totalDuration, 8) : GenerateResult(FindInOto(CV, note)); } - + batchim = $"{thisMidVowelTail} {LAST_CONSONANTS[thisLyric[2]][0]}"; - + if (FindInOto(batchim, note, true) == null) { batchim = batchim.ToLower(); // try to use lower-cased batchim } if (nextLyric[0] == "null" || nextLyric[0] == "ㅇ") { // batchim, doesn't need CC - if (isItNeedsFrontCV ){ + if (isItNeedsFrontCV) { return GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 8); } return GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), totalDuration, 8); } CC = $"{LAST_CONSONANTS[thisLyric[2]][0]} {FIRST_CONSONANTS[nextLyric[0]]}{MIDDLE_VOWELS[nextLyric[1]][1]}"; - + if (FindInOto(CC, note, true) == null) { if (CC.EndsWith("w") || CC.EndsWith("y")) { CC = CC.Substring(0, CC.Length - 1); @@ -262,27 +260,26 @@ private Result ConvertForCVVC(Note[] notes, string[] prevLyric, string[] thisLyr } if (FindInOto(CC, note, true) != null) { // batchim + CC - if (isItNeedsFrontCV){ + if (isItNeedsFrontCV) { return GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), FindInOto(CC, note), totalDuration, 120, 2, 3); } return GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), FindInOto(CC, note), totalDuration, 120, 2, 3); - } - else { // batchim + no CC - if (isItNeedsFrontCV){ + } else { // batchim + no CC + if (isItNeedsFrontCV) { GenerateResult(FindInOto(frontCV, note), FindInOto(batchim, note), totalDuration, 120, 5); } return GenerateResult(FindInOto(CV, note), FindInOto(batchim, note), totalDuration, 120, 5); } - + } - private string? FindInOto(String phoneme, Note note, bool nullIfNotFound=false){ + private string? FindInOto(String phoneme, Note note, bool nullIfNotFound = false) { return BaseKoreanPhonemizer.FindInOto(singer, phoneme, note, nullIfNotFound); } private bool IsENPhoneme(String phoneme) { bool isENPhoneme = false; - if (phoneme.StartsWith("rr") || phoneme.StartsWith("th") || phoneme.StartsWith("f") || phoneme.StartsWith("v")){ + if (phoneme.StartsWith("rr") || phoneme.StartsWith("th") || phoneme.StartsWith("f") || phoneme.StartsWith("v")) { isENPhoneme = true; } return isENPhoneme; @@ -291,22 +288,22 @@ private bool IsENPhoneme(String phoneme) { public override Result ConvertPhonemes(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) { Note note = notes[0]; bool prevIsEN = false; - bool currIsEN = false; + bool currIsEN = false; bool nextIsEN = false; - string[] prevENPhones = new string[3]{"", "", ""}; - string[] currENPhones = new string[3]{"", "", ""}; - string[] nextENPhones = new string[3]{"", "", ""}; - bool exitLoop = false; + string[] prevENPhones = new string[3] { "", "", "" }; + string[] currENPhones = new string[3] { "", "", "" }; + string[] nextENPhones = new string[3] { "", "", "" }; + bool exitLoop = false; if (IsENPhoneme(note.lyric)) { foreach (string[] _ in EN_PHONEMES) { if (exitLoop) { exitLoop = false; break; - } - foreach (string p in _){ + } + foreach (string p in _) { string grapheme = p.Split("=")[0]; - + if (!note.lyric.StartsWith(grapheme)) { continue; } @@ -316,8 +313,7 @@ public override Result ConvertPhonemes(Note[] notes, Note? prev, Note? next, Not if (note.lyric.Length != grapheme.Length) { currENPhones[2] = BATCHIM_ROMAJ[note.lyric.Substring(grapheme.Length)]; - } - else { + } else { currENPhones[2] = " "; } @@ -327,15 +323,15 @@ public override Result ConvertPhonemes(Note[] notes, Note? prev, Note? next, Not } } } - if (prev != null && IsENPhoneme(((Note)prev).lyric)){ + if (prev != null && IsENPhoneme(((Note)prev).lyric)) { foreach (string[] _ in EN_PHONEMES) { if (exitLoop) { exitLoop = false; break; - } - foreach (string p in _){ + } + foreach (string p in _) { string grapheme = p.Split("=")[0]; - + if (!((Note)prev).lyric.StartsWith(grapheme)) { continue; } @@ -345,26 +341,25 @@ public override Result ConvertPhonemes(Note[] notes, Note? prev, Note? next, Not if (((Note)prev).lyric.Length != grapheme.Length) { prevENPhones[2] = BATCHIM_ROMAJ[((Note)prev).lyric.Substring(grapheme.Length)]; - } - else { + } else { prevENPhones[2] = " "; } - + prevIsEN = true; exitLoop = true; break; } } } - if (next != null && IsENPhoneme(((Note)next).lyric)){ + if (next != null && IsENPhoneme(((Note)next).lyric)) { foreach (string[] _ in EN_PHONEMES) { if (exitLoop) { exitLoop = false; break; - } - foreach (string p in _){ + } + foreach (string p in _) { string grapheme = p.Split("=")[0]; - + if (!((Note)next).lyric.StartsWith(grapheme)) { continue; } @@ -374,8 +369,7 @@ public override Result ConvertPhonemes(Note[] notes, Note? prev, Note? next, Not if (((Note)next).lyric.Length != grapheme.Length) { prevENPhones[2] = BATCHIM_ROMAJ[((Note)next).lyric.Substring(grapheme.Length)]; - } - else { + } else { prevENPhones[2] = " "; } nextIsEN = true; @@ -384,19 +378,18 @@ public override Result ConvertPhonemes(Note[] notes, Note? prev, Note? next, Not } } } - - if (!KoreanPhonemizerUtil.IsHangeul(note.lyric) && !prevIsEN && !currIsEN && !nextIsEN){ + + if (!KoreanPhonemizerUtil.IsHangeul(note.lyric) && !prevIsEN && !currIsEN && !nextIsEN) { return GenerateResult(FindInOto(notes[0].lyric, notes[0])); } Hashtable lyrics; - if (KoreanPhonemizerUtil.IsHangeul(note.lyric)){ + if (KoreanPhonemizerUtil.IsHangeul(note.lyric)) { lyrics = KoreanPhonemizerUtil.Variate(prevNeighbour, note, nextNeighbour); - } - else { + } else { // handle current phoneme which is not hangeul, but have to supported by phonemizer - tha, thi, thu, fyeo... etc. - lyrics = new Hashtable() { [0] = "null", [1] = "null", [2] = "null", [3] = "null", [4] = "null", [5] = "null", [6] = "null", [7] = "null", [8] = "null",};// init into all null - + lyrics = new Hashtable() { [0] = "null", [1] = "null", [2] = "null", [3] = "null", [4] = "null", [5] = "null", [6] = "null", [7] = "null", [8] = "null", };// init into all null + if (prevNeighbour != null && !IsENPhoneme(((Note)prevNeighbour).lyric)) { Hashtable t = KoreanPhonemizerUtil.Variate(null, (Note)prevNeighbour, null); lyrics[0] = (string)t[3]; @@ -412,22 +405,22 @@ public override Result ConvertPhonemes(Note[] notes, Note? prev, Note? next, Not } string[] prevLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - prevIsEN ? prevENPhones[0] : (string)lyrics[0], - prevIsEN ? prevENPhones[1]:(string)lyrics[1], + prevIsEN ? prevENPhones[0] : (string)lyrics[0], + prevIsEN ? prevENPhones[1]:(string)lyrics[1], prevIsEN ? prevENPhones[2]:(string)lyrics[2] }; string[] thisLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - currIsEN ? currENPhones[0] : (string)lyrics[3], - currIsEN ? currENPhones[1] : (string)lyrics[4], + currIsEN ? currENPhones[0] : (string)lyrics[3], + currIsEN ? currENPhones[1] : (string)lyrics[4], currIsEN? currENPhones[2] : (string)lyrics[5] }; string[] nextLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - nextIsEN ? nextENPhones[0] : (string)lyrics[6], - nextIsEN ? nextENPhones[1] : (string)lyrics[7], + nextIsEN ? nextENPhones[0] : (string)lyrics[6], + nextIsEN ? nextENPhones[1] : (string)lyrics[7], nextIsEN ? nextENPhones[2] : (string)lyrics[8] }; - if (thisLyric[0] == "null") { + if (thisLyric[0] == "null") { return GenerateResult(FindInOto(notes[0].lyric, notes[0])); } if (prevLyric[2] != " " && prevIsEN && thisLyric[0] == "ㅇ") { // perform yeoneum when 'EN Phoneme with batchim' came @@ -436,7 +429,7 @@ public override Result ConvertPhonemes(Note[] notes, Note? prev, Note? next, Not } return ConvertForCVVC(notes, prevLyric, thisLyric, nextLyric, nextNeighbour); } - + public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) { Note note = notes[0]; @@ -448,8 +441,8 @@ public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, No Hashtable lyrics = KoreanPhonemizerUtil.Separate(prevNeighbour_.lyric); string[] prevLyric = new string[]{ // "ㄴ", "ㅑ", "ㅇ" - (string)lyrics[0], - (string)lyrics[1], + (string)lyrics[0], + (string)lyrics[1], (string)lyrics[2] }; @@ -458,14 +451,14 @@ public override Result GenerateEndSound(Note[] notes, Note? prev, Note? next, No string prevMidVowel; prevMidVowel = MIDDLE_VOWELS.ContainsKey(soundBeforeEndSound) ? MIDDLE_VOWELS[soundBeforeEndSound][2] : LAST_CONSONANTS[soundBeforeEndSound][0]; - + if (FindInOto($"{prevMidVowel} {endSound}", note, true) == null) { if (FindInOto($"{prevMidVowel}{endSound}", note, true) == null) { return GenerateResult(FindInOto($"{endSound}", note)); } return GenerateResult(FindInOto($"{prevMidVowel}{endSound}", note, true)); } - return GenerateResult(FindInOto($"{prevMidVowel} {endSound}", note)); + return GenerateResult(FindInOto($"{prevMidVowel} {endSound}", note)); } } -} \ No newline at end of file +} diff --git a/OpenUtau.Plugin.Builtin/KoreanVCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/KoreanVCVPhonemizer.cs index 541d5e2a1..450c877ae 100644 --- a/OpenUtau.Plugin.Builtin/KoreanVCVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/KoreanVCVPhonemizer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -6,361 +6,326 @@ using OpenUtau.Core.Ustx; using static OpenUtau.Core.KoreanPhonemizerUtil; -namespace OpenUtau.Plugin.Builtin -{ - [Phonemizer("Korean VCV Phonemizer", "KO VCV", "ldc", language: "KO")] - - public class KoreanVCVPhonemizer : BaseKoreanPhonemizer - { - /// - /// Initial jamo as ordered in Unicode - /// - static readonly string[] initials = { "g", "gg", "n", "d", "dd", "r", "m", "b", "bb", "s", "ss", string.Empty, "j", "jj", "ch", "k", "t", "p", "h" }; - // ㄱ ㄲ ㄴ ㄷ ㄸ ㄹ ㅁ ㅂ ㅃ ㅅ ㅆ ㅇ ㅈ ㅉ ㅊ ㅋ ㅌ ㅍ ㅎ - - /// - /// Medial jamo as ordered in Unicode - /// - static readonly string[] medials = { "a", "e", "ya", "ye", "eo", "e", "yeo", "ye", "o", "wa", "we", "we", "yo", "u", "weo", "we", "wi", "yu", "eu", "eui", "i" }; - // ㅏ ㅐ ㅑ ㅒ ㅓ ㅔ ㅕ ㅖ ㅗ ㅘ ㅙ ㅚ ㅛ ㅜ ㅝ ㅞ ㅟ ㅠ ㅡ ㅢ ㅣ - - /// - /// Final jamo as ordered in Unicode + vowel end breath sounds (inhale and exhale) - /// - static readonly string[] finals = { string.Empty, "k", "k", "k", "n", "n", "n", "t", "l", "l", "l", "l", "l", "l", "l", "l", "m", "p", "p", "t", "t", "ng", "t", "t", "k", "t", "p", "t", string.Empty, string.Empty, string.Empty, }; - // - ㄱ ㄲ ㄳ ㄴ ㄵ ㄶ ㄷ ㄹ ㄺ ㄻ ㄼ ㄽ ㄾ ㄿ ㅀ ㅁ ㅂ ㅄ ㅅ ㅆ ㅇ ㅈ ㅊ ㅋ ㅌ ㅍ ㅎ H B bre - - /// - /// Sonorant batchim (i.e., extendable batchim sounds) - /// - static readonly string[] sonorants = { "n", "m", "ng", "l" }; - - /// - /// Extra English-based sounds for phonetic hint input + alternate romanizations for tense plosives (ㄲ, ㄸ, ㅃ) - /// - static readonly string[] extras = { "f", "v", "th", "dh", "z", "rr", "kk", "pp", "tt" }; - - /// - /// Apply Korean sandhi rules to Hangeul lyrics. - /// - public override void SetUp(Note[][] groups, UProject project, UTrack track) { - // variate lyrics - RomanizeNotes(groups, false); - } - - /// - /// Gets the romanized initial, medial, and final components of the passed Hangul syllable. - /// - /// A Hangul syllable. - /// An array containing the initial, medial, and final sounds of the syllable. - public string[] GetIMF(string syllable) - { - byte[] bytes = Encoding.Unicode.GetBytes(syllable); - int numval = Convert.ToInt32(bytes[0]) + Convert.ToInt32(bytes[1]) * (16 * 16); - numval -= 44032; - int i = numval / 588; - numval -= i * 588; - int m = numval / 28; - numval -= m * 28; - int f = numval; - - string[] ret = { initials[i], medials[m], finals[f] }; - - return ret; - } - - /// - /// Separates the initial, medial, and final components of the passed phonetic hint. - /// - /// A phonetic hint. - /// An array containing the initial, medial, and final sounds of the phonetic hint. - public string[] GetIMFFromHint(string hint) - { - string[] hintSplit = hint.Split(' '); - - string i = Array.IndexOf(initials.Concat(extras).ToArray(), hintSplit[0]) > -1 ? hintSplit[0] : string.Empty; - string m = string.IsNullOrEmpty(i) ? hintSplit[0] : hintSplit[1]; - string f = (hintSplit.Length > 2 || (hintSplit.Length == 2 && string.IsNullOrEmpty(i))) ? hintSplit[^1] : string.Empty; - - if (i == "kk" || i == "pp" || i == "tt") i = i.Replace('k', 'g').Replace('p', 'b').Replace('t', 'd'); - - if (m == "oe" || m == "oi") m = "we"; - if (m == "ui") m = "eui"; - if (m == "ae" || m == "wae" || m == "yae") m = m.Replace("ae", "e"); - - string[] ret = { i, m, f }; - - return ret; - } - - /// - /// Gets the last sound of an alias. - /// - /// The alias to get the last sound of. - /// The last sound of the alias - public string GetLastSoundOfAlias(string lyric) - { - string lastSound = lyric.Split(' ')[^1]; - Regex symbolRemove = new Regex(@"\W"); - MatchCollection symbolMatches = symbolRemove.Matches(lastSound); - - foreach (Match symbolMatch in symbolMatches) - { - lastSound = lastSound.Replace(symbolMatch.Value, string.Empty); - } - - if (Array.IndexOf(finals, lastSound) == -1) - { - foreach (string i in initials) - { - if (!string.IsNullOrEmpty(i)) lastSound = lastSound.Replace(i, string.Empty); - } - } - - return lastSound; - } - - private USinger singer; - - // Store singer - public override void SetSinger(USinger singer) => this.singer = singer; - - public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) - { - Note note = notes[0]; - string color = string.Empty; - int shift = 0; - int? alt; - int totalDuration = notes.Sum(n => n.duration); - - string color1 = string.Empty; - int shift1 = 0; - int? alt1; - - PhonemeAttributes attr = note.phonemeAttributes.FirstOrDefault(a => a.index == 0); - color = attr.voiceColor; - shift = attr.toneShift; - alt = attr.alternate; - - PhonemeAttributes attr1 = note.phonemeAttributes.FirstOrDefault(a => a.index == 1); - color1 = attr1.voiceColor; - shift1 = attr1.toneShift; - alt1 = attr1.alternate; - - string[] currIMF; - string currPhoneme; - string[] prevIMF; - - var romaji2Korean = ConvertRomajiNoteToHangeul(notes, prevNeighbour, nextNeighbour); - if (romaji2Korean != null) { - notes = romaji2Korean.KoreanLyricNotes; - - note = notes[0]; - } - - // Check if notes are romaji - var currRomaji = IsKoreanRomaji(note.lyric); - var prevRomaji = IsKoreanRomaji(prevNeighbour?.lyric); - - // Improve romaji lyric parsing, to mix with hangeul, vowel endings, and phonetic hint - var currRomLyric = TryParseKoreanRomaji(note.lyric); - var prevRomLyric = TryParseKoreanRomaji(prevNeighbour?.lyric); - - // Check if lyric is R, - or an end breath and return appropriate Result; otherwise, move to next steps - if (note.lyric == "R" || note.lyric == "R2" || note.lyric == "-" || note.lyric == "H" || note.lyric == "B" || note.lyric == "bre") - { - currPhoneme = note.lyric; - - if (prevNeighbour == null) - { - return new Result - { - phonemes = new Phoneme[] { - new Phoneme { phoneme = currPhoneme } - } - }; - } - else - { - if (singer.TryGetMappedOto(prevNeighbour?.lyric, note.tone, color, out _)) { - string lastSound = GetLastSoundOfAlias(prevNeighbour?.lyric); - currPhoneme = $"{(!singer.TryGetMappedOto($"{lastSound} {currPhoneme}", note.tone, color, out _) ? lastSound.ToUpper() : lastSound)} {currPhoneme}"; - } - - else { - if (string.IsNullOrEmpty(prevNeighbour?.phoneticHint)) { - byte[] bytes = Encoding.Unicode.GetBytes($"{prevNeighbour?.lyric[0]}"); - int numval = Convert.ToInt32(bytes[0]) + Convert.ToInt32(bytes[1]) * (16 * 16); - if (prevNeighbour?.lyric.Length == 1 && numval >= 44032 && numval <= 55215) prevIMF = GetIMF(prevNeighbour?.lyric); - else if (prevRomaji && prevRomLyric != null) { - prevIMF = GetIMF(prevRomLyric); - } else - return new Result { - phonemes = new Phoneme[] { - new Phoneme { phoneme = currPhoneme } - } - }; - } else prevIMF = GetIMFFromHint(prevNeighbour?.phoneticHint); - - if (string.IsNullOrEmpty(prevIMF[2])) currPhoneme = $"{((prevIMF[1][0] == 'w' || prevIMF[1][0] == 'y' || prevIMF[1] == "oi") ? prevIMF[1].Remove(0, 1) : ((prevIMF[1] == "eui" || prevIMF[1] == "ui") ? "i" : prevIMF[1]))} {currPhoneme}"; - else currPhoneme = $"{(!singer.TryGetMappedOto($"{prevIMF[2]} {currPhoneme}", note.tone, color, out _) ? prevIMF[2].ToUpper() : prevIMF[2])} {currPhoneme}"; - } - - // Map alias (apply shift + color) - if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) { - currPhoneme = otoAlt.Alias; - } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) { - currPhoneme = oto.Alias; - } - - return new Result { - phonemes = new Phoneme[] { - new Phoneme { phoneme = currPhoneme } - } - }; - } - } - - // Get IMF of current note if valid, otherwise return the lyric as is - if (string.IsNullOrEmpty(note.phoneticHint)) { - byte[] bytes = Encoding.Unicode.GetBytes($"{note.lyric[0]}"); - int numval = Convert.ToInt32(bytes[0]) + Convert.ToInt32(bytes[1]) * (16 * 16); - if (note.lyric.Length == 1 && numval >= 44032 && numval <= 55215) currIMF = GetIMF(note.lyric); - else if (currRomaji && currRomLyric != null) { - currIMF = GetIMF(currRomLyric); - } else - return new Result { - phonemes = new Phoneme[] { - new Phoneme { phoneme = note.lyric } - } - }; - } else currIMF = GetIMFFromHint(note.phoneticHint); - - // Convert current note to phoneme - currPhoneme = $"{currIMF[0]}{currIMF[1]}"; - - if (currIMF[0] == "gg" || currIMF[0] == "dd" || currIMF[0] == "bb") - { - if (!singer.TryGetMappedOto($"- {currIMF[0]}{currIMF[1]}", note.tone + shift, color, out _)) currPhoneme = $"{currIMF[0].Replace('g', 'k').Replace('d', 't').Replace('b', 'p')}{currIMF[1]}"; - } - if (currIMF[1] == "eui") - { - if (!singer.TryGetMappedOto("- eui", note.tone + shift, color, out _)) currPhoneme = $"{currIMF[0]}ui"; - } - - // Adjust current phoneme based on previous neighbor - if (prevNeighbour != null && prevNeighbour?.lyric != "bre" && singer.TryGetMappedOto(prevNeighbour?.lyric, note.tone + shift, color, out _)) currPhoneme = $"{GetLastSoundOfAlias(prevNeighbour?.lyric)} {currPhoneme}"; - else - { - if (prevNeighbour == null || prevNeighbour?.lyric == "R" || prevNeighbour?.lyric == "R2" || prevNeighbour?.lyric == "-" || prevNeighbour?.lyric == "H" || prevNeighbour?.lyric == "B" || prevNeighbour?.lyric == "bre") currPhoneme = $"- {currPhoneme}"; - else - { - if (string.IsNullOrEmpty(prevNeighbour?.phoneticHint)) - { - byte[] bytes = Encoding.Unicode.GetBytes($"{prevNeighbour?.lyric[0]}"); - int numval = Convert.ToInt32(bytes[0]) + Convert.ToInt32(bytes[1]) * (16 * 16); - if (prevNeighbour?.lyric.Length == 1 && numval >= 44032 && numval <= 55215) prevIMF = GetIMF(prevNeighbour?.lyric); - else if (prevRomaji && prevRomLyric != null) { - prevIMF = GetIMF(prevRomLyric); - } else return new Result { - phonemes = new Phoneme[] { - new Phoneme { phoneme = note.lyric } - } - }; - } - else prevIMF = GetIMFFromHint(prevNeighbour?.phoneticHint); - - string prevConnect; - - if (!string.IsNullOrEmpty(prevIMF[2])) - { - if (Array.IndexOf(sonorants, prevIMF[2]) > -1) - { - if (singer.TryGetMappedOto($"{prevIMF[2]} {currPhoneme}", note.tone + shift, color, out _)) prevConnect = prevIMF[2]; - else prevConnect = prevIMF[2].ToUpper(); - } - else prevConnect = "-"; - } - else - { - if (prevIMF[1][0] == 'w' || prevIMF[1][0] == 'y' || prevIMF[1] == "oe") prevConnect = prevIMF[1].Remove(0, 1); - else if (prevIMF[1] == "eui") prevConnect = "i"; - else prevConnect = prevIMF[1]; - } - - currPhoneme = $"{prevConnect} {currPhoneme}"; - } - } - - // Return Result now if note has no batchim - if (string.IsNullOrEmpty(currIMF[2])) - { - // Map alias (apply shift + color) - if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) { - currPhoneme = otoAlt.Alias; - } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) { - currPhoneme = oto.Alias; - } - - return new Result - { - phonemes = new Phoneme[] { - new Phoneme { phoneme = currPhoneme } - } - }; - } - - // Adjust Result if note has batchim - else - { - if (currIMF[1] == "eui") { +namespace OpenUtau.Plugin.Builtin { + [Phonemizer("Korean VCV Phonemizer", "KO VCV", "ldc", language: "KO")] + + public class KoreanVCVPhonemizer : BaseKoreanPhonemizer { + /// + /// Initial jamo as ordered in Unicode + /// + static readonly string[] initials = { "g", "gg", "n", "d", "dd", "r", "m", "b", "bb", "s", "ss", string.Empty, "j", "jj", "ch", "k", "t", "p", "h" }; + // ㄱ ㄲ ㄴ ㄷ ㄸ ㄹ ㅁ ㅂ ㅃ ㅅ ㅆ ㅇ ㅈ ㅉ ㅊ ㅋ ㅌ ㅍ ㅎ + + /// + /// Medial jamo as ordered in Unicode + /// + static readonly string[] medials = { "a", "e", "ya", "ye", "eo", "e", "yeo", "ye", "o", "wa", "we", "we", "yo", "u", "weo", "we", "wi", "yu", "eu", "eui", "i" }; + // ㅏ ㅐ ㅑ ㅒ ㅓ ㅔ ㅕ ㅖ ㅗ ㅘ ㅙ ㅚ ㅛ ㅜ ㅝ ㅞ ㅟ ㅠ ㅡ ㅢ ㅣ + + /// + /// Final jamo as ordered in Unicode + vowel end breath sounds (inhale and exhale) + /// + static readonly string[] finals = { string.Empty, "k", "k", "k", "n", "n", "n", "t", "l", "l", "l", "l", "l", "l", "l", "l", "m", "p", "p", "t", "t", "ng", "t", "t", "k", "t", "p", "t", string.Empty, string.Empty, string.Empty, }; + // - ㄱ ㄲ ㄳ ㄴ ㄵ ㄶ ㄷ ㄹ ㄺ ㄻ ㄼ ㄽ ㄾ ㄿ ㅀ ㅁ ㅂ ㅄ ㅅ ㅆ ㅇ ㅈ ㅊ ㅋ ㅌ ㅍ ㅎ H B bre + + /// + /// Sonorant batchim (i.e., extendable batchim sounds) + /// + static readonly string[] sonorants = { "n", "m", "ng", "l" }; + + /// + /// Extra English-based sounds for phonetic hint input + alternate romanizations for tense plosives (ㄲ, ㄸ, ㅃ) + /// + static readonly string[] extras = { "f", "v", "th", "dh", "z", "rr", "kk", "pp", "tt" }; + + /// + /// Apply Korean sandhi rules to Hangeul lyrics. + /// + public override void SetUp(Note[][] groups, UProject project, UTrack track) { + // variate lyrics + RomanizeNotes(groups, false); + } + + /// + /// Gets the romanized initial, medial, and final components of the passed Hangul syllable. + /// + /// A Hangul syllable. + /// An array containing the initial, medial, and final sounds of the syllable. + public string[] GetIMF(string syllable) { + byte[] bytes = Encoding.Unicode.GetBytes(syllable); + int numval = Convert.ToInt32(bytes[0]) + Convert.ToInt32(bytes[1]) * (16 * 16); + numval -= 44032; + int i = numval / 588; + numval -= i * 588; + int m = numval / 28; + numval -= m * 28; + int f = numval; + + string[] ret = { initials[i], medials[m], finals[f] }; + + return ret; + } + + /// + /// Separates the initial, medial, and final components of the passed phonetic hint. + /// + /// A phonetic hint. + /// An array containing the initial, medial, and final sounds of the phonetic hint. + public string[] GetIMFFromHint(string hint) { + string[] hintSplit = hint.Split(' '); + + string i = Array.IndexOf(initials.Concat(extras).ToArray(), hintSplit[0]) > -1 ? hintSplit[0] : string.Empty; + string m = string.IsNullOrEmpty(i) ? hintSplit[0] : hintSplit[1]; + string f = (hintSplit.Length > 2 || (hintSplit.Length == 2 && string.IsNullOrEmpty(i))) ? hintSplit[^1] : string.Empty; + + if (i == "kk" || i == "pp" || i == "tt") i = i.Replace('k', 'g').Replace('p', 'b').Replace('t', 'd'); + + if (m == "oe" || m == "oi") m = "we"; + if (m == "ui") m = "eui"; + if (m == "ae" || m == "wae" || m == "yae") m = m.Replace("ae", "e"); + + string[] ret = { i, m, f }; + + return ret; + } + + /// + /// Gets the last sound of an alias. + /// + /// The alias to get the last sound of. + /// The last sound of the alias + public string GetLastSoundOfAlias(string lyric) { + string lastSound = lyric.Split(' ')[^1]; + Regex symbolRemove = new Regex(@"\W"); + MatchCollection symbolMatches = symbolRemove.Matches(lastSound); + + foreach (Match symbolMatch in symbolMatches) { + lastSound = lastSound.Replace(symbolMatch.Value, string.Empty); + } + + if (Array.IndexOf(finals, lastSound) == -1) { + foreach (string i in initials) { + if (!string.IsNullOrEmpty(i)) lastSound = lastSound.Replace(i, string.Empty); + } + } + + return lastSound; + } + + private USinger singer; + + // Store singer + public override void SetSinger(USinger singer) => this.singer = singer; + + public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) { + Note note = notes[0]; + string color = string.Empty; + int shift = 0; + int? alt; + int totalDuration = notes.Sum(n => n.duration); + + string color1 = string.Empty; + int shift1 = 0; + int? alt1; + + PhonemeAttributes attr = note.phonemeAttributes.FirstOrDefault(a => a.index == 0); + color = attr.voiceColor; + shift = attr.toneShift; + alt = attr.alternate; + + PhonemeAttributes attr1 = note.phonemeAttributes.FirstOrDefault(a => a.index == 1); + color1 = attr1.voiceColor; + shift1 = attr1.toneShift; + alt1 = attr1.alternate; + + string[] currIMF; + string currPhoneme; + string[] prevIMF; + + var romaji2Korean = ConvertRomajiNoteToHangeul(notes, prevNeighbour, nextNeighbour); + if (romaji2Korean != null) { + notes = romaji2Korean.KoreanLyricNotes; + + note = notes[0]; + } + + // Check if notes are romaji + var currRomaji = IsKoreanRomaji(note.lyric); + var prevRomaji = IsKoreanRomaji(prevNeighbour?.lyric); + + // Improve romaji lyric parsing, to mix with hangeul, vowel endings, and phonetic hint + var currRomLyric = TryParseKoreanRomaji(note.lyric); + var prevRomLyric = TryParseKoreanRomaji(prevNeighbour?.lyric); + + // Check if lyric is R, - or an end breath and return appropriate Result; otherwise, move to next steps + if (note.lyric == "R" || note.lyric == "R2" || note.lyric == "-" || note.lyric == "H" || note.lyric == "B" || note.lyric == "bre") { + currPhoneme = note.lyric; + + if (prevNeighbour == null) { + return new Result { + phonemes = new Phoneme[] { + new Phoneme { phoneme = currPhoneme } + } + }; + } else { + if (singer.TryGetMappedOto(prevNeighbour?.lyric, note.tone, color, out _)) { + string lastSound = GetLastSoundOfAlias(prevNeighbour?.lyric); + currPhoneme = $"{(!singer.TryGetMappedOto($"{lastSound} {currPhoneme}", note.tone, color, out _) ? lastSound.ToUpper() : lastSound)} {currPhoneme}"; + } else { + if (string.IsNullOrEmpty(prevNeighbour?.phoneticHint)) { + byte[] bytes = Encoding.Unicode.GetBytes($"{prevNeighbour?.lyric[0]}"); + int numval = Convert.ToInt32(bytes[0]) + Convert.ToInt32(bytes[1]) * (16 * 16); + if (prevNeighbour?.lyric.Length == 1 && numval >= 44032 && numval <= 55215) prevIMF = GetIMF(prevNeighbour?.lyric); + else if (prevRomaji && prevRomLyric != null) { + prevIMF = GetIMF(prevRomLyric); + } else + return new Result { + phonemes = new Phoneme[] { + new Phoneme { phoneme = currPhoneme } + } + }; + } else prevIMF = GetIMFFromHint(prevNeighbour?.phoneticHint); + + if (string.IsNullOrEmpty(prevIMF[2])) currPhoneme = $"{((prevIMF[1][0] == 'w' || prevIMF[1][0] == 'y' || prevIMF[1] == "oi") ? prevIMF[1].Remove(0, 1) : ((prevIMF[1] == "eui" || prevIMF[1] == "ui") ? "i" : prevIMF[1]))} {currPhoneme}"; + else currPhoneme = $"{(!singer.TryGetMappedOto($"{prevIMF[2]} {currPhoneme}", note.tone, color, out _) ? prevIMF[2].ToUpper() : prevIMF[2])} {currPhoneme}"; + } + + // Map alias (apply shift + color) + if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) { + currPhoneme = otoAlt.Alias; + } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) { + currPhoneme = oto.Alias; + } + + return new Result { + phonemes = new Phoneme[] { + new Phoneme { phoneme = currPhoneme } + } + }; + } + } + + // Get IMF of current note if valid, otherwise return the lyric as is + if (string.IsNullOrEmpty(note.phoneticHint)) { + byte[] bytes = Encoding.Unicode.GetBytes($"{note.lyric[0]}"); + int numval = Convert.ToInt32(bytes[0]) + Convert.ToInt32(bytes[1]) * (16 * 16); + if (note.lyric.Length == 1 && numval >= 44032 && numval <= 55215) currIMF = GetIMF(note.lyric); + else if (currRomaji && currRomLyric != null) { + currIMF = GetIMF(currRomLyric); + } else + return new Result { + phonemes = new Phoneme[] { + new Phoneme { phoneme = note.lyric } + } + }; + } else currIMF = GetIMFFromHint(note.phoneticHint); + + // Convert current note to phoneme + currPhoneme = $"{currIMF[0]}{currIMF[1]}"; + + if (currIMF[0] == "gg" || currIMF[0] == "dd" || currIMF[0] == "bb") { + if (!singer.TryGetMappedOto($"- {currIMF[0]}{currIMF[1]}", note.tone + shift, color, out _)) currPhoneme = $"{currIMF[0].Replace('g', 'k').Replace('d', 't').Replace('b', 'p')}{currIMF[1]}"; + } + if (currIMF[1] == "eui") { + if (!singer.TryGetMappedOto("- eui", note.tone + shift, color, out _)) currPhoneme = $"{currIMF[0]}ui"; + } + + // Adjust current phoneme based on previous neighbor + if (prevNeighbour != null && prevNeighbour?.lyric != "bre" && singer.TryGetMappedOto(prevNeighbour?.lyric, note.tone + shift, color, out _)) currPhoneme = $"{GetLastSoundOfAlias(prevNeighbour?.lyric)} {currPhoneme}"; + else { + if (prevNeighbour == null || prevNeighbour?.lyric == "R" || prevNeighbour?.lyric == "R2" || prevNeighbour?.lyric == "-" || prevNeighbour?.lyric == "H" || prevNeighbour?.lyric == "B" || prevNeighbour?.lyric == "bre") currPhoneme = $"- {currPhoneme}"; + else { + if (string.IsNullOrEmpty(prevNeighbour?.phoneticHint)) { + byte[] bytes = Encoding.Unicode.GetBytes($"{prevNeighbour?.lyric[0]}"); + int numval = Convert.ToInt32(bytes[0]) + Convert.ToInt32(bytes[1]) * (16 * 16); + if (prevNeighbour?.lyric.Length == 1 && numval >= 44032 && numval <= 55215) prevIMF = GetIMF(prevNeighbour?.lyric); + else if (prevRomaji && prevRomLyric != null) { + prevIMF = GetIMF(prevRomLyric); + } else return new Result { + phonemes = new Phoneme[] { + new Phoneme { phoneme = note.lyric } + } + }; + } else prevIMF = GetIMFFromHint(prevNeighbour?.phoneticHint); + + string prevConnect; + + if (!string.IsNullOrEmpty(prevIMF[2])) { + if (Array.IndexOf(sonorants, prevIMF[2]) > -1) { + if (singer.TryGetMappedOto($"{prevIMF[2]} {currPhoneme}", note.tone + shift, color, out _)) prevConnect = prevIMF[2]; + else prevConnect = prevIMF[2].ToUpper(); + } else prevConnect = "-"; + } else { + if (prevIMF[1][0] == 'w' || prevIMF[1][0] == 'y' || prevIMF[1] == "oe") prevConnect = prevIMF[1].Remove(0, 1); + else if (prevIMF[1] == "eui") prevConnect = "i"; + else prevConnect = prevIMF[1]; + } + + currPhoneme = $"{prevConnect} {currPhoneme}"; + } + } + + // Return Result now if note has no batchim + if (string.IsNullOrEmpty(currIMF[2])) { + // Map alias (apply shift + color) + if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) { + currPhoneme = otoAlt.Alias; + } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) { + currPhoneme = oto.Alias; + } + + return new Result { + phonemes = new Phoneme[] { + new Phoneme { phoneme = currPhoneme } + } + }; + } + + // Adjust Result if note has batchim + else { + if (currIMF[1] == "eui") { currIMF[1] = "ui"; } - + string secondPhoneme = (currIMF[1][0] == 'w' || currIMF[1][0] == 'y' || currIMF[1] == "oe" || (currIMF[1] == "ui")) ? currIMF[1].Remove(0, 1) : currIMF[1]; - if (nextNeighbour == null) - { - if (string.IsNullOrEmpty(currIMF[2])) secondPhoneme += " R"; - else - { - if (singer.TryGetMappedOto($"{secondPhoneme} {currIMF[2]}", note.tone + shift1, color1, out _)) secondPhoneme += $" {currIMF[2]}"; - else secondPhoneme += $" {currIMF[2].ToUpper()}"; - } - } - else if (!string.IsNullOrEmpty(currIMF[2])) - { - if (singer.TryGetMappedOto($"{secondPhoneme} {currIMF[2]}", note.tone + shift1, color1, out _)) secondPhoneme += $" {currIMF[2]}"; - else secondPhoneme += $" {currIMF[2].ToUpper()}"; - } - - int noteLength = 0; - for (int i = 0; i < notes.Length; i++) noteLength += notes[i].duration; - - int secondPosition = Math.Max(noteLength - (nextNeighbour == null ? 120 : 180), noteLength / 2); - - // Map alias (apply shift + color) - if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) { - currPhoneme = otoAlt.Alias; - } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) { - currPhoneme = oto.Alias; - } - - if (singer.TryGetMappedOto(secondPhoneme + alt1, note.tone + shift1, color1, out var otoAlt1)) { - secondPhoneme = otoAlt1.Alias; - } else if (singer.TryGetMappedOto(secondPhoneme, note.tone + shift1, color1, out var oto)) { - secondPhoneme = oto.Alias; - } - - // Return Result - return new Result - { - phonemes = new Phoneme[] { - new Phoneme { phoneme = currPhoneme }, - new Phoneme { phoneme = secondPhoneme, position = secondPosition } - } - }; - } - } - } + if (nextNeighbour == null) { + if (string.IsNullOrEmpty(currIMF[2])) secondPhoneme += " R"; + else { + if (singer.TryGetMappedOto($"{secondPhoneme} {currIMF[2]}", note.tone + shift1, color1, out _)) secondPhoneme += $" {currIMF[2]}"; + else secondPhoneme += $" {currIMF[2].ToUpper()}"; + } + } else if (!string.IsNullOrEmpty(currIMF[2])) { + if (singer.TryGetMappedOto($"{secondPhoneme} {currIMF[2]}", note.tone + shift1, color1, out _)) secondPhoneme += $" {currIMF[2]}"; + else secondPhoneme += $" {currIMF[2].ToUpper()}"; + } + + int noteLength = 0; + for (int i = 0; i < notes.Length; i++) noteLength += notes[i].duration; + + int secondPosition = Math.Max(noteLength - (nextNeighbour == null ? 120 : 180), noteLength / 2); + + // Map alias (apply shift + color) + if (singer.TryGetMappedOto(currPhoneme + alt, note.tone + shift, color, out var otoAlt)) { + currPhoneme = otoAlt.Alias; + } else if (singer.TryGetMappedOto(currPhoneme, note.tone + shift, color, out var oto)) { + currPhoneme = oto.Alias; + } + + if (singer.TryGetMappedOto(secondPhoneme + alt1, note.tone + shift1, color1, out var otoAlt1)) { + secondPhoneme = otoAlt1.Alias; + } else if (singer.TryGetMappedOto(secondPhoneme, note.tone + shift1, color1, out var oto)) { + secondPhoneme = oto.Alias; + } + + // Return Result + return new Result { + phonemes = new Phoneme[] { + new Phoneme { phoneme = currPhoneme }, + new Phoneme { phoneme = secondPhoneme, position = secondPosition } + } + }; + } + } + } } diff --git a/OpenUtau.Plugin.Builtin/MonophonePhonemizer.cs b/OpenUtau.Plugin.Builtin/MonophonePhonemizer.cs index d0648ad22..c5626f1dd 100644 --- a/OpenUtau.Plugin.Builtin/MonophonePhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/MonophonePhonemizer.cs @@ -1,17 +1,15 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Serilog; -namespace OpenUtau.Plugin.Builtin -{ - public abstract class MonophonePhonemizer : PhonemeBasedPhonemizer - { - public MonophonePhonemizer(){ +namespace OpenUtau.Plugin.Builtin { + public abstract class MonophonePhonemizer : PhonemeBasedPhonemizer { + public MonophonePhonemizer() { addTail = false; } - + protected override string GetPhonemeOrFallback(string prevSymbol, string symbol, int tone, string color, string alt) { if (!string.IsNullOrEmpty(alt) && singer.TryGetMappedOto($"{symbol}{alt}", tone, color, out var oto)) { return oto.Alias; @@ -29,4 +27,4 @@ protected override string GetPhonemeOrFallback(string prevSymbol, string symbol, return $"{symbol}{alt}"; } } -} \ No newline at end of file +} diff --git a/OpenUtau.Plugin.Builtin/PhonemeBasedPhonemizer.cs b/OpenUtau.Plugin.Builtin/PhonemeBasedPhonemizer.cs index 2c33d0a99..309a0e186 100644 --- a/OpenUtau.Plugin.Builtin/PhonemeBasedPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/PhonemeBasedPhonemizer.cs @@ -1,14 +1,12 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using OpenUtau.Api; using OpenUtau.Core.Ustx; using Serilog; -namespace OpenUtau.Plugin.Builtin -{ - public abstract class PhonemeBasedPhonemizer : Phonemizer - { +namespace OpenUtau.Plugin.Builtin { + public abstract class PhonemeBasedPhonemizer : Phonemizer { protected Dictionary vowelFallback; protected USinger singer; protected IG2p g2p; @@ -21,7 +19,7 @@ public abstract class PhonemeBasedPhonemizer : Phonemizer /// This property will later be exposed in UI for user adjustment. /// public int ConsonantLength { get; set; } = 60; - + public bool addTail { get; set; } = true; public PhonemeBasedPhonemizer() { @@ -92,14 +90,14 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN // - "+n" manually aligns to n-th phoneme. alignments.Clear(); //notes except those whose lyrics start witn "+*" or "+~" - var nonExtensionNotes = notes.Where(n=>!IsSyllableVowelExtensionNote(n)).ToArray(); + var nonExtensionNotes = notes.Where(n => !IsSyllableVowelExtensionNote(n)).ToArray(); for (int i = 0; i < symbols.Length; i++) { if (isVowel[i] && alignments.Count < nonExtensionNotes.Length) { //Handle glide phonemes //For "Consonant-Glide-Vowel" syllable, the glide phoneme is placed after the start position of the note. - if(i>=2 && isGlide[i-1] && !isVowel[i-2]){ - alignments.Add(Tuple.Create(i-1, nonExtensionNotes[alignments.Count].position - notes[0].position, false)); - } else{ + if (i >= 2 && isGlide[i - 1] && !isVowel[i - 2]) { + alignments.Add(Tuple.Create(i - 1, nonExtensionNotes[alignments.Count].position - notes[0].position, false)); + } else { alignments.Add(Tuple.Create(i, nonExtensionNotes[alignments.Count].position - notes[0].position, false)); } } @@ -219,4 +217,4 @@ void DistributeDuration(bool[] isVowel, Phoneme[] phonemes, int startIndex, int } } } -} \ No newline at end of file +} diff --git a/OpenUtau.Plugin.Builtin/PolishCVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/PolishCVCPhonemizer.cs index ed6d96598..732e213c2 100644 --- a/OpenUtau.Plugin.Builtin/PolishCVCPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/PolishCVCPhonemizer.cs @@ -24,14 +24,12 @@ protected override List ProcessSyllable(Syllable syllable) { var phonemes = new List(); if (syllable.IsStartingV) { basePhoneme = $"- {v}"; - } - else if (syllable.IsStartingCV) { + } else if (syllable.IsStartingCV) { basePhoneme = $"- {cc.Last()}{v}"; for (var i = 0; i < cc.Length - 1; i++) { phonemes.Add($"- {cc[i]}"); } - } - else if (syllable.IsVV) { + } else if (syllable.IsVV) { if (!CanMakeAliasExtension(syllable)) { basePhoneme = v; } else { diff --git a/OpenUtau.Plugin.Builtin/PresampSamplePhonemizer.cs b/OpenUtau.Plugin.Builtin/PresampSamplePhonemizer.cs index d330d681b..f9675cf9d 100644 --- a/OpenUtau.Plugin.Builtin/PresampSamplePhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/PresampSamplePhonemizer.cs @@ -54,7 +54,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN if (presamp.PhonemeList.TryGetValue(prevLyric, out PresampPhoneme prevPhoneme)) { prevVowel = prevPhoneme.Vowel; } - }; + } string vcpad = presamp.AliasRules.VCPAD; var attr0 = notes[0].phonemeAttributes?.FirstOrDefault(attr => attr.index == 0) ?? default; diff --git a/OpenUtau.Plugin.Builtin/RussianCVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/RussianCVCPhonemizer.cs index 46f70d4ad..ae677574b 100644 --- a/OpenUtau.Plugin.Builtin/RussianCVCPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/RussianCVCPhonemizer.cs @@ -43,22 +43,19 @@ protected override List ProcessSyllable(Syllable syllable) { var phonemes = new List(); if (syllable.IsStartingV) { basePhoneme = $"-{v}"; - } - else if (syllable.IsVV) { + } else if (syllable.IsVV) { if (!CanMakeAliasExtension(syllable)) { basePhoneme = v; } else { // the previous alias will be extended basePhoneme = null; } - } - else if (syllable.IsStartingCV) { + } else if (syllable.IsStartingCV) { basePhoneme = $"-{cc.Last()}{v}"; for (var i = 0; i < cc.Length - 1; i++) { phonemes.Add($"-{cc[i]}"); } - } - else { // VCV + } else { // VCV if (cc.Length == 1 || IsShort(syllable) || cc.Last() == "`") { basePhoneme = $"{cc.Last()}{v}"; } else { @@ -82,8 +79,7 @@ protected override List ProcessEnding(Ending ending) { var phonemes = new List(); if (ending.IsEndingV) { phonemes.Add($"{v}-"); - } - else { + } else { phonemes.Add($"{v}{cc[0]}-"); for (var i = 1; i < cc.Length; i++) { var cr = $"{cc[i]}-"; diff --git a/OpenUtau.Plugin.Builtin/SimpleVoicevoxENtoJAPhonemizer.cs b/OpenUtau.Plugin.Builtin/SimpleVoicevoxENtoJAPhonemizer.cs index 7ec7851db..da195e7a4 100644 --- a/OpenUtau.Plugin.Builtin/SimpleVoicevoxENtoJAPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/SimpleVoicevoxENtoJAPhonemizer.cs @@ -219,7 +219,7 @@ public override void SetSinger(USinger singer) { protected override string[] GetSymbols(Note note) { List modified = new List(); - if (VoicevoxUtils.phoneme_List.paus.TryGetValue(note.lyric,out string str)) { + if (VoicevoxUtils.phoneme_List.paus.TryGetValue(note.lyric, out string str)) { modified.Add(str); } else { string[] original = base.GetSymbols(note); @@ -252,8 +252,8 @@ protected override List ProcessSyllable(Syllable syllable) { return phonemes; } - // Check CCs for special clusters - var adjustedCC = new List(); + // Check CCs for special clusters + var adjustedCC = new List(); for (var i = 0; i < cc.Length; i++) { if (i == cc.Length - 1) { adjustedCC.Add(cc[i]); diff --git a/OpenUtau.Plugin.Builtin/SpanishMakkusanPhonemizer.cs b/OpenUtau.Plugin.Builtin/SpanishMakkusanPhonemizer.cs index ea5244d7e..b54e64185 100644 --- a/OpenUtau.Plugin.Builtin/SpanishMakkusanPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/SpanishMakkusanPhonemizer.cs @@ -1,13 +1,13 @@ -using System; +using System; using System.Collections.Generic; +using System.Linq; using System.Text; using OpenUtau.Api; using OpenUtau.Core.G2p; -using System.Linq; using Serilog; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("Spanish Makkusan Phonemizer", "ES MAKKU", "Lotte V", language:"ES")] + [Phonemizer("Spanish Makkusan Phonemizer", "ES MAKKU", "Lotte V", language: "ES")] public class SpanishMakkusanPhonemizer : SyllableBasedPhonemizer { /// /// Spanish phonemizer, based on Makkusan's Italian reclist. @@ -31,8 +31,7 @@ public class SpanishMakkusanPhonemizer : SyllableBasedPhonemizer { protected override Dictionary GetDictionaryPhonemesReplacement() => dictionaryReplacements; - protected override List ProcessSyllable(Syllable syllable) - { + protected override List ProcessSyllable(Syllable syllable) { string prevV = syllable.prevV; string[] cc = syllable.cc; string v = syllable.v; @@ -103,23 +102,23 @@ protected override List ProcessSyllable(Syllable syllable) } } else { basePhoneme = cc.Last() + v; - // try CCV - if (cc.Length - firstC > 1) { - for (var i = firstC; i < cc.Length; i++) { - var ccv = $"{string.Join("", cc.Skip(i))}{v}"; - if (HasOto(ccv, syllable.vowelTone) && !ccv.Contains("bre")) { + // try CCV + if (cc.Length - firstC > 1) { + for (var i = firstC; i < cc.Length; i++) { + var ccv = $"{string.Join("", cc.Skip(i))}{v}"; + if (HasOto(ccv, syllable.vowelTone) && !ccv.Contains("bre")) { + lastC = i; + basePhoneme = ccv; + if (!HasOto(ccv, syllable.vowelTone)) { + ccv = ValidateAlias(ccv); lastC = i; basePhoneme = ccv; - if (!HasOto(ccv, syllable.vowelTone)) { - ccv = ValidateAlias(ccv); - lastC = i; - basePhoneme = ccv; - break; - } break; } + break; } } + } phonemes.Add($"{prevV} {cc[0]}"); } for (var i = firstC; i < lastC; i++) { @@ -153,7 +152,7 @@ protected override List ProcessSyllable(Syllable syllable) cc2 = ValidateAlias(cc2); } if (!HasOto(cc2, syllable.tone)) { - cc2 = $"{cc[i + 1]}{cc[i + 2]}"; + cc2 = $"{cc[i + 1]}{cc[i + 2]}"; } if (!HasOto(cc2, syllable.tone)) { cc2 = ValidateAlias(cc2); @@ -177,7 +176,7 @@ protected override List ProcessSyllable(Syllable syllable) // like [V C1] [C1 C2-] [C3 ..] } } else { - // like [V C1] [C1 C2] [C2 ..] or like [V C1] [C1 -] [C3 ..] + // like [V C1] [C1 C2] [C2 ..] or like [V C1] [C1 -] [C3 ..] TryAddPhoneme(phonemes, syllable.tone, cc1, ValidateAlias(cc1)); } } @@ -186,8 +185,7 @@ protected override List ProcessSyllable(Syllable syllable) return phonemes; } - protected override List ProcessEnding(Ending ending) - { + protected override List ProcessEnding(Ending ending) { string[] cc = ending.cc; string v = ending.prevV; diff --git a/OpenUtau.Plugin.Builtin/SpanishSyllableBasedPhonemizer.cs b/OpenUtau.Plugin.Builtin/SpanishSyllableBasedPhonemizer.cs index e350abf21..a2e9c6fdb 100644 --- a/OpenUtau.Plugin.Builtin/SpanishSyllableBasedPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/SpanishSyllableBasedPhonemizer.cs @@ -1,10 +1,10 @@ -using System; +using System; using System.Collections.Generic; +using System.IO; +using System.Linq; using OpenUtau.Api; using OpenUtau.Core.G2p; -using System.Linq; using Serilog; -using System.IO; namespace OpenUtau.Plugin.Builtin { /// diff --git a/OpenUtau.Plugin.Builtin/SpanishVCCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/SpanishVCCVPhonemizer.cs index f4ff89841..22f9aa899 100644 --- a/OpenUtau.Plugin.Builtin/SpanishVCCVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/SpanishVCCVPhonemizer.cs @@ -1,9 +1,9 @@ -using System; +using System; using System.Collections.Generic; +using System.Linq; using System.Text; using OpenUtau.Api; using OpenUtau.Core.G2p; -using System.Linq; using Serilog; namespace OpenUtau.Plugin.Builtin { @@ -242,7 +242,7 @@ protected override List ProcessSyllable(Syllable syllable) { } } var cc2 = $"{string.Join("", cc.Skip(i))}"; - if (i + 1 < lastC && !vowels.Contains(cc2)) { + if (i + 1 < lastC && !vowels.Contains(cc2)) { if (!HasOto(cc2, syllable.tone)) { cc2 = ValidateAlias(cc2); } @@ -425,7 +425,7 @@ protected override string ValidateAlias(string alias) { } protected override double GetTransitionBasicLengthMs(string alias = "") { - foreach (var c in shortConsonants ) { + foreach (var c in shortConsonants) { if (alias.Contains(c) && !alias.Contains("rr") && !alias.StartsWith(c) && !alias.Contains("ar") && !alias.Contains("er") && !alias.Contains("ir") && !alias.Contains("or") && !alias.Contains("ur")) { return base.GetTransitionBasicLengthMs() * 0.50; } diff --git a/OpenUtau.Plugin.Builtin/SyllableBasedPhonemizer.cs b/OpenUtau.Plugin.Builtin/SyllableBasedPhonemizer.cs index 2d79fa9ca..2aedb73b0 100644 --- a/OpenUtau.Plugin.Builtin/SyllableBasedPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/SyllableBasedPhonemizer.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Text; +using System.Threading.Tasks; using OpenUtau.Api; using OpenUtau.Core.Ustx; -using System.Linq; -using System.IO; using Serilog; -using System.Threading.Tasks; using static OpenUtau.Api.Phonemizer; namespace OpenUtau.Plugin.Builtin { @@ -497,9 +497,9 @@ protected virtual string[] HandleWordNotFound(Note note) { string color = attr.voiceColor; int toneShift = attr.toneShift; var mpdlyric = MapPhoneme(note.lyric, note.tone + toneShift, color, alt, singer); - if(HasOto(mpdlyric, note.tone)){ + if (HasOto(mpdlyric, note.tone)) { error = mpdlyric; - }else{ + } else { error = "word not found"; } return null; @@ -594,8 +594,8 @@ protected virtual void ParseDictionary(string dictionaryText, G2pDictionary.Buil n => replacements != null && replacements.ContainsKey(n) ? replacements[n] : n); lock (builder) { builder.AddEntry(key, values); - }; - }; + } + } } #region helpers diff --git a/OpenUtau.Plugin.Builtin/VietnameseCVVCPhonemizer.cs b/OpenUtau.Plugin.Builtin/VietnameseCVVCPhonemizer.cs index 66881e045..5d93e660d 100644 --- a/OpenUtau.Plugin.Builtin/VietnameseCVVCPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/VietnameseCVVCPhonemizer.cs @@ -4,7 +4,7 @@ using OpenUtau.Core.Ustx; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("Vietnamese CVVC Phonemizer", "VIE CVVC", "Jani Tran", language:"VI")] + [Phonemizer("Vietnamese CVVC Phonemizer", "VIE CVVC", "Jani Tran", language: "VI")] public class VietnameseCVVCPhonemizer : Phonemizer { /// /// The lookup table to convert a hiragana to its tail vowel. @@ -41,9 +41,9 @@ static VietnameseCVVCPhonemizer() { private USinger singer; public override void SetSinger(USinger singer) => this.singer = singer; - + // Legacy mapping. Might adjust later to new mapping style. - public override bool LegacyMapping => true; + public override bool LegacyMapping => true; public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) { var note = notes[0]; @@ -88,19 +88,19 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN note.lyric = note.lyric.ToLower(); } } - note.lyric = note.lyric.Replace('à', 'a').Replace('á', 'a').Replace('ả', 'a').Replace('ã', 'a').Replace('ạ', 'a'); - note.lyric = note.lyric.Replace('ằ', 'ă').Replace('ắ', 'ă').Replace('ẳ', 'ă').Replace('ẵ', 'ă').Replace('ặ', 'ă'); - note.lyric = note.lyric.Replace('ầ', 'â').Replace('ấ', 'â').Replace('ẩ', 'â').Replace('ẫ', 'â').Replace('ậ', 'â'); - note.lyric = note.lyric.Replace('ờ', 'ơ').Replace('ớ', 'ơ').Replace('ở', 'ơ').Replace('ỡ', 'ơ').Replace('ợ', 'ơ'); - note.lyric = note.lyric.Replace('ì', 'i').Replace('í', 'i').Replace('ỉ', 'i').Replace('ĩ', 'i').Replace('ị', 'i'); - note.lyric = note.lyric.Replace('ỳ', 'y').Replace('ý', 'y').Replace('ỷ', 'y').Replace('ỹ', 'y').Replace('ỵ', 'y'); - note.lyric = note.lyric.Replace('è', 'e').Replace('é', 'e').Replace('ẻ', 'e').Replace('ẽ', 'e').Replace('ẹ', 'e'); - note.lyric = note.lyric.Replace('ề', 'ê').Replace('ế', 'ê').Replace('ể', 'ê').Replace('ễ', 'ê').Replace('ệ', 'ê'); - note.lyric = note.lyric.Replace('ò', 'o').Replace('ó', 'o').Replace('ỏ', 'o').Replace('õ', 'o').Replace('ọ', 'o'); - note.lyric = note.lyric.Replace('ồ', 'ô').Replace('ố', 'ô').Replace('ổ', 'ô').Replace('ỗ', 'ô').Replace('ộ', 'ô'); - note.lyric = note.lyric.Replace('ù', 'u').Replace('ú', 'u').Replace('ủ', 'u').Replace('ũ', 'u').Replace('ụ', 'u'); - note.lyric = note.lyric.Replace('ừ', 'ư').Replace('ứ', 'ư').Replace('ử', 'ư').Replace('ữ', 'ư').Replace('ự', 'ư'); - if (note.lyric == "quôc") { + note.lyric = note.lyric.Replace('à', 'a').Replace('á', 'a').Replace('ả', 'a').Replace('ã', 'a').Replace('ạ', 'a'); + note.lyric = note.lyric.Replace('ằ', 'ă').Replace('ắ', 'ă').Replace('ẳ', 'ă').Replace('ẵ', 'ă').Replace('ặ', 'ă'); + note.lyric = note.lyric.Replace('ầ', 'â').Replace('ấ', 'â').Replace('ẩ', 'â').Replace('ẫ', 'â').Replace('ậ', 'â'); + note.lyric = note.lyric.Replace('ờ', 'ơ').Replace('ớ', 'ơ').Replace('ở', 'ơ').Replace('ỡ', 'ơ').Replace('ợ', 'ơ'); + note.lyric = note.lyric.Replace('ì', 'i').Replace('í', 'i').Replace('ỉ', 'i').Replace('ĩ', 'i').Replace('ị', 'i'); + note.lyric = note.lyric.Replace('ỳ', 'y').Replace('ý', 'y').Replace('ỷ', 'y').Replace('ỹ', 'y').Replace('ỵ', 'y'); + note.lyric = note.lyric.Replace('è', 'e').Replace('é', 'e').Replace('ẻ', 'e').Replace('ẽ', 'e').Replace('ẹ', 'e'); + note.lyric = note.lyric.Replace('ề', 'ê').Replace('ế', 'ê').Replace('ể', 'ê').Replace('ễ', 'ê').Replace('ệ', 'ê'); + note.lyric = note.lyric.Replace('ò', 'o').Replace('ó', 'o').Replace('ỏ', 'o').Replace('õ', 'o').Replace('ọ', 'o'); + note.lyric = note.lyric.Replace('ồ', 'ô').Replace('ố', 'ô').Replace('ổ', 'ô').Replace('ỗ', 'ô').Replace('ộ', 'ô'); + note.lyric = note.lyric.Replace('ù', 'u').Replace('ú', 'u').Replace('ủ', 'u').Replace('ũ', 'u').Replace('ụ', 'u'); + note.lyric = note.lyric.Replace('ừ', 'ư').Replace('ứ', 'ư').Replace('ử', 'ư').Replace('ữ', 'ư').Replace('ự', 'ư'); + if (note.lyric == "quôc") { note.lyric = "quâc"; } if (note.lyric != "gi" && note.lyric != "gin" && note.lyric != "gim" && note.lyric != "ginh" && note.lyric != "ging" && note.lyric != "git" && note.lyric != "gip" && note.lyric != "gic" && note.lyric != "gich") { @@ -141,16 +141,21 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN || loi.StartsWith("T") || loi.StartsWith("Z") || loi.StartsWith("v") || loi.StartsWith("w") || loi.StartsWith("z") || loi.StartsWith("p")); int x = prevNeighbour?.duration ?? default(int); - if (x < 160 && prevNeighbour != null) { VCP = -(x * 4 / 8); } - else if (loi.StartsWith("b") || loi.StartsWith("d") || loi.StartsWith("g") || loi.StartsWith("d") || loi.StartsWith("k") || loi.StartsWith("l") - || loi.StartsWith("m") || loi.StartsWith("n") || loi.StartsWith("nh") || loi.StartsWith("ng") || loi.StartsWith("t") || loi.StartsWith("th") - || loi.StartsWith("v") || loi.StartsWith("w") || loi.StartsWith("y")) VCP = -70; - else VCP = -110; + if (x < 160 && prevNeighbour != null) { + VCP = -(x * 4 / 8); + } else if (loi.StartsWith("b") || loi.StartsWith("d") || loi.StartsWith("g") || loi.StartsWith("d") || loi.StartsWith("k") || loi.StartsWith("l") + || loi.StartsWith("m") || loi.StartsWith("n") || loi.StartsWith("nh") || loi.StartsWith("ng") || loi.StartsWith("t") || loi.StartsWith("th") + || loi.StartsWith("v") || loi.StartsWith("w") || loi.StartsWith("y")) { + VCP = -70; + } else { + VCP = -110; + } bool kocoC; if (tontaiC == true) { kocoC = false; - } else + } else { kocoC = true; + } bool BR = note.lyric.StartsWith("breath"); bool tontaiVV = (loi.EndsWith("ai") || loi.EndsWith("ơi") || loi.EndsWith("oi") || loi.EndsWith("ôi") || loi.EndsWith("ui") || loi.EndsWith("ưi") || loi.EndsWith("ao") || loi.EndsWith("eo") || loi.EndsWith("êu") || loi.EndsWith("iu") @@ -459,7 +464,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } } else if (prevNeighbour == null) { phonemes.Add( - new Phoneme { phoneme = $"-{V1}" }); + new Phoneme { phoneme = $"-{V1}" }); phonemes.Add( new Phoneme { phoneme = $"{V1}{V2}", position = Long }); phonemes.Add( diff --git a/OpenUtau.Plugin.Builtin/VietnameseVCVPhonemizer.cs b/OpenUtau.Plugin.Builtin/VietnameseVCVPhonemizer.cs index 41f6826fb..090302539 100644 --- a/OpenUtau.Plugin.Builtin/VietnameseVCVPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/VietnameseVCVPhonemizer.cs @@ -4,7 +4,7 @@ using OpenUtau.Core.Ustx; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("Vietnamese VCV Phonemizer", "VIE VCV", "Jani Tran", language:"VI")] + [Phonemizer("Vietnamese VCV Phonemizer", "VIE VCV", "Jani Tran", language: "VI")] public class VietnameseVCVPhonemizer : Phonemizer { /// /// The lookup table to convert a hiragana to its tail vowel. @@ -41,9 +41,9 @@ static VietnameseVCVPhonemizer() { private USinger singer; public override void SetSinger(USinger singer) => this.singer = singer; - + // Legacy mapping. Might adjust later to new mapping style. - public override bool LegacyMapping => true; + public override bool LegacyMapping => true; public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevNeighbour, Note? nextNeighbour, Note[] prevNeighbours) { var note = notes[0]; diff --git a/OpenUtau.Plugin.Builtin/VietnameseVINAPhonemizer.cs b/OpenUtau.Plugin.Builtin/VietnameseVINAPhonemizer.cs index 395181f9a..b02cd0f9b 100644 --- a/OpenUtau.Plugin.Builtin/VietnameseVINAPhonemizer.cs +++ b/OpenUtau.Plugin.Builtin/VietnameseVINAPhonemizer.cs @@ -5,7 +5,7 @@ using OpenUtau.Core.Ustx; namespace OpenUtau.Plugin.Builtin { - [Phonemizer("Vietnamese VINA Phonemizer", "VIE VINA", "Jani Tran - Hoang Phuc", language:"VI")] + [Phonemizer("Vietnamese VINA Phonemizer", "VIE VINA", "Jani Tran - Hoang Phuc", language: "VI")] public class VietnameseVINAPhonemizer : Phonemizer { /// /// The lookup table to convert a hiragana to its tail vowel. @@ -125,16 +125,21 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN || loi.Contains("uôn") || loi.Contains("uôN") || loi.Contains("uôm") || loi.Contains("uôt") || loi.Contains("uôk") || loi.Contains("uôi") || loi.Contains("ươn") || loi.Contains("ươN") || loi.Contains("ươm") || loi.Contains("ươt") || loi.Contains("ươk") || loi.Contains("ươp") || loi.Contains("ươi") || loi.Contains("ươu"); int x = prevNeighbour?.duration ?? default(int); - if (x < 160 && prevNeighbour != null) { VCP = - (x * 4 / 8); } - else if (loi.StartsWith("b") || loi.StartsWith("d") || loi.StartsWith("g") || loi.StartsWith("d") || loi.StartsWith("k") || loi.StartsWith("l") - || loi.StartsWith("m") || loi.StartsWith("n") || loi.StartsWith("nh") || loi.StartsWith("ng") || loi.StartsWith("t") || loi.StartsWith("th") - || loi.StartsWith("v") || loi.StartsWith("w") || loi.StartsWith("y")) VCP = -70; - else VCP = -110; + if (x < 160 && prevNeighbour != null) { + VCP = -(x * 4 / 8); + } else if (loi.StartsWith("b") || loi.StartsWith("d") || loi.StartsWith("g") || loi.StartsWith("d") || loi.StartsWith("k") || loi.StartsWith("l") + || loi.StartsWith("m") || loi.StartsWith("n") || loi.StartsWith("nh") || loi.StartsWith("ng") || loi.StartsWith("t") || loi.StartsWith("th") + || loi.StartsWith("v") || loi.StartsWith("w") || loi.StartsWith("y")) { + VCP = -70; + } else { + VCP = -110; + } bool koVVCchia; if (tontaiVVC == true) { koVVCchia = false; - } else + } else { koVVCchia = true; + } bool tontaiCcuoi = (loi.EndsWith("k") || loi.EndsWith("t") || loi.EndsWith("C") || loi.EndsWith("p") || loi.EndsWith(".")); bool tontaiC = loi.StartsWith("b") || loi.StartsWith("C") || loi.StartsWith("d") || loi.StartsWith("f") || loi.StartsWith("g") || loi.StartsWith("h") || loi.StartsWith("k") || loi.StartsWith("K") @@ -622,10 +627,10 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN phonemes.Add( new Phoneme { phoneme = $"{C}wA{N}" } ); - phonemes.Add( - new Phoneme { phoneme = $"{N_} -", position = End } - ); - } + phonemes.Add( + new Phoneme { phoneme = $"{N_} -", position = End } + ); + } } else { // if (loi.StartsWith(".")) { phonemes.Add( @@ -731,9 +736,9 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } else { phonemes.Add( new Phoneme { phoneme = $"{C}{V1}{V2}" }); - phonemes.Add( - new Phoneme { phoneme = $"{V2}{N}", position = ViTri }); - } + phonemes.Add( + new Phoneme { phoneme = $"{V2}{N}", position = ViTri }); + } } else { // ko có VV - if (_C) { phonemes.Add( @@ -745,9 +750,9 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } else { phonemes.Add( new Phoneme { phoneme = $"{C}{V1}{V2}" }); - phonemes.Add( - new Phoneme { phoneme = $"{V2_2}{N}", position = ViTri }); - } + phonemes.Add( + new Phoneme { phoneme = $"{V2_2}{N}", position = ViTri }); + } } } } @@ -853,9 +858,9 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } else { phonemes.Add( new Phoneme { phoneme = $"{C}{V1}{V2}" }); - phonemes.Add( - new Phoneme { phoneme = $"{VVC}", position = ViTri }); - } + phonemes.Add( + new Phoneme { phoneme = $"{VVC}", position = ViTri }); + } } else if (NoNext) { // ko có note kế tiếp if (_C) { @@ -1036,9 +1041,9 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN phonemes.Add( new Phoneme { phoneme = $"- {V1}" }); phonemes.Add( - new Phoneme { phoneme = $"{V1_}{V2}",position = ViTri }); + new Phoneme { phoneme = $"{V1_}{V2}", position = ViTri }); phonemes.Add( - new Phoneme { phoneme = $"{N} -", position = End }); + new Phoneme { phoneme = $"{N} -", position = End }); } } else { // co note ke tiep if (wV) { // oa oe uê ,... @@ -1151,7 +1156,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } } } - } else + } else if (prevNeighbour != null) { var lyric = prevNeighbour?.phoneticHint ?? prevNeighbour?.lyric; var unicode = ToUnicodeElements(lyric); @@ -1530,8 +1535,8 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } else if (wV) { phonemes.Add( new Phoneme { phoneme = $"{vow}{Cw}", position = VCP }); - phonemes.Add( - new Phoneme { phoneme = $"{C}{V1}{V2_2}" }); + phonemes.Add( + new Phoneme { phoneme = $"{C}{V1}{V2_2}" }); } else { // bths phonemes.Add( new Phoneme { phoneme = $"{vow}{Cw}", position = VCP }); @@ -2001,7 +2006,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN new Phoneme { phoneme = $"{V} -", position = End }); } else phonemes.Add( new Phoneme { phoneme = $"- {C}{V}" }); - } else + } else if (NoNext) { phonemes.Add( new Phoneme { phoneme = $"{vow}{C}", position = VCP }); @@ -2014,7 +2019,7 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN new Phoneme { phoneme = $"{vow}{C}", position = VCP }); phonemes.Add( new Phoneme { phoneme = $"{C}{V}" }); - } + } } else if (dem == 3) { string C = note.lyric.Substring(0, 1); string V1 = note.lyric.Substring(1, 1); @@ -2128,9 +2133,8 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN new Phoneme { phoneme = $"{V1}{V2}", position = ViTri }); } } - } - else { // nếu ko phải phụ âm y - // 2 âm VV, ví dụ: "oa" + } else { // nếu ko phải phụ âm y + // 2 âm VV, ví dụ: "oa" if (fry) { } else if ((dem == 2) && kocoC) { string V1 = loi.Substring(0, 1); @@ -2389,8 +2393,8 @@ public override Result Process(Note[] notes, Note? prev, Note? next, Note? prevN } else { phonemes.Add( new Phoneme { phoneme = $"{vow}{V1}" }); - phonemes.Add( - new Phoneme { phoneme = $"{VVC}", position = ViTri }); + phonemes.Add( + new Phoneme { phoneme = $"{VVC}", position = ViTri }); } } } diff --git a/OpenUtau.Test/App/AppTest.cs b/OpenUtau.Test/App/AppTest.cs index bc9c02b07..4b097015d 100644 --- a/OpenUtau.Test/App/AppTest.cs +++ b/OpenUtau.Test/App/AppTest.cs @@ -1,8 +1,8 @@ -using Xunit; -using Avalonia; +using Avalonia; using Avalonia.Headless; using Avalonia.Styling; using OpenUtau.App; +using Xunit; [assembly: AvaloniaTestApplication(typeof(TestAppBuilder))] diff --git a/OpenUtau.Test/Classic/PluginRunnerTest.cs b/OpenUtau.Test/Classic/PluginRunnerTest.cs index d97f2758b..ce41527cf 100644 --- a/OpenUtau.Test/Classic/PluginRunnerTest.cs +++ b/OpenUtau.Test/Classic/PluginRunnerTest.cs @@ -49,7 +49,7 @@ public static ExecuteArgument BasicUProject() { // Any flag must be registered in the project Ustx.AddDefaultExpressions(project); - + var before = UNote.Create(); before.lyric = "a"; before.duration = 10; @@ -157,7 +157,7 @@ private static Action DoNothingResponse() { // Different line feed code for each OS var eol = Environment.NewLine; expected = expected.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", eol); - + Assert.Equal(expected, text); writer.Write(text); }; diff --git a/OpenUtau.Test/Classic/UstTest.cs b/OpenUtau.Test/Classic/UstTest.cs index 1863f3916..da0552c82 100644 --- a/OpenUtau.Test/Classic/UstTest.cs +++ b/OpenUtau.Test/Classic/UstTest.cs @@ -78,11 +78,13 @@ public void EqualInLyric() { Assert.Single(part.notes); Assert.Equal("A==B[C=D],EFG", part.notes.First().lyric); Assert.Equal(60, part.notes.First().tone); - Assert.Equivalent(new UPitch {data = new List { + Assert.Equivalent(new UPitch { + data = new List { new PitchPoint { X = -222, Y = -19, shape = PitchPointShape.io}, new PitchPoint { X = 70, Y = -20.7f, shape = PitchPointShape.io}, // X = -222 + 292 = 70 new PitchPoint { X = 253, Y = 0, shape = PitchPointShape.io} // X = 70 + 183 = 253 - }, snapFirst = false } , part.notes.First().pitch); + }, snapFirst = false + }, part.notes.First().pitch); Assert.Equivalent(new UVibrato { length = 80, period = 200, depth = 20, @in = 20, @out = 20, shift = 0, drift = -50, volLink = 0 }, part.notes.First().vibrato); } } @@ -106,7 +108,7 @@ public void ParsePluginParseNoteTest() { var before = UNote.Create(); before.lyric = "a"; before.duration = 100; - + var first = UNote.Create(); first.lyric = "ka"; first.duration = 200; @@ -116,11 +118,11 @@ public void ParsePluginParseNoteTest() { new PitchPoint { X = 93.75f, Y = -12.2f, shape = PitchPointShape.io}, new PitchPoint { X = 194.7f, Y = 0, shape = PitchPointShape.io} }; - + var second = UNote.Create(); second.lyric = "r"; second.duration = 300; - + var third = UNote.Create(); third.lyric = "ta"; third.duration = 400; @@ -132,11 +134,11 @@ public void ParsePluginParseNoteTest() { var last = UNote.Create(); last.lyric = "na"; last.duration = 500; - + var after = UNote.Create(); after.lyric = "ha"; after.duration = 600; - + part.notes.Add(before); part.notes.Add(first); part.notes.Add(second); diff --git a/OpenUtau.Test/Core/Format/MusicXMLTest.cs b/OpenUtau.Test/Core/Format/MusicXMLTest.cs index cabc0f8e1..6099f7cbb 100644 --- a/OpenUtau.Test/Core/Format/MusicXMLTest.cs +++ b/OpenUtau.Test/Core/Format/MusicXMLTest.cs @@ -1,30 +1,29 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using Xunit; -using Xunit.Abstractions; - using OpenUtau.Core.Ustx; using ReactiveUI; +using Xunit; +using Xunit.Abstractions; namespace OpenUtau.Core.Format { public class MusicXMLTest { readonly ITestOutputHelper output; string basePath; - public MusicXMLTest(ITestOutputHelper output){ + public MusicXMLTest(ITestOutputHelper output) { this.output = output; var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); basePath = Path.Join(dir, "Files", "MusicXML"); } - static void Pairwise(IEnumerable enumerable, Action action){ + static void Pairwise(IEnumerable enumerable, Action action) { var enumerator = enumerable.GetEnumerator(); - if(!enumerator.MoveNext()) return; + if (!enumerator.MoveNext()) return; var prev = enumerator.Current; - while(enumerator.MoveNext()){ + while (enumerator.MoveNext()) { action(prev, enumerator.Current); prev = enumerator.Current; } @@ -35,7 +34,7 @@ static void Pairwise(IEnumerable enumerable, Action action){ /// which means that there is no gap between two notes. /// /// - static void AssertLegato(UVoicePart part){ + static void AssertLegato(UVoicePart part) { Pairwise(part.notes, (n1, n2) => { Assert.Equal(n1.duration, n2.position - n1.position); }); @@ -43,7 +42,7 @@ static void AssertLegato(UVoicePart part){ [Fact] public void PitchesTest() { - var project = MusicXML.LoadProject(Path.Join(basePath,"01a-Pitches-Pitches.musicxml")); + var project = MusicXML.LoadProject(Path.Join(basePath, "01a-Pitches-Pitches.musicxml")); var part = project.parts.First() as UVoicePart; int[] tonesOrig = new int[]{ 43, 45, 47, 48, @@ -56,69 +55,69 @@ public void PitchesTest() { 91, 93, 95, 96, }; int[] tones = tonesOrig - .Concat(tonesOrig.Select(t => t+1)) - .Concat(tonesOrig.Select(t => t-1)) - .Concat(new int[]{64, 65, 67, 69, 71, 72, 74, 76, 74, 70, 73, 73, 73, 73}) + .Concat(tonesOrig.Select(t => t + 1)) + .Concat(tonesOrig.Select(t => t - 1)) + .Concat(new int[] { 64, 65, 67, 69, 71, 72, 74, 76, 74, 70, 73, 73, 73, 73 }) .ToArray(); Assert.Equal(0, part.position); AssertLegato(part); Assert.Equal(0, part.notes.First().position); - foreach(var (n, t) in part.notes.Zip(tones)){ + foreach (var (n, t) in part.notes.Zip(tones)) { Assert.Equal(480, n.duration); Assert.Equal(t, n.tone); } } [Fact] - public void RestsTest(){ - var project = MusicXML.LoadProject(Path.Join(basePath,"02a-Rests-Durations.musicxml")); + public void RestsTest() { + var project = MusicXML.LoadProject(Path.Join(basePath, "02a-Rests-Durations.musicxml")); var part = project.parts.First() as UVoicePart; Assert.Empty(part.notes); } [Fact] - public void PitchedRestsTest(){ - var project = MusicXML.LoadProject(Path.Join(basePath,"02b-Rests-PitchedRests.musicxml")); + public void PitchedRestsTest() { + var project = MusicXML.LoadProject(Path.Join(basePath, "02b-Rests-PitchedRests.musicxml")); var part = project.parts.First() as UVoicePart; Assert.Empty(part.notes); } [Fact] - public void MultimeasureTimeSignaturesRestsTest(){ - var project = MusicXML.LoadProject(Path.Join(basePath,"02d-Rests-Multimeasure-TimeSignatures.musicxml")); + public void MultimeasureTimeSignaturesRestsTest() { + var project = MusicXML.LoadProject(Path.Join(basePath, "02d-Rests-Multimeasure-TimeSignatures.musicxml")); var part = project.parts.First() as UVoicePart; Assert.Single(part.notes); - Assert.Equal((2*4+3*3+2*2+2*4)*480, part.notes.First().position); - Assert.Equal(4*480, part.notes.First().duration); + Assert.Equal((2 * 4 + 3 * 3 + 2 * 2 + 2 * 4) * 480, part.notes.First().position); + Assert.Equal(4 * 480, part.notes.First().duration); } [Fact] - public void RhythmDurationsTest(){ - var project = MusicXML.LoadProject(Path.Join(basePath,"03aa-Rhythm-Durations.musicxml")); + public void RhythmDurationsTest() { + var project = MusicXML.LoadProject(Path.Join(basePath, "03aa-Rhythm-Durations.musicxml")); var part = project.parts.First() as UVoicePart; Assert.Equal(0, part.notes.First().position); AssertLegato(part); - var baseLengths = new int[] {128, 64, 32, 16, 8, 4, 2, 1, 1}; - var lengths = baseLengths.Select(l => l*30) - .Concat(baseLengths.Select(l => l*45)) - .Concat(baseLengths.Skip(2).Select(l => l*105)) + var baseLengths = new int[] { 128, 64, 32, 16, 8, 4, 2, 1, 1 }; + var lengths = baseLengths.Select(l => l * 30) + .Concat(baseLengths.Select(l => l * 45)) + .Concat(baseLengths.Skip(2).Select(l => l * 105)) .ToArray(); - foreach(var (n, l) in part.notes.Zip(lengths)){ + foreach (var (n, l) in part.notes.Zip(lengths)) { Assert.Equal(72, n.tone); Assert.Equal(l, n.duration); } } [Fact] - public void LyricsTest(){ + public void LyricsTest() { var project = MusicXML.LoadProject(Path.Join(basePath, "61a-Lyrics.musicxml")); var part = project.parts.First() as UVoicePart; Assert.Equal(0, part.notes.First().position); AssertLegato(part); var notesList = part.notes.ToList(); - foreach(var n in notesList[..^1]){ + foreach (var n in notesList[..^1]) { Assert.Equal(69, n.tone); Assert.Equal(480, n.duration); } diff --git a/OpenUtau.Test/Core/SignalChain/WaveSourceTest.cs b/OpenUtau.Test/Core/SignalChain/WaveSourceTest.cs index 1f544f077..90e4fcb29 100644 --- a/OpenUtau.Test/Core/SignalChain/WaveSourceTest.cs +++ b/OpenUtau.Test/Core/SignalChain/WaveSourceTest.cs @@ -1,8 +1,8 @@ -using Xunit; -using Xunit.Abstractions; -using System.IO; +using System.IO; using System.Reflection; using NAudio.Wave; +using Xunit; +using Xunit.Abstractions; namespace OpenUtau.Core.SignalChain { public class WaveSourceTest { diff --git a/OpenUtau.Test/Core/Util/Base64Test.cs b/OpenUtau.Test/Core/Util/Base64Test.cs index 13b09e529..69e5ef4c2 100644 --- a/OpenUtau.Test/Core/Util/Base64Test.cs +++ b/OpenUtau.Test/Core/Util/Base64Test.cs @@ -10,12 +10,12 @@ public void OnlyPointTest() { } [Fact] public void RunLengthTest() { - int[] data = { 0, 0}; - Assert.Equal("AA#1#",Base64.Base64EncodeInt12(data)); + int[] data = { 0, 0 }; + Assert.Equal("AA#1#", Base64.Base64EncodeInt12(data)); } [Fact] public void RunLength2Test() { - int[] data = { 0, 0,1,1 }; + int[] data = { 0, 0, 1, 1 }; Assert.Equal("AA#1#AB#1#", Base64.Base64EncodeInt12(data)); } [Fact] diff --git a/OpenUtau.Test/Plugins/EnArpaPlusTest.cs b/OpenUtau.Test/Plugins/EnArpaPlusTest.cs index d69694d11..660e59dfa 100644 --- a/OpenUtau.Test/Plugins/EnArpaPlusTest.cs +++ b/OpenUtau.Test/Plugins/EnArpaPlusTest.cs @@ -53,16 +53,18 @@ public void ColorTest() { } }, new string[] { "- hh_C3", "hh ay_W", "ay -_C3" }); } - public void SyllableTest(string lyric, string hint, string[] aliases) { - RunPhonemizeTest("en_arpa-plus", new NoteParams[] { new NoteParams { lyric = lyric, hint = hint, tone = "C3", phonemes = SamePhonemeParams(4, 0, 0, "") } }, aliases); - } + + // [Theory] + // public void SyllableTest(string lyric, string hint, string[] aliases) { + // RunPhonemizeTest("en_arpa-plus", new NoteParams[] { new NoteParams { lyric = lyric, hint = hint, tone = "C3", phonemes = SamePhonemeParams(4, 0, 0, "") } }, aliases); + // } + [Theory] [InlineData("read", "", new string[] { "- r_C3", "r eh_C3", "eh d_C3", "d -_C3" })] [InlineData("read", "r iy d", new string[] { "- r_C3", "r iy_C3", "iy d_C3", "d -_C3" })] [InlineData("asdfjkl", "r iy d", new string[] { "- r_C3", "r iy_C3", "iy d_C3", "d -_C3" })] [InlineData("", "r iy d", new string[] { "- r_C3", "r iy_C3", "iy d_C3", "d -_C3" })] - public void SyllableExternalEndingTest(string lyric, string hint, string[] aliases) { RunPhonemizeTest("en_arpa-plus", new NoteParams[] { new NoteParams { lyric = lyric, hint = hint, tone = "C3", phonemes = SamePhonemeParams(4, 0, 0, "") } }, aliases); } @@ -82,10 +84,10 @@ public void SyllableFallbackTest(string lyric, string hint, string[] aliases) { } [Theory] [InlineData("kroidroi", "", new string[] { "- kr_C3", "kr oy_C3", "iy dr_C3", "dr oy_C3", "oy -_C3" })] - [InlineData("whhat", "", new string[] { "- hh_C3", "hh uw_C3", "w ah_C3", "ah t_C3", "t -_C3" })] + [InlineData("whhat", "", new string[] { "- hh_C3", "hh uw_C3", "w ah_C3", "ah t_C3", "t -_C3" })] public void HintTest(string lyric, string hint, string[] aliases) { - RunPhonemizeTest("en_arpa-plus", new NoteParams[] { new NoteParams { lyric = lyric, hint = hint, tone = "C3", phonemes = SamePhonemeParams(4, 0, 0, "")} }, aliases); + RunPhonemizeTest("en_arpa-plus", new NoteParams[] { new NoteParams { lyric = lyric, hint = hint, tone = "C3", phonemes = SamePhonemeParams(4, 0, 0, "") } }, aliases); } } -} \ No newline at end of file +} diff --git a/OpenUtau.Test/Plugins/EnArpaTest.cs b/OpenUtau.Test/Plugins/EnArpaTest.cs index 2ee08792c..c8c797f69 100644 --- a/OpenUtau.Test/Plugins/EnArpaTest.cs +++ b/OpenUtau.Test/Plugins/EnArpaTest.cs @@ -61,7 +61,7 @@ public void ColorTest() { [InlineData("asdfjkl", "r iy d", new string[] { "- r_3", "r iy_3", "iy d_3", "d -_3" })] [InlineData("", "r iy d", new string[] { "- r_3", "r iy_3", "iy d_3", "d -_3" })] public void HintTest(string lyric, string hint, string[] aliases) { - RunPhonemizeTest("en_arpa", new NoteParams[] { new NoteParams { lyric = lyric, hint = hint, tone = "C4", phonemes = SamePhonemeParams(4, 0, 0, "")} }, aliases); + RunPhonemizeTest("en_arpa", new NoteParams[] { new NoteParams { lyric = lyric, hint = hint, tone = "C4", phonemes = SamePhonemeParams(4, 0, 0, "") } }, aliases); } } } diff --git a/OpenUtau.Test/Plugins/EnToJaTest.cs b/OpenUtau.Test/Plugins/EnToJaTest.cs index 54b9ed9d5..8157b9826 100644 --- a/OpenUtau.Test/Plugins/EnToJaTest.cs +++ b/OpenUtau.Test/Plugins/EnToJaTest.cs @@ -1,10 +1,10 @@ -using System.Xml.Linq; -using System; +using System; +using System.Linq; +using System.Xml.Linq; using OpenUtau.Api; using OpenUtau.Plugin.Builtin; using Xunit; using Xunit.Abstractions; -using System.Linq; namespace OpenUtau.Plugins { public class EnToJaTest : PhonemizerTestBase { @@ -44,10 +44,10 @@ public void MultipitchTest(string singerName, string[] tones, string[] aliases) new string[] { "- ごCA3", "o うA3" })] public void VoiceColorTest(string singerName, string color, string[] aliases) { RunPhonemizeTest(singerName, new NoteParams[] { - new NoteParams { - lyric = "go", - hint = "", - tone = "C4", + new NoteParams { + lyric = "go", + hint = "", + tone = "C4", phonemes = new PhonemeParams[] { new PhonemeParams { shift = 0, diff --git a/OpenUtau.Test/Plugins/EnXSampaTest.cs b/OpenUtau.Test/Plugins/EnXSampaTest.cs index 536bb5ec0..a8dae314c 100644 --- a/OpenUtau.Test/Plugins/EnXSampaTest.cs +++ b/OpenUtau.Test/Plugins/EnXSampaTest.cs @@ -49,7 +49,7 @@ public void ToneShiftTest() { [InlineData("read", "r i d", new string[] { "- ri", "i d-" })] [InlineData("asdfjkl", "r i d", new string[] { "- ri", "i d-" })] - [InlineData("", "r i d", new string[] {"- ri", "i d-" })] + [InlineData("", "r i d", new string[] { "- ri", "i d-" })] public void HintTest(string lyric, string hint, string[] aliases) { RunPhonemizeTest("en_delta0", new NoteParams[] { new NoteParams { lyric = lyric, hint = hint, tone = "C4", phonemes = SamePhonemeParams(4, 0, 0, "") } }, aliases); } diff --git a/OpenUtau.Test/Plugins/JaCvvcTest.cs b/OpenUtau.Test/Plugins/JaCvvcTest.cs index e8282439a..b97d876df 100644 --- a/OpenUtau.Test/Plugins/JaCvvcTest.cs +++ b/OpenUtau.Test/Plugins/JaCvvcTest.cs @@ -33,7 +33,7 @@ public void PhonemizeTest(string singerName, string[] lyrics, string[] tones, st [Fact] public void ColorTest() { - RunPhonemizeTest("ja_cvvc", new NoteParams[] { + RunPhonemizeTest("ja_cvvc", new NoteParams[] { new NoteParams { lyric = "あ", hint = "", diff --git a/OpenUtau.Test/Plugins/JaPresampTest.cs b/OpenUtau.Test/Plugins/JaPresampTest.cs index 55127bd37..3bcddfd52 100644 --- a/OpenUtau.Test/Plugins/JaPresampTest.cs +++ b/OpenUtau.Test/Plugins/JaPresampTest.cs @@ -95,7 +95,7 @@ public void CvGlottalTest() { }, ["あ", "あ", "か_CVVC_C4", "a ・_CVVC_C4", "・ あ_CVVC_C4", "a k_CVVC_C4", "か_CVVC_C4", "a あ・_VCV_D4", "a た_VCV_D4", "a あ・_VCV_D4", "a R_VCV_D4"]); } - + // CVVC [Fact] public void CvvcTest() { diff --git a/OpenUtau.Test/Plugins/PhonemizerTestBase.cs b/OpenUtau.Test/Plugins/PhonemizerTestBase.cs index 41dedc2be..f65a5f3e9 100644 --- a/OpenUtau.Test/Plugins/PhonemizerTestBase.cs +++ b/OpenUtau.Test/Plugins/PhonemizerTestBase.cs @@ -39,7 +39,7 @@ public void RunPhonemizeTest(string singerName, string[] lyrics, string[] alts, public void RunPhonemizeTest(string singerName, NoteParams[] inputs, string[] aliases) { var groups = GetMultiPhonemeNotes(inputs); - RunPhonemizeTest(singerName,groups, aliases); + RunPhonemizeTest(singerName, groups, aliases); } void RunPhonemizeTest(string singerName, List groups, string[] aliases) { @@ -142,7 +142,7 @@ void RunPhonemizeTest(string singerName, List groups, string[ group.Clear(); } var attr = new Phonemizer.PhonemeAttributes[noteParams.phonemes.Length]; - for (var j = 0;j < noteParams.phonemes.Length; j++) { + for (var j = 0; j < noteParams.phonemes.Length; j++) { var phonemeParams = noteParams.phonemes[j]; attr[j] = new Phonemizer.PhonemeAttributes { index = j, diff --git a/OpenUtau.Test/Plugins/ZhCvvcTest.cs b/OpenUtau.Test/Plugins/ZhCvvcTest.cs index 9423226e1..fc450bb3a 100644 --- a/OpenUtau.Test/Plugins/ZhCvvcTest.cs +++ b/OpenUtau.Test/Plugins/ZhCvvcTest.cs @@ -1,11 +1,10 @@ -using OpenUtau.Api; +using OpenUtau.Api; using OpenUtau.Plugin.Builtin; using Xunit; using Xunit.Abstractions; -namespace OpenUtau.Plugins -{ - public class ZhCvvcTest : PhonemizerTestBase{ +namespace OpenUtau.Plugins { + public class ZhCvvcTest : PhonemizerTestBase { public ZhCvvcTest(ITestOutputHelper output) : base(output) { } protected override Phonemizer CreatePhonemizer() { @@ -48,7 +47,7 @@ protected override Phonemizer CreatePhonemizer() { new string[] { "F4", "F4", "F4", "F4" }, new string[] { "", "", "", "" }, new string[] { "- jiF4", "i nyF4", "niF4", "i tF4", "taiF4", "ai mF4", "meiF4", "ei RF4" })] - + public void PhonemizeTest(string singerName, string[] lyrics, string[] alts, string[] tones, string[] colors, string[] aliases) { RunPhonemizeTest(singerName, lyrics, alts, tones, colors, aliases); } diff --git a/OpenUtau/Controls/FavouriteToggleButton.cs b/OpenUtau/Controls/FavouriteToggleButton.cs index e1ffcc931..fbffdb374 100644 --- a/OpenUtau/Controls/FavouriteToggleButton.cs +++ b/OpenUtau/Controls/FavouriteToggleButton.cs @@ -3,38 +3,32 @@ using Avalonia.Media; using OpenUtau.App; -public class FavouriteToggleButton : ToggleButton -{ +public class FavouriteToggleButton : ToggleButton { private readonly Path _iconPath; - public FavouriteToggleButton() - { + public FavouriteToggleButton() { //this.Height = 20; //this.Width = 20; // Create icon Path. - _iconPath = new Path - { + _iconPath = new Path { Fill = SolidColorBrush.Parse("#00000000"), Stroke = ThemeManager.AccentBrush3, StrokeThickness = 2, Data = Geometry.Parse("M12,21.35L10.55,20.03C5.4,15.36,2,12.28,2,8.5C2,5.42,4.42,3,7.5,3C9.24,3,10.91,3.81,12,5.09C13.09,3.81,14.76,3,16.5,3C19.58,3,22,5.42,22,8.5C22,12.28,18.6,15.36,13.45,20.04L12,21.35Z"), - RenderTransform = new ScaleTransform { ScaleX = 0.6,ScaleY = 0.6} + RenderTransform = new ScaleTransform { ScaleX = 0.6, ScaleY = 0.6 } }; this.Content = _iconPath; // Change icon on click. - this.PropertyChanged += (sender, e) => - { - if (e.Property == IsCheckedProperty) - { + this.PropertyChanged += (sender, e) => { + if (e.Property == IsCheckedProperty) { UpdateIcon(IsChecked ?? false); } }; } - private void UpdateIcon(bool isChecked) - { + private void UpdateIcon(bool isChecked) { if (isChecked) { _iconPath.Fill = ThemeManager.AccentBrush3; } else { diff --git a/OpenUtau/Controls/NotePropertiesControl.axaml.cs b/OpenUtau/Controls/NotePropertiesControl.axaml.cs index 3344b4af8..2d2b360b0 100644 --- a/OpenUtau/Controls/NotePropertiesControl.axaml.cs +++ b/OpenUtau/Controls/NotePropertiesControl.axaml.cs @@ -29,10 +29,10 @@ public NotePropertiesControl() { slider.AddHandler(PointerReleasedEvent, SliderPointerReleased, RoutingStrategies.Tunnel); slider.AddHandler(PointerMovedEvent, SliderPointerMoved, RoutingStrategies.Tunnel); }); - + MessageBus.Current.Listen() .Subscribe(e => { - if(e.refreshItem == "Part") { + if (e.refreshItem == "Part") { LoadPart(ViewModel.Part); } }); @@ -60,7 +60,7 @@ private void LoadPart(UPart? part) { private string textBoxValue = string.Empty; void OnTextBoxGotFocus(object? sender, GotFocusEventArgs args) { Log.Debug("Note property textbox got focus"); - if(sender is TextBox text) { + if (sender is TextBox text) { textBoxValue = text.Text ?? string.Empty; } } diff --git a/OpenUtau/Controls/NotePropertyExpression.axaml.cs b/OpenUtau/Controls/NotePropertyExpression.axaml.cs index c8d3c379d..6a367a699 100644 --- a/OpenUtau/Controls/NotePropertyExpression.axaml.cs +++ b/OpenUtau/Controls/NotePropertyExpression.axaml.cs @@ -10,7 +10,7 @@ public partial class NotePropertyExpression : UserControl { public NotePropertyExpression() { InitializeComponent(); - + slider.AddHandler(PointerPressedEvent, SliderPointerPressed, RoutingStrategies.Tunnel); slider.AddHandler(PointerReleasedEvent, SliderPointerReleased, RoutingStrategies.Tunnel); slider.AddHandler(PointerMovedEvent, SliderPointerMoved, RoutingStrategies.Tunnel); diff --git a/OpenUtau/Controls/PartControl.cs b/OpenUtau/Controls/PartControl.cs index 2014e2a41..71b42297f 100644 --- a/OpenUtau/Controls/PartControl.cs +++ b/OpenUtau/Controls/PartControl.cs @@ -2,18 +2,18 @@ using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; using Avalonia; -using Avalonia.Media; using Avalonia.Controls; using Avalonia.Controls.Primitives; +using Avalonia.Media; +using Avalonia.Media.Imaging; +using NWaves.Signals; using OpenUtau.Core.Ustx; using ReactiveUI; -using Avalonia.Media.Imaging; -using System.Runtime.InteropServices; -using System.Threading.Tasks; using Serilog; -using System.Threading; -using NWaves.Signals; namespace OpenUtau.App.Controls { class PartControl : Control, IDisposable, IProgress { diff --git a/OpenUtau/Controls/PhonemeCanvas.cs b/OpenUtau/Controls/PhonemeCanvas.cs index 40964db6b..db96cf98e 100644 --- a/OpenUtau/Controls/PhonemeCanvas.cs +++ b/OpenUtau/Controls/PhonemeCanvas.cs @@ -164,7 +164,7 @@ public override void Render(DrawingContext context) { if (viewModel.TickWidth > ViewConstants.PianoRollTickWidthShowDetails) { string phonemeText = !string.IsNullOrEmpty(phoneme.phonemeMapped) ? phoneme.phonemeMapped : phoneme.phoneme; if (!string.IsNullOrEmpty(phonemeText)) { - (double textX, double textY, Size size, TextLayout textLayout) + (double textX, double textY, Size size, TextLayout textLayout) = PhonemeUIRender.AliasPosition(viewModel, phoneme, langCode, ref lastTextEndX, ref raiseText); using (var state = context.PushTransform(Matrix.CreateTranslation(textX + 2, textY))) { var pen = mouseoverPhoneme == phoneme ? ThemeManager.AccentPen1Thickness2 : ThemeManager.NeutralAccentPenSemi; diff --git a/OpenUtau/Controls/PhonemeUIRender.cs b/OpenUtau/Controls/PhonemeUIRender.cs index 91fa9b14d..d8a64ff7b 100644 --- a/OpenUtau/Controls/PhonemeUIRender.cs +++ b/OpenUtau/Controls/PhonemeUIRender.cs @@ -1,4 +1,4 @@ -using Avalonia; +using Avalonia; using Avalonia.Media.TextFormatting; using OpenUtau.App.ViewModels; using OpenUtau.Core; @@ -7,8 +7,8 @@ using OpenUtau.Core.Util; namespace OpenUtau.App.Controls { - static class PhonemeUIRender{ - public static string getLangCode(UVoicePart part){ + static class PhonemeUIRender { + public static string getLangCode(UVoicePart part) { int trackNo = part.trackNo; var track = DocManager.Inst.Project.tracks[trackNo]; string langCode = ""; @@ -22,11 +22,11 @@ public static string getLangCode(UVoicePart part){ //Calculates the position of a phoneme alias on a piano roll view, //considering factors like tick width, phoneme text, and text layout. //It returns the x-coordinate and text y-coordinate of the alias - public static (double textX, double textY, Size size, TextLayout textLayout) - AliasPosition(NotesViewModel viewModel, UPhoneme phoneme, string? langCode, ref double lastTextEndX, ref bool raiseText){ + public static (double textX, double textY, Size size, TextLayout textLayout) + AliasPosition(NotesViewModel viewModel, UPhoneme phoneme, string? langCode, ref double lastTextEndX, ref bool raiseText) { string phonemeText = !string.IsNullOrEmpty(phoneme.phonemeMapped) ? phoneme.phonemeMapped : phoneme.phoneme; - if (Preferences.Default.DiffSingerLangCodeHide && !string.IsNullOrEmpty(langCode) && phonemeText.StartsWith(langCode+"/")) { + if (Preferences.Default.DiffSingerLangCodeHide && !string.IsNullOrEmpty(langCode) && phonemeText.StartsWith(langCode + "/")) { phonemeText = phonemeText.Substring(langCode.Length + 1); } var x = viewModel.TickToneToPoint(phoneme.position, 0).X; diff --git a/OpenUtau/Controls/PropertyEditors/FloatEditor.cs b/OpenUtau/Controls/PropertyEditors/FloatEditor.cs index 22306110e..f344c1047 100644 --- a/OpenUtau/Controls/PropertyEditors/FloatEditor.cs +++ b/OpenUtau/Controls/PropertyEditors/FloatEditor.cs @@ -6,9 +6,8 @@ using Avalonia.Interactivity; using ReactiveUI; -namespace OpenUtau.Controls{ - public class FloatEditor : TextBox - { +namespace OpenUtau.Controls { + public class FloatEditor : TextBox { protected override Type StyleKeyOverride => typeof(TextBox); public static readonly DirectProperty ValueProperty = AvaloniaProperty.RegisterDirect( @@ -18,45 +17,38 @@ public class FloatEditor : TextBox defaultBindingMode: BindingMode.TwoWay); private float _value = 0; - public FloatEditor() - { + public FloatEditor() { Text = "0"; this.WhenAnyValue(x => x.Text) - .Subscribe((text => { + .Subscribe((text => { OnTextChanged(text); })); } - public float Value - { + public float Value { get => _value; - set - { - if (SetAndRaise(ValueProperty, ref _value, value)) - { + set { + if (SetAndRaise(ValueProperty, ref _value, value)) { Text = value.ToString(); } } } - protected void OnTextChanged(string? newText) - { - if (!IsKeyboardFocusWithin){ + protected void OnTextChanged(string? newText) { + if (!IsKeyboardFocusWithin) { return; } - if( newText != null && float.TryParse(newText, out float newValue)) - { - Value = newValue; + if (newText != null && float.TryParse(newText, out float newValue)) { + Value = newValue; } } protected override void OnLostFocus(RoutedEventArgs e) { base.OnLostFocus(e); - if (!float.TryParse(Text, out float newValue)) - { + if (!float.TryParse(Text, out float newValue)) { Text = Value.ToString(); } } } -} \ No newline at end of file +} diff --git a/OpenUtau/Controls/PropertyEditors/IntEditor.cs b/OpenUtau/Controls/PropertyEditors/IntEditor.cs index 5cffa2c66..24dfce4be 100644 --- a/OpenUtau/Controls/PropertyEditors/IntEditor.cs +++ b/OpenUtau/Controls/PropertyEditors/IntEditor.cs @@ -1,4 +1,4 @@ -using System; +using System; using Avalonia; using Avalonia.Controls; @@ -6,9 +6,8 @@ using Avalonia.Interactivity; using ReactiveUI; -namespace OpenUtau.Controls{ - public class IntEditor : TextBox - { +namespace OpenUtau.Controls { + public class IntEditor : TextBox { protected override Type StyleKeyOverride => typeof(TextBox); public static readonly DirectProperty ValueProperty = AvaloniaProperty.RegisterDirect( @@ -18,45 +17,38 @@ public class IntEditor : TextBox defaultBindingMode: BindingMode.TwoWay); private int _value = 0; - public IntEditor() - { + public IntEditor() { Text = "0"; this.WhenAnyValue(x => x.Text) - .Subscribe((text => { + .Subscribe((text => { OnTextChanged(text); })); } - public int Value - { + public int Value { get => _value; - set - { - if (SetAndRaise(ValueProperty, ref _value, value)) - { + set { + if (SetAndRaise(ValueProperty, ref _value, value)) { Text = value.ToString() ?? ""; } } } - protected void OnTextChanged(string? newText) - { - if (!IsKeyboardFocusWithin){ + protected void OnTextChanged(string? newText) { + if (!IsKeyboardFocusWithin) { return; } - if( newText != null && int.TryParse(newText, out int newValue)) - { - Value = newValue; + if (newText != null && int.TryParse(newText, out int newValue)) { + Value = newValue; } } protected override void OnLostFocus(RoutedEventArgs e) { base.OnLostFocus(e); - if (!int.TryParse(Text, out int newValue)) - { + if (!int.TryParse(Text, out int newValue)) { Text = Value.ToString(); } } } -} \ No newline at end of file +} diff --git a/OpenUtau/Controls/SearchBar.axaml.cs b/OpenUtau/Controls/SearchBar.axaml.cs index 90efb2b92..eb9352f52 100644 --- a/OpenUtau/Controls/SearchBar.axaml.cs +++ b/OpenUtau/Controls/SearchBar.axaml.cs @@ -60,17 +60,17 @@ private void Box_GotFocus(object? sender, GotFocusEventArgs e) { box.SelectAll(); } - private void Box_KeyDown(object? sender, KeyEventArgs e){ - if(!IsVisible){ + private void Box_KeyDown(object? sender, KeyEventArgs e) { + if (!IsVisible) { return; } bool isShift = e.KeyModifiers == KeyModifiers.Shift; - switch (e.Key){ + switch (e.Key) { case Key.Enter: - if (DataContext is SearchNoteViewModel viewModel){ - if(isShift){ + if (DataContext is SearchNoteViewModel viewModel) { + if (isShift) { viewModel.Prev(); - }else{ + } else { viewModel.Next(); } } diff --git a/OpenUtau/Controls/TrackBackground.cs b/OpenUtau/Controls/TrackBackground.cs index 27425b2ee..3d7786a7a 100644 --- a/OpenUtau/Controls/TrackBackground.cs +++ b/OpenUtau/Controls/TrackBackground.cs @@ -78,7 +78,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang } } - int mod(int a, int b){ + int mod(int a, int b) { return (a % b + b) % b; } @@ -89,7 +89,7 @@ public override void Render(DrawingContext context) { int track = (int)TrackOffset; double top = TrackHeight * (track - TrackOffset); string[] degreeNames; - switch(Preferences.Default.DegreeStyle){ + switch (Preferences.Default.DegreeStyle) { case 1: degreeNames = MusicMath.Solfeges; break; diff --git a/OpenUtau/Controls/TrackHeaderCanvas.cs b/OpenUtau/Controls/TrackHeaderCanvas.cs index ca716e8fd..770d64469 100644 --- a/OpenUtau/Controls/TrackHeaderCanvas.cs +++ b/OpenUtau/Controls/TrackHeaderCanvas.cs @@ -90,7 +90,7 @@ public TrackHeaderCanvas() { .Subscribe(e => { foreach (var (track, header) in trackHeaders) { if (header.ViewModel != null) { - if(e.trackNo == -1) { + if (e.trackNo == -1) { header.ViewModel.ToggleMute(e.allmute); } else if (track.TrackNo == e.trackNo) { header.ViewModel.ToggleMute(); diff --git a/OpenUtau/FilePicker.cs b/OpenUtau/FilePicker.cs index 4ffdceaa4..05648b97b 100644 --- a/OpenUtau/FilePicker.cs +++ b/OpenUtau/FilePicker.cs @@ -169,7 +169,7 @@ public async static Task SaveFile public async static Task SaveFileAboutProject (Window window, string titleKey, params FilePickerFileType[] types) { - var path = await SaveFile(window, titleKey, Preferences.Default.RecentOpenProjectDirectory, + var path = await SaveFile(window, titleKey, Preferences.Default.RecentOpenProjectDirectory, Path.GetFileName(Path.ChangeExtension(DocManager.Inst.Project.FilePath, null)), types); var dir = Path.GetDirectoryName(path); if (dir != null) { diff --git a/OpenUtau/Program.cs b/OpenUtau/Program.cs index 30f8036c4..37bf2d9b2 100644 --- a/OpenUtau/Program.cs +++ b/OpenUtau/Program.cs @@ -55,8 +55,7 @@ public static void Main(string[] args) { public static AppBuilder BuildAvaloniaApp() { FontManagerOptions fontOptions = new(); if (OS.IsLinux()) { - using Process process = Process.Start(new ProcessStartInfo("fc-match") - { + using Process process = Process.Start(new ProcessStartInfo("fc-match") { ArgumentList = { "-f", "%{family}" }, RedirectStandardOutput = true })!; @@ -64,7 +63,7 @@ public static AppBuilder BuildAvaloniaApp() { string fontFamily = process.StandardOutput.ReadToEnd(); if (!string.IsNullOrEmpty(fontFamily)) { - string [] fontFamilies = fontFamily.Split(','); + string[] fontFamilies = fontFamily.Split(','); fontOptions.DefaultFamilyName = fontFamilies[0]; } } @@ -73,7 +72,7 @@ public static AppBuilder BuildAvaloniaApp() { .LogToTrace() .UseReactiveUI() .With(fontOptions) - .With(new X11PlatformOptions {EnableIme = true}); + .With(new X11PlatformOptions { EnableIme = true }); } public static void Run(string[] args) diff --git a/OpenUtau/ThemeManager.cs b/OpenUtau/ThemeManager.cs index 491afabff..a084fab46 100644 --- a/OpenUtau/ThemeManager.cs +++ b/OpenUtau/ThemeManager.cs @@ -158,7 +158,7 @@ public static void ChangePianorollColor(string color) { try { IResourceDictionary resDict = Application.Current.Resources; TrackColor tcolor = GetTrackColor(color); - + resDict["SelectedTrackAccentBrush"] = tcolor.AccentColor; resDict["SelectedTrackAccentLightBrush"] = tcolor.AccentColorLight; resDict["SelectedTrackAccentLightBrushSemi"] = tcolor.AccentColorLightSemi; diff --git a/OpenUtau/ViewLocator.cs b/OpenUtau/ViewLocator.cs index 48a030656..eed8b4324 100644 --- a/OpenUtau/ViewLocator.cs +++ b/OpenUtau/ViewLocator.cs @@ -1,7 +1,7 @@ -using Avalonia.Controls; +using System; +using Avalonia.Controls; using Avalonia.Controls.Templates; using OpenUtau.App.ViewModels; -using System; namespace OpenUtau.App { public class ViewLocator : IDataTemplate { diff --git a/OpenUtau/ViewModels/ExeSetupViewModel.cs b/OpenUtau/ViewModels/ExeSetupViewModel.cs index 00a06c7bd..99ed77bf2 100644 --- a/OpenUtau/ViewModels/ExeSetupViewModel.cs +++ b/OpenUtau/ViewModels/ExeSetupViewModel.cs @@ -9,7 +9,7 @@ public ExeSetupViewModel(string filePath) { message = string.Format(ThemeManager.GetString("exesetup.installing"), filePath); if (OS.IsMacOS()) { message += "\n\n" + ThemeManager.GetString("exesetup.mac"); - } else if(OS.IsLinux()) { + } else if (OS.IsLinux()) { message += "\n\n" + string.Format(ThemeManager.GetString("exesetup.linux"), "https://www.winehq.org/"); } } diff --git a/OpenUtau/ViewModels/ExpSelectorViewModel.cs b/OpenUtau/ViewModels/ExpSelectorViewModel.cs index a9c22d7e1..ef836698f 100644 --- a/OpenUtau/ViewModels/ExpSelectorViewModel.cs +++ b/OpenUtau/ViewModels/ExpSelectorViewModel.cs @@ -16,7 +16,7 @@ public class ExpSelectorViewModel : ViewModelBase, ICmdSubscriber { [Reactive] public ExpDisMode DisplayMode { get; set; } [Reactive] public UExpressionDescriptor? Descriptor { get; set; } public string Abbr { - get{ + get { if (Descriptor == null) { return ""; } @@ -52,7 +52,7 @@ public ExpSelectorViewModel() { } public bool SetExp(string abbr) { - if(Descriptors.Any(d => d.abbr == abbr)) { + if (Descriptors.Any(d => d.abbr == abbr)) { Descriptor = Descriptors.First(d => d.abbr == abbr); return true; } else { @@ -67,7 +67,7 @@ public void OnSelected(bool store) { if (DisplayMode != ExpDisMode.Visible && Descriptor != null) { DocManager.Inst.ExecuteCmd(new SelectExpressionNotification(Descriptor.abbr, Index, true)); } - if(store) { + if (store) { var project = DocManager.Inst.Project; project.expSecondary = project.expPrimary; project.expPrimary = Index; diff --git a/OpenUtau/ViewModels/MainWindowViewModel.cs b/OpenUtau/ViewModels/MainWindowViewModel.cs index ca98cce5e..8c10ed30f 100644 --- a/OpenUtau/ViewModels/MainWindowViewModel.cs +++ b/OpenUtau/ViewModels/MainWindowViewModel.cs @@ -45,7 +45,7 @@ public class MainWindowViewModel : ViewModelBase, ICmdSubscriber { public string Title => !ProjectSaved ? $"{AppVersion}" : $"{(DocManager.Inst.ChangesSaved ? "" : "*")}{AppVersion} [{DocManager.Inst.Project.FilePath}]"; - + /// ///0: welcome page, 1: tracks page /// @@ -128,7 +128,7 @@ public async void InitProject(MainWindow window) { return; } } - + var args = Environment.GetCommandLineArgs(); if (args.Length == 2 && File.Exists(args[1])) { try { @@ -206,7 +206,7 @@ public void SaveProject(string file = "") { this.RaisePropertyChanged(nameof(Title)); } - public void ImportTracks(UProject[] loadedProjects, bool importTempo){ + public void ImportTracks(UProject[] loadedProjects, bool importTempo) { if (loadedProjects == null || loadedProjects.Length < 1) { return; } @@ -251,7 +251,7 @@ public void ImportMidi(string file) { var track = new UTrack(project); track.TrackNo = project.tracks.Count; part.trackNo = track.TrackNo; - if(part.name != "New Part"){ + if (part.name != "New Part") { track.TrackName = part.name; } part.AfterLoad(project, track); @@ -337,7 +337,7 @@ public void RefreshTimelineContextMenu(int tick) { /// Remap a tick position from the old time axis to the new time axis without changing its absolute position (in ms). /// Note that this can only be used on positions, not durations. /// - private int RemapTickPos(int tickPos, TimeAxis oldTimeAxis, TimeAxis newTimeAxis){ + private int RemapTickPos(int tickPos, TimeAxis oldTimeAxis, TimeAxis newTimeAxis) { double msPos = oldTimeAxis.TickPosToMsPos(tickPos); return newTimeAxis.MsPosToTickPos(msPos); } @@ -346,41 +346,41 @@ private int RemapTickPos(int tickPos, TimeAxis oldTimeAxis, TimeAxis newTimeAxis /// Remap the starting and ending positions of all the notes and parts in the whole project /// from the old time axis to the new time axis, without changing their absolute positions in ms. /// - public void RemapTimeAxis(TimeAxis oldTimeAxis, TimeAxis newTimeAxis){ + public void RemapTimeAxis(TimeAxis oldTimeAxis, TimeAxis newTimeAxis) { var project = DocManager.Inst.Project; - foreach(var part in project.parts){ + foreach (var part in project.parts) { var partOldStartTick = part.position; var partNewStartTick = RemapTickPos(part.position, oldTimeAxis, newTimeAxis); - if(partNewStartTick != partOldStartTick){ + if (partNewStartTick != partOldStartTick) { DocManager.Inst.ExecuteCmd(new MovePartCommand( project, part, partNewStartTick, part.trackNo)); } - if(part is UVoicePart voicePart){ + if (part is UVoicePart voicePart) { var partOldDuration = voicePart.Duration; var partNewDuration = RemapTickPos(partOldStartTick + voicePart.duration, oldTimeAxis, newTimeAxis) - partNewStartTick; - if(partNewDuration != partOldDuration) { + if (partNewDuration != partOldDuration) { DocManager.Inst.ExecuteCmd(new ResizePartCommand( project, voicePart, partNewDuration - partOldDuration, false)); } var noteCommands = new List(); - foreach(var note in voicePart.notes){ + foreach (var note in voicePart.notes) { var noteOldStartTick = note.position + partOldStartTick; var noteOldEndTick = note.End + partOldStartTick; var noteOldDuration = note.duration; var noteNewStartTick = RemapTickPos(noteOldStartTick, oldTimeAxis, newTimeAxis); var noteNewEndTick = RemapTickPos(noteOldEndTick, oldTimeAxis, newTimeAxis); var deltaPosTickInPart = (noteNewStartTick - partNewStartTick) - (noteOldStartTick - partOldStartTick); - if(deltaPosTickInPart != 0){ + if (deltaPosTickInPart != 0) { noteCommands.Add(new MoveNoteCommand(voicePart, note, deltaPosTickInPart, 0)); } var noteNewDuration = noteNewEndTick - noteNewStartTick; var deltaDur = noteNewDuration - noteOldDuration; - if(deltaDur != 0){ + if (deltaDur != 0) { noteCommands.Add(new ResizeNoteCommand(voicePart, note, deltaDur)); } //TODO: expression curve remapping, phoneme timing remapping } - foreach(var command in noteCommands){ + foreach (var command in noteCommands) { DocManager.Inst.ExecuteCmd(command); } } diff --git a/OpenUtau/ViewModels/MenuItemViewModel.cs b/OpenUtau/ViewModels/MenuItemViewModel.cs index c4a97cc5c..2389cf1fe 100644 --- a/OpenUtau/ViewModels/MenuItemViewModel.cs +++ b/OpenUtau/ViewModels/MenuItemViewModel.cs @@ -18,7 +18,7 @@ public class MenuItemViewModel { public class SingerMenuItemViewModel : MenuItemViewModel { public bool IsFavourite { get { - if(CommandParameter is USinger singer) { + if (CommandParameter is USinger singer) { return singer.IsFavourite; } return false; @@ -32,11 +32,11 @@ public bool IsFavourite { private object? _icon; public object? Icon { get { - if(_icon == null) { + if (_icon == null) { if (CommandParameter is USinger) { _icon = new FavouriteToggleButton() { [!FavouriteToggleButton.IsCheckedProperty] = new Binding("IsFavourite") - + }; } } diff --git a/OpenUtau/ViewModels/MergeVoicebankViewModel.cs b/OpenUtau/ViewModels/MergeVoicebankViewModel.cs index 7a86cbfaa..e6791af34 100644 --- a/OpenUtau/ViewModels/MergeVoicebankViewModel.cs +++ b/OpenUtau/ViewModels/MergeVoicebankViewModel.cs @@ -1,37 +1,37 @@ -using Serilog; -using System; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; -using ReactiveUI.Fody.Helpers; +using DynamicData; using OpenUtau.Classic; using OpenUtau.Core; using OpenUtau.Core.Ustx; +using ReactiveUI.Fody.Helpers; +using Serilog; using SharpCompress; -using DynamicData; namespace OpenUtau.App.ViewModels { - public class ConvertItem{ + public class ConvertItem { public string Name { get; set; } public string NewName { get; set; } - public ConvertItem(string name){ + public ConvertItem(string name) { Name = name; NewName = name; } - public ConvertItem(string name, string newName){ + public ConvertItem(string name, string newName) { Name = name; NewName = newName; } - public override string ToString(){ + public override string ToString() { return $"{Name} -> {NewName}"; } } public class MergeVoicebankViewModel : ViewModelBase { [Reactive] public int Step { get; set; } - public List Voicebanks{ get; set; } + public List Voicebanks { get; set; } public ClassicSinger thisSinger; [Reactive] public ClassicSinger? OtherSinger { get; set; } List existingDirs = new List(); @@ -43,7 +43,7 @@ public class MergeVoicebankViewModel : ViewModelBase { List existingVoiceColors = new List(); [Reactive] public ObservableCollection VoiceColorRenames { get; set; } [Reactive] public string VoiceColorNameErrors { get; set; } = ""; - string[] supportedAudioTypes = new string[]{".wav", ".flac", ".ogg", ".mp3", ".aiff", ".aif", ".aifc"}; + string[] supportedAudioTypes = new string[] { ".wav", ".flac", ".ogg", ".mp3", ".aiff", ".aif", ".aifc" }; public MergeVoicebankViewModel(ClassicSinger thisVoicebank) { this.thisSinger = thisVoicebank; Step = 0; @@ -62,23 +62,23 @@ public MergeVoicebankViewModel(ClassicSinger thisVoicebank) { /// The name to suffix. /// The list of names to check against. /// The suffixed name. - string autoSuffix(string name, IList existingNames){ - if(!existingNames.Contains(name)){ + string autoSuffix(string name, IList existingNames) { + if (!existingNames.Contains(name)) { return name; } int i = 1; - while(existingNames.Contains(name + "_" + i)){ + while (existingNames.Contains(name + "_" + i)) { i++; } return name + "_" + i; } - public void Next(){ - if(OtherSinger == null){ + public void Next() { + if (OtherSinger == null) { return; } Step++; - if(Step == 1){ + if (Step == 1) { FolderRenames.Clear(); string l = thisSinger.Location; //For this voicebank, get all the directories and files in the voicebank's location (that file copied here can't use) @@ -91,36 +91,36 @@ public void Next(){ .Where(d => Directory.EnumerateFiles(d, "oto.ini", SearchOption.AllDirectories).Any()) .Select(d => Path.GetFileName(d)) .ToList(); - if(File.Exists(Path.Join(OtherSinger.Location, "oto.ini"))){ + if (File.Exists(Path.Join(OtherSinger.Location, "oto.ini"))) { FolderRenames.Add(new ConvertItem(".", autoSuffix(Path.GetFileName(OtherSinger.Location), existingDirs))); } - foreach(string dir in dirsToAdd){ + foreach (string dir in dirsToAdd) { FolderRenames.Add(new ConvertItem(dir, autoSuffix(dir, existingDirs))); } - } else if(Step == 2){ + } else if (Step == 2) { thisSinger.EnsureLoaded(); OtherSinger.EnsureLoaded(); SubbankRenames.Clear(); existingSubbanks = thisSinger.Subbanks.Select(b => $"{b.Prefix},{b.Suffix}").ToList(); List subbanksToAdd = OtherSinger.Subbanks.Select(b => $"{b.Prefix},{b.Suffix}").ToList(); - foreach(string subbank in subbanksToAdd){ + foreach (string subbank in subbanksToAdd) { SubbankRenames.Add(new ConvertItem(subbank, autoSuffix(subbank, existingSubbanks))); } - } else if(Step == 3){ + } else if (Step == 3) { VoiceColorRenames.Clear(); existingVoiceColors = thisSinger.Subbanks.Select(b => b.Color).Distinct().ToList(); List voiceColorsToAdd = OtherSinger.Subbanks.Select(b => b.Color).Distinct().ToList(); - foreach(string voiceColor in voiceColorsToAdd){ + foreach (string voiceColor in voiceColorsToAdd) { VoiceColorRenames.Add(new ConvertItem(voiceColor, autoSuffix(voiceColor, existingVoiceColors))); } } } - void ConvertOto(string fromPath, string toPath, List oldSubbanks, List newSubbanks){ - if(OtherSinger == null){ + void ConvertOto(string fromPath, string toPath, List oldSubbanks, List newSubbanks) { + if (OtherSinger == null) { return; } - if(!File.Exists(fromPath)){ + if (!File.Exists(fromPath)) { Log.Error($"File {fromPath} does not exist"); return; } @@ -128,7 +128,7 @@ void ConvertOto(string fromPath, string toPath, List oldSubbanks, List< var patterns = oldSubbanks.Select(subbank => new Regex($"^{Regex.Escape(subbank.Prefix)}(.*){Regex.Escape(subbank.Suffix)}$")) .ToList(); var otoSet = VoicebankLoader.ParseOtoSet(fromPath, OtherSinger.TextFileEncoding, OtherSinger.UseFilenameAsAlias); - foreach (var oto in otoSet.Otos){ + foreach (var oto in otoSet.Otos) { if (!oto.IsValid) { if (!string.IsNullOrEmpty(oto.Error)) { Log.Error(oto.Error); @@ -143,28 +143,28 @@ void ConvertOto(string fromPath, string toPath, List oldSubbanks, List< } } } - using (var stream = File.Open(toPath, FileMode.Create, FileAccess.Write)){ + using (var stream = File.Open(toPath, FileMode.Create, FileAccess.Write)) { VoicebankLoader.WriteOtoSet(otoSet, stream, thisSinger.TextFileEncoding); } } - Subbank ConvertSubBank(Subbank oldSubbank){ - var newName = SubbankRenames.First(r=>r.Name == $"{oldSubbank.Prefix},{oldSubbank.Suffix}").NewName; - var newColor = VoiceColorRenames.First(r=>r.Name == oldSubbank.Color).NewName; - if(newName.Contains(",")){ + Subbank ConvertSubBank(Subbank oldSubbank) { + var newName = SubbankRenames.First(r => r.Name == $"{oldSubbank.Prefix},{oldSubbank.Suffix}").NewName; + var newColor = VoiceColorRenames.First(r => r.Name == oldSubbank.Color).NewName; + if (newName.Contains(",")) { var n = newName.Split(","); - return new Subbank(){ + return new Subbank() { Prefix = n[0], Suffix = n[^1], Color = newColor, ToneRanges = oldSubbank.ToneRanges }; } else { - return new Subbank(){ + return new Subbank() { Prefix = "", Suffix = newName, Color = newColor, - ToneRanges = oldSubbank.ToneRanges + ToneRanges = oldSubbank.ToneRanges }; } } @@ -184,17 +184,14 @@ List CheckForConflicts(IList items, IList existingN .ToList(); } - public void CheckFolderNames() - { - var duplicates = CheckForDuplicates(FolderRenames, caseSensitive:false); - var conflicts = CheckForConflicts(FolderRenames, existingDirs, caseSensitive:false); + public void CheckFolderNames() { + var duplicates = CheckForDuplicates(FolderRenames, caseSensitive: false); + var conflicts = CheckForConflicts(FolderRenames, existingDirs, caseSensitive: false); FolderNameErrors = ""; - if (duplicates.Count > 0) - { + if (duplicates.Count > 0) { FolderNameErrors += $"Duplicate folder names: {string.Join(", ", duplicates)}\n"; } - if (conflicts.Count > 0) - { + if (conflicts.Count > 0) { FolderNameErrors += $"Folder names already existed: {string.Join(", ", conflicts)}\n"; } } @@ -221,30 +218,23 @@ public void CheckSubbankNames() { } } - public void CheckVoiceColorNames() - { + public void CheckVoiceColorNames() { var duplicates = CheckForDuplicates(VoiceColorRenames); var conflicts = CheckForConflicts(VoiceColorRenames, existingVoiceColors); VoiceColorNameErrors = ""; - if (duplicates.Count > 0) - { + if (duplicates.Count > 0) { VoiceColorNameErrors += $"Duplicate voice color names: {string.Join(", ", duplicates)}\n"; } - if (conflicts.Count > 0) - { + if (conflicts.Count > 0) { VoiceColorNameErrors += $"Voice color names already existed: {string.Join(", ", conflicts)}\n"; } } - public Task Merge() - { - return Task.Run(() => - { - try - { + public Task Merge() { + return Task.Run(() => { + try { Log.Information($"Merging voicebank {OtherSinger} to {thisSinger}"); - if (OtherSinger == null) - { + if (OtherSinger == null) { Log.Error("Voicebank merger: other singer is null"); return; } @@ -258,15 +248,12 @@ public Task Merge() .ToList(); var otosToConvert = new List(); var filesToCopy = new List(); - foreach (ConvertItem folder in FolderRenames) - { + foreach (ConvertItem folder in FolderRenames) { //Create folders Directory.CreateDirectory(Path.Join(thisSinger.Location, folder.NewName)); //Add oto.ini and audio files in one folder to list of files to copy, not recursive - void AddFolder(string fromDir, string toDir) - { - if (File.Exists(Path.Join(fromDir, "oto.ini"))) - { + void AddFolder(string fromDir, string toDir) { + if (File.Exists(Path.Join(fromDir, "oto.ini"))) { Directory.CreateDirectory(toDir); otosToConvert.Add(new ConvertItem( Path.Join(fromDir, "oto.ini"), @@ -280,12 +267,9 @@ void AddFolder(string fromDir, string toDir) } } - if (folder.Name == ".") - { + if (folder.Name == ".") { AddFolder(OtherSinger.Location, Path.Join(thisSinger.Location, folder.NewName)); - } - else - { + } else { string currentFolder = Path.Join(OtherSinger.Location, folder.Name); Directory.EnumerateFiles(currentFolder, "oto.ini", SearchOption.AllDirectories) .Select(d => Path.GetDirectoryName(d)!) @@ -295,14 +279,12 @@ void AddFolder(string fromDir, string toDir) var totalFiles = otosToConvert.Count + filesToCopy.Count; var progress = 0; //Convert oto.ini - foreach (ConvertItem oto in otosToConvert) - { + foreach (ConvertItem oto in otosToConvert) { DocManager.Inst.ExecuteCmd(new ProgressBarNotification(progress++ * 100.0 / totalFiles, $"{oto.NewName} <= {oto.Name}")); ConvertOto(oto.Name, oto.NewName, oldSubbanks, newSubbanks); } //Copy audio files - foreach (ConvertItem file in filesToCopy) - { + foreach (ConvertItem file in filesToCopy) { DocManager.Inst.ExecuteCmd(new ProgressBarNotification(progress++ * 100.0 / totalFiles, $"{file.NewName} <= {file.Name}")); File.Copy(file.Name, file.NewName, true); } @@ -316,19 +298,18 @@ void AddFolder(string fromDir, string toDir) bankConfig = VoicebankConfig.Load(stream); } } - } catch { + } catch { Log.Error($"Voicebank merger: failed to load character.yaml from {yamlFile}"); } - if (bankConfig == null) - { + if (bankConfig == null) { bankConfig = new VoicebankConfig(); } bankConfig.Subbanks = (thisSinger.Subbanks ?? new List()) .Select(s => s.subbank) .Concat(newSubbanks) .ToArray(); - foreach(var subbank in bankConfig.Subbanks) { - if(subbank.ToneRanges == null || subbank.ToneRanges.Length == 0) { + foreach (var subbank in bankConfig.Subbanks) { + if (subbank.ToneRanges == null || subbank.ToneRanges.Length == 0) { subbank.ToneRanges = ["C1-B7"]; } } @@ -340,8 +321,7 @@ void AddFolder(string fromDir, string toDir) var customEx = new MessageCustomizableException("Failed to merge voicebank", ": voicebank", e); DocManager.Inst.ExecuteCmd(new ErrorMessageNotification(customEx)); } finally { - new Task(() => - { + new Task(() => { DocManager.Inst.ExecuteCmd(new ProgressBarNotification(0, "")); DocManager.Inst.ExecuteCmd(new SingersChangedNotification()); }).Start(DocManager.Inst.MainScheduler); @@ -349,4 +329,4 @@ void AddFolder(string fromDir, string toDir) }); } } -} \ No newline at end of file +} diff --git a/OpenUtau/ViewModels/NoteDefaultsViewModel.cs b/OpenUtau/ViewModels/NoteDefaultsViewModel.cs index f8f15d5d9..07bb5ec95 100644 --- a/OpenUtau/ViewModels/NoteDefaultsViewModel.cs +++ b/OpenUtau/ViewModels/NoteDefaultsViewModel.cs @@ -59,7 +59,7 @@ public NoteDefaultsViewModel() { this.WhenAnyValue(vm => vm.DefaultLyric) .Subscribe(defaultLyric => { - if(defaultLyric == null){ + if (defaultLyric == null) { return; } NotePresets.Default.DefaultLyric = defaultLyric; @@ -67,7 +67,7 @@ public NoteDefaultsViewModel() { }); this.WhenAnyValue(vm => vm.SplittedLyric) .Subscribe(splittedLyric => { - if(splittedLyric == null){ + if (splittedLyric == null) { return; } NotePresets.Default.SplittedLyric = splittedLyric; diff --git a/OpenUtau/ViewModels/NoteSelectionViewModel.cs b/OpenUtau/ViewModels/NoteSelectionViewModel.cs index 661e1c404..83ebbeb0c 100644 --- a/OpenUtau/ViewModels/NoteSelectionViewModel.cs +++ b/OpenUtau/ViewModels/NoteSelectionViewModel.cs @@ -5,8 +5,8 @@ using OpenUtau.Core.Ustx; namespace OpenUtau.App.ViewModels { - public class NoteSelectionViewModel: IEnumerable { - public NoteSelectionViewModel() {} + public class NoteSelectionViewModel : IEnumerable { + public NoteSelectionViewModel() { } /// @@ -26,13 +26,13 @@ public NoteSelectionViewModel() {} /// The selection move/change point (either first/last of selection) /// public UNote? Head => IsReversed ? FirstOrDefault() : LastOrDefault(); - + public int Count => _notes.Count; public bool IsEmpty => _notes.Count == 0; private bool IsMultiple => _notes.Count > 1; public UNote? FirstOrDefault() { return _notes.FirstOrDefault(); } public UNote? LastOrDefault() { return _notes.LastOrDefault(); } - + /// /// Add note to selection /// @@ -259,7 +259,7 @@ public bool Resize(int delta) { if (_notes.Count == 1) { IsReversed = !isForwardMove; } - + // shrink selection if move is towards center bool isShrink = IsReversed ? isForwardMove : !isForwardMove; diff --git a/OpenUtau/ViewModels/NotesViewModel.cs b/OpenUtau/ViewModels/NotesViewModel.cs index 5b0323a94..5fdd673d5 100644 --- a/OpenUtau/ViewModels/NotesViewModel.cs +++ b/OpenUtau/ViewModels/NotesViewModel.cs @@ -319,9 +319,9 @@ private void UpdateSnapDiv() { SnapDivText = $"(1/{div})"; } - private void UpdateKey(){ + private void UpdateKey() { Key = userKey; - KeyText = "1="+MusicMath.KeysInOctave[userKey].Item1; + KeyText = "1=" + MusicMath.KeysInOctave[userKey].Item1; } public void OnXZoomed(Point position, double delta) { @@ -458,7 +458,7 @@ private Bitmap ResizePortrait(Bitmap Portrait, int PortraitHeight) { targetHeight = PortraitHeight; } int targetWidth = (int)Math.Round(targetHeight * Portrait.Size.Width / Portrait.Size.Height); - if(targetWidth == 0){ + if (targetWidth == 0) { targetWidth = 1; } return Portrait.CreateScaledBitmap(new PixelSize(targetWidth, targetHeight)); @@ -511,7 +511,7 @@ private void LoadPortrait(UPart? part, UProject? project) { Portrait = null; portraitSource = null; } else { - using (var stream = new MemoryStream(data)) { + using (var stream = new MemoryStream(data)) { Portrait = ResizePortrait(new Bitmap(stream), singer.PortraitHeight); portraitSource = singer.Portrait; } @@ -606,18 +606,18 @@ public void MoveSelection(int delta) { if (Selection.Move(delta)) { MessageBus.Current.SendMessage(new NotesSelectionEvent(Selection)); ScrollIntoView(Selection.Head!); - }; + } } public void ExtendSelection(int delta) { if (Selection.Resize(delta)) { MessageBus.Current.SendMessage(new NotesSelectionEvent(Selection)); ScrollIntoView(Selection.Head!); - }; + } } public void ExtendSelection(UNote note) { if (Selection.SelectTo(note)) { MessageBus.Current.SendMessage(new NotesSelectionEvent(Selection)); - }; + } } public void MoveCursor(int delta) { @@ -790,7 +790,7 @@ public void MergeSelectedNotes() { notes.Sort((a, b) => a.position.CompareTo(b.position)); //Ignore slur lyrics var mergedLyrics = String.Join("", notes.Select(x => x.lyric).Where(l => !l.StartsWith("+"))); - if(mergedLyrics == ""){ //If all notes are slur, the merged note is single slur note + if (mergedLyrics == "") { //If all notes are slur, the merged note is single slur note mergedLyrics = notes[0].lyric; } DocManager.Inst.StartUndoGroup(); @@ -858,7 +858,7 @@ public void PasteNotes() { public async void PasteSelectedParams(PianoRollWindow window) { if (Part != null && DocManager.Inst.NotesClipboard != null && DocManager.Inst.NotesClipboard.Count > 0) { var selectedNotes = Selection.ToList(); - if(selectedNotes.Count == 0) { + if (selectedNotes.Count == 0) { return; } @@ -959,7 +959,7 @@ private void ScrollIntoView(UNote note) { internal (UNote[], string[]) PrepareInsertLyrics() { var first = Selection.FirstOrDefault(); var last = Selection.LastOrDefault(); - if(Part == null){ + if (Part == null) { return (new UNote[0], new string[0]); } //If no note is selected, InsertLyrics will apply to all notes in the part. diff --git a/OpenUtau/ViewModels/NotesViewModelHitTest.cs b/OpenUtau/ViewModels/NotesViewModelHitTest.cs index f3cf9fa95..90a628bf7 100644 --- a/OpenUtau/ViewModels/NotesViewModelHitTest.cs +++ b/OpenUtau/ViewModels/NotesViewModelHitTest.cs @@ -376,7 +376,7 @@ public AliasHitInfo HitTestAlias(Point mousePos) { if (string.IsNullOrEmpty(phonemeText)) { continue; } - (double textX, double textY, Size size, TextLayout textLayout) + (double textX, double textY, Size size, TextLayout textLayout) = PhonemeUIRender.AliasPosition(viewModel, phoneme, langCode, ref lastTextEndX, ref raiseText); var rect = new Rect(new Point(textX - 2, textY + 1.5), size); if (rect.Contains(mousePos)) { diff --git a/OpenUtau/ViewModels/PasteParamViewModel.cs b/OpenUtau/ViewModels/PasteParamViewModel.cs index 41a105c17..4373e4434 100644 --- a/OpenUtau/ViewModels/PasteParamViewModel.cs +++ b/OpenUtau/ViewModels/PasteParamViewModel.cs @@ -8,8 +8,8 @@ public class PasteParamViewModel { public PasteParamViewModel() { Params.Add(new PasteParameter("pitch points", "")); Params.Add(new PasteParameter("vibrato", "")); - foreach(var exp in DocManager.Inst.Project.expressions) { - if(exp.Value.type != Core.Ustx.UExpressionType.Curve) { + foreach (var exp in DocManager.Inst.Project.expressions) { + if (exp.Value.type != Core.Ustx.UExpressionType.Curve) { Params.Add(new PasteParameter(exp.Value.name, exp.Key)); } } diff --git a/OpenUtau/ViewModels/PhoneticAssistantViewModel.cs b/OpenUtau/ViewModels/PhoneticAssistantViewModel.cs index cf77ce4fa..285cbe399 100644 --- a/OpenUtau/ViewModels/PhoneticAssistantViewModel.cs +++ b/OpenUtau/ViewModels/PhoneticAssistantViewModel.cs @@ -39,7 +39,7 @@ public G2pOption(Type klass) { private Api.G2pPack? g2p; public PhoneticAssistantViewModel() { - G2p = g2ps.FirstOrDefault(x=>x.name == Preferences.Default.PhoneticAssistant) ?? g2ps.First(); + G2p = g2ps.FirstOrDefault(x => x.name == Preferences.Default.PhoneticAssistant) ?? g2ps.First(); Grapheme = string.Empty; Phonemes = string.Empty; this.WhenAnyValue(x => x.G2p) diff --git a/OpenUtau/ViewModels/PreferencesViewModel.cs b/OpenUtau/ViewModels/PreferencesViewModel.cs index f9d3cd1ea..81ae3b0df 100644 --- a/OpenUtau/ViewModels/PreferencesViewModel.cs +++ b/OpenUtau/ViewModels/PreferencesViewModel.cs @@ -8,10 +8,10 @@ using OpenUtau.Audio; using OpenUtau.Classic; using OpenUtau.Core; +using OpenUtau.Core.Render; using OpenUtau.Core.Util; using ReactiveUI; using ReactiveUI.Fody.Helpers; -using OpenUtau.Core.Render; using Serilog; namespace OpenUtau.App.ViewModels { diff --git a/OpenUtau/ViewModels/SearchNoteViewModel.cs b/OpenUtau/ViewModels/SearchNoteViewModel.cs index 1dc5a7eb8..68dcda830 100644 --- a/OpenUtau/ViewModels/SearchNoteViewModel.cs +++ b/OpenUtau/ViewModels/SearchNoteViewModel.cs @@ -18,9 +18,9 @@ class SearchNoteViewModel : ViewModelBase { NotesViewModel notesViewModel { get; } List notes = new List(); int selection = -1; - [Reactive]public string ResultCount { get; private set; } = ""; - bool CaseSensitive{ get; set; } = true; - bool WholeWord{ get; set; } = false; + [Reactive] public string ResultCount { get; private set; } = ""; + bool CaseSensitive { get; set; } = true; + bool WholeWord { get; set; } = false; public SearchNoteViewModel(NotesViewModel notesViewModel) { this.notesViewModel = notesViewModel; @@ -97,7 +97,7 @@ public void Prev() { } public void Next() { - if(notes.Count() == 0) { + if (notes.Count() == 0) { selection = -1; } else if (notes.Count() == 1) { selection = 0; @@ -124,10 +124,10 @@ public void SelectAll() { MessageBus.Current.SendMessage(new NotesSelectionEvent(notesViewModel.Selection)); } - public void UpdateResult(){ + public void UpdateResult() { if (selection >= 0) { ResultCount = $"{selection + 1}/{Count}"; - }else{ + } else { ResultCount = $"{Count}"; } } diff --git a/OpenUtau/ViewModels/SingerPublishViewModel.cs b/OpenUtau/ViewModels/SingerPublishViewModel.cs index 64cc277ec..aa1d94885 100644 --- a/OpenUtau/ViewModels/SingerPublishViewModel.cs +++ b/OpenUtau/ViewModels/SingerPublishViewModel.cs @@ -1,9 +1,9 @@ -using System.IO; +using System.IO; using System.Threading.Tasks; using OpenUtau.Classic; using OpenUtau.Core; -using OpenUtau.Core.Util; using OpenUtau.Core.Ustx; +using OpenUtau.Core.Util; using ReactiveUI.Fody.Helpers; namespace OpenUtau.App.ViewModels { @@ -18,21 +18,20 @@ public SingerPublishViewModel(USinger singer) { IgnoreTypes = Preferences.Default.VoicebankPublishIgnores; } - public Task Publish(string outputFile){ + public Task Publish(string outputFile) { return Task.Run(() => { try { Preferences.Default.VoicebankPublishUseIgnore = UseIgnore; - if(UseIgnore){ + if (UseIgnore) { Preferences.Default.VoicebankPublishIgnores = IgnoreTypes; } Preferences.Save(); - if(Directory.Exists(singer.Location)){ + if (Directory.Exists(singer.Location)) { var publisher = new VoicebankPublisher((progress, info) => { DocManager.Inst.ExecuteCmd(new ProgressBarNotification(progress, info)); }, UseIgnore ? IgnoreTypes : null); - publisher.Publish(singer, outputFile); - } - else if(File.Exists(singer.Location)){ + publisher.Publish(singer, outputFile); + } else if (File.Exists(singer.Location)) { File.Copy(singer.Location, outputFile); } } finally { @@ -43,4 +42,4 @@ public Task Publish(string outputFile){ }); } } -} \ No newline at end of file +} diff --git a/OpenUtau/ViewModels/SingerSetupViewModel.cs b/OpenUtau/ViewModels/SingerSetupViewModel.cs index 064f8f043..e249a7378 100644 --- a/OpenUtau/ViewModels/SingerSetupViewModel.cs +++ b/OpenUtau/ViewModels/SingerSetupViewModel.cs @@ -46,13 +46,13 @@ public SingerSetupViewModel() { this.WhenAnyValue(vm => vm.ArchiveFilePath) .Subscribe(_ => { if (!string.IsNullOrEmpty(ArchiveFilePath)) { - if(IsEncrypted(ArchiveFilePath)) { + if (IsEncrypted(ArchiveFilePath)) { throw new MessageCustomizableException( "Encrypted archive file isn't supported", - "", + "", new Exception("Encrypted archive file: " + ArchiveFilePath) ); - } + } var config = LoadCharacterYaml(ArchiveFilePath); MissingInfo = string.IsNullOrEmpty(config?.SingerType); if (!string.IsNullOrEmpty(config?.TextFileEncoding)) { @@ -103,7 +103,7 @@ private bool IsEncrypted(string archiveFilePath) { private VoicebankConfig? LoadCharacterYaml(string archiveFilePath) { using (var archive = ArchiveFactory.Open(archiveFilePath)) { - var entry = archive.Entries.FirstOrDefault(e => Path.GetFileName(e.Key)=="character.yaml"); + var entry = archive.Entries.FirstOrDefault(e => Path.GetFileName(e.Key) == "character.yaml"); if (entry == null) { return null; } diff --git a/OpenUtau/ViewModels/TrackColorViewModel.cs b/OpenUtau/ViewModels/TrackColorViewModel.cs index 3e2eab80d..11995c2d4 100644 --- a/OpenUtau/ViewModels/TrackColorViewModel.cs +++ b/OpenUtau/ViewModels/TrackColorViewModel.cs @@ -16,7 +16,7 @@ public TrackColorViewModel(UTrack track) { } public void Finish() { - if(SelectedColor.Name != track.TrackColor) { + if (SelectedColor.Name != track.TrackColor) { DocManager.Inst.StartUndoGroup(); DocManager.Inst.ExecuteCmd(new ChangeTrackColorCommand(DocManager.Inst.Project, track, SelectedColor.Name)); DocManager.Inst.EndUndoGroup(); diff --git a/OpenUtau/ViewModels/TrackHeaderViewModel.cs b/OpenUtau/ViewModels/TrackHeaderViewModel.cs index 829de9839..b2df04c83 100644 --- a/OpenUtau/ViewModels/TrackHeaderViewModel.cs +++ b/OpenUtau/ViewModels/TrackHeaderViewModel.cs @@ -290,7 +290,7 @@ public void RefreshSingers() { Command = ReactiveCommand.Create(async () => { var mainWindow = (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime) ?.MainWindow as MainWindow; - if(mainWindow == null){ + if (mainWindow == null) { return; } var file = await FilePicker.OpenFileAboutSinger( @@ -359,17 +359,17 @@ public void RefreshSingers() { this.RaisePropertyChanged(nameof(SingerMenuItems)); } - public string GetPhonemizerGroupHeader(string key){ - if(key is null){ + public string GetPhonemizerGroupHeader(string key) { + if (key is null) { return "General"; } - if(ThemeManager.TryGetString($"languages.{key.ToLowerInvariant()}", out var value)){ + if (ThemeManager.TryGetString($"languages.{key.ToLowerInvariant()}", out var value)) { return $"{key}: {value}"; } return key; } - PhonemizerFactory? FindPhonemizerByName(string name){ + PhonemizerFactory? FindPhonemizerByName(string name) { return DocManager.Inst.PhonemizerFactories.FirstOrDefault( factory => factory.type.FullName == name); } @@ -377,9 +377,9 @@ public string GetPhonemizerGroupHeader(string key){ public void RefreshPhonemizers() { var items = new List(); //Singer default - if (track != null && track.Singer != null && track.Singer.Found){ + if (track != null && track.Singer != null && track.Singer.Found) { var factory = FindPhonemizerByName(track.Singer.DefaultPhonemizer); - if(factory != null){ + if (factory != null) { items.Add(new MenuItemViewModel() { Header = ThemeManager.GetString("tracks.singerdefault") + factory.ToString(), Command = SelectPhonemizerCommand, @@ -503,7 +503,7 @@ public void Rename() { public async void SelectTrackColor() { var dialog = new TrackColorDialog(); dialog.DataContext = new TrackColorViewModel(track); - + if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop && desktop.MainWindow != null) { await dialog.ShowDialog(desktop.MainWindow); TrackAccentColor = ThemeManager.GetTrackColor(track.TrackColor).AccentColor; diff --git a/OpenUtau/ViewModels/TracksViewModel.cs b/OpenUtau/ViewModels/TracksViewModel.cs index 9aacb3fa1..2ca3d938e 100644 --- a/OpenUtau/ViewModels/TracksViewModel.cs +++ b/OpenUtau/ViewModels/TracksViewModel.cs @@ -187,7 +187,7 @@ public int PointToTick(Point point) { } public void TickToLineTick(int tick, out int left, out int right) { - if(tick < 0 || SnapUnit <= 0){ + if (tick < 0 || SnapUnit <= 0) { left = right = 0; return; } diff --git a/OpenUtau/ViewModels/ViewModelBase.cs b/OpenUtau/ViewModels/ViewModelBase.cs index 1d841eb49..8611391cc 100644 --- a/OpenUtau/ViewModels/ViewModelBase.cs +++ b/OpenUtau/ViewModels/ViewModelBase.cs @@ -1,11 +1,9 @@ -using ReactiveUI; -using System; +using System; using System.Collections.Generic; using System.Text; +using ReactiveUI; -namespace OpenUtau.App.ViewModels -{ - public class ViewModelBase : ReactiveObject - { +namespace OpenUtau.App.ViewModels { + public class ViewModelBase : ReactiveObject { } } diff --git a/OpenUtau/ViewModels/VoiceColorMappingViewModel.cs b/OpenUtau/ViewModels/VoiceColorMappingViewModel.cs index 309f5c09f..6bfe04d50 100644 --- a/OpenUtau/ViewModels/VoiceColorMappingViewModel.cs +++ b/OpenUtau/ViewModels/VoiceColorMappingViewModel.cs @@ -34,7 +34,7 @@ public class ColorMapping { public int SelectedIndex { get; set; } public ObservableCollection NewColors { get; set; } - public ColorMapping(string name,int oldIndex, int selectedIndex, ObservableCollection newColors) { + public ColorMapping(string name, int oldIndex, int selectedIndex, ObservableCollection newColors) { Name = name; OldIndex = oldIndex; SelectedIndex = selectedIndex; diff --git a/OpenUtau/Views/LyricsReplaceDialog.axaml.cs b/OpenUtau/Views/LyricsReplaceDialog.axaml.cs index cce6a94c9..4fa25501c 100644 --- a/OpenUtau/Views/LyricsReplaceDialog.axaml.cs +++ b/OpenUtau/Views/LyricsReplaceDialog.axaml.cs @@ -14,7 +14,7 @@ void OnCancel(object? sender, RoutedEventArgs e) { } void OnFinish(object? sender, RoutedEventArgs e) { - if((DataContext as LyricsReplaceViewModel)!.Finish()) { + if ((DataContext as LyricsReplaceViewModel)!.Finish()) { Close(); } } diff --git a/OpenUtau/Views/MergeVoicebankDialog.axaml.cs b/OpenUtau/Views/MergeVoicebankDialog.axaml.cs index 3c14ee31b..b6ff52874 100644 --- a/OpenUtau/Views/MergeVoicebankDialog.axaml.cs +++ b/OpenUtau/Views/MergeVoicebankDialog.axaml.cs @@ -1,9 +1,9 @@ -using Serilog; -using System.Threading; +using System.Threading; using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Interactivity; using OpenUtau.App.ViewModels; +using Serilog; namespace OpenUtau.App.Views { public partial class MergeVoicebankDialog : Window { @@ -11,31 +11,25 @@ public MergeVoicebankDialog() { InitializeComponent(); } - void OnEditedFolder(object sender, DataGridCellEditEndedEventArgs e) - { + void OnEditedFolder(object sender, DataGridCellEditEndedEventArgs e) { var viewModel = DataContext as MergeVoicebankViewModel; - if (viewModel == null) - { + if (viewModel == null) { return; } viewModel.CheckFolderNames(); } - void OnEditedSubbank(object sender, DataGridCellEditEndedEventArgs e) - { + void OnEditedSubbank(object sender, DataGridCellEditEndedEventArgs e) { var viewModel = DataContext as MergeVoicebankViewModel; - if (viewModel == null) - { + if (viewModel == null) { return; } viewModel.CheckSubbankNames(); } - void OnEditedVoiceColor(object sender, DataGridCellEditEndedEventArgs e) - { + void OnEditedVoiceColor(object sender, DataGridCellEditEndedEventArgs e) { var viewModel = DataContext as MergeVoicebankViewModel; - if (viewModel == null) - { + if (viewModel == null) { return; } viewModel.CheckVoiceColorNames(); @@ -59,4 +53,4 @@ void MergeClicked(object sender, RoutedEventArgs arg) { Close(); } } -} \ No newline at end of file +} diff --git a/OpenUtau/Views/MessageBox.axaml.cs b/OpenUtau/Views/MessageBox.axaml.cs index 1222d121f..d4aaf2818 100644 --- a/OpenUtau/Views/MessageBox.axaml.cs +++ b/OpenUtau/Views/MessageBox.axaml.cs @@ -204,12 +204,12 @@ public static bool LoadingIsActive() { /// operations to be performed once the asynchronous action completes. /// public static Task ShowProcessing( - Window parent, - string text, - string title, - Action action, - Action? onFinished= null) { + Action? onFinished = null) { var msgbox = new MessageBox() { Title = title }; diff --git a/OpenUtau/Views/NoteEditStates.cs b/OpenUtau/Views/NoteEditStates.cs index 4b61172b7..6187e7539 100644 --- a/OpenUtau/Views/NoteEditStates.cs +++ b/OpenUtau/Views/NoteEditStates.cs @@ -436,7 +436,7 @@ public override void Update(IPointer pointer, Point point) { } int maxNoteTicks = (notesVm.IsSnapOn && snapUnit > 0) - ? (oldDur-1) / snapUnit * snapUnit + ? (oldDur - 1) / snapUnit * snapUnit : oldDur - 15; int maxDelta = maxNoteTicks - note.duration; @@ -1130,8 +1130,8 @@ class DrawLinePitchState : NoteEditState { double? lastPitch; Point lastPoint; public DrawLinePitchState( - Control control, - PianoRollViewModel vm, + Control control, + PianoRollViewModel vm, IValueTip valueTip) : base(control, vm, valueTip) { } public override void Begin(IPointer pointer, Point point) { base.Begin(pointer, point); diff --git a/OpenUtau/Views/PianoRollWindow.axaml.cs b/OpenUtau/Views/PianoRollWindow.axaml.cs index c4bcf6e37..fc1dc47aa 100644 --- a/OpenUtau/Views/PianoRollWindow.axaml.cs +++ b/OpenUtau/Views/PianoRollWindow.axaml.cs @@ -750,7 +750,7 @@ public void NotesCanvasPointerMoved(object sender, PointerEventArgs args) { if (ViewModel?.NotesViewModel?.HitTest == null) { return; } - if((ViewModel.NotesViewModel.DrawPitchTool || ViewModel.NotesViewModel.DrawLinePitchTool || ViewModel.NotesViewModel.OverwritePitchTool || ViewModel.NotesViewModel.EraserTool) && args.KeyModifiers != cmdKey) { + if ((ViewModel.NotesViewModel.DrawPitchTool || ViewModel.NotesViewModel.DrawLinePitchTool || ViewModel.NotesViewModel.OverwritePitchTool || ViewModel.NotesViewModel.EraserTool) && args.KeyModifiers != cmdKey) { Cursor = null; return; } @@ -1712,13 +1712,13 @@ bool OnKeyExtendedHandler(KeyEventArgs args) { } } break; - case Key.PageDown: { + case Key.PageDown: { if (isNone) { return MoveToNextPart(true); } } break; - #endregion + #endregion } return false; } diff --git a/OpenUtau/Views/SingerPublishDialog.axaml.cs b/OpenUtau/Views/SingerPublishDialog.axaml.cs index b77fda2ec..aab7910ca 100644 --- a/OpenUtau/Views/SingerPublishDialog.axaml.cs +++ b/OpenUtau/Views/SingerPublishDialog.axaml.cs @@ -1,11 +1,11 @@ -using System.IO; +using System.IO; using System.Threading; using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Platform.Storage; -using Serilog; using OpenUtau.App.ViewModels; +using Serilog; namespace OpenUtau.App.Views { public partial class SingerPublishDialog : Window { @@ -13,17 +13,17 @@ public SingerPublishDialog() { InitializeComponent(); } - async void PublishClicked(object sender, RoutedEventArgs arg){ + async void PublishClicked(object sender, RoutedEventArgs arg) { var viewModel = DataContext as SingerPublishViewModel; if (viewModel == null) { return; } var singer = viewModel.singer; - if(singer == null){ + if (singer == null) { return; } var types = FilePicker.ZIP; - if(File.Exists(singer.Location)){ + if (File.Exists(singer.Location)) { var suffix = Path.GetExtension(singer.Location); types = new FilePickerFileType(suffix.ToUpper()) { Patterns = new[] { "*" + suffix }, @@ -37,7 +37,7 @@ async void PublishClicked(object sender, RoutedEventArgs arg){ Publish(outputFile); } - void Publish(string outputFile){ + void Publish(string outputFile) { var viewModel = DataContext as SingerPublishViewModel; if (viewModel == null) { return; @@ -54,4 +54,4 @@ void Publish(string outputFile){ Close(); } } -} \ No newline at end of file +} diff --git a/OpenUtau/Views/SingersDialog.axaml.cs b/OpenUtau/Views/SingersDialog.axaml.cs index 4bd9b9cd4..df33c619f 100644 --- a/OpenUtau/Views/SingersDialog.axaml.cs +++ b/OpenUtau/Views/SingersDialog.axaml.cs @@ -313,13 +313,13 @@ void OnOpenReadme(object sender, RoutedEventArgs e) { } } - string? FindSample(USinger singer){ + string? FindSample(USinger singer) { var sample = singer.Sample; - if(sample!=null && File.Exists(sample)){ + if (sample != null && File.Exists(sample)) { return sample; } else if (singer.SingerType == USingerType.Classic || singer.SingerType == USingerType.Voicevox) { var path = singer.Location; - if(!Directory.Exists(path)){ + if (!Directory.Exists(path)) { return null; } string[] files = Directory.EnumerateFiles(path, "*.wav", SearchOption.AllDirectories) @@ -329,7 +329,7 @@ void OnOpenReadme(object sender, RoutedEventArgs e) { .Union(Directory.EnumerateFiles(path, "*.ogg", SearchOption.AllDirectories)) .Union(Directory.EnumerateFiles(path, "*.opus", SearchOption.AllDirectories)) .ToArray(); - if(files.Length==0){ + if (files.Length == 0) { return null; } Random rnd = new Random(Guid.NewGuid().GetHashCode()); @@ -351,10 +351,10 @@ public void OnPlayCharacterSample(object sender, RoutedEventArgs e) { } var sample = FindSample(viewModel.Singer); - if(sample == null){ + if (sample == null) { return; } - try{ + try { var playSound = Wave.OpenFile(sample); playBack.Init(playSound.ToSampleProvider()); } catch (Exception ex) { diff --git a/OpenUtau/Views/SliderDialog.axaml.cs b/OpenUtau/Views/SliderDialog.axaml.cs index 3562ea052..478ab0758 100644 --- a/OpenUtau/Views/SliderDialog.axaml.cs +++ b/OpenUtau/Views/SliderDialog.axaml.cs @@ -22,7 +22,7 @@ public SliderDialog(string title, double value, double min, double max, double t this.WhenAnyValue(d => d.Slider.Value) .Subscribe(value => { TextBlock.Text = value.ToString(); - }); + }); } private void OkButtonClick(object? sender, RoutedEventArgs e) {