日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C语言里的out函数,c语言 vc 用waveout函数写wave文件播放器

發(fā)布時(shí)間:2024/3/26 c/c++ 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言里的out函数,c语言 vc 用waveout函数写wave文件播放器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

用WaveOut函數(shù)寫(xiě)wave文件播放器

要炒菜的話(huà),就得先準(zhǔn)備工具,如鍋、鏟子、爐灶等。對(duì)程序來(lái)說(shuō),就是各種函數(shù)的應(yīng)用。WaveOut函數(shù)在windowsAPI中屬于低階接口,用來(lái)播放的話(huà)需要用到下面幾個(gè):

waveOutOpen – 打開(kāi)波形輸出設(shè)備

waveOutPrepareHeader – 準(zhǔn)備播放緩沖區(qū)

waveOutUnprepareHeader – 取消播放緩沖區(qū)

waveOutWrite – 將數(shù)據(jù)寫(xiě)入波形輸出設(shè)備

waveOutReset – 波形輸出設(shè)備復(fù)位(清除正在播放的數(shù)據(jù),停止播放)

waveOutPause – 波形輸出設(shè)備暫停(暫停播放)

waveOutRestart – 波形輸出設(shè)備恢復(fù)(繼續(xù)播放)

waveOutClose – 關(guān)閉波形輸出設(shè)備

播放時(shí)使用的順序大致如下:

waveOutOpen 打開(kāi)設(shè)備

waveOutPrepareHeader 準(zhǔn)備緩沖區(qū)

waveOutWrite 寫(xiě)入波形設(shè)備

waveOutReset 波形設(shè)備復(fù)位

waveOutClose 關(guān)閉波形設(shè)備

至于暫停就更簡(jiǎn)單,播放時(shí)執(zhí)行waveOutPause時(shí)暫停播放,再執(zhí)行waveOutRestart時(shí)繼續(xù)播放。

現(xiàn)在工具已經(jīng)齊備了,下來(lái)就是準(zhǔn)備材料了。對(duì)于這個(gè)播放器來(lái)說(shuō),最重要的材料是RIFF檔案、WAVEFORMATEX和WAVEHDR這三個(gè)結(jié)構(gòu)。下面就簡(jiǎn)單介紹一下這三個(gè)結(jié)構(gòu):

RIFF全稱(chēng)為資源互換文件格式(ResourcesInterchange FileFormat),RIFF文件是windows環(huán)境下大部分多媒體文件遵循的一種文件結(jié)構(gòu),RIFF文件所包含的數(shù)據(jù)類(lèi)型由該文件的擴(kuò)展名來(lái)標(biāo)識(shí),能以RIFF文件存儲(chǔ)的數(shù)據(jù)包括:音頻視頻交錯(cuò)格式數(shù)據(jù)(.AVI) 波形格式數(shù)據(jù)(.WAV) 位圖格式數(shù)據(jù)(.RDI) MIDI格式數(shù)據(jù)(.RMI)調(diào)色板格式(.PAL)多媒體電影(.RMN)動(dòng)畫(huà)光標(biāo)(.ANI)其它RIFF文件(.BND) 。具體格式如下:

WAV文件的基本格式

內(nèi)容

變量名

大小

取值

RIFF頭

文件標(biāo)識(shí)符串

fileId

4B

“RIFF”

頭后文件長(zhǎng)度

fileLen

4B

非負(fù)整數(shù)(=文件長(zhǎng)度-8)

數(shù)據(jù)類(lèi)型標(biāo)識(shí)符

波形文件標(biāo)識(shí)符

waveId

4B

“WAVE”

格式塊

塊頭

格式塊標(biāo)識(shí)符串

chkId

4B

“fmt ”

頭后塊長(zhǎng)度

chkLen

4B

非負(fù)整數(shù)(= 16或18)

塊數(shù)據(jù)

格式標(biāo)記

wFormatTag

2B

非負(fù)短整數(shù)(PCM=1)

聲道數(shù)

wChannels

2B

