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

[转自: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;
	}
}



你可能感兴趣的:(Windows音频编程:Win32 Wave API 的使用)