상세 컨텐츠

본문 제목

DirectSound C++ Document

프로그래밍 관련/사운드

by AlrepondTech 2020. 9. 19. 00:33

본문

반응형

 

 

 

 

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

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

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

 

 

 

번역 : 최도경(lifeisforu@hanmail.net)

이메일 : lifeisforu@hanmail.net

홈페이지 : www.lifeisforu.net

출처 ; DirectX 9.0 SDK C++ document

비상업적 목적으로 자유로이 배포해 주세요. 불분명한 해석 뒤에는 원문을 실었습니다. 그리고 원문과 함께 보는 것이 좋을 것입니다.

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

 

DirectSound C++ Document

이 섹션은 C와 C++로 작성된 응용프로그램에서 사운드를 재생하고 캡춰하기 위해서 필요한 Microsoft® DirectSound® 에 대한 정보를 제공한다.

정보는 다음 섹션으로 제출된다:

  • What's New in DirectSound. Microsoft DirectX® 9.0 의 DirectSound에서 새로워진 기능에 대한 안내
  • Introduction to DirectSound. DirectSound가 무엇이고, 응용프로그램을 위해 그것이 무엇을 할 수 있는지, 그리고 DirectSound와 Microsoft DirectMusic®의 비교, 그리고 사운드를 재생하기 위해 응용프로그램에서 취해야만 할 단계에 대한 개관이다.
  • Getting Started with DirectSound. DirectSound 프로젝트를 설정하고 디버깅하는 데 대한 정보.
  • Using DirectSound. API를 사용하기 위한 가이드. 아마도 이 섹션의 내용에 익숙해지고 싶을 것이다. 이것은 레퍼런스 섹션과 함께 이용될 수 있다.
  • Advanced Topics in DirectSound. 특별한 응용프로그램이나 매우 최적화된 수행성을 필요로 하는 응용프로그램을 개발하는데 있어서 흥미로운 정보.
  • DirectSound C++ Samples. SDK에 있는 샘플 응용프로그램에 대한 안내이다. 필요로한 샘플 코드를 짚어준다. 기본 함수를 어떻게  구현하는지 뿐만 아니라, 각 샘플은 하나 이상의 개별적인 DirectSound 함수를 설명한다.
  • DirectSound C/C++ Reference. Dsound.h에 선언된 모든 API 요소에 대한 세부적인 정보.

 

1. What's New in DirectSound

DirectSound 응용프로그램 프로그래밍 인터페이스(API)는 DirectX 9.0 에서 특별히 변하지 않았다. 그러나 수행성 측면에서 많은 부분이 강화되었다.

부가적으로 다음과 같은 변화들이 생겨났다:

  • 사운드 버퍼의 최대 주파수가 100kHz에서 200kHz로 증가했으면, 이는 운영체제에 의해서 지원된다. (이들 고 주파수들은 DirectShow에 의해 지원되지 않는다)
  • 주파수와 이펙트 제어(DSBCAPS_CTRLFREQUENCY 와 DSBCAPS_CTRLFX)가 버퍼 상에서 혼용될 수 있다. 이들 플래그를 혼용하는 것은 버퍼에서 도플러 이동(shift)과 함께 이펙트를 사용할 수 있게 해 준다.
  • WAVEFORMATEXTENSIBLE 구조체에 의해 기술된 오디오 포맷들이 DirectSound를 통해 완전히 지원된다.
  • 표준 이펙트인 DMOs가 WAVE_FORMAT_IEEE_FLOAT 포맷으로 오디오 데이터를 처리할 수 있게 되었다.
  • 매우 작은 증가에도 불구하고 ImediaObjectInPlace::Process를 반복적으로 호출했어야 하는 것과는 달리, (DirectSound의 바깥에서 호스팅될 때) 표준 이펙트가 parameter curves를 지원한다.

 

2. Introduction to DirectSound

이 섹션은 DirectSound의 기능과 API를 시작하기 위해 해야 할 필요가 있는 것에 대한 간단한 개관을 제공한다. 정보는 다음과 같은 섹션으로 제출되어 있다.

  • The Power of DirectSound
  • DirectSound and DirectMusic

 

1) The Power of DirectSound

DirectSound는 매우 낮은 지연율로 사운드를 재생할 수 있게 해 주면, 응용프로그램에 하드웨어 리소스에 대한 고수준의 제어를 제공한다.

DirectSound 인터페이스를 응용프로그램에 사용함으로써 다음과 같은 것들을 할 수 있다 :

  • WAV 포맷으로 파일이나 리소스로부터 사운드를 재생한다.
  • 다중 사운드를 동시에 재생한다.
  • 하드웨어에 의해 제어되는 버퍼에 높은 우선순위의 사운드를 할당한다.
  • 사운드를 사용자가 정의할 수 있는 3-D 환경에 위치한다.
  • 에코나 코러스 같은 이펙트를 추가하고, 이펙트 인자를 동적으로 바꾼다.
  • 마이크로폰이나 다른 입력으로부터 WAV 사운드를 캡춰한다.

DirectSound 는 Microsoft® Windows® 98, Microsoft® Windows® 2000, 그리고 그 이후의 운영체제에서 작동한다. 캡춰 효과와 같은 어떤 함수들은 단지 XP나 그 이후의 버전에서만 이용 가능하다.

See Also

  • DirectSound and DirectMusic

 

2) DirectSound and DirectMusic

DirectSound 와 DirectMusic은 서로 중복되는 기능을 가진 분리된 DirectX 컴포넌트이다. 둘 다 WAV 사운드를 재생한다. 그리고 DirectMusic은 궁극적으로 모든 사운드를 DirectSound버퍼를 통해 재생되는 waveform으로 합성한다.

DirectMusic 는 DirectSound보다는 게임과 다른 인터랙티브(interactive) 응용프로그램에서 대부분의 오디오 시나리오를 위한 완전한 솔루션을 제공하는 좀 더 완전한 기능의 API이다. 그 이름에도 불구하고 DirectMusic은 비음악적인 사운드 효과를 포함한 모든 종류의 사운드를 재생한다. DirectSound는 시스템 자원을 사용하고 가능한 한 적은 지연률(latency)로 재생되어야만 하는 많은 짧은 사운드를 가진 게임과 같은 저수순의 하드웨어 자원에 대한 관리를 요구하는 시나리오를 위한 선택적인 API이다.

다른 컨텐츠를 재생하기 위해서 DirectMusic을 사용하는 응용프로그램 안에서도 DirectSound API를 사용하여 독립적으로 WAV 사운드를 재생할 수 있다. 또한 DirectSound를 사용하여 DirectMusic에 의해 관리되는 사운드 버퍼를 조작할 수도 있따. 예를 들어 DirectMusic audiopath로부터 DirectSound 버퍼를 획득하고, 그것을 3-D 공간으로 이동시킬 수 있다.

다음 표는 두 API에 의해 제공되는 기능에 대한 요약이다.

Functionality DirectMusic DirectSound
WAV 사운드 재생
MIDI 재생 아니요
DirectMusic Producer segments 재생 아니요
컨텐츠 파일 로드와
개체 관리
No, 그러나 일부는 샘플 코드에서 제공한다.
실행시간에 음악적 인자 제어 아니요
큐에서 관리되는 사운드를 위해서 타임라인을 관리 아니요
downloadable sounds (DLS) 사용 아니요
개별 사운드의 볼륨(volume), 음정(pitch), 팬(pan) 설정 DirectSound API를 통해서 가능
다중 사운드(audiopath)상에서 볼륨 설정 아니요
3-D 사운드 구현 DirectSound API 를 통해서 가능
effects (DMOs) 적용 DirectMusic Producer content 나  DirectSound API를 통해서 가능
mix-in (send) effects를 위한 체인(chain) 버퍼 DirectMusic Producer content를 통해서 가능 아니요
WAV 사운드 캡춰 아니요
완전한 duplex(음악 :이중음표) 구현 아니요
MIDI 캡춰 아니요
하드웨어 버퍼의 할당 제어 아니요

 

3. Getting Started with DirectSound

이 섹션은 DirectSound 프로젝트를 설정하고 디버깅하는 정보를 제공할 뿐만 아니라, 사운드를 재생하기 위해 요구되는 프로그래밍 단계에 대한 짧은 개관을 제공한다.

DirectSound를 시작하기 위한 더 많은 정보들이 다음 주제들에 포함되어 있다:

  • Building DirectSound Projects
  • Debugging DirectSound Projects
  • Adjusting DirectSound Acceleration for Testing
  • First Steps in DirectSound Programming

1) Building DirectSound Projects

프로젝트는 Dsound.h 헤더 파일을 포함해야 한다. 만약 DirectSound를 DirectMusic과 함께 사용하고 있다면, Dmusici.h를 삽입할 때 이 헤더가 삽입된다.

만약 DirectSound API를 직접 사용하고 있고, DirectSoundCreate8과 같은 헬퍼 함수를 사용할 수 있게 되길 원한다면, Dsound.lib를 링크하고 라이브러리 검색 경로에 적절한 폴더를 삽입하라.

 

응용프로그램이 DirectSound에 의해 사용되는 GUID에 대한 접근권한을 가질 수 있도록 해야 한다. 다른 전처리기들이 지시되기 전에 INITGUID를 정의하거나, Dxguid.lib를 링크하라.

 

2) Debugging DirectSound Projects

DirectX 소프트웨어 개발 도구의 디버그 버전으로 설치되어 있는 DirectSound 동적 링크 라이브러리(DLL)는 디버그 출력 윈도우에 응용프로그램이 실행되고 있는 것과 관련한 정보를 생성한다.

Control Panel의 DirectX Properites의 DirectSound 페이지에 있는 Debug Output Level 슬라이더를 사용하여 디버그 레벨을 0부터 5까지 설정할 수 있다. 0의 설정은 디버깅 정보를 생성하지 않고, 5의 정보는 매우 세밀한 정보를 생성한다. 대부분의 목적에 대해서 레벨을 2보다 높게 설정할 필요가 없다; 높은 레벨에서의 출력은 에러나 경고와 어울리지 않는다. 단지 순수하게 정보성을 띄고 있을 뿐이다.

 

3) Adjusting DirectSound Acceleration for Testing

Control Panel의 Sounds 와 Audio Devices 페이지를 사용함으로써, 시스템에서 DirectSound의 수행성(performance)을 조정할 수 있다. Audio 탭의 Sound Playback 그룹에 있는 Advanced 버튼을 클릭한다. Advanced Audio Properties 다이얼로그 박스에서 Performance 탭을 선택한다. 슬라이더가 다음의 설정 중 하나로 하드웨어 가속을 조정할 수 있게 해 준다:

Full

완전한 DirectSound 가속을 가능하게 하는데 IksPropertySet 확장을 가능하게 하는 것을 포함한다.

Standard

DirectSound 보조 버퍼의 하드웨어 가속을 가능하게 한다. 그러나 하드웨어 지정 IksPropertySet 확장을 사용할 수 없게 한다. 이것은 Windows 2000의 기본 설정이다.

Basic

DirectSound 보조 버퍼의 하드웨어 가속을 불가능하게 한다. 이 옵션은 비가속 사운드 카드를 테스트할 목적으로 에뮬레이트 하고자 할 때 유용하다.

Emulation

DirectSound 를 에뮬레이션 모드로 만드는데, 이는 시스템에 DirectSound와 호환성 있는 드라이버가 없는 것처럼 동작하게 한다. 모든  믹싱이 사용자 모드의 DirectSound에 의해 수행되며, 결과 데이터는 Win32 waveform-audio 함수로 보내진다. 이것은 일반적으로 지연률을 크게 증가시키는 결과를 낳는다.

 

4) First Steps in DirectSound Programming

이 주제는 DirectSound API를 사용함으로써 사운드를 재생하기 위해 취해야만 할 단계의 짧은 개관을 제공한다. 세부적인 사항을 위해서는 Using DirectSound를 참조하라.

짧은 사운드를 재생하는 것은 다음 단계를 요구한다:

1. Create a device object

DirectSoundCreate8 을 호출해 IdirectSound8 인터페이스를 지원하는 개체를 생성한다. 이 개체는 보통 기본 재생 장치를 제출한다. 선택적으로 먼저 가능한 장치를 열거해 사용하고자 하는 장치의 GUDIO를 획득하고, 그것을 DirectSoundCreate8로 넘길 수도 있다.

Note   DirectSound 는 컴포넌트 오브젝트 모델에 기반하고 있다. 그러나 DMOs 이펙트를 사용하고 있지 않은 이상, COM을 명시적으로 초기화할 필요는 없다.

2. Create a secondary buffer

IdirectSound8::CreateSoundBuffer 를 사용하여 사운드 데이터를 저장할 버퍼 개체를 생성한다. 그러한 버퍼는 보조(secondary)버퍼라고 불리우는데, 모든 사운드를 혼합(mix)하는 주(primary)버퍼와 구분된다.

3. Obtain PCM data

WAVE 파일이나 리소스로부터 데이터를 읽어들여 개별 버퍼에 넣는다. DirectX SDK는 이것을 수행하기 위해 사용할 수 있는 샘플 코드를 포함하고 있다.

4. Put data in the buffer

IdirectSoundBuffer8::Lock 메서드를 호출함으로써 쓰기 연산을 위한 보조 버퍼를 준비한다. 대부분의 경우에 이 메서드는 단일한 메모리 주소를 반환한다. 개별 버퍼로부터 데이터를 복사하고, IdirectSoundBuffer8::Unlock을 호출한다.

5. Play the buffer

IdirectSoundBuffer8::Play 를 호출함으로써 사운드를 재생한다. 파일의 끝에 도달했을 때 버퍼를 중지시키거나, 그 너머로 재생을 계속하거나, IdirectSoundBuffer8::Stop을 호출할 때까지 재생을 계속하도록 명령할 수 있다. 버퍼를 반복적으로 재생하고 멈출 수 있다; 그러나 같은 데이터를 포함하는 다른 버퍼를 생성하지 않는 한, 한 번에 단지 하나의 사운드 인스턴스만이 재생될 수 있다. 주어진 시간에 여러 개의 버퍼가 재생될 수 있으며, 자동적으로 믹싱이 수행된다.

이전의 단계에서 가능한 가장 간단한 시나리오를 적용했다. 일반적으로 몇 초가 넘는 사운드들은 스트리밍된다; 즉 이미 재생된 데이터는 주기적으로 새로운 데이터에 의해 대체된다는 것이다.

SDK에 들어있는 샘플 코드는 DirectSound를 사용하여 일반적인 작업들을 수행하는 방법을 보여준다. 더 많은 정보를 원한다면 DirectSound C++ Samples를 참조하라.

 

4. Using DirectSound

이 섹션은 응용프로그램 개발에서 Microsoft® DirectSound® 응용프로그램 프로그래밍 인터페이스(API)를 사용하는 방법에 대한 안내이다.

정보는 다음과 같은 주제들로 제시되어 있다:

  • DirectSound Playback Objects
  • DirectSound Devices
  • DirectSound Buffers
  • Using WAV Data
  • 3-D Sound
  • Using Effects
  • Capturing Waveforms

See Also

  • Introduction to DirectSound
  • Advanced Topics in DirectSound
  • DirectSound C/C++ Reference

 

1) DirectSound Playback Objects

다음의 개체들은 사운드를 재생하는데 사용된다:

Object Number Purpose Main interfaces
장치(Device) 각 응용프로그램에서 하나 장치를 관리하고 사운드 버퍼를 생성한다. IDirectSound8
보조 버퍼
(Secondary buffer)
각 사운드에 대해 하나 정적이거나 스트리밍되는 사운드를 관리하고 그것을 주 버퍼로 재생한다. IDirectSoundBuffer8, IDirectSound3DBuffer8, IDirectSoundNotify8
주 버퍼
(Primary buffer)
각 응용프로그램에서 하나 보조 버퍼로부터의 사운드를 혼합하고 재생한다. 그리고 전역 3-D 인자를 제어한다. IDirectSoundBuffer, IDirectSound3DListener8
효과
(Effect)
보조버퍼에 대해서 0 개 혹은 다수 개 보조버퍼에서 사운드를 변환한다. IDirectSoundFXChorus8 와 같은 개별적인 효과에 대한 인터페이스

 

응용프로그램에서 DirectSound를 구현하는데 있어서 첫 번째 단계는 렌더링 장치를 제출하는 장치 개체를 생성하는 것이다. 그리고 나서 이 개체는 버퍼를 생성하는데 사용된다.

Note   DirectSound 는 컴포넌트 개체 모델(COM)에 기반하고 있다. 그러나 DMOs 이펙트를 사용하지 않는 한, CoInitialize나 CoInitializeEx를 사용해 COM을 명시적으로 초기화할 필요는 없다.

보조 버퍼들은 응용프로그램에 의해서 생성되고 관리된다. DirectSound는 자동적으로 주 버퍼를 생성하고 관리한다. 그리고 응용프로그램은 이 개체에 대한 인터페이스를 획득하지 않고도 사운드를 재생할 수 있다. 그러나 IdirectSound3Dlistener8 인터페이스를 획득하기 위해서는 응용프로그램은 반드시 명시적으로 주버퍼를 생성해야만 한다.

 

보조 버퍼의 사운드가 재생될 때, DirectSound는 그것들을 주 버퍼에서 혼합하고, 렌더링 장치로 그것들을 보낸다. 이용 가능한 처리 시간은 DirectSound가 혼합할 수 있는 버퍼의 개수로 제한되어 있다.(원문 : Only the available processing time limits the number of buffers that DirectSound can mix.)

Note   WDM(Windows driver model) 하에서 혼합은 커널 믹서에 의해 수행되며, 주 버퍼는 실제로 어떠한 데이터도 포함하지 않는다. 더 많은 정보를 원한다면, DirectSound Driver Models를 참조하라.

짧은 사운드는 전체가 보조버퍼로 로드될 수 있으며, 간단한 메서드 호출에 의해 언제라도 재생될 수 있다. 긴 사운드는 스트리밍되어야만 한다. 응용프로그램은 재생 커서의 위치를 폴링(역자주 : 기억장치의 상태를 정기적으로 점검, polling)하거나 재생커서가 특정위치에 도달했을 때 통지를 요청함으로써 더 많은 데이터를 버퍼로 스트리밍할 때임을 알아낼 수 있다.

보조 버퍼들은 코러스나 에코 같은 효과들을 포함할 수 있다. 그것들은 3-D 제어 기능도 가지고 있다. 전역 3-D 인자들은 주버퍼 상의 IdirectSound3Dlistener8 인터페이스에 의해서 제어된다.

 

2) DirectSound Devices

DirectSound 장치 개체는 렌더링 장치를 제출하며, 장치를 관리하고 사운드 버퍼를 생성하는데 사용된다.

다중 응용프로그램은 같은 사운드 장치에 대한 개체들을 생성할 수 있다. 입력 포커스가 응용프로그램들 사이에서 바뀔 때, 오디오 출력은 하나의 응용프로그램 스트림에서 다른 것의 스트림으로 자동적으로 바뀐다. 결과적으로 응용프로그램은 입력 포커스가 바뀌었을 때, 그것들의 버퍼를 반복적으로 재생하거나 중지할 필요가 없다.

이 섹션은 응용프로그램이 이용가능한 사운드 개체를 열거하고, 장치 개체를 생성하고, 장치를 관리하기 위해서 그 개체의 IdirectSound8 메서드를 사용하는 방법에 대해 기술한다. 다음 주제들이 다뤄지고 있다:

  • Enumerating Sound Devices
  • Creating the Device Object
  • Cooperative Levels
  • Device Capabilities
  • Speaker Configuration

 

 Enumerating Sound Devices