非負(fù)短整數(shù)(= 1或2)

采樣率

dwSampleRate

4B

非負(fù)整數(shù)(單聲道采樣數(shù)/秒)

平均字節(jié)率

dwAvgBytesRate

4B

非負(fù)整數(shù)(字節(jié)數(shù)/秒)

數(shù)據(jù)塊對(duì)齊

wBlockAlign

2B

非負(fù)短整數(shù)(不足補(bǔ)零)

采樣位數(shù)

wBitsPerSample

2B

非負(fù)短整數(shù)(PCM時(shí)才有)

擴(kuò)展域大小

wExtSize

2B

非負(fù)短整數(shù)

可選(根據(jù)chkLen=16 or 18判斷)

擴(kuò)展域

extraInfo

extSize B

擴(kuò)展信息

數(shù)據(jù)塊

塊頭

數(shù)據(jù)塊標(biāo)識(shí)符串

chkId

4B

“data”

頭后塊長(zhǎng)度

chkLen

4B

非負(fù)整數(shù)

塊數(shù)據(jù)

波形采樣數(shù)據(jù)

x或xl、xr

chkLen B

左右聲道樣本交叉排列

樣本值為整數(shù)(整字節(jié)存儲(chǔ),不足位補(bǔ)零),

整個(gè)數(shù)據(jù)塊按blockAlign對(duì)齊

注意:波形聲音檔案以文字字串「RIFF」開(kāi)始,用來(lái)標(biāo)識(shí)這是一個(gè) RIFF 檔案。字串後面是一個(gè) 32 位元的資料塊大小,表示檔案其余部分的大小,或者是小於 8位元組的檔案大小。 資料塊以文字字串「WAVE」開(kāi)始,用來(lái)標(biāo)識(shí)這是一個(gè)波形聲音塊,後面是文字字串「fmt」——注意用空白使之成為 4 字元的字串——用來(lái)標(biāo)識(shí)包含波形聲音資料格式的子資料塊。「fmt」字串的後面是格式資訊大小,這里是 16 位元組。格式資訊是 WAVEFORMATEX 結(jié)構(gòu)的前 16 個(gè)位元組,或者,像最初定義時(shí)一樣,是包含 WAVEFORMAT 結(jié)構(gòu)的 PCMWAVEFORMAT 結(jié)構(gòu),其定義如下:

typedef struct pcmwaveformat - tag

{

WAVEFORMAT wf ; /*音頻波形格式結(jié)構(gòu)*/

WORD wBitsPerSample; /* 采樣大小 */

} PCMWAVEFORMAT;

typedef struct waveformat - tag

{

WORD wFormatTag ; /* 指定格式類(lèi)型; 默認(rèn) WAVE_FORMAT_PCM = 1; */

WORD nChannels;/* 指出波形數(shù)據(jù)的聲道數(shù); 單聲道為 1, 立體聲為 2 */

DWORD nSamplesPerSec;/* 指定采樣頻率(每秒的樣本數(shù)) */

DWORD nAvgBytesperSec;/* 指定數(shù)據(jù)傳輸?shù)膫鬏斔俾?每秒的字節(jié)數(shù)) */

WORD nBlockAlign;/* 指定塊對(duì)齊塊對(duì)齊是數(shù)據(jù)的最小單位 */

} WAVEFORMAT; /*音頻波形格式結(jié)構(gòu)*/

格式資訊的後面是文字字串「data」,然後是 32 位元的資料大小,最後是波形資料本身。 用於讀取標(biāo)記檔案的一個(gè)重要規(guī)則是忽略不準(zhǔn)備處理的資料塊。

音頻波形擴(kuò)展格式結(jié)構(gòu)WAVEFORMATEX用于打開(kāi)音頻設(shè)備,其定義如下:

typedef struct

