DirectSound对于单声道的Wav文件(或者说对于单声道的PCM音频数据)提供了内置3D音效的模拟,你能够控制每一个声源和收听者的立体位置,对移动的物体应用多普勒效果等等。在单个应用程序中,可以有多个声源,但是只能有一个收听者。

1. 3D音效概念简介

  1. 3D坐标: 坐标采用左手笛卡尔坐标系,x轴向右延伸,y轴向上延伸,z轴向前延伸。
  2. 3D处理模式: DirectSound由三种3D环境处理模式:普通模式禁用模式头部相关模式。普通模式就是完整的3D模式,禁用模式不言而喻,头部相关模式是部分3D模式(因为该模式下所有的声源参数都是参考听者位置的,而不是参考原点)。
  3. 延迟生效: 因此每次应用3D配置,DirectSound都要进行大量的计算,可能会家中cpu的负担。因此,声源和听者都支持一种叫做延迟设置的方式,多个以延迟设置设置的参数需要调用提交函数才能应用到音频数据上,这样可以避免多次重复计算。

1.1 声源(Source)相关概念

  • 最小距离: 在最小距离范围内,听到的声源音量大小保持不变;在最小距离范围外,听到的音量开始成比例衰减(例如最小距离是10米,则听者站在距离声源20米处听到的声音是原始声音的1/2)。
  • 最大距离: 在最大距离外的听者,不管再怎么朝外移动,听到的音量都不会再减小。
  • 朝向: 朝向用来指定声源投射的方向,具体见下一点。
  • 音量投射角度: 3D环境下的音量有一个锥形的投射角度(当设置朝向时),分内角和外角:内角的声音是正常的音量,外角的音量通常是衰减的音量,在内角边界向外角边界过渡时音量逐级衰减。

  • 移动速度: 移动速度在整个3D环境里主要是用来计算多普勒效应(Doppler Effect)的。

1.2 听者(Listener)相关概念

  • 朝向: 听者的朝向角度由两个3维向量构成,实际上这个朝向是一个平面。两个三维向量都以听者头部中心为原点,一个向顶部延伸,一个向前延伸。

  • 距离因子: 距离因子(Distance Factor)表示三维空间中的单位,与成正比(例如距离因子为2,则一个三维点(1,0,0)表示现实中距离原点x轴2米)。
  • 多普勒因子: 表示产生的多普勒效应是真实效应的几倍。
  • 滚降因子: 表示音量随距离的衰减程度。0表示不衰减,1表示衰减成程度与现实环境相同,等等。

2. 3D示例程序

2.1 获取和设置声源最大最小距离

IDirectSound3DBuffer8::GetMaxDistance(D3DVALUE * pflMaxDistance);

IDirectSound3DBuffer8::GetMinDistance(D3DVALUE * pflMinDistance);

IDirectSound3DBuffer8::SetMaxDistance(D3DVALUE flMaxDistance, DWORD dwApply);

IDirectSound3DBuffer8::SetMinDistance(D3DVALUE flMinDistance, DWORD dwApply);

dwApply参数用来指定是立即生效还是延迟生效(需要调用CommitDeferredSettings函数)。

2.2 获取和设置声源音量投射角度

因为投射角度中外角肯定要比内角大,为了保证这一点我们需要做些额外的判断处理:

void MainWindow::on_coneAnglesInside_valueChanged(int value)
{
DWORD insideAngle, outsideAngle;
if (m_wavPlayer.get3DSource()->GetConeAngles(&insideAngle, &outsideAngle) != DS_OK)
throw std::exception("GetConeAngles error"); if (static_cast<unsigned>(value) > outsideAngle)
ui->coneAnglesOutside->setValue(value),
outsideAngle = value;
if (m_wavPlayer.get3DSource()->SetConeAngles(value, outsideAngle, DS3D_IMMEDIATE) != DS_OK)
throw std::exception("SetConeAngles error"); ui->coneAnglesInsideLabel->setText(QString("coneAnglesInside(%1)").arg(value));
}

2.3 获取和设置声源朝向

这里也有一个特殊情况要处理:朝向的3个维度不能都为0,否则就是一个无效的方向:

