MMIO编程播放wave音频文件

WAV文件的结构为:
'RIFF'<文件大小>'WAVE'<格式块><数据块>
RIFF文件本身就是一个RIFF块,其数据域是WAV子块,而WAV子块又包含格式块('fmt ')和数据块('data')。
 
通常在播放音频前需要对音频进行处理时采用这种方式打开。
 
具体步骤:
 1、打开wav文件。
 2、将wav文件(格式块及数据块)载入内存
 3、打开音频设备。
 4、准备要播放的数据。
 5、播放。
 6、播放完成后关闭音频设备,释放内存。
 
代码:
 HMMIO hmmio;
 CFileDialog FileDlg(true,NULL,NULL,OFN_HIDEREADONLY ,"wave music(*.wav)|*.wav|all file(*.*)|*.*||");
 CString strName;
 MMCKINFO mmckinfoParent;
 MMCKINFO mmckinfoSubChunk;
 if(IDOK == FileDlg.DoModal())
 {
  strName = FileDlg.GetPathName();
 }
 else
 {
  return;
 }
 //打开文件
 if(!(hmmio = mmioOpen(strName.GetBuffer(strName.GetLength()), NULL, MMIO_READ|MMIO_ALLOCBUF)))
 {
  MessageBox("打开文件失败!");
  return ;
 }
 //检测是否是wav格式文件
 mmckinfoParent.fccType = mmioFOURCC('W','A','V','E');
 if(mmioDescend(hmmio, (LPMMCKINFO)&mmckinfoParent, NULL, MMIO_FINDRIFF))
 {
  MessageBox("格式错误!");
  mmioClose(hmmio,0);
  return;
 }
 //寻找fmt格式块
 mmckinfoSubChunk.ckid = mmioFOURCC('f','m','t',' ');
 if(mmioDescend(hmmio, &mmckinfoSubChunk, &mmckinfoParent, MMIO_FINDCHUNK))
 {
  MessageBox("寻找格式块失败!");
  mmioClose(hmmio,0);
  return;
 }
 
 //获得fmt块大小,申请内存
 DWORD dwFmtSize = mmckinfoSubChunk.cksize;
 HANDLE hFormat = LocalAlloc(LMEM_MOVEABLE, LOWORD(dwFmtSize));
 if(!hFormat)
 {
  MessageBox("申请内存失败!");
  mmioClose(hmmio,0);
  return ;
 }
 //读取fmt块
 WAVEFORMATEX* lpFormat = (WAVEFORMATEX*)LocalLock(hFormat);
 if(!lpFormat)
 {
  MessageBox("锁定内存失败");
  mmioClose(hmmio,0);
  LocalFree(hFormat);
  return;
 }
 if((unsigned long)mmioRead (hmmio, (HPSTR)lpFormat, dwFmtSize) != dwFmtSize)
 {
  MessageBox("读取格式块失败");
  LocalUnlock(hFormat);
  LocalFree(hFormat);
  mmioClose(hmmio,0);
  return ;
 }
 //离开fmt块
 mmioAscend (hmmio, &mmckinfoSubChunk, 0);
 //寻找data数据块
 mmckinfoSubChunk.ckid = mmioFOURCC('d','a','t','a');
 if(mmioDescend (hmmio, &mmckinfoSubChunk, &mmckinfoParent, MMIO_FINDCHUNK))
 {
  MessageBox ("寻找数据块失败");
  LocalUnlock(hFormat);
  LocalFree(hFormat);
  mmioClose(hmmio,0);
  return;
 }
 //获得data块大小,申请内存
 DWORD dwDataSize = mmckinfoSubChunk.cksize;
 DWORD dwDataOffset = mmckinfoSubChunk.dwDataOffset;
 if(dwDataSize == 0L)
 {
  MessageBox ("数据块中无数据");
  LocalUnlock(hFormat);
  LocalFree(hFormat);
  mmioClose(hmmio,0);
  return;
 }
 HPSTR lpData = new char[dwDataSize];
 if(!lpData)
 {
  MessageBox ("申请内存失败");
  LocalUnlock(hFormat);
  LocalFree(hFormat);
  mmioClose(hmmio,0);
  return;
 }
 //读取data块
 if(mmioSeek(hmmio, dwDataOffset, SEEK_SET)<0)
 {
  MessageBox ("读取数据块失败");
  LocalUnlock(hFormat);
  LocalFree(hFormat);
  mmioClose(hmmio,0);
  delete []lpData;
  return;
 }
 DWORD dwWaveLong = mmioRead (hmmio, (HPSTR)lpData, dwDataSize);
 if(dwWaveLong<0)
 {
  MessageBox ("读取数据块失败");
  LocalUnlock(hFormat);
  LocalFree(hFormat);
  mmioClose(hmmio,0);
  delete []lpData;
  return;
 }
 WAVEHDR WaveOutHdr;
 HWAVEOUT hWaveOut;
 //检测音频设备能否播放指定音频
 if(waveOutOpen (&hWaveOut, WAVE_MAPPER, lpFormat, NULL, NULL, CALLBACK_NULL) != 0)
 {
  MessageBox ("不能播放指定格式");
  LocalUnlock(hFormat);
  LocalFree(hFormat);
  mmioClose(hmmio,0);
  delete []lpData;
  return;
 }
 //准备要播放的数据
 WaveOutHdr.lpData = (HPSTR)lpData;
 WaveOutHdr.dwBufferLength = dwWaveLong;
 WaveOutHdr.dwFlags = 0;
 if(waveOutPrepareHeader (hWaveOut, &WaveOutHdr, sizeof(WAVEHDR)) != 0)
 {
  MessageBox ("准备数据失败");
  waveOutClose(hWaveOut);
  LocalUnlock(hFormat);
  LocalFree(hFormat);
  mmioClose(hmmio,0);
  delete []lpData;
  return;
 }
 //播放音频文件
 if(waveOutWrite (hWaveOut, &WaveOutHdr, sizeof(WAVEHDR)) != 0)
 {
  MessageBox ("播放失败");
  waveOutClose(hWaveOut);
  LocalUnlock(hFormat);
  LocalFree(hFormat);
  mmioClose(hmmio,0);
  delete []lpData;
  return;
 }
 Sleep(8000);//等待播放完成
 //关闭音频设备,释放内存
 waveOutReset(hWaveOut);
 waveOutClose(hWaveOut);
 LocalUnlock(hFormat);
 LocalFree(hFormat);
 mmioClose(hmmio,0);
 delete []lpData;
 
需要 mmsystem.h 和 winmm.lib
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值