您的位置:首页 > 编程语言

MMIO编程播放wave音频文件

2009-04-30 23:36 405 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: