次の方法で共有


Windows と話す

Windows Vista における音声認識と音声合成の新規 API

Robert Brown


この記事は、WinFX のプレリリース版に基づいています。この記事の内容はいずれも、変更される可能性があります。

この記事で取り上げる話題:

  • 音声認識と音声合成の概要
  • Windows Vista の音声認識エクスペリエンス
  • Windows Vista の音声 API
  • 発音の制御と文法の作成

この記事で使用する技術:

  • Windows Vista、WinFX

翻訳元: Exploring New Speech Recognition And Synthesis APIs In Windows Vista (英語)


目次

  1. 音声の要素
  2. Windows Vista に話しかける
  3. Windows Vista の音声 API
  4. System.Speech.Synthesis
  5. System.Speech.Recognition
  6. 電話アプリケーション
  7. まとめ

補足事項

  • SAPI 5.3 の新規事項

マイクロソフトは、10 年以上もの間、音声技術の研究と開発を重ねてきました。1993 年には、カーネギー メロン大学 Sphinx-II 音声認識システムの 4 人の担当者の内の Xuedong (XD) Huang、Fil Alleva、および Mei-Yuh Hwang と契約しました。この音声認識システムは、1992 年に今までにない精度を達成し音声の分野での名声を得ています。1994 年、Speech API (SAPI) 1.0 チームが形成され、その当初から、マイクロソフトは、精度が高く、また強力な API を介して開発者が使用できる音声技術の作成を目指していました。このチームは進歩を続け、何年にもわたり、より強力な音声プラットフォームのリリースを続けています。

最近の数年で、マイクロソフトは、音声技術をメインストリームでの使用に導入することをより重要視するようになりました。その結果、音声対応の電話システムを実装するのに使用される Speech Server、およびユーザーが Windows Mobile デバイスを音声コマンドで制御することを可能にする Voice Command などの製品が開発されました。当然、マイクロソフトの音声チームは、Windows Vista の開発にも大きく関わっています。強力な音声技術と、強力な API を組み合わせる戦略は、Windows Vista でも継続しています。

Windows Vista には、キーボード、またはマウスを使用せずに Windows を制御したり、テキストを入力したりする必要のあるユーザー専用に設計された組み込みの音声認識ユーザー インターフェイスが含まれます。また、最新の汎用的な音声認識エンジンもあります。このエンジンは、精度がきわめて高いだけでなく、さまざまな言語での使用が可能です。また、Windows Vista は、音声合成においてもマイクロソフトの新世代の始まりとなります。これは、最新の技術を活用するために完全に作成し直されています。

開発者としては、Windows Vista に含まれる新規の WinFX 名前空間である System.Speech に注目しましょう。これにより、開発者は、Windows フォーム アプリケーション、および Windows Presentation Framework に基づくアプリケーションを簡単に音声対応にするこができます。さらに、更新された COM Speech API (SAPI 5.3) により、プラットフォームの高度な音声機能にネイティブ コードでアクセスすることも可能です。これについての詳細は、SAPI 5.3 の新規事項 を参照してください。


1. 音声の要素

音声技術の概念には、実際には、合成および認識の 2 つの技術が含まれます (図 1 を参照してください)。音声合成は、入力としてテキストを受け取り、出力として音声ストリームを作成します。音声合成は、テキスト読み上げ (TTS) とも言われます。一方、音声認識はこの反対です。入力として音声ストリームを受け取り、それをテキストに変換します。

図 1 音声認識、および音声合成
図 1 音声認識、および音声合成

文字列を、その語句が話されているかのように聞こえるような音声ストリームに正確に変換する合成には、多くの処理が必要となります。この処理は、フロント エンドおよびバック エンドの 2 つの部分からなるシステムと考えると理解しやすくなります。

フロント エンドは、自然言語ルールを使用してのテキストの分析に特化します。これは、文字列を分析して、どこの言葉なのかを判断します (この処理は、英語の場合には簡単ですが、中国語や日本語などの場合には簡単ではありません)。このフロント エンドは、機能および品詞といった詳細も分析します。たとえば、それぞれの単語が、固有名詞、数字、またはその他の何かであるか、文がどこで始まり、どこで終わっているか、疑問文、あるいは平叙文のどちらか、さらに文の時制は過去、現在、または未来か、などを判別します。

単語、句、および文の単位で、発音、およびイントネーションを適切に選択するためには、これらすべての要素が必要となります。英語の場合、疑問文では、通常、最後が上昇調になります。また、"read" という単語は、その時制によって発音がさまざまに変化します。テキストを音声に変換するには、単語、または句がどのように使用されているかを認識することが欠かせません。このようなルールは、各言語によって異なるため、処理はさらに複雑になります。想像できるとおり、フロント エンドは、とても高度な分析を行う必要があります。

