2008年1月4日金曜日

アクエストーク と C# で音声合成の実験

マイクロソフトの音声合成インターフェース、SAPIの最新版 5.3 には日本語の音声合成が付属していないし、フリーの対応音声合成モジュールもない。前のバージョン SAPI4にはそれなりのがあったわけだが、そもそもヤル気のなさげなものばかり。公的な研究機関のつくったGtalk なんぞ、余りに不自然で変すぎる。聞いたところによると、自然に聞こえるとかそういったことにはあまり興味がないらしい。っていうか研究はすでに終了しているし。
そんななか、SAPIと関係ないけれど、フリーで結構イイ声を出してくれるものを見つけた。・・・っていうかWikiPediaにリンクがあったんだけどね。AQUEST社というところが出している「AquesTalk」という製品で、Linux版は有償だが、Windows版は無償という、普通と逆なもの。組み込み用ということでサイズは小さいのだが、なかなかよい声をだす。
でも辞書がないので、普通に文章を読むことはできない。まぁそれはそれで趣味で使う分には問題なし。もし普通文を読ませたいなら、それこそGTalkのガラティアプロジェクトから持ってくればいいかな。

ということで、しゃべらせてみよう。 必要なのは、
  • Windows XP/SP2
  • Microsoft Visual C# 2005 Express Edition

こんだけ。

プログラムはこんな感じ。



using System;
using System.Windows.Forms;
using System.Runtime.InteropServices; // DllImport

namespace Sample{
///
/// メインフォーム
///

public partial class MainForm : Form
{
///
/// コンストラクタ
///

public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int iret = Program.AquesTalkDa_PlaySync("これわ、ふり'ーの、おん'せい/ごーせい/そ'ふと、あ'くえすと'ーくで/しゃべって/います。", 100);
}
}
///
/// アプリケーション開始クラス
///

static class Program
{
[DllImport("AquesTalkDa.dll")]
public static extern int AquesTalkDa_PlaySync(string koe, int iSpeed);
[STAThread]
static void Main()
{
Application.Run(new MainForm());// フォームを起動
}
}
}

このプログラムのプロジェクト Talk_01.zip (ダウンロードできます)



このサンプルは、AQUEST社のブログで紹介された方法そのままなので、次は、もうちょっと複雑な発声をやってみる。



上の実験では単にしゃべらせるだけなのでしゃべってる間は何もしないで待つ、ってことでもよかったんですが、しゃべっている間に何かさせようとか、複数のしゃべりを同時にするとかだと待っててはいけません。つまり非同期って奴ですね。

そこでAquesTalkDa_PlaySync()じゃなくて、AquesTalkDa_Play()を使わなければならない。



using System;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices; // DllImport

namespace Sample
{
///
/// メインフォーム
///

public partial class MainForm : Form
{

// 再生フラグ
private const int SND_SYNC = 0x0; // 同期再生
private const int SND_ASYNC = 0x1; // 非同期再生
private const int SND_MEMORY = 0x4; // バッファからの再生
private const int SND_LOOP = 0x8; // ループ再生
private const int SND_NOSTOP = 0x10; // 再生中のサウンドを停止しない
private const int SND_NOWAIT = 0x2000; // ビジー状態なら即座に処理を返す

///
/// コンストラクタ
///

public MainForm()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
IntPtr hMe = Program.AquesTalkDa_Create();

IntPtr hwnd = Program.FindWindow(this.Text, null);

int iret = Program.AquesTalkDa_Play(hMe, "これわ、ふり'ーの", (int)120, hwnd, 0, 0);

IntPtr hMe2 = Program.AquesTalkDa_Create();

iret = Program.AquesTalkDa_Play(hMe2, "おん'せい/ごーせい/そ'ふと", (int)60, hwnd, 0, 0);

//Program.AquesTalkDa_Release(hMe);
//Program.AquesTalkDa_Release(hMe2);
}

private void button2_Click(object sender, EventArgs e)
{

IntPtr size;
IntPtr voiceBuffer = Program.AquesTalk_Synthe("あ'くえすと'ーくで/しゃべって/い'ます。", 100, out size);

Program.PlaySound(voiceBuffer, 0, SND_MEMORY | SND_ASYNC);

//Program.AquesTalk_FreeWave((IntPtr)voiceBuffer);
}

private void MainForm_Load(object sender, EventArgs e)
{

}
}

///
/// アプリケーション開始クラス
///

static class Program
{
//[DllImport("AquesTalkDa.dll")]
//public static extern int AquesTalkDa_PlaySync(string koe, int iSpeed);
[DllImport("AquesTalkDa.dll")]
public static extern int AquesTalkDa_Play(IntPtr hMe, string koe, int iSpeed, IntPtr Wnd, uint msg, uint dwUser);
[DllImport("AquesTalkDa.dll")]
public static extern IntPtr AquesTalkDa_Create();
[DllImport("AquesTalkDa.dll")]
public static extern void AquesTalkDa_Release( IntPtr hMe);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("AquesTalk.dll")]
public static extern IntPtr AquesTalk_Synthe(string koe, int iSpeed, out IntPtr size);
[DllImport("AquesTalk.dll")]
public static extern void AquesTalk_FreeWave(IntPtr wav);

[DllImport("winmm.dll", EntryPoint = "PlaySound")]
public static extern int PlaySound(
//[MarshalAs(UnmanagedType.LPArray)] byte[] pszSound,
IntPtr pszSound,
int hModule,
int dwFlags);


///
/// アプリケーションのメイン エントリ ポイントです。
///

[STAThread]
static void Main()
{
// コントロール等を Windows XP のスタイルにします。
// はずしてもかまいません。
Application.EnableVisualStyles();

// GDI+ を使用してコントロールのテキストを描画します。
// はずしてもかまいません。
Application.SetCompatibleTextRenderingDefault(false);

// フォームを起動します。
Application.Run(new MainForm());
}
}
}


こんな具合に、ずいぶん面倒くさくなる。

このプログラムのプロジェクト Talk_02.zip (ダウンロードできます)

1 件のコメント:

monmoko さんのコメント...
このコメントは投稿者によって削除されました。