안녕하세요
아래는 질문하신 내용에 대한 답입니다
=>
MAXNUMOFBUFFER 는 버퍼링할 버퍼 개수
사운드 디바이스에서는 한 버퍼를 채웠을 경우 다른 버퍼에 채우고..계속...흔히 말하는 큐(queue)
구조의 버퍼를 가지고 있죠
버퍼를 한개 사용할 때의 문제점은 그 버퍼를 다 채웠을 경우 그 버퍼를 비워주고(디스크에 쓴다거나 네트워크로
날린다거나) 하는 동안
의 발생한 사운드를 채울 수 가 없기때문에 보통 2 개 이상 사용합니다
아래 처럼 400 바이트에 8 개의 버퍼를 사용하는 이유는 버퍼가 찼을 때 디바이스가 WIM_DATA
메세지를 통해 알려주기 때문에 버퍼를 작게 잡을 수록 딜레이 없이 통보 받을 수 있기때문입니다 버퍼가 작은 만큼 (400 바이트면 보이스 8k
샘플링에 샘플당 8 비트 모노일 경우 0.05 초의 작은 시간입니다) 8 개의 버퍼를 둔까닭이고요 (그래봤자 0.4 초 뿐이 안되겠죠) 버퍼를
8 개 다 채웠는데 미쳐 버퍼를 네트워크로 전송못하는 일이 나면 흔히 말해 음이 튀겠죠 (버퍼개수를 더 두던가 DSound 를 이용하면 통보없이
버퍼를 추적가능하긴합니다)
#define MAXNUMOFBUFFER 8
#define
BUFFER_SIZE 400
BYTE pWaveIn[MAXNUMOFBUFFER][BUFFER_SIZE];
WAVEHDR WaveHeaderIn[MAXNUMOFBUFFER][sizeof(WAVEHDR)];
void Start_Record()
{
int i;
pcmIn.wf.wFormatTag =
WAVE_FORMAT_PCM;
pcmIn.wf.nChannels =
MONO;
pcmIn.wf.nBlockAlign =
BITS/8;
pcmIn.wBitsPerSample =
BITS;
pcmIn.wf.nSamplesPerSec = SAMPLING;
pcmIn.wf.nAvgBytesPerSec=
SAMPLING*pcmIn.wf.nBlockAlign;
for( i = 0; i < MAXNUMOFBUFFER;
i++){
WaveHeaderIn[i]->lpData
= (LPSTR)pWaveIn[i];
WaveHeaderIn[i]->dwBufferLength
= BUFFER_SIZE;
WaveHeaderIn[i]->dwBytesRecorded
= 0L;
WaveHeaderIn[i]->dwFlags
= 0L;
WaveHeaderIn[i]->dwLoops
= 0L;
}
=> 데이터를 마련 대충 인자는 버퍼 길이, 현재 까지 채워진 버퍼길이(0으로
초기화)
if(
waveInOpen((LPHWAVEIN)&hWaveIn,WAVE_MAPPER,(tWAVEFORMATEX*)&pcmIn,(DWORD)(VOID*)wave_inproc,0L,CALLBACK_FUNCTION)
){
AfxMessageBox("Wave Open
Error.");
return;
}
for( i = 0; i < MAXNUMOFBUFFER;
i++){
if(
waveInPrepareHeader( hWaveIn, WaveHeaderIn[i], sizeof(WAVEHDR) )){
AfxMessageBox("Prepare
Error.");
return;
}
}
=> 장치에 이 버퍼는 준비가 된 버퍼다 알려줌 (저도 이짓을 왜 하는지는 자세한 설명을 본적이 없어서
패스)
for( i = 0; i < HALFNUMOFBUFFER;
i++){
if(
waveInAddBuffer( hWaveIn, WaveHeaderIn[i], sizeof(WAVEHDR) )){
AfxMessageBox("Add
Error.");
return;
}
}
=> 장치 큐에 버퍼를 추가시켜줌 (먼 처음 추가된 버퍼 부터 채워지기 시작합, 첫버퍼가 다 찼으면 2
번째 버퍼...계속.. 8 까지 다찼으면 ? 그전에 사용한 버퍼를 큐에 다시 추가 시켜서 0 번 부터 다시 채워지게
해야겠죠)
if(waveInStart(hWaveIn)){
AfxMessageBox("Redord
Error.");
return;
}
}
void CALLBACK wave_inproc( HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD
dwParam1, DWORD dwParam2)
{
switch(uMsg)
{
case WIM_DATA: //When Bufffer is full of DATA
{
SendPack.control
= SIGNAL_VOICE;
memcpy(
SendPack.Data,pWaveIn[WaveCountIn], BUFFER_SIZE);
if(g_pUdpSock)
g_pUdpSock->Send(&SendPack,sizeof(SendPack));
if(
WaveCountIn == (MAXNUMOFBUFFER-1) )
WaveCountIn
= 0;
else
WaveCountIn++;
if( WaveCountIn >
(MAXNUMOFBUFFER-HALFNUMOFBUFFER) && WaveCountIn <
MAXNUMOFBUFFER)
{
if(
waveInAddBuffer( hWaveIn,
WaveHeaderIn[WaveCountIn-(MAXNUMOFBUFFER-(HALFNUMOFBUFFER-1))], sizeof(WAVEHDR)
)){
AfxMessageBox("Add
Error.");
return;
}
}
else{
if(
waveInAddBuffer( hWaveIn, WaveHeaderIn[WaveCountIn+(HALFNUMOFBUFFER-1)],
sizeof(WAVEHDR) )){
AfxMessageBox("Add
Error.");
return;
}
break;
}
=> WIM_DATA -> 버퍼를 채웠다 처리해라 (네트워크로 전송) => 대충 사용된 버퍼를 큐의 뒷끄트머리에 추가, 위의 예에선 왜 두개의
구문으로 나누었는지는 파악이 안됨...그냥 차례대로 해도 무방
}
}
}
ps.. 여기서 딜레이 값음 버퍼 하나의 찰때까지의 시간 (0.05 초) + 네트워크로 전송될때 까지의
시간(알파)
|