バック エンドは、また別の処理を行います。フロント エンドによって行われた分析を受け取り、さらに必要な分析を独自に行い、入力テキスト対する適切な音声を生成します。旧来の音声合成 (および今日の最も単純な音声合成) は、アルゴリズムで個々の音声を生成するため、機械的な音声になります。Windows Vista に含まれるような最新の音声合成では、何時間分もの録音された音声で構成される音声部品データベースを活用します。バック エンドの有効性は、それぞれの入力に対してどれだけ適切な音声部品を選択できるか、およびそれらをどれだけ滑らかにつなぎ合わせることができるかによって決まります。

これは、とても複雑に思えるかもしれませんが、実際に、複雑です。このようなテキスト読み上げ機能がオペレーティング システムに組み込まれることにより、アプリケーションでは、この技術を単純に使用するだけで済むという利点があります。独自に音声エンジンを作成する必要がなくなります。この記事の後で説明しますが、このような処理はすべて 1 つの関数呼び出しで実行することが可能です。すばらしいことです。

音声認識は、音声合成よりもさらに複雑になります。しかし、これも、フロント エンドとバック エンドに分けて考えることができます。フロント エンドは、音声ストリームを処理しながら、人の言葉と思われる部分の音声を分離し、それを、信号として声の特性を表す一連の数値に変換します。バック エンドは、フロント エンドが作成した出力を受け取り、音響モデル、辞書、および言語モデルという 3 つのデータベースを検索することに特化した検索エンジンです。音響モデルは、言語の音として聞こえる部分を表します。これは、特定のユーザーの話し方のパターン、および音響環境の特徴を認識するように学習させることができます。辞書は、言語の多数の語句と、それぞれがどのように発音されるかの情報のリストです。言語モデルは、言語の語句がどのように組み合わせられるかを表します。

これらのモデルのいずれも重要です。言葉がどのように聞こえるかを正確に指定することは不可能です。人が話す言葉は、簡単に定義できる厳格で正式な文法のルールにはほとんど従っていません。適切なモデルを作成するためには、大量の見本データを取得することが重要です。また、そのデータを分析して実際のモデルを作成する技術の精度も同様に重要になります。

言葉がまったく同じように話されることはないので、認識で、完全一致が見つかることはありません。音声の特定の一部でも、話者はさまざまな言い方をする可能性があります。認識機能の性能は、どれだけ、検索の精度を上げ、適切でない一致は排除し、より適合する一致を選択できるかによって決まります。認識機能の精度を上げるには、それが保持する言語モデルと音響モデルの適切さ、および音声処理アルゴリズムと、モデル全体から検索をするアルゴリズムの両方の適切さが必要です。モデルとアルゴリズムが向上すれば、間違いが少なくなり、結果が見つかる速度も上がります。当然のことですが、これを適切に実現する技術は簡単ではありません。

認識機能の組み込み言語モデルは、広範囲な言語分野 (たとえば、日常的な口語英語など) を表しますが、特定のアプリケーションの言語モデル要件はごく限られている場合も多くあります。アプリケーションでは、通常、そのアプリケーションにおいて特定の意味を持つ発話のみを必要とします。つまり、アプリケーションは、汎用的な言語モデルを使用するよりも、アプリケーションにおいて必要となる音声のみを認識機能に聞き取らせるようにする文法を使用することが必要となります。これには、多くの利点があります。認識の精度が上がり、認識結果すべてがアプリケーションにおいて意味があることが保証されます。また、認識エンジンが、認識したテキストに固有の意味的な値を指定することができるようになります。図 2 は、実際のシナリオでのこれらの利点を示しています。

図 2 アプリケーションへの入力のための音声認識の使用
図 2 アプリケーションへの入力のための音声認識の使用

ページのトップへ


2. Windows Vista に話しかける

精度は、全体の一面にすぎません。Windows Vista の音声認識技術では、組み込みのデスクトップ音声認識エクスペリエンスで、ユーザーが必要とする主要機能に対応する音声エクスペリエンス全体を提供することを目的としています。これには、音声認識技術の使用方法を説明したり、そのユーザーの話し方を理解できるようにシステムに学習させたりする対話的チュートリアルも含まれます。

システムには、Windows を制御する組み込みのコマンドが含まれます。これにより、"メモ帳を開始"、および "電卓に切り替え" などのコマンドを使用してアプリケーションを開始、切り替え、および終了することが可能です。メニューやボタンなどの画面上のインターフェイス要素は、"ファイル"、および "開く" などのコマンドを言うことにより制御できます。"Shift、Control、左矢印を 3 回押す" などのコマンドで、マウスおよびキーボードをエミュレートするサポートもあります。

Windows Vista の音声技術には、組み込みのディクテーション機能 (ユーザーの声をテキストに変換する)、および編集制御 (文書内のテキストに対して挿入、訂正および操作を行う) が含まれます。間違って認識された語句は、再度ディクテーションを行い、別の語句や、スペリングを選択して訂正することができます。たとえば、"Robot を Robert に訂正"、あるいは "R、O、B、E、rabbit の R、telephone の T とスペル" などとします。また、音声コマンドによって、テキストの選択、文書内の移動、および編集を行うこともできます。たとえば、"'My name is' を選択"、"Robert の後ろに移動"、は "Brown を大文字にする" などです。

