C#使用DirectX.DirectSound播放语音
作者:程序猿evint 发布时间:2022-08-28 01:22:33
标签:C#,DirectX.DirectSound,播放语音
最近在做项目时,需要进行音频文件的即时播放,并且要求同时播放多条语音,之前C#程序中语音播放一直使用System.Media类库的SoundPlayer类进行播放,但是这个播放类有个弊端,就是在播放时不能抢占式播放语音,经过查找资料DirectX.DirectSound可同时播放多条语音。
DirectX.DirectSound的特点
1、可同时播放多条语音
2、可分左右声道进行播放
3、可随时释放正在播放的语音
此组件处理流程:
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、定义
/// <summary>
/// 播放设备
/// </summary>
private Device secDev = new Device();
/// <summary>
/// 播放缓冲区
/// </summary>
private SecondaryBuffer secBuffer = null;
/// <summary>
/// 可视化组件
/// </summary>
private Control control;
/// <summary>
/// 是否被创建
/// </summary>
private bool IsCreate = false;
来源:https://blog.csdn.net/evint888/article/details/122387024
0
投稿
猜你喜欢
- 本文实例讲述了java实现mp3合并的方法。分享给大家供大家参考。具体实现方法如下:package test;import java.io.
- 本文实例为大家分享了Java实现考试系统的具体代码,供大家参考,具体内容如下说明这里的考试系统是指由学生,老师以及考试机构成的,学生通过用户
- 本文实例讲述了C#数据结构之堆栈(Stack)。分享给大家供大家参考,具体如下:堆栈(Stack)最明显的特征就是“先进后出”,本质上讲堆栈
- 目录注解是什么?元注解是什么?标准的元注解:@Target元注解:@Retention元注解:@Documented元注解:@Inherit
- 一般情况下是不可以用static修饰类的。如果一定要用static修饰类的话,通常static修饰的是匿名内部类。在一个类中创建另外一个类,
- 前言本文主要介绍了关于java静默加载Class的相关内容,之所以有这篇文章,是因为有时候在开发的时候,我们有这样的场景,我们只想得到一个C
- 文件目录结构文件目录结构很重要,特别注意的是rule文件要放在主启动类上一级位置,才能够扫描。写pom<dependencies>
- 单链表:每个数据是以节点的形式存在的每个节点分为数据域和指针域数据域中保存该节点的数据指针域中保存指向下一个节点的指针实现思路:节点类Sin
- ELK是三款软件的简称,分别是Elasticsearch、Logstash、Kibana组成,在发展的过程中,又有新成员Beats的加入,所
- 死锁在多线程的情况下,会出现数据不同步情况, 而为了避免这种情况,之前也说了:界区实现方法有两种,一种是用synchronized,一种是用
- 文件写入为提供相对较高性能的文件读写操作,这里果断选择了 NIO 对文件的操作,因为业务背景需要数据的安全落盘。这里主要采用 ByteBuf
- 一、月份英文简写DateTime dt = DateTime.Now;string MM = dt.AddMonths(-1).ToStri
- 使用YZMHelper帮助类即可using System;using System.Web;using System.Drawing;usi
- 描述符描述符是你添加到那些定义中来改变他们的意思的关键词。Java 语言有很多描述符,包括以下这些:可访问描述符不可访问描述符应用描述符,你
- 从接收输入值说起在日常的开发应用中,有时候需要直接接收外部设备如键盘等的输入值,而对于这种数据的接收方式,我们一般有三种方法:字节流读取,字
- package com.cjonline.foundation.evisa;import java.io.BufferedReader;im
- 首先给出代码和输出://import java.sql.DriverManager;//import java.sql.SQLExcepti
- 日常对于金额计算,应该都是用的BigDecimal,可是苦于没有好的工具类方法,现在贡献一个我正在用的对于数字计算的工具类,项目中就是用的这
- 前言Spring框架对Bean进行装配提供了很灵活的方式,下面归纳一下主要的方式:在XML中进行显示配置在Java中进行显示配置隐式的bea
- 今天是开篇,得要吹一下算法,算法就好比程序开发中的利剑,所到之处,刀起头落。 针对现实中的排序问题,算法有七把利剑可以助你马道成功