⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 texttospeech.cpp

📁 一个用vc写成的手写数字识别的例子
💻 CPP
字号:
// TextToSpeech.cpp: implementation of the CASRTextToSpeech class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TextToSpeech.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CASRTextToSpeech::CASRTextToSpeech()
{
	m_IpVoice = NULL;
	m_cpOutAudio=NULL;
	m_strLastError=_T("");
}

CASRTextToSpeech::~CASRTextToSpeech()
{
	if(m_IpVoice) 
	{
		Close();
	}
}

// initialize
HRESULT CASRTextToSpeech::Init(HWND hWnd)
{
   if (FAILED(CoInitialize(NULL))) 
   {
	   m_strLastError=_T("Error intialization COM");
	   return FALSE;
   }

   HRESULT hr;	
   hr = m_IpVoice.CoCreateInstance(CLSID_SpVoice);

   if (FAILED(hr)) 
   {
	   m_strLastError=_T("Error creating voice");
	   return hr;
   }
	
//   hr = m_IpVoice->SetInterest(SPFEI(SPEI_VISEME), SPFEI(SPEI_VISEME));
   hr = m_IpVoice->SetInterest(SPFEI_ALL_TTS_EVENTS, SPFEI_ALL_TTS_EVENTS); //触发所有TTS事件
   if (FAILED(hr)) 
   {
	   m_strLastError=_T("Error creating interest...seriously");
	   return hr;
   }

   if (::IsWindow(hWnd))
   {
	   hr = m_IpVoice->SetNotifyWindowMessage(hWnd, WM_SPEVENT, 0, 0);     //设置事件到达所通知的窗口
	   if (FAILED(hr)) 
	   {
		   m_strLastError=_T("Error setting notification window");
		   return FALSE;
	   }
   }
   else
   {
	  m_strLastError=_T("Error no this window");
	  return FALSE;
   }

   SpCreateDefaultObjectFromCategoryId( SPCAT_AUDIOOUT, &m_cpOutAudio );    //创建默认的音频输出

   return TRUE;
}

void CASRTextToSpeech::Close()
{
	if(m_IpVoice) 
	{    
		m_IpVoice.Release();
		m_IpVoice=NULL;
	}
	if(m_cpOutAudio)
	{
		m_cpOutAudio.Release();
		m_cpOutAudio=NULL;
	}
	CoUninitialize();
}
   
// speak
HRESULT CASRTextToSpeech::Speak(const WCHAR *pwcs,DWORD dwFlags,ULONG *pulStreamNumber)
{
	HRESULT hr=m_IpVoice->Speak(pwcs,dwFlags,pulStreamNumber);
	if (FAILED(hr)) 
	{                                                                                                                                
		switch (hr)
		{
		case E_INVALIDARG:
		      m_strLastError=_T("One or more parameters are invalid");
			  break;
		case E_POINTER:
		      m_strLastError=_T("Invalid pointer");
			  break;			
		case E_OUTOFMEMORY:
		      m_strLastError=_T("Exceeded available memory");
			  break;
		case SPERR_INVALID_FLAGS:
		      m_strLastError=_T("Invalid flags specified for this operation");
			  break;
		case SPERR_DEVICE_BUSY:
		      m_strLastError=_T("Timeout occurred on synchronous call");
			  break;
		}
	}                          

	return hr;
}

HRESULT CASRTextToSpeech::SpeakText(CString strText, DWORD dwFlags)
{
	return Speak(strText.AllocSysString(),dwFlags,NULL);
}

HRESULT CASRTextToSpeech::SpeakXML(CString strXMLText, DWORD dwFlags)
{
	return Speak(strXMLText.AllocSysString(),dwFlags,NULL);
}

HRESULT CASRTextToSpeech::SpeakTextFile(CString strTextPath)
{
	return Speak(strTextPath.AllocSysString(),SPF_IS_FILENAME|SPF_ASYNC|SPF_IS_NOT_XML,NULL);
}