만약 응용프로그램이 사용자가 선호하는 재생 장치를 통해서 간단하게 사운드를 재생할 것이라면, 이용 가능한 장치를 열거할 필요가 없다. DirectSoundCreate8 함수를 사용해 장치 개체를 생성할 때, 기본 장치를 지정할 수 있다. 더 많은 정보를 원하면 Creating the Device Object를 참조하라.

열거는 다음 상황에서 필요하다:

  • 어떠한 장치 상에서는 이용 가능하지 않을 수 있는 기능을 필요로 할 때.
  • 두 개 이상의 장치를 요구할 때.
  • 사용자가 장치를 선택하게 하고 싶을 때.

열거는 세 가지 목적을 위해 작동한다:

  • 하드웨어가 이용가능한지를 기록한다.
  • 각 장치에 대한 GUID를 제공한다.
  • 마치 각 장치들이 열거된 것처럼 각 장치에 대한 임시 장치 개체를 생성할 수 있게 해 준다. 그렇게 함으로써 장치의 기능을 검사할 수 있다.

장치를 열거하기 위해서는 먼저 시스템 상의 각 장치에 대해 한 번 호출될 콜백(callback) 함수를 설정해야만 한다. 이 함수에 원하는 것은 무엇이든 할 수 있으며, 어떠한 이름을 주든지 상관이 없다. 그러나 반드시 DSEnumCallback의 원형(prototype)과 같은 형식으로 선언해야만 한다. 콜백 함수는 열거가 계속되면 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환한다 – 예를 들어 필요로 하는 기능을 가진 장치를 찾은 이후.

다음 콜백 함수는 각 열거된 장치의 이름을 콤보 박스에 추가하고, 그것의 GUID를 item 데이터로 저장한다. 첫 번째 세 인자들에 대한 값은 장치 드라이버에 의해 제공된다. 네 번째 인자는 DirectSoundEnumerate 함수로부터 넘겨진다; 이 인자는 32비트 값을 넘기기 위해 사용될 수 있으며, 이 경우에는 콤보박스의 윈도우 핸들이다. Windowsx.h에서 정의된 매크로는 문자열과 데이터를 콤보박스에 추가하는데 사용된다.

 

BOOL CALLBACK DSEnumProc(LPGUID lpGUID,
    LPCTSTR lpszDesc,
    LPCTSTR lpszDrvName,
    LPVOID lpContext) {
    HWND hCombo = (HWND) lpContext;
    LPGUID lpTemp = NULL;

    if (lpGUID != NULL) //  NULL only for " Primary Sound Driver".
    {
        if ((lpTemp = (LPGUID) malloc(sizeof(GUID))) == NULL) {
            return (TRUE);
        }
        memcpy(lpTemp, lpGUID, sizeof(GUID));
    }

    ComboBox_AddString(hCombo, lpszDesc);
    ComboBox_SetItemData(hCombo,
        ComboBox_FindString(hCombo, 0, lpszDesc),
        lpTemp);
    free(lpTemp);
    return (TRUE);
}

 

열거는 콤보박스를 포함하고 있는 다이얼로그 박스가 초기화되고 있을 때 설정된다. (원문 : The enumeration is set in motion when the dialog box containing the combo box is initialized.) hCombo는 콤보 박스의 핸들로, hDlg는 다이얼로그 박스의 핸들로 간주한다.

 

if (FAILED(DirectSoundEnumerate((LPDSENUMCALLBACK) DSEnumProc, (VOID * ) & hCombo))) {
    EndDialog(hDlg, TRUE);
    return (TRUE);
}

 

이 경우에 콤보 박스 핸들의 주소는 DirectSoundEnumerate로 넘겨지는데, 이는 그것을 순서대로 콜백 함수에 넘겨준다. 이 인자는 콜백함수를 가지고서 접근을 하고자 원하는 것에 대한 32비트 값일 수 있다.(원문 : This parameter can be any 32-bit value that you want to have access to within the callback)

Note   첫 번째로 열거된 장치는 항상 주 사운드 드라이버(Primary Sound Driver)라 불린다. 콜백 함수의 그리고 lpGUID 인자는 NULL이다. 이 장치는 Control Panel 에서 사용자에 의해 설정된 선호하는 재생 장치를 제출한다. 개별적으로 열거하는 것은, 사용자가 장치에 대한 선택을 하게 할 때, 응용프로그램이 리스트에 “주 사운드 드라이버”를 추가하기 쉽게 하기 위해서이다.(원문 : It is enumerated separately to make it easy for the application to add "Primary Sound Driver" to a list when presenting the user with a choice of devices.) 또한 주 장치는 적절한 이름 및 GUID와 함께 열거된다.

 

 Creating the Device Object

장치 개체를 생성하는 가장 간단한 방법은 DirectSoundCreate8 함수를 사용하는 것이다. 이 함수의 첫 번째 인자는 개체와 관련된 장치의 GUID를 지정한다. 장치를 열거함으로써 이 GUID를 얻을 수 있으며, 기본 장치를 지정하는 다음 GUID 중의 하나를 넘길 수도 있다:

GUID definition Description
DSDEVID_DefaultPlayback 오디오 장치의 기본 시스템. 장치 GUID 인자에 NULL을 넘김으로써 이 장치를 지정할 수도 있다. 기본 장치는 “주 DirectSound 드라이버”로 열거된 것이다.
DSDEVID_DefaultVoicePlayback 기본 voice communication 장치. 일반적으로 이것은 마이크로폰을 가진 USB 헤드셋과 같은 보조(secondary) 장치이다.

만약 아무런 장치도 제출되지 않으면 DirectSoundCreate8 호출은 실패한다.

아무런 사운드 장치도 없거나, VXD 드라이버 환경에서 사운드 장치가 표준 Win32 waveform-audio 함수를 사용하는 응용프로그램의 제어 하에 있다면, 함수는 에러를 반환한다. 응용프로그램이 이러한 호출에 대해 실패할 것에 대해 준비를 해야 한다. 그래서 사운드 없이 계속 진행할 수도 있고, 이미 사운드 장치를 사용하고 있는 응용프로그램을 닫는다는 것을 사용자에게 알려줘야 한다.(원문 : You should prepare your applications for this call to fail so that they can either continue without sound or prompt the user to close the application that is already using the sound device.)

 

다음 코드는 기본 장치를 위한 개체를 생성하고 IdirectSound8 인터페이스를 획득한다.

LPDIRECTSOUND8 lpds; HRESULT hr = DirectSoundCreate8(NULL, &lpds, NULL)); 

 

Note   DirectSoundCreate8  CoInitialize나 CoInitializeEx가 호출되게 하지 않는다. 그러나 응용프로그램이 DMOs 이펙트를 사용한다면, 개체가 생성되기 이전에 COM이 명시적으로 초기화되어야만 한다

응용프로그램이 사운드를 재생하는 것 뿐만 아니라 사운드를 캡춰하기도 한다면, DirectSoundFullDuplexCreate8 함수를 사용함으로써 재생버퍼와 캡춰버퍼와 함께 렌더링장치와 캡춰장치 둘 다 편리하게 생성할 수 있다.

또한 표준 COM 함수를 사용하여 다음과 같이 장치 개체를 생성할 수도 있다.

CoInitializeEx를 호출하여 COM을 응용프로그램 시작부에서 초기화한다.
HRESULT hr = CoInitializeEx(NULL, 0);
if (FAILED(hr)) {
    ErrorHandler(hr); // Add error-handling here.
}
IdirectSoundCreate8이 아니라 IdirectSound8::Initialize 메서드와
CoCreateInstance 메서드를 사용하여 장치 개체를 생성한다.

LPDIRECTSOUND8 lpds;
hr = CoCreateInstance( & CLSID_DirectSound8,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_IDirectSound8,
    (LPVOID * ) & lpds);
if (FAILED(hr)) {
    ErrorHandler(hr); // Add error-handling here.
}

CLSID_DirectSound8은 DirectSound 드라이버 개체 클래스의 클래스 식별자이며,
IID_IdirectSound8은 인터페이스 식별자이다.lpds 인자는 인터페이스 포인터를 받는다
IdirectSound8::Initialize 메서드를 호출하여 개체와 장치를 연관시킨다.
이 메서드는 DirectSoundCreate8이 사용하는 것과 같은 장치 GUID를 취한다.

hr = lpds - > Initialize(NULL);
if (FAILED(hr)) {
    ErrorHandler(hr); // Add error-handling here.
}
응용프로그램을 닫기 전에 CoUninitialize 함수를 다음과 같이
호출함으로써 COM 라이브러리를 닫는다:

CoUninitialize();

 Cooperative Levels

윈도우는 multitasking 환경이기 때문에, 하나 이상의 응용프로그램이 동시에 장치 드라이버를 사용해 작업할 수가 있다. 협력 레벨의 사용을 통해서 DirectX는 각 응용프로그램이 잘못된 시간이나 잘못된 방식으로 장치에 대한 접근을 획득할 수 없게 한다. 각 DirectSound 응용프로그램은 응용프로그램이 장치에 대한 접근을 어느 정도로 허용받았는 지를 결정하는 협력레벨을 가지고 있다.

장치 개체를 생성한 이후에는 반드시 IdirectSound8::SetCooperativeLevel 메서드를 사용하여 장치에 대한 협력레벨을 설정해야 한다. 이것을 수행하지 않으면, 아무런 소리도 들리지 않을 것이다.

다음 예제는 IdirectSound8 인터페이스에 의해 제출된 DirectSound 장치인 lpDirectSound에 대한 협력레벨을 설정하는 예제이다. HWnd 인자는 응용프로그램 윈도우에 대한 핸들이다.

HRESULT hr = lpDirectSound - > SetCooperativeLevel(hwnd, DSSCL_PRIORITY);
if (FAILED(hr)) {
    ErrorHandler(hr); // Add error-handling here.
}

 

DirectSound는 사운드 장치를 위한 3 개의 협력 레벨을 정의하는데, DSSCL_NORMAL, DSSCL_PRIORITY, DSSCL_WRITEPRIMARY로 지정되어 있다. 이들 레벨은 다음 주제에서 설명되고 있다:

  • Normal Cooperative Level
  • Priority Cooperative Level
  • Write-primary Cooperative Level

Note   DSSCL_EXCLUSIVE 협력 레벨은 폐기되었다. DirectX응용프로그램이 다른 응용프로그램의 소리를 없애는 것은 더 이상 불가능하다. 배타적인 레벨을 요구하는 응용프로그램은 priority(우선순위) 레벨을 대신 부여받는다. 

 

) Normal Cooperative Level

평균 협력 레벨(DSSCL_NORMAL) 에서, 응용프로그램은 주버퍼의 포맷을 설정하거나 주버퍼에 쓰거나, 장치의 보드기반 메모리를 채워넣을(compact) 수 없다. 이 협력 레벨을 가진 모든 응용프로그램은 22kHz의 주버퍼 포맷과 스테레오 사운드, 8비트 샘플을 사용하여야 한다. 그래서 장치는 가능한 한 부드럽게 응용프로그램 사이를 전환할 수 있다.

 

) Priority Cooperative Level

DirectSound 장치가 우선순위 협력 레벨(DSSCL_PRIORITY)를 사용할 때, 응용프로그램은 먼저 하드웨어 믹싱과 같은 하드웨어 리소스에 대한 첫 번째 권한을 가지며, 장치의 주 사운드 버퍼의 포맷을 설정하거나 장치의 보드 기반 메모리를 채울 수 있다.

게임 응용프로그램은 대부분 모든 환경에서 우선순위 협력 레벨을 사용해야만 한다. This level gives the most robust behavior while allowing the application control over sampling rate and bit depth. 또한 우선순위 협력 레벨은 IP 전화와 같은 다른 응용프로그램으로부터의 오디오가 게임으로부터 오디오와 함께 들릴 수 있도록 허용한다.

 

) Write-primary Cooperative Level

최상의 협력 레벨은 write-primary 협력 레벨(DSSCL_WRITEPRIMARY)이다. DirectSound가 이 협력 레벨을 사용할 때, 응용프로그램은 비WDM 드라이버 상의 주 사운드 버퍼에 직접 접근할 수 있다. 이 모드에서 응용프로그램은 주 버퍼에 대해서 직접 쓰기를 해야만 한다. 보조버퍼는 이 동작이 수행되는 동안에 재생될 수가 없다.

주 버퍼의 오디오 샘플에 대한 직접 쓰기 접근 획득하기 위해서는, 응용프로그램이 반드시 write-primary 레벨로 설정되어야만 한다. 만약 응용프로그램에 이 레벨이 설정되지 않았다면, 주버퍼 상의 IDirectSoundBuffer::Lock 메서드에 대한 모든 호출이 실패할 것이다.

Note   주버퍼는 IdirectSoundBuffer8이 아니라 IdirectSoundBuffer만을 지원한다.

응용프로그램이 write-primary 협력레벨로 설정되어 있고, foreground(최상위 실행 우선순위)를 획득했을 때, 다른 응용프로그램에 대한 모든 보조 버퍼들은 정지되며, 소실된 것처럼 기록된다. 응용프로그램이 순서대로 background(낮은 실행 우선순위)로 이동할 때, 그것의 주 버퍼들은 소실된 것처럼 기록되며, 응용프로그램이 foreground로 다시 이동할 때 재저장되어야만 한다. 더 많은 정보를 원한다면 Buffer Management를 참조하라.

만약 DirectSound 드라이버가 사용자 시스템상에 제출되지 않았다면 write-primary 협력 레벨은 설정될 수 없다. 그러한 경우가 발생하는지 확인하기 위해서는 IDirectSound8::GetCaps 메서드를 호출하고, DSCAPS 구조체의 DSCAPS_EMULDRIVER 플래그를 검사해야 한다.

See Also

  • Writing to the Primary Buffer

 

 Device Capabilities

DirectSound 는 응용프로그램이 사운드 디바이스의 하드웨어 기능을 시험할 수 있게 한다. 그렇지만 많은 응용프로그램들이 그럴 필요가 없다. 왜냐하면 DirectSound는 자동적으로 가능한 하드웨어 가속의 이점을 취하기 때문이다. 그러나 고수행성 응용프로그램은 그 정보를 사용하여 가능한 하드웨어에 대한 사운드 요청을 조정할 수 있다.

(원문 : However, high-performance applications can use the information to scale their sound requirements to the available hardware.)

 

예를 들어 응용프로그램은 하드웨어 믹싱이 가능한 경우에 그렇지 않은 경우보다 더 많은 사운드에 대한 재생을 선택할 수 있다.

 

DirectSoundCreate8 함수를 호출하여 장치 개체를 생성한 이후에, 응용프로그램은 IDirectSound8::GetCaps 메서드를 호출하여 사운드 장치의 기능을 받을 수 있다.

다음의 예제는 IDirectSound8 인터페이스 포인터인 lpDirectSound에 의해 제출된 장치의 기능을 받는다.

DSCAPS dscaps;

dscaps.dwSize = sizeof(DSCAPS);
HRESULT hr = lpDirectSound - > GetCaps( & dscaps);
if (FAILED(hr)) {
    ErrorHandler(hr); // Add error-handling here.
}

 

DSCAPS 구조체는 현재 사용 가능한 리소스와 각 유형에 대한 최대 리소스를 포함한 사운드 장치의 수행성과 리소스에 대한 정보를 받는다. DwSize 멤버는 메서드가 호출되기 이전에 반드시 초기화되어 있어야 한다는 점에 주의하라.

만약 응용프로그램이 하드웨어 기능을 조정한다면, 모든 버퍼 할당의 사이에서 IDirectsound8::GetCaps 메서드를 호출하여 다음 버퍼를 생성하기 위한 충분한 리소스가 있는지 확인해야만 한다.

 

 Speaker Configuration

DirectSound는 스피커 구성(즉 청취자에 상대적인 스피커의 위치, configuration)을 사용해 사용자의 사운드 시스템을 위한 3-D 효과를 최적화한다.

Windows® 98, Windows 2000, 그리고 그 이후의 운영체제에서, 스피커 구성(configuration)은 Control Panel에서 사용자에 의해 설정될 수 있다. 응용프로그램은 IDirectSound8::GetSpeakerConfig를 사용하여 이 값을 받을 수 있다. 응용프로그램은 IDirectSound::SetSpeakerConfig를 사용하여 그 설정을 오버라이드할 수 없다. 왜냐하면 이것은 다른 사용자와 응용프로그램에 영향을 미치는 전역 설정이기 때문이다.

 

3) DirectSound Buffers

DirectSound 버퍼 개체는 소스로부터 목적지로의 waveform 데이터 전송을 제어한다. 소스는 아마도 신디사이저(synthesizer)나 다른 버퍼, WAV 파일, 또는 리소스일 것이다. 대부분의 버퍼에 대해, 목적지는 주버퍼라 불리는 믹싱 엔진이다. 데이터는 주버퍼로부터  하드웨어로 이동하는데, 하드웨어는 샘플을 사운드 wave로 변환한다.

DirectSound 버퍼를 사용하는데 대한 정보는 다음 주제에 포함되어 있다:

Information about using DirectSound buffers is contained in the following topics:

  • Buffer Basics
  • Creating Secondary Buffers
  • Duplicating Buffers
  • Buffer Control Options
  • 3-D Algorithms for Buffers
  • Filling and Playing Static Buffers
  • Using Streaming Buffers
  • Playback Controls
  • Play and Write Cursors
  • Play Buffer Notification
  • Mixing Sounds
  • Looping Sounds
  • Buffer Management

캡춰 버퍼에 대한 더 많은 정보를 원한다면 Capturing Waveforms를 참조하라.

 

 Buffer Basics

응용프로그램은 적어도 하나의 보조 버퍼를 생성하여 개별 사운드를 저장하고 재생해야만 한다.

보조 버퍼는 응용프로그램의 생명주기 전체에 걸쳐 존재할 수 있으며, 더 이상 필요없을 때 제거될 수도 있다. 짧은 단일 사운드를 포함하는 정적 버퍼일 수도 있으며, 재생될 때마다 새로운 데이터로 갱신되는 스트리밍 버퍼일 수도 있다. 메모리에 대한 요구를 제한하기 위해서, 긴 사운드는 몇 초의 데이터만을 저장하는 스트리밍 버퍼를 통해서 재생되어야만 한다.

다른 보조 버퍼로부터의 사운드를 간단하게 동시에 재생하는 것만으로 사운드를 믹스(mix, 혼합)할 수 있다. 처리 능력이 되는 한, 동시에 여러 개의 버퍼를 재생하는 것이 가능하다.

보조 버퍼는 서로 다른 방식으로 생성된다. 버퍼의 특질은 다음을 포함한다 :

  • Format. 버퍼의 포맷은 반드시 그것이 재생하는 waveform 데이터의 포맷과 일치하여야 한다.
  • Controls. 다른 버퍼는 볼륨, 주파수, 2차원이나 3차원에서의 이동과 같은 다른 제어를 가진다. 버퍼를 생성할 때, 필요한 제어만을 지정할 수 있다; 예를 들어 3-D 환경에서 존재하지 않는 사운드에 대해서는 3-D 버퍼를 생성할 필요가 없다.
  • Location. 버퍼는 하드웨어에 의해 관리되는 메모리에 존재하거나, 소프트웨어에 의해 관리되는 메모리에 존재할 수 있다. 하드웨어 버퍼는 더 효율적이지만, 개수가 제한되어 있다.

See Also

  • DSBUFFERDESC

 

 Creating Secondary Buffers

