- 음악과 나 -/『 짬 통 』

음성채팅

noon2dy 2006. 5. 6. 01:22

 

 

2005-05-03 오후 5:15:56   /  번호: 515637  / 평점:  (-) category: VC++ 일반  /  조회: 412 
 음성채팅..소스 분석좀 도와주세요...^^; ssun / sun9109  
ssun님께 메시지 보내기  ssun님을 내 주소록에 추가합니다.  ssun님의 블로그가 없습니다  

맨땅에 헤딩하듯 음성채팅을 시작했는데요...

여기저기 소스 받아서 분석해보는데

개념도 없고 실력도 딸려서 쉽지가 않네요..

 

아래소스는 '권진호(crowback)'님이 꽤 오래전 올리신 음성채팅소스중 일부 입니다..

분석하는 중에 모르는 부분이 있어서요....^^;

 

대략 제가 분석한건

헤더를 설정->녹음할버퍼넣구->녹음시작.....버퍼가 차면 콜백함수호출->웨이브데이터 송신->다음버퍼설정?

이런식인거 같은데요....

 

붉은글씨로 적힌 부분이 정확하게 뭘 의미하는지 모르겠습니다.

 

왜 헤더 구조체를 이차원배열로 여러개 설정해놨는지

콜백함수에서 데이터 보낸후에 waveInAddBuffer()는 뭘의미하는지....

대략적이나마 조언 부탁드립니다...

 

 

#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;

    }

 

    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;

        }

    }

    

    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;

            }

        }

    }

}

 

 

이 글에 평점 주기:  
  2005-05-03 오후 8:00:05   /  번호: 515683  / 평점:  (9.0)  
 Re: .. 김현종 / linusix  
김현종님께 메시지 보내기  김현종님을 내 주소록에 추가합니다.  김현종님의 블로그가 없습니다  

안녕하세요

 

아래는 질문하신 내용에 대한 답입니다

 

=>

 

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 초) + 네트워크로 전송될때 까지의 시간(알파)

 

 

이 글에 평점 주기:  

 

'- 음악과 나 - > 『 짬 통 』' 카테고리의 다른 글

네모네모 로직  (0) 2006.05.06
저수준 제어를 이용한 WAVE 재생  (0) 2006.05.06
FFT  (0) 2006.05.06
wave 변환  (0) 2006.05.06
음악파일 주파수 추출  (0) 2006.05.06