1、先设置wavein和waveout参数:采样率、数据位数、通道数、数据格式等参数,然后建立wavein和waveout的回调函数,代码如下:
wfx.nSamplesPerSec = 8000;
wfx.wBitsPerSample = 16;
wfx.nChannels= 1;
wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = (wfx.wBitsPerSample *
wfx.nChannels) >> 3;
wfx.nAvgBytesPerSec = wfx.nBlockAlign *
wfx.nSamplesPerSec;
waveFreeBlockCount_IN = 5;
if(waveInOpen(&hWaveIn,
WAVE_MAPPER, &wfx, (DWORD_PTR)waveInProc,
(DWORD_PTR)&waveFreeBlockCount_IN,
CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
{
ExitProcess(1);
}
waveBlocks = allocateBlocks(BLOCK_SIZE,
BLOCK_COUNT);
waveFreeBlockCount = BLOCK_COUNT;
waveCurrentBlock= 0;
InitializeCriticalSection(&waveCriticalSection);
wfx.nSamplesPerSec = 8000;
wfx.wBitsPerSample = 16;
wfx.nChannels= 1;
wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = (wfx.wBitsPerSample *
wfx.nChannels) >> 3;
wfx.nAvgBytesPerSec = wfx.nBlockAlign *
wfx.nSamplesPerSec;
if(waveOutOpen(&hWaveOut,
WAVE_MAPPER, &wfx, (DWORD_PTR)waveOutProc,
(DWORD_PTR)&waveFreeBlockCount, CALLBACK_FUNCTION)
!= MMSYSERR_NOERROR)
{
ExitProcess(1);
}
//建立两个数组(这里可以建立多个数组)用来缓冲音频数据
//DWORD bufsize = 2 * 1024;
DWORD bufsize = 1985*2;
pBuffer1 = new
BYTE[bufsize];
pBuffer2 = new BYTE[bufsize];
pBuffer3 = new
BYTE[bufsize];
pBuffer4 = new BYTE[bufsize];
pBuffer5 = new BYTE[bufsize];
//将建立好的wHdr1做为备用
wHdr1.lpData =
(LPSTR)pBuffer1;
wHdr1.dwBufferLength =
bufsize;
wHdr1.dwBytesRecorded =
0;
wHdr1.dwUser = 0;
wHdr1.dwFlags = 0;
wHdr1.dwLoops = 1;
wHdr1.lpNext = NULL;
wHdr1.reserved = 0;
waveInPrepareHeader(hWaveIn,&wHdr1,sizeof(WAVEHDR));
//将建立好的wHdr2做为备用
wHdr2.lpData =
(LPSTR)pBuffer2;
wHdr2.dwBufferLength =
bufsize;
wHdr2.dwBytesRecorded =
0;
wHdr2.dwUser = 0;
wHdr2.dwFlags = 0;
wHdr2.dwLoops = 1;
wHdr2.lpNext = NULL;
wHdr2.reserved =
0;
waveInPrepareHeader(hWaveIn,&wHdr2,sizeof(WAVEHDR));
//将建立好的wHdr3做为备用
wHdr3.lpData =
(LPSTR)pBuffer3;
wHdr3.dwBufferLength =
bufsize;
wHdr3.dwBytesRecorded =
0;
wHdr3.dwUser = 0;
wHdr3.dwFlags = 0;
wHdr3.dwLoops = 1;
wHdr3.lpNext = NULL;
wHdr3.reserved =
0;
waveInPrepareHeader(hWaveIn,&wHdr3,sizeof(WAVEHDR));
//将建立好的wHdr4做为备用
wHdr4.lpData =
(LPSTR)pBuffer4;
wHdr4.dwBufferLength =
bufsize;
wHdr4.dwBytesRecorded =
0;
wHdr4.dwUser = 0;
wHdr4.dwFlags = 0;
wHdr4.dwLoops = 1;
wHdr4.lpNext = NULL;
wHdr4.reserved =
0;
waveInPrepareHeader(hWaveIn,&wHdr4,sizeof(WAVEHDR));
//将建立好的wHdr5做为备用
wHdr5.lpData =
(LPSTR)pBuffer5;
wHdr5.dwBufferLength =
bufsize;
wHdr5.dwBytesRecorded =
0;
wHdr5.dwUser = 0;
wHdr5.dwFlags = 0;
wHdr5.dwLoops = 1;
wHdr5.lpNext = NULL;
wHdr5.reserved = 0;
waveInPrepareHeader(hWaveIn,&wHdr5,sizeof(WAVEHDR));
//将两个wHdr添加到waveIn中去
waveInAddBuffer (hWaveIn, &wHdr1,
sizeof (WAVEHDR)) ;
waveInAddBuffer (hWaveIn, &wHdr2,
sizeof (WAVEHDR)) ;
waveInAddBuffer (hWaveIn, &wHdr3,
sizeof (WAVEHDR)) ;
waveInAddBuffer (hWaveIn, &wHdr4,
sizeof (WAVEHDR)) ;
waveInAddBuffer (hWaveIn, &wHdr5,
sizeof (WAVEHDR)) ;
//开始音频采集
UDP_Decode_num = 1;
Stop_Mic_Data_Flag = 0;
MIC_Receive_Flag = 1;
Code_Data_Flag_A = 0;
Code_Data_Flag_B = 0;
Code_Data_Flag_C = 0;
Code_Data_Flag_D = 0;
Code_Data_Flag_E = 0;
waveInStart(hWaveIn); //启动语音采集
2、wavein和waveout回调函数
static void CALLBACK waveInProc(HWAVEIN hWaveIn,UINT uMsg,DWORD
dwInstance,DWORD dwParam1,DWORD dwParam2)
{
//这个CIMAADPCMDlg就是你的音频采集类
//CPCM_PLAYDlg *pWnd =
(CPCM_PLAYDlg*)dwInstance;
int re(0);
switch(uMsg)
{
case
WIM_OPEN:
TRACE("WIM_OPEN\n");
break;
case
WIM_DATA:
//TRACE("WIM_DATA\n");
//这里就是对采集到的数据做处理的地方,我是做了发送处理
//((PWAVEHDR)dwParam1)->lpData这就是采集到的数据指针
//((PWAVEHDR)dwParam1)->dwBytesRecorded这就是采集到的数据长度
//re =
send(pWnd->sends,((PWAVEHDR)dwParam1)->lpData,((PWAVEHDR)dwParam1)->dwBytesRecorded,0);
//处理完了之后还要再把这个缓冲数组加回去
if(Code_Data_Flag_A
== 0 && MIC_Receive_Flag ==
1)
{
BUF1
= ((PWAVEHDR)dwParam1)->lpData;
MIC_Receive_Num
= ((PWAVEHDR)dwParam1)->dwBytesRecorded;
MIC_Receive_Flag
= 2;
Code_Data_Flag_A
= 1;
}
else
if(Code_Data_Flag_B == 0 &&
MIC_Receive_Flag == 2)
{
BUF2
= ((PWAVEHDR)dwParam1)->lpData;
MIC_Receive_Num
= ((PWAVEHDR)dwParam1)->dwBytesRecorded;
MIC_Receive_Flag
= 3;
Code_Data_Flag_B
= 1;
}
else
if(Code_Data_Flag_C == 0 &&
MIC_Receive_Flag == 3)
{
BUF3
= ((PWAVEHDR)dwParam1)->lpData;
MIC_Receive_Num
= ((PWAVEHDR)dwParam1)->dwBytesRecorded;
MIC_Receive_Flag
= 4;
Code_Data_Flag_C
= 1;
}
else
if(Code_Data_Flag_C == 0 &&
MIC_Receive_Flag == 4)
{
BUF4
= ((PWAVEHDR)dwParam1)->lpData;
MIC_Receive_Num
= ((PWAVEHDR)dwParam1)->dwBytesRecorded;
MIC_Receive_Flag
= 5;
Code_Data_Flag_D
= 1;
}
else
if(Code_Data_Flag_C == 0 &&
MIC_Receive_Flag == 5)
{
BUF5
= ((PWAVEHDR)dwParam1)->lpData;
MIC_Receive_Num
= ((PWAVEHDR)dwParam1)->dwBytesRecorded;
MIC_Receive_Flag
= 1;
Code_Data_Flag_E
= 1;
}
//BUF1 =
((PWAVEHDR)dwParam1)->lpData;
//MIC_Receive_Num
= ((PWAVEHDR)dwParam1)->dwBytesRecorded;
//MIC_Receive_Flag
= 1;
//Stop_Mic_Data_Flag代表是否继续采集,因为当停止采集的时候,只有当所有的
//缓冲数组都腾出来之后才能close,所以需要停止采集时就不要再waveInAddBuffer了
if(Stop_Mic_Data_Flag
== 0)
{
waveInPrepareHeader(hWaveIn,
(PWAVEHDR) dwParam1, sizeof (WAVEHDR));
waveInAddBuffer
(hWaveIn, (PWAVEHDR) dwParam1, sizeof (WAVEHDR)) ;
//TRACE("%d\n",Stop_Mic_Data_Flag);
}
break;
case
WIM_CLOSE:
TRACE("WIM_CLOSE\n");
break;
default:
break;
}
}
static void CALLBACK waveOutProc(HWAVEOUT hWaveOut,UINT
uMsg,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2)
{
int* freeBlockCounter = (int*)dwInstance;
if(uMsg != WOM_DONE)
return;
EnterCriticalSection(&waveCriticalSection);
(*freeBlockCounter)++;
LeaveCriticalSection(&waveCriticalSection);
}
void writeAudio(HWAVEOUT hWaveOut,LPSTR data, int size)
{
WAVEHDR* current;
int remain;
current =
&waveBlocks[waveCurrentBlock];
while(size > 0)
{
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 -
(int)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);
while(!waveFreeBlockCount)
{
Sleep(10);
}
waveCurrentBlock++;
waveCurrentBlock %=
BLOCK_COUNT;
current =
&waveBlocks[waveCurrentBlock];
current->dwUser
= 0;
}
}
WAVEHDR* allocateBlocks(int size, int count)
{
unsigned char* buffer;
int i;
WAVEHDR* blocks;
DWORD totalBufferSize = (size + sizeof(WAVEHDR))
* count;
if((buffer = (unsigned
char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
totalBufferSize)) == NULL)
{
fprintf(stderr, "Memory
allocationerror\n");
ExitProcess(1);
}
blocks = (WAVEHDR*)buffer;
buffer += sizeof(WAVEHDR) * count;
for(i = 0; i < count; i++)
{
blocks[i].dwBufferLength =
size;
blocks[i].lpData =
(LPSTR)buffer;
buffer += size;
}
return blocks;
}
void freeBlocks(WAVEHDR* blockArray)
{
HeapFree(GetProcessHeap(), 0, blockArray);
}
3、变量定义
#define BLOCK_SIZE 20480
#define BLOCK_COUNT 20
//WAVEHDR waveHeader1,waveHeader2;
BYTE
*pBuffer1,*pBuffer2,*pBuffer3,*pBuffer4,*pBuffer5;//采集音频时的数据缓存
WAVEHDR wHdr1,wHdr2,wHdr3,wHdr4,wHdr5;
//采集音频时包含数据缓存的结构体
int Stop_Mic_Data_Flag;
int MIC_Receive_Flag;
int MIC_Receive_Num;
LPSTR BUF1 =
(char*)malloc(4000);
LPSTR BUF2 =
(char*)malloc(4000);
LPSTR BUF3 =
(char*)malloc(4000);
LPSTR BUF4 =
(char*)malloc(4000);
LPSTR BUF5 =
(char*)malloc(4000);
WAVEFORMATEX waveFormat;
WAVEOUTCAPS pwoc;
HWAVEOUT hWaveOut;
HWAVEIN hWaveIn;
WAVEFORMATEX * lpFormat;
WAVEFORMATEX wfx;
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
LPSTR loadAudioBlock(LPCWSTR filename, DWORD* blockSize);
void writeAudioBlock(HWAVEOUT hWaveOut , LPSTR block, DWORD
size);
//消息回掉函数
static void CALLBACK waveOutProc(HWAVEOUT, UINT, DWORD, DWORD,
DWORD);
static void CALLBACK waveInProc(HWAVEIN, 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);
static CRITICAL_SECTION waveCriticalSection;
static WAVEHDR* waveBlocks;
static volatile int waveFreeBlockCount;
static volatile int waveFreeBlockCount_IN;
static int waveCurrentBlock;
4、需要加载头文件
#include "mmreg.h"
#include "mmsystem.h"
#pragma comment(lib, "ws2_32.lib")
5、附加说明
经验证明:语音采集开辟5个缓冲区,每个大于采集时间大于100ms,放音开辟20个缓冲区,每个大于100ms,能完全保证语音采集和放音的连续性,无中断发生。
加载中,请稍候......