ユーザー インターフェイスは邪魔にならないように、ただしユーザーが常に音声システムを制御できるように設計されています (図 3 を参照してください)。マイクの状態には、休止状態の場合でも簡単にアクセスできます。テキストのフィードバックは、システムが処理していることをユーザーに伝え、ユーザーへの指示を示します。また、ユーザーが話したことを明確にするためのユーザー インターフェイスもあります。ユーザーが言ったコマンドが複数の意味に解釈できる場合には、システムがこのインターフェイスを使用して意図されたことを明確にします。さらに、繰り返し使用することにより、基盤となるモデルが継続的に調整され精度が向上します。

図 3 Windows Vista の音声 UI
図 3 Windows Vista の音声 UI

組み込みの音声機能を有効にするには、[Start] メニューから、[All Programs]、[Accessories]、[Accessibility] と選択し、[Speech Recognition] をクリックします。初回の場合には、システムによってチュートリアルが表示されます。ここで、基本的なコマンドが説明されます。また、バックグラウンドでの言語モデル調整を有効にするオプションもあります。有効にした場合には、システムが、バックグラウンドで文書、および電子メールを読み取り、そのユーザーの表現方法に、より一致するように言語モデルを調整します。既定の設定で、さまざまな機能が使用可能です。システムに "何と言えばいいですか" と聞いて、説明を表示してみることをお勧めします。

しかし、開発者として、このようなユーザー エクスペリエンスのすべてを考慮する必要があるのはなぜでしょうか。これが開発者に関係するのは、これがオペレーティング システムによって提供される既定の機能であるためです。これは、作成するアプリケーションで自動的に使用できる機能です。音声技術は、Windows アクセシビリティ インターフェイスを使用して、各アプリケーションの機能を検出し、それぞれに音声対応 UI を提供します。アクセス可能な要素の名前をユーザーが言った場合、システムは、その要素の既定の機能を起動します。つまり、アクセス可能なアプリケーションを構築した場合には、既定で、音声対応アプリケーションを構築したことになります。

ページのトップへ


3. Windows Vista の音声 API

Windows Vista では、アクセス可能なアプリケーションは自動的に音声対応にすることができます。これは、簡単な音声コマンドでアプリケーションを操作できるようにする場合にはとても役に立ちます。しかし、Windows Vista が自動的に提供する汎用的な音声対応 UI よりも、高度な、あるいは専用の音声対応ユーザー インターフェイスが必要になる場合もあります。

このようなユーザー インターフェイスが必要となる例は多く存在します。たとえば、ユーザーが常に手を使うような作業をしている場合があります。ユーザーは、マウスを握ったり、キーボードを打ったりするたびに、その作業を中断します。これが、安全性あるいは生産性の低下につながることもあります。ユーザーが、コンピュータの画面以外の何かを常に見ている必要がある場合も同様です。また、アプリケーションにとても多くの機能があり、それらがツールバー メニューの中のどこにあるのかわからなくなってしまうこともあります。音声コマンドは、深いメニュー構成をフラットに広げ、多くのコマンドにすばやくアクセスすることを可能にします。ユーザーから "言うのは簡単だけれども、それをやるのは難しい" と言われることがありますが、おそらくそれは正しいことなのでしょう。

Windows Vista には、次の 2 つの 音声 API があります。

  • ネイティブ アプリケーション向けの SAPI 5.3
  • WinFX の System.Speech.Recognition 名前空間、および System.Speech.Synthesis 名前空間

図 4 は、これらの各 API が、アプリケーション、および基盤となる認識と合成のエンジンとどのように関連するかを示しています。

図 4 Windows Vista の音声 API
図 4 Windows Vista の音声 API

音声認識エンジンには、SAPI を使用してアクセスします。System.Speech.Recognition 名前空間のクラスも、SAPI が提供する機能をラップしています。(この実装の詳細は、Windows Vista の今後のリリースでは変更される可能性がありますが、注意しておく必要があります。) 一方、音声合成エンジンは、System.Speech.Synthesis のクラスから直接アクセスします。また、アンマネージ アプリケーションで使用されるときは SAPI でアクセスします。

どちらの場合も SAPI デバイス ドライバ インターフェイス (DDI) が実装されます。これは、エンジンがその上位層とやり取りできるようにする API です。デバイス ドライバ API によって、ハードウェア デバイスがそれを使用するソフトウェアとやり取り可能になるのと同様です。つまり、開発者は、SAPI、または System.Speech を使用する場合でも、自由に SAPI DDI を実装する他のエンジンを使用することができます (また、多くがそうしています)。