{

WORD wFormatTag; /* 指定格式類(lèi)型; 默認(rèn) WAVE_FORMAT_PCM = 1; */

WORD nChannels; /* 指出波形數(shù)據(jù)的聲道數(shù); 單聲道為 1, 立體聲為 2 */

DWORD nSamplesPerSec; /* 指定采樣頻率(每秒的樣本數(shù)) */

DWORD nAvgBytesPerSec; /* 指定數(shù)據(jù)傳輸?shù)膫鬏斔俾?每秒的字節(jié)數(shù)) */

WORD nBlockAlign; /* 指定塊對(duì)齊塊對(duì)齊是數(shù)據(jù)的最小單位 */

WORD wBitsPerSample; /* 采樣大小 */

WORD cbSize; /* 附加信息的字節(jié)大小 */

} WAVEFORMATEX;

音頻數(shù)據(jù)塊緩存結(jié)構(gòu)WAVEHDR

其聲明如下:

type struct{

LPSTR lpData; /* 指向鎖定的數(shù)據(jù)緩沖區(qū)的指針 */

DWORD dwBufferLength; /* 數(shù)據(jù)緩沖區(qū)的大小 */

DWORD dwBytesRecorded; /* 錄音時(shí)指明緩沖區(qū)中的數(shù)據(jù)量 */

DWORD dwUser; /* 用戶(hù)數(shù)據(jù) */

DWORD dwFlag; /* 提供緩沖區(qū)信息的標(biāo)志 */

DWORD dwLoops; /* 循環(huán)播放的次數(shù) */

struct wavehdr_tag *lpNext; /* 保留 */

DWORD reserved; /* 保留 */

} WAVEHDR;

dwFlags中提供緩沖區(qū)信息的標(biāo)志。定義以下值:

WHDR_DONE被設(shè)備驅(qū)動(dòng)程序設(shè)置,用來(lái)標(biāo)識(shí)它是完成的(緩沖區(qū))并且正在返回它到應(yīng)用程序

WHDR_PREPARED由Windows設(shè)置表明,在緩沖區(qū)已準(zhǔn)備waveInPrepareHeader或waveOutPrepareHeader功能。

WHDR_BEGINLOOP這個(gè)緩沖區(qū)是在第一個(gè)循環(huán)緩沖區(qū)。這個(gè)標(biāo)志僅用于輸出緩沖器。

WHDR_ENDLOOP這個(gè)緩沖區(qū)是在一個(gè)循環(huán)中的最后一個(gè)緩沖區(qū)。這個(gè)標(biāo)志僅用于輸出緩沖器。

WHDR_INQUEUE由Windows設(shè)置為顯示緩沖區(qū)排隊(duì)播放。

現(xiàn)在材料、工具都有了,接下來(lái)就是如何炒的問(wèn)題了。windows程序設(shè)計(jì)是一種以物件為導(dǎo)向的創(chuàng)作,所謂物件就是程式與資料的組合,你所見(jiàn)到的程序界面就是一種物件。你可以先在紙上畫(huà)出程序的界面,然后再根據(jù)它逐步添加各個(gè)模塊功能。下面就是播放器的界面:

如圖有8個(gè)按鈕和一個(gè)列表框,它們代表了程序的各個(gè)功能模塊。有了界面就等于建好了房子的框架,下來(lái)只要添磚加瓦就可以了。windows程序是以消息作為驅(qū)動(dòng)的,對(duì)這些功能模塊的處理就是各種消息的處理,下面請(qǐng)看偽代碼:

//對(duì)話(huà)方塊回調(diào)函數(shù)BOOL CALLBACK DlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

//處理窗口消息

switch (message)

