This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

character / miniview / addons / gd_cubism / example / demo_effect_custom_03.cs
4.3 kB 136 lines
1// SPDX-License-Identifier: MIT 2// SPDX-FileCopyrightText: 2023 MizunagiKB <mizukb@live.jp> 3using System; 4using Godot; 5 6#pragma warning disable CA1050 7#pragma warning disable IDE1006 8 9 10public partial class demo_effect_custom_03 : Node2D 11{ 12 private const String DEFAULT_ASSET = "res://addons/gd_cubism/example/res/live2d/mao_pro_jp/runtime/mao_pro.model3.json"; 13 14 private GDCubismUserModelCS cubism_model; 15 private GDCubismEffectCustomCS cubism_efx; 16 17 private String param_mouth_name = "ParamMouthA"; 18 [Export] 19 private float min_db = 60.0f; 20 [Export] 21 private int min_voice_freq = 0; 22 [Export] 23 private int max_voice_freq = 3200; 24 [Export] 25 private int history_size = 6; 26 27 [ExportCategory("Audio")] 28 [Export] 29 private String audio_bus_name = "Voice"; 30 [Export] 31 private int audio_efx_index = 0; 32 33 private AudioEffectSpectrumAnalyzerInstance spectrum; 34 private GDCubismParameterCS param_mouth; 35 private Godot.Collections.Array<float> ary_volume_history; 36 private int history_position = 0; 37 private bool lipsync_ready = false; 38 39 private void array_rebuild() 40 { 41 if (this.history_size != this.ary_volume_history.Count) 42 { 43 this.ary_volume_history.Resize(this.history_size); 44 this.ary_volume_history.Fill(0.0f); 45 } 46 } 47 48 private void recalc_model_position(GDCubismUserModelCS model) 49 { 50 if(model.Assets == "") return; 51 52 Godot.Collections.Dictionary canvas_info = model.GetCanvasInfo(); 53 54 if(canvas_info.Count > 0) 55 { 56 Vector2 vct_viewport_size = new(GetViewportRect().Size.X, GetViewportRect().Size.Y); 57 Vector2 size_in_pixels = (Vector2)canvas_info["size_in_pixels"]; 58 float scale = vct_viewport_size.Y / Math.Max(size_in_pixels.X, size_in_pixels.Y); 59 model.GetInternalObject().Position = new(vct_viewport_size.X * 0.5f, vct_viewport_size.Y * 0.5f); 60 model.GetInternalObject().Scale = new(scale, scale); 61 } 62 } 63 64 public override void _Ready() 65 { 66 this.cubism_efx = new(GetNode<Node>("GDCubismUserModel/GDCubismEffectCustom")); 67 this.cubism_efx.CubismPrologue += this._on_cubism_prologue; 68 this.cubism_efx.CubismEpilogue += this._on_cubism_epilogue; 69 this.cubism_efx.CubismInit += this._on_cubism_init; 70 this.cubism_efx.CubismTerm += this._on_cubism_term; 71 this.cubism_efx.CubismProcess += this._on_cubism_process; 72 73 this.cubism_model = new(GetNode<Node2D>("GDCubismUserModel")); 74 if (this.cubism_model.Assets == "") this.cubism_model.Assets = DEFAULT_ASSET; 75 } 76 77 public override void _Process(double delta) 78 { 79 this.recalc_model_position(this.cubism_model); 80 } 81 82 private float array_avg() 83 { 84 float sum_v = 0.0f; 85 foreach (float v in this.ary_volume_history) 86 { 87 sum_v += v; 88 } 89 return sum_v / this.ary_volume_history.Count; 90 } 91 92 private void _on_cubism_prologue(Node2D _model, float v) {} 93 private void _on_cubism_epilogue(Node2D _model, float v) {} 94 private void _on_cubism_init(Node2D _model) {} 95 96 private void _on_cubism_term(Node2D _model) 97 { 98 this.lipsync_ready = false; 99 this.param_mouth = null; 100 this.ary_volume_history.Clear(); 101 this.history_position = 0; 102 } 103 104 private void _on_cubism_process(Node2D _model, double delta) 105 { 106 if (this.lipsync_ready == false) return; 107 108 this.array_rebuild(); 109 110 float m = this.spectrum.GetMagnitudeForFrequencyRange( 111 this.min_voice_freq, 112 this.max_voice_freq 113 ).Length(); 114 115 var v = Math.Clamp((min_db + Mathf.LinearToDb(m)) / this.min_db, 0.0f, 1.0f); 116 117 this.ary_volume_history[this.history_position] = v; 118 this.history_position += 1; 119 120 if (this.history_position >= this.ary_volume_history.Count) 121 { 122 this.history_position = 0; 123 } 124 125 float avg_v = this.array_avg(); 126 127 if (this.param_mouth != null) 128 { 129 this.param_mouth.Value = Math.Max(this.param_mouth.Value - 0.2f, 0.0f); 130 if (avg_v > 0.1f) 131 { 132 this.param_mouth.Value = 1.0f; 133 } 134 } 135 } 136}