sapi 实现语音朗读

2023-11-07

头文件定义(CSpeechSpeekImpl.h):

#pragma once

#include "sphelper.h"
class CSpeechSpeekImpl
{
public:
    CSpeechSpeekImpl(void);
    ~CSpeechSpeekImpl(void);

    HRESULT SpeechVoice(LPCSTR lpszVoiceText, UINT bSyn=TRUE);
    HRESULT SetVolume(USHORT usVolume);
    HRESULT MakeWavFile(LPCTSTR lpszVoiceText, LPCTSTR lpszWaveFile);

private:
    ISpVoice* m_pVoice;
    BOOL Inited();
    void EnumVoicePackage();
};

源码实现(CSpeechSpeekImpl.cpp):

#include "StdAfx.h"
#include "SpeechSpeekImpl.h"

#include "sapi.h"
#pragma comment(lib,"sapi.lib")

CSpeechSpeekImpl::CSpeechSpeekImpl(void)
{
    m_pVoice = NULL;
    CoInitialize(NULL);
    Inited();
}


CSpeechSpeekImpl::~CSpeechSpeekImpl(void)
{
    if ( m_pVoice )
        m_pVoice->Release();
    CoUninitialize();
}

BOOL CSpeechSpeekImpl::Inited()
{
    //初始化COM 
    if ( m_pVoice == NULL )
    {
        //初始化SAPI 
        HRESULT hr = CoCreateInstance(CLSID_SpVoice, 
            NULL, 
            CLSCTX_ALL, 
            IID_ISpVoice, 
            (void **)&m_pVoice); 
        ISpObjectToken * pSpObjectToken = NULL; 
        if (SUCCEEDED(SpFindBestToken(SPCAT_VOICES, 
            L"language=804", 
            NULL, 
            &pSpObjectToken)))//804代表中文 
        { 
            m_pVoice->SetVoice(pSpObjectToken);//声音大小
            m_pVoice->SetRate(-8);//设置朗读速度(取值范围:-10到10)
            pSpObjectToken->Release(); 
        }
        else
        { 
            return FALSE; 
        } 
    }

    if ( m_pVoice == NULL )
        return FALSE;

    return TRUE;
}

HRESULT CSpeechSpeekImpl::SpeechVoice(LPCSTR lpszVoiceText, UINT bSyn/*=TRUE*/)
{
    if ( !Inited() )
        return E_FAIL;

    //朗读文字 
    CString strText = __T(lpszVoiceText);
    BSTR lpwszVoiceText = strText.AllocSysString();
    m_pVoice->SetRate(2);	//设置朗读速度(取值范围:-10到10)
    HRESULT hr = m_pVoice->Speak(lpwszVoiceText, SPF_ASYNC, NULL); 
    SysFreeString(lpwszVoiceText);

    return S_OK;
}


HRESULT CSpeechSpeekImpl::SetVolume(USHORT usVolume)
{
    if ( !Inited() )
        return E_FAIL;

    return m_pVoice->SetVolume(usVolume);// m_pVoice->SetVolume(usVolume);
}

//生成WAV文件
HRESULT CSpeechSpeekImpl::MakeWavFile(LPCTSTR lpszVoiceText, LPCTSTR lpszWaveFile)
{
    if ( !Inited() )
        return E_FAIL;

    CComPtr<ISpStream> cpISpStream;
    CComPtr<ISpStreamFormat> cpISpStreamFormat;
    CSpStreamFormat spStreamFormat;
    m_pVoice->GetOutputStream(&cpISpStreamFormat);
    spStreamFormat.AssignFormat(cpISpStreamFormat);
    HRESULT hResult = SPBindToFile(lpszWaveFile, 
        SPFM_CREATE_ALWAYS, 
        &cpISpStream, 
        &spStreamFormat.FormatId(), 
        spStreamFormat.WaveFormatExPtr());
    if(SUCCEEDED(hResult))
    {
        m_pVoice->SetOutput(cpISpStream, TRUE);
        CString strText = __T(lpszVoiceText);
        BSTR lpwszVoiceText = strText.AllocSysString();
        m_pVoice->SetRate(2);
        m_pVoice->Speak(lpwszVoiceText, SPF_DEFAULT, NULL);
        SysFreeString(lpwszVoiceText);
        return S_OK;
    }
    else
    {
        return E_FAIL;
    }
}


