DirectSound应用
只是使用的假设PlaySound()这个API函数来显示的声音效果,然后,然后,它不会出现在混合声音,因为PlaySound还有播放期间声音,这将不可避免地导致现有声音停止。
因此,使用
PlaySound()包括丰富音乐与音效的游戏世界是不现实的。
而DirectSound就能够完美的解决混音问题,并且它直接针对硬件编程。最大程度上减小了游戏进程逻辑对于声音播放效果的影响。
在这篇文章里,先谈谈DirectSound的使用。
初始化工作第一步,也是全部DirectX组建初始化的必做工作,总的来说分为三个步骤:1、设置好库连接的支持。2、加入须要的头文件。
3、也是大家最easy遗忘的一步,将
设置文件夹中与DirectX SDK相关的库与头文件的连接保持在最顶端。
以下针对DirectSound来具体讲讲上面三个步骤,1.加入库连接,能够有两种方法,你能够在project菜单条中选择设置选项,并在连接这一项的对象与库模块这一栏目中写上
Dsound.lib Dxguid.lib两个字符串。你也能够仅仅在工作区用加入文件的方法把这两项放在里面。2.加入<dsound.h>头文件放在代码段的顶端。这个无须赘言。3.假设此时发现有些
Directsound的类名无法识别,那么请检查工具菜单项的设置选项中文件夹的设置,看是否在lib与include中都将DirectX SDK相关内容都放在第一位,由于在编译连接中第一位的库
是作为连接的首选的。
另外还应加入Winmm.lib以及mmsystem.h,mmreg.h头文件,由于载入WAVE文件时会用到。
初始化工作第二步,DirectSound对象的建立
(1)建立DirectSound对象
(2)设定共享层级
(3)设定主缓冲区的格式
首先要建立一个代表声卡的DirectSound对象,我们先定义LPDIRECTSOUND pDS,然后用DirectSoundCreate(NULL, &pDS, NULL);方法来建立它,假设你想察看这个对象是否成功
的建立,能够定义一个HRESULT result变量。由它接受DirectSoundCreate方法的返回值得并推断是否等于DS_OK,假设不等于它,则能够用MessageBox()方式弹出对话框来告诉程
序员建立失败。注意DirectSoundCreate()中的第一个參数。是NULL。表示使用眼下预设的声卡。也能够调用DirectSoundEnumerate取得可用的声卡。
然后要设定程序协调层级,使用pDS调用SetCooperativeLevel方法来实现,注意这种方法有两个參数,第一个參数代表应用程序的主窗体,而第二个參数则设定使用资源的优
先权。
最后要看看缓冲区的概念。主缓冲区能够看作一个DirectSound是用来播放声音,产生混音效果的区域。它能够自己主动生成。也能够自己建立,但假设自己建立并设定其播放模式
,在设置协调层级时,标志位必须设定为DSSCL_PRIORITY.次缓冲区则存储播放声音的文件。在载入声音文件后,仅仅要调用Play()方法,声音就会自己主动的送入主缓冲区中并进行播放
。
在初始化过程中。应重点注意DSBUFFERDESC结构,它担负着区分主次缓冲区以及缓冲区明细初始化的重任,在使用它时,首先要清空,能够使用memset()方法来将其全部内存中
的位设为0。同一时候要设置结构的大小,并确定它的标志位,以及设置缓冲区大小与格式,其详细的初始化过程能够看文章结尾的样例。
在完毕了初始化工作后。应该先把须要播放的声音文件加载到已经完毕初始化的次缓冲区中。这里重点讲下怎样读入一个声音文件以及取得当中的信息与播放的资料。
首先我们要知道,WAVE是利用区块(chunk)方式存储文件的,包括纪录文件格式的fmt区块与文件实际内容的data区块。因此读取文件必需要完毕下面步骤:
(1)打开文件
(2)确认是否为RIFF文件。类型为WAVE
(3)寻找fmt区块,取得文件格式
(4)寻找data区块。取得文件内容
(5)关闭文件
(6)载入声音入次缓冲区
详细过程见样例。
最后当然是播放与停止的使用了,详细能够自己去用次缓冲区指针试一下。
/*--------------------------------------------------------------------------------*/
// 以下是我写的一个使用DirectSound的样例:
////////////////////////////下面为头文件部分
#ifndef GAMESOUND
#define GAMESOUND
#include "dsound.h"
#include "windows.h"
#include "mmsystem.h"
#include "mmreg.h"
class GameSound
{
private:
HWND soundhwnd;
HRESULT result; //用来接受建立后的返回值
LPDIRECTSOUND pDS; //代表声卡的DirectSound对象
LPDIRECTSOUNDBUFFER pMainBuf; //声明主缓冲区指针
DSBUFFERDESC desc; //声明描写叙述结构。用来初始化缓冲区域
WAVEFORMATEX pwfmt; //声明声音结构,用来设定播放格式
WAVEFORMATEX swfmt; //声明声音结构
MMCKINFO ckRiff; //RIFF区块的信息
MMCKINFO ckInfo; //子区块的信息
MMRESULT mmresult; //返回的结果
DWORD size; //实际资料的大小
HMMIO hbackground; //打开的多媒体文件
public:
GameSound();
void GameSoundInit(HWND); //GameSound对象的建立
void GameSoundbufferConstruct(); //缓冲区的创建
void GameSoundfmtSet(int ,int ,int); //通过主缓冲区指针来设置播放格式
void GameSoundReadWAVfile(char*, HMMIO&);//将声音文件读入并将明细存在HMMIO结构中
void GameSoundReadinbuffer(LPDIRECTSOUNDBUFFER&, char*);//将声音文件读入次缓冲区中
LPDIRECTSOUNDBUFFER pStartmusic; //声明子缓冲区指针(開始音乐指针)
LPDIRECTSOUNDBUFFER pTalkmusic; //声明子缓冲区指针(谈天音乐指针)
LPDIRECTSOUNDBUFFER pWalkmusic; //声明子缓冲区指针(行走音乐指针)
LPDIRECTSOUNDBUFFER pWarmusic; //声明子缓冲区指针(战斗音乐指针)
LPDIRECTSOUNDBUFFER pyudimusic; //声明子缓冲区指针(攻击声音指针)
LPDIRECTSOUNDBUFFER pwinmusic; //声明子缓冲区指针(胜利音乐指针)
LPDIRECTSOUNDBUFFER plosemusic; //声明子缓冲区指针(失败声音指针)
LPDIRECTSOUNDBUFFER pAttacksound; //声明子缓冲区指针(攻击声音指针)
LPDIRECTSOUNDBUFFER pAIAttacksound; //声明子缓冲区指针(攻击声音指针)
void GameSoundAllstop(); //for背景音乐。让背景音乐更换时,先前的全部音乐都停止,从而播放新的音乐
void GameMusicplay(LPDIRECTSOUNDBUFFER&); //用来播放循环音乐
void GameSoundplay(LPDIRECTSOUNDBUFFER&); //用来播放一次性音效
};
#endif
////////////////////////////下面为源文件部分
#include "GameSound.h"
GameSound::GameSound()
{
}
void GameSound::GameSoundInit(HWND hwnd)
{
this->pDS;
this->soundhwnd = hwnd;
this->result = DirectSoundCreate(NULL, &pDS, NULL);
if(this->result != DS_OK)
MessageBox(hwnd, "建立 DirectSound 对象失败!", NULL,MB_OK);
this->result = this->pDS->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);
if(this->result != DS_OK)
MessageBox(hwnd, "设定程序协调层级失败!", NULL,MB_OK);
this->GameSoundbufferConstruct();
}
void GameSound::GameSoundbufferConstruct()
{
memset(&this->desc, 0, sizeof(desc)); //清空结构内容
desc.dwSize = sizeof(desc); //配制描写叙述结构大小
desc.dwFlags = DSBCAPS_PRIMARYBUFFER; //???
desc.dwBufferBytes = 0;
desc.lpwfxFormat = NULL;
result = pDS->CreateSoundBuffer(&desc, &this->pMainBuf, NULL);
if(this->result != DS_OK)
MessageBox(this->soundhwnd, "建立主缓冲区域失败!", NULL,MB_OK);
this->GameSoundReadinbuffer(this->pTalkmusic, "sound//talk2.wav");
this->GameSoundReadinbuffer(this->pStartmusic, "sound//startwav.wav");
this->GameSoundReadinbuffer(this->pWarmusic, "sound//zhandou.wav");
this->GameSoundReadinbuffer(this->pWalkmusic, "sound//mainwav.wav");
this->GameSoundReadinbuffer(this->pAttacksound, "sound//fire.wav");
this->GameSoundReadinbuffer(this->pAIAttacksound, "sound//fire2.wav");
this->GameSoundReadinbuffer(this->pyudimusic, "sound//yudi.wav");
this->GameSoundReadinbuffer(this->pwinmusic, "sound//win.wav");
this->GameSoundReadinbuffer(this->plosemusic, "sound//lose.wav");
}
void GameSound::GameSoundfmtSet(int channels, int SamplesPerSec, int wBitPerSample)
{
memset(&this->pwfmt, 0, sizeof(pwfmt));
this->pwfmt.wFormatTag = WAVE_FORMAT_PCM;
this->pwfmt.nChannels = channels;
this->pwfmt.nSamplesPerSec = SamplesPerSec;
this->pwfmt.wBitsPerSample = wBitPerSample;
this->pwfmt.nBlockAlign = this->pwfmt.wBitsPerSample / 8 * this->pwfmt.nChannels;
this->pwfmt.nAvgBytesPerSec = this->pwfmt.nSamplesPerSec * this->pwfmt.nBlockAlign;
this->result = this->pMainBuf->SetFormat(&this->pwfmt);
if(this->result != DS_OK)
MessageBox(this->soundhwnd, "设定播放格式失败!
", NULL,MB_OK);
}
void GameSound::GameSoundReadWAVfile(char* filename, HMMIO &hmmbackground)
{
hmmbackground = mmioOpen(filename, NULL, MMIO_ALLOCBUF | MMIO_READ); //打开文件
if(hmmbackground == NULL)
MessageBox(this->soundhwnd, "文件不存在!", NULL,MB_OK);
//搜索类型
ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E');//设定文件类型
mmresult = mmioDescend(hmmbackground, &ckRiff, NULL, MMIO_FINDRIFF);
if(mmresult != MMSYSERR_NOERROR)
MessageBox(this->soundhwnd, "文件格式错误!
", NULL,MB_OK);
//搜索区块
ckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');//设定区块类型
mmresult = mmioDescend(hmmbackground, &ckInfo, &ckRiff, MMIO_FINDCHUNK);
if(mmresult != MMSYSERR_NOERROR)
MessageBox(this->soundhwnd, "文件格式错误!", NULL,MB_OK);
if(mmioRead(hmmbackground, (HPSTR)&swfmt, sizeof(swfmt)) == -1)
MessageBox(this->soundhwnd, "读取格式失败!
", NULL,MB_OK);
mmresult = mmioAscend(hmmbackground, &ckInfo, 0); //跳出子区块
//搜索区块
ckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
mmresult = mmioDescend(hmmbackground, &ckInfo, &ckRiff, MMIO_FINDCHUNK);
if(mmresult != MMSYSERR_NOERROR)
MessageBox(this->soundhwnd, "文件格式错误!", NULL,MB_OK);
size = ckInfo.cksize;
}
void GameSound::GameSoundReadinbuffer(LPDIRECTSOUNDBUFFER& buffer, char* filename)
{
LPVOID pAudio;
DWORD bytesAudio;
this->GameSoundReadWAVfile(filename, this->hbackground);
memset(&this->desc, 0, sizeof(desc)); //清空结构内容
desc.dwSize = sizeof(desc); //配制描写叙述结构大小
desc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLPAN |
DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS; //?
??
desc.dwBufferBytes = this->size;
desc.lpwfxFormat = &this->swfmt;
result = pDS->CreateSoundBuffer(&desc, &buffer, NULL);
if(this->result != DS_OK)
MessageBox(this->soundhwnd, "建立次缓冲区域失败!
", NULL,MB_OK);
result = buffer->Lock(0, this->size, &pAudio, &bytesAudio, NULL, NULL, NULL);
if(this->result != DS_OK)
MessageBox(this->soundhwnd, "锁定缓冲区失败!", NULL,MB_OK);
this->mmresult = mmioRead(this->hbackground, (HPSTR)pAudio, bytesAudio);
if(mmresult == -1)
MessageBox(this->soundhwnd, "读取声音文件资料失败", NULL,MB_OK);
this->result = buffer->Unlock(pAudio, bytesAudio, NULL, NULL);
if(this->result != DS_OK)
MessageBox(this->soundhwnd, "解除锁定缓冲区失败!", NULL,MB_OK);
mmioClose(this->hbackground, 0);
}
void GameSound::GameSoundAllstop()
{
this->pAttacksound->Stop();
this->pStartmusic->Stop();
this->pTalkmusic->Stop();
this->pWalkmusic->Stop();
this->pWarmusic->Stop();
this->pyudimusic->Stop();
this->pwinmusic->Stop();
this->plosemusic->Stop();
this->pAIAttacksound->Stop();
this->pAttacksound->SetCurrentPosition(0);
this->pStartmusic->SetCurrentPosition(0);
this->pTalkmusic->SetCurrentPosition(0);
this->pWalkmusic->SetCurrentPosition(0);
this->pWarmusic->SetCurrentPosition(0);
this->pyudimusic->SetCurrentPosition(0);
this->pwinmusic->SetCurrentPosition(0);
this->plosemusic->SetCurrentPosition(0);
this->pAIAttacksound->SetCurrentPosition(0);
}
void GameSound::GameMusicplay(LPDIRECTSOUNDBUFFER& buffer)
{
this->GameSoundAllstop();
buffer->Play(0, 0, 1);
}
void GameSound::GameSoundplay(LPDIRECTSOUNDBUFFER& buffer)
{
buffer->Play(0, 0, 0);
}
DirectSound应用的更多相关文章
- WIN32下使用DirectSound接口的简单音频播放器(支持wav和mp3)
刚好最近接触了一些DirectSound,就写了一个小程序练练手,可以用来添加播放基本的wav和mp3音频文件的播放器.界面只是简单的GDI,dxsdk只使用了DirectSound8相关的接口. D ...
- 运用Microsoft.DirectX.DirectSound和Microsoft.DirectX实现简单的录音功能
1.首先要使用Microsoft.DirectX.DirectSound和Microsoft.DirectX这两个dll进行录音,需要先安装microsoft directx 9.0cz这个组件, 百 ...
- Microsoft.DirectX.DirectSound.dll和Microsoft.DirectX.dll引用,导致项目无法调试问题
最近在做录音功能,用到了Microsoft.DirectX.DirectSound.dll和Microsoft.DirectX.dll两个dll,但是引入后,无法调试项目 具体解决方法: 修改app. ...
- DirectSound的应用
假设仅仅使用PlaySound()这个API函数来表现声音效果的话,那么就无法表现出声音的混音效果,由于PlaySound在播放还有一个声音时,必定会导致现有声音的停止.因此,使用 PlaySound ...
- DirectSound播放PCM(可播放实时采集的音频数据)
前言 该篇整理的原始来源为http://blog.csdn.net/leixiaohua1020/article/details/40540147.非常感谢该博主的无私奉献,写了不少关于不同多媒体库的 ...
- 最简单的视音频播放示例8:DirectSound播放PCM
本文记录DirectSound播放音频的技术.DirectSound是Windows下最常见的音频播放技术.目前大部分的音频播放应用都是通过DirectSound来播放的.本文记录一个使用Direct ...
- [转]directsound抓取麦克风PCM数据封装类
网上有很多方法从麦克风读取PCM数据,不想一一举例.只是在这里发布一个我自己写的directsound的麦克风PCM数据采集类,通过它,可以很方便的利用directsound技术把麦克风的数据采集到, ...
- DirectSound学习(三)--类、方法、属性翻译
DirectSound.Device :Contains methods and properties used to create buffer objects, manage devices, a ...
- DirectSound学习(二)--流式缓冲区
使用流式缓冲方式播放波形音频文件比较复杂,主要原因是在只有一个缓冲区提供给用户的前提下,这个缓冲区在提供给声卡播放数据的同是还需要用户不断的定时向其中写入数据.要注意从缓冲区这时是一个环形缓冲区,声音 ...
- Microsoft.DirectX.DirectSound学习(一)
背景:为什么用到这个类库呢?公司要一个要播放音频文件(.wav)的功能,本来想着很ez的事,网上提供的jq插件.本地也有很多播放器,怎么用都行.可当我实现的时候发现大部分网上插件在火狐上不支持.wav ...
随机推荐
- java单元测试(Junit)
JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework),供Java开发人员编写单元测试之用. 对不同性质的被 ...
- jQuery整理笔记2----jQuery选择整理
一个.基本的选择 1.ID选择器 JavaScript提供了原生方法实如今DOM中选择指定ID值得元素. 使用方法例如以下: var element=document.getElementById(& ...
- 查看.a架构文件
苹果公司现在要求所有新提交的评论app,我们必须支持64位架构.而我们的在线项目编制,操作员做了一堆SDK在需要访问,我们发现,在这个过程中,有些SDK的.a文件进入后,链接错误,如提示 Undefi ...
- Metatable和Metamethod(转)
Metatable和Metamethod是用来干啥的?它们可以使得表a和b的表达式“a + b”变得有意义,其中metatable使两个不相关的表a和b之间可以进行操作,而操作的具体行为比如说&quo ...
- String、StringBuffer和StringBuilder
一.String和StringBuffer String类型和StringBuffer类型的主要性能差别事实上在于String是不可变的对象,因此在每次对String类型进行改变的时候事实上都等同于生 ...
- HDU 5059 Help him(细节)
HDU 5059 Help him 题目链接 直接用字符串去比較就可以,先推断原数字正确不对,然后写一个推断函数,注意细节,然后注意判掉空串情况 代码: #include <cstdio> ...
- 无法Debug SQL: Unable to start T-SQL Debugging. Could not attach to SQL Server process on
今天SSMS debug SQL当脚本,突然错误: Unable to start T-SQL Debugging. Could not attach to SQL Server process on ...
- [HA]负载均衡:HAPROXY与KEEPALIVED强强联合
第一步:更改系统控制配置文件,同意分配虚拟IP(VIP) /etc/sysctl.conf net.ipv4.ip_nonlocal_bind=1 <pre style="word-w ...
- HDU1312 Red and Black 解读
递归搜索方法标题,采用递归搜索方法,但是,如果没有迭代计算的真正的政党格. 我们的想法是: 1 每一个搜索为党格要改变电流方向格的值至 '*',或任何其他非'.'的值,代表方格了 2 递归的时候不回复 ...
- 走向DBA[MSSQL篇] 面试官最喜欢的问题 ----索引+C#面试题客串
原文:走向DBA[MSSQL篇] 面试官最喜欢的问题 ----索引+C#面试题客串 对大量数据进行查询时,可以应用到索引技术.索引是一种特殊类型的数据库对象,它保存着数据表中一列或者多列的排序结果,有 ...