図 4 で、合成エンジンは、必ずアプリケーションと同じプロセスでインスタンス化されていますが、認識エンジンは、SAPISVR.EXE という別のプロセスでインスタンス化されていることに注意してください。これにより、複数のアプリケーションで同時に使用可能な共有認識エンジが提供されます。この設計には、多くの利点があります。まず、認識エンジンは、合成エンジンよりもかなり多くの実行時リソースを必要としますが、認識エンジンを共有することにより、このオーバーヘッドを削減する効果があります。また、共有認識エンジンは、Windows Vista の組み込みの音声機能によっても使用されます。このため、共有認識エンジンを使用するアプリケーションは、システムのマイク、およびフィードバック UI を活用することができます。追加のコードの記述や、ユーザーに通知するための新たな UI は必要ありません。

ページのトップへ


4. System.Speech.Synthesis

マネージ アプリケーションから音声合成を使用するサンプルをいくつか説明します。従来からよく使用される UI 出力の例ですが、"Hello, world" と発声するアプリケーションから始めます。図 5 を参照してください。このサンプルでは、Visual C# で作成された状態のコンソール アプリケーションに 3 行を追加しただけです。追加した最初の行は、単純に System.Speech.Synthesis の名前空間を導入しています。追加した 2 つ目の行は、SpeechSynthesizer のインスタンスを宣言し、作成しています。これが、その名前が示すとおり音声合成機能です。追加した 3 つ目の行は、SpeakText の呼び出しです。音声合成機能を起動するのに必要なことは、これですべてです。

図 5 Hello の発声

using System;
using System.Speech.Synthesis;

namespace TTS_Console_Sample_1
{
    class Program
    {
        static void Main(string[] args)
        {
            SpeechSynthesizer synth = new SpeechSynthesizer();
            synth.SpeakText("Hello, world!");
        }
    }
}

SpeechSynthesizer クラスは、[Speech] コントロール パネルで既定として指定されている音声合成機能を既定で使用します。ただし、SAPI DDI 対応の合成機能であれば使用することができます。

次のサンプル (図 6 を参照してください) は、Windows 2000 と Windows XP からの従来の Sam の音声、および Windows Vista からの新規の Anna と Microsoft Lili の音声を使用して実行する方法を示しています。(このサンプル、および残りの System.Speech.Synthesis のサンプルはすべて、最初の例と同じコード フレームワークを使用し、Main の中身のみを変更しています。) このサンプルは、必要とする合成機能の名前を使用する 3 つの SelectVoice のインスタンスを示しています。Windows Vista の中国語音声合成機能、Lili を使用する例も含まれています。ただ、Lili は、英語の音声にも対応できます。

図 6 複数の音声

SpeechSynthesizer synth = new SpeechSynthesizer();

synth.SelectVoice("Microsoft Sam");
synth.SpeakText("I'm Sam.");
synth.SpeakText("You may have heard me speaking to you in Windows XP.");
synth.SpeakText("Anna will make me redundant.");

synth.SelectVoice("Microsoft Anna");
synth.SpeakText("I am the new voice in Windows.");
synth.SpeakText("Sam belongs to a previous generation.");
synth.SpeakText("I sound great.");