버퍼를 생성하기 위해서는 IDirectSound8::CreateSoundBuffer메서드를 호출한다. 이 메서드는 IdirectSoundBuffer 인터페이스의 포인터를 리턴한다. 이를 통해서 응용프로그램은 IdirectSoundBuffer9 인터페이스를 획득할 수 있다.

다음 예제 함수는 보조 사운드 버퍼를 생성하고 IdirectSoundBuffer8 인터페이스를 반환한다.

HRESULT CreateBasicBuffer(LPDIRECTSOUND8 lpDirectSound, LPDIRECTSOUNDBUFFER8 * ppDsb8) {
    WAVEFORMATEX wfx;
    DSBUFFERDESC dsbdesc;
    LPDIRECTSOUNDBUFFER pDsb = NULL;
    HRESULT hr;

    // Set up WAV format structure. 

    memset( & wfx, 0, sizeof(WAVEFORMATEX));
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nChannels = 2;
    wfx.nSamplesPerSec = 22050;
    wfx.nBlockAlign = 4;
    wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
    wfx.wBitsPerSample = 16;

    // Set up DSBUFFERDESC structure. 

    memset( & dsbdesc, 0, sizeof(DSBUFFERDESC));
    dsbdesc.dwSize = sizeof(DSBUFFERDESC);
    dsbdesc.dwFlags =
        DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
    dsbdesc.dwBufferBytes = 3 * wfx.nAvgBytesPerSec;
    dsbdesc.lpwfxFormat = & wfx;

    // Create buffer. 

    hr = lpDirectSound - > CreateSoundBuffer( & dsbdesc, & pDsb, NULL);
    if (SUCCEEDED(hr)) {
        hr = pDsb - > QueryInterface(IID_IDirectSoundBuffer8, (LPVOID * ) ppDsb8);
        pDsb - > Release();
    }
    return hr;
}

 

예제 함수는 3초의 스트리밍 데이터를 저장할 수 있을 만큼 큰 스트리밍 버퍼를 생성한다. 비스트리밍 버퍼는 전체 사운드를 저장할 만큼 충분히 커야만 한다.

만약 버퍼의 위치가 지정되지 않으면, DirectSound는 가능하다면 그것을 하드웨어에 의해 제어되는 메모리에 위치시킨다. 하드웨어 버퍼는 사운드 카드 프로세서에 의해 혼합되기 때문에, 응용프로그램의 수행성에 영향을 더 조금 끼친다.

만약 DirectSound가 버퍼가 속할 위치를 결정하게 하는 것이 아니라, 직접 버퍼의 위치를 결정하고자 한다면, DSBUFFERDESC 구조체 안의DSBCAPS_LOCHARDWARE 나 DSBCAPS_LOCSOFTWARE 플래그를 설정한다. 만약 DSBCAPS_LOCHARDWARE 플래그가 설정되었는데 하드웨어 리소스가 부족하다면, 버퍼 생성 요구는 실패한다.

DirectSound 의 voice 관리 기능의 이점을 취하고 싶다면, 버퍼를 생성할 때 DSBCAPS_LOCDEFER 플래그를 지정하라. 이 플래그는 그것이 재생될 때까지 버퍼에 대한 리소스 할당을 연기한다. 더 많은 정보를 원하면 Dynamic Voice management를 참조하라.

IdirectSoundBuffer8::GetCaps 메서드를 사용함으로써 현재 존재하는 버퍼의 위치를 확인하고, DSBCAPS 구조체의 dwFlags 멤버가 DSBCAPS_LOCHARDWARE 인지 DSBCAPS_LOCSORTWARE 플래그인지를 검사할 수 있다. 둘 중의 하나가 항상 지정되어 있다.

버퍼 개체는 그것을 생성한 장치 개체에 의해서 소유된다. 장치 개체가 메모리에서 해제될 때, 그 개체에 의해 생성된 모든 버퍼들 또한 해제되며, 참조될 수 없다.

 

 Duplicating Buffers

IDirectSound8::DuplicateSoundBuffer 메서드를 사용함으로써 같은 데이터를 포함하는 두 개 이상의 보조 버퍼를 생성할 수 있다. 주 사운드 버퍼를 중복시킬 수는 없다. 버퍼를 중복시키는 것은 원래의 버퍼와 메모리를 공유하는 것이기 때문에, 하나의 버퍼에 있는 데이터를 변경하는 것은 중복된 버퍼들에 영향을 끼친다.

 

 Buffer Control Options

사운드 버퍼를 생성할 때, 응용프로그램은 반드시 버퍼에 필요로 하는 제어 옵션을 지정해야만 한다. 이것은 DSBUFFERDESC 구조체에의 dwFlags 멤버에 의해 수행되는데, 그것은 다음 테이블 중 하나 이상의 값을 포함할 수 있다.

Flag Description
DSBCAPS_CTRL3D 사운드 소스가 3-D 공간으로 이동될 수 있다
DSBCAPS_CTRLFX 버퍼에 이펙트가 추가될 수 있다.
DSBCAPS_CTRLFREQUENCY 사운드의 주파수가 변경될 수 있다.
DSBCAPS_CTRLPAN 사운드 소스가 왼쪽에서 오른쪽으로 이동될 수 있다
DSBCAPS_CTRLPOSITIONNOTIFY 통지 위치가 버퍼상에서 설정될 수 있다
DSBCAPS_CTRLVOLUME 사운드의 볼륨이 변경될 수 있다

 

제어의 특정 조합은 허용되지 않는다. 더 많은 정보를 원한다면 DSBUFFERDESC를 참조하라.

모든 사운드 카드에 대한 최상의 수행성을 획득하기 위해서는, 응용프로그램이 사용하게 될 단일한 제어 옵션을 지정해야만 한다.

DirectSound 는 하드웨어 자원(resource)이 사운드 버퍼에 할당될 수 있는지를 판단하기 위해서 제어 옵션을 사용한다. 예를 들어 장치는 하드웨어 버퍼를 지원하지만, 그들 버퍼에 대한 팬 제어를 지원하지 않을 수도 있다. 이 경우에 DirectSound는 DSBCAPS_CTRLPAN 플래그가 지정되어 있지 않은 경우에만 하드웨어 가속을 사용할 것이다.

만약 응용프로그램이 버퍼가 없는 제어를 사용하고자 한다면, 메서드 호출은 실패할 것이다. 예를 들어 IdirectSoundBuffer8::SetVolume 메서드를 사용하여 볼륨을 변경시키려고 시도할 때, 메서드는 버퍼가 생성되었을 때 DSBCAPS_CTRLVOLUME 플래그가 지정되었던 경우에만 성공할 수 있다. 그렇지 않으면 메서드는 실패하고, DSERR_CONTROLUNAVAIL 에러 코드를 반환한다.

See Also

  • Playback Controls

 

 3-D Algorithms for Buffers

DSBCAPS_CTRL3D 제어 플래그를 사용하여 보조 버퍼를 생성할 때, 버퍼가 소프트웨어상에 있다면 사운드를 공간화(spatilaizing)하는 데 사용되는 알고리즘을 지정할 수도 있다. 기본값으로 HRTF(no head-related transfer function)이 수행되며, 청취자에 상대적인 사운드의 위치는 패닝과 볼륨으로만 식별된다. 버퍼에 대해 두 레벨의 HRTF를 요청할 수 있다.

더 많은 정보를 원한다면 DSBUFFERDESC를 참조하라.

 

 Filling and Playing Static Buffers

자체적으로 전체 사운드를 포함하고 있는 보조 버퍼를 정적(static)버퍼라고 부른다. 비록 같은 버퍼를 다른 사운드를 위해 재사용할 수는 있지만, 일반적으로 정적버퍼에 데이터는 한번만 쓰여진다.

정적버퍼는 스트리밍 버퍼와 비슷하게 생성되고 관리된다. 차이가 있다면 사용되는 방식이다: 정적 버퍼는 한 번에 채워져 재생되지만, 스트리밍 버퍼는 계속적으로 재생하고 있는 데이터를 교체한다.

Note   정적 버퍼는 버퍼 기술에 DSBCAPS_STATIC 플래그를 반드시 설정해야만 생성할 수 있는 것이 아니다. 이 사운드 카드 상에서 메모리를 할당해 줄 것을 요청하는 것이다. 그렇지만 이것은 현재 대부분의 하드웨어에서 사용이 불가능하다. 정적 버퍼는 시스템 메모리에 위치할 수도 있고, DSBCAPS_LOCHARDWARE 나 DSBCAPS_LOCSOFTWARE 플래그를 사용해 생성될 수도 있다.

데이터를 정적 버퍼로 로드하는 것은 세 단계를 필요로 한다:

  1. IdirectSoundBuffer8::Lock을 사용해 전체 버퍼를 잠근다. 버퍼안에서 사운드 작성을 시작하고 싶은 위치(일반적으로 0)에 오프셋을 지정한다. 그리고 그 지점의 메모리 주소를 다시 얻어 온다.
  2. 표준 메모리 복사 루틴(역자주 : memcpy 같은 것?)을 사용해 반환된 주소에 오디오 데이터를 쓴다.
  3. IdirectSoundBuffer8::Unlock을 사용해 버퍼를 잠근다.

다음 예제에서 이 단계들을 다루고 있는데, lpdsbStatic은 IdirectSoundBuffer8의 인터페이스 포인터이고, pbData는 데이터 소스의 주소이다:

LPVOID lpvWrite;
DWORD dwLength;

if (DS_OK == lpdsbStatic - > Lock(
        0, // 잠금을 시작한 오프셋
        0, // 잠글 크기; 플래그 때문에 무시됨
        &
        lpvWrite, // 잠겨진 첫번째 부분의 주소를 얻는다
        &
        dwLength, // 첫번째 부분의 잠겨진 크기를 얻는다
        NULL, // wraparound 부분의 주소. 필요없음. 
        NULL, // wraparound 부분의 크기. 필요없음.
        DSBLOCK_ENTIREBUFFER)) // 플래그.
{
    memcpy(lpvWrite, pbData, dwLength);
    lpdsbStatic - > Unlock(
        lpvWrite, // 잠금을 시작한 부분의 주소.
        dwLength, // 잠근 크기.
        NULL, // wraparound 부분.
        0); // wraparound 크기.
} else
    (
        ErrorHandler(); // 에러 처리 코드
    }
버퍼를 재생하기 위해서는 IdirectSoundBuffer8::Play를 다음과 같이 호출한다:

    lpdsbStatic - > SetCurrentPosition(0);
HRESULT hr = lpdsbStatic - > Play(
    0, // 사용되지 않음.
    0, // voice 관리에 대한 우선순위.
    0); // 플래그.
if (FAILED(hr))
    (
        ErrorHandler(); // 에러 처리 코드.
    }

DSBPLAY_LOOPING 플래그가 예제에 설정되어 있지 않기 때문에, 버퍼는 끝에 도달했을 때 자동으로 멈추지 않는다. 또한 IdirectSoundBuffer8::Stop 메서드를 사용하여 일찍 중지시킬 수도 있다. 버퍼를 일찍 중지시키면, 재생 커서의 위치는 그대로 남는다. 그러므로 예제에서IdirectSoundBuffer8::SetCurrentPosition 호출은 시작점에서 버퍼가 시작하도록 만든다.

 

 Using Streaming Buffers

스트리밍 버퍼는 버퍼에 한 번에 넣을 수 없는 긴 사운드를 재생한다. 버퍼가 재생되는 만큼 오래된 데이터는 주기적으로 새로운 데이터로 교체된다.

스트리밍 버퍼를 재생하기 위해서는 IdirectSoundBuffer8::Play 메서드를 호출하는데, dwFlags 인자에 DSBPLAY_LOOPING을 지정한다.

재생을 중지하기 위해서는 IdirectSoundBuffer8::Stop 메서드를 호출한다. 이 메서드는 버퍼를 즉각 멈추며, 모든 데이터가 재생되었는지 확인할 필요가 없다. 이것은 재생 위치를 폴링(역자주 : 주기적으로 검색)하거나 통지 위치를 설정함으로써 수행된다.

버퍼로 스트리밍하는 것은 다음 단계를 요구한다:

  1. 버퍼가 새로운 데이터를 받을 준비가 되었는지 확인한다. 이는 재생커서를 폴링하거나 통지를 기다림으로써 수행된다.
  2. IdirectSoundBuffer8::Lock을 사용해서 버퍼의 일부를 잠근다. 이 메서드는 데이터가 현재 쓰여질 수 있는 한 개 혹은 두 개의 주소를 반환한다.
  3. 표준 메모리 복사 루틴을 이용해 반환된 주소나 주소에 오디오 데이터를 작성한다.
  4. IdirectSoundBuffer8::Unlock을 사용해 버퍼 잠금을 해제한다.

IdirectSoundBuffer8::Lock 이 두 개의 주소를 반환할 수 있는 이유는 시작 위치를 고려하지 않고, 버퍼의 크기만큼 원하는 바이트 수만큼 잠글 수 있게 하기 위해서이다. (역자주 : 만약 잠겨질 부분이 2개가) 필요하다면 잠겨진 부분은 버퍼의 시작점과 함께 한꺼번에 묶어야 한다(?, wrap around). 그렇게 했을 경우, 두 개의 분리된 메모리 복사를 수행해야만 한다.

예를 들어 40,000 바이트의 버퍼에서 오프셋 20,000을 시작점으로 해서 30,000 바이트를 잠궜다고 하자. 이 경우 Lock을 호출할 때, 그것은 4개의 값을 반환한다:

  • 오프셋 20,000의 메모리 주소
  • 그 지점부터 버퍼의 끝까지 잠겨진 바이트 수; 즉 20,000 바이트. 이 바이트 수만큼 첫번째 주소에 쓴다.
  • 오프셋 0의 메모리 주소.
  • 그 지점부터 잠겨진 바이트 수; 즉 10,000 바이트. 이 바이트 수만큼 두 번째 주소에 쓴다.

만약 wraparound가 필요하지 않다면, 마지막 2개의 값은 NULL과 0이다.

비록 전체 버퍼를 잠그는 것이 가능하지만, 그것이 재생되고 있는 동안 그렇게 할 필요는 없다. 일반적으로 매번 버퍼의 단지 한 조각만을 갱신한다. 예를 들어 버퍼의 첫 번째 4분의 1을 잠그고 쓰자 마자, 재생 커서가 두 번째 4분의 1에 도달한다. 재생 커서와 쓰기 커서 사이에 놓인 버퍼의 일부분을 쓸 필요가 없다.