#define SET_ONE_VECTOR_WITH_ZERO_CHECK_OF_SOURCE(getFunc, setFunc, sliderName, valueX, valueY, valueZ)  \
D3DVECTOR vector; \
if (m_wavPlayer.get3DSource()->getFunc(&vector) != DS_OK) \
throw std::exception(#getFunc " error"); \
\
if (!(valueX == 0.0 && valueY == 0.0 && valueZ == 0.0)) \
if (m_wavPlayer.get3DSource()->setFunc(valueX, valueY, valueZ, DS3D_IMMEDIATE) != DS_OK) \
throw std::exception(#setFunc " error"); \
\
ui->sliderName##Label->setText(QString(#sliderName "(%1)").arg(value)); void MainWindow::on_coneOrientationX_valueChanged(int value)
{
SET_ONE_VECTOR_WITH_ZERO_CHECK_OF_SOURCE(GetConeOrientation, SetConeOrientation, coneOrientationX,
value, vector.y, vector.z);
}

其他相关设置这里就不给出代码了,都比较简单,有需要的可以看官方文档

3. 运行结果示意图

界面太大,我就分成3张图展示了:

完整代码见链接

DirectSound---3D环境的更多相关文章

  1. CSS3 3D环境实现立体 魔方效果代码

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 第1部分: 游戏引擎介绍, 渲染和构造3D世界

    原文作者:Jake Simpson译者: 向海Email:GameWorldChina@myway.com ---------------------------------------------- ...

  3. 三分钟学会用 js + css3 打造酷炫3D相册

    之前发过该文,后来不知怎么回事不见了,现在重新发一下. 中秋主题的3D旋转相册 如图,这是通过Javascript和css3来实现的.整个案例只有不到80行代码,我希望通过这个案例,让正处于迷茫期的j ...

  4. 3D banner(CSS3+HTML5)

    1.这是一篇 3Dbanner制作的简易流程,支持高版本的chrome和firefox浏览器,俩浏览器显示可能会有些差异 2.没有兼容性代码,因为仅仅只是熟悉流程,希望小伙伴们自己改善哈(>﹏& ...

  5. Material Design 概念,环境和基本属性

    Material Design 概念,环境和基本属性 Material Design是随Android 5.0推出的一种设计概念, 涉及到了跨平台和设备的视觉,动态,交互设计等方面.   设计概念 M ...

  6. 【Unity3d游戏开发】Unity3D中的3D数学基础---向量

    向量是2D.3D数学研究的标准工具,在3D游戏中向量是基础.因此掌握好向量的一些基本概念以及属性和常用运算方法就显得尤为重要.在本篇博客中,马三就来和大家一起回顾和学习一下Unity3D中那些常用的3 ...

  7. 3D建模与处理软件简介

    [前言]自半年前笔者发表博客“什么是计算机图形学”以来,时常有人来向笔者询问3D模型的构建方法与工具.笔者的研究方向是以3D技术为主,具体包括3D建模,3D处理及3D打印三个方面,在3D建模与处理方面 ...

  8. CSS 3 3D转换

    绘制3D环境 父元素设置了 preserve-3d  子元素就可以以父元素作为平面进行3d转换 transform-style: preserve-3d; 设置视点 :表示透视效果  值越小 透视效果 ...

  9. JAVA智能设备基于OpenGL的3D开发技术 之AABB碰撞检测算法论述

    摘要:无论是PC机的3D还是智能设备应用上,碰撞检测始终是程序开发的难点,甚至可以用碰撞检测作为衡量3D引擎是否完善的标准.现有许多3D碰撞检测算法,其中AABB碰撞检测是一种卓有成效而又经典的检测算 ...

随机推荐

  1. rsync实现数据增量备份

    环境说明: 主机ip:192.168.0.201 需备份的目录:/opt/mail 备份机器ip:192.168.0.215 1.编辑/etc/rsyncd.conf文件(etc目录不存在的话,需要手 ...

  2. 2018/1/15 JAVA多线程相关

    本文不说synchronized相关,它就是JAVA的一个保留关键字,jdk自己实现了它,但说真的,可应用场景真的少,相比lock接口,它还是被淘汰好吧; 首先,说说lock接口,lock接口是一个工 ...

  3. codeM美团编程大赛初赛B轮E题

    题目描述 给出一个正整数n,我们把1..n在k进制下的表示连起来记为s(n,k),例如s(16,16)=123456789ABCDEF10, s(5,2)=11011100101.现在对于给定的n和字 ...

  4. Swift百万线程攻破单例(Singleton)模式

    一.不安全的单例实现 在上一篇文章我们给出了单例的设计模式,直接给出了线程安全的实现方法.单例的实现有多种方法,如下面: class SwiftSingleton { class var shared ...

  5. mybatis3:Invalid bound statement (not found)

    最近在玩ssm框架搭建,突然发现最后的时候mybaits和SpringMvc进行整合的时候出现错误 Invalid bound statement (not found) 这个错误有可能出现在以下几个 ...

  6. ACdream 1068

    我没有用二分法,直接构造最小数,既然题目保证答案一定存在那么与上界无关. 如给定S=16,它能构成的最小数为79,尽量用9补位,最高位为S%9.如果构造的数大于下界A,那么直接输出,因为这是S能构成的 ...

  7. 《清华梦的粉碎》by王垠

     清华梦的诞生 小时候,妈妈给我一个梦.她指着一个大哥哥的照片对我说,这是爸爸的学生,他考上了清华大学,他是我们中学的骄傲.长大后,你也要进入清华大学读书,为我们家争光.我不知道清华是什么样子,但是我 ...

  8. CodeForces-748B

    关键在于判断是否能够得到解决办法,我的思路就是用一个数组来记录每个小写字母对应的按键,如果它出现对应两个级以上不同的按键那么就说明不能得出解决办法,直接打印'-1'.如果能够得出解决办法,就扫描一下数 ...

  9. ActiveMq笔记2-消息持久化

    为了避免意外宕机以后丢失信息,需要做到重启后可以恢复消息队列,消息系统一般都会采用持久化机制. ActiveMQ的消息持久化机制有JDBC,AMQ,KahaDB和LevelDB, 无论使用哪种持久化方 ...

  10. 网络基础tcp/ip协议二

    物理层解析: 物理层是TCP/IP模型的最低层,物理层为数据提供数据传输可靠通路. 物理层关心的介质: 信号 接口 传输介质 信号的分类:(信号是信息传递的媒介.) 模拟信号:连续变化的物理量 数字信 ...