Ejemplo n.º 1
0
        /// <summary>
        /// 音声変換時のデータコールバックメソッド
        /// </summary>
        /// <param name="reason">呼び出し要因</param>
        /// <param name="job_id">ジョブID</param>
        /// <param name="tick">時刻[ms]</param>
        /// <param name="user_data">ユーザーデータ(SpeechJobDataへのポインタ)</param>
        /// <returns>ゼロを返す</returns>
        private static int RawBufferCallback(AitalkCore.EventReason reason, int job_id, long tick, IntPtr user_data)
        {
            GCHandle      gc_handle = GCHandle.FromIntPtr(user_data);
            SpeechJobData job_data  = gc_handle.Target as SpeechJobData;

            if (job_data == null)
            {
                return(0);
            }

            // 変換できた分だけGetData()で読み取ってjob_dataのバッファに格納する
            int buffer_capacity = job_data.BufferCapacity;

            byte[]            buffer = new byte[2 * buffer_capacity];
            AitalkCore.Result result;
            int read_samples;

            do
            {
                result = AitalkCore.GetData(job_id, buffer, buffer_capacity, out read_samples);
                if (result != AitalkCore.Result.Success)
                {
                    break;
                }
                job_data.Output.AddRange(new ArraySegment <byte>(buffer, 0, 2 * read_samples));
            }while ((buffer_capacity - 1) <= read_samples);
            if (reason == AitalkCore.EventReason.RawBufferClose)
            {
                job_data.CloseEvent.Set();
            }
            return(0);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// パラメータを設定する。
        /// param.Sizeおよびparam.NumberOfSpeakersは自動的に設定される。
        /// </summary>
        /// <param name="tts_param">パラメータ(話者パラメータを除く)</param>
        /// <param name="speaker_params">話者パラメータ</param>
        private static void SetParameters(AitalkCore.TtsParam tts_param, AitalkCore.TtsParam.SpeakerParam[] speaker_params)
        {
            // パラメータを格納するバッファを確保する
            int    size = Marshal.SizeOf <AitalkCore.TtsParam>() + Marshal.SizeOf <AitalkCore.TtsParam.SpeakerParam>() * speaker_params.Length;
            IntPtr ptr  = Marshal.AllocCoTaskMem(size);

            try
            {
                // パラメータを設定する
                tts_param.Size             = size;
                tts_param.NumberOfSpeakers = speaker_params.Length;
                Marshal.StructureToPtr <AitalkCore.TtsParam>(tts_param, ptr, false);
                for (int index = 0; index < speaker_params.Length; index++)
                {
                    IntPtr speaker_ptr = IntPtr.Add(ptr, Marshal.SizeOf <AitalkCore.TtsParam>() + Marshal.SizeOf <AitalkCore.TtsParam.SpeakerParam>() * index);
                    Marshal.StructureToPtr <AitalkCore.TtsParam.SpeakerParam>(speaker_params[index], speaker_ptr, false);
                }
                AitalkCore.Result result;
                result = AitalkCore.SetParam(ptr);
                if (result != AitalkCore.Result.Success)
                {
                    throw new AitalkException("動作パラメータの設定に失敗しました。", result);
                }
            }
            finally
            {
                Marshal.FreeCoTaskMem(ptr);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// ボイスライブラリを読み込む
        /// </summary>
        /// <param name="voice_db_name">ボイスライブラリ名</param>
        public static void LoadVoice(string voice_db_name)
        {
            if (voice_db_name == CurrentVoice)
            {
                return;
            }

            CurrentVoice = null;
            AitalkCore.VoiceClear();
            if (voice_db_name == null)
            {
                return;
            }
            AitalkCore.Result result;
            result = AitalkCore.VoiceLoad(voice_db_name);
            if (result != AitalkCore.Result.Success)
            {
                throw new AitalkException($"ボイスライブラリ'{voice_db_name}'の読み込みに失敗しました。", result);
            }

            // パラメータを読み込む
            GetParameters(out var tts_param, out var speaker_params);
            tts_param.TextBufferCallback = TextBufferCallback;
            tts_param.RawBufferCallback  = RawBufferCallback;
            tts_param.TtsEventCallback   = TtsEventCallback;
            tts_param.PauseBegin         = 0;
            tts_param.PauseTerm          = 0;
            tts_param.ExtendFormatFlags  = AitalkCore.ExtendFormat.JeitaRuby | AitalkCore.ExtendFormat.AutoBookmark;
            Parameter = new AitalkParameter(voice_db_name, tts_param, speaker_params);

            CurrentVoice = voice_db_name;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// 言語ライブラリを読み込む
        /// </summary>
        /// <param name="language_name">言語名</param>
        public static void LoadLanguage(string language_name)
        {
            if (language_name == CurrentLanguage)
            {
                return;
            }
            // 言語の設定をする際はカレントディレクトリを一時的にVOICEROID2のインストールディレクトリに変更する
            // それ以外ではLangLoad()はエラーを返す
            string current_directory = System.IO.Directory.GetCurrentDirectory();

            System.IO.Directory.SetCurrentDirectory(InstallDirectory);
            CurrentLanguage = null;
            AitalkCore.Result result;
            result = AitalkCore.LangClear();
            if ((result == AitalkCore.Result.Success) || (result == AitalkCore.Result.NotLoaded))
            {
                result = AitalkCore.LangLoad($"{InstallDirectory}\\Lang\\{language_name}");
            }
            System.IO.Directory.SetCurrentDirectory(current_directory);
            if (result != AitalkCore.Result.Success)
            {
                throw new AitalkException($"言語'{language_name}'の読み込みに失敗しました。", result);
            }
            CurrentLanguage = language_name;
        }
Ejemplo n.º 5
0
 /// <summary>
 /// AITalkを終了する
 /// </summary>
 public static void Finish()
 {
     if (IsInitialized == true)
     {
         IsInitialized = false;
         AitalkCore.End();
     }
     CurrentLanguage = null;
     CurrentVoice    = null;
 }
Ejemplo n.º 6
0
        /// <summary>
        /// テキストを読み仮名に変換する
        /// </summary>
        /// <param name="text">テキスト</param>
        /// <param name="Timeout">タイムアウト[ms]。0以下はタイムアウト無しで待ち続ける。</param>
        /// <returns>読み仮名文字列</returns>
        public static string TextToKana(string text, int timeout = 0)
        {
            UpdateParameter();

            // ShiftJISに変換する
            UnicodeToShiftJis(text, out byte[] shiftjis_bytes, out int[] shiftjis_positions);

            // コールバックメソッドとの同期オブジェクトを用意する
            KanaJobData job_data = new KanaJobData();

            job_data.BufferCapacity = 0x1000;
            job_data.Output         = new List <byte>();
            job_data.CloseEvent     = new EventWaitHandle(false, EventResetMode.ManualReset);
            GCHandle gc_handle = GCHandle.Alloc(job_data);

            try
            {
                // 変換を開始する
                AitalkCore.JobParam job_param;
                job_param.ModeInOut = AitalkCore.JobInOut.PlainToKana;
                job_param.UserData  = GCHandle.ToIntPtr(gc_handle);
                AitalkCore.Result result;
                result = AitalkCore.TextToKana(out int job_id, ref job_param, shiftjis_bytes);
                if (result != AitalkCore.Result.Success)
                {
                    throw new AitalkException($"仮名変換が開始できませんでした。[{string.Join(",", shiftjis_bytes)}]", result);
                }

                // 変換の終了を待つ
                // timeoutで与えられた時間だけ待つ
                bool respond;
                respond = job_data.CloseEvent.WaitOne((0 < timeout) ? timeout : -1);

                // 変換を終了する
                result = AitalkCore.CloseKana(job_id);
                if (respond == false)
                {
                    throw new AitalkException("仮名変換がタイムアウトしました。");
                }
                else if (result != AitalkCore.Result.Success)
                {
                    throw new AitalkException("仮名変換が正常に終了しませんでした。", result);
                }
            }
            finally
            {
                gc_handle.Free();
            }

            // 変換結果に含まれるIrq MARKのバイト位置を文字位置へ置き換える
            Encoding encoding = Encoding.GetEncoding(932);

            return(ReplaceIrqMark(encoding.GetString(job_data.Output.ToArray()), shiftjis_positions));
        }
Ejemplo n.º 7
0
 /// <summary>
 /// 記号ポーズ辞書を読み込む
 /// </summary>
 /// <param name="path">ファイルパス</param>
 public static void ReloadSymbolDictionary(string path)
 {
     AitalkCore.ReloadSymbolDic(null);
     if (path == null)
     {
         return;
     }
     AitalkCore.Result result;
     result = AitalkCore.ReloadSymbolDic(path);
     if (result == AitalkCore.Result.UserDictionaryNoEntry)
     {
         AitalkCore.ReloadSymbolDic(null);
     }
     else if (result != AitalkCore.Result.Success)
     {
         throw new AitalkException($"記号ポーズ辞書'{path}'の読み込みに失敗しました。", result);
     }
 }
Ejemplo n.º 8
0
        /// <summary>
        /// パラメータを取得する
        /// </summary>
        /// <param name="tts_param">パラメータ(話者パラメータを除く)</param>
        /// <param name="speaker_params">話者パラメータ</param>
        private static void GetParameters(out AitalkCore.TtsParam tts_param, out AitalkCore.TtsParam.SpeakerParam[] speaker_params)
        {
            // パラメータを格納するのに必要なバッファサイズを取得する
            AitalkCore.Result result;
            int size = 0;

            result = AitalkCore.GetParam(IntPtr.Zero, ref size);
            if ((result != AitalkCore.Result.Insufficient) || (size < Marshal.SizeOf <AitalkCore.TtsParam>()))
            {
                throw new AitalkException("動作パラメータの長さの取得に失敗しました。", result);
            }

            IntPtr ptr = Marshal.AllocCoTaskMem(size);

            try
            {
                // パラメータを読み取る
                Marshal.WriteInt32(ptr, (int)Marshal.OffsetOf <AitalkCore.TtsParam>("Size"), size);
                result = AitalkCore.GetParam(ptr, ref size);
                if (result != AitalkCore.Result.Success)
                {
                    throw new AitalkException("動作パラメータの取得に失敗しました。", result);
                }
                tts_param = Marshal.PtrToStructure <AitalkCore.TtsParam>(ptr);

                // 話者のパラメータを読み取る
                speaker_params = new AitalkCore.TtsParam.SpeakerParam[tts_param.NumberOfSpeakers];
                for (int index = 0; index < speaker_params.Length; index++)
                {
                    IntPtr speaker_ptr = IntPtr.Add(ptr, Marshal.SizeOf <AitalkCore.TtsParam>() + Marshal.SizeOf <AitalkCore.TtsParam.SpeakerParam>() * index);
                    speaker_params[index] = Marshal.PtrToStructure <AitalkCore.TtsParam.SpeakerParam>(speaker_ptr);
                }
            }
            finally
            {
                Marshal.FreeCoTaskMem(ptr);
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// AITalkを初期化する
        /// </summary>
        /// <param name="install_directory">VOICEROID2のインストールディレクトリ</param>
        /// <param name="authenticate_code">認証コード</param>
        public static void Initialize(string install_directory, string authenticate_code)
        {
            Finish();

            // aitalked.dllをロードするために
            // DLLの探索パスをVOICEROID2のディレクトリに変更する
            if ((InstallDirectory != null) && (InstallDirectory != install_directory))
            {
                throw new AitalkException($"インストールディレクトリを変更して再び初期化することはできません。");
            }
            InstallDirectory = install_directory;
            SetDllDirectory(InstallDirectory);

            // AITalkを初期化する
            AitalkCore.Config config;
            config.VoiceDbSampleRate    = VoiceSampleRate;
            config.VoiceDbDirectory     = $"{InstallDirectory}\\Voice";
            config.TimeoutMilliseconds  = TimeoutMilliseconds;
            config.LicensePath          = $"{InstallDirectory}\\aitalk.lic";
            config.AuthenticateCodeSeed = authenticate_code;
            config.ReservedZero         = 0;
            var result = AitalkCore.Result.Success;

            try
            {
                result = AitalkCore.Init(ref config);
            }
            catch (Exception e)
            {
                throw new AitalkException($"AITalkの初期化に失敗しました。", e);
            }
            if (result != AitalkCore.Result.Success)
            {
                throw new AitalkException($"AITalkの初期化に失敗しました。", result);
            }
            IsInitialized = true;
        }
Ejemplo n.º 10
0
        /// <summary>
        /// 読み仮名を読み上げてWAVEファイルをストリームに出力する。
        /// なお、ストリームへの書き込みは変換がすべて終わった後に行われる。
        /// </summary>
        /// <param name="kana">読み仮名</param>
        /// <param name="wave_stream">WAVEファイルの出力先ストリーム</param>
        /// <param name="timeout">タイムアウト[ms]。0以下はタイムアウト無しで待ち続ける。</param>
        public static void KanaToSpeech(string kana, Stream wave_stream, int timeout = 0)
        {
            UpdateParameter();

            // コールバックメソッドとの同期オブジェクトを用意する
            SpeechJobData job_data = new SpeechJobData();

            job_data.BufferCapacity = 176400;
            job_data.Output         = new List <byte>();
            job_data.EventData      = new List <TtsEventData>();
            job_data.CloseEvent     = new EventWaitHandle(false, EventResetMode.ManualReset);
            GCHandle gc_handle = GCHandle.Alloc(job_data);

            try
            {
                // 変換を開始する
                AitalkCore.JobParam job_param;
                job_param.ModeInOut = AitalkCore.JobInOut.KanaToWave;
                job_param.UserData  = GCHandle.ToIntPtr(gc_handle);
                AitalkCore.Result result;
                result = AitalkCore.TextToSpeech(out int job_id, ref job_param, kana);
                if (result != AitalkCore.Result.Success)
                {
                    throw new AitalkException("音声変換が開始できませんでした。", result);
                }

                // 変換の終了を待つ
                // timeoutで与えられた時間だけ待つ
                bool respond;
                respond = job_data.CloseEvent.WaitOne((0 < timeout) ? timeout : -1);

                // 変換を終了する
                result = AitalkCore.CloseSpeech(job_id);
                if (respond == false)
                {
                    throw new AitalkException("音声変換がタイムアウトしました。");
                }
                else if (result != AitalkCore.Result.Success)
                {
                    throw new AitalkException("音声変換が正常に終了しませんでした。", result);
                }
            }
            finally
            {
                gc_handle.Free();
            }

            // TTSイベントをJSONに変換する
            // 変換後の文字列にヌル終端がてら4の倍数の長さになるようパディングを施す
            MemoryStream event_stream = new MemoryStream();
            var          serializer   = new DataContractJsonSerializer(typeof(List <TtsEventData>));

            serializer.WriteObject(event_stream, job_data.EventData);
            int padding = 4 - ((int)event_stream.Length % 4);

            for (int cnt = 0; cnt < padding; cnt++)
            {
                event_stream.WriteByte(0x0);
            }
            byte[] event_json = event_stream.ToArray();

            // データをWAVE形式で出力する
            // phonチャンクとしてTTSイベントを埋め込む
            byte[] data   = job_data.Output.ToArray();
            var    writer = new BinaryWriter(wave_stream);

            writer.Write(new byte[4] {
                (byte)'R', (byte)'I', (byte)'F', (byte)'F'
            });
            writer.Write(44 + event_json.Length + data.Length);
            writer.Write(new byte[4] {
                (byte)'W', (byte)'A', (byte)'V', (byte)'E'
            });
            writer.Write(new byte[4] {
                (byte)'f', (byte)'m', (byte)'t', (byte)' '
            });
            writer.Write(16);
            writer.Write((short)0x1);
            writer.Write((short)1);
            writer.Write(VoiceSampleRate);
            writer.Write(2 * VoiceSampleRate);
            writer.Write((short)2);
            writer.Write((short)16);
            writer.Write(new byte[4] {
                (byte)'p', (byte)'h', (byte)'o', (byte)'n'
            });
            writer.Write(event_json.Length);
            writer.Write(event_json);
            writer.Write(new byte[4] {
                (byte)'d', (byte)'a', (byte)'t', (byte)'a'
            });
            writer.Write(data.Length);
            writer.Write(data);
        }