HRESULT CASRTextToSpeech::SpeakXMLFile(CString strXMLPath)
{
	return Speak(strXMLPath.AllocSysString(),SPF_IS_FILENAME|SPF_ASYNC|SPF_IS_XML,NULL);
}

HRESULT CASRTextToSpeech::SpeakFromWAV(CString strPathWAV)
{
	CComPtr<ISpStream>       cpWavStream;
	HRESULT hr = SPBindToFile( strPathWAV, SPFM_OPEN_READONLY, &cpWavStream );
    if( SUCCEEDED( hr ))
    {
        hr = m_IpVoice->SpeakStream( cpWavStream, SPF_ASYNC, NULL );
    }
	m_IpVoice->WaitUntilDone( INFINITE );
	cpWavStream.Release();
	return hr; 
}

HRESULT CASRTextToSpeech::SpeakToWAV(CString strText,CString strPathWAV)
{
	CComPtr<ISpStreamFormat>    cpOldStream;
	CComPtr<ISpStream>          cpWavStream;
	CSpStreamFormat             OriginalFmt;

	HRESULT hr;
	hr = m_IpVoice->GetOutputStream( &cpOldStream );
	if (hr == S_OK)
	{
		hr = OriginalFmt.AssignFormat(cpOldStream);
	}
	else
	{
		hr = E_FAIL;
	}
	// User SAPI helper function in sphelper.h to create a wav file
	if (SUCCEEDED(hr))
	{
		hr = SPBindToFile(strPathWAV, SPFM_CREATE_ALWAYS, &cpWavStream, &OriginalFmt.FormatId(), OriginalFmt.WaveFormatExPtr() ); 
	}
	if( SUCCEEDED( hr ))
	{
		// Set the voice's output to the wav file instead of the speakers
		hr = m_IpVoice->SetOutput(cpWavStream, TRUE);
	}
    if ( SUCCEEDED( hr ) )
    {
	   // Do the Speak
	   SpeakText(strText);
    }

			// Set output back to original stream
			// Wait until the speak is finished if saving to a wav file so that
			// the smart pointer cpWavStream doesn't get released before its
			// finished writing to the wav.
	m_IpVoice->WaitUntilDone( INFINITE );
	cpWavStream.Release();
			
    // Reset output
	m_IpVoice->SetOutput( cpOldStream, FALSE );

	cpOldStream.Release();

	return hr;
}

HRESULT CASRTextToSpeech::Pause()
{
	return m_IpVoice->Pause();
}

HRESULT CASRTextToSpeech::Resume()
{
	return m_IpVoice->Resume();
}

// rate
HRESULT CASRTextToSpeech::SetRate(long lRateAdjust)
{
	return m_IpVoice->SetRate(lRateAdjust);
}

HRESULT CASRTextToSpeech::GetRate(long* plRateAdjust)
{
	return m_IpVoice->GetRate(plRateAdjust);
}

// volume
HRESULT CASRTextToSpeech::SetVolume(USHORT usVolume)
{
	return m_IpVoice->SetVolume(usVolume);
}

HRESULT CASRTextToSpeech::GetVolume(USHORT* pusVolume)
{
	return m_IpVoice->GetVolume(pusVolume);
}

// voice
ULONG CASRTextToSpeech::GetVoiceCount()
{
	HRESULT                             hr = S_OK;
	CComPtr<ISpObjectToken>             cpVoiceToken;
	CComPtr<IEnumSpObjectTokens>        cpEnum;
	ULONG                               ulCount = -1;

	//Enumerate the available voices 
	hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
	if(FAILED(hr))
	{
		m_strLastError = _T("Error to enumerate voices");
		return -1;
	}

	//Get the number of voices
	hr = cpEnum->GetCount(&ulCount);
	if(FAILED(hr))
	{
		m_strLastError = _T("Error to get voice count");
		return -1;
	}

	return ulCount;
}

