聲音的基礎知識2

三、聲音文件的聲音數據的讀取操作

操作聲音文件,也就是將WAVE文件打開,獲取其中的聲音數據,根據所需要的聲音數據處理算法,進行相應的數學運算,然後將結果重新存儲與WAVE格式的文件中去。可以使用CFILE類來實現讀取操作,也可以使用另外一種方法,拿就是使用Windows提供的多媒體處理函數(這些函數都以mmino打頭)。這裏就介紹如何使用這些相關的函數來獲取聲音文件的數據,至於如何進行處理,那要根據你的目的來選擇不同的算法了。WAVE文件的操作流程如下:

1.調用mminoOpen函數來打開WAVE文件,獲取HMMIO類型的文件句柄;

2.根據WAVE文件的結構,調用mmioRead、mmioWrite和mmioSeek函數實現文件的讀、寫和定位操作;

3.調用mmioClose函數來關閉WAVE文件。

下面的函數代碼就是根據WAVE文件的格式,實現了讀取雙聲道立體聲數據,但是在使用下面的代碼過程中,注意需要在程序中鏈接Winmm.lib庫,並且包含頭文件"Mmsystem.h"。

BYTE * GetData(Cstring *pString)
//獲取聲音文件數據的函數,pString參數指向要打開的聲音文件;
{
if (pString==NULL)
return NULL;
HMMIO file1;//定義HMMIO文件句柄;
file1=mmioOpen((LPSTR)pString,NULL,MMIO_READWRITE);//以讀寫模式打開所給的WAVE文件;
if(file1==NULL)
{
MessageBox("WAVE文件打開失敗!");
Return NULL;
}
char style[4];//定義一個四字節的數據,用來存放文件的類型;
mmioSeek(file1,8,SEEK_SET);//定位到WAVE文件的類型位置
mmioRead(file1,style,4);
if(style[0]!='W'||style[1]!='A'||style[2]!='V'||style[3]!='E')//判斷該文件是否爲"WAVE"文件格式
{
MessageBox("該文件不是WAVE格式的文件!");
Return NULL;
}
PCMWAVEFORMAT format; //定義PCMWAVEFORMAT結構對象,用來判斷WAVE文件格式;
mmioSeek(file1,20,SEEK_SET);
//對打開的文件進行定位,此時指向WAVE文件的PCMWAVEFORMAT結構的數據;
mmioRead(file1,(char*)&format,sizeof(PCMWAVEFORMAT));//獲取該結構的數據;
if(format.wf.nChannels!=2)//判斷是否是立體聲聲音;
{
MessageBox("該聲音文件不是雙通道立體聲文件");
return NULL;
}
mmioSeek(file1,24+sizeof(PCMWAVEFORMAT),SEEK_SET);
//獲取WAVE文件的聲音數據的大小;
long size;
mmioRead(file1,(char*)&size,4);
BYTE *pData;
pData=(BYTE*)new char[size];//根據數據的大小申請緩衝區;
mmioSeek(file1,28+sizeof(PCMWAVEFORMAT),SEEK_SET);//對文件重新定位;
mmioRead(file1,(char*)pData,size);//讀取聲音數據;
mmioClose(file1, MMIO_FHOPEN);//關閉WAVE文件;
return pData;
}

四、使用MCI方法操作聲音文件

WAVE聲音文件一個最基本的操作就是將文件中的聲音數據播放出來,用Windows提供的API函數BOOL sndPlaySound(LPCSTR lpszSound, UINT fuSound)可以實現小型WAV文件的播放,其中參數lpszSound 爲所要播放的聲音文件,fuSound爲播放聲音文件時所用的標誌位。例如實現Sound.wav 文件的異步播放,只要調用函數sndPlaySound("c:/windows/Sound.wav",SND_ASYNC)就可以了,由此可以看到sndPlaySound函數使用是很簡單的。但是當WAVE文件大於100K時,這時候系統無法將聲音數據一次性的讀入內存,sndPlaySound函數就不能進行播放了。爲了解決這個問題,你的一個選擇就是用MCI方法來操作聲音文件了。在使用MCI方法之前,首先需要在你開發的項目設置Project->Setting->Link->Object/library modules中加入winmm.lib。並在頭文件中包括"mmsystem.h"頭文件。

MicroSoft API提供了MCI(The Media Control Interface)的方法mciSendCommand()和mciSendString()來完成WAVE文件的播放,這裏僅介紹mciSendCommand()函數的使用。

原型:DWORD mciSendCommand(UINT wDeviceID,UINT wMessage,DWORD dwParam1,DWORD dwParam2);

參數:wDeviceID:接受消息的設備ID;

Message:MCI命令消息;

wParam1:命令的標誌位;

wParam2:所使用參數塊的指針

返值:調用成功,返回零;否則,返回雙字中的低字存放有錯誤信息。

在使用MCI播放聲音文件時,首先要打開音頻設備,爲此要定義MCI_OPEN_PARMS變量 OpenParms,並設置該結構的相應分量:

OpenParms.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_WAVEFORM_AUDIO;//WAVE類型
OpenParms.lpstrElementName = (LPCSTR) Filename;//打開的聲音文件名;
OpenParms.wDeviceID = 0;//打開的音頻設備的ID
mciSendCommand (NULL, MCI_OPEN,MCI_WAIT | MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_ELEMENT, (DWORD)(LPVOID) &OpenParms)函數調用發送MCI_OPEN命令後,返回的參數 OpenParms中成員變量的wDeviceID指明打開了哪個設備。需要關閉音頻設備時只要調用mciSendCommand (m_wDeviceID, MCI_CLOSE, NULL, NULL)就可以了。

播放WAVE文件時,需要定義MCI_PLAY_PARMS變量PlayParms,對該變量進行如下設置:PlayParms.dwFrom = 0,這是爲了指定從什麼地方(時間)播放WAVE文件,設置好以後,調用函數mciSendCommand (m_wDeviceID, MCI_PLAY,MCI_FROM, (DWORD)(LPVOID)&PlayParms));就實現了WAVE聲音文件的播放。

另外,調用mciSendCommand (m_wDeviceID, MCI_PAUSE, 0,(DWORD)(LPVOID)&PlayParms)實現了暫停功能。調用mciSendCommand (m_wDeviceID, MCI_STOP, NULL, NULL)實現停止功能等,可以看出,這些不同的功能實現都是依靠參數"Message"取不同的值來實現的。 不同的Message和dwParam1、dwParam2的組合還可以實現文件的 跳躍功能。如下面的代碼實現了跳轉到WAVE文件末端的操作:mciSendCommand (m_wDeviceID, MCI_SEEK, MCI_SEEK_TO_END, NULL)。

下面的代碼實現了WAVE聲音文件的播放:

void CTest1View::OnMciPlayWave()
{
// TODO: Add your command handler code here
MCI_OPEN_PARMS mciOpenParms;
MCI_PLAY_PARMS PlayParms;
mciOpenParms.dwCallback=0;
mciOpenParms.lpstrElementName="d://chimes.wav";
mciOpenParms.wDeviceID=0;
mciOpenParms.lpstrDeviceType="waveaudio";
mciOpenParms.lpstrAlias=" ";
PlayParms.dwCallback=0;
PlayParms.dwTo=0;
PlayParms.dwFrom=0;
mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciOpenParms);//打開音頻設備;
mciSendCommand(mciOpenParms.wDeviceID,MCI_PLAY,MCI_WAIT,(DWORD)(LPVOID)&PlayParms);//播放WAVE聲音文件;
mciSendCommand(mciOpenParms.wDeviceID,MCI_CLOSE,NULL,NULL);//關閉音頻設備;
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章