{

case WM_INITDIALOG://處理對(duì)話(huà)方塊初始化消息

//初始化代碼

return TRUE ;

//處理窗口控件消息

case WM_COMMAND:

switch (LOWORD (wParam))

{

case IDC_OPEN://處理打開(kāi)按鈕消息

//獲取文件名

//輸出音樂(lè)文件列表

//將循環(huán)標(biāo)志改為正常

//獲取wave音頻格式

//打開(kāi)波形設(shè)備if(waveOutOpen(&(params.hWaveOut), WAVE_MAPPER, &wfx, (DWORD)waveOutProc,

(DWORD)&waveFreeBlockCount, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)

{

//顯示錯(cuò)誤信息

return TRUE ;

}//將當(dāng)前播放文件加亮

//開(kāi)啟音頻緩沖線(xiàn)程

return TRUE ;

//處理暫停播放消息

case IDC_PAUSE:

if//如果暫停條件為真

{

//繼續(xù)播放

}

else//如果暫停條件為假

{

//暫停播放

}

return TRUE ;

//處理上一首消息

case IDC_LAST:

//如果播放的是第一首則不處理

//發(fā)送WM_WAVEPLAY消息

return TRUE ;

//處理下一首消息

case IDC_NEXT:

//如果播放的是最后一首則不處理

//發(fā)送WM_WAVEPLAY消息

return TRUE ;

//處理正常播放消息

case IDC_NORMAL:

//將標(biāo)志置為正常播放

return TRUE ;

//處理單次循環(huán)消息

case IDC_REPLAY_ONE:

//將標(biāo)志置為單次循環(huán)

return TRUE ;

//處理全部循環(huán)消息

case IDC_REPLAY_ALL:

//將標(biāo)志置為全部循環(huán)

return TRUE ;

//處理停止消息

case IDC_STOP:

//設(shè)置停止標(biāo)志

//發(fā)送WM_WAVEPLAY消息

return TRUE ;

//處理列表控件消息

case IDC_LIST:

if(HIWORD(wParam) == LBN_DBLCLK)//如果雙擊文件

{//設(shè)置線(xiàn)程關(guān)閉條件為真

//重置波形設(shè)備

//解除所有的WAVEHDR結(jié)構(gòu)

//關(guān)閉波形設(shè)備

//如果存在打開(kāi)文件句柄則關(guān)閉它

//取得雙擊的文件序號(hào)

//獲取wave文件音頻格式結(jié)構(gòu)

//打開(kāi)波形設(shè)備//開(kāi)啟音頻緩沖線(xiàn)程

}

return TRUE ;

}

break ;

//處理自定義消息

case WM_WAVEPLAY:

//設(shè)置線(xiàn)程關(guān)閉條件為真

//重置波形設(shè)備

//解鎖所有的WAVEHDR結(jié)構(gòu)

//關(guān)閉波形設(shè)備

//如果存在文件句柄則關(guān)閉它

//如果停止條件為真則退出處理

//如果單次循環(huán)條件為真

{

//代碼

}

//如果全部循環(huán)條件為真

{

//代碼

}

//如果播放上一首條件為真

{

//代碼

}

//如果播放下一首條件為真

{

//代碼

}//如果播放的是最后一首則不處理

//獲取wave文件音頻格式結(jié)構(gòu)

//打開(kāi)波形設(shè)備

//發(fā)送列表框控件當(dāng)前選擇加亮消息

//開(kāi)啟音頻緩沖線(xiàn)程

return TRUE ;

//處理系統(tǒng)控件消息

case WM_SYSCOMMAND:

switch (wParam)

{

case SC_CLOSE://處理窗口關(guān)閉消息

if (音頻設(shè)備打開(kāi))

{

//設(shè)置線(xiàn)程關(guān)閉條件為真

//重置波形設(shè)備

//解鎖所有的WAVEHDR結(jié)構(gòu)

//釋放所有的音頻緩沖塊

//關(guān)閉波形設(shè)備

//如果文件句柄存在則關(guān)閉它

//結(jié)束對(duì)話(huà)方塊

}

else

{

//釋放所有的音頻緩沖塊

//如果文件句柄存在則關(guān)閉它

//結(jié)束對(duì)話(huà)方塊

}

return TRUE ;

}

break ;

}

return FALSE ;//返回假值

}

對(duì)于程序設(shè)計(jì)來(lái)說(shuō),最重要的就是邏輯。具體到這個(gè)播放器,就是各個(gè)模塊的邏輯以及它們之間的聯(lián)系。比如,按下打開(kāi)按鈕時(shí),彈出打開(kāi)文件對(duì)話(huà)框,然后讀取文件名,打開(kāi)設(shè)備,鎖定緩沖,再進(jìn)行播放,然后循環(huán),直到所有文件播放完畢。除了各個(gè)模塊自身的消息外,這個(gè)程序設(shè)計(jì)了一個(gè)自定義消息WM_WAVEPLAY,利用它對(duì)上一首、下一首、單次循環(huán)、全部循環(huán)、停止等按鈕消息進(jìn)行處理,這就大大縮減了代碼,使邏輯結(jié)構(gòu)更加清晰。邏輯搞清楚了,接下來(lái)就是最后一步了。將各個(gè)模塊的代碼填充完整,這個(gè)程序就基本完工了,剩下的就是調(diào)試工作了。

不過(guò)這里還有兩個(gè)問(wèn)題需要注意,一個(gè)是打開(kāi)音頻設(shè)備要用回調(diào)函數(shù)處理,另一個(gè)就是多線(xiàn)程技術(shù)。首先說(shuō)一下打開(kāi)音頻設(shè)備的問(wèn)題,請(qǐng)看一看上面的紅色代碼:

if(waveOutOpen(&(params.hWaveOut), WAVE_MAPPER, &wfx, (DWORD)waveOutProc,

(DWORD)&waveFreeBlockCount, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)

{

//顯示錯(cuò)誤信息

return TRUE ;

}waveOutProc就是回調(diào)函數(shù)的名稱(chēng),waveFreeBlockCount就是傳給它的參數(shù),CALLBACK_FUNCTION指明使用回調(diào)函數(shù)處理。回調(diào)函數(shù)的名稱(chēng)可以自定義,但是格式卻必須如下:static void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1,DWORD dwParam2 )

{

//處理音頻設(shè)備播放時(shí)的各種消息

return ;

}

為什么要在回調(diào)函數(shù)中處理設(shè)備消息?這是因?yàn)榉乐乖O(shè)備消息會(huì)干擾到程序與外界的交互消息,比如設(shè)備在播放文件時(shí),程序也許會(huì)收到用戶(hù)輸入的消息,如果同時(shí)處理設(shè)備消息,這時(shí)就有可能會(huì)導(dǎo)致故障,而用回調(diào)函數(shù)就不會(huì)出現(xiàn)這種狀況,因?yàn)樗窃诹硪痪€(xiàn)程中處理消息。

這個(gè)播放器還必須使用多線(xiàn)程技術(shù),因?yàn)椴シ盼募r(shí)需要不停讀音頻緩沖,這會(huì)導(dǎo)致界面暫時(shí)卡死(即不能與用戶(hù)進(jìn)行交互),只能等待播放完畢。怎么解決呢?用一個(gè)線(xiàn)程專(zhuān)門(mén)進(jìn)行音頻數(shù)據(jù)的緩沖與播放,而主線(xiàn)程用于各種用戶(hù)消息的處理。請(qǐng)看代碼:

#include //包含多線(xiàn)程處理頭文件

VOID bufThread(PVOID pvoid) ;//聲明音頻緩沖線(xiàn)程函數(shù)

_beginthread(bufThread,0,&params) ;//開(kāi)啟音頻緩沖線(xiàn)程

//定義音頻緩沖線(xiàn)程函數(shù)

VOID bufThread(PVOID pvoid)