void CSpeechSpeekImpl::EnumVoicePackage()
{
    //初始化COM组件
    if (FAILED(::CoInitialize(NULL)))
        return;

    //枚举所有语音Token
    IEnumSpObjectTokens* pIEnumSpObjectTokens = NULL;
    if(SUCCEEDED(SpEnumTokens(SPCAT_VOICES, NULL, NULL, &pIEnumSpObjectTokens)))
    {
        //得到所有语音Token的个数
        ULONG ulTokensNumber = 0;
        pIEnumSpObjectTokens->GetCount(&ulTokensNumber);

        //检测该机器是否安装有语音包
        if (ulTokensNumber == 0)
            return;    

        //将语音包的名字加入组合框控件
        CString strVoicePackageName = _T("");
        CString strTokenPrefixText = _T("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\");
        for(ULONG i=0; i<ulTokensNumber; i++)
        {
            ISpObjectToken* pISpObjectToken = NULL;
            pIEnumSpObjectTokens->Item(i, &pISpObjectToken);
            WCHAR* pChar;
            pISpObjectToken->GetId(&pChar);
            strVoicePackageName = pChar;
            strVoicePackageName.Delete(0, strTokenPrefixText.GetLength());
        }

//设置语言
// 		ISpObjectToken *pISpObjectToken = NULL;
// 		pIEnumSpObjectTokens->Item(1, &pISpObjectToken);
// 		m_pVoice->SetVoice(pISpObjectToken);
// 		pISpObjectToken->Release();

        pIEnumSpObjectTokens->Release();
    }
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

sapi 实现语音朗读 的相关文章

  • JS 元素遍历

    1 循环遍历从getElementsByClassName返回的所有元素 var elements document getElementsByClassName classname Array prototype forEach call
  • Gh0st 远程管理系统新概念

    接触Gh0st有很长一段时间了 对于插件或是界面已然是轻车熟路 从下月开始将分章节系统性详细讲解架构模式 以及如何设计自己企业的远控管理软件
  • VC++ MapWinGis篇(创建图层)

    MapWinGis控件的引用 import MapWinGIS ocx rename IImage gisIImage rename ImageType gisImageType rename Point gisPoint using na
  • VC++ 控制台程序常用接口

    1 申请一个控制台窗口 如果程序本身是控制台程序 可以不用调用 AllocConsole 2 获取控制台屏幕缓冲区的句柄 HANDLE m hConsole GetStdHandle STD OUTPUT HANDLE 3 设置控制台标题
  • TightVNC H264编解码(一)

    时光流逝 时间过的真快啊 疲于工作 发现近一个多月没写文章了 此文算是对最近的工作做个总结吧 经过尽二个月的不断摸索 TightVNC终于支持H264编解码了 前期真正编写H264编解码器只花了一周左右时间 但是测试发现效果并不是太理想 帧
  • VC++ HBITMAP保存文件

    请先看下面这段代码 BOOL SaveBmp HBITMAP bmp string path FILE f fopen path c str wb if f return 0 BITMAP bmpinfo GetObject bmp siz
  • VC++ 获取文件版本号

    源码实现 pragma comment lib Version lib typedef struct VS VERSIONINFO WORD wLength WORD wValueLength WORD wType WCHAR szKey
  • WTL 界面设计篇(CSkinDialog)

    头文件声明 CSkinDialog h pragma once include
  • OpenGL GLFW入门篇 - 画矩形

    效果图 主体代码 void DrawRectangle void GLfloat xl yt xr yb w h glPushMatrix glLoadIdentity glTranslatef 0 0 0 0 0 f w 1 2 h 1
  • C++ 可扩展的内存缓冲区

    类声明 CMemBuffer h pragma once class CMemBuffer public CMemBuffer DWORD dwSize 0 CMemBuffer void 申请内存 BOOL Realloc DWORD d
  • GDI+ 显示GIF图像

    头文件定义 pragma once include
  • VC++ UI布局管理器

    程序从codeproject上下载的 功能类似QT的QLayout 有了它界面缩放再也不会乱套了 具体使用方法可参考源码示例 资源下载链接地址 https download csdn net download u012156872 1926
  • VC++ CSWDirectoryListCtrl磁盘文件列表

    效果图 头文件定义 CSWDirectoryListCtrl h pragma once include afxwin h include
  • Node.js EventEmitter事件

    Node js EventEmitter Node js 所有的异步 I O 操作在完成时都会发送一个事件到事件队列 Node js 里面的许多对象都会分发事件 一个 net Server 对象会在每次有新连接时触发一个事件 一个 fs r
  • VCPKG 包下载失败解决思路

    vcpkg经常会遇到资源无法访问 可能是域名解析出了问题 我们只需要将域名解析后的ip地址添加到hosts文件列表中可解决此问题 如 185 199 108 133 raw githubusercontent com 在此之前可先通过终端p
  • live555 流媒体开源库

    live555对每一个从事过流媒体开发的从业者而言 都不曾陌生 就像每一个从事音视频行业的从业者而言 ffmpeg也不曾陌生 随着行业需求的发展 live555也是越见强大 因前几天帮朋友项目查找问题 重拾live555 没想到时隔10年
  • CStdioFile扩展(支持Ansi、Unicode、Utf-8等文本格式)

    头文件声明 CStdioFileEx h StdioFileEx h interface for the CStdioFileEx class Version 1 1 23 August 2003 Incorporated fixes fr
  • VC++ 源码实现通达信公式管理器2

    前面我们介绍了如何加载显示公式列表 本篇章介绍如何格式化显示公式内容 常用的CEdit或CRichEdit是不支持这种格式显示的 这里需要借助第三方控件SciLexer 没错 Notepad 就是使用的这个控件 它支持不同的文本内容支持不同
  • MetaEditor 编译原理之MQ4文件语法解析

    语法解析 顾名思义就是将一个文件或者一段代码 按照语法结构拆分为一个一个的单词 比如 extern int TakeProfit 50 int start int i 0 while i lt TakeProfit i return i 正
  • C++ StrCmpLogicalW文件名排序

    打开资源管理器 文件列表如下 搜索文件列表 include

随机推荐

  • 移动端H5页面在微信浏览器内audio无法自动播放问题解决

    相信许多小伙伴都遇见过这话种情况 在微信浏览器内添加的audio 无法自动播放 之前写过好多那种活动页添加的背景音乐都可以自动播放 直到后来ios 增加了限制就出现了这个问题 怎么解决的只需给audio标签增加一个属性就可以解决如下图
  • 二、MySQL入门

    1 如何查看MySQL是否运行 1查看进程 root sc mysql ps awx grep mysqld 12953 pts 1 S 0 00 bin sh usr local mysql bin mysqld safe datadir
  • JVM运行原理及Stack和Heap的实现过程

    Java语言写的源程序通过Java编译器 编译成与平台无关的 字节码程序 class文件 也就是0 1二进制程序 然后在OS之上的Java解释器中解释执行 而JVM是java的核心和基础 在java编译器和os平台之间的虚拟处理器 注 本网
  • js wangEditor富文本编辑器

  • 收藏清单:Java测试相关资源汇总

    收藏清单 Java测试相关资源汇总 Virtual environments 虚拟化环境 Vagrant 配置简单可信赖的虚拟化环境管理工具 Docker docker就不用多说了 Performance stress load 性能测试
  • 36-Jenkins-Job迁移

    Job迁移 前言 1 安装插件 2 配置信息 3 使用插件 前言 本篇来学习Jenkins中如何快速迁移job 在工作中可能会遇到这样的场景 即需要把一个Jenkins上的job迁移到另外一台Jenkins上 那怎么做比较好呢 一起来学习下
  • Shader Graph2-PBR介绍之表面属性(图解)

    PBR的实现由光线和表面属性决定 下面我们介绍一下表面属性 这个5个属性在ShaderGraph的根节点是经常的看到 左侧是Unity中的 右侧是UE中的 在没有Metallic金属的情况下 基础颜色值就决定了颜色的漫反射值 也就是说基础颜
  • gitee在README.md中添加图片

    前言 在使用gitee的添加README md文件的时候 有时候会希望能放一些效果图来实现展示效果 实现步骤 1 在项目中添加你的效果图片 比如我的就放在 assets 1 png 然后提交上去 2 打开你的项目 找到刚到图片 然后点击 3
  • Elasticsearch学习系列一(部署和配置IK分词器)

    优质资源分享 学习路线指引 点击解锁 知识定位 人群定位 Python实战微信订餐小程序 进阶级 本课程是python flask 微信小程序的完美结合 从项目搭建到腾讯云部署上线 打造一个全栈订餐系统 Python量化交易实战 入门级 手
  • 基于深度学习的图像分类任务实现(二)卷积神经网络分类器&基于Residual Bolck的卷积神经网络分类器

    文章目录 1 代码编写思路 2 卷积神经网络分类器 2 1基本原理 2 2 代码实现 2 3 运行结果 3 基于Residual Bolck的卷积神经网络分类器 3 1基本原理 3 2代码实现 3 3模型结构可视化 3 4运行结果 实现多种
  • 【python实战】爬一爬某二手车的买卖数据

    获取当前页面下的车型的 表显里程 等数据 结果如下 直接讲代码实现 代码实现基本分四步 1 发送请求 2 获取数据 3 解析数据 4 保存数据 1 发送请求 import requests url https www XXX com chi
  • redis-dump 安装与简单使用

    redis dump是将redis和json互转的工具 redis dump是基于ruby开发 需要ruby环境 而且新版本的redis dump要求2 2 2以上的ruby版本 centos中yum只能安装2 0版本的ruby 需要先安装
  • Linux命令大全(手册)

    http man linuxde net
  • 超全面的前端工程化配置指南

    前端工程化配置指南 本文讲解如何构建一个工程化的前端库 并结合 Github Actions 自动发布到 Github 和 NPM 的整个详细流程 示例 我们经常看到像 Vue React 这些流行的开源项目有很多配置文件 他们是干什么用的
  • hive相关汇总

    hive 1 hive 有哪些方式保存元数据 各有哪些特点 2 hive内部表和外部表的区别 3 生产环境中为什么建议使用外部表 什么时候使用内部表 什么时候使用外部表 4 你们数据库怎么导入hive 的 有没有出现问题 5 简述Hive中
  • vue项目如何播放m3u8格式视频

    vue项目如何播放m3u8格式视频 安装依赖 找到public index html 再要播放的地方 1 引入 2 注册 3 使用组件 4 样式自己调整 5 双击可全屏 结果 安装依赖 npm install easydarwin easy
  • Qt 信号与槽自动关联

    被动关联与自动关联区别 被动关联 也就是我们经常使用的connect函数 显示的指定SIGNAL和SLOT 自动关联 隐式指明信号与槽的关系 主要利用部件设置的Objectname与信号signal名字关联 自动关联说明 规则要求1 自动关
  • matlab绘制三维图形

    matlab绘制三维图形 三维曲线 plot3函数与plot函数用法十分相似 其调用格式为 plot3 x1 y1 z1 选项1 x2 y2 z2 选项2 xn yn zn 选项n 其中每一组x y z组成一组曲线的坐标参数 选项的定义和p
  • Spring Boot + Vue的网上商城之商品订单售后退款退货实现

    Spring Boot Vue的网上商城之商品订单售后退款退货实现 思路 在网上商城中 商品订单售后退款退货是一个必不可少的功能 当用户购买的商品有质量问题或者不满意时 可以申请售后服务 包括退款 退货等操作 在这篇博客中 我们将介绍如何使
  • sapi 实现语音朗读

    头文件定义 CSpeechSpeekImpl h pragma once include sphelper h class CSpeechSpeekImpl public CSpeechSpeekImpl void CSpeechSpeek