多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > Playback audio data from memory in windows

Playback audio data from memory in windows

來源:程序員人生   發布時間:2015-08-25 08:49:23 閱讀次數:3663次

Continue previous article : Understand wave format, and implement a wave reader , In here , I will demonstrate how to play audio in windows.

(Zeroth are wave format, you could refer to previous article.)

First , the struct WAVEFORMATEX would be used, the members of WAVEFORMATEX are very explicit, I do not explain that.


Second, the structure WAVEHDR, which is for managing audio buffer. One should set audio buffer in the WAVEHDR structure  to require windows to play that audio.


The functions will be used:

waveOutOpen: open the audio output device for playback.
         The function  needs a HWAVEOUT as output.
         One should have set WAVEHDR to feed the waveOutOpen.
         The function needs to set a callback function, waveOutProc.
          
waveOutPrepareHeader/waveOutPrepareHeader:
        Set the the structure WAVEHDR be prepared/cleaned.

 waveOutWrite: Set the audio data to the audio output device.


To ensure the audio playback be smooth, it is necessary to use 2 block of buffer:
one for preparing, one for playing, in interleave form(very similar to producer consumer semaphores problem). In here, I use EnterCriticalSection/LeaveCriticalSection.



My code is below, the full code with previouse is too long, I omit the previous code:
The part should be inserted after the line


#define MAX_STR_LEN 256


#define KB (1024) #define SEND_SIZE (8*KB) #define BLOCK_SIZE (16*KB) #define BLOCK_COUNT (2) #include <windows.h> #include <Mmreg.h> CRITICAL_SECTION waveCriticalSection; WAVEFORMATEX wFmt; /*for debug, or the should not be global variable*/ void CALLBACK WaveOutProc( HWAVEOUT device, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ) { static unsigned int cnt = 0; DWORD *pFreeBlockCounter; pFreeBlockCounter = (DWORD*)(long long)dwInstance; switch(uMsg) { case WOM_DONE: printf("playing time = %1.3f s ", cnt*BLOCK_SIZE/(float)(wFmt.nAvgBytesPerSec)); cnt++; EnterCriticalSection(&waveCriticalSection); (*pFreeBlockCounter)++; LeaveCriticalSection(&waveCriticalSection); break; case WOM_OPEN: InitializeCriticalSection(&waveCriticalSection); break; case WOM_CLOSE: DeleteCriticalSection(&waveCriticalSection); break; }/*if uMsg == WOM_DONE*/ }/*WaveCallBack*/



Below code should be insert in front of the "return" line in main:


