//Windows音频编程:Win32 Wave API 的使用
//下面是一个Win32控制台程序的源码,环境VS2008,新建一个空的Win32控制台项目,加入此文件编译即可,功能为录制5秒并回放。注意不要选择Unicode字符集,不然设备名会出现乱码。
//
// WaveAPI.cpp
//
// by: 知秋一叶
//
// 转载:http://blog.csdn.net/zhi_qiu_yi_ye/article/details/6663366
#include <windows.h>
#include <stdio.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;
}
}