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

            if (job_data == null)
            {
                return(0);
            }
            switch (reason)
            {
            case AitalkCore.EventReason.PhoneticLabel:
            case AitalkCore.EventReason.Bookmark:
            case AitalkCore.EventReason.AutoBookmark:
                job_data.EventData.Add(new TtsEventData(tick, name, reason));
                break;
            }
            return(0);
        }
Exemplo n.º 3
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);
        }