SAPI (Speech API) を、C#やC++/CLIといった.NET言語から使用できるようにするためのライブラリのコードです。
ライブラリのテストプログラムの実行イメージ
ライブラリとテストプログラム (Visual Studio 2008)
音声処理を行うクラスです。
// SpeechEngine.h #pragma once #pragma warning(disable : 4996) // 古い関数の使用に対する警告を抑制する #include <sphelper.h> #define WM_REC_EVENT WM_USER + 0 // 認識メッセージ #define WORD_MAX_SIZE 0xFF // 認識結果の語の最大サイズ namespace SAPI { // 音声エンジン class SpeechEngine { // Construction -------------------------------------------------------- public: SpeechEngine(); ~SpeechEngine(); // Operation ----------------------------------------------------------- public: void Init( HWND hWnd, const wchar_t* grammarFile ); int GetRecognitionEvent(); BOOL GetRecognitionResult( wchar_t* text ); BOOL GetRecognizedPronunciation( wchar_t* text ); BOOL GetConfidence( double& value ); const wchar_t* GetState( int eventID ); private: void InitMicrophone( CComPtr< ISpRecognizer > &recognizer ); void InitGrammar( wchar_t const* grammarFile ); // Attribute =========================================================== private: CComPtr< ISpRecoContext > m_recoContext; // 認識コンテキスト CComPtr< ISpRecoGrammar > m_recoGrammar; // ディクテーション文法 CSpEvent m_spEvent; // SAPIイベント }; }
#include "stdafx.h" #include "SpeechEngine.h" #include "SapiException.h " using namespace SAPI; // コンストラクタ SpeechEngine::SpeechEngine() : m_recoContext( NULL ), m_recoGrammar( NULL ) { } // デストラクタ SpeechEngine::~SpeechEngine() { if( m_recoContext != NULL ) { // 認識コンテキストを解放する m_recoContext.Release(); } if( m_recoGrammar != NULL ) { // ディクテーション文法を解放する m_recoGrammar.Release(); } // COMを閉じる ::CoUninitialize(); ::OutputDebugString( L"SAPIを破棄した\r\n" ); } // 初期化する void SpeechEngine::Init( HWND hWnd, const wchar_t* grammarFile ) { HRESULT result; CComPtr< ISpRecognizer > recognizer; // 認識エンジン オブジェクト // COMを初期化する result = ::CoInitialize( NULL ); if( FAILED( result ) ) { throw new SapiException( L"COM の初期化に失敗した" ); } // 認識エンジン オブジェクトを生成する result = recognizer.CoCreateInstance( CLSID_SpInprocRecognizer ); if( FAILED( result ) ) { throw new SapiException( L"認識エンジン オブジェクトの生成に失敗した" ); } // 認識コンテクスト オブジェクトを生成する result = recognizer->CreateRecoContext( &m_recoContext ); if( FAILED( result ) ) { throw new SapiException( L"認識コンテクスト オブジェクトの生成に失敗した" ); } // ウィンドウズ メッセージを認識コンテクストに登録する result = m_recoContext->SetNotifyWindowMessage( hWnd, WM_REC_EVENT, 0, 0 ); if( FAILED( result ) ) { throw new SapiException( L"ウィンドウズ メッセージの 認識コンテクストへの登録に失敗した" ); } // 認識エンジンに要求するイベントの種類を設定する const ULONGLONG eventInterest = SPFEI( SPEI_RECOGNITION ) | // 第2パス最終結果生成 SPFEI( SPEI_FALSE_RECOGNITION ) | // 第2パス最終結果生成 SPFEI( SPEI_SOUND_START ) | // 音声検出 (切り出しを行う場合は、切り出し開始位置検出時) SPFEI( SPEI_SOUND_END ); // 切り出し終了位置検出 result = m_recoContext->SetInterest( eventInterest, eventInterest ); if( FAILED( result ) ) { throw new SapiException( L"認識エンジンに要求する イベントの種類の設定に失敗した" ); } // マイクを初期化する InitMicrophone( recognizer ); // 文法を初期化する InitGrammar( grammarFile ); ::OutputDebugString( L"SAPIを初期化した\r\n" ); } // マイクを初期化する void SpeechEngine::InitMicrophone( CComPtr< ISpRecognizer > &recognizer ) { HRESULT result; CComPtr< ISpAudio > audio; // リアルタイム オーディオ ストリーム // デフォルトのオーディオ オブジェクトを生成する result = SpCreateDefaultObjectFromCategoryId( SPCAT_AUDIOIN, &audio ); if( FAILED( result ) ) { throw new SapiException( L"オーディオ オブジェクトの生成に失敗した" ); } // ... 入力ストリームに音声認識エンジンを使うように設定する result = recognizer->SetInput( audio, true ); if( FAILED( result ) ) { throw new SapiException( L"入力ストーの設定に失敗した" ); } } // 文法を初期化する void SpeechEngine::InitGrammar( wchar_t const* grammarFile ) { HRESULT result; const ULONGLONG grammarID = 0; // 文法ID // XMLによるコマンド文法を生成する result = m_recoContext->CreateGrammar( grammarID, &m_recoGrammar ); if( FAILED( result ) ) { throw new SapiException( L"コマンド文法の生成に失敗した" ); } if( grammarFile != NULL ) { // ファイルからディクテーション文法を読み込む result = m_recoGrammar->LoadCmdFromFile( grammarFile, SPLO_STATIC ); if( FAILED( result ) ) { throw new SapiException( L"ファイルからのディクテショ文読込みに失敗した" ); } // ディクテーションの文法規則をアクテブす result = m_recoGrammar->SetRuleState( NULL, NULL, SPRS_ACTIVE ); if( FAILED( result ) ) { throw new SapiException( L"ディクテーションの文法規則をアクティブにできなかった" ); } } else { // デフォルトのディクテーション文法を読み込む result = m_recoGrammar->LoadDictation( NULL, SPLO_STATIC ); if( FAILED( result ) ) { throw new SapiException( L"デフォルトのディクテーション文法の読み込みに失敗した" ); } // ディクテーションのトピックをアクティブにする result = m_recoGrammar->SetDictationState( SPRS_ACTIVE ); if( FAILED( result ) ) { throw new SapiException( L"ディクテーションのトピックを アクティブにできなかった" ); } } } // 認識イベントを取得する int SpeechEngine::GetRecognitionEvent() { // キューにイベントがなければ何もしない if( m_spEvent.GetFrom( m_recoContext ) != S_OK ) { return 0; } // イベントIDを返す return m_spEvent.eEventId; } // 認識結果を取得する BOOL SpeechEngine::GetRecognitionResult( wchar_t* text ) { CSpDynamicString dynamicStrig; // 認識結果を取得する HRESULT result = m_spEvent.RecoResult()->GetText( ( ULONG )SP_GETWHOLEPHRASE, ( ULONG )SP_GETWHOLEPHRASE, true, &dynamicStrig, NULL ); if( FAILED( result ) || ( dynamicStrig == NULL ) ) { // 取得に失敗したならば、処理を中止する return false; } // 認識された文字列の型を変換して取得する wcscpy_s( text, WORD_MAX_SIZE, W2T( dynamicStrig ) ); return true; } // 認識された発音を取得する BOOL SpeechEngine::GetRecognizedPronunciation( wchar_t* text ) { SPPHRASE* phrase; // First-Bestのフレーズを取得する HRESULT result = m_spEvent.RecoResult()->GetPhrase( &phrase ); if( FAILED( result ) ) { return false; } // ... それの発音を取得する const SPPHONEID* phoneID = phrase->pElements->pszPronunciation; if( phoneID == NULL ) { return false; } // 取得された文字列の型を変換する wcscpy_s( text, WORD_MAX_SIZE, reinterpret_cast< const wchar_t* >( phoneID ) ); return true; } // 信頼度を取得する BOOL SpeechEngine::GetConfidence( double& value ) { SPPHRASE* phrase; // First-Bestのフレーズを取得する HRESULT result = m_spEvent.RecoResult()->GetPhrase( &phrase ); if( FAILED( result ) ) { return false; } // ... それの信頼度を取得する value = phrase->Rule.SREngineConfidence; return true; } // 状態を取得する const wchar_t* SpeechEngine::GetState( int eventID ) { switch( eventID ) { case SPEI_SOUND_START: // 音声が開始された return L"認識中"; case SPEI_SOUND_END: // 音声が終了された return L"終了"; case SPEI_RECOGNITION: // 認識した return L"待機中"; case SPEI_FALSE_RECOGNITION: // 認識に失敗した return L"認識失敗"; } return L"error"; }
上記クラスのラッパーです。
// Recognition.h #pragma once #include "SpeechEngine.h" namespace SAPI { class SpeechEngine; // 認識 public ref class Recognition { // Construction -------------------------------------------------------- public: ~Recognition() { Recognition::!Recognition(); } !Recognition(); // Operation ----------------------------------------------------------- public: bool Init( System::IntPtr hWnd ); bool Init( System::IntPtr hWnd, System::String^ grammarFile ); int GetRecognitionEvent(); bool GetRecognitionResult( System::String^% text ); bool GetRecognizedPronunciation( System::String^% text ); bool GetConfidence( double& value ); System::String^ GetState( int eventID ); // Attribute =========================================================== private: SpeechEngine* m_sapi; public: literal int REC_EVENT = WM_REC_EVENT; // 認識イベント literal int SOUND_START = SPEI_SOUND_START; // 音声が開始された literal int SOUND_END = SPEI_SOUND_END; // 音声が終了された literal int RECOGNITION = SPEI_RECOGNITION; // 認識した literal int FALSE_RECOGNITION = SPEI_FALSE_RECOGNITION; // 認識に失敗した }; }
#include "StdAfx.h" #include "Recognition.h" #include "SapiException.h " using namespace SAPI; using namespace System::Diagnostics; // ファイナライザ Recognition::!Recognition() { delete m_sapi; } // 初期化する bool Recognition::Init( System::IntPtr hWnd ) { return Init( hWnd, nullptr ); } // 初期化する bool Recognition::Init( System::IntPtr hWnd, System::String^ grammarFile ) { Debug::Write( "SAPIを初期化する" ); // SAPIを構築する m_sapi = new SpeechEngine(); // ウィンドウ ハンドルへキャストする HWND windowHandle = reinterpret_cast< HWND >( hWnd.ToInt32() ); try { pin_ptr< wchar_t > wcharPinptr = nullptr; if( grammarFile != nullptr ) { // System::Stringをwchar_t型の配列にする array< wchar_t >^ wcharArray = grammarFile->ToCharArray(); // ... アンマネージド関数に渡すために、配列のアドレスを固定する wcharPinptr = &wcharArray[ 0 ]; } // 初期化する m_sapi->Init( windowHandle, wcharPinptr ); } catch( SapiException* e ) { // SAPIの例外を捕捉した Debug::Write( gcnew System::String( e->GetMessage() ) ); Debug::Write( "SAPIの初期化に失敗した" ); return false; } return true; } // 認識イベントを取得する int Recognition::GetRecognitionEvent() { return m_sapi->GetRecognitionEvent(); } // 認識結果を取得する bool Recognition::GetRecognitionResult( System::String^% text ) { wchar_t result[ WORD_MAX_SIZE ]; if( !m_sapi->GetRecognitionResult( result ) ) { return false; } // 型を変換する text = gcnew System::String( result ); return true; } // 認識された発音を取得する bool Recognition::GetRecognizedPronunciation( System::String^% text ) { wchar_t result[ WORD_MAX_SIZE ]; if( !m_sapi->GetRecognizedPronunciation( result ) ) { return false; } // 型を変換する text = gcnew System::String( result ); return true; } // 信頼度を取得する bool Recognition::GetConfidence( double& value ) { if( !m_sapi->GetConfidence( value ) ) { return false; } return true; } // 状態を取得する System::String^ Recognition::GetState( int eventID ) { return gcnew System::String( m_sapi->GetState( eventID ) ); }