프로그래밍 관련/사운드

다이렉트 사운드 녹음,재생

AlrepondTech 2011. 1. 5. 14:38
반응형

 

 

 

 

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

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

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

 

 

 

 

 

 

출처: http://lino.egloos.com/2371333

안녕하십니까...석재헌입니다.

예전에 강좌를 하던 적이 있었는데...시간이 없는 관계로 흐지부지 되어 버렸습니다.

죄송하다는 말씀을 드리면서, DirectSound를 이용해서 사운드를 자기 맘대로 녹음 및 재생하는 강좌를 하겠습니다.

1. DirectSound 를 쓰는 이유

- DirectSound 를 쓰는 이유중 가장 많은 이유는 오디오 컨트롤이, 저수준 오디오 함수보다 간결하면서 쉽다는 이유죠...

저 수준 오디오 함수의 경우는 계속 오디오 버퍼를 신경써가면서, 오디오 장치에 버퍼를 던져 줘야 합니다. 특히, 오디오 믹싱의 경우 는 저수준 함수로는 구현하기가 매우 어렵습니다. 실시간 처리를 위해서는 오디오저수준 함수에 어셈블러까지 합해서 해줘야, 자신이 원 하는 속도가 나오죠.....

다이렉트 사운드의 경우는, 그런것을 신경쓸 필요가 없다는 것이 최대의 장점입니다.
구 조를 여기에서 자세하게 설명을 드리기는 어렵지만, 다이렉트 사운드에는 일차버퍼, 이차 버퍼라는 놈이 존재합니다. 일차 버퍼는 쉽 게 우리가 들을 수 있는 최종적인 소리를 가지고 있다고 생각을 하시면 됩니다. 이차 버퍼는 그 전 단계에 들어가는 여러가지 소리들 을 가지고 있다고 생각하시면 되구요.

게임을 예로 들어 보겠습니다. 스타를 하면 배경음악도 나오고, 각각의 유닛의 목소리도 함께 나오지 않습니까..??

이 때 우리가 들을 수 있는 소리는 일차버퍼라는 놈이 재생한 소리이고, 각각의 배경음악이나 유닛의 목소리는 다른 이차 버퍼에 각각 들어가 있습니다.

따로 믹싱이라는 과정을 생각해줄 필요 없이, 플레이를 해주면 각각이 믹싱이 되어서 하나의 스트림으로 플레이가 됩니다.
( 여기에 대한, 자세한 예제는 코드구루에 가시면 다이렉트X 예제에 있습니다. 참고하시길 바라겠습니다. )

다이렉트 캡처도 이런한 다이렉트 사운드의 장점을 가지고 있습니다. 초기화의 과정은 저수준 오디오 함수보다 신경쓸 일이 많지만, 일단 세팅이 된다면, 저수준 오디오 함수와는 달리 안정적입니다.

2. 다이렉트 캡처 사운드의 초기화

초기화 과정은 다른 다이렉트 계열의 함수와 동일 합니다.
소리를 녹음하시기 위해서는 다음의 3가지가 필요합니다.

1)    LPDIRECTSOUNDNOTIFY m_pDSNotify;
     LPDIRECTSOUNDCAPTUREBUFFER m_pDSBCapture;
     LPDIRECTSOUNDCAPTURE m_pDSCapture;

다이렉트 사운드 캡처 , 캡처버퍼, notify 객체 이렇게 3가지를 먼저 정의를 하시고,

 

 

 

반응형

 

 

728x90

 


2)   다른 컴포넌트의 일반적인 과정처럼, 초기화 과정을 거칩니다.

- 다이렉트 사운드 캡처 생성     
   CoInitialize(NULL);
   // Create IDirectSoundCapture using the preferred capture device
   DirectSoundCaptureCreate( NULL, &m_pDSCapture, NULL ) );

- 다이렉트 사운드 버퍼 생성 ( 위에서 생성한 다이렉트 사운드 캡처를 이용해서 생성합니다.)
   m_pDSCapture->CreateCaptureBuffer( &dscbd, &m_pDSBCapture, NULL ) )
  
위에서의 dscbd는 DSCBUFFERDESC 타입의 구조체이며, 사운드 캡처시의 포맷, 버퍼의 길이 등을 정의 하는 구조체입니다.

- Notify 객체 설정 (제일 복잡하지만, 제일 중요합니다. )

기본적인 스토리는 객체의 주소를 얻어온 다음, Notify하기 위한 Event ( 다이렉트 사운드는 이벤트를 사용합니다.)와 버퍼에서의 위치를 각각 알려준 다음, 이것을 설정합니다.

스토리는 어렵지 않은데...여기에서는 생소한 구조체들이 많이 나와서, 어려운 것 처럼 보입니다...속지 마시길...

-Notify 객체의 인터페이스를 얻어 옵니다. 
  m_pDSBCapture->QueryInterface( IID_IDirectSoundNotify, (VOID**&m_pDSNotify)
       
- Notify 할 곳을 알려주기 위해서 필요한 구조체입니다.
   NUM_REC_NOTIFICATION 는 사용자가 정의합니다. 버퍼에서 몇 번이나 Notifyf 를 시
  킬 것인지를.. 
 
  DSBPOSITIONNOTIFY    m_aPosNotify[ NUM_REC_NOTIFICATIONS + 1 ];


-  위에서 정의한 m_aPosNotify를 초기화합니다.

   for( INT i = 0; i < NUM_REC_NOTIFICATIONS; i++ )
   {  
       m_aPosNotify[i].dwOffset = (m_dwNotifySize * i) + m_dwNotifySize - 1;
       m_aPosNotify[i].hEventNotify = m_hNotificationEvents[0];             
   }
   
  m_hNotificationEvent는 이벤트의 핸들로서 , 여기서는 두개가 정의가 되어 있습니다.

   ( 제일 마지막 위치에서는, 다시 버퍼의 처음으로 되돌아가 가게 합니다. )
   m_aPosNotify[i].dwOffset     = DSBPN_OFFSETSTOP;
   m_aPosNotify[i].hEventNotify = m_hNotificationEvents[1];

 이렇게 구조체를 설정한 후에는 , Notify 객체에 Notify 구조체를 설정합니다.

  m_pDSNotify->SetNotificationPositions(NUM_REC_NOTIFICATIONS+1,m_aPosNotify)

 이렇게 하면, 기본적인 설정과정은 마치게 됩니다.


3. 다이뵈?캡처의 시작
위에서 생성한 다이렉트 사운드에 Start 메서드를 이용하면 간단하게 시작이 됩니다.

 m_pDSCapture->Start(DSCBSTART_LOOPING);

 // DSCBSTART_LOOPING 은 명시적으로 중지하라는 말이 있을때까지, 계속적으로 녹음을 하라는 얘기입니다.


다음에 이제, 위에서 설정한 Notify를 이용해서, 녹음된 데이타를 처리하는 방법에 대해서 말씀을 드리겠습니다.

 

 

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

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

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

 

 

 

 

 

반응형