### GET /app/{path} Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/interface/http/http-001 Serves static content from the document root folder configured in AssistantSeika's HTTP settings. ```APIDOC ## GET /app/{path} ### Description Serves static content from the document root folder configured in AssistantSeika's HTTP settings. ### Method GET ### Endpoint /app/{path} ### Parameters #### Path Parameters - **path** (string) - Required - Path to the requested file relative to the document root ### Response #### Success Response (200) - File content (e.g., HTML, CSS, JS) #### Response Example (Not provided in source) ``` -------------------------------- ### GET /PLAY2/{cid}/{talktext} Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/interface/http/http-001 Performs voice synthesis using GET method with talktext in the URL. ```APIDOC ## GET /PLAY2/{cid}/{talktext} ### Description Performs voice synthesis using GET method with talktext in the URL. ### Method GET ### Endpoint /PLAY2/{cid}/{talktext} ### Parameters #### Path Parameters - **cid** (string) - Required - Speaker identifier - **talktext** (string) - Required - Text to be spoken (URL-encoded UTF-8) ### Response #### Success Response (200) - Audio data (for playback) #### Response Example (Not provided in source) ``` -------------------------------- ### AssistantSeika起動バッチファイル(bootsample.cmd) Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/troubleshoot/troubleshoot-020 バッチファイルからAssistantSeikaを起動し、製品スキャンやHTTP機能を実行するためのサンプル。SeikaCtl.exeを使用して起動確認やエラーハンドリングを行う。 ```batch @echo off chcp 65001 SET ASPATH="D:\Program Files\510Product\AssistantSeika" SET SCPATH="D:\AssistantSeika20230901c\SeikaCtl"   rem ****** 音声合成製品起動処理をここに記述 rem ****** 音声合成製品起動完了確認処理をここに記述 rem ****** AssistantSeikaがまだ起動していなければ起動を実施する。   %SCPATH%\SeikaCtl waitboot 5 if ERRORLEVEL 8 ( echo AssistantSeika起動開始します。 %SCPATH%\SeikaCtl boot %ASPATH% if ERRORLEVEL 8 ( echo AssistantSeika起動に失敗しました。終了します。 PAUSE EXIT /B 8 ) %SCPATH%\SeikaCtl waitboot 60 ) rem ****** AssistantSeikaの製品スキャンボタンを押す。   echo 製品スキャン中 %SCPATH%\SeikaCtl prodscan if ERRORLEVEL 8 ( echo 製品スキャンに失敗しました。終了します。 PAUSE %SCPATH%\SeikaCtl shutdown EXIT /B 8 ) rem ****** AssistantSeikaのHTTP機能を起動する ※必要な場合   %SCPATH%\SeikaCtl boothttp if ERRORLEVEL 8 ( echo HTTP機能の起動に失敗しました。終了します。 PAUSE %SCPATH%\SeikaCtl shutdown EXIT /B 8 )   EXIT /B 0 ``` -------------------------------- ### GET /SAVE2/{cid}/{talktext} Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/interface/http/http-001 Performs voice synthesis and returns audio data using GET method with talktext in the URL. ```APIDOC ## GET /SAVE2/{cid}/{talktext} ### Description Performs voice synthesis and returns audio data using GET method with talktext in the URL. ### Method GET ### Endpoint /SAVE2/{cid}/{talktext} ### Parameters #### Path Parameters - **cid** (string) - Required - Speaker identifier - **talktext** (string) - Required - Text to be spoken (URL-encoded UTF-8) ### Response #### Success Response (200) - Audio data (WAV file) #### Response Example (Not provided in source) ``` -------------------------------- ### WCF接続と発声のサンプル (sample.cs) Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/interface/wcf/wcf-003 AssistantSeikaのWCFサービスに接続し、Talk()とTalk2()で発声する例。エフェクトと感情パラメタを指定する。ChannelFactoryでIScAPIsインタフェースを使用する。 ```csharp using System.Collections.Generic; using System.ServiceModel; using System.Threading; using AssistantSeika; namespace sampleSpeak { class Program { static void Main(string[] args) { string BaseAddr = "net.pipe://localhost/EchoSeika/CentralGate/ApiEntry"; ChannelFactory Channel = new ChannelFactory(new NetNamedPipeBinding(), new EndpointAddress(BaseAddr)); IScAPIs api = Channel.CreateChannel(); while (Channel.State != CommunicationState.Opened) { Thread.Sleep(100); } Dictionary effetcs = new Dictionary() { { "volume", 1.0m }, { "speed", 0.9m }, { "pitch" , 1.3m }, { "intonation", 1.0m } }; Dictionary emotions = new Dictionary() { {"喜び", 0.60m } }; string s = "あー嬉しいなー"; string[] t = new string[] { "あー嬉しいなー", "ホント嬉しいなー" }; api.Talk( 2000, s, "", effetcs, emotions ); // api.Talk( 2000, s, @"F:\AssistantSeika\sandbox\2000.wav", effetcs, emotions ); api.Talk2( 2000, t, "", effetcs, emotions ); // api.Talk2( 2000, t, @"F:\AssistantSeika\sandbox\2000.wav", effetcs, emotions ); Channel.Close(); } } } ``` -------------------------------- ### GET /STORE2/{keyname} Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/interface/http/http-001 Retrieves the value associated with a key in the simple KVS. ```APIDOC ## GET /STORE2/{keyname} ### Description Retrieves the value associated with a key in the simple KVS. ### Method GET ### Endpoint /STORE2/{keyname} ### Parameters #### Path Parameters - **keyname** (string) - Required - Key name ### Response #### Success Response (200) - **value** (array of strings) - The stored value #### Response Example (Not provided in source) ``` -------------------------------- ### AssistantSeika用ScDeviceDriverクラスの実装 Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/samples/assistantseika-093 BouyomiChanProxyを使用して音声合成を行うScDeviceDriverクラスのコード。コンストラクタでアバターパラメータを初期化し、Playメソッドで同期発声、PlayAsyncメソッドで非同期発声を行います。 ```csharp private BouyomiChanProxy BouyomiTalkProxy = null; private string[] AvatorNames = { "女性1", "女性2", "男性1", "男性2", "中性", "ロボット", "機械1", "機械2" }; private FNF.Utility.VoiceType VT; public ScDeviceDriver() { ScDrvName = DrvName; ScDrvVersion = DrvVersion; ScDrvProdName = DrvProdName; CidBaseIndex = CidBase; AvatorParams = new Dictionary(); IsAlive = false; try { BouyomiTalkProxy = new BouyomiChanProxy(); if (BouyomiTalkProxy.IsActive) { for (int i = 0; i < AvatorNames.Length; i++) { AvatorParam item = new AvatorParam(); item.AvatorIndex = i; item.AvatorName = AvatorNames[i]; item.VoiceEffects_default = new Dictionary { {EnumVoiceEffect.volume, new EffectValueInfo( 100m, 0.0m, 100.0m, 1.00m)}, {EnumVoiceEffect.speed, new EffectValueInfo( 100m, 50.0m, 200.0m, 1.00m)}, {EnumVoiceEffect.pitch, new EffectValueInfo( 100m, 50.0m, 200.0m, 1.00m)} }; item.VoiceEffects = new Dictionary { {EnumVoiceEffect.volume, new EffectValueInfo( 100m, 0.0m, 100.0m, 1.00m)}, {EnumVoiceEffect.speed, new EffectValueInfo( 100m, 50.0m, 200.0m, 1.00m)}, {EnumVoiceEffect.pitch, new EffectValueInfo( 100m, 50.0m, 200.0m, 1.00m)} }; item.VoiceEmotions_default = new Dictionary(); item.VoiceEmotions = new Dictionary(); AvatorParams.Add(i, item); } } } catch (Exception) { // ThrowException(string.Format(@"{0} {1}", e.Message, e.StackTrace)); } IsAlive = AvatorParams.Count != 0; } ~ScDeviceDriver() { BouyomiTalkProxy?.Dispose(); Dispose(false); } public override void Dispose(bool disposing) { if (Disposed) return; if (disposing) { AvatorParams.Clear(); BouyomiTalkProxy?.Dispose(); GC.SuppressFinalize(this); } Disposed = true; } public void Dispose() { Dispose(true); } /// /// 指定話者で指定テキストで発声 /// /// 話者CID /// 発声させるテキスト /// 発声にかかった時間(ミリ秒) public override double Play(int cid, string talkText) { Semaphore.Wait(); Stopwatch sw = new Stopwatch(); int avatorIndex = ConvertAvatorIndex(cid); int speed = Convert.ToInt32(AvatorParams[avatorIndex].VoiceEffects[EnumVoiceEffect.speed].value); int tone = Convert.ToInt32(AvatorParams[avatorIndex].VoiceEffects[EnumVoiceEffect.pitch].value); int volume = Convert.ToInt32(AvatorParams[avatorIndex].VoiceEffects[EnumVoiceEffect.volume].value); AvatorSelect(avatorIndex); ApplyEffectParameters(avatorIndex); ApplyEmotionParameters(avatorIndex); sw.Start(); try { // 再生中なら待つ while (BouyomiTalkProxy.NowPlaying == true) { Thread.Sleep(10); } BouyomiTalkProxy.AddTalkTask2(talkText, speed, tone, volume, VT); // 再生中フラグが立つまで待つ while (BouyomiTalkProxy.NowPlaying == false) { Thread.Sleep(10); } // 再生終了まで待つ while (BouyomiTalkProxy.NowPlaying == true) { Thread.Sleep(10); } } catch (Exception) { // } sw.Stop(); Semaphore.Release(); return sw.ElapsedMilliseconds; } /// /// 指定話者で指定テキストで発声 /// /// 話者CID /// 発声させるテキスト public override void PlayAsync(int cid, string talkText) { Task.Run(() => { Semaphore.Wait(); ``` -------------------------------- ### GET /AVATOR2 Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/interface/http/http-001 Retrieves the list of available speakers (cid) for voice synthesis. ```APIDOC ## GET /AVATOR2 ### Description Retrieves the list of available speakers (cid) for voice synthesis. ### Method GET ### Endpoint /AVATOR2 ### Response #### Success Response (200) - List of speaker cids #### Response Example (Not provided in source) ``` -------------------------------- ### Seikactl メインコード (Program.cs) Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/samples/assistantseika-099 Seikactl コマンドのエントリポイント。コマンドライン引数を解析し、オプションに応じて WCF クライアントの操作や AssistantSeika.exe の起動を行う。エラー時はメッセージを表示して終了コード 8 を返す。 ```csharp using System; using System.Diagnostics; using System.IO; using System.Threading; namespace Seikactl { class Program { static int Main(string[] args) { Opts opt = new Opts(args); WCFClient scc =new WCFClient(); if (opt.isActive) { if (opt.isASWaitBoot) { if (0 < opt.ASWaitTime) { int times = 0; for (times = 0; times < opt.ASWaitTime; times++) { try { scc.Version(); break; } catch (Exception) { Thread.Sleep(1000); } } if (times == opt.ASWaitTime) { Console.WriteLine("not alive"); return 8; } } else { Console.WriteLine(@"value {0} is invalid.", opt.ASWaitTime); return 8; } } if (opt.isProdScan) { try { scc.ProductScan(); } catch (Exception e) { Console.WriteLine("fail. {0}", e.Message); return 8; } } if (opt.isBootHttpSrv) { try { scc.BootHttpService(); } catch (Exception e) { Console.WriteLine("fail. {0}", e.Message); return 8; } } if (opt.isASStartup) { try { var ps = new Process(); ps.StartInfo.UseShellExecute = false; ps.StartInfo.WorkingDirectory = Path.GetFullPath(opt.ASBootPath); ps.StartInfo.FileName = Path.Combine( opt.ASBootPath, "AssistantSeika.exe"); ps.Start(); } catch (Exception e) { Console.WriteLine("fail. {0}", e.Message); return 8; } } if (opt.isASShutdown) { try { scc.Shutdown(); } catch (Exception e) { Console.WriteLine("fail. {0}", e.Message); return 8; } } } return 0; } } } ``` -------------------------------- ### GET /STORE2/{keyname}/READFLUSH Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/interface/http/http-001 Retrieves the value associated with a key and deletes it in the same operation. ```APIDOC ## GET /STORE2/{keyname}/READFLUSH ### Description Retrieves the value associated with a key and deletes it in the same operation. ### Method GET ### Endpoint /STORE2/{keyname}/READFLUSH ### Parameters #### Path Parameters - **keyname** (string) - Required - Key name ### Response #### Success Response (200) - **value** (array of strings) - The stored value before deletion #### Response Example (Not provided in source) ``` -------------------------------- ### GET /EFFECT/{cid}/clear Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/interface/http/http-001 Clears all effect and emotion parameter changes for a given speaker. ```APIDOC ## GET /EFFECT/{cid}/clear ### Description Clears all effect and emotion parameter changes for a given speaker. ### Method GET ### Endpoint /EFFECT/{cid}/clear ### Parameters #### Path Parameters - **cid** (string) - Required - Speaker identifier ### Response #### Success Response (200) - (Not specified in source) ``` -------------------------------- ### WCFクライアントのメソッド群 Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/samples/assistantseika-099 WCFクライアントのメソッド群。 ```csharp api.ProductScan(); cf.Close(); } ``` ```csharp public void BootHttpService() { var cf = CreateChannelFactory(); var api = CreateChannel(cf); api.BootHttpService(); cf.Close(); } ``` ```csharp public Dictionary AvatorList() { var cf = CreateChannelFactory(); var api = CreateChannel(cf); var ans = api.AvatorList(); cf.Close(); return ans; } ``` ```csharp public Dictionary> AvatorList2() { var cf = CreateChannelFactory(); var api = CreateChannel(cf); var ans = api.AvatorList2(); cf.Close(); return ans; } ``` ```csharp public Dictionary> AvatorListDetail2() { var cf = CreateChannelFactory(); var api = CreateChannel(cf); var list1 = api.AvatorListDetail2(); cf.Close(); var ans = new Dictionary>(); foreach(var item1 in list1) { if (item1.Value["isalias"] == "False") { ans.Add(item1.Key, new Dictionary()); foreach (var item2 in item1.Value) { ans[item1.Key].Add(item2.Key, item2.Value); } } } return ans; } ``` ```csharp public Dictionary>> GetDefaultParams2(int cid) { var cf = CreateChannelFactory(); var api = CreateChannel(cf); var ans = api.GetDefaultParams2(cid); cf.Close(); return ans; } ``` ```csharp public Dictionary>> GetCurrentParams2(int cid) { var cf = CreateChannelFactory(); var api = CreateChannel(cf); var ans = api.GetCurrentParams2(cid); cf.Close(); return ans; } ``` ```csharp public void ResetParams2(int cid) { var cf = CreateChannelFactory(); var api = CreateChannel(cf); api.ResetParams2(cid); cf.Close(); } ``` ```csharp public double Talk(int cid, string talktext, string filepath, Dictionary effects, Dictionary emotions) { var cf = CreateChannelFactory(); var api = CreateChannel(cf); var ans = api.Talk(cid, talktext, filepath == "" ? "" : MakeFullPath(filepath), effects, emotions); cf.Close(); return ans; } ``` ```csharp public double Talk2(int cid, string[] talktexts, string filepath, Dictionary effects, Dictionary emotions) { var cf = CreateChannelFactory(); var api = CreateChannel(cf); var ans = api.Talk2(cid, talktexts, filepath == "" ? "" : MakeFullPath(filepath), effects, emotions); cf.Close(); return ans; } ``` ```csharp public void TalkAsync(int cid, string talktext, Dictionary effects, Dictionary emotions) { var cf = CreateChannelFactory(); var api = CreateChannel(cf); api.TalkAsync(cid, talktext, effects, emotions); cf.Close(); } ``` ```csharp public void TalkAsync2(int cid, string[] talktexts, Dictionary effects, Dictionary emotions) { var cf = CreateChannelFactory(); var api = CreateChannel(cf); api.TalkAsync2(cid, talktexts, effects, emotions); cf.Close(); } ``` ```csharp public int CheckCid(int cid) { var cf = CreateChannelFactory(); var api = CreateChannel(cf); int ans = api.CheckCid(cid); cf.Close(); return ans; } ``` ```csharp public void Shutdown() { var cf = CreateChannelFactory(); var api = CreateChannel(cf); api.Shutdown(); cf.Close(); } ``` ```csharp private string MakeFullPath(string filepath) { return Path.GetFullPath(filepath); } ``` -------------------------------- ### GET /AVATOR2/{cid} Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/interface/http/http-001 Retrieves the parameters (effects and emotions) assigned to a specific speaker cid. ```APIDOC ## GET /AVATOR2/{cid} ### Description Retrieves the parameters (effects and emotions) assigned to a specific speaker cid. ### Method GET ### Endpoint /AVATOR2/{cid} ### Parameters #### Path Parameters - **cid** (string) - Required - Speaker identifier ### Response #### Success Response (200) - **effects** (object) - Effect parameters - **emotions** (object) - Emotion parameters #### Response Example (Not provided in source) ``` -------------------------------- ### 棒読みちゃん連携による発声処理(Talk) Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/samples/assistantseika-093 指定されたCIDからアバターインデックスを取得し、音声パラメータ(速度・音程・音量)を設定して、棒読みちゃんに発声タスクを追加する。再生中は待機し、再生終了まで待つ。例外は無視される。 ```csharp int avatorIndex = ConvertAvatorIndex(cid); int speed = Convert.ToInt32(AvatorParams[avatorIndex].VoiceEffects[EnumVoiceEffect.speed].value); int tone = Convert.ToInt32(AvatorParams[avatorIndex].VoiceEffects[EnumVoiceEffect.pitch].value); int volume = Convert.ToInt32(AvatorParams[avatorIndex].VoiceEffects[EnumVoiceEffect.volume].value);   AvatorSelect(avatorIndex); ApplyEffectParameters(avatorIndex); ApplyEmotionParameters(avatorIndex);   try { // 再生中なら待つ while (BouyomiTalkProxy.NowPlaying == true) { Thread.Sleep(10); }   BouyomiTalkProxy.AddTalkTask2(talkText, speed, tone, volume, VT);   // 再生中フラグが立つまで待つ while (BouyomiTalkProxy.NowPlaying == false) { Thread.Sleep(10); }   // 再生終了まで待つ while (BouyomiTalkProxy.NowPlaying == true) { Thread.Sleep(10); } } catch (Exception) { // }   Semaphore.Release(); }); } ``` -------------------------------- ### WCFクライアントコード Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/samples/assistantseika-099 WCFクライアントコードのサンプル。 ```csharp [OperationContract] Dictionary>> GetDefaultParams2(int cid); [OperationContract] Dictionary>> GetCurrentParams2(int cid); [OperationContract] void ResetParams2(int cid); [OperationContract] double Talk(int cid, string talktext, string filepath, Dictionary effects, Dictionary emotions); [OperationContract] double Talk2(int cid, string[] talktexts, string filepath, Dictionary effects, Dictionary emotions); [OperationContract] void TalkAsync(int cid, string talktext, Dictionary effects, Dictionary emotions); [OperationContract] void TalkAsync2(int cid, string[] talktexts, Dictionary effects, Dictionary emotions); [OperationContract] double Save(int cid, string talktext, string filepath, Dictionary effects, Dictionary emotions); [OperationContract] int CheckCid(int cid); [OperationContract] void Shutdown(); } } ``` -------------------------------- ### GET /EMOTION/{cid}/{param}/{value} Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/interface/http/http-001 Sets an emotion parameter (e.g., 喜び) to a specified value for a given speaker. ```APIDOC ## GET /EMOTION/{cid}/{param}/{value} ### Description Sets an emotion parameter (e.g., 喜び) to a specified value for a given speaker. ### Method GET ### Endpoint /EMOTION/{cid}/{param}/{value} ### Parameters #### Path Parameters - **cid** (string) - Required - Speaker identifier - **param** (string) - Required - Emotion parameter name (e.g., 喜び) - **value** (number) - Required - Value to set ### Response #### Success Response (200) - (Not specified in source) ``` -------------------------------- ### 話者名の定義とデバイスドライバの初期化 Source: https://wiki.hgotoh.jp/documents/tools/assistantseika/samples/assistantseika-094 話者名をCidBaseに基づいて定義し、ScDeviceDriverコンストラクタでドライバの初期化と話者リストの処理を行います。音声効果のデフォルト値もここで設定されます。 ```csharp new titles( "かほ", CidBase + 2), new titles( "ななこ", CidBase + 3), new titles( "のぞみ", CidBase + 4), new titles( "せいじ", CidBase + 5) // new titles( "みやび", CidBase + 6), // new titles( "やまと", CidBase + 7) }; ``` ```csharp public ScDeviceDriver() { ScDrvName = DrvName; ScDrvVersion = DrvVersion; ScDrvProdName = DrvProdName; ScDrvTextMaxLength = DrvTextMaxLength; CidBaseIndex = CidBase; AvatorParams = new Dictionary(); IsAlive = false; AItalk3Process = GetAItalk3Process(); if (AItalk3Process != null) { // 認識対象外、もしくはユーザ定義プリセットに割り当てるcidのカウンター int cbaseCounter = 1 + AITalk2Names.Select(v => v.FixedCid).Max(); if (cbaseCounter < (CidBase + SplitLine)) cbaseCounter = CidBase + SplitLine; try { _app = new WindowsAppFriend(AItalk3Process); uiTreeTop = WindowControl.FromZTop(_app); // 音声効果タブ選択 FormsTabControl ci = new FormsTabControl(uiTreeTop.IdentifyFromZIndex(2, 0, 0, 1, 0, 0, 1)); ci.EmulateTabSelect(0); // 音声効果 Thread.Sleep(10); // リストボックスから話者一覧を取得して処理 titles ent = null; AvatorListx = new FormsComboBox(uiTreeTop.IdentifyFromZIndex(2, 0, 0, 1, 0, 0, 0, 0, 0)); for (int avatorIdx = 0; avatorIdx < AvatorListx.ItemCount; avatorIdx++) { if (cbaseCounter >= (CidBase + MaxAvators)) break; AvatorListx.EmulateChangeSelect(avatorIdx); AItalk3.AvatorParam avator = new AItalk3.AvatorParam(); avator.AvatorIndex = avatorIdx; avator.IndexOfUserList = avatorIdx; avator.AvatorUI = new AItalk3.AvatorUIParam(); avator.AvatorUI.TalkTextBox = new WindowControl(uiTreeTop.Dynamic().ay); avator.AvatorUI.PlayButton = new FormsButton(uiTreeTop.Dynamic().a2); avator.AvatorUI.SaveButton = new FormsButton(uiTreeTop.Dynamic().a4); avator.AvatorUI.VolumeText = new FormsTextBox(uiTreeTop.Dynamic().cs); avator.AvatorUI.SpeedText = new FormsTextBox(uiTreeTop.Dynamic().cr); avator.AvatorUI.PitchText = new FormsTextBox(uiTreeTop.Dynamic().cq); avator.AvatorUI.IntonationText = new FormsTextBox(uiTreeTop.Dynamic().cp); avator.AvatorName = AvatorListx.Dynamic().SelectedItem.ItemText; // 認識している話者名ならば固定のcidを設定 try { ent = AITalk2Names.Where(v => v.Avator == avator.AvatorName).First(); avator.FixedCid = ent.FixedCid; } catch (Exception) { avator.FixedCid = cbaseCounter; cbaseCounter++; } // このタイミングで一旦登録する AvatorParams.Add(avator.FixedCid, avator); avator.VoiceEffects_default = new Dictionary { { EnumVoiceEffect.volume, new EffectValueInfo(GetSliderValue(avator.FixedCid, EnumVoiceEffect.volume), 0.0m, 2.0m, 0.01m)}, { EnumVoiceEffect.speed, new EffectValueInfo(GetSliderValue(avator.FixedCid, EnumVoiceEffect.speed), 0.5m, 4.0m, 0.01m)}, { EnumVoiceEffect.pitch, new EffectValueInfo(GetSliderValue(avator.FixedCid, EnumVoiceEffect.pitch), 0.5m, 2.0m, 0.01m)}, { EnumVoiceEffect.intonation, new EffectValueInfo(GetSliderValue(avator.FixedCid, EnumVoiceEffect.intonation), 0.0m, 2.0m, 0.01m)} }; avator.VoiceEffects = new Dictionary { { EnumVoiceEffect.volume, new EffectValueInfo(GetSliderValue(avator.FixedCid, EnumVoiceEffect.volume), 0.0m, 2.0m, 0.01m)}, { EnumVoiceEffect.speed, new EffectValueInfo(GetSliderValue(avator.FixedCid, EnumVoiceEffect.speed), 0.5m, 4.0m, 0.01m)}, { EnumVoiceEffect.pitch, new EffectValueInfo(GetSliderValue(avator.FixedCid, EnumVoiceEffect.pitch), 0.5m, 2.0m, 0.01m)} }; } } } } ```