{

DWORD readBytes ;//定義一個(gè)儲(chǔ)存讀取文件字節(jié)數(shù)的DWORD變量

char buffer[BLOCK_SIZE] = {'\0'} ; /* 定義一個(gè)臨時(shí)緩沖 */

volatile PPARAMS pparams ;//定義一個(gè)參數(shù)結(jié)構(gòu)指針

waveFreeBlockCount = BLOCK_COUNT; //設(shè)置空閑緩沖塊的總數(shù)量

waveCurrentBlock= 0;//設(shè)置當(dāng)前緩沖塊為第一塊

pparams = (PPARAMS)pvoid ;//給參數(shù)結(jié)構(gòu)指針賦值

if(pparams->bShutoff)//判斷線(xiàn)程關(guān)閉條件

return ;

//移動(dòng)文件指針到音頻數(shù)據(jù)起始地址

if(INVALID_SET_FILE_POINTER == SetFilePointer(pparams->hFile,

pparams->iCount,NULL,FILE_BEGIN))

{

MessageBox(NULL,TEXT("指針神經(jīng)病!"),

TEXT("提示"),MB_OK | MB_ICONWARNING);

return ;

}

//在循環(huán)中讀取音頻數(shù)據(jù)到臨時(shí)緩沖,再寫(xiě)入波形設(shè)備

while(!pparams->bShutoff) //判斷線(xiàn)程關(guān)閉條件

{

//讀取數(shù)據(jù)到臨時(shí)緩沖

if(!ReadFile(pparams->hFile, buffer, sizeof(buffer), &readBytes, NULL))

break ;

//如果數(shù)據(jù)為零則退出循環(huán)

if(readBytes == 0)

break;

//如果讀取的結(jié)果小于臨時(shí)緩沖,則填入0補(bǔ)充完整

if(readBytes < sizeof(buffer))

memset(buffer + readBytes, 0, sizeof(buffer) - readBytes);

//將音頻數(shù)據(jù)寫(xiě)入波形設(shè)備進(jìn)行播放

writeAudio(pparams->hWaveOut, buffer,sizeof(buffer));

}

//關(guān)閉文件

CloseHandle(pparams->hFile);

if(pparams->bShutoff)//判斷線(xiàn)程關(guān)閉條件

return ;

//如果線(xiàn)程關(guān)閉條件為假且空閑緩沖塊數(shù)量小于全部緩沖塊數(shù)量則等待

while(!pparams->bShutoff && waveFreeBlockCount < BLOCK_COUNT)

Sleep(0) ;//線(xiàn)程交出自己的時(shí)間片段給別的線(xiàn)程

if(!pparams->bShutoff)//如果線(xiàn)程關(guān)閉條件為假則發(fā)送用戶(hù)自定義消息

PostMessage(pparams->hwnd,WM_WAVEPLAY,0,0) ;

return ;

}

在建立多執(zhí)行緒的 Windows 程式時(shí),需要在「Project Settings」對(duì)話(huà)方塊中做一些修改。選擇「C/C++」頁(yè)面標(biāo)簽,然後在「Category」下拉式清單方塊中選擇「Code Generation」。在「Use Run-Time Library」下拉式清單方塊中,可以看到用於「Release」設(shè)定的「Single-Threaded」和用於 Debug 設(shè)定的「Debug Single-Threaded」。將這些分別改為「Multithreaded」和「Debug Multithreaded」。這將把編譯器旗標(biāo)改為/MT,它是編譯器在編譯多執(zhí)行緒的應(yīng)用程式所需要的。 具體地說(shuō), 編譯器將在.OBJ 檔案中插入 LIBCMT.LIB 檔案名,而不是 LIBC.LIB。連結(jié)程式使用這個(gè)名稱(chēng)與執(zhí)行期程式庫(kù)函式連結(jié)。 LIBC.LIB 和 LIBCMT.LIB 檔案包含 C 語(yǔ)言程式庫(kù)函式, 有些 C 語(yǔ)言程式庫(kù)函式包含靜態(tài)資料。例如,由於 strtok 函式可能被連續(xù)地多次呼叫,所以它在靜態(tài)記憶體中儲(chǔ)存了一個(gè)指標(biāo)。在多執(zhí)行緒程式中,每個(gè)執(zhí)行緒必須在 strtok 函式中有它自己的靜態(tài)指標(biāo)。因此,這個(gè)函式的多執(zhí)行緒版本稍微不同於單執(zhí)行緒的 strtok 函式。 同時(shí)請(qǐng)注意,必須包含表頭檔案 PROCESS.H,這個(gè)檔案定義一個(gè)名為_(kāi)beginthread 的函式,它啟動(dòng)一個(gè)新的執(zhí)行緒。只有定義了_MT 識(shí)別字,才會(huì)宣告這個(gè)函式,這是/MT 旗標(biāo)的另一個(gè)結(jié)果。下面簡(jiǎn)單介紹一下_beginthread函數(shù):

