Search Tips Advanced Search |
| Delphi Graphics and Game Programming Exposed with DirectX 7.0 by John Ayres Wordware Publishing, Inc. ISBN: 1556226373 Pub Date: 12/01/99
Search this book:
Previous | Table of Contents | Next
Setting the Format of the Primary Buffer As noted above, the primary buffer has a default format of 22,050 Hz, 2 channels, 8 bits per sample. Regardless of the format of any secondary sound buffers, DirectSound converts them on the fly into the format of the primary buffer. This is completely transparent to the developer, and in general, most applications can take advantage of this automatic conversion and never be concerned with the format of any audio data. However, it does take some processing time to do this conversion, and in a high-performance game where no processing time should be wasted, this may be unacceptable. Alternatively, the developer may desire better sound quality than that offered by the default format. Fortunately, DirectSound provides a method by which the format of the primary buffer can be changed as desired by the developer.
| Note: DirectSound is optimized for 16-bits-per-sample sounds. Therefore, changing the primary sound buffer format for 16-bit sounds can further reduce playback latency and reduce the load on the CPU when processing sound data.
In order to change the format of the primary buffer, a TDSBufferDesc structure (containing buffer description information) must be initialized. This data structure is described later in this chapter, but the dwFlags member must be set to DSBCAPS_ PRIMARYBUFFER, the dwBufferBytes member must be set to 0, and the lpwfxFormat member must be set to nil. Then, the CreateSoundBuffer method of the IDirectSound object is called, passing this data structure as a parameter, to retrieve a pointer to the primary sound buffer object (the CreateSoundBuffer function is discussed in more detail later). Once a pointer to the primary sound buffer object is retrieved, a TWaveFormatEx structure is initialized to the appropriate settings for the desired primary buffer format. Finally, the SetFormat method of the primary sound is called, passing it the initialized TWaveFormatEx structure. The SetFormat method of IDirectSoundBuffer is defined as:
    function SetFormat(

    const lpcfxFormat: TWaveFormatEx        // a TWaveFormatEx structure

    ): HResult;                             // returns a DirectX error code
At this point, the pointer to the primary sound buffer object can be released, as the new format settings are persistent until the format of the primary sound buffer is again modified.
| Note: The cooperative level of the DirectSound object must be set to a minimum of DSSCL_PRIORITY before the format of the primary sound buffer can be changed.
In the following example, the sample sound is known to have a format of 44,100 Hz, 2 channels, 16 bits per sample. The format of the primary sound buffer is changed to that of the sample sound to facilitate the most optimum audio playback environment. Several functions not yet discussed are used in the example, but will be explained later in the chapter. Listing 9-4: Setting the format of the primary sound buffer
    var

      DXSound: IDirectSound;

      Sound: IDirectSoundBuffer;

    procedure TForm1.FormCreate(Sender: TObject);

    var

      BufDesc: TDSBufferDesc;

      Format: TWaveFormatEx;

      PrimeBuf: IDirectSoundBuffer;

    begin

      {create the DirectSound object}

      DirectSoundCreate(nil, DXSound, nil);

      {set its cooperative level high enough to allow the application to

       change the format of the primary buffer}

      DXSound.SetCooperativeLevel(Handle, DSSCL_PRIORITY);

      {initialize the buffer description structure to indicate we wish to

       retrieve the primary buffer}

      FillChar(BufDesc, SizeOf(TDSBufferDesc), 0);

      BufDesc.dwSize        := SizeOf(TDSBufferDesc);

      BufDesc.dwFlags       := DSBCAPS_PRIMARYBUFFER;

      BufDesc.dwBufferBytes := 0;

      BufDesc.lpwfxFormat   := nil;

      {retrieve the primary buffer}

      DXSound.CreateSoundBuffer(BufDesc, PrimeBuf, nil);

      {initialize the wave format structure to the desired primary buffer

       format settings. this will be the same format used by the example

       sound, which should have lower playback latency since it no longer

       needs to be converted}

      FillChar(Format, SizeOf(TWaveFormatEx), 0);

      Format.wFormatTag      := WAVE_FORMAT_PCM;

      Format.nChannels       := 2;

      Format.nSamplesPerSec  := 44100;

      Format.wBitsPerSample  := 16;

      Format.nBlockAlign     := (Format.nChannels*Format.wBitsPerSample) div 8;

      Format.nAvgBytesPerSec := Format.nSamplesPerSec*Format.nBlockAlign;

      {set the format of the primary buffer}

      PrimeBuf.SetFormat(Format);

      {release the primary buffer (it retains the settings just defined)}

      PrimeBuf := nil;

      {load in the example sound}

      Sound := DSLoadSound(DXSound, ExtractFilePath(ParamStr(0))+‘Sample.wav’,

                           FALSE);

    end;

    procedure TForm1.Button1Click(Sender: TObject);

    begin

      {play the example sound (the primary buffer is now in the same format

       as this sound buffer)}

      Sound.SetCurrentPosition(0);

      Sound.Play(0, 0, 0);

    end;
Creating Buffers Now that DirectSound has been properly instantiated, the application has checked that the sound card provides the desired capabilities, and the format of the primary sound buffer has been changed to match that of the sounds to be played, it is time to start loading and playing sounds. As with initialization, there are several steps the developer must follow in order to properly create a secondary sound buffer and load it with sound data. Unlike initialization, however, none of these steps are optional, and some are repeated regularly when creating a streaming buffer. In order to load and play a WAV file, the application must perform the following: • Describe the format of the WAV file to be played • Describe various secondary sound buffer attributes, such as the size of the buffer and any buffer capabilities • Create the sound buffer (an IDirectSoundBuffer object) using the above information • Copy the sound data from the WAV file into the buffer • Play the sound buffer • Repeat the last two steps for streaming buffers By far, the most complex step in initializing a secondary sound buffer is copying the data from a WAV file into the sound buffer itself. Unfortunately, DirectSound does not come with any built-in methods for retrieving audio data from a file or a resource. However, the DirectX SDK comes with several units that contain functions for performing this necessary step, specifically the Wave.C and DSUtil.C units. These units have been converted to Pascal, and live in the form of the DSUtil.pas, DSWaveFiles.pas, and DSWaveResources.pas units. The DSUtil unit contains a function (DSLoadSound, used in the previous example) that will load a sound from a WAV file or a resource, passing back an instantiated IDirectSoundBuffer interface (static sounds only). The DSUtil unit uses functions located in the DSWaveFiles and DSWaveResources units to provide this functionality, and the examples that follow will discuss how to use these functions to initialize sound buffers with sound data.
Previous | Table of Contents | Next

Products | Contact Us | About Us | Privacy | Ad Info | Home Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.