(원문 : Although it's possible to lock the entire buffer, you must not do so while it is playing. Normally you refresh only a fraction of the buffer each time. For example, you might lock and write to the first quarter of the buffer as soon as the play cursor reaches the second quarter, and so on. You must never write to the part of the buffer that lies between the play cursor and the write cursor.)

다음은 사운드 버퍼에 데이터를 작성하는데, dwOffset에 넘겨진 위치에서 시작한다:

 

BOOL AppWriteDataToBuffer(
    LPDIRECTSOUNDBUFFER8 lpDsb, // 버퍼
    DWORD dwOffset, // 재생커서
    LPBYTE lpbSoundData, // 데이터의 시작
    DWORD dwSoundBytes) // 복사할 블록의 크기
{
    LPVOID lpvPtr1;
    DWORD dwBytes1;
    LPVOID lpvPtr2;
    DWORD dwBytes2;
    HRESULT hr;

    // 재생 블록의 메모리 주소 획득. 블록이 wraps around된다면 두 부분이 됨.

    hr = lpDsb - > Lock(dwOffset, dwSoundBytes, & lpvPtr1, &
        dwBytes1, & lpvPtr2, & dwBytes2, 0);

    // 버퍼를 소실하면, 재저장하고 잠금 재시도. 

    if (DSERR_BUFFERLOST == hr) {
        lpDsb - > Restore();
        hr = lpDsb - > Lock(dwOffset, dwSoundBytes, &
            lpvPtr1, & dwBytes1, &
            lpvPtr2, & dwBytes2, 0);
    }
    if (SUCCEEDED(hr)) {
        // 포인터를 작성 

        CopyMemory(lpvPtr1, lpbSoundData, dwBytes1);
        if (NULL != lpvPtr2) {
            CopyMemory(lpvPtr2, lpbSoundData + dwBytes1, dwBytes2);
        }

        // DirectSound로 데이터를 보냄 

        hr = lpDsb - > Unlock(lpvPtr1, dwBytes1, lpvPtr2,
            dwBytes2);
        if (SUCCEEDED(hr)) {
            // 성공. 
            return TRUE;
        }
    }

    // Lock, Unlock, Restore 실패. 

    return FALSE;
}

 

See Also

  • Play and Write Cursors
  • Play Buffer Notification
  • Reading WAV Data
  • Using Buffers Efficiently

 

 Playback Controls

버퍼가 재생되는 위치의 볼륨을 얻거나 설정하기 위해서, 응용프로그램은 IdirectSoundBuffer8::GetVolume 이나 IdirectSoundBuffer8::SetVolume메서드를 사용할 수 있다. 주버퍼에서 볼륨을 설정하는 것은 사운드 카드의 waveform-audio 볼륨을 변경시킨다. 볼륨은 감쇄에 대한 수 백분의 일 단위의 데시벨(db)로 측정된다; 기본 볼륨을 증폭하는 것은 불가능하다. (원문 : Volume is measured as hundredths of decibels(dB) of attenuation; it is not possible to amplify the default volume). 데시벨 단위는 선형이 아님에 주의하라; a reduction in volume of 3 dB is equivalent to a halving of the sound energy, and sounds generally become inaudible long before the maximum attenuation of 100 dB is reached.

IdirectSoundBuffer8::GetFrequency 와 IdirectSoundBuffer8::SetFrequency 메서드를 호출하여, 오디오 샘플이 재생되고 있는 위치의 주파수를 얻거나 설정할 수 있다. 주 버퍼의 주파수는 변경할 수 없다.

왼쪽- 오른쪽 축의 사운드 소스의 위치를 얻거나 설정하려면, IdirectSoundBuffer8::GetPan과 IdirectSoundBuffer8::SetPan 메서드를 호출하면 된다. 3-D 기능이 있는 버퍼는 패닝(panned)될 수 없다.

이러한 제어 중 하나를 사용하기 위해서는, 퍼버를 생성할 때 적절한 플래그를 설정해야만 한다. Buffer Control Options를 참조하라.

 

 Play and Write Cursors

DirectSound는 버퍼에 두 개의 포인터를 유지한다: 재생 커서와 쓰기 커서이다; 이러한 위치들은 버퍼 안에서의 바이트 단위 오프셋이며, 절대 메모리의 주소가 아니다.

IdirectSoundBuffer8::Play 메서드는 항상 재생 커서의 위치에서 재생을 시작한다. 버퍼가 생성될 때, 재생 커서는 0으로 설정된다. 버퍼가 재생될 때마다, 커서는 움직이며 항상 재생될 다음 데이터의 바이트를 가리킨다. 버퍼의 재생이 중지되면 커서는 그대로 남는다.

쓰기 커서는 버퍼에 데이터가 성공적으로 쓰여진 다음 위치에 존재한다. 재생 커서와 쓰기 커서 사이의 블록은 이미 재생되도록 위임된(역자주 : 예약되었다 정도가 적당한 듯, committed) 것이며, 그것을 변경하는 것은 안전하지 않다.

시계 방향으로 버퍼에 기록한 데이터를 가지고 시계 표면처럼 버퍼를 가시화할 수 있다. 재생 커서와 기록커서는 같은 속도로 표면을 지나가는 두 개의 시계바늘(hands)와 같은데, 쓰기 커서는 항상 재생 커서의 약간 앞을 유지한다. 만약 재생 커서가 1의 위치에 있다면, 쓰기 커서는 2의 위치에 있으며, 2 이후에다가 데이터를 써야지만 안전하다. 1과 2 사이의 데이터는 이미 DirectSound에 의해 재생을 위한 큐에 들어가 있을 것이며, 손댈 수가 없다.

쓰기 커서는 재생 커서와 함께 움직이는 것이지, 버퍼에 대해 쓰여진 데이터와 함께 움직이는 것이 아니다. 만약 데이터를 스트리밍하고 있다면, 버퍼에 있는 자신의 포인터가 쓰여질 수 있는 다음 데이터 블록을 가리키도록 유지할 책임이 있다.

응용프로그램은 IdirectSoundBuffer8::GetCurretPosition 메서드를 사용해 재생과 쓰기 커서를 검색할 수 있다. IdirectSoundBuffer8::SetCurrentPosition 메서드는 재생 커서를 이동할 수 있게 해 준다. 응용프로그램은 쓰기 커서의 위치를 제어할 수는 없다.

재생 커서가 가능한 한 정확하게 기록되도록 하기 위해서는, 보조 버퍼를 생성할 때, 항상 DSBCAPS_GETCURRENTPOSITION@ 플래그를 지정하도록 하라. 더 많은 정보를 원한다면 DSBUFFERDESC를 참조하라.

 

 Play Buffer Notification

DirectSound는 재생 커서가 버퍼의 특정 위치의 도달했을 때나 버퍼가 멈췄을 때, 응용프로그램에 통지를 보낼 수 있다. 이것은 두 가지 일반적인 상황에서 유용할 수 있다.

  • 사운드가 재생을 멈췄을 때, 다른 버퍼를 재생하는 것과 같은 어떤 행동을 취해야만 한다.
  • 응용프로그램이 데이터를 버퍼에 스트리밍하고 있으며, 재생 커서가 미리 지정된 위치에 도달했을 때를 알아야 할 필요가 있다. 그래야만 재생되었던 데이터가 새로운 데이터로 재지정될 수 있다.

Note   만약 voice 관리의 이점을 취하고 있다면, 버퍼가 통지 위치에 도달하기 전에 버퍼를 끝내는 것도 가능하다. DSBPOSITIONNOTIFY를 참조하라.

IdirectSoundNotify8::SetNotificationPositions 메서드를 사용하여, 버퍼 안에 이벤트가 표시되어야 할 몇 개의 지점이라도 설정할 수 있다. 그러나 버퍼가 재생되고 있을 때는 이를 수행할 수 없다.

먼저 IdirectSoundNotify8 인터페이스의 포인터를 획득한다. 버퍼 개체의 QueryInterface메서드를 사용하여 이를 수행할 수 있다. (역자주 : 버퍼가 여러 개라면)통지를 설정하고자 하는 각 버퍼로부터 개별적인 인터페이스가 획득되어야 한다.

각 통지 위치에 대해서, Win32 CreateEvent 함수를 가진 이벤트 개체를 생성하라. 이 이벤트에 대한 핸들을 DSBPOSITIONNOTIFY 구조체의 hEventNotify 멤버에 넣는다. 그 구조체의 dwOffset 멤버에는 버퍼안의 이벤트가 표시되기 원하는 오프셋을 지정한다. 그리고 나서 구조체의 주소나 (만약 하나 이상의 통지 위치를 설정하고자 한다면) 구조체 배열의 주소를 SetNotificationPosition에 넘긴다.

다음 예제 함수는 단일한 통지 위치를 설정한다. 이벤트는 재생이 정지될 때 표시가 되는데, 이는(역자주 : 재생이 정지되는 경우는) 반복재생되지 않는 버퍼의 끝에 도달했거나, 응용프로그램이 IdirectSoundBuffer8::Stop 메서드에 의해 호출되었기 때문이다.

 

HRESULT SetStopNotification(HANDLE hMyEvent,
    LPDIRECTSOUNDBUFFER8 lpDsbSecondary) {
    LPDIRECTSOUNDNOTIFY8 lpDsNotify;
    DSBPOSITIONNOTIFY PositionNotify;
    HRESULT hr;

    if (SUCCEEDED(
            hr = lpDsbSecondary - > QueryInterface(IID_IDirectSoundNotify8,
                (LPVOID * ) & lpDsNotify))) {
        PositionNotify.dwOffset = DSBPN_OFFSETSTOP;
        PositionNotify.hEventNotify = hMyEvent;
        hr = lpDsNotify - > SetNotificationPositions(1, & PositionNotify);
        lpDsNotify - > Release();
    }
    return hr;
}

 

 Mixing Sounds

동시에 재생되는 보조 버퍼는 주 버퍼에서 자동으로 믹싱(혼 합, mixing)된다. Windows driver model(WDM) 하에서는 믹싱은 커널 믹서에 의해 수행되었다. 다른 보조 버퍼는 다른 WAV 포맷(예를 들어 다른 샘플링율)을 가지고 있으며, 사운드는 주버퍼의 포맷이나 필요하면 커널 믹서의 포맷으로 변환된다.

VXD 드라이버 하에서, DirectSound 믹서는 응용프로그램의 사운드가 같은 WAV포맷을 사용하고, 하드웨어 출력 포맷이 사운드의 포맷과 일치하는 경우, 최상의 사운드 품질을 생성한다. 이것이 수행되면, 믹서는 어떠한 포맷 형변환도 수행할 필요가 없다. 응용프로그램은 하드웨어 출력 포맷을 주 사운드 버퍼 개체를 생성하고, IdirectSoundBuffer8::SetFormat 메서드를 호출함으로써 변경할 수 있다. 이렇게 하기 위해서는 우선순위 협력 레벨(Priority Cooperative Level)을 필요로 한다. 보조 버퍼를 생성하기 이전에 반드시 주 버퍼를 설정해야만 한다. DirectSound는 응용프로그램이 입력 포커스를 획득할 때마다 마지막 호출에서 지정된 포맷에 대한 하드웨어 포맷을 재저장할 것이다.

WDM 드라이버 상에서, 보조 버퍼 포맷을 설정하는 것은 아무런 효과가 없다. 포맷은 커널 믹서에 의해 결정된다. 더 많은 정보를 원하면 DirectSound Driver Models를 참조하라.

 

 Looping Sounds

DirectSound 는 사운드의 부분적인 반복이나 전체 반복을 직접 지원하지 않는다. 반복의 끝에 도달할 때마다 반복의 시작점으로 재생커서를 재설정함으로써 정적 버퍼상에서 반복을 구현하는 것이 가능하기는 하지만, 그렇게 하는 것은 갑작스런 오디오 펄스의 변화(audio glitches)를  일으켜서, DirectSound는 미리 처리된 데이터(preprocessed data)를 버리고, 전처리(preprocessing)를 다시 시작해야만 할 수도 있다.

사운드의 일부를 반복하기 위해서는, 스트리밍 버퍼에서 사운드를 재생하고, 소스 데이터 안에서 반복을 구현한다.

See Also

  • Using Streaming Buffers

 

 Buffer Management

IdirectSoundBuffer8::GetCaps 메서드는 DirectSoundBuffer 개체의 기능을 검색한다.

응용프로그램은 IdirectSoundBuffer8::GetStatus 메서드를 사용하여 버퍼가 재생되고 있는지, 혹은 멈춰있는지를 확인할 수 있다.

IDirectSoundBuffer8::GetFormat 메서드는 버퍼 안의 사운드 데이터의 포맷에 대한 정보를 검색하는데 사용될 수 있다. IdirectSoundBuffer8::SetFormat 메서드를 사용해 주버퍼의 사운드 데이터 포맷을 설정할 수도 있다. 더 많은 정보를 원하면 Mixing Sounds를 참조하라.

Note   SetFormat 메서드는 보조 버퍼 상에서 호출될 수 없다. 보조 버퍼가 생성된 이후에, 그것의 포맷은 혼합된다. 다른 포맷으로 되어 있는 사운드를 재생하기 위해서는, 이 포맷을 가진 새로운 사운드 버퍼를 생성해야만 한다.

사운드 버퍼에 대한 메모리는 특정한 상황에서 소실될 수 있다; 예를 들어 버퍼가 사운드 카드 메모리 안에 위치했을 때나, 다른 응용프로그램이 하드웨어 자원들에 대한 제어를 획득했을 때이다. 소실(loss)은 write-primary 협력 레벨을 가진 응용프로그램이 프로그램 최상위 우선순위를 얻게 되었을 때도 발생한다; 이 경우 DirectSound는 다른 사운드 버퍼를 소실되게 만들고, 최상위 우선순위를 얻은 응용프로그램은 주 버퍼에 직접 쓸 수가 있다.

DSERR_BUFFERLOST 에러 코드는 IdirectSoundBuffer8::Lock 이나 IdirectSoundBuffer8::Play 메서드가 소실된 버퍼에 대해 호출되었을 때 반환된다. 응용프로그램이 write-primary 보다 더 낮은 협력 레벨을 가지거나, 낮은 우선순위로 이동할 때, 다른 응용프로그램은 IdirectSoundBuffer8::Restore 메서드를 호출함으로써 버퍼 메모리를 재할당하려고 시도할 수 있다. 만약 성공적이면, 이 메서드는 버퍼 메모리와 볼륨이나 팬 설정 같은 버퍼에 대한 다른 모든 설정이 재저장된다. 그러나 재저장된 버퍼는 유효한 데이터를 가지고 있지 않을 수 있다. 그래서 (역자주 : 버퍼를) 소유하고 있는 응용프로그램은 데이터를 버퍼에 다시 작성해야 한다.

 

4) Using WAV Data

WDM(Windows driver model) 하에서 DirectSound 하드웨어 버퍼는 하드웨어에 의해 지원되는 포맷을 제공하는 WAVEFORMATEX 나 WAVEFORMATEXTENSIBLE 구조체 안에 기술될 수 있는 압축, 혹은 비압축 사운드 포맷을 모두 재생할 수 있다.(원문 : Under the Windows driver model (WDM), DirectSound hardware buffers can play any uncompressed or compressed sound format that can be described in a WAVEFORMATEX or WAVEFORMATEXTENSIBLE structure, provided the format is supported by the hardware.)소프트웨어 버퍼와 비WDM 하드웨어 버퍼는 단지 8비트와 16비트의 비압축 포맷을 지원할 뿐이다.

waveform (혹은 WAV) 데이터는 보통 파일에 저장되거나 Resource Interchange File Format(RIFF)으로 리소스에 저장된다. 그 데이터는 샘플링율이나 출력 채널의 개수와 같은 인자를 포함하는 WAV 포맷에 대한 기술을 포함한다.

WAV 사운드에 대한 더 많은 정보는 다음의 주제들에 포함되어 있다:

  • Multichannel WAV Formats
  • Reading WAV Data
  • Calculating the Duration of a WAV Sound

 

 

 

반응형

 

728x90

 

 

 Multichannel WAV Formats

WDM 드라이버 상에서, DirectSound는 front left, front center, front right, back left, back right에 스피커를 가지고, 부가적으로는 low-frequency enhancer(역자주 : 우퍼)를 가지는 5.1과 같은 스피커 구성을 위해 두 개 이상의 출력 채널을 가질 수 있는 WAV 포맷을 지원한다.

WAVEFORMATEXTENSIBLE 구조체는 다중 채널 wave 포맷을 기술한다. 이 구조체는 WAVFORMATEX 의 cbSize 멤버에 의해 이미 지원되었던 부가적인 바이트를 구성하는 WAVEFORMATEX의 확장이다. WAVEFORMATEXTENSIBLE 구조체는 예를 들어 DSBUFFERDESC 구조체에서 처럼 요구가 있다면 WAVEFORMATEX로 형변환될 수 있다.

시스템이 다중 채널 WAV 파일에서 지정된 채널의 개수보다 적은 물리적 스피커로 구성되어 있다면, 오디오 데이터는 적절하게 혼합되고 현존하는 스피커로 출력된다.

DirectSound 는 이펙트나 3-D 처리를 다중채널 포맷으로 된 버퍼 상에서 지원하지 않는다. DSBCAPS_CTRL3D나 DSBCAPS_CTRLFX 플래그를 가진 버퍼를 생성하거나 다중 WAV 포맷을 생성하려고 시도하면 실패할 것이다.

다중 WAV 포멧에 대한 정보를 더 원한다면, Multiple Channel Audio Data and WAVE Files를 참조하라. 이는 www.microsoft.com에서 볼 수 있다.

 

 Reading WAV Data

WAV 파일은 헤더 정보(예를 들어 사운드 샘플의 포맷)나 데이터(샘플 자체)를 포함하는 다양한 개수의 이름있는(named) 청크로 구성된 Resource Interchage File Format(RIFF)으로 되어 있다. Win32 API는 RIFF 파일을 열고, 닫고, 청크를 검색하는 등의 작업을 위한 함수를 제공한다. 이러한 함수의 이름은 “mmio”로 시작한다.

실행가능하게 WAV 사운드를 저장하기 위해서는, WAV 파일을 리소스로서 임포트하고, 그것들에 문자열 이름을 설정한다. CwaveFile  Sample Class(역자주 : M$ 예제)는 이러한 리소스들이 “WAVE”나 “WAV”일 것을 요구하며, 그것들을 DLL보다는 실행가능한 모듈에서 검색하기를 원한다.

DirectSound API는 사운드 데이터를 읽기 위한 메서드는 지원하지 않는다. 그러나 많은 SDK 샘플 응용프로그램에서 사용된 Dsutil.cpp파일은 파일이나 리소스, 메모리 위치로부터 사운드 버퍼를 생성하는데 사용될 수 있는 몇 개의 클래스를 구현한다.

샘플 클래스를 사용하여 DirectSound를 초기화하고 버퍼를 생성하거나 로드하는 것은 다음과 같은 기본적인 단계를 포함한다:

  1. CSoundManager 샘플 클래스의 개체를 생성한다.
  2. CsoundManager::Initialize를 호출하여 장치 개체를 생성한다.
  3. 파일이나 리소스의 이름을 CsoundManager::Create에 넘기거나 메모리 위치를 CsoundManager::CreateFromMemory로 넘긴다. 이들 메서드는 Csound 샘플 클래스의 개체를 반환하는데, 이 개체는 데이터를 포함하기에 충분히 큰 하나 이상의 정적 버퍼를 의미한다.(동시에 여러 개의 사운드 인스턴스를 재생하기 위한 다중 버퍼를 생성할 수 있다) 그렇지 않으면 파일이나 리소스의 이름을 CSoundManager::CreateStreaming으로 넘기는 방법도 있다. 이 메서드는 단일 스트리밍 버퍼를 의미하는 CStreamingSound 샘플 클래스의 개체를 반환한다.
  4. 이전 단계에서 획득한 개체 상에서 FillBufferWithSound 메서드를 호출한다. 이것은 파일이나 리소스, 메모리 위치로부터 버퍼로 데이터를 읽어들인다. 스트리밍 버퍼에 대해서는 그것이 저장할 수 있는 만큼의 데이터만을 버퍼에 채운다; 버퍼가 재생되는 것만큼 데이터를 갱신하기 위해서는 CstreamingSound::HandleWaveStreamNotification을 사용한다.

실제 데이터 읽기 작업은 CSound나 CstremingSound 개체의 protected 멤버인  CWaveFile 개체에 의해 수행된다는 점에 주의하라. 일반적으로 CWaveFile을 직접 사용할 필요는 없다; 그러나 WAV 데이터가 어떻게 분석되는 지에 대한 정보를 얻기 위해서 이 클래스의 구현을 참조할 수는 있다.

See Also

  • DirectSound Sample Framework

 

 Calculating the Duration of a WAV Sound

waveform 이 재생될 시간의 길이는 데이터의 크기와 포맷에 의해 결정된다. 데이터의 크기와 포맷은 DirectSound 샘플 프레임워크의 CWaveFile::GetSize와 CWaveFile::GetFormat 메서드에 의해서 검색될 수 있다.

샘플 클래스에서 사용되지는 않는 다음 예제 함수는 밀리세컨드(1000분의 1초, milliseconds) 단위로 WAV 파일의 재생시간(duration)을 반환한다:

 

DWORD GetSoundLength(LPSTR strFileName) {
    CWaveFile * pWav;
    DWORD dwLen = 0;
    DWORD dwSize;
    WAVEFORMATEX * wfx;

    pWav = new CWaveFile();
    if (SUCCEEDED(pWav - > Open(strFileName, NULL, WAVEFILE_READ))) {
        wfx = pWav - > GetFormat();
        dwSize = pWav - > GetSize();
        dwLen = (DWORD)(1000 * dwSize / wfx - > nAvgBytesPerSec);
        pWav - > Close();
    }
    if (pWav) delete pWav;
    return dwLen;
}

 

See Also

  • CWaveFile Sample Class
  • DirectSound Sample Framework
  • Reading WAV Data

 

5) 3-D Sound

DirectSound 를 사용해 3-D 그래픽에 통합될 수 있는 사운드를 위해 3-D 세계를 생성할 수 있다. 사운드 소스와 청취자를 공간에 배치하고, 도플러(Doppler) 효과를 적용해 움직이는 사운드를 변화(shift)시킬 수 있으며, 거리에 따른 사운드의 감쇄율과 같은 물리적 인자를 제어할 수 있다.

DirectSound 는 가상 3-D 이펙트를 두 개의 스피커나 헤드셋에 생성할 수 있다. 또한 사용자가 Control Panel에서 서라운드 사운드 스피커를 선택했다면 WDM 드라이버를 사용해 다중 채널 시스템의 이점을 취할 수도 있을 것이다. 더 많은 정보를 원한다면 DSBUFFERDESC를 참조하라.

다음 주제들은 일반적인 관점에서의 3-D 사운드에 대해 다루고 있다:

  • Coordinates of 3-D Space
  • Perception of Sound Positions

다음 섹션에서는 응용프로그램에서 3-D 사운드를 사용하는 방법에 대한 정보를 찾을 수 있다 :

  • DirectSound 3-D Buffers
  • DirectSound 3-D Listeners

 

 Coordinates of 3-D Space

3-D 공간에서 사운드 소스(sound sources)와 청취자(listeners)의 위치(position), 세기(velocity), 방향(orientation)은 세 개의 축에 대한 값인 데카르트 좌표계(Cartesian coordinates)로 표현된다: x축, y축, z축. 이들 축은 응용프로그램에 의해 확정된 뷰포인트와 관련이 있다. X축의 값은 왼쪽에서 오른쪽으로 증가하며, y 축의 값은 아래에서 위로 증가한다, 그리고 z축은 가까운 쪽에서 먼 쪽으로(역자주 : 화면 안쪽으로) 증가한다.

D3DVECTOR 구조체는 세 축에 대한 위치, 세기, 방향을 기술할 수 있는 값을 포함한다.

일반적으로 벡터는 (x, y, z) 순으로 괄호 안에 콤마로 분리된 세 값으로 표현된다.

위치에 대해 값은 기본적으로 미터(meters) 단위이다. 만약 응용프로그램이 3-D 그래픽을 위한 측정 단위로 미터를 사용하지 않는다면, 응용프로그램에 정의된 거리 단위에 대한 미터(meters per applicatioin-specified distance unit)를 의미하는 부동소수점 값인 distance 요소를 설정할 수 있다. 예를 들어 응용프로그램이 feet 를 사용한다면, 그것은 발 하나의 미터 수를 의미하는 0.3048의 거리 요소를 지정할 수 있다. 더 많은 정보를 원한다면 Distance Factor를 참조하라.

