SpeechRecognitionEngine は 16 bit オーディオでのみ動作する

SpeechRecognitionEngine は SetInputToAudioStream(Stream, SpeechAudioFormatInfo) メソッドによって任意のオーディオストリームとそのフォーマットから音声認識処理を開始することができます。 ところが SpeechRecognitionEngine は 16bit のオーディオストリームと、そのフォーマット設定でのみ動作するようです。 ここでは、私が行った検証について紹介します。

Microsoft 社の Kinect Sensor V2 のサンプルでは SpeechRecognitionEngine は 16bit のオーディオを要求するとコメントされています。

Microsoft.Speech (v11) で確認していますが、System.Speech でも同じことが言える可能性は十分にあります。 ただし、Microsoft.Speech と System.Speech は仕様が異なる点が多々あるため、 16bit 以外のオーディオでも正しく動作したり、異なる原因で動作しないことも考えられます。

ここでは 32bit オーディオで検証していますが、24bit オーディオでは検証していません。

SpeechAudioFormatInfo について

フォーマットを指定するための SpeechAudioFormatInfo には 2 種類のコンストラクタが用意されていて、 一方は簡易的なもの、もう一方は詳細を指定して初期化するものになっています。詳細は公式を確認してください。

System.Speech.SpeechAudioFormatInfo - msdn Microsoft.Speech.SpeechAudioFormatInfo - msdn

簡易的なコンストラクタでは 16bit オーディオの設定でのみ、インスタンスを初期化することができますが、 詳細なコンストラクタでは 32bit オーディオの設定でインスタンスを初期化することが可能です。 例えば次ように初期化することができます。

new SpeechAudioFormatInfo(
    EncodingFormat.Pcm,
    16000, // SamplesPerSec (16sampes/1msec from ms sample)
    32,    // BitsPerSample,
    1,     // Channnel Count
    64000, // AverageBytesPerSecond(=SamplesPerSec * BlockAlign)
    4,     // BlockAlign
    null   // FormatSpecificData
    );

パラメータの詳細については割愛しますが、 サンプルあたりの情報量は 32bit 、したがってサンプルあたりに必要な byte 数(BlockAlign) を 4 として設定しているのが確認できればよいと思います。

32bit 設定の SpeechAudioFormatInfo を指定すると例外が通知される

用意した 32bit のオーディオストリームと対応する設定の SpeechAudioFormatInfo を SpeechRecognitionEngine.SetInputToAudioStream() に設定すると、 例外「NotImplementedException (メソッドまたは操作は実装されていません。)」が通知されます。

簡単に詳細を確認したところ、どうも Speech 内部の実装にある ISpRecognizer.GetFormat なる処理で例外が通知されているようなので、 これはもう 16bit にしか対応していない、ということになります。

32bit オーディオストリームを入力しても音声認識されない

32bit のオーディオストリームを 16 bit のオーディオフォーマット設定(SpeechAudioFormatInfo) で入力したところ、例外は通知されなくなりました。 音声認識も Recognize メソッドなどによって開始することができますが、認識処理そのものは正しく実行されないようです。

this.speechEngine.SetInputToAudioStream(
    32bitAudioStream, new SpeechAudioFormatInfo(EncodingFormat.Pcm,
                                                16000,
                                                16,
                                                1,
                                                32000,
                                                2,
                                                null));

32bit オーディオストリームしか得られない場合に

Microsoft 社の Kinect Sensor V2 のサンプルを読む限り、 Stream.Read メソッドによって得られる結果が 16 bit の情報になるようにラップすることで 32bit のオーディオストリームも音声認識させることが可能になるようです。

またマイク入力などの場合には SetInputToDefaultAudioDevice() メソッドを利用し、 OS で設定した標準のマイク入力を SpeechRecognitionEngine に入力する、という手があります。