windows下使用waveout函数族播放wav文件
要使用waveout函数组,族,首先要知道几个数据结构,首先是这个
typedef struct tWAVEFORMATEX
{
WORD wFormatTag; /* 格式的类型 */
WORD nChannels; /* 通道数 */
DWORD nSamplesPerSec; /* 采样频率 */
DWORD nAvgBytesPerSec; /* 比特率 采样率*声道数*采样位数/8 */
WORD nBlockAlign; /* 一次采样的宽度 通道数*采样位数/8 */
WORD wBitsPerSample; /* 采样位数 */
WORD cbSize; /* 外部附加信息,不用设置为0 */
/* extra information (after cbSize) */
} WAVEFORMATEX,
这个结构体在打开音频设备准备播放声音的时候是必须的,打开音频设备的时候需要使用的函数为
if(!(waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER,(LPWAVEFORMATEX)&pFormat,(DWORD)this, , ) == MMSYSERR_NOERROR))
第一个参数是音频设备的句柄,定义如下
LPHWAVEOUT hWaveOut;
实际上也就是一个设备指针
第二个参数为设备类型,其中选择WAVE_MAPPER能选一个能够播放给定格式的波形音频输出装置
第三个参数为音频数据的格式信息
第四个参数是一个回调函数
第五个是回调函数的资源句柄
第六个是打开装置的标识,具体的描述可以去看msdn成功后返回MMSYSERR_NOERROR ,否则返回以下值:
值描述
MMSYSERR_ALLOCATED 表示资源已存在
MMSYSERR_BADDEVICEID 装置ID超出范围
MMSYSERR_NODRIVER 没有驱动
MMSYSERR_NOMEM 不能分配内存
WAVERR_BADFORMAT 企图打开一个不被支持的格式
WAVERR_SYNC 装置是可同步的,但waveOutOpen没用有WAVE_ALLOWSYNC
打开音频设备之后就需要准备音频的格式信息了,这里需要第二个结构体
/* wave data block header */
typedef struct wavehdr_tag {
LPSTR lpData; /*指向锁定数据缓冲区的指针 */
DWORD dwBufferLength; /*数据缓冲区长度 */
DWORD dwBytesRecorded; /* used for input only */
DWORD_PTR dwUser; /* for client's use */
DWORD dwFlags; /* assorted flags (see defines) */
DWORD dwLoops; /* loop control counter */
struct wavehdr_tag FAR *lpNext; /* reserved for driver */
DWORD_PTR reserved; /* reserved for driver */
} WAVEHDR
使用方式如下
hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD)sizeof(WAVEHDR));
if(hWaveHdr == NULL)
{
MessageBox("Not enough memory for header","error",MB_OK);//打开设备失败
return;
}
lpWaveHdr = (LPWAVEHDR)GlobalLock(hWaveHdr);
if(lpWaveHdr == NULL)
{
MessageBox("Failed to lock memory for header","error",MB_OK);
return;
} // 初始化音频结构After allocation, set up and prepare header.
lpWaveHdr->lpData = (char *)pVoiceBuffer;
lpWaveHdr->dwBufferLength = lFileSize;
lpWaveHdr->dwFlags = 0L; //WHDR_BEGINLOOP | WHDR_ENDLOOP;
lpWaveHdr->dwLoops = 0L; if(waveOutPrepareHeader((HWAVEOUT)hWaveOut, lpWaveHdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
缓冲区可以设置为我们读取进来的数据的内存地址,另外,该缓冲区需要锁定
接下来就可以写入数据了
wResult = waveOutWrite((HWAVEOUT)hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
写入数据失败的话要把之前锁定的缓冲区解除掉,使用这个函数
waveOutUnprepareHeader((HWAVEOUT)hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
GlobalUnlock(lpWaveHdr);
GlobalFree(hWaveHdr);
如果成功就可以进入循环一直播放知道数据播放完成,如下
while(waveOutUnprepareHeader((HWAVEOUT)hWaveOut, lpWaveHdr, sizeof(WAVEHDR))!= MMSYSERR_NOERROR)
{
//循环清除缓冲区,如果成功表示播放完毕
//如果没有播放完毕则循环下面语句
if(bExit)
break;//让循环也可以响应消息
MSG message;
if(::PeekMessage (&message,NULL,,,PM_REMOVE))
{
::TranslateMessage (&message);
::DispatchMessage (&message);
}
}
数据播放完成之后需要先复位播放器在关闭音频设备,如下
//播放完毕
if(waveOutReset((HWAVEOUT)hWaveOut) != MMSYSERR_NOERROR)
{
MessageBox("WaveOutReset Error!","error",MB_OK);
return;
}
if(waveOutClose((HWAVEOUT)hWaveOut)!= MMSYSERR_NOERROR)
{
MessageBox("WaveOutClose Error!","error",MB_OK);
return;
}
通过这些就能完成一个基本的wav播放器了,同时mp3的播放器只需要mp3解码也能做了
界面如下

工程代码链接如下
http://download.csdn.net/detail/dengrengong/8639579
windows下使用waveout函数族播放wav文件的更多相关文章
- WinAPI: sndPlaySound - 播放 wav 文件
WinAPI: sndPlaySound - 播放 wav 文件 //声明: sndPlaySound( lpszSoundName: PChar; {声音文件} uFlags: UINT{播 ...
- 如何播放 WAV 文件?
from http://www.vckbase.com/index.php/wv/434 平时,你在多媒体软件的设计中是怎样处理声音文件的呢?使用Windows 提供的API函数 sndPlaySou ...
- C#播放wav文件
C#使用HWQPlayer类播放wav文件 类的代码: using System.IO; using System.Runtime.InteropServices; namespace HoverTr ...
- python 播放 wav 文件
未使用其他库, 只是使用 pywin32 调用系统底层 API 播放 wav 文件. # Our raison d'etre - playing sounds import pywintypes im ...
- Windows下Git Bash中VIM打开文件中文乱码
Windows下Git Bash中VIM打开文件中文乱码,解决方法是: 步骤一 admin@DESKTOP-O99620V MINGW64 /d/项目GGE/Hard_for_GGE (master) ...
- 使用WaveOut API播放WAV音频文件(解决卡顿)
虽然waveout已经过时,但是其api简单,有些时候也还是需要用到. 其实还是自己上msdn查阅相应api最靠谱,waveout也有提供暂停.设置音量等接口的,这里给个链接,需要的可以自己查找: h ...
- 8086汇编语言 调用声卡播放wav文件(sound blaster)
开更 大概最后做了一个能播放无损音乐(无压缩.不需解码)的播放器 原理是基于dosbox的模拟声卡,通过硬件之间的相互通讯做到的 关于详细内容接下来再讲. 一.从dosbox入手 我们知道cpu可以直 ...
- Linux音频编程--使用ALSA库播放wav文件
在UBUNTU系统上使用alsa库完成了对外播放的wav文件的案例. 案例代码: /** *test.c * *注意:这个例子在Ubuntu 12.04.1环境下编译运行成功. * */ #inclu ...
- windows下安装easy_install, pip 及whl文件安装方法
转:http://www.cnblogs.com/wu-wenmin/p/4250330.html 写在前面的话 最近在看"Computer Vision with Python" ...
随机推荐
- linux ubuntu下如何安装并且切换java版本(Unsupported major.minor version 52.0)
最近在做一个dcos(数据中心操作系统)的东西,需要用marathon来做进程管理.遗憾的是0.6版本的marathon在API方面很是缺少,换成了0.15版本之后,运行时提示“Unsupported ...
- java 文件字节输出流
Example10_5.java import java.io.*; public class Example10_5 { public static void main(String args[]) ...
- cocos2d-x 3.x随机数
1.使用标准库std::rand()函数 rand();//产生0~RAND_MAX(0x7fff=32767)间的int类型随机数 rand()%;//产生0~5间的int类型随机数,不包括5 2. ...
- angular.js_$scope
Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带. Scope 是一个对象,有可用的方法和属性. Scope 可应用在视图和控制器上. Angular ...
- 转:浏览器与WEB服务器工作过程举例
用户通过“浏览器”访问因特网上的WEB服务器,浏览器和服务器之间的信息交换使用超文本传输协议(HTTP--HyperText Transfer Protocol). 例:用户访问东南大学主页 Http ...
- PAT (Advanced Level) 1109. Group Photo (25)
简单模拟. #include<cstdio> #include<cstring> #include<cmath> #include<vector> #i ...
- xtraReprot 动态绑定数据 数据列动态
这样做并不是我想出来的,是之前做一个报表模板时搜的,原地址忘了 我要做的报表模板要求是传入一个DataTble,不管datatable的列数多少,计算列宽后显示报表 这是我的报表: 灰色那个XRtab ...
- 随机法解决TSP问题
TSP问题一直是个头疼的问题,但是解决的方法数不胜数,很多的算法也都能解决.百度资料一大堆,但是我找到了代码比较简练的一种.随机法.下面只是个人的看法而已,如果有任何问题虚心接受. 顾名思义,随机法就 ...
- Base64笔记
1. 昨天的<MIME笔记>中提到,MIME主要使用两种编码转换方式----Quoted-printable和Base64----将8位的非英语字符转化为7位的ASCII字符. 虽然这样的 ...
- Mysql命令-求一列字段的总和
求和命令 mysql> select SUM(price) from order where create_time>'2016-03-12';+------------+| SUM(pr ...