// TTS.cpp: CTTS クラスのインプリメンテーション // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "ebwin.h" #include "TTS.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // 構築/消滅 ////////////////////////////////////////////////////////////////////// CTTS::CTTS() { HRESULT hr = S_OK; m_pVoice = NULL; m_TTS_attr_name = ""; m_buffer = NULL; if (FAILED(::CoInitialize(NULL))) return; hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&m_pVoice); if( ! SUCCEEDED(hr)) m_pVoice = NULL; // 音声フォーマットの設定 if ( m_pVoice ) { CSpStreamFormat Fmt; hr = Fmt.AssignFormat( SPSF_44kHz16BitMono ); if ( SUCCEEDED( hr ) ) SpCreateDefaultObjectFromCategoryId( SPCAT_AUDIOOUT, &m_cpOutAudio ); if ( m_cpOutAudio ) { hr = m_cpOutAudio->SetFormat( Fmt.FormatId(), Fmt.WaveFormatExPtr() ); if( SUCCEEDED( hr ) ) hr = m_pVoice->SetOutput( m_cpOutAudio, FALSE ); } } } CTTS::~CTTS() { m_cpOutAudio.Release(); if ( m_buffer ) { free( m_buffer ); m_buffer = NULL; } if ( m_pVoice ) { m_pVoice->Release(); m_pVoice = NULL; } ::CoUninitialize(); } // 音声の変更 // ex) ChangeVoice( "Mictosoft Mary" ) HRESULT CTTS::ChangeVoice( CString name ) { #if !defined(UNICODE) int wlen,dlen; #endif if ( !m_pVoice ) return E_INVALIDARG; if ( m_TTS_attr_name.Compare( name ) == 0 ) return S_OK; Stop(); // stop voice m_TTS_attr_name = name; HRESULT hr = S_OK; CComPtr cpToken; CComPtr cpEnum; // Create the SAPI voice WCHAR wname[128]; wcscpy(wname,L"Name="); #ifdef UNICODE wcscat(wname, m_TTS_attr_name ); #else wlen = wcslen(wname); dlen = ::MultiByteToWideChar( _KANJI_CP , // コードページ 0, // 文字の種類を指定するフラグ (LPCTSTR)m_TTS_attr_name, // マップ元文字列のアドレス m_TTS_attr_name.GetLength(), // マップ元文字列のバイト数 wname+wlen, // マップ先ワイド文字列を入れるバッファのアドレス (128-wlen)*2 // バッファのサイズ ); wname[wlen+dlen] = 0; #endif //Enumerate voice tokens with attribute if(SUCCEEDED(hr)) hr = SpEnumTokens(SPCAT_VOICES, wname, NULL, &cpEnum); //Get the closest token if(SUCCEEDED(hr)) hr = cpEnum ->Next(1, &cpToken, NULL); //set the voice if(SUCCEEDED(hr)) { hr = m_pVoice->SetVoice( cpToken); } //Release objects cpEnum.Release(); cpToken.Release(); return hr; } // 文字列の読み上げ HRESULT CTTS::Speak( LPCTSTR buf ) { HRESULT hr = S_OK; if ( !m_pVoice ) return E_INVALIDARG; if ( m_buffer ) { free( m_buffer ); m_buffer = NULL; } #if defined(UNICODE) int size = _tcslen(buf); m_buffer = (WCHAR*)malloc( (size+1)*2 ); _tcscpy( m_buffer, buf ); #else int dlen; int size = strlen(buf); m_buffer = (WCHAR*)malloc( (size+1)*2 ); dlen = ::MultiByteToWideChar( _KANJI_CP , // コードページ 0, // 文字の種類を指定するフラグ (char*)buf, // マップ元文字列のアドレス size, // マップ元文字列のバイト数 m_buffer, // マップ先ワイド文字列を入れるバッファのアドレス size*2 // バッファのサイズ ); m_buffer[dlen] = 0; #endif // Speak the text string hr = m_pVoice->Speak(m_buffer, SVSFlagsAsync, NULL); return hr; } // 文字列の読み上げの中断 HRESULT CTTS::Stop() { HRESULT hr = S_OK; if ( !m_pVoice ) return E_INVALIDARG; hr = m_pVoice->Speak( NULL, SPF_PURGEBEFORESPEAK, 0 ); if ( m_buffer ) { free( m_buffer ); m_buffer = NULL; } return hr; } // 利用可能な音声を列挙する HRESULT CTTS::EnumVoice( CStringArray *lines ) { HRESULT hr = S_OK; lines->RemoveAll(); if ( !m_pVoice ) return E_INVALIDARG; CComPtr cpToken; CComPtr cpEnum; ULONG ulCount; //Enumerate the available voices if(SUCCEEDED(hr)) hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum); //Get the number of voices if(SUCCEEDED(hr)) hr = cpEnum->GetCount(&ulCount); // Obtain a list of available voice tokens, set the voice to the token, and call Speak while (SUCCEEDED(hr) && ulCount -- ) { cpToken.Release(); if(SUCCEEDED(hr)) hr = cpEnum->Next( 1, &cpToken, NULL ); if(SUCCEEDED(hr)) { WCHAR *desc; SpGetDescription( cpToken, &desc, SpGetUserDefaultUILanguage() ); #ifdef UNICODE lines->Add( CString(desc) ); #else int wlen = wcslen(desc); BYTE* mbstr = (BYTE*)malloc( wlen*2+1 ); int nChar = ::WideCharToMultiByte(_KANJI_CP , NULL, desc, wlen, (char*)mbstr, wlen*2, NULL, NULL); // 変換(→ShiftJIS) mbstr[nChar] = '\0'; lines->Add( CString( mbstr ) ); free( mbstr ); #endif } } cpEnum.Release(); cpToken.Release(); return hr; }