#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\n", 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*/
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\n", &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\n", 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.
Playback audio data from memory in windows
原文地址:http://blog.csdn.net/u013606170/article/details/44949447