努力したWiki

推敲の足りないメモ書き多数

ユーザ用ツール

サイト用ツール


documents:voiceroid:echoseika:echoseika-004

echoseika DLL 最終版ソース

2018/07/01
echoseikaは公開を終了いたしましたが、Win32 APIによるVOICEROID制御の資料として残しています。

ご自身で作成するアプリケーションの参考にソースの参照を行っていただくのは構いませんしそのように利用してもらう事を意図しています。

ソース

旧版は1本だったのですが、最終版はソースが複数に分かれています。
申し訳ないのですが全部の掲示ではなく、要素部分の掲示になります。

Avator.cs

Avator.cs
using System;
 
namespace echoSeikaAPI
{
    /// <summary>
    /// ターゲットアバター
    /// </summary>
    public enum Avator
    {
        /// <summary>
        /// VOICEROID+ 京町セイカ EX
        /// </summary>
        SEIKA,
        /// <summary>
        /// VOICEROID+ 鷹の爪 吉田くん EX
        /// </summary>
        YOSHIDA_EX,
        /// <summary>
        /// VOICEROID+ 月読アイ EX
        /// </summary>
        AI_EX,
        /// <summary>
        /// VOICEROID+ 月読ショウタ EX
        /// </summary>
        SHOUTA_EX,
        /// <summary>
        /// VOICEROID+ 水奈瀬コウ EX
        /// </summary>
        MINASE,
        /// <summary>
        /// VOICEROID+ 東北きりたん EX
        /// </summary>
        KIRITAN,
        /// <summary>
        /// VOICEROID+ 東北ずん子
        /// </summary>
        ZUNKO,
        /// <summary>
        /// VOICEROID+ 東北ずん子 EX
        /// </summary>
        ZUNKO_EX,
        /// <summary>
        /// VOICEROID+ 民安ともえ EX
        /// </summary>
        TAMMY_EX,
        /// <summary>
        /// VOICEROID+ 結月ゆかり EX
        /// </summary>
        YUKARI_EX,
        /// <summary>
        /// VOICEROID+ 琴葉茜
        /// </summary>
        AKANE,
        /// <summary>
        /// VOICEROID+ 琴葉葵
        /// </summary>
        AOI,
        /// <summary>
        /// VOICEROID+ 民安ともえ
        /// </summary>
        TAMMY,
        /// <summary>
        /// VOICEROID+ 結月ゆかり
        /// </summary>
        YUKARI,
        /// <summary>
        /// VOICEROID+ 鷹の爪 吉田くん
        /// </summary>
        YOSHIDA,
        /// <summary>
        /// 音街ウナTalk Ex
        /// </summary>
        UNA,
        /// <summary>
        /// Microsoft Speach Platform
        /// </summary>
        SPF,
        /// <summary>
        /// Speech API 5
        /// </summary>
        SAPI,
        /// <summary>
        /// CeVIOさとうささら
        /// </summary>
        SASARA,
        /// <summary>
        /// CeVIOすずきつづみ
        /// </summary>
        TSUZUMI,
        /// <summary>
        /// CeVIOタカハシ
        /// </summary>
        TAKAHASHI,
        /// <summary>
        /// CeVIO-ONE
        /// </summary>
        ONE,
        /// <summary>
        /// CeVIO-IA
        /// </summary>
        IA,
        /// <summary>
        /// VOICEROID2 琴葉茜(まだこれを使う機能は実装されていません)
        /// </summary>
        AKANE2,
        /// <summary>
        /// VOICEROID2 琴葉葵(まだこれを使う機能は実装されていません)
        /// </summary>
        AOI2,
        /// <summary>
        /// VOICEROID2 結月ゆかり(まだこれを使う機能は実装されていません)
        /// </summary>
        YUKARI2,
        /// <summary>
        /// VOICEROID2 紲星あかり(まだこれを使う機能は実装されていません)
        /// </summary>
        AKARI
    }
 
    /// <summary>
    /// プロダクト名サポートクラス
    /// </summary>
    public static class AvatorEx
    {
        /// <summary>
        /// プロダクト名
        /// </summary>
        /// <param name="value">アバター</param>
        /// <returns>名称文字列</returns>
        public static string ProdName(this Avator value)
        {
            string[] values =
            {
                "VOICEROID+ 京町セイカ EX",
                "VOICEROID+ 鷹の爪 吉田くん EX",
                "VOICEROID+ 月読アイ EX",
                "VOICEROID+ 月読ショウタ EX",
                "VOICEROID+ 水奈瀬コウ EX",
                "VOICEROID+ 東北きりたん EX",
                "VOICEROID+ 東北ずん子",
                "VOICEROID+ 東北ずん子 EX",
                "VOICEROID+ 民安ともえ EX",
                "VOICEROID+ 結月ゆかり EX",
                "VOICEROID+ 琴葉茜",
                "VOICEROID+ 琴葉葵",
                "VOICEROID+ 民安ともえ",
                "VOICEROID+ 結月ゆかり",
                "VOICEROID+ 鷹の爪 吉田くん",
                "音街ウナTalk Ex",
                "Microsoft 音声合成エンジン(Speech Platform)",
                "Microsoft 音声合成エンジン(SAPI)",
                "CeVIO-さとうささら",
                "CeVIO-すずきつづみ",
                "CeVIO-タカハシ",
                "CeVIO-ONE",
                "CeVIO-IA",
                "VOICEROID2 琴葉茜",
                "VOICEROID2 琴葉葵",
                "VOICEROID2 結月ゆかり",
                "VOICEROID2 紲星あかり"
            };
 
            return values[(int)value];
        }
        /// <summary>
        /// GUI構造(VOICEROID用)
        /// </summary>
        /// <param name="value">アバター(VOICEROID+/+EX用)</param>
        /// <returns>旧式GUIならtrue</returns>
        public static bool isOldType(this Avator value)
        {
            bool ans = false;
 
            switch (value)
            {
                case Avator.TAMMY:
                case Avator.YUKARI:
                case Avator.YOSHIDA:
                    ans = true;
                    break;
 
                default:
                    ans = false;
                    break;
            }
            return ans;
        }
        /// <summary>
        /// 製品種類
        /// </summary>
        /// <param name="value">アバター</param>
        /// <returns>そのアバターをサポートしている製品</returns>
        public static TTSProduct TTS_Products(this Avator value)
        {
            TTSProduct ans;
 
            switch (value)
            {
                case Avator.SEIKA:
                case Avator.YOSHIDA_EX:
                case Avator.AI_EX:
                case Avator.SHOUTA_EX:
                case Avator.MINASE:
                case Avator.KIRITAN:
                case Avator.ZUNKO:
                case Avator.ZUNKO_EX:
                case Avator.TAMMY_EX:
                case Avator.YUKARI_EX:
                case Avator.AKANE:
                case Avator.AOI:
                case Avator.TAMMY:
                case Avator.YUKARI:
                case Avator.YOSHIDA:
                case Avator.UNA:
                    ans = TTSProduct.VOICEROID;
                    break;
 
                case Avator.SASARA:
                case Avator.TSUZUMI:
                case Avator.TAKAHASHI:
                case Avator.ONE:
                case Avator.IA:
                    ans = TTSProduct.CEVIO;
                    break;
 
                case Avator.SPF:
                    ans = TTSProduct.MS_SPF;
                    break;
 
                case Avator.SAPI:
                    ans = TTSProduct.MS_SAPI;
                    break;
 
                case Avator.AKANE2:
                case Avator.AOI2:
                case Avator.YUKARI2:
                case Avator.AKARI:
                    ans = TTSProduct.VOICEROID2;
                    break;
 
                default:
                    ans = TTSProduct.VOICEROID;
                    break;
            }
            return ans;
        }
    }
 
    /// <summary>
    /// 音声効果パラメタ
    /// </summary>
    public enum VoiceEffectParam
    {
        /// <summary>
        /// 音声効果の音量
        /// </summary>
        volume,
 
        /// <summary>
        /// 音声効果の話速
        /// </summary>
        speed,
 
        /// <summary>
        /// 音声効果の高さ
        /// </summary>
        pitch,
 
        /// <summary>
        /// 音声効果の声質(CeVIO)
        /// </summary>
        alpha,
 
        /// <summary>
        /// 音声効果の抑揚
        /// </summary>
        intonation
    }
 
    /// <summary>
    /// 使用する音声合成製品
    /// </summary>
    public enum TTSProduct
    {
        /// <summary>
        /// VOICEROID+/+EX
        /// </summary>
        VOICEROID,
        /// <summary>
        /// 現在サポートされていません
        /// </summary>
        VOICEROID2,
        /// <summary>
        /// CeVIO
        /// </summary>
        CEVIO,
        /// <summary>
        /// Microsoft Speech Platform
        /// </summary>
        MS_SPF,
        /// <summary>
        /// Speech API
        /// </summary>
        MS_SAPI
    }
}

BaseInstance.cs

BaseInstance.cs
using System;
using System.Collections.Generic;
using System.Text;
 
namespace echoSeikaAPI
{
    class BaseInstance
    {
        /// <summary>
        /// 感情表現パラメータ保持
        /// </summary>
        protected class EmotionValue
        {
            public decimal value;
            public decimal value_min;
            public decimal value_max;
 
            public EmotionValue(decimal val, decimal min, decimal max)
            {
                value = val;
                value_min = min;
                value_max = max;
            }
        }
        /// <summary>
        /// 音声効果パラメータ保持
        /// </summary>
        protected class EffectValue
        {
            public decimal value;
            public decimal value_min;
            public decimal value_max;
            public decimal value_step;
 
            public EffectValue(decimal val, decimal min, decimal max, decimal step)
            {
                value = val;
                value_min = min;
                value_max = max;
                value_step = step;
            }
        }
 
        protected Dictionary<string, EmotionValue> emotions; // 感情表現パラメタ
        protected Dictionary<string, EffectValue> effects;   // 音声効果パラメタ
        private StringBuilder TalkTextSb = new StringBuilder();
        private StringBuilder WavFilePathSb = new StringBuilder();
        private decimal truncs(decimal val, int digits)
        {
            decimal scale = (decimal)Math.Pow(10, digits);
            decimal ans = val > 0 ? Math.Floor(val * scale) / scale : Math.Ceiling(val * scale) / scale;
 
            return ans;
        }
 
        public bool SetEffect(string ef, decimal value)
        {
            bool ans = false;
 
            if (effects.ContainsKey(ef))
            {
                EffectValue ev = effects[ef];
                if (value < ev.value_min)
                {
                    ev.value = ev.value_min;
                }
                else if (value > ev.value_max)
                {
                    ev.value = ev.value_max;
                }
                else
                {
                    ev.value = value;
                }
 
                ans = true;
            }
 
            return ans;
        }
        public bool SetEmotion(string em, decimal value)
        {
            bool ans = false;
 
            if (emotions.ContainsKey(em))
            {
                EmotionValue ev = emotions[em];
                if (value < ev.value_min)
                {
                    ev.value = ev.value_min;
                }
                else if ( value > ev.value_max)
                {
                    ev.value = ev.value_max;
                }
                else
                {
                    ev.value = value;
                }
 
                ans = true; 
            }
 
            return ans;
        }
        public string TalkText
        {
            set
            {
                TalkTextSb.Clear();
                TalkTextSb.Append(value);
            }
            get
            {
                return TalkTextSb.ToString();
            }
        }
        public string WavFilePath
        {
            set
            {
                WavFilePathSb.Clear();
                WavFilePathSb.Append(value);
            }
            get
            {
                return WavFilePathSb.ToString();
            }
        }
 
        public virtual bool isAlive { get; }
        public virtual void PlayVoice(bool async = true)
        {
        }
        public virtual void PlayVoiceWithSave()
        {
        }
        public virtual void SaveVoice()
        {
        }
        public virtual void SetTalkerName(string cvName)
        {
        }
        public virtual string[] GetTalkerList()
        {
            return new string[] { };
        }
 
        public virtual int WinPostMessageWait{ get; set; }
    }
}

VoiceroidInstance.cs

VoiceroidInstance.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
 
namespace echoSeikaAPI
{
    internal class VoiceroidInstance : BaseInstance
    {
        private Avator voiceroid;
        private enum UIhWnds
        {
            voiceroid_processid,
            voiceroid_mainwindow,
            voiceroid_mainwindow_child,
            voiceroid_textbox,
            voiceroid_playbutton,
            voiceroid_savebutton,
            voiceroid_effect_window,
            voiceroid_effect_window_child,
            voiceroid_pitch_slider,
            voiceroid_speed_slider,
            voiceroid_volume_slider,
            voiceroid_High_frequency,
            voiceroid_intonation_textbox,
            voiceroid_pitch_textbox,
            voiceroid_speed_textbox,
            voiceroid_volume_textbox,
            voiceroid_intonation_initbutton,
            voiceroid_pitch_initbutton,
            voiceroid_speed_initbutton,
            voiceroid_volume_initbutton,
            savedlg_mainwindow,
            savedlg_editbox,
            savedlg_savebutton
        };
        private Dictionary<UIhWnds, IntPtr> hMainWnds { get; }
        private Dictionary<UIhWnds, IntPtr> hDlgWnds;
        private IntPtr WndHRestor;
        private int RetryCount = 3;
        private int RetryWaitms = 1000;
        private int winPostMessageWait = 1000;
        private bool aliveInstance = false;
        private bool usePm = true;
 
        public override int WinPostMessageWait { set { winPostMessageWait = value < 100 ? 100 : value; } get { return winPostMessageWait; } }
 
        public VoiceroidInstance(Avator cv, bool use_pm = true)
        {
            voiceroid = cv;
            hMainWnds = new Dictionary<UIhWnds, IntPtr>();
            hDlgWnds = new Dictionary<UIhWnds, IntPtr>();
            usePm = use_pm;
 
            switch (cv)
            {
                case Avator.YUKARI:
                case Avator.TAMMY:
                case Avator.YOSHIDA:
                    effects = new Dictionary<string, EffectValue>
                    {
                        {"volume",     new EffectValue(1.0m, 0.0m, 2.0m, 0.05m)},
                        {"speed",      new EffectValue(1.0m, 0.5m, 2.0m, 0.10m)},
                        {"pitch",      new EffectValue(1.0m, 0.5m, 2.0m, 0.10m)},
                        {"alpha",      new EffectValue(0.0m, 0.0m, 0.0m, 0.00m)},
                        {"intonation", new EffectValue(1.0m, 0.0m, 2.0m, 0.05m)}
                    };
                    break;
 
                default:
                    effects = new Dictionary<string, EffectValue>
                    {
                        {"volume",     new EffectValue(1.0m, 0.0m, 2.0m, 0.01m)},
                        {"speed",      new EffectValue(1.0m, 0.5m, 4.0m, 0.01m)},
                        {"pitch",      new EffectValue(1.0m, 0.5m, 2.0m, 0.01m)},
                        {"alpha",      new EffectValue(0.0m, 0.0m, 0.0m, 0.00m)},
                        {"intonation", new EffectValue(1.0m, 0.0m, 2.0m, 0.01m)}
                    };
                    break;
            }
            emotions = new Dictionary<string, EmotionValue>() { }; // 感情パラメタはない
 
            ScanWindowHandles();
 
            if (hMainWnds[UIhWnds.voiceroid_mainwindow] != IntPtr.Zero) aliveInstance = true;
 
            // Zオーダー制御をしてみる
            SetWindowPos(hMainWnds[UIhWnds.voiceroid_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 
            // "Program Manager"の子ウインドウにしてみる
            if (usePm)
            {
                WndHRestor = GetParent(hMainWnds[UIhWnds.voiceroid_mainwindow]);
                IntPtr a = FindWindow(null, "Program Manager");
                if (a != null)
                {
                    SetParent(hMainWnds[UIhWnds.voiceroid_mainwindow], a);
                }
            }
        }
        ~VoiceroidInstance()
        {
            if (usePm) SetParent(hMainWnds[UIhWnds.voiceroid_mainwindow], WndHRestor);
        }
        public void ReScanWindowHandle()
        {
            hMainWnds.Clear();
            hDlgWnds.Clear();
 
            ScanWindowHandles();
        }
        public bool UnicodeText { get; set; }
        public override bool isAlive
        {
            get
            {
                return aliveInstance;
            }
        }
        public override void PlayVoice(bool async = true)
        {
            if (TalkText.Length == 0) return;
 
            switch (voiceroid)
            {
                case Avator.TAMMY:
                case Avator.YOSHIDA:
                    SetVoiceEffect_Voiceroid_Plus();
                    CopyTalkText_voiceroid_Plus();
                    PlayVoice_Voiceroid_Plus();
                    //if (!async) WaitPlaying2();  //再生終了待ちができなくなりました
                    break;
 
                case Avator.YUKARI:
                    //SetVoiceEffect_Voiceroid_Plus();
                    SetVoiceEffect_Voiceroid_Plus_2();
                    CopyTalkText_voiceroid_Plus();
                    PlayVoice_Voiceroid_Plus();
                    //if (!async) WaitPlaying2();  //再生終了待ちができなくなりました
                    break;
 
                case Avator.ZUNKO:
                    SetVoiceEffect_Voiceroid_Plus_Ex();
                    CopyTalkText_voiceroid_Plus_Ex();
                    PlayVoice_Voiceroid_Plus_Ex();
                    if (!async) WaitPlaying2();
                    break;
 
                default:
                    SetVoiceEffect_Voiceroid_Plus_Ex();
                    CopyTalkText_voiceroid_Plus_Ex();
                    PlayVoice_Voiceroid_Plus_Ex();
                    if (!async) WaitPlaying2();
                    break;
            }
        }
        //public override void PlayVoiceWithSave()
        //{
        //    if (TalkText.Length == 0) return;
 
        //    switch (voiceroid)
        //    {
        //        case Avator.TAMMY:
        //        case Avator.YOSHIDA:
        //            SetVoiceEffect_Voiceroid_Plus();
        //            CopyTalkText_voiceroid_Plus();
        //            SaveVoice_voiceroid_Plus();
        //            PlayVoice_Voiceroid_Plus();
        //            break;
 
        //        case Avator.YUKARI:
        //            SetVoiceEffect_Voiceroid_Plus_2();
        //            CopyTalkText_voiceroid_Plus();
        //            SaveVoice_voiceroid_Plus();
        //            PlayVoice_Voiceroid_Plus();
        //            break;
 
        //        case Avator.ZUNKO:
        //            SetVoiceEffect_Voiceroid_Plus_Ex();
        //            CopyTalkText_voiceroid_Plus_Ex();
        //            SaveVoice_voiceroid_Plus_2();
        //            PlayVoice_Voiceroid_Plus_Ex();
        //            break;
 
        //        default:
        //            SetVoiceEffect_Voiceroid_Plus_Ex();
        //            CopyTalkText_voiceroid_Plus_Ex();
        //            SaveVoice_voiceroid_Plus_Ex();
        //            PlayVoice_Voiceroid_Plus_Ex();
        //            break;
        //    }
        //}
        public override void SaveVoice()
        {
            if (TalkText.Length == 0) return;
 
            switch (voiceroid)
            {
                case Avator.TAMMY:
                case Avator.YOSHIDA:
                    SetVoiceEffect_Voiceroid_Plus();
                    CopyTalkText_voiceroid_Plus();
                    SaveVoice_voiceroid_Plus();
                    break;
 
                case Avator.YUKARI:
                    SetVoiceEffect_Voiceroid_Plus_2();
                    CopyTalkText_voiceroid_Plus();
                    SaveVoice_voiceroid_Plus();
                    break;
 
                case Avator.ZUNKO:
                    SetVoiceEffect_Voiceroid_Plus_Ex();
                    CopyTalkText_voiceroid_Plus_Ex();
                    SaveVoice_voiceroid_Plus_2();
                    break;
 
                default:
                    SetVoiceEffect_Voiceroid_Plus_Ex();
                    CopyTalkText_voiceroid_Plus_Ex();
                    SaveVoice_voiceroid_Plus_Ex();
                    break;
            }
        }
 
        private void ScanWindowHandles()
        {
            GetMainWindowHandle(voiceroid);
            switch (voiceroid)
            {
                case Avator.YUKARI:
                case Avator.TAMMY:
                case Avator.YOSHIDA:
                    GetMainWindowControlHandle_Voiceroid_Plus();
                    GetVoiceEffectWindowHandle_Voiceroid_Plus();
                    break;
 
                case Avator.ZUNKO:
                    GetMainWindowControlHandle_Voiceroid_Plus_2();
                    GetVoiceEffectWindowHandle_Voiceroid_Plus_Ex();
                    break;
 
                default:
                    GetMainWindowControlHandle_Voiceroid_Plus_Ex();
                    GetVoiceEffectWindowHandle_Voiceroid_Plus_Ex();
                    break;
            }
        }
        private void GetMainWindowHandle(Avator cv)
        {
            string winTitle1 = cv.ProdName();
            string winTitle2 = winTitle1 + "*";
 
            if (cv.isOldType())
            {
                for (int i = 0; i < RetryCount; i++)
                {
                    IntPtr hWnd1 = FindWindow("TkTopLevel", winTitle1);
                    IntPtr hWnd2 = FindWindow("TkTopLevel", winTitle2);
 
                    if (hWnd1 != IntPtr.Zero)
                    {
                        int processId1 = 0;
                        GetWindowThreadProcessId(hWnd1, out processId1);
 
                        hMainWnds.Add(UIhWnds.voiceroid_mainwindow, hWnd1);
                        hMainWnds.Add(UIhWnds.voiceroid_processid, (IntPtr)processId1);
                    }
                    if (hWnd2 != IntPtr.Zero)
                    {
                        int processId2 = 0;
                        GetWindowThreadProcessId(hWnd2, out processId2);
 
                        hMainWnds.Add(UIhWnds.voiceroid_mainwindow, hWnd2);
                        hMainWnds.Add(UIhWnds.voiceroid_processid, (IntPtr)processId2);
                    }
                    if ((hWnd1 != IntPtr.Zero) || (hWnd2 != IntPtr.Zero)) break;
                    if (i < (RetryCount - 1)) Thread.Sleep(RetryWaitms);
                }
            }
            else
            {
                IntPtr hWnd = IntPtr.Zero;
                IntPtr hWndDaddy = IntPtr.Zero;
                int processId = 0;
 
                for (int i = 0; i < RetryCount; i++)
                {
                    Process[] ps = Process.GetProcesses();
 
                    foreach (Process pitem in ps)
                    {
                        if ((pitem.MainWindowHandle != IntPtr.Zero) &&
                               ((pitem.MainWindowTitle.Equals(winTitle1)) || (pitem.MainWindowTitle.Equals(winTitle2))))
                        {
                            hWnd = pitem.MainWindowHandle;
                            processId = pitem.Id;
                            hMainWnds.Add(UIhWnds.voiceroid_mainwindow, hWnd);
                            hMainWnds.Add(UIhWnds.voiceroid_processid, (IntPtr)processId);
                        }
                    }
                    if (hWnd != IntPtr.Zero) break;
                    if (i < (RetryCount - 1)) Thread.Sleep(RetryWaitms);
                }
            }
 
            if (!hMainWnds.ContainsKey(UIhWnds.voiceroid_mainwindow))
            {
                hMainWnds.Add(UIhWnds.voiceroid_mainwindow, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_processid, IntPtr.Zero);
            }
 
            // Zオーダー制御をしてみる
            SetWindowPos(hMainWnds[UIhWnds.voiceroid_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
 
        }
        private void GetMainWindowControlHandle_Voiceroid_Plus_Ex()
        {
            IntPtr hWndMainWinPtr = hMainWnds[UIhWnds.voiceroid_mainwindow];
 
            if (hWndMainWinPtr == IntPtr.Zero)
            {
                hMainWnds.Add(UIhWnds.voiceroid_textbox, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_playbutton, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_savebutton, IntPtr.Zero);
                return;
            }
 
            IntPtr hWndWorkPtr = IntPtr.Zero;
 
            // テキストボックス
            hWndWorkPtr = hWndMainWinPtr;
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第1層ウインドウ
            hMainWnds.Add(UIhWnds.voiceroid_mainwindow_child, hWndWorkPtr);
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第2層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第3層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第4層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第5層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第6層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第7層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第8層ウインドウ(テキストボックス) 
            hMainWnds.Add(UIhWnds.voiceroid_textbox, hWndWorkPtr);
 
            // 再生ボタン
            hWndWorkPtr = hWndMainWinPtr;
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第1層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第2層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第3層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第4層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第5層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第6層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第7層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第7層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第8層ウインドウ(再生ボタン)
            hMainWnds.Add(UIhWnds.voiceroid_playbutton, hWndWorkPtr);
 
            // 音声保存ボタン
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT);    // 第8層2番目ウインドウ(停止ボタン)
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT);    // 第8層3番目ウインドウ(音声保存ボタン)
            hMainWnds.Add(UIhWnds.voiceroid_savebutton, hWndWorkPtr);
        }
        private void GetMainWindowControlHandle_Voiceroid_Plus_2()
        {
            IntPtr hWndMainWinPtr = hMainWnds[UIhWnds.voiceroid_mainwindow];
 
            if (hWndMainWinPtr == IntPtr.Zero)
            {
                hMainWnds.Add(UIhWnds.voiceroid_textbox, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_playbutton, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_savebutton, IntPtr.Zero);
                return;
            }
 
            IntPtr hWndWorkPtr = IntPtr.Zero;
 
            //テキストボックス
            hWndWorkPtr = hWndMainWinPtr;
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第1層ウインドウ
            hMainWnds.Add(UIhWnds.voiceroid_mainwindow_child, hWndWorkPtr);
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第2層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第3層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第4層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第5層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第6層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第7層ウインドウ(テキストボックス) 
            hMainWnds.Add(UIhWnds.voiceroid_textbox, hWndWorkPtr);
 
            //再生ボタン
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第7層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第8層ウインドウ(再生ボタン)
            hMainWnds.Add(UIhWnds.voiceroid_playbutton, hWndWorkPtr);
 
            //保存ボタン
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第8層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第8層3番目ウインドウ(音声保存ボタン)
            hMainWnds.Add(UIhWnds.voiceroid_savebutton, hWndWorkPtr);
        }
        private void GetMainWindowControlHandle_Voiceroid_Plus()
        {
            IntPtr hWndMainWinPtr = hMainWnds[UIhWnds.voiceroid_mainwindow];
 
            if (hWndMainWinPtr == IntPtr.Zero)
            {
                hMainWnds.Add(UIhWnds.voiceroid_textbox, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_playbutton, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_savebutton, IntPtr.Zero);
                return;
            }
 
            IntPtr hWndWorkPtr = IntPtr.Zero;
 
            //テキストボックス
            hWndWorkPtr = hWndMainWinPtr;
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第1層ウインドウ
            hMainWnds.Add(UIhWnds.voiceroid_mainwindow_child, hWndWorkPtr);
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第2層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層3番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第3層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第3層2番目ウインドウ(テキストボックス) 
            hMainWnds.Add(UIhWnds.voiceroid_textbox, hWndWorkPtr);
 
            //保存ボタン
            hWndWorkPtr = hWndMainWinPtr;
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第1層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第2層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第3層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第3層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第3層3番目ウインドウ(保存ボタン)
            hMainWnds.Add(UIhWnds.voiceroid_savebutton, hWndWorkPtr);
 
            //再生ボタン
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第3層4番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第3層5番目ウインドウ(再生ボタン)
            hMainWnds.Add(UIhWnds.voiceroid_playbutton, hWndWorkPtr);
        }
        private void GetVoiceEffectWindowHandle_Voiceroid_Plus_Ex()
        {
            IntPtr hWndWorkPtr = hMainWnds[UIhWnds.voiceroid_mainwindow];
 
            if (hWndWorkPtr == IntPtr.Zero)
            {
                hMainWnds.Add(UIhWnds.voiceroid_intonation_initbutton, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_pitch_initbutton, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_speed_initbutton, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_volume_initbutton, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_intonation_textbox, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_pitch_textbox, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_speed_textbox, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_volume_textbox, IntPtr.Zero);
 
                return;
            }
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第1層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第2層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第3層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第4層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第4層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第5層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第6層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第6層2番目ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第7層ウインドウ
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第8層1番目ウインドウ(抑揚初期値ボタン) 
            hMainWnds.Add(UIhWnds.voiceroid_intonation_initbutton, hWndWorkPtr);
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第8層2番目ウインドウ(高さ初期値ボタン) 
            hMainWnds.Add(UIhWnds.voiceroid_pitch_initbutton, hWndWorkPtr);
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第8層3番目ウインドウ(話速初期値ボタン) 
            hMainWnds.Add(UIhWnds.voiceroid_speed_initbutton, hWndWorkPtr);
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第8層4番目ウインドウ(音量初期値ボタン) 
            hMainWnds.Add(UIhWnds.voiceroid_volume_initbutton, hWndWorkPtr);
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第8層5番目ウインドウ(抑揚) 
            hMainWnds.Add(UIhWnds.voiceroid_intonation_textbox, hWndWorkPtr);
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第8層6番目ウインドウ(高さ) 
            hMainWnds.Add(UIhWnds.voiceroid_pitch_textbox, hWndWorkPtr);
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第8層7番目ウインドウ(話速) 
            hMainWnds.Add(UIhWnds.voiceroid_speed_textbox, hWndWorkPtr);
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第8層8番目ウインドウ(音量) 
            hMainWnds.Add(UIhWnds.voiceroid_volume_textbox, hWndWorkPtr);
        }
        private void GetVoiceEffectWindowHandle_Voiceroid_Plus()
        {
            IntPtr hWnd = IntPtr.Zero;
            int voiceroidProcessId = (int)hMainWnds[UIhWnds.voiceroid_processid];
 
            hWnd = FindWindow("TkTopLevel", "音声効果");
 
            if (hWnd != IntPtr.Zero)
            {
                int processId = 0;
 
                while (!hWnd.Equals(IntPtr.Zero))
                {
                    GetWindowThreadProcessId(hWnd, out processId);
                    if (processId == voiceroidProcessId)
                    {
                        break;
                    }
                    else
                    {
                        hWnd = GetWindow(hWnd, GW_HWNDNEXT);
                    }
                }
            }
 
            if (hWnd == IntPtr.Zero)
            {
                hMainWnds.Add(UIhWnds.voiceroid_effect_window, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_effect_window_child, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_High_frequency, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_pitch_slider, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_speed_slider, IntPtr.Zero);
                hMainWnds.Add(UIhWnds.voiceroid_volume_slider, IntPtr.Zero);
 
                return;
            }
 
            IntPtr hWndWorkPtr = hWnd;
 
            hMainWnds.Add(UIhWnds.voiceroid_effect_window, hWndWorkPtr);
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第1層ウインドウ
            hMainWnds.Add(UIhWnds.voiceroid_effect_window_child, hWndWorkPtr);
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD);    // 第2層1番目ウインドウ(高域強調と出荷時の設定に戻すボタン)
            hMainWnds.Add(UIhWnds.voiceroid_High_frequency, hWndWorkPtr);
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層2番目ウインドウ(エコー:ゲイン)
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層3番目ウインドウ(エコー:タイム)
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層4番目ウインドウ(ピッチ) 
            hMainWnds.Add(UIhWnds.voiceroid_pitch_slider, hWndWorkPtr);
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層5番目ウインドウ(速度) 
            hMainWnds.Add(UIhWnds.voiceroid_speed_slider, hWndWorkPtr);
 
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT); // 第2層6番目ウインドウ(音量) 
            hMainWnds.Add(UIhWnds.voiceroid_volume_slider, hWndWorkPtr);
        }
        private void SetVoiceEffect_init_Voiceroid_Plus_Ex()
        {
            SendMessage(hMainWnds[UIhWnds.voiceroid_intonation_initbutton], BM_CLICK, 0, 0);             // 抑揚初期化ボタンクリック
            SendMessage(hMainWnds[UIhWnds.voiceroid_pitch_initbutton], BM_CLICK, 0, 0);                  // 高さ初期化ボタンクリック
            SendMessage(hMainWnds[UIhWnds.voiceroid_speed_initbutton], BM_CLICK, 0, 0);                  // 話速初期化ボタンクリック
            SendMessage(hMainWnds[UIhWnds.voiceroid_volume_initbutton], BM_CLICK, 0, 0);                 // 音量初期化ボタンクリック
        }
        private void SetVoiceEffect_init_Voiceroid_Plus()
        {
            SendMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_SETFOCUS, 0, 0);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_F7, 0x00410001); // 初期化(F7押下
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_F7, 0xC0410001);
        }
        private void SetVoiceEffect_Voiceroid_Plus_Ex()
        {
            SetVoiceEffect_init_Voiceroid_Plus_Ex();
 
            SendMessage(hMainWnds[UIhWnds.voiceroid_intonation_textbox], EM_SETSEL, 0, UInt32.MaxValue); // 抑揚を選択
            SetClipboard(effects["intonation"].value.ToString());                                        // 抑揚の値をクリップボードに転記
            SendMessage(hMainWnds[UIhWnds.voiceroid_intonation_textbox], WM_PASTE, 0, 0);                // 抑揚数値をペースト
            PostMessage(hMainWnds[UIhWnds.voiceroid_intonation_textbox], WM_KEYDOWN, VK_RETURN, 0);      // 抑揚数値を確定
 
            SendMessage(hMainWnds[UIhWnds.voiceroid_pitch_textbox], EM_SETSEL, 0, UInt32.MaxValue);      // 高さを選択
            SetClipboard(effects["pitch"].value.ToString());                                             // 高さの値をクリップボードに転記
            SendMessage(hMainWnds[UIhWnds.voiceroid_pitch_textbox], WM_PASTE, 0, 0);                     // 高さ数値をペースト
            PostMessage(hMainWnds[UIhWnds.voiceroid_pitch_textbox], WM_KEYDOWN, VK_RETURN, 0);           // 高さ数値を確定
 
            SendMessage(hMainWnds[UIhWnds.voiceroid_speed_textbox], EM_SETSEL, 0, UInt32.MaxValue);      // 話速を選択
            SetClipboard(effects["speed"].value.ToString());                                             // 話速の値をクリップボードに転記
            SendMessage(hMainWnds[UIhWnds.voiceroid_speed_textbox], WM_PASTE, 0, 0);                     // 話速数値をペースト
            PostMessage(hMainWnds[UIhWnds.voiceroid_speed_textbox], WM_KEYDOWN, VK_RETURN, 0);           // 話速数値を確定
 
            SendMessage(hMainWnds[UIhWnds.voiceroid_volume_textbox], EM_SETSEL, 0, UInt32.MaxValue);     // 音量を選択
            SetClipboard(effects["volume"].value.ToString());                                            // 音量の値をクリップボードに転記
            SendMessage(hMainWnds[UIhWnds.voiceroid_volume_textbox], WM_PASTE, 0, 0);                    // 音量数値をペースト
            PostMessage(hMainWnds[UIhWnds.voiceroid_volume_textbox], WM_KEYDOWN, VK_RETURN, 0);          // 音量数値を確定
        }
        private void SetVoiceEffect_Voiceroid_Plus()
        {
            SetVoiceEffect_init_Voiceroid_Plus();
 
            SendMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_SETFOCUS, 0, 0);
 
            // 音量を選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
            if (effects["volume"].value != 1.0m) TuneVoiceEffectSlider_Voiceroid_Plus(0.00m, 2.00m, 0.05m, effects["volume"].value);
 
            // 速度を選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
            if (effects["speed"].value != 1.0m) TuneVoiceEffectSlider_Voiceroid_Plus(0.50m, 2.00m, 0.10m, effects["speed"].value);
 
            // ピッチを選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
            if (effects["pitch"].value != 1.0m) TuneVoiceEffectSlider_Voiceroid_Plus(0.50m, 2.00m, 0.10m, effects["pitch"].value);
 
            // エコー:タイムを選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
 
            // エコー:ゲインを選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
 
            // 高域強調を選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
        }
        private void SetVoiceEffect_Voiceroid_Plus_2()
        {
            SetVoiceEffect_init_Voiceroid_Plus();
 
            SendMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_SETFOCUS, 0, 0);
 
            // 音量を選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
            if (effects["volume"].value != 1.0m) TuneVoiceEffectSlider_Voiceroid_Plus(0.00m, 2.00m, 0.01m, effects["volume"].value);
 
            // 速度を選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
            if (effects["speed"].value != 1.0m) TuneVoiceEffectSlider_Voiceroid_Plus(0.50m, 2.00m, 0.01m, effects["speed"].value);
 
            // ピッチを選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
            if (effects["pitch"].value != 1.0m) TuneVoiceEffectSlider_Voiceroid_Plus(0.50m, 2.00m, 0.01m, effects["pitch"].value);
 
            // エコー:タイムを選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
 
            // エコー:ゲインを選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
 
            // 高域強調を選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
 
            // 出荷時の設定に戻すを選択
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_CHAR, VK_TAB, 0x000F0001);
            PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_TAB, 0xC00F0001);
        }
        private void TuneVoiceEffectSlider_Voiceroid_Plus(decimal min, decimal max, decimal step, decimal val)
        {
            decimal value = val;
 
            if (1.00m < value)
            {
                value = max < value ? max : value;
                for (decimal count = 1.00m; count < value; count += step)
                {
                    PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_RIGHT, 0x014D0001);
                    PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_RIGHT, 0xC14D0001);
                }
            }
            else
            {
                value = min > value ? min : value;
                for (decimal count = 1.00m; count > value; count -= step)
                {
                    PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYDOWN, VK_LEFT, 0x014B0001);
                    PostMessage(hMainWnds[UIhWnds.voiceroid_effect_window_child], WM_KEYUP, VK_LEFT, 0xC14B0001);
                }
            }
        }
        private void CopyTalkText_voiceroid_Plus_Ex()
        {
            // 多分VOICEROID+EXで有効な方法
            WaitPlaying();
            SendMessage(hMainWnds[UIhWnds.voiceroid_textbox], EM_SETSEL, 0, UInt32.MaxValue); // 全テキストを選択
            SetClipboard(TalkText);                                                           // クリップボードに転記
            SendMessage(hMainWnds[UIhWnds.voiceroid_textbox], WM_PASTE, 0, 0);                // クリップボードの内容をペースト
        }
        private void CopyTalkText_voiceroid_Plus_2()
        {
            // 多分VOICEROID+の新しい方で有効
            SendMessage(hMainWnds[UIhWnds.voiceroid_mainwindow], WM_COMMAND, 60, 0);          // メニューの全て選択
            //SendMessage(hMainWnds[UIhWnds.voiceroid_mainwindow], WM_COMMAND, 52, 0);        // メニューの削除
            SetClipboard(TalkText);                                                           // クリップボードに転記
            SendMessage(hMainWnds[UIhWnds.voiceroid_mainwindow], WM_COMMAND, 56, 0);          // メニューの貼り付け
        }
        private void CopyTalkText_voiceroid_Plus()
        {
            // 多分VOICEROID+の初期型で有効
            SendMessage(hMainWnds[UIhWnds.voiceroid_mainwindow], WM_COMMAND, 46, 0);          // メニューの元に戻す
            SetClipboard(TalkText);                                                           // クリップボードに転記
            SendMessage(hMainWnds[UIhWnds.voiceroid_mainwindow], WM_COMMAND, 56, 0);          // メニューの貼り付け
        }
        private void GetSaveDialogWindowHandle_Type1(string dlgtitle, int retryCount, int retryWaitms)
        {
            IntPtr hWndWorkPtr = IntPtr.Zero;
            IntPtr hWndDlgWinPtr = IntPtr.Zero;
            IntPtr hWndDaddy = IntPtr.Zero;
            IntPtr hParentWnd = hMainWnds[UIhWnds.voiceroid_mainwindow];
 
            hDlgWnds.Clear();
 
            for (int i = 0; i < retryCount; i++)
            {
                hWndWorkPtr = FindWindow("#32770", dlgtitle); // "#32770 (ダイアログ)" はダイアログのクラス名?
 
                if (hWndWorkPtr != IntPtr.Zero)
                {
                    while (!hWndWorkPtr.Equals(IntPtr.Zero))
                    {
                        hWndDaddy = GetParent(hWndWorkPtr);
                        if (hParentWnd.Equals(hWndDaddy))
                        {
                            break;
                        }
                        else
                        {
                            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_HWNDNEXT);
                        }
                    }
                }
 
                if (hParentWnd.Equals(hWndDaddy)) break;
                if (i < (retryCount - 1)) Thread.Sleep(retryWaitms);
            }
            hWndDlgWinPtr = hWndWorkPtr;
 
            if (hWndDlgWinPtr == IntPtr.Zero)
            {
                hDlgWnds.Add(UIhWnds.savedlg_mainwindow, IntPtr.Zero);
                hDlgWnds.Add(UIhWnds.savedlg_editbox, IntPtr.Zero);
                hDlgWnds.Add(UIhWnds.savedlg_savebutton, IntPtr.Zero);
                return;
            }
 
            // Zオーダー制御をしてみる
            SetWindowPos(hWndDlgWinPtr, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 
            // ダイアログウインドウハンドル
            hDlgWnds.Add(UIhWnds.savedlg_mainwindow, hWndDlgWinPtr);
 
            // テキストボックス
            hWndWorkPtr = hWndDlgWinPtr;
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD); // 第1層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD); // 第2層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD); // 第3層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD); // 第4層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD); // 第5層ウインドウ
            hDlgWnds.Add(UIhWnds.savedlg_editbox, hWndWorkPtr); // テキストボックス
 
            // 保存ボタン
            hWndWorkPtr = FindWindowEx(hWndDlgWinPtr, IntPtr.Zero, "Button", "保存(&S)"); // 配下の保存ボタン
            hDlgWnds.Add(UIhWnds.savedlg_savebutton, hWndWorkPtr);
 
        }
        private void GetSaveDialogWindowHandle_Type2(string dlgtitle, int retryCount, int retryWaitms)
        {
            IntPtr hWnd = IntPtr.Zero;
            IntPtr hWndWorkPtr = IntPtr.Zero;
            IntPtr hWndDlgWinPtr = IntPtr.Zero;
            int processId = 0;
            int voiceroidProcessId = (int)hMainWnds[UIhWnds.voiceroid_processid];
 
            hDlgWnds.Clear();
 
            for (int i = 0; i < retryCount; i++)
            {
                hWnd = FindWindow("#32770", dlgtitle); // "#32770 (ダイアログ)" はダイアログのクラス名?
 
                if (hWnd != IntPtr.Zero)
                {
                    while (!hWnd.Equals(IntPtr.Zero))
                    {
                        GetWindowThreadProcessId(hWnd, out processId);
                        if (processId == voiceroidProcessId)
                        {
                            break;
                        }
                        else
                        {
                            hWnd = GetWindow(hWnd, GW_HWNDNEXT);
                        }
                    }
                }
 
                if (voiceroidProcessId == processId) break;
                if (i < (retryCount - 1)) Thread.Sleep(retryWaitms);
            }
 
            hWndDlgWinPtr = hWnd;
 
            if (hWndDlgWinPtr == IntPtr.Zero)
            {
                hDlgWnds.Add(UIhWnds.savedlg_editbox, IntPtr.Zero);
                hDlgWnds.Add(UIhWnds.savedlg_savebutton, IntPtr.Zero);
                return;
            }
 
            // Zオーダー制御をしてみる
            SetWindowPos(hWndDlgWinPtr, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 
            // ダイアログウインドウハンドル
            hDlgWnds.Add(UIhWnds.savedlg_mainwindow, hWndDlgWinPtr);
 
            // テキストボックス
            hWndWorkPtr = hWndDlgWinPtr;
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD); // 第1層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD); // 第2層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD); // 第3層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD); // 第4層ウインドウ
            hWndWorkPtr = GetWindow(hWndWorkPtr, GW_CHILD); // 第5層ウインドウ
            hDlgWnds.Add(UIhWnds.savedlg_editbox, hWndWorkPtr); // テキストボックス
 
            // 保存ボタン
            hWndWorkPtr = FindWindowEx(hWndDlgWinPtr, IntPtr.Zero, "Button", "保存(&S)"); // 配下の保存ボタン
            hDlgWnds.Add(UIhWnds.savedlg_savebutton, hWndWorkPtr);
 
        }
        private void PlayVoice_Voiceroid_Plus_Ex()
        {
            SendMessage(hMainWnds[UIhWnds.voiceroid_playbutton], BM_CLICK, 0, 0); // 再生ボタンクリック
        }
        private void PlayVoice_Voiceroid_Plus_2()
        {
            SendMessage(hMainWnds[UIhWnds.voiceroid_playbutton], WM_NULL, 0, 0); // 再生ボタンクリック
        }
        private void PlayVoice_Voiceroid_Plus()
        {
            SendMessage(hMainWnds[UIhWnds.voiceroid_playbutton], WM_NULL, 0, 0); // 再生ボタンクリック
        }
        private void SaveVoice_voiceroid_Plus_Ex()
        {
            if (WavFilePath.Length == 0) return;
 
            SetupOutputFiles(WavFilePath);
 
            PostMessage(hMainWnds[UIhWnds.voiceroid_savebutton], BM_CLICK, 0, 0); // 音声保存ボタンクリック
 
            Thread.Sleep(winPostMessageWait);
            GetSaveDialogWindowHandle_Type1("音声ファイルの保存", 300, 100);
 
            // Zオーダー制御をしてみる
            SetWindowPos(hDlgWnds[UIhWnds.savedlg_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
            SetWindowPos(hMainWnds[UIhWnds.voiceroid_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 
            SaveDialogControl(WavFilePath.ToString());
            SetWindowPos(hMainWnds[UIhWnds.voiceroid_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
        }
        private void SaveVoice_voiceroid_Plus_2()
        {
            if (WavFilePath.Length == 0) return;
 
            SetupOutputFiles(WavFilePath);
 
            PostMessage(hMainWnds[UIhWnds.voiceroid_savebutton], BM_CLICK, 0, 0); // 音声保存ボタンクリック
 
            Thread.Sleep(winPostMessageWait);
            GetSaveDialogWindowHandle_Type2("音声ファイルの保存", 300, 100);
 
            // Zオーダー制御をしてみる
            SetWindowPos(hDlgWnds[UIhWnds.savedlg_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
            SetWindowPos(hMainWnds[UIhWnds.voiceroid_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 
            SaveDialogControl(WavFilePath.ToString());
            SetWindowPos(hMainWnds[UIhWnds.voiceroid_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
        }
        private void SaveVoice_voiceroid_Plus()
        {
            if (WavFilePath.Length == 0) return;
 
            SetupOutputFiles(WavFilePath);
 
            PostMessage(hMainWnds[UIhWnds.voiceroid_savebutton], WM_NULL, 0, 0); // 音声保存ボタンクリック
 
            Thread.Sleep(winPostMessageWait);
            GetSaveDialogWindowHandle_Type1("音声ファイルの保存", 300, 100);
 
            // Zオーダー制御をしてみる
            SetWindowPos(hDlgWnds[UIhWnds.savedlg_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
            SetWindowPos(hMainWnds[UIhWnds.voiceroid_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 
            SaveDialogControl(WavFilePath.ToString());
            SetWindowPos(hMainWnds[UIhWnds.voiceroid_mainwindow], HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
        }
        private void SaveDialogControl(string filenamePath)
        {
 
            if (!hDlgWnds[UIhWnds.savedlg_mainwindow].Equals(IntPtr.Zero))
            {
                StringBuilder sb = new StringBuilder(filenamePath);
 
                SendMessage(hDlgWnds[UIhWnds.savedlg_editbox], WM_SETTEXT, 0, sb);
                SendMessage(hDlgWnds[UIhWnds.savedlg_savebutton], BM_CLICK, 0, 0);
            }
 
            Thread.Sleep(100);
        }
        private void SetupOutputFiles(string WavFilePath)
        {
            FileInfo fi = new FileInfo(WavFilePath);
            string TxtFilePath = Regex.Replace(fi.FullName, fi.Extension + "$", ".txt");
            try
            {
                if (fi.Exists) File.Delete(WavFilePath);
            }
            catch (Exception)
            {
                //
            }
            try
            {
                if (File.Exists(TxtFilePath)) File.Delete(TxtFilePath);
            }
            catch (Exception)
            {
                //
            }
        }
        private void WaitPlaying()
        {
            int winTextLen = 0;
            int count = 0;
 
            while (true)
            {
                winTextLen = GetWindowTextLength(hMainWnds[UIhWnds.voiceroid_playbutton]);
 
                if (0 < winTextLen)
                {
                    StringBuilder sb = new StringBuilder(winTextLen + 1);
                    GetWindowText(hMainWnds[UIhWnds.voiceroid_playbutton], sb, sb.Capacity);
 
                    if (sb.ToString() == " 再生")  // 文字列先頭が空白なので注意
                    {
                        break;
                    }
                    else
                    {
                        count++;
                        Thread.Sleep(100);
                        if (1800 < count) break; // 3分待ったら待つの止めるよ!
                    }
                }
            }
        }
        private void WaitPlaying2()
        {
            int winTextLen = 0;
            int count = 0;
 
            // VOICEROID +EX はキャプションの変化が遅い模様
 
            while (true)
            {
                winTextLen = GetWindowTextLength(hMainWnds[UIhWnds.voiceroid_playbutton]);
 
                if (0 < winTextLen)
                {
                    StringBuilder sb = new StringBuilder(winTextLen + 1);
                    GetWindowText(hMainWnds[UIhWnds.voiceroid_playbutton], sb, sb.Capacity);
 
                    if (sb.ToString() != " 再生")  // 文字列先頭が空白なので注意
                    {
                        break;
                    }
                    else
                    {
                        count++;
                        Thread.Sleep(100);
                        if (1800 < count) break; // 3分待ったら次のループへ移るよ!
                    }
                }
            }
 
            winTextLen = 0;
            count = 0;
            while (true)
            {
                winTextLen = GetWindowTextLength(hMainWnds[UIhWnds.voiceroid_playbutton]);
 
                if (0 < winTextLen)
                {
                    StringBuilder sb = new StringBuilder(winTextLen + 1);
                    GetWindowText(hMainWnds[UIhWnds.voiceroid_playbutton], sb, sb.Capacity);
 
                    if (sb.ToString() == " 再生")  // 文字列先頭が空白なので注意
                    {
                        break;
                    }
                    else
                    {
                        count++;
                        Thread.Sleep(100);
                        if (1800 < count) break; // 3分待ったら待つの止めるよ!
                    }
                }
            }
        }
        private void SetClipboard(string text)
        {
            Thread t = new Thread(() => {
                Clipboard.SetText(text, (UnicodeText ? TextDataFormat.UnicodeText : TextDataFormat.Text));
            });
            t.SetApartmentState(ApartmentState.STA);
            t.Start();
            t.Join();
        }
 
        private const uint WM_NULL = 0x0000;
        private const uint WM_ACTIVATE = 0x0006;
        private const uint WM_SETFOCUS = 0x0007;
        private const uint WM_SETTEXT = 0x000C;
        private const uint WM_PAINT = 0x000F;
        private const uint WM_SHOWWINDOW = 0x0018;
        private const uint WM_SETCURSOR = 0x0020;
        private const uint WM_NEXTDLGCTL = 0x0028;
        private const uint WM_WINDOWPOSCHANGING = 0x0046;
        private const uint WM_NOTIFY = 0x004E;
        private const uint WM_NCACTIVATE = 0x0086;
        private const uint WM_KEYDOWN = 0x0100;
        private const uint WM_KEYUP = 0x0101;
        private const uint WM_CHAR = 0x0102;
        private const uint WM_COMMAND = 0x0111;
        private const uint WM_HSCROLL = 0x114;
        private const uint WM_VSCROLL = 0x115;
        private const uint WM_IME_SETCONTEXT = 0x0281;
        private const uint WM_IME_NOTIFY = 0x0282;
        private const uint WM_PASTE = 0x0302;
        private const uint TBM_GETPOS = 0x400;
        private const uint TBM_SETPOS = 0x405;
        private const uint EM_SETSEL = 0x00B1;
        private const uint BM_CLICK = 0x00F5;
        private const uint GW_HWNDNEXT = 0x0002;
        private const uint GW_CHILD = 0x0005;
        private const int VK_TAB = 0x09;
        private const int VK_RETURN = 0x0D;
        private const int VK_LEFT = 0x25;
        private const int VK_RIGHT = 0x27;
        private const int VK_F7 = 0x76;
        private const int SB_LINELEFT = 0x00;
        private const int SB_LINERIGHT = 0x01;
        private const int IMN_SETCOMPOSITIONWINDOW = 0x0B;
        private const int IMN_OPENSTATUSWINDOW = 0x02;
        private const int IMN_CLOSESTATUSWINDOW = 0x01;
        private const int WA_ACTIVE = 1;
 
        private const int SWP_NOSIZE = 0x0001;
        private const int SWP_NOMOVE = 0x0002;
        private const int SWP_NOZORDER = 0x0004;
        private const int SWP_NOREDRAW = 0x0008;
        private const int SWP_NOACTIVATE = 0x0010;
        private const int SWP_FRAMECHANGED = 0x0020;
        private const int SWP_SHOWWINDOW = 0x0040;
        private const int SWP_HIDEWINDOW = 0x0080;
        private const int SWP_NOCOPYBITS = 0x0100;
        private const int SWP_NOOWNERZORDER = 0x0200;
        private const int SWP_NOSENDCHANGING = 0x400;
        private const int SWP_DEFERERASE = 0x2000;
        private const int SWP_ASYNCWINDOWPOS = 0x4000;
        private const int SWP_DRAWFRAME = SWP_FRAMECHANGED;
        private const int SWP_NOREPOSITION = SWP_NOOWNERZORDER;
 
        private const int HWND_TOP = 0;
        private const int HWND_BOTTOM = 1;
        private const int HWND_TOPMOST = -1;
        private const int HWND_NOTOPMOST = -2;
 
 
        [DllImport("user32.dll")]
        private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
 
        [DllImport("user32.dll")]
        private static extern IntPtr GetParent(IntPtr hWnd);
 
        [DllImport("user32.dll")]
        private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent);
 
        [DllImport("user32.dll")]
        private static extern int PostMessage(IntPtr hWnd, uint Msg, int wParam, uint lParam);
 
        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, uint lParam);
 
        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, IntPtr lParam);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, string lParam);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowTextLength(IntPtr hWnd);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpString);
 
        [DllImport("user32.dll")]
        private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
 
        [DllImport("user32.dll")]
        private static extern IntPtr SetFocus(IntPtr hWnd);
 
        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int uFlags);
    }
}

CevioInstance.cs

CevioInstance.cs
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Reflection;
//using CeVIO.Talk.RemoteService;
 
namespace echoSeikaAPI
{
    internal class CevioInstance : BaseInstance
    {
        //private dynamic service;
        private dynamic cevioTalker;
        //private Talker cevioTalker;
        private dynamic takerList;
        private double timeout = 3 * 60 * 1000;
        private bool aliveInstance = false;
 
        public CevioInstance(Avator cv)
        {
            try
            {
                string cvname = Regex.Replace(cv.ProdName(), @"^CeVIO-", "");// 先頭の "CeVIO-"を削ってるよ
 
                //Type t1 = Type.GetTypeFromProgID("CeVIO.Talk.RemoteService.ServiceControl");
                Type t2 = Type.GetTypeFromProgID("CeVIO.Talk.RemoteService.Talker");
 
                //service = Activator.CreateInstance(t1);
                //service.StartHost(false);
                cevioTalker = Activator.CreateInstance(t2);
                //cevioTalker = new Talker();
                cevioTalker.Cast = cvname;
 
                effects = new Dictionary<string, EffectValue>
                {
                    {"volume",     new EffectValue( (uint)cevioTalker.Volume,    0.0m, 100.0m, 1.0m) },
                    {"speed",      new EffectValue( (uint)cevioTalker.Speed,     0.0m, 100.0m, 1.0m) },
                    {"pitch",      new EffectValue( (uint)cevioTalker.Tone,      0.0m, 100.0m, 1.0m) },
                    {"alpha",      new EffectValue( (uint)cevioTalker.Alpha,     0.0m, 100.0m, 1.0m) },
                    {"intonation", new EffectValue( (uint)cevioTalker.ToneScale, 0.0m, 100.0m, 1.0m) }
                };
 
                emotions = new Dictionary<string, EmotionValue>();
                for (int i = 0; i < cevioTalker.Components.Count; i++)
                {
                    emotions.Add(cevioTalker.Components[i].Name, new EmotionValue((decimal)cevioTalker.Components[i].Value, 0.00m, 100.0m));
                }
 
                aliveInstance = true;
            }
            catch (Exception e)
            {
                //Console.WriteLine(e.Message);
                aliveInstance = false;
            }
        }
        ~CevioInstance()
        {
            // ServiceControl.CloseHost();
        }
 
        public override bool isAlive
        {
            get
            {
                return aliveInstance;
            }
        }
        public override void PlayVoice(bool async = true)
        {
            ApplyEffectParameters();
            ApplyEmotionParameters();
 
            dynamic status = cevioTalker.Speak(TalkText);  //SpeakingState status = cevioTalker.Speak(TalkText);
            if (!async)
            {
                status.Wait(timeout);
            }
        }
        public override void SaveVoice()
        {
            ApplyEffectParameters();
            ApplyEmotionParameters();
 
            string WavFileName = WavFilePath;
            if (!Regex.IsMatch(WavFileName, @"\.[Ww][Aa][Vv]$"))
            {
                WavFileName += ".wav";
            }
            cevioTalker.OutputWaveToFile(TalkText, WavFileName);
        }
        public override string[] GetTalkerList()
        {
            takerList = cevioTalker.AvailableCasts;
            return takerList.Core;
 
 
            //return Talker.AvailableCasts;
        }
 
        private void ApplyEmotionParameters()
        {
            if (emotions.Count != 0)
            {
                foreach (KeyValuePair<string, EmotionValue> item in emotions)
                {
                    cevioTalker.Components[item.Key].Value = (uint)(emotions[item.Key].value);
                }
            }
        }
        private void ApplyEffectParameters()
        {
            if (emotions.Count != 0)
            {
                foreach (KeyValuePair<string, EffectValue> item in effects)
                {
                    switch (item.Key)
                    {
                        case "volume":
                            cevioTalker.Volume = (uint)(item.Value.value);
                            break;
                        case "speed":
                            cevioTalker.Speed = (uint)(item.Value.value);
                            break;
                        case "pitch":
                            cevioTalker.Tone = (uint)(item.Value.value);
                            break;
                        case "alpha":
                            cevioTalker.Alpha = (uint)(item.Value.value);
                            break;
                        case "intonation":
                            cevioTalker.ToneScale = (uint)(item.Value.value);
                            break;
                    }
                }
            }
        }
 
    }
}

SapiInstance.cs

SapiInstance.cs
using System;
using System.Collections.Generic;
using SpeechLib;
using System.Text.RegularExpressions;
using System.Threading;
 
namespace echoSeikaAPI
{
    internal class SapiInstance : BaseInstance
    {
        private SpVoice sapi = null;
        private ISpeechObjectTokens talkerList = null;
        private int talkerIndex = -1;
        private bool aliveInstance = false;
 
        public SapiInstance()
        {
            try
            {
                sapi = new SpVoice();
                talkerList = sapi.GetVoices("", "");
                talkerIndex = 0;
 
                sapi.Volume = 100;
                sapi.Rate = 0;
                sapi.Voice = talkerList.Item(talkerIndex);
 
                effects = new Dictionary<string, EffectValue>
                {
                    {"volume",     new EffectValue( (decimal)sapi.Volume,    0.0m, 100.0m, 1.0m) },
                    {"speed",      new EffectValue( (decimal)sapi.Rate,    -10.0m,  10.0m, 1.0m) }
                };
 
                aliveInstance = true;
            }
            catch(Exception)
            {
                aliveInstance = false;
            }
        }
 
        public override bool isAlive
        {
            get
            {
                return aliveInstance;
            }
        }
        public override void PlayVoice(bool async = true)
        {
            try
            {
                sapi.Voice = talkerList.Item(talkerIndex);
                sapi.Volume = (int)effects["volume"].value;
                sapi.Rate = (int)effects["speed"].value;
 
                if (!async)
                {
                    Thread t = new Thread(() => {
                        sapi.Speak(TalkText);
                    });
                    t.SetApartmentState(ApartmentState.STA);
                    t.Start();
                    t.Join();
                }
                else
                {
                    Thread t = new Thread(() => {
                        sapi.Speak(TalkText, SpeechVoiceSpeakFlags.SVSFlagsAsync);
                    });
                    t.SetApartmentState(ApartmentState.STA);
                    t.Start();
                    //t.Join();
                }
            }
            catch (Exception)
            {
                //
            }
        }
        public override void SaveVoice()
        {
            string WavFileName = WavFilePath;
            if (!Regex.IsMatch(WavFileName, @"\.[Ww][Aa][Vv]$"))
            {
                WavFileName += ".wav";
            }
 
            try
            {
                SpFileStream ss = new SpFileStream();
                ss.Open(WavFileName, SpeechStreamFileMode.SSFMCreateForWrite);
 
                sapi.Voice = talkerList.Item(talkerIndex);
                sapi.Volume = (int)effects["volume"].value;
                sapi.Rate = (int)effects["speed"].value;
 
                sapi.AudioOutputStream = ss;
 
                Thread t = new Thread(() => {
                    sapi.Speak(TalkText);
                });
                t.SetApartmentState(ApartmentState.STA);
                t.Start();
                t.Join();
                ss.Close();
            }
            catch(Exception)
            {
                //
            }
        }
        public override void SetTalkerName(string cvName)
        {
            talkerIndex = -1;
            talkerList = sapi.GetVoices("", "");
            for(int i = 0; i<talkerList.Count; i++)
            {
                if (talkerList.Item(i).GetAttribute("Name") == cvName)
                {
                    talkerIndex = i;
                    break;
                }
            }
            if (talkerIndex == -1) talkerIndex = 0;
        }
        public override string[] GetTalkerList()
        {
            string[] ans = new string[talkerList.Count];
 
            for (int i = 0; i < talkerList.Count; i++)
            {
                ans[i] = talkerList.Item(i).GetAttribute("Name");
            }
 
            return ans;
        }
    }
}

SpeechPlatformInstance.cs

SpeechPlatformInstance.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Speech.Synthesis;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
using System.Threading;
 
namespace echoSeikaAPI
{
    internal class SpeechPlatformInstance : BaseInstance
    {
        private SpeechSynthesizer spf = null;
        private ReadOnlyCollection<InstalledVoice> talkerList = null;
        private int talkerIndex = -1;
        private bool aliveInstance = false;
 
        public SpeechPlatformInstance()
        {
            try
            {
                spf = new SpeechSynthesizer();
                talkerList = spf.GetInstalledVoices();
                talkerIndex = 0;
 
                spf.Volume = 100;
                spf.Rate = 0;
 
                effects = new Dictionary<string, EffectValue>
                {
                    {"volume",     new EffectValue( (decimal)spf.Volume,    0.0m, 100.0m, 1.0m) },
                    {"speed",      new EffectValue( (decimal)spf.Rate,    -10.0m,  10.0m, 1.0m) }
                };
 
                aliveInstance = true;
            }
            catch (Exception)
            {
                aliveInstance = false;
            }
        }
        public override bool isAlive
        {
            get
            {
                return aliveInstance;
            }
        }
        public override void PlayVoice(bool async = true)
        {
            try
            {
                spf.SetOutputToDefaultAudioDevice();
 
                spf.SelectVoice(talkerList[talkerIndex].VoiceInfo.Name);
                spf.Volume = (int)effects["volume"].value;
                spf.Rate = (int)effects["speed"].value;
 
                if (!async)
                {
                    spf.Speak(TalkText);
                }
                else
                {
                    spf.SpeakAsync(TalkText);
                }
            }
            catch(Exception)
            {
                //
            }
        }
        public override void SaveVoice()
        {
            string WavFileName = WavFilePath;
 
            if (!Regex.IsMatch(WavFileName, @"\.[Ww][Aa][Vv]$")) WavFileName += ".wav";
 
            try
            {
                spf.SelectVoice(talkerList[talkerIndex].VoiceInfo.Name);
                spf.Volume = (int)effects["volume"].value;
                spf.Rate = (int)effects["speed"].value;
 
                spf.SetOutputToWaveFile(WavFileName);
                spf.Speak(TalkText);
            }
            catch (Exception)
            {
                //
            }
        }
        public override void SetTalkerName(string cvName)
        {
            talkerIndex = -1;
            talkerList = spf.GetInstalledVoices();
            for (int i = 0; i < talkerList.Count; i++)
            {
                if (talkerList[i].VoiceInfo.Name == cvName)
                {
                    talkerIndex = i;
                    break;
                }
            }
            if (talkerIndex == -1) talkerIndex = 0;
        }
        public override string[] GetTalkerList()
        {
            return talkerList.Select(item => item.VoiceInfo.Name).ToArray<string>();
        }
 
    }
}
documents/voiceroid/echoseika/echoseika-004.txt · 最終更新: 2018/06/30 15:01 by k896951

ページ用ツール