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的应用,布布扣,bubuko.com

时间: 2024-10-12 17:12:01

DirectSound的应用的相关文章

最简单的视频播放示例8:DirectSound播放PCM

本文记录DirectSound播放音频的技术.DirectSound是Windows下最常见的音频播放技术.目前大部分的音频播放应用都是通过DirectSound来播放的.本文记录一个使用DirectSound播放PCM的例子.注:一位仁兄已经提醒我DirectSound已经计划被XAudio2取代了.后来考证了一下发现确有此事.因此在下次更新中考虑加入XAudio2播放PCM的例子.本文仍然记录一下DirectSound这位"元老". DirectSound简介 DirectSoun

WIN32下使用DirectSound接口的简单音频播放器(支持wav和mp3)

刚好最近接触了一些DirectSound,就写了一个小程序练练手,可以用来添加播放基本的wav和mp3音频文件的播放器.界面只是简单的GDI,dxsdk只使用了DirectSound8相关的接口. DirectSound的使用步骤很简单 首先你要创建一个DirectSound8设备对象 1 HRESULT DirectSoundCreate8( 2 LPCGUID lpcGuidDevice, 3 LPDIRECTSOUND8 * ppDS8, 4 LPUNKNOWN pUnkOuter 5 )

C#使用DirectSound录音基本方法

原文地址:http://blog.donews.com/uplook/archive/2005/12/14/657145.aspx 注:1.原文有程序终止后仍有线程在运行的情况,这里修正了下 2.DirectSound录音详细介绍:http://blog.csdn.net/woaixiaozhe/article/details/7863007 3."Mixed mode assembly is built against version 'v1.1.4322' of the runtime an

DirectSound播放PCM(可播放实时采集的音频数据)

前言 该篇整理的原始来源为http://blog.csdn.net/leixiaohua1020/article/details/40540147.非常感谢该博主的无私奉献,写了不少关于不同多媒体库的博文.让我这个小白学习到不少.现在将其整理是为了收录,以备自己查看. 一.DirectSound简介 DirectSound是微软所开发DirectX的组件之一,可以在Windows 操作系统上录音,并且记录波形音效(waveform sound).目前DirectSound 是一个成熟的API ,

DirectSound学习(三)--类、方法、属性翻译

DirectSound.Device :Contains methods and properties used to create buffer objects, manage devices, and set up the environment. 包含用于创建缓冲区对象,管理设备的方法和属性,并设置环境.方法: Method Description Compact This method has no effect. 没有解释 Device Initializes a new instan

最简单的视音频播放示例8:DirectSound播放PCM

本文记录DirectSound播放音频的技术.DirectSound是Windows下最常见的音频播放技术.目前大部分的音频播放应用都是通过DirectSound来播放的.本文记录一个使用DirectSound播放PCM的例子.注:一位仁兄已经提醒我DirectSound已经计划被XAudio2取代了.后来考证了一下发现确有此事.因此在下次更新中考虑加入XAudio2播放PCM的例子.本文仍然记录一下DirectSound这位“元老”. DirectSound简介 DirectSound是微软所

SlimDX的DirectSound模块

网上SlimDX的资源很少,搜到了http://www.xukailun.me/article/238/这篇关于<SlimDX的DirectSound模块应用实战>的文章,备份下来以备不时之需. 1.基本的播放功能 void CreateDirectSound(Guid deviceId, IntPtr handle) { // 音频设备的Id _ds = new DirectSound(deviceId); // 需要使用窗口的句柄 _ds.SetCooperativeLevel(handl

DirectSound导致程序启动假死

错误代码:DirectSound.dll"正尝试在 OS 加载程序锁内执行托管代码.不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起. 解决方案有设置配置文件的startrup节点 <startup useLegacyV2RuntimeActivationPolicy="true"> 如果提示 未处理System.TypeInitializationException 说明检查不到设备 需要查看设备驱动或启动虚拟录音设备 原文地

DirectSound播放缓冲区长度计算

播放测试时,发现声音播放速度不对,找了不少地方,没发现错误,无奈,采用定时器,抓捕播放通知事件时间,发现每秒多了4次,这才恍然大悟,缺少对齐数.原公式为:dwPlayBufLen = iSamplesPerSec / iFrameFpsPerSec; 缺少了nBlockAlign对齐数,因为播放长度是按字节排序的,必须存在采样字长概念,而采样字长是按字节计算,每字节计为1,公式为:nBlockAlign = (nChannels  *  wBitsPerSample)  /  8; 修改播放缓冲