HRESULT CASRTextToSpeech::GetVoice(WCHAR **ppszDescription, ULONG lIndex)
{
	HRESULT                             hr = S_OK;
	CComPtr<ISpObjectToken>             cpVoiceToken;
	CComPtr<IEnumSpObjectTokens>        cpEnum;
	ULONG                               ulCount = 0;

	if (lIndex == -1)
	{
		// current voice
		//

		hr = m_IpVoice->GetVoice(&cpVoiceToken);
		if(FAILED(hr))
		{
			m_strLastError = _T("Error to get current voice");
			return hr;
		}

		SpGetDescription(cpVoiceToken, ppszDescription);
		if(FAILED(hr))
		{
			m_strLastError = _T("Error to get current voice description");
			return hr;
		}
	}
	else
	{
		// else other voices, we should enumerate the voice list first
		//

		//Enumerate the available voices 
		hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
		if(FAILED(hr))
		{
			m_strLastError = _T("Error to enumerate voices");
			return hr;
		}

		//Get the number of voices
		hr = cpEnum->GetCount(&ulCount);
		if(FAILED(hr))
		{
			m_strLastError = _T("Error to voice count");
			return hr;
		}

		// range control
		ASSERT(lIndex >= 0);
		ASSERT(lIndex < ulCount);

		// Obtain specified voice id
		ULONG l = 0;
		while (SUCCEEDED(hr))
		{
			cpVoiceToken.Release();
			hr = cpEnum->Next( 1, &cpVoiceToken, NULL );
			if(FAILED(hr))
			{
				m_strLastError = _T("Error to get voice token");
				return hr;
			}

			if (l == lIndex)
			{
				hr = SpGetDescription(cpVoiceToken, ppszDescription);
				if(FAILED(hr))
				{
					m_strLastError = _T("Error to get voice description");
					return hr;
				}
				break;
			}

			l++;
		}
	}

	return hr;
}

HRESULT CASRTextToSpeech::SetVoice(WCHAR **ppszDescription)
{
	HRESULT                             hr = S_OK;
	CComPtr<ISpObjectToken>             cpVoiceToken;
	CComPtr<IEnumSpObjectTokens>        cpEnum;
	ULONG                               ulCount = 0;

	//Enumerate the available voices 
	hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
	if(FAILED(hr))
	{
		m_strLastError = _T("Error to enumerate voices");
		return hr;
	}

	//Get the number of voices
	hr = cpEnum->GetCount(&ulCount);
	if(FAILED(hr))
	{
		m_strLastError = _T("Error to voice count");
		return hr;
	}

	// Obtain specified voice id
	while (SUCCEEDED(hr) && ulCount--)
	{
		cpVoiceToken.Release();
		hr = cpEnum->Next( 1, &cpVoiceToken, NULL );
		if(FAILED(hr))
		{
			m_strLastError = _T("Error to voice token");
			return hr;
		}

		WCHAR *pszDescription1;
		hr = SpGetDescription(cpVoiceToken, &pszDescription1);
		if(FAILED(hr))
		{
			m_strLastError = _T("Error to get voice description");
			return hr;
		}

		if (! wcsicmp(pszDescription1, *ppszDescription))
		{
			hr = m_IpVoice->SetVoice(cpVoiceToken);
			if(FAILED(hr))
			{
				m_strLastError = _T("Error to set voice");
				return hr;
			}

			break;
		}
	}

	return hr;
}

HRESULT CASRTextToSpeech::SetAudio(SPSTREAMFORMAT eFmt)
{
	HRESULT hr;
    CSpStreamFormat Fmt;
    Fmt.AssignFormat(eFmt);
	if ( m_cpOutAudio )
	{
		hr = m_cpOutAudio->SetFormat( Fmt.FormatId(), Fmt.WaveFormatExPtr());
	}
	else
	{
		hr = E_FAIL;
	}

    if( SUCCEEDED( hr ))
    {
        hr = m_IpVoice->SetOutput( m_cpOutAudio, FALSE );
    }

	return hr;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -