谁能帮我实现WaveOut的循环播放和停止播放功能?有代码,不懂WaveOut也可以过来学习一下。

away5678 2010-09-29 09:44:19
目前情况:
播放完后就自己退出了。

要求:
加入循环开关和停止开关,以及音量控制。
觉得写得不好的,也可以帮忙优化。
十分感谢~~

没办法,我最高只有100分了。。
环境为Win32,最终运行环境为WinCE
代码如下:

播放的音频文件路径由参数输入。
运行前加入winmm.lib

#include "stdafx.h"
#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>

/*
* some good values for block size and count
*/
#define BLOCK_SIZE 1024*8
#define BLOCK_COUNT 20
/*
* function prototypes
*/
static void CALLBACK waveOutProc(HWAVEOUT, UINT, DWORD, DWORD, DWORD);
static WAVEHDR* allocateBlocks(int size, int count);
static void freeBlocks(WAVEHDR* blockArray);
static void writeAudio(HWAVEOUT hWaveOut, LPSTR data, int size);
/*
* module level variables
*/
static CRITICAL_SECTION waveCriticalSection;
static WAVEHDR* waveBlocks;
static volatile int waveFreeBlockCount;
static int waveCurrentBlock;

int _tmain(int argc, _TCHAR* argv[])
{
HWAVEOUT hWaveOut; /* device handle */
HANDLE hFile;/* file handle */
WAVEFORMATEX wfx; /* look this up in your documentation */
char buffer[1024]; /* intermediate buffer for reading */
int i;
/*
* quick argument check
*/
if(argc != 2) {
fprintf(stderr, "usage: %s \n", argv[0]);
ExitProcess(1);
}
/*
* initialise the module variables
*/
waveBlocks = allocateBlocks(BLOCK_SIZE, BLOCK_COUNT);
waveFreeBlockCount = BLOCK_COUNT;
waveCurrentBlock= 0;
InitializeCriticalSection(&waveCriticalSection);

//printf(argv[1]);
/*
* try and open the file
*/
if((hFile = CreateFile(
argv[1],
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL )) == INVALID_HANDLE_VALUE) {

fprintf(stderr, "%s: unable to open file '%s'\n", argv[0], argv[1]);
ExitProcess(1);
}
/*
* set up the WAVEFORMATEX structure.
*/
wfx.nSamplesPerSec = 22050; /* sample rate */
wfx.wBitsPerSample = 16; /* sample size */
wfx.nChannels= 2; /* channels*/
//wfx.nAvgBytesPerSec
wfx.cbSize = 0; /* size of _extra_ info */
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) >> 3;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
/*
* try to open the default wave device. WAVE_MAPPER is
* a constant defined in mmsystem.h, it always points to the
* default wave device on the system (some people have 2 or
* more sound cards).
*/
if(waveOutOpen(
&hWaveOut,
WAVE_MAPPER,
&wfx,
(DWORD_PTR)waveOutProc,
(DWORD_PTR)&waveFreeBlockCount,
CALLBACK_FUNCTION
) != MMSYSERR_NOERROR) {
fprintf(stderr, "%s: unable to open wave mapper device\n", argv[0]);
ExitProcess(1);
}
/*
* playback loop
*/
while(1) {
DWORD readBytes;
if(!ReadFile(hFile, buffer, sizeof(buffer), &readBytes, NULL))
break;
if(readBytes == 0)
break;
//printf("ReadFile_OK\n");
if(readBytes < sizeof(buffer)) {
printf("at end of buffer\n");
memset(buffer + readBytes, 0, sizeof(buffer) - readBytes);

}
writeAudio(hWaveOut, buffer, sizeof(buffer));
}
/*
* wait for all blocks to complete
*/
while(waveFreeBlockCount < BLOCK_COUNT)
Sleep(10);

/*
* unprepare any blocks that are still prepared
*/
for(i = 0; i < waveFreeBlockCount; i++)
if(waveBlocks[i].dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof(WAVEHDR));

DeleteCriticalSection(&waveCriticalSection);
freeBlocks(waveBlocks);
waveOutClose(hWaveOut);
CloseHandle(hFile);

system("pause");

return 0;
}


static void CALLBACK waveOutProc( HWAVEOUT hWaveOut,
UINT uMsg,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2 ) {

/*
* pointer to free block counter
*/
int* freeBlockCounter = (int*)dwInstance;
/*
* ignore calls that occur due to openining and closing the
* device.
*/
if(uMsg != WOM_DONE)
return;

EnterCriticalSection(&waveCriticalSection);
(*freeBlockCounter)++;
LeaveCriticalSection(&waveCriticalSection);

//WOM_CLOSE: 关闭wave-form设备
//WOM_DONE: wave数据播放完毕

}

static WAVEHDR* allocateBlocks(int size, int count)
{

unsigned char* buffer;
int i;
WAVEHDR* blocks;
DWORD totalBufferSize = (size + sizeof(WAVEHDR)) * count;
/*
* allocate memory for the entire set in one go
*/
if((buffer = (unsigned char*) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, totalBufferSize )) == NULL) {
fprintf(stderr, "Memory allocation error\n");
ExitProcess(1);
}
/*
* and set up the pointers to each bit
*/
blocks = (WAVEHDR*)buffer;
buffer += sizeof(WAVEHDR) * count;
for(i = 0; i < count; i++) {
blocks[i].dwBufferLength = size;
blocks[i].lpData = (LPSTR)(LPCTSTR)buffer;
buffer += size;
}
return blocks;

}

static void freeBlocks(WAVEHDR* blockArray)
{
/*
* and this is why allocateBlocks works the way it does
*/
HeapFree(GetProcessHeap(), 0, blockArray);
}

void writeAudio(HWAVEOUT hWaveOut, LPSTR data, int size)
{

WAVEHDR* current;
int remain;
current = &waveBlocks[waveCurrentBlock];
while(size > 0) {

/*
* first make sure the header we're going to use is unprepared
*/
if(current->dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR));

if(size < (int)(BLOCK_SIZE - current->dwUser)) {
memcpy(current->lpData + current->dwUser, data, size);
current->dwUser += size;
break;
}
remain = BLOCK_SIZE - current->dwUser;
memcpy(current->lpData + current->dwUser, data, remain);
size -= remain;
data += remain;
current->dwBufferLength = BLOCK_SIZE;
waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, current, sizeof(WAVEHDR));
EnterCriticalSection(&waveCriticalSection);
waveFreeBlockCount--;
LeaveCriticalSection(&waveCriticalSection);
/*
* wait for a block to become free
*/
while(!waveFreeBlockCount)
Sleep(10);

/*
* point to the next block
*/
waveCurrentBlock++;
waveCurrentBlock %= BLOCK_COUNT;
current = &waveBlocks[waveCurrentBlock];
current->dwUser = 0;

}

}
...全文
279 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
away5678 2010-09-30
  • 打赏
  • 举报
回复
LS的提示对我有点启发,我试试研究一下先~
zgl7903 2010-09-29
  • 打赏
  • 举报
回复
WAVEHDR 的标志可以试试看
dwFlags
Flags supplying information about the buffer. The following values are defined:
WHDR_BEGINLOOP
This buffer is the first buffer in a loop. This flag is used only with output buffers.
WHDR_ENDLOOP
This buffer is the last buffer in a loop. This flag is used only with output buffers.

dwLoops
Number of times to play the loop. This member is used only with output buffers.

Use the WHDR_BEGINLOOP and WHDR_ENDLOOP flags in the dwFlags member to specify the beginning and ending data blocks for looping. To loop on a single block, specify both flags for the same block. Use the dwLoops member in the WAVEHDR structure for the first block in the loop to specify the number of times to play the loop.
away5678 2010-09-29
  • 打赏
  • 举报
回复
呵呵。。。
感谢LS~
傻X 2010-09-29
  • 打赏
  • 举报
回复
我是来学习的

2,640

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