VC下实现DirectSound

2023-11-03 23:08
文章标签 实现 vc directsound

本文主要是介绍VC下实现DirectSound,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

加入音乐是增强应用程序功能的所有方法中最简单的一个。音乐可以使用户心情
愉快;在合适的场合播放恰当的音乐能够使程序员和他的VC++程序焕发光彩。

 

---- Microsoft Windows Multimedia API提供了三种方法来播放WAV文件:

PlaySound()函数。它可以通过单行编码来播放Wave格式的声音。此函数有两个限制
:必须将声音数据完整地载入物理内存;数据格式必须被所配置的某一音频驱动器支
持。根据经验,PlaySound()适用于100K以下的文件。

MCI(The Media Control Interface)。MCI功能强大,不仅可以实现WAV文件的播放,
而且还可以播放MIDI及CD音频。

低级Wave音频设备。用这些设备可以运行完全控制Wave数据的应用文件。
---- 前两种方法使用简单,但无法实现两个及两个以上的WAV文件的播放;第三种方法
实现起来非常复杂,非专业人员很难完成。DirectSound可以实现八个及八个以上WAV文
件的同时播放,能使多媒体程序更加生动,而且简单易用,但它仅适合于Windows 95下
的程序,也不支持WAV文件的记录及存储""这是唯一让人遗憾的地方。实现
DirectSound需要以下几个步骤:
1. 创建及初始化DirectSound
LPDIRECTSOUND m_pDirectObject;
if(DirectSoundCreate(NULL,&m_pDirectObject,NULL)==DS_OK)
file://设定应用程序的声音设备优先级别方式,一般为DSSCL_NORMAL
m_pDirectObject->SetCooperativeLevel
(this- >m_hWnd,DSSCL_NORMAL);
else
AfxMessageBox("DirectSound Create failed");

2. 将WAV文件读入内存,找到格式块,数据块位置及数据长度。
m_pMemory,m_pFormat,m_pData,m_dwSize在头文件中声明。
BOOL CDirectWave::LoadFile (CString Filename){
CFile File;
DWORD dwSize;
if (!File.Open (Filename,
CFile::modeRead | CFile::shareDenyNone))
return FALSE;
dwSize = File.Seek (0, CFile::end);
File.Seek (0, CFile::begin);
file://m_pMemory内存存储块指针,类型:LPVOID
m_pMemory = GlobalAlloc (GMEM_FIXED, dwSize);
if (File.ReadHuge (m_pMemory, dwSize) != dwSize){
File.Close ();
return FALSE;
}
File.Close ();

LPDWORD pdw,pdwEnd;
DWORD dwRiff,dwType, dwLength, dwLength;
if (m_pFormat) file://格式块指针,类型:LPWAVEFORMATEX
m_pFormat = NULL;
if (m_pData) file://数据块指针,类型:LPBYTE
m_pData = NULL;
if (m_dwSize) file://数据长度,类型:DWORD
m_dwSize = 0;
pdw = (DWORD *) m_pMemory;
dwRiff = *pdw++;
dwLength = *pdw++;
dwType = *pdw++;

if (dwRiff != mmioFOURCC ('R', 'I', 'F', 'F'))
return FALSE;
if (dwType != mmioFOURCC ('W', 'A', 'V', 'E'))
return FALSE;
file://寻找格式块,数据块位置及数据长度
pdwEnd = (DWORD *)((BYTE *) pdw + dwLength - 4);
while (pdw < pdwEnd){
dwType = *pdw++;
dwLength = *pdw++;
switch (dwType){
case mmioFOURCC('f', 'm', 't', ' '):
if (!m_pFormat){
if (dwLength < sizeof (WAVEFORMAT))
return FALSE;
m_pFormat = (LPWAVEFORMATEX) pdw;
if (m_pData && m_dwSize)
return TRUE;
}
break;

case mmioFOURCC('d', 'a', 't', 'a'):
if (!m_pData || !m_dwSize){
m_pData = (LPBYTE) pdw;
m_dwSize = dwLength;
if (m_pFormat)
return TRUE;
}
break;
}
pdw = (DWORD *)((BYTE *) pdw +
((dwLength + 1) &~ 1));
}
file://未找到,返回FALSE
return FALSE;
}

3. 创建声音缓冲区
DSBUFFERDESC BufferDesc;
memset (&BufferDesc, 0, sizeof (BufferDesc));
BufferDesc.lpwfxFormat = (LPWAVEFORMATEX) m_pFormat;
BufferDesc.dwSize = sizeof (DSBUFFERDESC);
BufferDesc.dwBufferBytes = m_dwSize;
BufferDesc.dwFlags = 0;
file://头文件中声明m_pDSoundBuffer,类
型:LPDIRECTSOUNDBUFFER
if (pDSoundObject->CreateSoundBuffer
(&BufferDesc, &m_pDSoundBuffer, 0) != DS_OK)
return FALSE;

4. 载入声音数据
BOOL CDirectWave::LoadData (void){
LPVOID lpPtr1, lpPtr2;
DWORD dwLen1, dwLen2;
HRESULT hResult;

TryLoad:
hResult = m_pDSoundBuffer- >Lock
(0, m_dwSize, &lpPtr1, &dwLen1, &lpPtr2, &dwLen2, 0);
if (hResult == DS_OK){
memcpy (lpPtr1, m_pData, dwLen1);
if (lpPtr2)
memcpy (lpPtr2, m_pData + dwLen1, dwLen2);
m_pDSoundBuffer- >Unlock
(lpPtr1, dwLen1, lpPtr2, dwLen2);
return TRUE;
}
else if (hResult == DSERR_BUFFERLOST){
hResult = m_pDSoundBuffer- >Restore ();
if (hResult == DS_OK)
goto TryLoad;
}
return FALSE;
}

5. 播放及停止
void CDirectWave::Play (BOOL bLoop){
DWORD dwFlags = 0;
file://dwFlags= DSBPLAY_LOOPING可实现循环播放
TryPlay:
if (m_pDSoundBuffer- >
Play (0, 0, dwFlags) == DSERR_BUFFERLOST){
if (LoadData ())//数据丢失,重新装载
goto TryPlay;
}
}
void CDirectWave::Stop (void){
m_pDSoundBuffer- >Stop ();
}
6. 关闭。释放内存块,声音缓冲区。

DirectSound需要用到mmsystem.h,dsound.h两个头文件。

 

 

更多技术文章请参看施昌权的个人网站: http://www.joyvc.cn

 

 

这篇关于VC下实现DirectSound的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/341496

相关文章

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核