ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第九章 DirectX 输入和声音(下)

2021-10-24 16:32:37  阅读:241  来源: 互联网

标签:声音 播放 XAudio2 第九章 音频 buffer DirectX NULL 输入


声音的播放在Windows API就有这样的支持函数。PlaySound是Windows用于播放音乐的API函数。在vs2010以上版本需要加入#pragma comment(lib, "winmm.lib")才能使用PlaySound。PlaySound函数原型为 BOOL PlaySound(LPCSTR pszSound, HMODULE hmod,DWORD fdwSound)。参数pszSound是指定了要播放声音的字符串,该参数可以是WAVE文件。参数hmod是应用程序的实例句柄,设置为NULL即可。参数fdwSound是预定义值的组合。

WAVE文件格式是一种由微软和IBM联合开发的用于音频数字存储的标准,它采用RIFF文件格式结构。WAVE文件作为最经典的Windows多媒体音频格式,应用非常广泛,它使用三个参数来表示声音:采样位数、采样频率和声道数。WAVE对音频流的编码没有硬性规定,通常采用的音频编码方式是脉冲编码调制(PCM)。PCM音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准的数字音频数据。目前在线播放、播放器播放以及下载音频格式中最常见的就是MP3。MP3是一种音频压缩技术,其全称是动态影像专家压缩标准音频层面3,简称为MP3。WAVE是录音时用的标准的WINDOWS文件格式,文件的扩展名为“WAV”,数据本身的格式为PCM或压缩型,属于无损音乐格式的一种。所以WAV文件相对于MP3文件比较大。MP3被设计用来大幅度地降低音频数据量,将音乐以1:10 甚至 1:12 的压缩率,压缩成容量较小的文件。MP3是一种有损音乐格式,而WAV则是一种无损音乐格式。MP3一般是用于我们普通用户听歌,而WAV文件通常用于录音室录音和专业音频项目。

在早期的DirectX中对音频操作的API有两个DirectMusic和DirectSound。可自从DirectX 9.0c之后,DXMusic和DirectSound就被XAudio2给取代了。使用XAudio2的基本流程如下:

1. 初始化 XAudio2 引擎

2. 加载wave文件

3. 通过CreateSourceVoice 方法来创建源语音

4. 使用 SubmitSourceBuffer函数将 XAUDIO2 _ 缓冲区提交到源语音

5. 使用 start 函数启动源语音。

我们使用VS2019新建项目“D3D_09_Sound”,首先我们要创建 “DXUT.h”,“ SDKwavefile.h”和“SDKwavefile.cpp”。其中“DXUT.h”内如如下:

#pragma once

#ifndef SAFE_DELETE
#define SAFE_DELETE(p)       { if (p) { delete (p);     (p)=NULL; } }
#endif    

#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p);   (p)=NULL; } }
#endif  

#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p)      { if (p) { (p)->Release(); (p)=NULL; } }
#endif

它定义了三个宏,主要用来释放对象的。然后就是SDKwavefile文件,这个文件来源于DirectX安装目录下Samples\C++\DXUT\Optional下面,主要就是对WAVE音频文件的封装。有了这个文件,我们播放声音就非常的方便了。接下来,我们开始介绍main.cpp文件内容。使用XAudio2来播放声音,需要先引入xaudio2.h头文件。其实XAudio2的使用和DirectX没有直接关系,但是为了我们的整体代码的设计,我们就将播放声音的代码统一放置到initScene函数中,代码如下:

// 初始化 XAudio2
CoInitializeEx(NULL, COINIT_MULTITHREADED);

// 创建 XAudio2 对象
IXAudio2* pXAudio2 = NULL;
XAudio2Create(&pXAudio2, 0);

// 创建一个主声音
IXAudio2MasteringVoice* pMasteringVoice = NULL;
pXAudio2->CreateMasteringVoice(&pMasteringVoice);

// 读取wave文件
CWaveFile wav;
wav.Open((LPWSTR)L"MusicSurround.wav", NULL, WAVEFILE_READ);

// 获取文件格式
WAVEFORMATEX* pwfx = wav.GetFormat();

// 声音数据字节大小
DWORD cbWaveSize = wav.GetSize();

// 声音数据字节数组
BYTE* pbWaveData = new BYTE[cbWaveSize];
wav.Read(pbWaveData, cbWaveSize, &cbWaveSize);

// 创建一个源声音
IXAudio2SourceVoice* pSourceVoice;
pXAudio2->CreateSourceVoice(&pSourceVoice, pwfx);

// 填充 WAVEFORMATEXTENSIBLE 结构
XAUDIO2_BUFFER buffer = { 0 };
buffer.Flags = XAUDIO2_END_OF_STREAM;// 可以设为0或XAUDIO2_END_OF_STREAM,当设为后者时,将使XAudio2播放完该数据块后自动停止,不再播放下一个数据块
buffer.AudioBytes = cbWaveSize;	// 音频数据的长度,按字节算
buffer.pAudioData = pbWaveData;	// 具体音频数据的地址,unsigned char pBuffer[]
buffer.PlayBegin = 0;			// 起始播放地址
buffer.PlayLength = 0;			// 播放长度,0为整数据块
buffer.LoopBegin = 0;			// 循环起始位置
buffer.LoopLength = 0;			// 循环长度,按字节算
buffer.LoopCount = 0;			// 循环次数,0为不循环,255为无限循环
buffer.pContext = NULL;			// 这里的pContext用来标识该数据块,供回调用,可以是NULL

// 提交 XAUDIO2_BUFFER 
pSourceVoice->SubmitSourceBuffer(&buffer);

// 播放声音
pSourceVoice->Start(0, XAUDIO2_COMMIT_NOW);

// Cleanup XAudio2
//SAFE_DELETE_ARRAY(pbWaveData);
//pSourceVoice->DestroyVoice();
//pMasteringVoice->DestroyVoice();
//pXAudio2->Release();
//pXAudio2 = NULL;
//CoUninitialize();

XAudio2共有三种声音,源音,混音和主音,XAudio2通过他们来操作和播放音频数据。源声音代表音频原始数据,它需要把数据传递给其他声音(混音或主音)。混音是对声音的进步一处理,它需要把数据传递给其他声音(混音或主音)。主音主要是音频数据发送给硬件。声音数据从源声音开始,可以选择经过一个或多个混音,最后发送到主音,由主音将因音频数据发送给硬件。使用XAudio2设置合适的声音锥可以模拟3D立体声。3D立体声和2D声不同的地方是它是会随着距离衰减的,距离越近声音越大,距离越远声音越小。在游戏中,通常我们需要控制整个游戏的背景音乐,同时单独控制一些特效(攻击、爆炸之类)音乐。所谓混音就是将多路音频混合成一路进行输出。

本课程的所有代码案例下载地址:

workspace.zip

备注:这是我们游戏开发系列教程的第二个课程,这个课程主要使用C++语言和DirectX来讲解游戏开发中的一些基础理论知识。学习目标主要依理解理论知识为主,附带的C++代码能够看懂且运行成功即可,不要求我们使用DirectX来开发游戏。课程中如果有一些错误的地方,请大家留言指正,感激不尽!

标签:声音,播放,XAudio2,第九章,音频,buffer,DirectX,NULL,输入
来源: https://blog.csdn.net/konkon2012/article/details/120935770

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有