C#使用DirectX.DirectSound播放语音
最近在做项目时,需要进行音频文件的即时播放,并且要求同时播放多条语音,之前C#程序中语音播放一直使用System.Media类库的SoundPlayer类进行播放,但是这个播放类有个弊端,就是在播放时不能抢占式播放语音,经过查找资料DirectX.DirectSound可同时播放多条语音。
DirectX.DirectSound的特点
1、可同时播放多条语音
2、可分左右声道进行播放
3、可随时释放正在播放的语音
【C#使用DirectX.DirectSound播放语音】此组件处理流程:
1、创建播放线程
public void StartDirectXSoundThread(Control _con) {IsStart = true; if (control == null) control = _con; Task task = new Task(() =>{while (true){try{if (!IsStart) break; if (!IsPlaying()){if (soundlist.Count > 0){if (!IsPlayVoice){IsPlayVoice = true; control.Invoke((MethodInvoker)delegate{SoundPlay(soundlist[0]); soundlist.RemoveAt(0); }); }}}}catch (Exception ex){LogHelper.Debug(ex); }finally{}Thread.Sleep(100); }}); task.Start(); }
2、释放播放线程
public void StopDirectXSoundThread(){IsStart = false; }
3、判断是否播放中,通过PlayPosition!=0和播放缓冲是否null的条件判断是否播放
private bool IsPlaying(){bool Ret = false; try{if (IsCreate){if (secBuffer != null){if (secBuffer.PlayPosition != 0){Ret = true; }}}}catch (Exception ex){LogHelper.Debug(ex); }return Ret; }
4、播放音频
public void SoundPlay(string _wavpath){try{if (_wavpath.IndexOf("\\") < 0){_wavpath = SoundPath + _wavpath; }if (_wavpath.IndexOf(".wav") < 0){_wavpath += ".wav"; }if (!File.Exists(_wavpath)){LogHelper.Info("无" + _wavpath + "文件!"); }else{secDev.SetCooperativeLevel(control, CooperativeLevel.Normal); BufferDescription buffdes = new BufferDescription(){GlobalFocus = true}; secBuffer = new SecondaryBuffer(_wavpath, buffdes, secDev); secBuffer.Play(0, BufferPlayFlags.Default); //设置缓冲区为默认播放 }IsCreate = true; IsPlayVoice = false; }catch (Exception ex){LogHelper.Debug(ex); }}
左右声道通过secBuffer.Pan属性进行控制,值含义见下图:
a、Center中心通道,左右通道同时播放,默认值0
b、Right右通道,值10000
c、Right左通道,值-10000
文章图片
5、清除播放中音频 ,播放中的音频可以通过Dispose()方法进行释放
public void ClearPlay(){if (secBuffer != null){soundlist.Clear(); secBuffer.Dispose(); IsCreate = false; }}
6、定义
/// /// 播放设备/// private Device secDev = new Device(); /// /// 播放缓冲区/// private SecondaryBuffer secBuffer = null; /// /// 可视化组件/// private Control control; /// /// 是否被创建/// private bool IsCreate = false;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
推荐阅读
- C#调用USB摄像头的方法
- 深度学习|基于传统神经网络,使用Keras训练自己的数据集
- Go|使用 grpcurl 通过命令行访问 gRPC 服务
- 到底为什么不建议使用SELECT|到底为什么不建议使用SELECT *()
- 【笔记】使用|【笔记】使用 PDB 符号文件导出 Windows 内核数据结构
- 【nodejs进阶之旅(2)】:使用koa2+mysql|【nodejs进阶之旅(2)】:使用koa2+mysql 实现列表数据分页
- 监控网页内容变化,语音播放更新内容
- 高性能Go语言日志模块dlog使用说明
- vue3中的watch和watchEffect差异和使用
- ASP.NET|ASP.NET Core中的Razor页面使用视图组件