세기에 대해, 벡터는 초당 어떠한 단위로 각 축을 이동한 비율을 기술한다. 다시 말하는데 기본 단위는 미터이지만, 이 값은 응용프로그램에 의해 수정될 수 있다.

(원문 : For velocity, the vector describes the rate of movement along each axis in units per second. Again, the default unit is meters, but this can be changed by the application.)

 

방향에 대해 그 값은 임의의 단위이며, 다른 것에 대해 상대적이다. 만약 3-D 세계의 기본(base) 뷰가 수평선을 향해 북쪽을 바라보고 있고, 청취자의 (역자주 : 시선)방향이 (-1, 0, 1)이라면 청취자는 북서쪽을 바라보고 있는 것이다. 벡터의 값들은 절대값이 아니기 때문에, 그 벡터는 (-5, 0, 5) 나 (-0.25, 0. 0.25)로 표현되어도 같은 의미가 된다.

 

(원문 : For orientation, the values are in arbitrary units and are relative to one another. If the base view of the 3-D world is facing north toward the horizon, and the orientation of the listener is (-1, 0, 1) the listener is facing northwest. Because the values within a vector are not in absolute units, the vector could equally well be expressed as (-5, 0, 5) or (-0.25, 0, 0.25).)

 

(역자주 : 아래는 종이에 벡터 그리는 법 설명이라 그냥 넘어갑니다. 역시 수학해석은 ㅠㅠ)

You can see how vectors in 2-D space work by drawing them on a sheet of graph paper. Let the values increase from the bottom of the paper to the top and from left to right. A line drawn from (0, 0) to (1, 1) has the same orientation, or direction, as one drawn from (0, 0), to (5, 5). However, the second line indicates a greater distance, or velocity. 3-D vectors work in just the same way, with an additional axis in the up-down direction.

 

 Perception of Sound Positions

실제 세계에서 공간 안의 사운드 위치를 인식하는 것은 몇 가지 요소에 의해 영향을 받는다. 이러한 모든 요소가 청각적인 것은 아니다; 가장 중요한 것은 시야(sight)이다. 사운드 자체로부터의 실마리는 다음을 포함한다(원문 : Clues from the sounds themselves include the following):

  • Overall loudness. 사운드 소스가 청취자로부터 멀어지는 방향으로 움직이면, 그것의 인식되는(들리는?) 볼륨은 고정된 비율로 감소한다. 이 현상은 롤오프(rolloff)로 알려져 있다.
  • Interaural intensity difference. 청취자의 오른쪽에서 발생한 사운드가 왼쪽 귀보다는 오른쪽 귀에서 더 크게 들린다.
  • Interaural time difference. 청취자의 오른쪽에 있는 소스로부터 발생한 사운드가 왼쪽 귀보다는 오른쪽 귀에 약간 빨리 도달한다. 이 차이는 거의 밀리세컨드 정도이다.
  • Muffling. 청취자의 뒤로부터 발생한 사운드가 앞에서 발생하는 사운드보다 약간 둔탁해지는데, 귀의 모양과 방향이 그것의 정도를 결정한다. 부가적으로 사운드가 오른쪽으로부터 발생했다면, 왼쪽 귀에 도달하는 사운드는 청취자 머리의 부피뿐만 아니라 왼쪽 귀의 방향에 의해서도 둔탁해 질 것이다.
  • Effect of the earlobes. 귓바퀴나 귀의 주름은 음정과 다른 방향에서 도달하는 사운드의 시간차에 약간의 차이를 발생시킨다. 이 효과에 대한 수학 이론은 HRTF(head-related transfer function)로 알려져 있다.

 

 DirectSound 3-D Buffers

3-D 환경에 있는 각 사운드 소스는 IDirectSound3Dbuffer8 인터페이스에 의해 표현된다. 이 인터페이스는 단지 DSBCAPS_CTRL3D 플래그를 통해 생성된 사운드 버퍼에 의해서만 지원된다. 이 인터페이스의 메서드는 단일 사운드 소스의 인자들을 설정하고 검색하는 데 사용된다.

응용프로그램은 DirectSound의 3-D 기능을 사용할 때 반드시 단청(한쪽 귀만의, monaural)의 사운드 소스를 제공해야만 한다. 만약 DSBCAPS_CTRL3D플래그 세트를 가진 버퍼와 두 개 이상의 채널을 가진 WAV 포맷을 생성하려고 시도한다면, 에러를 일으키게 된다.

이 섹션은 응용프로그램이 3-D 개체를 획득하고 관리하는 방법에 대해 기술한다. 다음 주제들이 논의된다:

  • Obtaining the 3-D Buffer Object
  • Minimum and Maximum Distances
  • Processing Mode
  • Buffer Position and Velocity
  • Sound Cones
  • Batch Parameters for 3-D Buffers

 

) Obtaining the 3-D Buffer Object

IDirectSound3Dbuffer8 인터페이스는 DSBUFFERDESC 구조체의 dwFlags 멤버가DSBCAPS_CTRL3D 플래그로 생성된 보조 DirectSound 버퍼로부터 획득할 수 있다.

응용프로그램이 DirectMusic 기능(performance)를 사용하지 않고 자체의 DirectSound 보조 버퍼를 생성하고 관리하고 있는 중이라면, 다음의 샘플코드에서와 같이 버퍼에 QueryInterface 메서드를 호출함으로써 IDirectSound3Dbuffer8을 획득할 수 있는데, lpDsbSecondary는 IdirectSoundBuffer8 인터페이스이다.

LPDIRECTSOUND3DBUFFER8 lpDs3dBuffer;

HRESULT hr = lpDsbSecondary - > QueryInterface(IID_IDirectSound3DBuffer8,
    (LPVOID * ) & lpDs3dBuffer);

 

See Also

  • Using Effects in DirectMusic

 

) Minimum and Maximum Distances

청취자가 사운드 소스에 접근할수록, 사운드는 커딘다; 거리가 절반이 되면 볼륨은 두 배가 된다. 그러나 특정 지점을 지나면 볼륨을 계속해서 증가시키는 것은 불합리하다. 이것이 사운드 소스에 대한 최소 거리이다.

사운드에 대해 설정하는 최소거리는 소리가 거리에 따라 얼마나 빨리 작아질 지(원 문 : fade away with distance)를 결정한다. 예를 들어서 이 값을 제트 엔진에 대해서는 100 미터로 벌에 대해서는 2센티미터로 지정할 수 있다. 이러한 설정을 사용하여, 제트엔진은 청취자에서 200미터 만큼 벌어지면 볼륨이 절반이 되지만, 벌은 단지 4센티미터만 멀어져도 볼륨이 절반이 된다.

다음 그림은 거리가 증가함에 따라서 제트엔진과 벌의 볼륨에 최소와 최대 거리가 어떠한 영향을 미치는 지를 보여준다.

 

사운드 버퍼에 대한 기본 최소 거리는 DS3D_DEFAULTMINDISTANCE이며 1 단위나 기본 거리 요소에서 1미터로 정의되어 있다.(원문 : The default minimum distance for a sound buffer, DS3D_DEFAULTMINDISTANCE, is defined as 1 unit, or 1 meter at the default distance factor.) 이 값을 바꿀 필요가 없다면 청취자로부터 1미터가 떨어져 있을 때 전체 볼륨의 소리가 날 것이며, 2미터 떨어지면 절반의 볼륨, 4미터 떨어지면 1/4의 볼륨의 소리가 나는 식이다. 대부분의 사운드에 대해서 아마도 더 큰 최소 거리를 설정하기를 원할 것이다. 그래야만 거리가 멀어질 때마다 급격하게 소리가 줄어들지 않을 것이다.

사운드 소스에 대한 최대 거리는 사운드의 볼륨이 더 이상 감소하지 않는 거리이다. 기본 DirectSound 3-D 버퍼를 위한 최대 거리(DS3D_DEFAULTMAXDISTANCE)는 1억미터인데, 이는 대부분의 경우 사운드가 들리는 범위 밖으로 나가고 난 이후에도 계속해서 감쇄가 계산될 것이라는 것을 의미한다. VXD 드라이버 하의 소프트웨어 버퍼 상에서 불필요한 처리를 피하기 위해서는, 응용프로그램은 합리적인 최대 거리를 설정해야만 하며, DSBCAPS_MUTE3DATMAXDISTANCE 플래그를 버퍼 생성시에 포함해야만 한다. DirectMusic에서 이 플래그는 audiopath의 일부로서 생성된 표준 3-D버퍼에 자동으로 설정된다.

최대 거리는 사운드가 들리지 않는 것을 방지하기 위해 사용되기도 한다. 예를 들어서 사운드에 대해 최소 거리를 100미터로 설정했다면, 그 사운드는 1,000 미터나 그보다 약간 이전에서는 실제적으로 들리지 않게 될 것이다. 최대 거리를 800 미터로 설정함으로써, 사운드가 항상 거리에 상관없이 적어도 1-8의 최대 볼륨을 가질 수 있게 보장한다

 

(역자주 : 전체 사운드를 10이라고 본 것 같음). 물론 이 경우에 DSBCAPS_MUTE3DATMAXDISTANCE 플래그를 설정해서는 안된다.

 

(원문 : The maximum distance can also be used to prevent a sound from becoming inaudible. For example, if you have set the minimum distance for a sound at 100 meters, that sound might become effectively inaudible at 1,000 meters or less. By setting the maximum distance at 800 meters, you ensure that the sound always has at least one-eighth of its maximum volume regardless of the distance. In this case, of course, you would not set the DSBCAPS_MUTE3DATMAXDISTANCE flag.)

기본적으로 거리 값은 미터로 표현된다.

 

모든 사운드 버퍼에 대해 볼륨에서 거리에 따른 효과를 적용하고자 한다면, rolloff 요소를 변경할 수 있다.

See Also

  • IDirectSound3DBuffer8::GetMinDistance
  • IDirectSound3DBuffer8::SetMinDistance
  • IDirectSound3DBuffer8::GetMaxDistance
  • IDirectSound3DBuffer8::SetMaxDistance
  • Distance Factor
  • Rolloff Factor

 

) Processing Mode

사운드 버퍼는 세 가지 처리(processing) 모드를 가지고 있다: normal, head-relative, disabled.

normal 모드에서 사운드 소스는 월드 공간에서 절대적인 좌표에 위치하고, 절대적인 좌표를 향한다. 이것은 기본 모드이며, 움직이지 않고 청취자와 함께 회전하지 않는 사운드에 대해 사용된다.

head-relative 모드에서 사운드 소스의 3-D 속성은 모드 현재 위치, 세기, 청취자의 방향에 관련이 있다. 청취자가 움직이거나 방향을 바꾸면, 버퍼는 자동으로 월드 공간에서의 위치를 재지정한다. head-relative 모드는 청취자의 머리 주변을 돌아다니는 파리 같은 사운드에 대해 사용될 수 있다. 그러나 청취자와 함께 이동하는 대부분의 사운드는 3-D 사운드가 될 필요가 전혀 없다.

disabled 모드에서 3-D 사운드 처리는 불가능하며, 사운드는 청취자 머리의 중심으로부터 나오는 것 처럼 보인다.

See Also

  • IDirectSound3DBuffer8::SetMode

 

) Buffer Position and Velocity

사운드 소스가 이동하면, 그것의 위치와 세기를 지정하는 것은 응용프로그램의 역할이다.

위치는 세 축에 대한 월드 공간이나 청취자에 상대적인 거리로 측정이 되는데, 이는 처리 모드에 의존한다.(원문 : Position is measured in distance units along each of the three axes, relative to either world space or the listener, depending on the processing mode.)

세기는 벡터의 세 축에 대해 초당 거리 단위로 측정된다. 기본적으로 거리단위는 미터이다. 세기는 DirectSound에 의해 Doppler 변화(shift) 효과를 계산하기 위한 목적으로만 사용된다.

See Also

  • IDirectSound3DBuffer8::GetPosition
  • IDirectSound3DBuffer8::SetPosition
  • IDirectSound3DBuffer8::GetVelocity
  • IDirectSound3DBuffer8::SetVelocity
  • Distance Factor
  • Doppler Effect

 

) Sound Cones

방향이 없는 사운드는 모든 방향에서 주어진 거리에 대해 같은 감쇄율을 가진다. 방향을 가진 사운드는 향하고 있는 방향에서 가장 크게 소리난다. 방향이 있는 사운드의 크기를 기술하는 모델을 사운드 콘(cone)이라고 부른다. 사운드 콘은 안쪽 콘 과 바깥쪽 콘으로 이루어져 있다. 바깥쪽 콘 의 각도는 안쪽 콘의 각도와 같거나 커야만 한다.

버퍼의 기본 볼륨과 청취자로부터의 거리, 청취자의 방향 등을 고려한 이후에, 안쪽 콘에서는 마치 콘이라는 것이 존재하지 않는 것처럼 사운드의 볼륨이 결정될 것이다.

(원문 : At any angle within the inner cone, the volume of the sound is just what it would be if there were no cone, after taking into account the basic volume of the buffer, the distance from the listener, the listener's orientation, and so on.)(역자주 : 안쪽 콘에서는 어디에서 소리를 듣더라도 같은 크기로 들린다는 의미인듯)

 

바깥 쪽 콘에서 일반적인 불륨은 응용프로그램에 의해 설정된 요소에 의해 감쇄될 것이다. 바깥쪽 콘의 볼륨은 100단위의 데시벨로 표현되며, 음수이다. 왜냐하면 기본 볼륨인 0으로부터 감쇄되는 것을 표현하기 때문이다.(역자주 : 바깥쪽 콘부터 감쇄가 시작된다는 의미인듯)

안쪽과 바깥쪽 콘 사이는 안쪽 볼륨으로부터 바깥쪽 불륨으로 변화하는 지역이다. 볼륨은 각도가 증가할 때 감소한다.

다음 그림은 사운드 콘의 개념을 보여준다.

모든 3-D 사운드 버퍼는 사운드 콘을 가지는데, 기본 버퍼는 전방향성(omnidirectional, 全方向性, 역자주 : 모든 방향)의 사운드 소스처럼 동작한다. 왜냐하면 바깥쪽 볼륨은 감쇄되지 않으며, 안쪽과 바깥쪽 콘 각도는 360도이기 때문이다. 응용프로그램이 이러한 값들을 변경하지 않는 이상, 사운드는 어떠한 적절한 방향도 가지지 않는다.

사운드 콘을 적절하게 설계하는 것은 응용프로그램에 훌륭한 효과를 추가할 수 있다. 예를 들어서 방의 중간에 사운드 소스를 위치시키고, 그것의 방향을 복도 안의 열려진 문을 향하게 설정한다. 그리고 나서 안쪽 콘의 각도를 설정해 그것이 출입구의 폭만큼 확장되게 설정하고, 바깥쪽 콘은 좀 더 넓게 설정하고, 바깥쪽 콘의 볼륨을 들을 수 없게 한다. 복도를 움직이는 청취자는 사운드를 문 가까이에 왔을 때만 듣기 시작할 수 있을 것이며, 청취자가 문의 앞쪽으로 다가올수록 사운드가 더 크게 들릴 것이다.

 

(원문 : Designing sound cones properly can add dramatic effects to your application. For example, you could position a sound source in the center of a room, setting its orientation toward an open door in a hallway. Then set the angle of the inside cone so that it extends to the width of the doorway, make the outside cone a bit wider, and set the outside cone volume to inaudible. A listener moving along the hallway will begin to hear the sound only when near the doorway, and the sound will be loudest as the listener passes in front of the open door.)

 

See Also

  • IDirectSound3DBuffer8::GetConeAngles
  • IDirectSound3DBuffer8::SetConeAngles
  • IDirectSound3DBuffer8::GetConeOrientation
  • IDirectSound3DBuffer8::SetConeOrientation
  • IDirectSound3DBuffer8::GetConeOutsideVolume
  • IDirectSound3DBuffer8::SetConeOutsideVolume

 

) Batch Parameters for 3-D Buffers

응용프로그램은 3-D 사운드 버퍼의 인자들을 개별적으로 혹은 한꺼번에 검색하거나 설정할 수 있다. 만약 사운드 소스가 움직이고 있으면, 위치, 방향, 세기와 같은 다중 인자들을 한 번에 설정하고자 할 것이다. 현재의 인자들을 검색하기 위해  IDirectSound3Dbuffer8::GetAllParameters 를 호출하고, DS3DBUFFER 구조체의 적절한 인자를 변경한 다음, 그 구조체를 다시 IDirectSound3Dbuffer8::SetAllParemeters를 호출함으로써 그 것을 수행할 수 있다.

인자 변경은 그것들을 연기된(deffered) 것으로 플래그를 지정하고(flagging) 그 다음에 한 번에 실행시킴으로써 더욱 효율적으로 만들어질 수도 있다. 더 많은 정보를 원하면 Deffered Settings를 참조하라.(원문 : Parameter changes can also be made more efficiently by flagging them as deferred and then executing them all at once. For more information, see Deferred Settings.

 

 DirectSound 3-D Listeners

실제 세계에서와 같이 가상 3-D 환경에서 사운드는 수신(reception) 지점에 대해  상대적으로만 존재한다. DirectX 응용프로그램에서 3-D 사운드 효과는 사운드 소스의 위치, 방향, 세기 값에 의해서만 영향을 받는 것이 아니라, 가상 청취자의 위치, 방향, 세기에도 영향을 받는다.

기본적으로 청취자는 모든 벡터의 0점에 정지되어 있으며, 코는 양의 Z축을 향하고 머리는 양의 Y축을 향해 있다. 응용프로그램은 이러한 모든 값을 변경해 가상공간에서의 사용자의 전면(facing)과 이동을 반영한다. 청취자 개체는 Doppler 변화의 양과 거리에 따른 볼륨 감쇄의 비율 같은 청각(acoustic) 환경의 일반적인 인자를 제어할 수도 있다.

이 섹션은 응용프로그램이 청취자 개체를 획득하고 전역 3-D 사운드 인자를 관리하는 방법에 대해 기술한다. 다음 주제들이 논의된다 :

  • Obtaining the 3-D Listener
  • Spatial Parameters of the Listener
  • Distance Factor
  • Doppler Effect
  • Rolloff Factor
  • Batch Parameters for 3-D Listeners
  • Deferred Settings

 

) Obtaining the 3-D Listener

전역 사운드 인자는 주버퍼로부터 IDirectSound3Dlistener8 인터페이스를 사용함으로써 설정되고 획득된다. 응용프로그램에는 단지 하나의 주버퍼와 하나의 청취자만이 존재한다.

응용프로그램이 DirectMusic audiopaths를 사용하고 있지 않다면, 주버퍼 개체를 생성한 다음에 그것으로부터 청취자 인터페이스를 획득해야만 한다. DSBCAPS_CTRL3D와 DSBUFFERDESC 구조체의 dwFlags 멤버를 DSBCAPS_PRIMARYBUFFER 플래그로 설정하고, IDirectSound8::CreateSoundBuffer 메서드를 사용해 주버퍼를 생성한다. 그 버퍼에 대한 IDirectSound3Dlistener8 의 포인터를 획득하기 위해서 결과 버퍼 상에서 QueryInterface 메서드를 호출한다.

다음 예제 함수는 청취자의 인터페이스를 획득한다.

 

GetListener(LPDIRECTSOUND8 lpds, LPDIRECTSOUND3DLISTENER8 * ppListener) {
    DSBUFFERDESC dsbd;
    LPDIRECTSOUNDBUFFER lpdsbPrimary; // IDirectSoundBuffer8을 사용할 수 없음.
    LPDIRECTSOUND3DLISTENER8 lp3DListener = NULL;
    HRESULT hr;

    ZeroMemory( & dsbd, sizeof(DSBUFFERDESC));
    dsbd.dwSize = sizeof(DSBUFFERDESC);
    dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;

    if (SUCCEEDED(hr = lpds - > CreateSoundBuffer( & dsbd, & lpdsbPrimary, NULL))) {
        hr = lpdsbPrimary - > QueryInterface(IID_IDirectSound3DListener8,
            (LPVOID * ) ppListener);
        lpdsbPrimary - > Release();
    }
    return hr;
}

 

See Also

  • Using 3-D Sound in DirectMusic

 

) Spatial Parameters of the Listener

사운드 소스와 마찬가지로, 청취자도 3-D 월드에서의 위치, 방향, 세기를 가지고 있다.

청취자의 방향은 청취자의 머리 중앙에서 원점(origin) 을 공유하는 두 벡터 사이의 관계에 의해 정의된다: top 과 front 벡터. 다음의 그림에서처럼 top 벡터는 머리의 위쪽을 곧장 가리키며, front는 top 벡터에 대해 직각으로 청취자의 얼굴 앞쪽을 가리킨다.

기본적으로 front 벡터는 (0.0, 0.0. 1.0)이며, top 벡터는 (0.0, 1.0, 0.0)이다. 두 벡터는 반드시 다른 하나에 대해서 직각이어야만 한다. 필요하다면 DirectSound는 front 벡터를 조정해 top 벡터에 대해서 수직이 되도록 할 것이다.

위치는 벡터를 따라서 거리 단위로 측정된다.

세기는 벡터를 따라 초당 거리 단위로 측정된다. 기본적으로 거리 단위는 미터이다. 세기는 DirectSound에 의해 도플러(Doppler) 변화에 대한 효과를 계산하기 위한 목적으로만 사용된다.

See Also

  • IDirectSound3DListener8::GetOrientation
  • IDirectSound3DListener8::SetOrientation
  • IDirectSound3DListener8::GetPosition
  • IDirectSound3DListener8::SetPosition
  • IDirectSound3DListener8::GetVelocity
  • IDirectSound3DListener8::SetVelocity

 

) Distance Factor

거리 요소는 벡터 단위에서 미터의 숫자이다. 기본적으로 거리 요소는 1.0이다. 만약 버퍼의 세기가 (2.0, 0.0, 0.0)이라면 사운드 소스는x축을 따라 초당 2미터를 움직일 것이라고 고려할 수 있다. 3-D 그래픽 벡터에 대한 다른 측정 단위를 사용하는 응용프로그램은 아마도 거리 요소를 그에 맞게 변경하고자 할 것이다.

예를 들어 응용프로그램에서 기본 측정 단위가 foot(역자주 : 발 하나 크기)나 0.3048 미터라고 가정해 보자. 거리 요소를 0.3048로 설정하자. 그로부터 당신은 메서드 호출을 위한 인자에서 feet를 사용하고, 그것은 자동적으로 미터로 변환된다.

거리 요소는 주요하게는 도플러 변화에 영향을 미치는데, 이는 초당 n 단위에 의해 표현되는 실제 세기를 변환함으로써 수행된다. 그것은 rolloff에 직접적으로 영향을 끼치지 않는다. 왜냐하면 거리에 따른 감쇄율은 벡터 단위의 최소 거리에 기반하고 있기 때문이다. 만약 주어진 사운드에 대한 최소 거리를 2 라는 단위로 설정하였다면, 그것들의 단위가 feet이든, 미터이든, 아니면 다른 측정 단위이건 간에 상관 없이 볼륨은 4라는 단위의 거리에서 반으로 작아질 것이다. 더 많은 정보를 원하면 Minmum and Maximum Distance를 참조하라.

See Also

  • IDirectSound3DListener8::GetDistanceFactor
  • IDirectSound3DListener8::SetDistanceFactor

 

) Doppler Effect

DirectSound 는 자동적으로 세기를 가지고 있는 버퍼나 청취자에 대한 도플러 변화 효과를 생성한다. 효과는 누적된다(cumulative): 만약 청취자와 사운드 버퍼가 모두 움직이면, 시스템은 자동적으로 상대적인 세기를 계산하고, 도플러 효과를 그에 맞게 조정한다.

응용프로그램에서 사실적인 도플러 변화 효과를 얻기 위해, 움직이고 있는 개체의 속도를 계산하고, 적절한 세기를 사운드 소스나 청취자에 설정해야만 한다. 특별한 효과를 위해서 개별적인 경우에 이 값을 마음대로 과장하거나 축소할 수 있다. 또한 도플러 요소를 변경함으로써 도플러 변화를 전역적으로 증가시키거나 감소시킬 수 있다.

도플러 요소는 DS3D_MINDOPPLERFACTOR부터 DS3D_MAXDOPPLERFACTOR 까지의 범위를 가질 수 있는데, 이는 0.0 과 10.0으로 정의되어 있다. 0 값은 사운드에 도플러 변화가 적용되지 않는다는 것을 의미한다. 모든 다른 값들은 실제 세계에서의 다중 도플러 변화를 표현한다.

See Also

  • IDirectSound3DListener8::GetDopplerFactor
  • IDirectSound3DListener8::SetDopplerFactor

 

) Rolloff Factor

rolloff는 사운드에 적용되는 감쇄의 총합으로 사운드 소스로부터의 청취자의 거리에 기반한다. DirectSound는 rolloff을 무시하거나, 그것을 과장하거나, 실제 세계에서와 같은 효과를 줄 수 있는데, 이는 rolloff 요소라 불리는 전역 인자에 기반하고 있다.

rolloff 요소는 DS3D_MINROLLOFFFACTOR 부터 DS3D_MAXROLLOFFFACTOR까지의 값을 가지는데, 그것은 사운드가 청취자로부터의 거리에 관계없이 전체 볼륨을 유지할 수 있음을 의미한다. 모든 다른 값들은 다중 실세계의 rolloff 를 표현한다.

rolloff 요소는 전역적이다. 개별 사운드 버퍼에 대한 거리의 효과를 변경하기 위해서, 버퍼에 대한 최소 거리를 설정할 수 있다.

See Also

  • IDirectSound3DListener8::GetRolloffFactor
  • IDirectSound3DListener8::SetRolloffFactor
  • Minimum and Maximum Distances

 

) Batch Parameters for 3-D Listeners

응용프로그램은 3-D 청취자 개체의 인자를 개별적으로 혹은 여러 개를 동시에 설정하거나 획득할 수 있다. 만약 청취자가 이동하고 있다면, 위치, 방향, 세기 같은 인자들을 한꺼번에 설정하고자 할 것이다. 현재의 인자를 획득하기 위해서 IDirectSound3Dlistener8::GetAllParameters를 사용하거나, DS3DLISTENER 구조체의 적절한 인자를 수정하고, 그 구조체를 IDirectSound3Dlistener8::SetAllParemeters 로 다시 보내 이러한 작업을 수행할 수 있다.

연기되도록 플래그를 설정하고 그것을 한꺼번에 실행함으로써 더욱 효율적으로 인자변경이 이루어지게 할 수도 있다. 더 많은 정보를 원한다면 Deffered Settings를 참조하라.

 

) Deferred Settings

3-D 사운드 버퍼와 청취자 설정들에 대한 모든 변경은 CPU 사이클을 희생해 가면서  재 혼합(remixing)을 일으킨다. 3-D 설정을 변화해서 생기는 수행성 악화를 최소화하기 위해서, 3-D 설정을 바꾸는 IDirectSound3Dlistener8이나 IDirectSound3Dbuffer8 메서드의 dwApply 인자에 DS3D_DEFFERED 플래그를 설정한다. 그리고 나서 IDirectSound3Dlistener8::CommitDefferedSettings 메서드를 호출해 모든 연기된 명령들을 한 번에 실행시킨다.

연기되었던 설정들은 즉각적인 설정을 통해 덮어 쓰여진다. 예를 들어 만약 청취자의 세기를 DS3D_DEFFERED 플래그와 함께 (1.0, 0.0, 0.0)으로 설정하고, 그것을 DS3D_IMMEDIATE 플래그와 함께 (2.0, 0.0, 0.0)으로 설정한다면, 세기는 (2.0, 0.0, 0.0)이 되고, CommitDefferedSettings 가 호출되었을 때 변경되지 않는다.

 

6) Using Effects

DirectX는 DirectX Media Objects(DMOs)를 통한 사운드의 이펙트 처리를 지원한다. 표준 이펙트 세트는 모든 DirectX 응용프로그램에서 이용 가능하다. 다른 DMOs는 시스템에 등록될(registered) 수 있다.

Waves reverberation(반사, 여운)을 기대하는 모든 표준 DMOs는 8이나 16비트 PCM 데이터를 DirectSound에 의해 지원되는 샘플링율로 하나나 두 개의 채널로 처리할 수 있다. Waves reverberation은 8비트 샘플을 지원하지 않는다.

이펙트를 구현하기 위해 DirectSound 응용프로그램은 먼저 COM을 초기화하기 위해서 CoInitialize를 호출해야만 한다. 이렇게 한다고 해서 DirectSoundCreate8을 사용해 장치 개체를 생성하지 못하는 것은 아니다.(원문 : Doing so does not preclude creating the device object by using DirectSoundCreate8.)

DirectSound API를 사용하여 이펙트를 포함하고 있는 다른 버퍼로 다중 버퍼의 출력이 혼합되는 이펙트의 체인을 생성하는 것은 불가능하다. 버퍼 체인은 DirectMusic을 위해 제작된 컨텐츠에서만 이용 가능하다. 더 많은 정보를 원한다면 Buffer Chains를 참조하라.

이펙트를 설정하고 사용하는데 대한 정보를 포함하는 주제들이 다음에 나와 있다:

  • Setting Effects on Buffers
  • Effect Parameters
  • Standard Effects

 

 Setting Effects on Buffers

DSBUFFERDESC 구조체에 DSBCAPS_CTRLFX 플래그가 설정되어 생성된 보조버퍼 상에 여러 개의 이펙트를 설정할 수 있다. 버퍼는 반드시 중지되고 잠겨 있어야만 한다. DirectX 9.0 에서 이펙트는 결코 하드웨어 가속되지 않는다. 하드웨어 버퍼에 이펙트를 설정하는 것은 가능하지만, 그렇게 하는 것은 아무런 이점이 없다.

이펙트는 매우 작은 버퍼에서는 부드럽게 작동하지 않을 것이다. DirectSound는 데이터를 0.015초보다 적은 데이터를 저장하는 이펙트 가능 버퍼의 생성을 허용하지 않는다.(원문 : DirectSound does not permit the creation of effects-capable buffers that hold less than 150 milliseconds of data.) 이 값은 DSBSIZE_FX_MIN으로 정의되어 있다

다음 샘플 함수는 버퍼에 에코(echo) 이펙트를 설정하고, 개발 환경의 출력 윈도우에 결과를 디스플레이한다.

 

HRESULT SetEcho(LPDIRECTSOUNDBUFFER8 pDSBuffer) {
    HRESULT hr;
    DWORD dwResults[1]; // One element for each effect.

    // 이펙트를 기술한다.
    DSEFFECTDESC dsEffect;
    memset( & dsEffect, 0, sizeof(DSEFFECTDESC));
    dsEffect.dwSize = sizeof(DSEFFECTDESC);
    dsEffect.dwFlags = 0;
    dsEffect.guidDSFXClass = GUID_DSFX_STANDARD_ECHO;

    // 이펙트를 설정한다
    if (SUCCEEDED(hr = pDSBuffer - > SetFX(1, & dsEffect, dwResults))) {
        switch (dwResults[0]) {
            case DSFXR_LOCHARDWARE:
                OutputDebugString("Effect was placed in hardware.");
                break;
            case DSFXR_LOCSOFTWARE:
                OutputDebugString("Effect was placed in software.");
                break;
            case DSFXR_UNALLOCATED:
                OutputDebugString("Effect is not yet allocated to hardware or software.");
                break;
        }
    }
    return hr;
}

 

 Effect Parameters

사운드 이펙트의 인자를 설정하거나 얻기 위해서는, 먼저 그 이펙트를 포함하는 버퍼의 적절한 인터페이스를 획득해야만 한다. 다음의 인터페이스들은 모든 시스템 상에서 이용 가능한 표준 DMOs의 인자에 대한 접근을 부여한다.

  • IDirectSoundFXChorus8
  • IDirectSoundFXCompressor8
  • IDirectSoundFXDistortion8
  • IDirectSoundFXEcho8
  • IDirectSoundFXFlanger8
  • IDirectSoundFXGargle8
  • IDirectSoundFXI3DL2Reverb8
  • IDirectSoundFXParamEq8
  • IDirectSoundFXWavesReverb8

이러한 인터페이스를 획득하기 위해서는 관련 IID를 그 이펙트를 포함하고 있는 버퍼의 QueryInterface에 넘긴다. IID의 리스트를 보려면 DirectSound Interface GUIDs를 참조하라.

이펙트 인자들에서의 변경은 항상 즉시 이루어지지는 않는다. 효율성을 위해서 DirectSound는 재생 커서에서 시작해 버퍼가 재생되기 이전까지 버퍼의 0.01초의 사운드 데이터를 처리한다. 이 처리는 다음 호출들 이후에 발생한다. (원문 : For efficiency, DirectSound processes 100 milliseconds of sound data in a buffer, starting at the play cursor, before the buffer is played. This preprocessing happens after all of the following calls:)

  • IDirectSoundBuffer8::SetCurrentPosition
  • IDirectSoundBuffer8::SetFX
  • IDirectSoundBuffer8::Stop
  • IDirectSoundBuffer8::Unlock

 

 Standard Effects

 

이 주제는 DirectX에 의해 제공되는 사운드 이펙트에 대한 소개이다. 다음 이펙트들을 다루고 있다:

  • Chorus
  • Compression
  • Distortion
  • Echo
  • Environmental Reverberation
  • Flange
  • Gargle
  • Parametric Equalizer
  • Waves Reverberation

 

) Chorus

코러스는 원래의 사운드를 약간 지연시켜 메아리치게(echo) 하고 메아리의 지연을 약간 변조함으로써 생성되는 voice-doubling(역자주 : 두 개의 소리가 나는) 이펙트이다.(원문 : Chorus is a voice-doubling effect created by echoing the original sound with a slight delay and slightly modulating the delay of the echo.)

이 이펙트는 IDirectSoundFXChorus8 인터페이스에 의해서 표현된다. 그것의 인자들은 DSFXChorus 구조체에 포함되어 있다.

 

) Compression

Compression is a reduction(감소) in the fluctuation(파동) of a signal(신호) above a certain amplitude(진폭).

이 이펙트는 IDirectSoundFXCompressor8 인터페이스에 의해서 표현된다. 그것의 인자들은 DSFXCompressor 구조체에 포함되어 있다.

 

) Distortion

Distortion is achieved by adding harmonics(배음(倍音)) to the signal in such a way that, as the level increases, the top of the waveform becomes squared off or clipped.

이 이펙트는 IDirectSoundFXDistortion8 인터페이스에 의해서 표현된다. 그것의 인자들은 DSFXDistortion 구조체에 포함되어 있다.

 

) Echo

에코 이펙트는 고정된 지연시간 이후에 전체 사운드가 반복되도록 만든다.

이 이펙트는 IDirectSoundFXEcho8 인터페이스에 의해서 표현된다. 그것의 인자들은 DSFXEcho 구조체에 포함되어 있다.

 

) Environmental Reverberation

역자주 : 이 부분은 정말 해석이 개판이네요. 알아서 보세요.

DirectX는 Interactive Audio Special Interest Group에 의해 공표된 Interactive 3-D Audio Level 2(I3DL2) 규약에 부합하여, 환경 반사(environmental reverberation)를 일부 지원한다. DirectX 환경 반사 이펙트는 I3DL2 규약에 있는 청취자 속성의 구현이다. 소스 속성은 지원되지 않는다.

청취자에 도달하는 사운드는 세 가지의 임시 요소(temporal component)를 가진다:

  • direct path는 사운드 소스로부터 어떤 면에도 부딪히지 않고 청취자로 직접 가는 오디오 신호이다.
  • 초기의 반사(reflection) 는 벽이나, 문, 그리고 천장과 같은 면에 한 두 번 반사하고 나서 청취자에게 도달하는 오디오 신호이다. 만약 신호가 청취자에게 가는 길에서 단지 하나의 벽에만 부딪힌 사운드의 결과라면, 그것은 첫 번째 순서의 반사(first-order reflection)이라고 한다. 만약 그것이 청취자에게 도달하기 이전에 두 개의 벽에 부딪혔다면 두 번째 순서의 반사(second-order reflection)이라고 한다. 사람은 일반적으로 단지 첫 번째나 두 번째 순서의 개별적인 반사만을 인식할 수 있다.(원문 : Early reflections are the audio signals that reach the listener after one or two reflections off surfaces such as the walls, floor, and ceiling. If a signal is the result of the sound hitting only one wall on its way to the listener, it is called a first-order reflection. If it bounces off two walls before reaching the listener, it is called a second-order reflection. Humans can typically perceive individual reflections only of the first or second order.)
  • 후기 reverberation(여운, 반사), 혹은 간단히 reverb는 일반적으로 감소하는 강도의 에코들의 조밀한 연속인, 조합된 낮은 순서의 반사로 구성되어 있다.(원문 :  Late reverberation, or simply reverb, consists of the combined lower-order reflections, usually a dense succession of echoes of diminishing intensity.)

초기 반사와 후기 여운의 조합은 종종 room 이펙트라고 불린다.

Note   DirectSound 구현에서, 단지 room 이펙트로 보내진 신호만이 들린다. Direct path를 듣기 위해서는 사운드를 환경 reverb 이펙트를 가지지 않는 다른 버퍼에서 동시에 재생하라.

Reverberation 속성은 다음을 포함한다:

  • 초기 reflection 과 후기 reverberation의 감쇄
  • rolloff 요소 혹은 거리에 따라 반사된 신호가 감쇄되는 비율. direct path 에 대한  rolloff 요소는 DirectSound 청취자에 의해서 관리된다.
  • refelction 지연. 이것은 direct-path 신호의 도착과 첫 번째 초기 reflection 도착 사이의 간격이다.
  • reverb 지연. 이것은 첫 번째 초기 reflection과 후기 reverberation의 시작 사이의 간격이다.
  • Decay time(붕괴시간). 이것은 후기 reverbation의 시작과 그것의 강도가 60dB까지 내려가게 된 시간 사이의 간격이다.
  • Diffusion(확 산)은 후기 reverberation에서 초당 에코의 개수에 대한 비례항(proportional)이다. Implementation(역자주 : 특정 언어를 특정 기종의 컴퓨터에 맞추는 것)에 의존하여, 에코의 강도는 reverberation decays처럼 변경될 수 있다. DirectX에서 응용프로그램은 implementation에 의해 허용된 범위의 퍼센트를 설정함으로써 이 속성을 제어할 수 있다.
  • (원문 : Diffusion, which is proportional to the number of echos per second in the late reverberation. Depending on the implementation, the density of echos can change as the reverberation decays. In DirectX, the application can control this property by setting a percentage of the range allowed by the implementation.)
  • Density(밀 도)는 후기 reverberation에서 hertz 당 공명(resonance, 반향)의 개수에 대한 비례항(proportional)이다. 낮은 밀도는 작은 방에서 찾을 수 있는 것과 같은 속이 빈 사운드를 생성한다. DirectX에서 응용프로그램은 implementation에 의해 허용되는 범위의 퍼센트를 설정함으로써 이 속성을 제어할 수 있다.
  • (원문 : Density, which is is proportional to the number of resonances per hertz in the late reverberation. Lower densities produce hollower sounds like those found in small rooms. In DirectX, the application can control this property by setting a percentage of the range allowed by the implementation.)

reverb 속성은 IDirectSoundFXI3DL2Reverb8 인터페이스에 의해 표현되며, 그 환경의 인자들은 DSFXI3DL2Reverb 구조체에 포함되어 있다.

DirectX는 많은 집합의 기본 인자들이나, preset(역자주 : 미리 설정해 놓은 것)을 제공하는데, 그것들은 산에서부터 하수관까지의 범위에 이르는 오디오 환경의 reverb 속성을 기술한다. 대부분의 응용프로그램은 IDirectSoundFXI3DL2Reverb::SetPreset을 사용함으로써 이러한 환경 중의 하나를 간단히 선택할 수 있다.

사용자 정의 속성을 설정하고자 한다면, IDirectSoundFXI3DL2Reverb8::SetAllParameters를 사용하라. IDirectSoundFXI3DL2Reverb8::GetAllParameters를 사용하여 현재 속성을 얻을 수도 있다.

 

) Flange

Flange is an echo effect in which the delay between the original signal and its echo is very short and varies over time. The result is sometimes referred to as a sweeping sound. The term flange originated with the practice of grabbing the flanges of a tape reel to change the speed.

This effect is represented by the IDirectSoundFXFlanger8 interface. Its parameters are contained in the DSFXFlanger structure.

 

) Gargle

gargle 이펙트는 신호의 진폭(amplitude)를 변조한다.

이 이펙트는 IDirectSoundFXGargle8 인터페이스에 의해 표현된다. 그것의 인자는 DSFXGargle 구조체에 포함되어 있다.

 

) Parametric Equalizer

parametric equalizer 는 주어진 주파수의 신호를 확대하거나 축소한다.

다른 음정에 대한 parametric equalizer 이펙트는 같은 버퍼 상에 GUID_DSFX_STANDARD_PARAMEQ 이펙트의 다중 인스턴스를 설정함으로써 동시에 적용될 수 있다. 이러한 방식으로 응용프로그램은 하드웨어 equalize에 의해 제공되는 것과 유사한 톤(역자주 : 특정 주파수의 소리, 신호, tone) 제어를 가질 수 있다.

이 이펙트는 IDirectSoundFXParamEq8 인터페이스에 의해 표현된다. 그것의 인자는 DSFVParamEq 구조체에 포함되어 있다.

 

) Waves Reverberation

Wave reverberation 이펙트는 music과 함께 사용하기 위한 것이다. Waves reverberation DMO는 Waves MaxxVerb 기술에 기반해 있으며, 이는 Microsoft에 특허권이 있다.

이 이펙트는 IDirectSoundFXWavesReverb8 인터페이스에 의해 표현된다. 그것의 인자는 DSFXWavesReverb 구조체에 포함되어 있다.

 

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

역자주 : Capturing Waveforms는 제가 이용하는 범위를 넘어섰기 때문에 중간에 번역하다가 말았습니다.

 

 Capturing Waveforms

IdirectSoundCapture8 인터페이스에 의해 표현되는 DirectSound 캡춰 장치 개체는 사운드 캡춰 장치의 기능을 질의하고, 입력 소스로부터 오디오를 캡춰하기 위한 버퍼를 생성하기 위해서 사용된다. 데이터는 PCM이나 압축된 포맷으로 캡춰된다.

IdirectSoundCaptureBuffer8 인터페이스에 의해 표현되는 DirectSound 캡춰 버퍼 개체는 입력 장치로부터의 데이터를 받기 위해 사용되는 버퍼를 의미한다. 재생 버퍼와 마찬가지로 이 버퍼는 개념적으로 순환적이다: 입력이 버퍼의 끝에 도달하면, 그것은 자동적으로 시작점에서 다시 출발한다.

IdirectSoundCapture8 의 메서드는 버퍼의 속성들을 얻고, 오디오 캡춰를 시작하고 중지하고, 메모리의 일부를 잠글 수 있게 해준다. 그래서 Full-duplex implementation에서의 재생이나 파일로의 저장을 위한 데이터를 안전하게 받을 수 있다. 캡춰 이펙트를 지원하는 운영 체제 상에서, 이 인터페이스는 DMOs를 얻기 위한, 그리고 이펙트의 상태를 조회하기 위한 메서드도 제공하고 있다.

waveform 캡춰에 대한 더 많은 정보들은 다음 주제에서 찾을 수 있다:

  • Enumerating Capture Devices
  • Creating the Capture Device Object
  • Capture Device Capabilities
  • Creating a Capture Buffer
  • Capture Buffer Information
  • Capture Buffer Notification
  • Capture Buffer Effects
  • Using the Capture Buffer
  • Writing to a WAV File

 

) Enumerating Capture Devices

응용프로그램이 사용자가 선호하는 캡춰 장치를 통해서 간단히 사운드를 캡춰하고자 한다면, 이용가능한 장치를 열거할 필요가 없다. DirectSoundCaptureCreate8 이나 DirectSoundFullDuplexCreate8 함수를 호출함으로써 장치 개체를 생성할 때, 기본 장치를 지정할 수 있다. 더 많은 정보를 원한다면 Creating the Capture Device Object를 참조하라.

열거는 다음의 상황에서 필요하다:

  • 응용프로그램이 모든 드라이버 상에서 이용할 수는 없는 기능을 필요로 한다.
  • 응용프로그램이 두 개 이상의 장치를 요청한다.
  • 사용자가 장치를 선택할 수 있게 한다. 

열거는 세 가지 목적을 위해서 동작한다 :

  • 어떤 하드웨어가 이용가능한지를 기록한다.
  • 각 장치에 대한 GUID를 제공한다.
  • 마치 장치가 열거된 것처럼 임시 장치 개체를 생성해 장치의 기능을 검사할 수 있게 해 준다.

장치를 열거하기 위해서는, 시스템상의 각 장치를 위해 한 번 호출될 콜백 함수를 먼저 설정해야만 한다. 이 함수에 어떤 것이든 원하는 것을 수행할 수 있으며, 어떤 이름을 지정해도 상관없다. 그러나 DSEnumCallback 함수원형과 같은 형식으로 선언해야만 한다. 이 콜백 함수는 열거가 계속될 경우는 반드시 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환해야만 한다. 예를 들어 원하는 장치를  찾았을 때는 FALSE이다.

샘플 콜백 함수를 보기 위해서는 Enumerating Sound Devices를 참조하라.

열거는 DirectSoundCaptureEnumerate 함수를 다음과 같이 사용함으로써 in motion으로 설정된다:

DWORD pv;  // 32비트값. HRESULT hr = DirectSoundCaptureEnumerate(    (LPDSENUMCALLBACK)DSEnumProc, (VOID*)&pv);

두 번째 인자는 콜백 함수안에 대한 접근을 가지고자 하는 32비트 값일 수 있다.

Note   열거된 첫 번째 장치는 항상 Primary Sound Capture Driver라고 불리며, 콜백함수의 lpGUID 인자는 NULL이다. 이 장치는 Control Panel에서 사용자에 의해서 설정된 선호되는 캡춰 장치를 의미한다. 그것은 사용자에게 장치의 선택을 하게 할 때, 응용프로그램이 “Primary Sound Capture Driver”를 리스트에 추가하기 쉽게 하기 위해서 개별적으로 열거된다. 또한 주 캡춰 장치는 적절한 이름 및 GUID과 함께 열거된다.

 

) Creating the Capture Device Object

DirectSoundCaptureCreate8 이나 DirectSoundFullDuplexCreate8 함수 중 하나를 호출함으로써 캡춰 장치를 생성할 수 있다. 두 함수는 모두 IdirectSoundCapture8 인터페이스의 포인터를 받는다.

DirectSoundCaptureCreate 에 대한 LpcGUID 인자나 DirectSoundFullDuplexCreate8에 대한 pcGuidRenderDevice 인자는 열거에 의해 획득된 GUID 일 수도 있고, 다음에 미리 정의된 GUID 중 하나일 수도 있다:

GUID Description
DSDEVID_DefaultCapture 기본 시스템 캡춰 장치. 장치의 GUID 대신에 NULL 포인터를 넘김으로써 이 장치를 지정할 수도 있다.
DSDEVID_DefaultVoiceCapture 기본 음성(voice) 대화 캡춰 장치. 일반적으로 이것은 마이크를 가진 USB 헤드셋과 같은 보조 장치이다.

 

어떠한 장치도 제출되지 않으면, 이 호출은 실패한다.

CoCreateInstance 함수를 사용하여 개체를 생성할 수도 있다. 절차는 장치 개체의 그것과 유사하다; Creating the Device Object를 참조하라. 만약 CoCreateInstance를 사용한다면, 개체는 Control Panel에서 사용자에 의해 선택된 기본 캡춰 장치를 위해 생성된다.

만약 재생 장치와 캡춰 장치 개체의 공존(coexist)를 원한다면, 재생 장치 개체를 먼저 생성하고 초기화해야 한다. 아니면 DirectSoundFullDuplexCreate8을 사용해도 된다.

어떤 오디오 장치는 기본적으로 완전한 duplex 오디오를 위해 구성되지 않는다(원문 : Some audio devices aren't configured for full duplex audio by default.). 응용프로그램이 재생 장치와 캡춰 장치의 개체를 생성하고 초기화하는데 문제를 가지고 있다면, 사용자에게 오디오 장치 기능을 검사해 full duplex가 이용 가능하도록 설정할 것을 충고해야 한다.

 

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

 

5. Advanced Topics in DirectSound

이 섹션은 Microsoft® DirectSound® applications에 대해 필요하지는 않은 최적화와 진보된 기능에 대한 정보를 포함한다.

정보는 다음의 주제들로 제출되어 있다:

  • DirectSound Driver Models
  • Property Sets for DirectSound Buffers
  • Optimizing DirectSound Performance
  • Writing to the Primary Buffer

 

1) DirectSound Driver Models

VXD 드라이버 모델 하에서, 모든 DirectSound 믹싱(mixing)은 가상 장치 드라이버인 Dsound.vxd에서 수행된다. Dsound.vxd는 호스트 CPU로부터 데이터를 받기 위해 사운드 카드가 사용하는 실제 DMA 버퍼에 대한 근접한 접근을 제공하기도 한다. 이것은 DirectSound 주버퍼와 같다. DirectSound 응용프로그램은 샘플링율이나 비트 깊이 같은 주 버퍼의 지정된 속성을 설정할 수도 있으며, 따라서 하드웨어 자체의 속성을 변경하게 된다.(원문 : This is the same as the DirectSound primary buffer. A DirectSound application can set specific properties of the primary buffer, such as sampling rate and bit depth, thus changing the properties of the hardware itself.)

Windwos Driver Model 하에서, DirectSound는 하드웨어 가속 버퍼의 경우를 제외하고는 사운드 하드웨어에 대한 직접 접근을 하지 않는다. 대신에 DirectSound는 데이터를 커널 믹서로 보낸다. 커널 믹서의 작업은 다중 오디오 스트림을 일반적인 포맷으로 변환하고, 그것들을 혼합하고, 결과를 하드웨어에 보내는 것이다. 어떤 측면에서 Dsound.vxd가 하는 것과 같다. 주요한 차이는 Dsound.vxd는 단지 DirectSound 버퍼 데이터만을 혼합하지만, 커널 믹서는 Win32 waveOut 함수를 사용하는 응용프로그램으로부터의 데이터를 포함한 모든 Windows 오디오 데이터를 혼합한다. DirectSound 와 waveform-audio 출력 장치가 동시에 열릴 수 없다는 규칙은 WDM 드라이버를 가진 시스템에서는 맞지 않다.

특별히 가장 중요한 것은 커널 믹서의 오디오 하드웨어와의 관련성인데, 커널 믹서는 하드웨어의 DMA 버퍼 포맷을 지정할 수 있는 시스템상의 유일한 소프트웨어이다. 그것은 혼합되도록 요청된 기본적인 사운드를 기초로 하여 포맷을 결정한다. 그것은 출력 포맷을 혼합되도록 요구된 사운드의 최상위 품질의 포맷으로 설정하거나, 하드웨어가 제공하는 것과 가장 근접하는 포맷으로 설정한다.

이것은 매우 중요한 것을 내포하고 있다: DirectSound는 하드웨어의 DMA 버퍼의 포맷을 설정할 수 없다. 응용프로그램에 대해, 이것은 하드웨어 포맷이 실제로 재생하고자 하는 데이터에 기반한다는 것을 의미한다. 만약 44kHz 파일을 재생하면, Kmixer는 모든 데이터는 44kHz까지 혼합할 것이며, 하드웨어가 44kHz에서 동작하도록 만들 것이다.

응용프로그램 개발자로서는 사용될 드라이버 모델을 선택할 수 없다. 그것은 완전히 사운드 카드의 유형과 윈도우의 버전, 그리고 설치된 드라이버에 의해 결정된다. 이러한 이유로 응용프로그램을 검사할 때 모든 가능성들을 다루는 것이 매우 중요하다. DirectSounds는 Dsound.vxd를 사용하고 있거나, 커널 믹서를 사용하고 있을 것이고, 당신은 응용프로그램의 동작과 수행성이 둘 중에 어떤 것에 부합될 것인지를 결정해야만 한다.

 

2) System Property Sets

system-wide DirectSound 장치 속성에 대한 정보는 CLSID_DirectSoundPrivate(11AB3EC0-25EC-11d1-A4D8-00C04FC28ACA) 클래스의 개체로부터 얻을 수 있다. 이 클래스는 IKsPropertySet 인터페이스를 지원한다. 이 CLSID와 속성은 Dsconf.h에 정의되어 있다.

  1. 이 클래스의 개체를 생성하기 위해서는 LoadLibrary 함수를 호출해 Dsound.dll을 로드한다.
  2. GetProcAddress 함수를 호출해 DllGetClassObject 함수를 획득한다.
  3. DllGetClassObject를 호출해 CLSID_DirectSoundPrivate 클래스에 대한 클래스 팩토리의 IClassFactory 인터페이스를 획득한다.
  4. IClassFactory::CreateInstance를 호출해 CLSID_DirectSoundPrivate 개체를 생성하고, IksPropertySet 인터페이스(IID_IKsPropertySet)을 획득한다.

CLSID_DirectSoundPrivate 개체는 하나의 속성 집합인 DSPROPSETID_DirectSoundDevice(84624F82-25EC-11d1-A4D8-00C04FC28ACA)를 지원한다. 이 속성 집합은 다음의 세 가지 읽기 전용 속성을 공개한다.

  • DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING
  • DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION
  • DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE

DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING

이 속성은 Windows Multimedia 장치 이름을 지정하는 것과 관련된 DirectSound 장치 GUID를 획득한다.

속성 데이터는 DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_DATA 구조체에 포함되어 있으며, ANSI 와 Unicode 버전이 이용 가능하다. 이 구조체는 다음의 멤버들을 가지고 있다. (역자주 : 표 편집이 어려워 열거한다)

 DeviceName     

자료형 : String   

[in] 장치의 이름

 DataFlow

자료형 : DIRECTSOUNDDEVICE_DATAFLOW            

[in] 데이터 플로우(흐름, flow)의 방향. DIRECTSOUNDDEVICE_DATAFLOW_RENDER 이거나 DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE이다.

 DeviceID

자료형 : GUID

[out] DirectSound 장치 ID

DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION

이 속성은 GUID에 의해 지정된 DirectSound 장치의 전체 기술을 얻는다.

속성 데이터는 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA 구조체에 포함되어 있는데, ANSI와 Unicode 버전이 이용 가능하다. 이 구조체는 다음과 같은 멤버들을 가지고 있다.

 Type

자료형 : DIRECTSOUNDDEVICE_TYPE

[out]  장치 유형 : DIRECTSOUNDDEVICE_TYPE_EMULATED, DIRECTSOUNDDEVICE_TYPE_VXD, DIRECTSOUNDDEVICE_TYPE_WDM.

 

 DataFlow

자료형 : DIRECTSOUNDDEVICE_DATAFLOW

[in, out] 데이터 흐름의 방향 : DIRECTSOUNDDEVICE_DATAFLOW_RENDER, DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE.

 

 DeviceID

자료형 : GUID

[in] DirectSound 장치 GUID 이거나 DataFlow에 의해 지정된 유형의 기본 장치에 대해서는 NULL이다.

 Description

자료형 : String

[out] DirectSound 장치에 대한 기술

 

 Module

자료형 : String

[out] DirectSound드라이버의 모듈 이름

 

 

 Interface

자료형 : String

[out] PnP 장치 인터페이스 이름

 

 WaveDeviceID

자료형 : ULONG

[out] 관련된 Windows Multimedia 장치의 식별자

 

DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE

이 속성은 모든 DirectSound 렌더나 capture 장치를 열거한다.

속성 데이터는 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA 구조체에 포함되어 있으며, Ansi 와 Unicode 버전이 이용 가능하다. 이 구조체는 다음과 같은 멤버를 가지고 있다.

 Callback

자료형 : LPFNDIRECTSOUNDDEVICEENUMERATECALLBACK

[in] 응용프로그램 정의 콜백 함수. IKsPropertySet::Get이 호출될 때, 이 함수가 호출된다.

 

 Context

자료형 : LPVOID

[in] 사용자 정의 값인데 열거된 각 장치에 대해 콜백함수에 넘겨지게 된다.

 

3) Property Sets for DirectSound Buffers

사운드 카드 상에서 확장된 속성의 사용하기 위해서는, IKsPropertySet 인터페이스를 지원하는 드라이버가 어떤 것인지 먼저 결정하고, 만약 지원된다면 그 인터페이스의 포인터를 획득해야만 한다. 다음과 같이 DirectSound 3-D 버퍼 개체상에 현재 존재하고 있는 인터페이스의 QueryInterface 메서드를 호출함으로써 이것을 수행할 수 있다:

HRESULT hr = lpDirectSound3DBuffer - > QueryInterface(

IID_IKsPropertySet,

(void ** ) & lpKsPropertySet));

 

이 예제에서 lpDirectSound3Dbuffer는 버퍼의 인터페이스에 대한 포인터이며, lpKsPropertySet은 하나가 발경된다면 IKsPropertySet의 주소를 받는다. IID_IKsPropertySet은 Dsound.h에 정의된 GUID이다. 이 인터페이스는 버퍼가 하드웨어 가속되고 속성 집합을 지원하는 드라이버 하에서 작동할 경우만 이용 가능하다.

Note   DirectSound 에서의 이 인터페이스 선언은 Ksproxy.h 와 Strmif.h와는 다르다. 만약 프로젝트가 Ksproxy.h나 Strmif.h를 포함하고 있지만, DirectSound implementation을 사용하고자 한다면, Dsound.h를 먼저 삽입하라. 이렇게 하지 못하면 IKsPropertySet의 메서드가 호출될 때, 응용프로그램이 응답을 멈추게 만들 것이다.

IKsPropertySet::QuerySupport 메서드를 사용하여 개별 속성을 살펴 볼 수 있다. PropertySetId 인자의 값은 하드웨어 제작업체에 의해서 지정된 GUID이다.

존재하는 개별 속성에 대한 지원을 결정한 다음에는, IKsPropertySet::Set 메서드를 사용하여 속성의 상태를 변경시키고, IKsPropertySet::Get 메서드를 사용하여 현재 상태를 알아볼 수 있다. 속성의 상태는 pPropertyData 인자에서 설정되거나 반환된다.