char *pAudioData; pAudioData = (char*)malloc(audioDataLen); fread(pAudioData, 1, audioDataLen, pWaveFile); fclose(pWaveFile); /*step 0, variables*/ MMRESULT ret; HWAVEOUT hDevice; int waveFreeBlockCount; WAVEHDR *pWaveHeaderWithBlock; int waveCurrentBlock; /*step 1: initialize */ hDevice = NULL; /*set WAVEFORMATEX*/ wFmt.wFormatTag = (WORD)WAVE_FORMAT_PCM; wFmt.nSamplesPerSec = (WORD)nSamplesPerSec; wFmt.wBitsPerSample = (WORD)bitsPerSample; wFmt.nChannels = (WORD)nChannel; wFmt.nBlockAlign = (WORD)(wFmt.nChannels*(bitsPerSample/8)); wFmt.nAvgBytesPerSec = wFmt.nSamplesPerSec* wFmt.nBlockAlign; wFmt.cbSize = 0; /*set up callback function to play audio*/ ret = waveOutOpen( &hDevice, WAVE_MAPPER, &wFmt, (DWORD_PTR)WaveOutProc, (DWORD_PTR)&waveFreeBlockCount, CALLBACK_FUNCTION); if(0 != ret) { char errStr[MAX_STR_LEN]; waveOutGetErrorText(ret, &errStr[0], MAX_STR_LEN); printf("error = %s ", &errStr[0]); goto Flag_end_main; }/*if */ /* * prepare and set up buffer for struct WAVEHDR use 2 buffer to load audio data in interleave form */ pWaveHeaderWithBlock = (WAVEHDR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (BLOCK_SIZE + sizeof(WAVEHDR)) * BLOCK_COUNT); if(NULL == pWaveHeaderWithBlock) goto Flag_end_main; WAVEHDR *pBlockHeader; pBlockHeader = (WAVEHDR*)pWaveHeaderWithBlock; for(int i = 0; i < BLOCK_COUNT; i++) { pBlockHeader[i].dwBufferLength = BLOCK_SIZE; pBlockHeader[i].lpData = (LPSTR)(pWaveHeaderWithBlock) + sizeof(WAVEHDR) * BLOCK_COUNT + i*BLOCK_SIZE; }/*for i*/ waveFreeBlockCount = BLOCK_COUNT; waveCurrentBlock = 0; if(NULL == pWaveHeaderWithBlock) goto Flag_end_main; unsigned int remainderLen; remainderLen = audioDataLen; char *pMovAudioData; pMovAudioData = pAudioData; pMovAudioData += (unsigned int)(nSamplesPerSec*nChannel*2); remainderLen -= (unsigned int)(nSamplesPerSec*nChannel*2); unsigned int cnt; cnt = 0; while(remainderLen > SEND_SIZE) { printf("send time = %1.3f s ", cnt*SEND_SIZE/((float)bytesPerSec) ); cnt++; /* * Step 3 play audio ! */ WAVEHDR* pCurrentWaveHeader; unsigned long remain; unsigned int size; char *pData; size = SEND_SIZE; pCurrentWaveHeader = &pWaveHeaderWithBlock[waveCurrentBlock]; pData = (char*)pMovAudioData; while(size > 0) { /* make sure the header we're going to use is unprepared cleans up the preparation */ if(WHDR_PREPARED & pCurrentWaveHeader->dwFlags) waveOutUnprepareHeader(hDevice, pCurrentWaveHeader, sizeof(WAVEHDR)); if(size < (int)(BLOCK_SIZE - pCurrentWaveHeader->dwUser)) { /* the buffer is enough, stow all data in current WAVEHDR's buffer. */ memcpy(pCurrentWaveHeader->lpData + pCurrentWaveHeader->dwUser, pData, size); pCurrentWaveHeader->dwUser += size; break; }/*if*/ /*the buffer would be full */ remain = BLOCK_SIZE - (unsigned long)pCurrentWaveHeader->dwUser; memcpy(pCurrentWaveHeader->lpData + pCurrentWaveHeader->dwUser, pData, remain); /*remaining would be stowed in the other WAVEHDR, note the size here */ size -= remain; pData += remain; /*full size of the WAVEHDR's buffer is BLOCK_SIZE */ pCurrentWaveHeader->dwBufferLength = BLOCK_SIZE; /*preparation...*/ waveOutPrepareHeader(hDevice, pCurrentWaveHeader, sizeof(WAVEHDR)); /*write the data to audio device */ waveOutWrite(hDevice, pCurrentWaveHeader, sizeof(WAVEHDR)); /* the data or previous data is under playing assure the counter waveFreeBlockCount would not be disorder */ EnterCriticalSection(&waveCriticalSection); waveFreeBlockCount--; LeaveCriticalSection(&waveCriticalSection); /* * wait for there is block in free */ while(0 == waveFreeBlockCount) Sleep(5); /* * point to the next block */ waveCurrentBlock++; waveCurrentBlock %= BLOCK_COUNT; pCurrentWaveHeader = &pWaveHeaderWithBlock[waveCurrentBlock]; pCurrentWaveHeader->dwUser = 0; }/*while*/ pMovAudioData += SEND_SIZE; remainderLen -= SEND_SIZE; }/*while remainderLen > SEND_SIZE*/ //SendAudioBuf(pMovAudioData, remainderLen); Flag_end_main: for(int i = 0; i < waveFreeBlockCount; i++){ if(NULL != pWaveHeaderWithBlock) { if(pWaveHeaderWithBlock[i].dwFlags & WHDR_PREPARED) waveOutUnprepareHeader(hDevice, &pWaveHeaderWithBlock[i], sizeof(WAVEHDR)); }/*if*/ pWaveHeaderWithBlock = NULL; }/*for i waveFreeBlockCount*/ if(NULL != hDevice) waveOutClose(hDevice); hDevice = NULL; if(NULL != pWaveHeaderWithBlock) HeapFree(GetProcessHeap(), 0, pWaveHeaderWithBlock); pWaveHeaderWithBlock = NULL;



Now, you have a hand-made wave player in windows.

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 亚洲在线第一页 | 免费观看性行为的视频网站 | 亚洲精品亚洲人成毛片不卡 | 亚洲综合片 | 国产永久免费视频 | 日韩乱码视频 | 中文字幕亚洲欧美 | ccav在线永久免费看 | 国产一区三区二区中文在线 | 亚洲福利在线看 | 69热视频| 在线播放免费人成毛片乱码 | 色中色资源站 | 精品精品国产高清a毛片牛牛 | 国产香蕉一区二区在线观看 | 一级女性全黄生活片免费看 | 欧美一区二区三区播放 | 国产中文字幕在线 | 羞羞动漫入口 | 手机看片福利在线 | 小说图片亚洲 | 2022国产精品网站在线播放 | 久伊人| 国产成人a一在线观看 | 国产精品视频视频久久 | 亚洲小说春色综合另类网蜜桃 | 一区二区三区四区在线播放 | 日本一区二区三区在线观看视频 | 一二三四在线播放免费观看中文版视频 | 开心丁香婷婷深爱五月 | 久久综合九色综合桃花 | 噜噜噜在线视频免费观看 | 成人影院一区二区三区 | 亚洲经典自拍 | ak福利午夜在线观看 | 欧美性精品videofree | 国产精品亚洲午夜一区二区三区 | 欧美xxxx性free| 国99久9在线 | 免费 | 欧美wwwxxxx| haose16在线永久免费 |