您的位置:首页 > 编程语言

Windows音频编程:Win32 Wave API 的使用

2012-10-26 11:14 801 查看
[转自:http://blog.csdn.net/zhi_qiu_yi_ye/article/details/6663366]

使用 Wave API 进行Windows音频编程可以保持很大的自由度,而且与Linux中的OSS编程模式很像。下面我简单介绍函数的调用顺序,具体的用法参见MSDN(VS2008)。

录音:

waveInOpen -> waveInPrepareHeader -> waveInAddBuffer -> waveInStart -> waveInStop -> waveInReset ->waveInUnprepareHeader -> waveInClose

录音的回调函数只需要处理WIM_DATA消息,拷贝数据及重新调用waveInAddBuffer将此缓存加入队列。

放音:

waveOutOpen -> waveOutPrepareHeader -> waveOutWrite -> waveOutReset -> waveOutUnprepareHeader -> waveOutClose

下面是一个Win32控制台程序的源码,环境VS2008,新建一个空的Win32控制台项目,加入此文件编译即可,功能为录制5秒并回放。注意不要选择Unicode字符集,不然设备名会出现乱码。

#include "stdafx.h"

//
//	WaveAPI.cpp
//
// by: 知秋一叶
//

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")

#define BUFFER_SIZE (44100*16*2/8*5)	// 录制声音长度
#define FRAGMENT_SIZE 1024				// 缓存区大小
#define FRAGMENT_NUM 4					// 缓存区个数

static unsigned char buffer[BUFFER_SIZE] = {0};
static int buf_count = 0;

// 函数定义
void CALLBACK waveInProc(HWAVEIN hwi,
UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2     );
void CALLBACK waveOutProc(  HWAVEOUT hwo,
UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2     );

// 入口
int main()
{
/* 录音 */

// Device
int nReturn = waveInGetNumDevs();
printf("输入设备数目:%d\n", nReturn);
for (int i=0; i<nReturn; i++)
{
WAVEINCAPS wic;
waveInGetDevCaps(i, &wic, sizeof(WAVEINCAPS));
printf("#%d\t设备名:%s\n", i, wic.szPname);
}

// open
HWAVEIN hWaveIn;
WAVEFORMATEX wavform;
wavform.wFormatTag = WAVE_FORMAT_PCM;
wavform.nChannels = 2;
wavform.nSamplesPerSec = 44100;
wavform.nAvgBytesPerSec = 44100*16*2/8;
wavform.nBlockAlign = 4;
wavform.wBitsPerSample = 16;
wavform.cbSize = 0;

waveInOpen(&hWaveIn, WAVE_MAPPER, &wavform, (DWORD_PTR)waveInProc, 0, CALLBACK_FUNCTION);

WAVEINCAPS wic;
waveInGetDevCaps((UINT_PTR)hWaveIn, &wic, sizeof(WAVEINCAPS));
printf("打开的输入设备:%s\n", wic.szPname);

// prepare buffer
static WAVEHDR wh[FRAGMENT_NUM];
for (int i=0; i<FRAGMENT_NUM; i++)
{
wh[i].lpData = new char[FRAGMENT_SIZE];
wh[i].dwBufferLength = FRAGMENT_SIZE;
wh[i].dwBytesRecorded = 0;
wh[i].dwUser = NULL;
wh[i].dwFlags = 0;
wh[i].dwLoops = 1;
wh[i].lpNext = NULL;
wh[i].reserved = 0;

waveInPrepareHeader(hWaveIn, &wh[i], sizeof(WAVEHDR));
waveInAddBuffer(hWaveIn, &wh[i], sizeof(WAVEHDR));
}

// record
printf("Start to Record...\n");

buf_count = 0;
waveInStart(hWaveIn);

while (buf_count < BUFFER_SIZE)
{
Sleep(1);
}

printf("Record Over!\n\n");

// clean
waveInStop(hWaveIn);
waveInReset(hWaveIn);
for (int i=0; i<FRAGMENT_NUM; i++)
{
waveInUnprepareHeader(hWaveIn, &wh[i], sizeof(WAVEHDR));
delete wh[i].lpData;
}
waveInClose(hWaveIn);

system("pause");
printf("\n");

/* 放音 */

// Device
nReturn = waveOutGetNumDevs();
printf("\n输出设备数目:%d\n", nReturn);
for (int i=0; i<nReturn; i++)
{
WAVEOUTCAPS woc;
waveOutGetDevCaps(i, &woc, sizeof(WAVEOUTCAPS));
printf("#%d\t设备名:%s\n", i, wic.szPname);
}

// open
HWAVEOUT hWaveOut;
waveOutOpen(&hWaveOut, WAVE_MAPPER, &wavform, (DWORD_PTR)waveOutProc, 0, CALLBACK_FUNCTION);

WAVEOUTCAPS woc;
waveOutGetDevCaps((UINT_PTR)hWaveOut, &woc, sizeof(WAVEOUTCAPS));
printf("打开的输出设备:%s\n", wic.szPname);

// prepare buffer
WAVEHDR wavhdr;
wavhdr.lpData = (LPSTR)buffer;
wavhdr.dwBufferLength = BUFFER_SIZE;
wavhdr.dwFlags = 0;
wavhdr.dwLoops = 0;

waveOutPrepareHeader(hWaveOut, &wavhdr, sizeof(WAVEHDR));

// play
printf("Start to Play...\n");

buf_count = 0;
waveOutWrite(hWaveOut, &wavhdr, sizeof(WAVEHDR));
while (buf_count < BUFFER_SIZE)
{
Sleep(1);
}

// clean
waveOutReset(hWaveOut);
waveOutUnprepareHeader(hWaveOut, &wavhdr, sizeof(WAVEHDR));
waveOutClose(hWaveOut);

printf("Play Over!\n\n");

return 0;
}

// 录音回调函数
void CALLBACK waveInProc(HWAVEIN hwi,
UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2     )
{
LPWAVEHDR pwh = (LPWAVEHDR)dwParam1;

if ((WIM_DATA==uMsg) && (buf_count<BUFFER_SIZE))
{
int temp = BUFFER_SIZE - buf_count;
temp = (temp>pwh->dwBytesRecorded) ? pwh->dwBytesRecorded : temp;
memcpy(buffer+buf_count, pwh->lpData, temp);
buf_count += temp;

waveInAddBuffer(hwi, pwh, sizeof(WAVEHDR));
}
}

// 放音回调函数
void CALLBACK waveOutProc(  HWAVEOUT hwo,
UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2     )
{
if (WOM_DONE == uMsg)
{
buf_count = BUFFER_SIZE;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: