使用SAPI实现TTS文字转wav文件的功能

//头文件

/*
	文件名:tts_module.h
	2018年4月23日11:04:18
	代码目的:把文字(英语或者汉字)转化成wav文件。可以播放。即TTS text to speech。
*/
class String2Speech
{
public:
	//string to wchar*
	static WCHAR* str_to_wcharstr(std::string mystring)
	{

		int mystringSize = (int)(mystring.length()+1);
		wchar_t* mywstring = new wchar_t[mystringSize];
		MultiByteToWideChar( CP_ACP, 0, mystring.c_str(), -1, mywstring, mystringSize );
		return mywstring;
	}
	
	static bool ConvertTTS(std::string str, char *SzFileName);

};

经过代码走读,头文件修改成如下:


class String2Speech

{
public:
    virtual ~String2Speech(){}
    static bool ConvertTTS(const std::string& Content, const std::string& FileName);
};


头文件的实现如下:

/*
	2018年4月23日11:06:25
	代码功能:实现tts_module.h头文件中的函数。完成TTS
*/
#include "stdafx.h"
#include <sapi.h>  
#include <sphelper.h>  
#include "tts_module.h"
#include <time.h>

using namespace std;

/** @fn     bool String2Speech::ConvertTTS(string str, char *SzFileName)
 *  @brief  实现std::string转换为wav文件
 *  @param  str [in] 传入的std::string,将其转换为wav文件
 *  @param  SzFileName  [in],传入的char数组,大小应足以保存类似len(2018-4-16 15-46-39.wav)+1的大小
 *  @return 成功创建文件返回true, 否则返回true
 */
bool String2Speech::ConvertTTS(string str, char *SzFileName)
{
	ISpVoice *pVoice = NULL;  
	if (FAILED(::CoInitialize(NULL)))  
		return FALSE;  
	HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
	if (SUCCEEDED(hr))  
	{  
		CComPtr <ISpStream> cpWavStream;  
		CComPtr <ISpStreamFormat> cpOldStream;  
		CSpStreamFormat originalFmt;  
		pVoice->GetOutputStream(&cpOldStream);  
		originalFmt.AssignFormat(cpOldStream);
		char SaveName[30];

		// 基于当前系统的当前日期/时间
		time_t now = time(0);
		tm *t = localtime(&now);

		sprintf_s(SaveName, "%d-%d-%d %d-%d-%d.wav", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); 
		strcpy_s(SzFileName, strlen(SaveName)+1, SaveName);
		hr = SPBindToFile(SaveName, SPFM_CREATE_ALWAYS, &cpWavStream, &originalFmt.FormatId(), originalFmt.WaveFormatExPtr());  
		if (SUCCEEDED(hr))  
		{  

			pVoice->SetOutput(cpWavStream, TRUE);  

			WCHAR* w = str_to_wcharstr(str);
			//use mywstring to do:
			pVoice->Speak(w, SPF_IS_XML, NULL); 
			delete [] w;
			pVoice->Release();  
			pVoice = NULL;  

		}

	}  

	::CoUninitialize();  
	return true;


}  

经过代码走读,类实现文件如下:

#include "stdafx.h"
#include <sapi.h>  
#include <sphelper.h>  
#include "tts_module.h"




using namespace std;


/** @fn     bool String2Speech::ConvertTTS(const std::string& Content, const std::string& FileName)
 *  @brief  实现std::string转换为wav文件
 *  @param  Content [in] 类型std::string引用,将其转换为wav文件
 *  @param  FileName  [in],类型std::string引用,内容形式为GUID.wav。
 *  @return 成功创建文件返回true, 否则返回true
 */
bool String2Speech::ConvertTTS(const std::string& Content, const std::string& FileName)
{
	ISpVoice *pVoice = NULL; 
	if (FAILED(::CoInitialize(NULL)))  
		return false;
    bool ret = true;
    do 
    {
        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
        if (FAILED(hr) || (NULL == pVoice))
        {
            TALKCLIENTPLUGIN_ERROR(" -CoCreateInstance Fails, errCode: %d", GetLastError());
            ret = false;
            break;
        }
        
        CComPtr <ISpStream> cpWavStream;  
        CComPtr <ISpStreamFormat> cpOldStream;  
        CSpStreamFormat originalFmt;
        hr = pVoice->GetOutputStream(&cpOldStream);


        //在没有声卡的情况下pVoice->GetOutputStream()中cpOldStream会生成空指针
        //之前的代码并有对hr和cpOldStream进行非空判断,导致了程序在此处发生崩溃,因为生成了空指针
        if (FAILED(hr) || (NULL == cpOldStream))
        {
            TALKCLIENTPLUGIN_ERROR("- GetOutputStream failed, lastError:[%d][%d]", hr, GetLastError());
            ret = false;
            break;
        }


        originalFmt.AssignFormat(cpOldStream);
        hr = SPBindToFile(FileName.c_str(), SPFM_CREATE_ALWAYS, &cpWavStream, &originalFmt.FormatId(), originalFmt.WaveFormatExPtr());  
        if (FAILED(hr))
        {
            TALKCLIENTPLUGIN_ERROR("- SPBindToFile Fails, errCode: %d", GetLastError());
            ret = false;
            break;
        }
        pVoice->SetOutput(cpWavStream, TRUE);  
        //把文字内容转换成宽字符串进行播放,生成wav文件
        std::wstring VoiceContent = CommonTools::G2W(Content.c_str()); 
        pVoice->Speak(VoiceContent.c_str(), SPF_IS_XML, NULL); 
        pVoice->Release();  
        pVoice = NULL;       
    } while (0);


	::CoUninitialize();
	return ret;
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值