또한 부가적인 속성 인자들은 IKsPropertySet::Set 메서드에 대한 인자인 pPropertyParams 안의 개체로 보내질 것이다. 이 인자가 사용되게 될 정확한 방법은 속성집합에 대한 하드웨어 제작업체의 명세에 정의되어 있지만, 일반적으로 그것은 속성 집합의 인스턴스를 정의하는데 사용된다. 사실 pPropertyParams 인자는 거의 사용되지 않는다.

 

 

 

4) Optimizing DirectSound Performance

이 섹션은 오디오 데이터를 직접 DirectSound 버퍼로 재생하는 응용프로그램의 수행성을 증가시키기 위한 잡다한 팁을 제공한다. 다음 주제들이 다뤄진다 :

  • Using Hardware Mixing
  • Dynamic Voice Management
  • Using Buffers Efficiently

 

 Using Hardware Mixing

현재의 사운드 카드들은 PCI(peripheral component interconnect) 로컬 버스에 연결하도록 설계되어 있다. 이 버스는 시스템 메모리에 대한 빠른 접근을 제공한다. 결과적으로 오디오 프로세서가 시스템 메모리에 있는 버퍼로부터 데이터를 직접 혼합하기에 실용적이다. 그리고 카드 자체가 메모리 버퍼를 가지고 있을 필요가 없다.

PCI 카드에서 정적 버퍼와 스트리밍 버퍼는 사실상 같다. 그리고 같은 버퍼는 DSCAPS에 정적 버퍼와 스트리밍 버퍼, 모두인 것으로 기록될 것이다. DSBUFFERDESC의 DSBCAPS_STATIC 플래그는 DirectSound 버퍼의 위치에 영향을 미치지 않는다.

다음 팁은 대부분의 하드웨어를 믹싱할 수 있도록 도와줄 것이다.(원문 : The ollowing tips will help you make the most of hardware mixing.)

  • 실행시간에 IDirectSound8::GetCaps 메서드를 사용해 어떤 포맷이 사운드 가속 하드웨어에 의해 지원되는지 확인하고, 가능한 한 그런 포맷만을 사용하라.
  • 가장 많이 사용하는 사운드에 대한 버퍼를 첫 번째로 생성한다. 하드웨어에 의해 혼합될 수 있는 버퍼의 개수는 제한되어 있다.
  • 버퍼가 하드웨어에서 생성되도록 하기 위해서는, DSBUFFERDESC 구조체의 dwFlags 멤버에 DSBCAPS_LOCHARDWARE 플래그를 지정한다. 만약 이렇게 했는데, 하드웨어 믹싱을 위한 자원이 이용 불가능하다면 IDirectSound8::CreateSoundBuffer 메서드는 실패할 것이다.
  • 음성(voice) 관리자를 사용해 DirectSound가 만약 하드웨어 자원이 이용 가능하다면 하드웨어 자원에 버퍼를 할당하게 하고, 하드웨어 자원을 늘리기 위해서 중요치 않은 버퍼를 강제로 종료시키게 한다. Dynamic Voice Management를 참조하라.

 

 Dynamic Voice Management

많은 사운드 카드들이 자신만의 보조버퍼를 유지하고, 3-D 이펙트를 조작하며, 그것들을 혼합한다. 이들 하드웨어 버퍼는 보통 카드 자체에 있기 보다는 시스템 메모리에 위치한다. 그런데 그것들은 장치에 의해 혼합되기 때문에, 소프트웨어 버퍼보다는 시스템 프로세서에 대해 작업을 요청할 때 더욱 요구가 작아진다(원문 : but because they are mixed by the device, they make far smaller demands on the system processor than do software buffers.). 결국 가장 효율적인 것은 가능한 한 많은 버퍼를 하드웨어에 할당하는 것이다. 이것은 3-D 버퍼일 경우 더욱 그렇다.

기본적으로 DirectSound는 가능하다면 버퍼를 하드웨어에 할당한다. 그러나 디바이스가 한 번에 연주할 수 있는 만큼의 하드웨어 버퍼만을 생성할 수 있다. 다시 말하면, 하드웨어 버퍼의 개수는 하드웨어 voice의 기능에 의해 제한된다는 것이다. DirectSound는 하드웨어 voice를 버퍼가 생성될 때 할당하며, 버퍼가 제거되었을 때만 해제한다. 응용프로그램이 많은 버퍼를 생성하게 되면, 그것들 중의 일부는 소프트웨어와 같이 될 것이며, 이는 사운드 카드보다는 CPU에 의해 관리되고 혼합될 것이라는 것을 의미한다.

Note   DirectSound 음성(voice) 관리자는 메모리가 아니라 하드웨어 믹싱 자원을 할당한다. PCI 카드에서 버퍼는 그것이 하드웨어 믹서에 할당되었는지 소프트웨어 믹서에 할당되었는지에 관계없이 그것이 할당되기 전후에 같은 메모리를 점유한다.

 

(원문 :  manager allocates hardware mixing resources, not memory. On a PCI card, the buffer occupies the same memory before and after it is allocated, regardless of whether it is allocated to the hardware mixer or the software mixer.)

 

Dynamic voice management는 버퍼가 재생될 때까지 음성 할당을 연기하고, DirectSound가 저순위(low-priority)의 사운드를 일찍 중지하고, 그들의 리소스를 해제함으로써 이러한 리소스들이 새로운 버퍼에 할당될 수 있게 함으로써 하드웨어 자원의 제한된 기능을 극복할 수 있게 해 준다.

하드웨어 믹싱과 3-D 이펙트에 대한 자원 할당을 버퍼가 재생되는 순간까지 연기하기 위해서는, IDirectSound8::CreateSoundBuffer에 넘겨지는 DSBUFFERDESC 구조체에 DSBCAPS_LOCDEFER 플래그를 지정한다. IdirectSoundBuffer8::Play 나 IdirectSoundBuffer8::AcquireResource를 그런 버퍼에 호출할 때, DirectSound는 그 버퍼를 가능한 한 하드웨어 위치시킬 것이며, 그렇지 않으면 소프트웨어에 위치시킬 것이다.

Play를 호출할 때, 다음 테이블에 있는 플래그 중 하나를 넘기거나, 세 번째와 처음 두 플래그를 조합한 것 중의 하나를 넘김으로써, 버퍼에 대한 하드웨어 voice를 해제하려고 시도할 수 있다(원문 : When calling Play, you can attempt to free a hardware voice for the buffer by passing one of the flags in the following table, or one of the first two flags in combination with the third.). 그리고 나서 DirectSound는 플래그에 의해 지정된 것처럼 종료되기에 적절한 재생중인 버퍼를 검색한다.

Flag Criterion
DSBPLAY_TERMINATEBY_TIME 다른 후보 버퍼들보터 더 오래 재생되고 있는 버퍼를 선택한다.
DSBPLAY_TERMINATEBY_DISTANCE 청취자로부터 가장 멀리 떨어진 3-D 후보 버퍼를 선택한다.
DSBPLAY_TERMINATEBY_PRIORITY Play 에 대한 호출에서 설정된 채로, 후보 버퍼들 중에서 가장 낮은 우선순위를 가진 버퍼를 선택한다(원문 : Select the buffer that has the lowest priority of candidate buffers, as set in the call to Play). 만약 이것이 다른 두 플래그 중 하나와 조합이 된다면, 다른 플래그는 단지 매듭을 풀기 위해서만 사용된다.(원문 :  If this is combined with one of the other two flags, the other flag is used only to resolve ties.)

 

적절한 버퍼를 찾았다면, DirectSound는 그것을 중지하고, 새롭게 재생되는 버퍼에 대해 사용되고 있었던 voice를 할당한다. 만약 어떤 버퍼도 종료하기에 적합하지 않다면, DSBPLAY_LOCHARDWARE 플래그가 지정되어 Play에 대한 호출이 실패하지 않는 이상, 새롭게 재생되는 버퍼는 소프트웨어에서 재생된다.

연기된 버퍼가 재생될 때 어떻게 다뤄지는지에 대한 정보를 원한다면, IdirectSoundBuffer8::Play를 참조하라.

Note   버퍼를 생성할 때 DSBCAPS_LOCDERFER 와 함께 DSBCAPS_STATIC 플래그를 조합하면 안 된다. DSBCAPS_STATIC 버퍼는 오래된 카드의 경우이기는 하지만 가능하다면 카드 기반 메모리에 위치한다. 만약 그러한 버퍼를 DSBCAPS_LOCDEFER 플래그와 함께 생성한다면, 버퍼 메모리는 버퍼가 첫 번째로 재생될 때까지 사운드 카드에 복사되지 않는다. 그리고 이는 심각한 지연(delay)을 유발할 수 있다.

 

 Using Buffers Efficiently

스트리밍 버퍼를 사용하고 있을 때, 통지의 주파수와 데이터 쓰기를 제한하라. 많은 통지 위치를 가진 버퍼나, 매우 짧은 간격의 통지를 가진 작은 버퍼를 생성하지 말라. 스트리밍 버퍼는 한 두 개의 데이터를 저장할 수 있으며, 단지 두 개의 통지 위치를 가질 수 있다.

수행성은 보조버퍼의 팬, 볼륨, 주파수 등을 변경할 때 영향을 받는다. 그것은 DirectSound가 버퍼를 재생하기 이전에 짧은 시간동안 사운드를 혼합하고, 어떤 변화는 미리 혼합한 버퍼를 비우고 다시 혼합하게 만들기 때문이다.

제어 변경의 개수를 최소화하기 위해서는 IdirectSoundBuffer8::SetVolume, IdirectSoundBuffer8::SetPan, IdirectSoundBuffer8::SetFrequency의 호출 빈도를 줄여야 한다. 예를 들어 만약 사운드를 왼쪽 스피커에서 오른쪽 스피커로 애니메이션 프레임과 동기화하여 이동하는 루틴을 가지고 있다고 하면, 두 세 프레임마다 SetPan 메서드 호출을 시도해야 한다. 3-D 버퍼에서는 연기된 설정을 만들어 사용하라.(원문 : On 3-D buffers, use deferred settings to make)

소프트웨어에서 3-D 버퍼는 중앙 처리 장치에 대해 많은 요구를 만들어 낸다는 것을 명심하라. 이러한 요구를 줄이기 위해서는 다음과 같이 할 수 있다 :

  • 자주 사용되는 사운드는 가능한 한 하드웨어 버퍼에 둔다.
  • 이펙트를 사용하는 효과가 필요하지 않은 사운드에 대해 3-D 버퍼를 사용하지 말라.
  • IDirectSound3Dbuffer8::SetMode를 DS3DMODE_DISABLE 플래그와 함께 사용해 청취자에게서 더 이상 상대적으로 움직일 필요가 없는 3-D 사운드 버퍼에 대한 3-D 처리를 불가능하게 한다.
  • 인자 변경은 한 묶음(batch)으로 하거나, 연기된 설정을 사용해 모든 버퍼와 청취자에 대한 변경을 한꺼번에 처리한다.

See Also

  • Batch Parameters for 3-D Buffers
  • Batch Parameters for 3-D Listeners
  • Deferred Settings
  • Minimum and Maximum Distances

 

5) Writing to the Primary Buffer

특별한 혼합이나 보조버퍼에 의해 지원되지 않는 다른 이펙트를 요구하는 응용프로그램에 대해, DirectSound는 주 버퍼에 대한 직접 접근을 허용한다.

주 버퍼에 대한 쓰기 접근을 획득할 때, 다른 DirectSound 기능은 이용 불가능해 진다. 보조 버퍼들은 혼합되지 않으며, 하드웨어 가속 믹싱도 불가능하다.

대부분의 응용프로그램들은 주 버퍼에 대한 직접 접근 대신에 보조버퍼를 사용한다. 응용프로그램은 보조 버퍼를 쉽게 쓸 수 있다. 왜냐하면 더 큰 크기의 버퍼는 데이터의 다음 블록을 쓰는데 더 많은 시간이 들기 때문이며, 그것에 의해서 오디오에서의 간격의 위험(risk of gaps)을 최소화한다(원문 :  Applications can write to a secondary buffer easily because the larger buffer size provides more time to write the next block of data, thereby minimizing the risk of gaps in the audio.). 비록 응용프로그램이 혼합을 요청하지 않는 오디오 데이터의 한 스트림을 사용하는 것과 같은 간단한 오디오 요청을 가지고 있다고 할지라도, 그것의 오디오 데이터를 재생하기 위해서 보조 버퍼를 사용함으로써 더 좋은 수행성을 성취할 수 있다.

Note   주 버퍼에 직접 쓰는 것은 Windows driver model(WDM) 환경에서는 아무런 이익도 없다. WDM 환경에서는, 주 버퍼는 사실상 커널 믹서에 의해 혼합된 보조 버퍼이다. WDM에 대한 더 많은 정보를 원한다면 DirectSound Driver Models를 참조하라.

주 버퍼의 크기를 지정할 수는 없다. 그리고 버퍼가 생성된 이후에 반환되는 크기를 받아들여야만 한다. 주 버퍼는 일반적으로 매우 작다. 그래서 만약 응용프로그램이 이러한 종류의 버퍼에 직접 쓰려고 한다면, 이전에 작성된 데이터를 다시 재생하는 것을 방지하기 위해서 짧은 간격으로 데이터 블록을 작성해야만 한다.

주 버퍼에 대한 쓰기 접근은 그것이 하드웨어에 존재하지 않는 이상 획득할 수 없다. 이러한 경우가 어떤 경우인지 알고 싶다면, IdirectSoundBuffer8::GetCaps 메서드를 호출하고, 반환된 DSBCAPS 구조체의 dwFlags에 DSBCAPS_LOCHARDWARE 플래그가 설정되어 있는지 검사한다. 만약 소프트웨어라고 열거된 주 버퍼를 잠그려고 시도한다면, 그 호출은 실패할 것이다.

IdiretSound8::CreateSoundBuffer 메서드에 넘겨지는 DSBUFFERDESC 구조체에 DSBCAPS_PRIMARYBUFFER 플래그를 지정함으로써 접근 가능한 주 버퍼를 새성한다. 만약 버퍼를 쓰고자 한다면, 협력레벨은 DSSCL_WRITEPRIMARY여야 한다.

주 사운드 버퍼는 반드시 반복 재생되어야만 한다. DSBPLAY_LOOPING 플래그를 설정하라.

다음 예제는 주 버퍼에 대한 쓰기 접근을 획득하는 방법을 보여준다. 주 버퍼는 IDirectSoundBuffer8이 아니라 IDirectSoundBuffer인터페이스만을 지원한다는 것에 주의하라.

 

BOOL AppCreateWritePrimaryBuffer(
    LPDIRECTSOUND8 lpDirectSound,
    LPDIRECTSOUNDBUFFER * lplpDsb,
    LPDWORD lpdwBufferSize,
    HWND hwnd) {
    DSBUFFERDESC dsbdesc;
    DSBCAPS dsbcaps;
    HRESULT hr;
    WAVEFORMATEX wf;

    // Set up wave format structure. 
    memset( & wf, 0, sizeof(WAVEFORMATEX));
    wf.wFormatTag = WAVE_FORMAT_PCM;
    wf.nChannels = 2;
    wf.nSamplesPerSec = 22050;
    wf.nBlockAlign = 4;
    wf.nAvgBytesPerSec =
        wf.nSamplesPerSec * wf.nBlockAlign;
    wf.wBitsPerSample = 16;

    // Set up DSBUFFERDESC structure. 
    memset( & dsbdesc, 0, sizeof(DSBUFFERDESC));
    dsbdesc.dwSize = sizeof(DSBUFFERDESC);
    dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
    // Buffer size is determined by sound hardware. 
    dsbdesc.dwBufferBytes = 0;
    dsbdesc.lpwfxFormat = NULL; // Must be NULL for primary buffers. 

    // Obtain write-primary cooperative level. 
    hr = lpDirectSound - > SetCooperativeLevel(hwnd, DSSCL_WRITEPRIMARY);
    if SUCCEEDED(hr) {
        // Try to create buffer. 
        hr = lpDirectSound - > CreateSoundBuffer( & dsbdesc,
            lplpDsb, NULL);
        if SUCCEEDED(hr) {
            // Set primary buffer to desired format. 
            hr = ( * lplpDsb) - > SetFormat( & wf);
            if SUCCEEDED(hr) {
                // If you want to know the buffer size, call GetCaps. 
                dsbcaps.dwSize = sizeof(DSBCAPS);
                ( * lplpDsb) - > GetCaps( & dsbcaps);
                * lpdwBufferSize = dsbcaps.dwBufferBytes;
                return TRUE;
            }
        }
    }
    // Failure. 
    * lplpDsb = NULL;
    * lpdwBufferSize = 0;
    return FALSE;
}

 

다음 예제는 응용프로그램이 사용자 정의 믹서를 구현하는 방법을 설명한다. AppMixIntoPrimaryBuffer 샘플 함수는 보통의 간격(regular intervals)으로 호출되어야만 할 것이며, 사운드 디바이스가 데이터 블록을 반복하는 것으로부터 막기 위해 충분히 빈번하게 호출되어야 한다. (원문 : The following example illustrates how an application might implement a custom mixer. The AppMixIntoPrimaryBuffer sample function would have to be called at regular intervals, frequently enough to prevent the sound device from repeating blocks of data.) CustomMixer 함수는 응용프로그램에 정의된 함수인데, 몇 개의 스트림을 응용프로그램에 정의된 APPSTREAMINFO 구조체에 지정된 것처럼 혼합하고, 그 결과를 지정된 포인터에 쓴다.

 

BOOL AppMixIntoPrimaryBuffer(
    APPSTREAMINFO * lpAppStreamInfo,
    LPDIRECTSOUNDBUFFER lpDsbPrimary,
    DWORD dwDataBytes,
    DWORD dwOldPos,
    LPDWORD lpdwNewPos) {
    LPVOID lpvPtr1;
    DWORD dwBytes1;
    LPVOID lpvPtr2;
    DWORD dwBytes2;
    HRESULT hr;
    // Obtain write pointer. 
    hr = lpDsbPrimary - > Lock(dwOldPos, dwDataBytes, &
        lpvPtr1, & dwBytes1, &
        lpvPtr2, & dwBytes2, 0);

    // If DSERR_BUFFERLOST is returned, restore and retry lock. 

    if (DSERR_BUFFERLOST == hr) {
        lpDsbPrimary - > Restore();
        hr = lpDsbPrimary - > Lock(dwOldPos, dwDataBytes, &
            lpvPtr1, & dwBytes1, &
            lpvPtr2, & dwBytes2, 0);
    }
    if SUCCEEDED(hr) {
        // Mix data into the returned pointers. 
        CustomMixer(lpAppStreamInfo, lpvPtr1, dwBytes1);
        * lpdwNewPos = dwOldPos + dwBytes1;
        if (NULL != lpvPtr2) {
            CustomMixer(lpAppStreamInfo, lpvPtr2, dwBytes2);
            * lpdwNewPos = dwBytes2; // Because it wrapped around. 
        }
        // Release the data back to DirectSound. 
        hr = lpDsbPrimary - > Unlock(lpvPtr1, dwBytes1,
            lpvPtr2, dwBytes2);
        if SUCCEEDED(hr) {
            return TRUE;
        }
    }
    // Lock or Unlock failed. 
    return FALSE;
}

 

 

[출처] [펌] DirectSound C++ Document (번역:최도경)|작성자 소환마검

 

 

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

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

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

 

 

반응형


관련글 더보기

댓글 영역