270 likes | 507 Views
Chapter 13 DirectSound 로 잡음 만들기. History of Sound Programming. Sound programming always gets put off until the end DOS Third party sound libraries: Miles Sound System, Diamondware Sound Toolkit… high price Windows Sound and multimedia support: not for real-time video game
E N D
History of Sound Programming • Sound programming always gets put off until the end • DOS • Third party sound libraries: Miles Sound System, Diamondware Sound Toolkit… high price • Windows • Sound and multimedia support: not for real-time video game • DirectSound and DirectMusic • free • high performance • Support for million different sound card
Extension of DirectSound and Music • DirectSound3D • 3D sound support • DirectMusic • Playing MIDI files • DLS (Downloadable Sounds) data • Sound can be selected by game users on-the-fly.
DirectSound • Related components • DirectSound3D • DirectSoundCapture
DirectSound Components • Run-time .DLL • Compile-time library and header (DSOUND.LIB and DSOUND.H)
DirectSound Interfaces - 2 • IUnknown • IDirectSound • main COM object, one per a sound card • IDirectSoundBuffer • primary buffer : currently playing sound • secondary buffer : stored sound, system memory or SRAM (sound RAM) • IDirectSoundCapture • capture (record), ex) record player’s name!, voice recognition • IDirectSoundNotify • Send message back to DirectSound
Starting Up DirectSound LPDIRECTSOUND lpds; DirectSoundCreate(NULL, &lpds, NULL); // lpGuid, lpDS, … // lpGuid = NULL : default sound card
Understanding Cooperation Level • Normal Cooperation • Play sound for the game application + other applications • Default primary buffer of 22KHz, stereo, 8-bit 가 제공됨 • Priority Cooperation • First access to all the h/w • Only necessary for changing the data format of the primary buffer: ex) 16-bit sample .. • Exclusive Cooperation • Same as Priority, your application will be audible only when it’s in the foreground. • Write-Primary Cooperation • Total control for the primary buffer.
Setting the Cooperation Level if (FAILED(lpds->SetCooperativeLevel(main_window_handle, DSSCL_NORMAL))) { … }
Primary Sound Buffer • Mixing h/w (or s/w) on the sound card • Processes all the time • You don’t need to manually control the primary buffer • DirectSound create one primary buffer for you (when we use DSSCL_NORMAL). • 22 KHZ stereo in 8-bit (default)
Secondary Buffers • Can be any size • SRAM or System memory? • Sounds on SRAM: low-cost for processing • Two Kinds of Secondary Buffers • Static • Streaming
Creating Secondary Sound Buffers // After filling the sound buffer description structure here. …. CreateSoundBuffer(LPDSBUFFERDESC lpdsbd, LPDIRECTSOUNDBUFFER lpdsbuffer, NULL);
Sound Buffer Description typedef struct { DWORD dwSize; DWORD dwFlags; DWORD dwBufferBytes; // buffer size in bytes DWORD dwReserved; // unused LPWAVEFORMATEX lpwfxFormat; // the wave format } DSBUFFERDESC; • Usual Flag Combination • DSBCAPS_CTRLDEFAULT : default control (volume, pan, frequency) • DSBCAPS_STATIC : static (not streaming) • DSBCAPS_LOCSOFTARE : system memory
WAVEFORMAT structure typedef structure { WORD wFormatTag; // always WAVE_FORMAT_PCM WORD nChannels; // 1 for mono, 2 for stereo DWORD nSamplesPerSec; // Samples per second 11025 or 22050 … DWORD nAvgBytesPerSec; // average data rate (SamplePerSec * nBlockAlign) WORD nBlockAlign; // nchannels * bytespersample WORD wBitsPerSample; // Bits per sample WORD cbSize; // advanced, 0 } WAVEFORMATEX;
Sound Buffer Creation Example - 1 ex) 11 KHz, mono, 8-bit with enough storage for 2 secs LPDIRECTSOUNDBUFFER lpdsbuffer; DSBUFFERDESC dsbd; // description WAVEFORMATEX pcmwf; // format description // WAVEFORMAT Creation memset(&pcmwf, 0, sizeof(WAVEFORMATEX)); pcmwf.wFormatTag = WAVE_FORMAT_PCM; // always pcmwf.nChannels = 1; // Mono pcmwf.nSamplesPerSec = 11025; // 11 kHz sampling pcmwf.nBlockAlign = 1; // 1 channel * 1 bytes / sample pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign; pcmwf.wBitsPerSample = 8; // 8bits / sample pcmwf.cbSize = 0; // always 0
Sound Buffer Creation Example - 2 // Create DSBUFFERDESC memset(dsbd, 0, sizeof(DSBUFFERDESC)); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_STATIC | DSBCAPS_LOCSOFTARE; dsbd.dwBufferBytes = 22050; // for 2 seconds with 11 kHz dsbd.lpwfxFormat = &pcmwf; // Create the buffer if (FAILED(lpds->CreateSoundBuffer(&dsbd, &lpdsbuffer, NULL))) { /* error */ }
Writing Data to Secondary Buffers • Lock the buffer • Fill the buffer • Unlock the buffer UCHAR *audio_ptr_1, *audio_ptr_2; int audio_length_1, audio_length_2; if (FAILED(lpdsbuffer->Lock(0, 1000, (void **)audio_ptr_1, &audio_length_1, (void **)audio_ptr_2, &audio_length_2, DSBLOCK_ENTIREBUFFER))) {…} …. if (FAILED(lpdsbuffer->Unlock(audio_ptr_1, audio_length_1, audio_ptr_2, audio_length_2))) { … }
Rendering Sounds • Playing HRESULT Play( DWORD dwReserved1, DWORD dwReserved2, // both 0 DWORD dwFlags); // control flags to play // Example lpdsbuffer->Play(0, 0, DSBPLAY_LOOPING); // or flag=0 (no looping) • Stopping lpdsbuffer->Stop( )
Controlling Sound - 1 • Controlling the Volume lpdsbuffer->SetVolume(LONG lVolume) lVolume = 0 : max sound (0 dB) lVolume = -10000 : no sound (-100 dB) • Volume control macro (0 ~ 100) #define DSVOLUME_TO_DB(volume) ((DWORD)(-30*(100-volume))) lpdsbuffer->SetVolume(DSVOLUME_TO_DB(50)); // 50% volume // -30 * (100 – 50) = -1500 (50%) // -30 * (100 – 100) = 0 (maximum) // -30 * (100 – 0) = -30 * 100 = -3000 (minimum)
Controlling Sounds - 4 • Frequency • lpdsbuffer->SetFrequency(22050) : 만약 원래가 11025 Hz 라면 속도가 2배로 된다. • Panning • lpdsbuffer->SetPan(0) : center • lpdsbuffer->SetPan(-10000) : right channel = -100dB • lpdsbuffer->SetPan(10000) : left channel = -100dB • lpdsbuffer->SetPan(-500) : right channel = -5 dB (more sound to left channel)
Getting Information - 1 • Determining the Capability of the H/W • GetCaps(LPDSCAPS lpDSCaps); • DSCAPS structure typedef { DWORD dwSize; … DWORD dwMaxSecondarySampleRate; … } DSCAPS;
Getting Information - 2 • Determining the Info of Buffer GetCaps(LPDSBCAPS lpDSBCaps); typdef struct { … DWORD dwBufferBytes; DWORD UnlockTransferRate; // Sample rate DWORD dwPlayCpuOverhead; // % of processor to mix this sound … } DSBCAPS;
Getting Information - 3 • Determining the Status of Sound Play • lpdsbuffer->GetStatus(&status); • Status • DSBSTATUS_BUFFERLOST : something wrong! • DSBSTATUS_LOOPING : looped mode • DSBSTATUS_PLAYING : sound is now playing • Other Information • Retrieve volume, pan, frequency setting etc.. • See DirectSound documents