C#使用SAPI开发异步TTS DLL 跨语言调用时如何检测语音播放状态
SAPI 异步 TTS DLL 播放控制与状态查询解决方案
你可以从以下几个方向落地实现:
1. DLL 内部维护全局静态实例,完全屏蔽上层传递逻辑
- 同进程内调用的场景下,直接将异步播放创建的
ISpVoice实例指针存储在 DLL 内部的全局静态变量中,不需要上层传递任何实例相关数据。后续查询状态、中止播放的接口直接读写这个全局实例即可。 - 并发调用场景下需要加读写锁,避免多线程同时操作实例引发内存异常。如果需要支持多路并行播放,可以维护全局的<整数ID-实例指针>映射表,播放接口返回给上层一个整数类型的实例ID,上层后续操作仅需传递这个ID即可,所有开发语言都支持整数类型传递,不存在跨语言兼容问题。
- 状态查询直接调用实例的
ISpVoice::GetStatus()方法即可获取当前播放状态,中止播放调用ISpVoice::Speak(NULL, SPF_PURGEBEFORESPEAK, 0)就能清空播放队列立即停止。
2. 绑定 SAPI 事件回调维护全局播放状态标记
- 给
ISpVoice实例注册SPFEI(SPEI_END_INPUT_STREAM)事件回调,播放正常结束、主动中止、播放出错都会触发该事件。你在DLL内部维护一个全局的isPlaying布尔变量,调用播放接口时设为true,事件触发时设为false即可。 - 上层仅需要调用你封装的
bool TTS_IsPlaying()接口获取这个布尔值就行,完全不需要感知内部实例的存在。
3. 封装纯C风格跨语言接口,隐藏所有内部实现
你可以仅对外暴露三个通用接口,不管上层是什么开发语言都能直接调用,不需要传递任何实例参数:
int TTS_Play(const wchar_t* text):传入待合成文本,内部创建/复用ISpVoice实例发起异步播放,返回码标识调用结果bool TTS_IsPlaying():返回当前是否有语音正在播放void TTS_Stop():立即中止当前所有播放任务,清空播放队列
4. 命名共享内存存储状态(适配多进程调用场景)
如果你的DLL会被多个进程调用,全局变量不共享的场景下,可以在DLL内部创建一块命名共享内存,用来存储当前的播放状态、实例映射信息,所有进程的查询、中止操作都读写这块共享内存即可。
内容的提问来源于stack exchange,提问作者Eric Blackburn
相关产品推荐
相关产品推荐

