프로그래밍 관련/사운드

이준곤님 Direct Sound 설명 (사운드 믹싱 검색)

AlrepondTech 2011. 1. 5. 12:15
반응형

 

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

 

안녕하세요~ 이준곤(LeeChen) 입니다.  

한동안 시간을 핑계삼아 지연되고 있는 윈도우즈 게임 강좌를 성원해주시는 많은 분들께    
진심으로 감사드리며 앞으로도 계속적으로 강좌를 하겠습니다.  

7-1. Direct Sound

  벌써 7번째 다이렉트 사운드를 처리할 수 있는 시간이 되었군요~  
  다이렉트 사운드는 도스 시절의 사운드는 DMA전송을 사용해서 멀티사운드등을 처리했던    
  것으로 기억하고 있습니다.(그런가??) 그래도 가끔 메모리 충돌현상으로 인해 더욱 좋은    
  사운드 라이브러리를 누가 만드는가가 관건이었던 시절이 있었죠?  
  그러나 윈도우즈의 특징이 하드웨어를 제어하는데 있어 시간적인 투자를 할필요가
  없다는 것이죠~ (^^; )  
  다이렉트 사운드는 기존의 도스용 라이브러리의 경우 함수들이 추가될 경우 새로운    
  라이브러리가 이전에 개발한 프로그램과 제대로 호환이 안되거나 일정한 표준이 없어    
  우왕자왕했습니다.  그러나 Component Object Model(COM)을 지원하므로서 이러한
  문제는 문제가 되지 않습니다.  
  다이렉트 사운드는 IDirectSound와 IDirectSoundBuffer로 구성 되어 있습니다.  
  다이렉트 버퍼는 1차 사운드 버퍼(Primary Sound)와 2차 사운드 버퍼(Secondary  
  Sound Buffer)로  나누어 집니다. 1차 사운드 버퍼는 2차사운드 버퍼의 버퍼를 믹싱하여
  출력하며 2차 사운드 버퍼는 실제 게임에 사용되는 오직 하나의 사운드만을 담고
  있습니다. 이해가 되는지 모르겠군요?  2차 사운드 버퍼는 사운드 버퍼의 메모리보다 큰
  메모리 영역을 사용할 수 있으며 사운드 카드 내의 메모리보다 큰 메모리의 영역을 사용할
  경우 시스템 메모리를 사용하게 된다. 또한 2차 사운드 버퍼의 모든 음향들은 1차 사운드
  버퍼로 보내기 전에 자동으로 믹싱되어 보내지게 됩니다.  
    
  모식도로 표현하면

HRESULT SetCooperativeLevel(LPDIRECTDRAW lpDD, HWND hWnd,
                                                                   DWORD dwFlags)


  그림 가지고는 이해 하기 힘들다구요? 한마디로 하나의 1차 사운드 버퍼에 여러개의 2차    
  사운드 버퍼가 존재가 가능하다는 것을 보여 주는 모식도 입니다.  
  다이렉트 사운드는 다음과 같은 과정으로 하나의 사운드를 출력 하게 됩니다.  
  1) 다이렉트 사운드 객체 생성  
  2) 필요한 사운드의 2차 버퍼 생성  
  3) 생성된 버퍼에 음향 데이타를 전송  (이때 lock와 Unlock를 사용합니다.)  
  4) 2차 사운드 버퍼에 있는 음향들을 출력  
  아주 간단한 구조를 가지고 있죠? 이찌 보면 지금까지 배웠던 이미지 출력과도 비슷하다고
  볼수 있네요?  
  그럼 사운드가 출력하기 까지의 모식도를 보도록 하죠!

1. 다이렉트 사운드 생성  
  LPDIRECTSOUND lpDs;  
  HWND          hwnd;    
  HRESULT     dsrval;  
  dsrval = DirectSoundCreate(NULL, &lpDs, NULL);  
  if(dsrval != DS_OK)  
       return FALSE; // 다이렉트 사운드 생성의 실패시  
  lpDs->SetCooperativeLevel(hwnd, DDSSCL_NORMAL);  


여기까지가 사운드 객체의 생성하는 코드였습니다.  
함수는 앞에서 배운 다이렉트 함수 구조와 다른것이 없으므로 함수설명을 생략하겠습니다.  
자~ 이번에는 2차 사운드 버퍼를 생성해 봅시다. 앞에서 장황하게 설명만 해놓고 2차
버퍼가 무척 중요하건 것 같은 생각으로 들지만 살펴보면 별거 아니네? 하실 겁니다.

2. 필요한 데이타의 2차 버퍼 생성
LPDIRECTSOUND        lpDs;  
LPPCMWAVEFORMAT     pcmwf;  
LPDIRECTSOUNDBUFFER lpDsb;  
DSBUFFERDESC   dsbd = {0};  
  
dsbd.dwSize  = sizeof(dsbd);  
dsbd.dwFlags = DSBCAPS_CTRLDEFAULT;  
dsbd.dwBufferByte = 30000;  
dsbd.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;  
dsrval = lpDs->CreateSoundBuffer(&dsbd, lplpDsb, NULL);  
if(dsrval != DS_OK)  
          return FALSE; // 당연 실패 했을 경우겠죠?  

여기까지가 2차 사운드 버퍼를 생성하는 코드 입니다. 어떻습니까? 그리 어렵지는 않죠?    
2차 사운드는 두종류로 나누어 집니다. 어떤 걸까요?  
바로 Static Buffer와 String Buffer로 나누어 집니다. 보통 짧은 소리는 Static Buffer에
답겨지고 여러번 반복 출력 하기 위해 사용되어 집니다. 긴 소리는 String Buffer에 답겨 지게 되
며 2~3회 반촉 출력 하기 위해 사용되어집니다.  
그렇다면 지금까지 앞의 1)과 2)에 해당된 것은 구현이 된 상태고, 음향 데이타를 생성된  
버퍼에 전송하는 것을 알아 봅시다.

3. 생성된 버퍼에 음향 데이타를 전송
LPDIRECTSOUNDBUFFER lpDsb;    
DWORD dwOffset = 0;  
DWORD dwLength = 30000;  
LPVOID lpvPtr;  
DWORD  dwBytes;  
dsrval = lpDsb->Lock(dwOffset, dwLength, &lpvPtr, &dwBytes,NULL, NULL, 0);  
if(dsrval != DS_OK)  
           return FALSE;  
// 이부분은 어째? 어느 부분과 비슷하죠?  
// 지난 번에 배운 lock과 unlock를 참조 하세요~  
LPBYTE  lpbSoundData;// 전송할 음향 데이타  
LPVOID lpvPtr;  
DWORD dwBytes;  
CopyMemory(lpvPtr, lpbSoundData, dwBytes);  
dsrval = lpDsb->Unlock(lpvPtr, dwBytes, NULL, 0);  
if(dsrval != DS_OK)  
         return FALSE;  

자~ 여기까지가 일단은 만들어진 사운드를 다이렉트 버퍼에 전송 해지게 되었습니다.    
어떻습니까? 지금까지 배운 것들이 모두 비슷비슷하죠?  

4. 2차 사운드 버퍼에 있는 음향들을 출력
LPDIRECTSOUNDBUFFER lpDsb;    
lpDsb->Play(0, 0, DSBPLAY_LOOPING);  
// 기타 여러 처리들  
.......  
// 나중에 멈추고 싶으면...  
lpDsb->Stop();  


  출력하는 것이 이정도면 어느정도 이해가 되셨겠죠?  
  함수가 그리 어렵지 않기 때문에 설명보다는 코딩된 것이 이해 하기가 어렵지 않을 겁니다.  
  그렇다고 여기서 사운드 처리가 끝나느냐? 그건 아니죠! 우리가 게임을 하면서 마치
  사람이  오른쪽에서 걸어오는 착각을 느끼거나~ 왼쪽에서 오른 쪽으로 사라져 가는 비행기 소리~    
  또는 저멀리서 바로 앞으로 날아 오는 무언가의 물체 소리를 우리는 어떻게 구현을 할것인가?  
  바로 이러한 문제는 아주 쉽습니다. 보륨조절로 인해 작게 들렸다 크게 들리면 저멀리서    
  가까이 오는 듯하는 효과를 볼수 있습니다. 그리고 오른쪽 스피커를 크게 했다가 점점  
  왼쪽 스피커로 소리를 나오게 하면 마치 우리는 3차원 음향을 듣는 듯한 착각을 하게  
  됩니다.  이러한 효과는 어떻게 얻는냐? 그것이 문제군요? (^^;)  
  그러나 이글을 보는 분은 이미 알고 있는 분도 계실테고 어라~ 이런 또 뭐야~  하는 분도
  있을 겁니다.  
  이럴때를 위해 다이렉트 사운드는 이러한 함수를 제공합니다.  

SetVolume(lpDS, DWORD, dwVolume);   // 요건 함수를 호출하여 원하는 볼륨으로 소리나게 하는  함수 입니다.  

SetPan(lpDs, DWORDm dwPan);   // 좌우의 사운드 밸런스를 조절하는 기능을 하는 함수  

SetFrequency(lpDS, LPDWORD, lpdwFrequency);   // 소리의 피치를 조정합니다.
                                                                   // dwFrequency 값이 높을  수록 피치가 증가합니다.
                                                                   // 만약 조정하기 전에 현재 피치를 알기 위해서는 GetFrequency()함수를 호출  해서 값을 얻어 오면 됩니다.  

SetCurrentPosition();   // 이함수는 현재 데이타의 위치를 알아 내는 함수 입니다.  
                                // 데이타의 끝나는 부분을 체크할 때 유용하게 사용되어 지겠죠?  

 

 

=================================

=================================

=================================

 

 

 

반응형

'프로그래밍 관련 > 사운드' 카테고리의 다른 글

DX 사운드 옵션 설명  (0) 2011.01.05
Direct Sound 란? (wiki 자료)  (0) 2011.01.05
게임 사운드 믹싱 관련  (0) 2011.01.05
OGG 사운드 재생  (0) 2011.01.05
사운드 다이렉트 OGG 재생  (0) 2011.01.05