DirectSound的应用

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);
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/118077.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • JavaWeb-过滤器Filter学习(四)敏感词过滤实例

    JavaWeb-过滤器Filter学习(四)敏感词过滤实例通过Filter来实现留言板的敏感词过滤…思路很简单,我们这里的敏感词是直接先放进去的,实际项目中,肯定是存在数据库中。在Filter过滤器中,我们先拿到用户提交的留言,如果出现了敏感词,我们就用*号来替换。代码演示:index.jsp:<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%><%@taglibur

  • leetcode-49字母异位词分组(map)[通俗易懂]

    leetcode-49字母异位词分组(map)[通俗易懂]原题链接给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。示例:输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]输出:[ [“ate”,”eat”,”tea”], [“nat”,”tan”], [“bat”]]说明:所有输入均为小写字母。不考虑答案输出的顺序。tclass Solution {public: vector<vector<string>> g

  • pycharm最新2021年激活码_通用破解码

    pycharm最新2021年激活码_通用破解码,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • MCP2515模块_mcp2515接收错误

    MCP2515模块_mcp2515接收错误1、在配置Linux编译选项时,开启相应的SPI选项,如下所示->DeviceDrivers->SPIsupportSPIsupport***SPIMasterControllerDrivers***-*-BitbangingSPImasterSamsungS3C24XXseriesSPI<>SamsungS3C24XXserie…

    2022年10月31日
  • C# CultureInfo中常用的InvariantCulture

    C# CultureInfo中常用的InvariantCulture本文参考自CultureInfo中重要的InvariantCulture,纯属读书笔记,加深记忆1、CultureInfo的InvariantCulture的作用(1)、CultureInfo使整个.NETFramework更加人性化,因为这可以使同一个数据适应不同地区和文化,这样当然满足处于不同地区和文化的用户。但前提是数据给“人”看,如果这些数据用于计算机之间的传输,即给“…

  • 堆排序算法(图解详细流程)

    堆排序算法(图解详细流程)堆排序的时间复杂度O(N*logN),额外空间复杂度O(1),是一个不稳定性的排序目录一准备知识1.1大根堆和小根堆二堆排序基本步骤2.1构造堆2.2固定最大值再构造堆三总结四代码一准备知识堆的结构可以分为大根堆和小根堆,是一个完全二叉树,而堆排序是根据堆的这种数据结构设计的一种排序,下面先来看看什么是大根堆和小根堆1.1大根…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号