ゆっくりボイス:AquesTalk 1 を C# から呼び出してみる

前回、SofTalk というフリーソフトをコマンドラインから呼び出し、ゆっくりボイスでテキストを発話させてみた。

今回は SofTalk が利用している大元の合成音声ライブラリ「AquesTalk」を利用して、自作の C# のコードから発話させてみようと思う。

目次

AquesTalk のおさらい

合成音声ライブラリ AquesTalk は、大きく分けて 1・2・10 系という3つのバージョンがある。いずれも機能制限がある「評価版」であれば、公式サイトから無料でダウンロード、利用できる。

いずれのバージョンも、Windows 向けには .dll、Linux 向けには .so ファイルといった「動的リンクライブラリ」を提供しているので、プログラミング言語を問わず、.dll ファイルを呼び出すためのコードを書けば AquesTalk が利用できるというワケ。

公式サイトには C/C++ 言語のコード例が記載されている「プログラミングガイド」などのドキュメントがあり、どういう関数が存在し、どういう引数を指定して呼び出せばよいかなどが確認できるので、合わせてダウンロードして読んでおこう。

今回はバージョン 1 系を利用したコードを組んでいく。

評価版の制限を回避したい

前述のとおり、公式サイトでダウンロードできる「評価版」のライブラリは、機能制限がかかっている。

評価版は「ナ行、マ行」の音韻がすべて「ヌ」になる制限があります。

つまり、「こんちわ」というテキストを渡すと「こんちわ」と発話するような制限があるようだ。この制限を回避するには、ライセンスを購入する必要がある。

しかし、フリーソフトの「SofTalk」や「棒読みちゃん」にはこうした制限はかかっていないのに、なぜ本家本元の AquesTalk ライブラリにはこうした制限がかかっているのだろうか?

コレは AquesTalk のライセンス形態が途中で変更されたためにこのようになっているらしく、以前のライセンス形態で提供されていた AquesTalk 1 系はもっと自由に使えたようである。

そこで色々試したところ、公式サイトからダウンロードできる評価版の AquesTalk.dll ではなく、「SofTalk」や「棒読みちゃん」に同梱されている AquesTalk.dll ファイルを利用することで、評価版の制限を回避して発話させることに成功した。以下でもう少し詳しく解説しようと思う。

ただし、当然ながら自己責任で。このプログラムは手元で遊びで利用するにとどめてもらいたい。

AquesTalk.dll を用意する

善良な市民は、公式サイトから評価版のライブラリ aqtk1-win-eva_173.zip をダウンロードし、Zip を解凍した中から aqtk1-win-eva/x86/f1/AquesTalk.dll を取得しておく。64bit 版の x64/ ディレクトリではなく、32bit 版の x86/ ディレクトリにある方を使用すること。

f1/ と同階層に他にもディレクトリがいくつかあるが、コレがそれぞれの声質になっている。今回は「f1 女声1」を使用する前提で話を進めるが、他のボイスを使用したい場合はそのディレクトリ配下の AquesTalk.dll を取得すれば良い。

前述のとおり、評価版を回避してみたい人は、「SofTalk」や「棒読みちゃん」をダウンロードし、その中から AquesTalk.dll を取得する。

SofTalk 同梱の DLL でも、棒読みちゃん同梱の DLL でも、どちらでも同じように利用できた。

C# コードを書く

ということで、AquesTalk.dll を用意したら、以下のような C# のコードを書いていく。

using System;                          // Console
using System.IO;                       // MemoryStream
using System.Media;                    // SoundPlayer
using System.Runtime.InteropServices;  // Marshal

public class ATK1 {
  // DLL ファイルへのパス
  const string dllPath = ".\\AquesTalk.dll";
  
  [DllImport(dllPath)]
  private static extern IntPtr AquesTalk_Synthe(string koe, int iSpeed, ref int size);
  
  [DllImport(dllPath)]
  private static extern void AquesTalk_FreeWave(IntPtr wavPtr);
  
  public static void Main() {
    Console.WriteLine("Start");
    
    // 速度
    const int iSpeed = 100;
    // テキスト
    const string koe = "こんにちわこんにちわ";
    Console.WriteLine("DLL   : {0}", dllPath);
    Console.WriteLine("Speed : {0}", iSpeed);
    Console.WriteLine("Text  : {0}", koe);
    
    // 音声ファイルとしてそのまま保存可能なバイト列の先頭ポイントを取得する
    int size = 0;
    IntPtr wavPtr = IntPtr.Zero;
    try {
      wavPtr = AquesTalk_Synthe(koe, iSpeed, ref size);  // throws
      
      // 失敗していれば終了する
      if(wavPtr == IntPtr.Zero) {
        Console.WriteLine("ERROR : 音声生成に失敗しました。不正な文字が使われた可能性があります。終了します");
        return;
      }
    }
    catch(Exception exception) {
      Console.WriteLine("ERROR : 例外が発生しました");
      Console.WriteLine(exception);
      Console.WriteLine("終了します");
      return;
    }
    
    // C# で扱えるようにマネージド側へコピーする
    byte[] wav = new byte[size];
    Marshal.Copy(wavPtr, wav, 0, size);
    
    // アンマネージドポインタは用がなくなった瞬間に解放する
    AquesTalk_FreeWave(wavPtr);
    
    // 同期再生する
    using(var ms = new MemoryStream(wav))
    using(var sp = new SoundPlayer(ms)) {
      sp.PlaySync();
    }
    
    Console.WriteLine("Finished");
  }
}

公式のプログラミングガイドやブログ記事等を参考に書いてみた。

C# コードを csc.exe でコンパイルする

こうして記述した C# のコードを、.NET Framework に内蔵されている csc.exe でコンパイルする。というのも、僕はあまり C# に明るくなく、Visual Studio で開発したりしていないので、今回はかなり簡易的に、csc.exe を使ってコンパイルしてしまっている。

ココで、AquesTalk.dll との兼ね合いで 32bit 版の実行ファイルを生成する必要があるので、そのためのオプション指定 /platform:x86 を忘れずにしておこう。使用する csc.exe も 64bit 版ではなく 32bit 版を使う方が良いだろう (ディレクトリパスが Framework64\ ではなく Framework\ の方を使う)。

csc.exe の所在やバージョンは環境によると思うが、自分の環境では以下のフルパスを指定してコンパイルした。

@Rem コンパイルする
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /nologo /platform:x86 .\atk1.cs

@Rem 実行する
.\atk1.exe

そしてコンパイルして生成した atk1.exe を実行すれば、実行時に同ディレクトリにあるであろう AquesTalk.dll を利用して発話できる。

.dll ファイルは「動的リンクライブラリ」と言うだけあって、コンパイル時に atk1.exe の中には内包されず、EXE の実行時に DLL ファイルを探しに行くモノなので、利用する際は atk1.exeAquesTalk.dll が必ずセットで必要になる。

また、今回のコードの場合でいうと、AquesTalk.dll を別の声質のモノと差し替えれば、atk1.exe の方は再コンパイルすることなく声質を変えたりもできる。

以上

今回は以上とする。

読み上げ速度やテキストを標準入力で受け取れるように C# コードを書ければ、CLI ツールが出来上がるだろう。

また、途中でも触れたように AquesTalk ライブラリは漢字や英数字が認識できないので、テキストをひらがなに展開するような事前処理を入れてあげたりすると「SofTalk」や「棒読みちゃん」のように利用しやすくなるだろう。

フリーソフトの他にも、既に似たような Python 製のコードが存在したりするものの、Twitter のタイムラインを読み上げさせたりするようなプログラムも、コレを元に組んでいけそうだ。

参考