synth.SelectVoice("Microsoft Lili");
synth.SpeakText("我是在北京被研究开发的 我使用了专业播音员的声音。每
个听到过我说话的人都说我是中文语音合成中最棒的!"); // 表示には、MS 明朝、および SimSun が必要です。
/* "私は、北京で開発されました。プロのニュース アナウンサーの声を録音して使用しています。
私の声を聞いた人は誰もが、私の音声は、今までで最もすばらしく合成された
中国語だと言います。" */

どちらのサンプルでも、合成 API は、コンソール API と同じように使用されています。つまり、アプリケーションが単純に文字を送ると、その文字列がすぐに連続して出力されます。しかし、より高度な出力として、文書表示に相当するような合成も考えられます。この場合、合成機能への入力は、出力される内容の他に、内容の特定の部分に適用されるさまざまなエフェクトや設定も含む文書となります。

XHTML 文書では、Web ページ上の特定の部分に適用される表示スタイル、および構造を記述することができます。これと同様に、SpeechSynthesizer クラスでは、音声合成記述言語 (Speech Synthesis Markup Language: SSML) という XML 文書形式を使用することができます。W3C SSML 勧告 (www.w3.org/TR/speech-synthesis) でわかりやすく説明されているため、この記事では、SSML の説明については省略します。簡単に言えば、アプリケーションでは、単純に、SSML 文書をそのまま合成機能にロードし、それを出力することができます。以下に、SSML ファイルのロード、および出力の例を示します。

SpeechSynthesizer synth = new SpeechSynthesizer();
PromptBuilder savedPrompt = new PromptBuilder();
savedPrompt.AppendSsml("c:\\prompt.ssml");
synth.Speak(SavedPrompt);

SSML ファイルの作成に代わる便利な手段として、System.Speech.Synthesis の PromptBuilder クラスを使用できます。PromptBuilder は、SSML 文書で表現できることはほとんど表現でき、より簡単に使用することができます (図 7 を参照してください)。高度な合成を作成する場合の一般的なモデルでは、最初に PromptBuilder を使用して必要な処理を行うプロンプトを作成し、その後、Synthesizer の Speak メソッド、あるいは SpeakAsync メソッドを使用してそれを出力します。

図 7 PromptBuilder の使用

//このプロンプトはかなり複雑です。
//このため、最初にそれを作成し、その後、出力を行います。
PromptBuilder myPrompt = new PromptBuilder();

//メインとなる音声スタイルを開始
PromptStyle mainStyle = new PromptStyle();
mainStyle.Rate = PromptRate.Medium;
mainStyle.Volume = PromptVolume.Loud;
myPrompt.StartStyle(MainStyle);

//聴者に警告
myPrompt.AppendAudio(new Uri(
    "file://c:\\windows\\media\\notify.wav"), "Attention!");
myPrompt.AppendText("Here are some important messages.");

//最初の重要なメッセージ
myPrompt.AppendTextWithPronunciation("WinFX", "wɪnɛfɛks");
myPrompt.AppendText("is a great platform.");

//2 つ目のメッセージ
myPrompt.AppendTextWithHint("ASP", SayAs.Acronym);
myPrompt.AppendText(
    "is an acronym for Active Server Pages. Whereas an ASP is a snake.");

myPrompt.AppendBreak();

//これらのメッセージがどれだけ重要かを強調
PromptStyle interimStyle = new PromptStyle();
interimStyle.Emphasis = PromptEmphasis.Strong;
myPrompt.StartStyle(interimStyle);
myPrompt.AppendText("Please remember these two things.");
myPrompt.EndStyle();

//ここから、メインの音声モデルに戻る
myPrompt.AppendBreak();
myPrompt.AppendText("Thank you");

myPrompt.EndStyle();
//合成機能を取得し、このメッセージを出力
SpeechSynthesizer synth = new SpeechSynthesizer();
synth.Speak(myPrompt);

図 7 は、PromptBuilder の多数の強力な機能を示しています。最初に、これが、階層構造の文書を生成していることに注意してください。このサンプルでは、別のスタイル内にネストされている音声スタイルが使用されています。文書の最初で、文書全体に使用する音声スタイルを開始しています。半分ほどのところで、強調するためにスタイルを別のものに切り替えています。このスタイルを終了したときに、文書は自動的に前のスタイルに戻ります。

このサンプルでは、他にも多くの便利な機能が使用されています。AppendAudio 関数は、WAV ファイルを出力に結合します。WAV ファイルが検出されないときに使用する代替のテキストも指定できます。AppendTextWithPronunciation 関数では、単語の正確な発音を指定することができます。音声合成エンジンは、豊富な辞書と、未知の単語の発音を導き出すアルゴリズムを組み合わせることにより、特定の言語で一般的に使用されるほとんどの単語の発音は認識できます。ただし、専門用語や商標なども含むすべての単語において、その認識された発音が正しいとは限りません。たとえば、"WinFX" は、おそらく "winfeks" と発音されます。このサンプルでは、国際音標文字を使用して "WinFX" を "wɪnɛfɛks" と記述しています。ここで、文字 "ɪ" は、Unicode 文字 0x026A ("fish" の "i" であり、"five" の "i" ではありません) です。また、文字 "ɛ" は、Unicode 文字 0x025B (一般アメリカ英語で "bed" の "e" です) です。

合成エンジンは、通常は、頭字語と大文字化された単語を区別できます。ただし、頭字語が、エンジンのヒューリスティックによって誤って 1 つの単語と推定される場合があります。このため、トークンを頭字語と識別させるために AppendTextWithHint 関数を使用することができます。PromptBuilder では、さまざまなニュアンスを導入することができます。このサンプルは、わかりやすくするため、すべてを網羅しているわけではありません。

内容の仕様と実行時の出力を分離することのもう 1 つの利点は、アプリケーションと、それが出力する特定の内容を自由に分離できることです。PromptBuilder を使用してプロンプトを SSML として永続化することで、アプリケーションの別の部分で、またはまったく別のアプリケーションでそれをロードすることが可能です。次のコードは、PromptBuilder での SSML ファイルへの書き込みです。

using(StreamWriter promptWriter = new StreamWriter("c:\\prompt.ssml"))
{
    promptWriter.Write(myPrompt.ToXml());
}

内容を分離するもう 1 つの方法として、次のように、プロンプト全体を、後で再生できるように音声ファイルに出力することができます。

SpeechSynthesizer synth = new SpeechSynthesizer();
synth.SetOutputToWaveFile("c:\\message.wav");
synth.Speak(myPrompt);
synth.SetOutputToNull();

SSML マークアップ、または PromptBuilder クラスのどちらを使用するかによって、設定のスタイルが異なります。使いやすいものを使用してかまいません。

最後に、SSML および PromptBuilder に関して、合成機能で実行可能な機能は、それぞれによって多少異なることに注意してください。このため、特定の動作は、これらのメカニズムのどちらで要求する場合でも、エンジンにそれを処理する機能があれば適用されるような付加的な要求と考えるようにします。

ページのトップへ


5. System.Speech.Recognition

アプリケーションでは、汎用的なディクテーション言語モデルを使用することができますが、実際にやってみると、認識結果の処理を行う部分のアプリケーション開発が困難であることがすぐにわかるでしょう。たとえば、ピザの注文システムを考えてみましょう。ユーザーが "ペパローニ ピザをお願いします" と言った場合には、その結果に、たいていはこの文字列が含まれます。しかし、ユーザーの発音のニュアンス、または周囲のノイズの状態によって、"ペッパーをプラザにお願いします" など、類似の別の文章が結果に含まれる可能性もあります。また、ユーザーが "メアリーは子羊を飼っています" と言った場合、結果がこのとおりになったとしても、ピザの注文システムでは意味をなしません。このような間違った結果はいずれも、アプリケーションでは使用することができません。このため、アプリケーションでは、アプリケーションが何を聞き取るかを具体的に記述する文法を提供する必要があります。

図 8 では、既定の Windows フォーム アプリケーションに数行を追加して、基本的な音声認識を実現しています。最初に、System.Speech.Recognition 名前空間を導入し、SpeechRecognizer オブジェクトのインスタンスを作成します。Form1_Load では 3 つの処理を実行します。文法を作成し、文法の SpeechRecognized イベントを受け取ることができるようにイベント ハンドラを文法に追加し、最後に、その文法を認識機能にロードします。これで、認識機能は、文法によって定義されたパターンに一致する音声を聞き取るようになります。文法に一致する何らかの音声を認識したときは、文法の SpeechRecognized イベント ハンドラが呼び出されます。このイベント ハンドラで Result オブジェクトにアクセスし、認識されたテキストを処理します。

図 8 ピザの注文

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections.Generic;
using System.Speech.Recognition;

namespace Reco_Sample_1
{
    public partial class Form1 : Form
    {
        //認識機能を作成
        SpeechRecognizer _recognizer = new SpeechRecognizer();

        public Form1() { InitializeComponent(); }

        private void Form1_Load(object sender, EventArgs e)
        {
           //ピザの文法を作成
           Choices pizzaChoices = new Choices();
           pizzaChoices.AddPhrase("I'd like a cheese pizza");
           pizzaChoices.AddPhrase("I'd like a pepperoni pizza");
           pizzaChoices.AddPhrase("I'd like a large pepperoni pizza");
           pizzaChoices.AddPhrase(
               "I'd like a small thin crust vegetarian pizza");
           Grammar pizzaGrammar = 
               new Grammar(new GrammarBuilder(pizzaChoices));

           //イベント ハンドラを追加
           pizzaGrammar.SpeechRecognized += 
               new EventHandler<RecognitionEventArgs>(
                   PizzaGrammar_SpeechRecognized);

           _recognizer.LoadGrammar(pizzaGrammar);
        }

        void PizzaGrammar_SpeechRecognized(
            object sender, RecognitionEventArgs e)
        {
            MessageBox.Show(e.Result.Text);
        }
    }
}

System.Speech.Recognition API は、W3C 音声認識文法仕様 (Speech Recognition Grammar Specification: SRGS) をサポートしています。この仕様については、www.w3.org/TR/speech-grammar (英語) を参照してください。この API は、SRGS XML 文書を作成、および処理する一連のクラスを提供します。ただし、SRGS は複雑すぎる場合があるので、この API では GrammarBuilder クラスも提供しています。ここでのピザ注文システムには、このクラスで十分です。

GrammarBuilder では、一連の語句および選択肢から文法を組み立てることができます。図 8 では、必要としない発話 ("メアリは子羊を飼っています") を聞き取ることの問題を解決し、エンジンが、不明確な音声からより適した選択を行えるようにしています。ユーザーが "ピザ" の発音を間違えても、"プラザ" という単語が認識されることはなくなります。この数行で、システムの精度は大幅に向上します。しかし、この文法にはまだいくつかの問題があります。

ユーザーが言う可能性のあることをすべて網羅して一覧しようとする手法は、手間がかかり、間違いも多くなり、保守も困難です。実際には、とても小さい文法でのみ実現可能です。それよりも、単語の組み合わせの方法を定義する文法を定義する方が適切です。また、アプリケーションがサイズ、トッピング、生地の種類を必要とする場合、結果文字列からこれらの値を解析するのも開発者にとっては難しい作業となります。認識システムで、結果の中にあるこれらの意味的な特性も識別できる方がより便利です。System.Speech.Recognition、および Windows Vista 認識エンジンでは、これが簡単にできます。

図 9 は、Choices クラスを使用して、ユーザーが選択肢のリストから何かを言う場合の文法を組み立てる方法を示しています。このコードでは、各 Choices インスタンスの内容は、コンストラクタで文字列パラメータのシーケンスとして指定されます。しかし、Choices を設定する方法は他にも多くあります。新しい語句を繰り返して追加したり、配列から Choices を構成したり、Choices を Choices に追加して、複雑でも人が理解できる組み合わせのルールを作成したりすることができます。あるいは、GrammarBuilder インスタンスを Choices に追加して、段階的に柔軟な文法を作成していくようにすることもできます (このサンプルの Permutations の部分で示されています)。

図 9 Choices を使用した文法の組み立て

private void Form1_Load(object sender, EventArgs e)
{
    //[I'd like] a [<size>] [<crust>] [<topping>] pizza [please]

    //choices の中心となるセットを作成
    Choices sizes = new Choices("small", "regular", "large");
    Choices crusts = new Choices("thin crust", "thick crust");
    Choices toppings = new Choices("vegetarian", "pepperoni", "cheese");

    //choices の順列を作成...

    //3 つすべてを選択
    GrammarBuilder sizeCrustTopping = new GrammarBuilder();
    sizeCrustTopping.AppendChoices(sizes, "size");
    sizeCrustTopping.AppendChoices(crusts, "crust");
    sizeCrustTopping.AppendChoices(toppings, "topping");

    //サイズとトッピングを選択し、既定で厚い生地とする
    GrammarBuilder sizeAndTopping = new GrammarBuilder();
    sizeAndTopping.AppendChoices(sizes, "size");
    sizeAndTopping.AppendChoices(toppings, "topping");
    sizeAndTopping.AppendResultKeyValue("crust", "thick crust");

    //トップングのみを選択し、その他は既定のままとする
    GrammarBuilder toppingOnly = new GrammarBuilder();
    toppingOnly.AppendChoices(toppings, "topping");
    toppingOnly.AppendResultKeyValue("size", "regular");
    toppingOnly.AppendResultKeyValue("crust", "thick crust");

    //順列を組み立てる
    Choices permutations = new Choices();
    permutations.AddGrammarBuilders(sizeCrustTopping);
    permutations.AddGrammarBuilders(sizeAndTopping);
    permutations.AddGrammarBuilders(toppingOnly);

    //完全なパターンを作成...
    GrammarBuilder pizzaRequest = new GrammarBuilder();
    //最初 "[I'd like] a"
    pizzaRequest.AppendChoices(new Choices("I'd like a", "a"));
    //順列 "[<size>] [<crust>] [<topping>]"
    pizzaRequest.AppendChoices(permutations);
    //最後 "pizza [please]"
    pizzaRequest.AppendChoices(new Choices("pizza", "pizza please"));

    //ピザの文法を作成
    Grammar pizzaGrammar = new Grammar(pizzaRequest);

    //イベント ハンドラを追加
    pizzaGrammar.SpeechRecognized += 
        new EventHandler<RecognitionEventArgs>(
            PizzaGrammar_SpeechRecognized);

    //文法を認識機能にロード
    _recognizer.LoadGrammar(pizzaGrammar);
}

void PizzaGrammar_SpeechRecognized(object sender, RecognitionEventArgs e)
{
    StringBuilder resultString = new StringBuilder();
    resultString.Append("Raw text result: ");
    resultString.AppendLine(e.Result.Text);
    resultString.Append("Size: ");
    resultString.AppendLine(e.Result.Semantics["size"].Value.ToString());
    resultString.Append("Crust: ");
    resultString.AppendLine(e.Result.Semantics["crust"].Value.ToString());
    resultString.Append("Topping: ");
    resultString.AppendLine(
        e.Result.Semantics["topping"].Value.ToString());
    MessageBox.Show(resultString.ToString());
}

図 9 には、結果から意味的な値を取得する方法も示されています。GrammarBuilder を使用する場合、Choices を文法に追加し、意味的な値をそれに付属させることができます。このサンプルでは、次のステートメントで行われています。

AppendChoices(toppings, "topping");

特定の言葉が、発話されていない意味的な値を暗に含む場合もあります。たとえば、ユーザーがピザのサイズを指定しない場合には、文法でサイズを "regular" に指定します。これは、次のステートメントで行われています。

AppendResultKeyValue("size", "regular");

結果から意味的な値を取得するには、RecognitionEventArgs.Result.Semantics[<name>] でアクセスします。

ページのトップへ


6. 電話アプリケーション

音声アプリケーションの最も大きな成長分野の 1 つが電話システムです。この原理の多くは、デスクトップでの音声と同じです。認識と合成が重要な技術であり、適切な文法およびプロンプトの設計が必要となります。

電話アプリケーションの開発には、他にも多くの要素が必要となります。電話アプリケーションでは、まったく別の音響モデルが必要です。このモデルは、電話システムとやり取りする必要があり、GUI がないので、ユーザーと交わされた会話を管理する必要もあります。また、電話システム アプリケーションでは、パフォーマンスを低下させることなく大量の電話をサービスできるようなスケーラビリティも必要です。

Microsoft Speech Server プラットフォームおよび SDK の開発の目的であった音声対応の電話アプリケーションの設計、チューニング、配置、およびホストは、簡単なプロジェクトではありません。Microsoft Speech Server についての詳細は、Speech Server Web サイトを参照してください。

ページのトップへ


7. まとめ

Windows Vista には、OS に組み込みの、新しく、強力なデスクトップ音声プラットフォームが含まれます。直感的な UI、および強力な API により、エンド ユーザーおよび開発者はこれらの技術を簡単に活用できます。Windows Vista の最新ベータ ビルドを入手している場合は、これらの新機能をすぐに試してみることができます。

この記事が公開されるまでには、Windows Vista Speech Recognition Web サイトも公開されます。この他のマイクロソフトの音声認識技術に関する情報については、参考資料 を参照してください。


SAPI 5.3 の新規事項

SAPI 5.3 は SAPI 5.1 からの増分的な更新 です。SAPI の中心となる目的、およびアーキテクチャに変更はありません。SAPI 5.3 では、パフォーマンスの改善、およびセキュリティと安定性の強化が行われ、以下のさまざまな新機能が追加されます。

W3C 音声合成記述言語 (Speech Synthesis Markup Language)

SAPI 5.3 は、W3C 音声合成記述言語 (Speech Synthesis Markup Language: SSML) バージョン 1.0 をサポートします。SSML は、音声の特徴、スピード、ボリューム、調子、強調、および発音を記述する機能を提供します。これにより、開発者はアプリケーションでの TTS がより自然に聞こえるようにすることができます。

W3C 音声認識文法仕様 (Speech Recognition Grammar Specification)

SAPI 5.3 には、W3C 音声認識文法仕様 (Speech Recognition Grammar Specification: SRGS) を使用する、コンテキストフリーな文法の定義のサポートが追加されます。これには、2 つの制約があります。まず、DTMC (プッシュ音) の文法を指定する SRGS の使用はサポートされません。また、XML で表現される SRGS のみがサポートされ、拡張バッカス記法 (Augmented Backus-Naur Form: ABNF) はサポートされません。

意味的な解釈

SAPI 5.3 では、SRGS 文法に、JScript で意味的な解釈を示す注釈を付けることが可能になるため、認識結果に、認識されたテキストに加えて、テキストの意味的な解釈も含めることができます。これにより、アプリケーションで認識結果を簡単に使用できるようになり、文法の作成者が、名前と値のセットで実現される以上の意味的な処理の全体を提供することができます。

辞書でのユーザー指定の "ショートカット"

これは、辞書に文字列を追加し、それにショートカットを関連付ける機能です。ディクテーションで、ユーザーがショートカットの語を言った場合、認識機能は、本来の文字列を戻します。

たとえば、場所を表すショートカットを作成しておき、ユーザーが "私の住所" と言ったときに、実際には、アプリケーションに "123 Smith Street, Apt. 7C, Bloggsville 98765, USA" というデータが渡されるようにすることができます。以下は、辞書でショートカットを設定するコードです。

CComPtr<ISpShortcut> cpShortcut;
HRESULT hr = cpShortcut.CoCreateInstance(CLSID_SpShortcut);
if (SUCCEEDED(hr))
{
    hr = cpShortcut.AddShortcut(L"my address", 1033, 
        L"123 Smith Street, Apt. 7C, Bloggsville 98765, USA", 
        SPSHT_OTHER);
}

このコードを使用すると、音声辞書にショートカットが追加されます。ユーザーが、"私の住所" と言った場合には、解釈されたテキストとして実際の住所が戻されます。

エンジンの発音の検出

SAPI 5.3 では、アプリケーションから Windows Vista の認識エンジンおよび合成エンジンに、特定の語に使用する発音を照会することができます。この API は、アプリケーションに、発音だけでなく、その発音がどのように導き出されたかも通知します。


参考資料

この記事では、Windows Vista に含まれる新しい音声技術の機能についてのみ説明しました。他の詳細については、次の参考資料を参照してください。

次のマイクロソフト音声チームのメンバによる活発なブログも役に立ちます。


Robert Brown は、マイクロソフトの Speech & Natural Language チームのリード プログラム マネージャです。Robert は、1995 年にマイクロソフトに入社し、VOIP、メッセージング テクノロジ、Speech Server、および Windows Vista の音声プラットフォームに携わってきました。この記事に協力してくださった Robert Stumberger、Rob Chambers、およびマイクロソフトの音声チームの他のメンバの皆様に感謝の意を申し上げます。


この記事は、MSDN マガジン - 2006 年 1 月からの翻訳です。

QJ: 060103

ページのトップへ