beginthreaduintptr_t _beginthread(

void( *start_address )( void * ),

unsigned stack_size,

void *arglist

);

Parameters 參數(shù):

start_address:程序執(zhí)行一個(gè)新線(xiàn)程的起始地址,即線(xiàn)程函數(shù)的名稱(chēng)。

Start address of a routine that begins execution of a new thread. For _beginthread, the calling convention is either __cdecl or __clrcall; for _beginthreadex, it is either __stdcall or __clrcall.

stack_size:新線(xiàn)程的堆棧大小或0值。

Stack size for a new thread or 0.

Arglist:傳給新線(xiàn)程的變量清單或空值。

Argument list to be passed to a new thread or NULL.

Return Value 返回值:

如果新線(xiàn)程建立成功,函數(shù)返回該線(xiàn)程的句柄;然而,如果新線(xiàn)程退出太快,_beginthread函數(shù)可能返回一個(gè)有誤的句柄。_beginthread發(fā)生錯(cuò)誤時(shí)返回1L。

在使用多線(xiàn)程時(shí),還需注意共享變量的互斥,這里利用了臨界區(qū)域的技術(shù)。這種臨界區(qū)域技術(shù)專(zhuān)用于多線(xiàn)程中共享變量的互斥使用,在任何時(shí)刻,只有一個(gè)執(zhí)行緒能擁有一個(gè)臨界區(qū)域。因此,一個(gè)執(zhí)行緒可以進(jìn)入一個(gè)臨界區(qū)域,設(shè)定一個(gè)變量,然後退出臨界區(qū)域。另一個(gè)使用該變量的執(zhí)行緒在存取變量中的項(xiàng)目之前也要先進(jìn)入該臨界區(qū)域,然後再退出臨界區(qū)域。請(qǐng)看代碼:

static CRITICAL_SECTION waveCriticalSection;//定義一個(gè)臨界區(qū)域

InitializeCriticalSection(&waveCriticalSection);//初始化臨界區(qū)域

EnterCriticalSection(&waveCriticalSection);//進(jìn)行臨界區(qū)域

(*freeBlockCounter)++;//設(shè)定變量

LeaveCriticalSection(&waveCriticalSection);//退出臨界區(qū)域

DeleteCriticalSection(&waveCriticalSection);//刪除臨界區(qū)域

注意,您可以定義多個(gè)臨界區(qū)域物件,比如 cs1 和 cs2。例如,如果一個(gè)程式有四個(gè)執(zhí)行緒,而前兩個(gè)執(zhí)行緒共用一些資料,那么它們可以使用一個(gè)臨界區(qū)域物件,而另外兩個(gè)執(zhí)行緒共用一些其他的資料,那么它們可以使用另一個(gè)臨界區(qū)域物件。 您在主執(zhí)行緒中使用臨界區(qū)域時(shí)應(yīng)該小心,如果從屬執(zhí)行緒在它自己的臨界區(qū)域中花費(fèi)了一段很長(zhǎng)的時(shí)間,那么它可能會(huì)將主執(zhí)行緒的執(zhí)行阻礙很長(zhǎng)一段時(shí)間。

至此播放器就順利地誕生了,盡管它還比較粗糙,但各項(xiàng)功能還算完備。不過(guò),請(qǐng)注意此播放器只能播放wave文件,不支持其它類(lèi)型的文件。下面就是完整代碼的附件,有需要的就請(qǐng)下載。http://download.csdn.net/detail/dnfyg_000/4976055

總結(jié)

以上是生活随笔為你收集整理的C语言里的out函数,c语言 vc 用waveout函数写wave文件播放器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。