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
Finally, the Play method is called to actually begin audio playback. The Play method is defined as:
    function Play(

    dwReserved1,                      // reserved

    dwReserved2,                      // reserved

    dwFlags: DWORD                    // play control flags

    ): HResult;                       // returns a DirectX error code
The first two parameters are unused and should be set to zero. The third parameter can be set to zero to simply play the sound once, or it can be set to DSBPLAY_LOOPING to continuously play the sound. The Stop method can be called to discontinue any sound playback from the buffer (the Stop method has no parameters).
| Note: Like DirectDraw surfaces, the memory allocated to secondary sound buffers can be lost when another application takes over the sound hardware. In this case, any calls to the Lock or Play methods will return DSERR_BUFFERLOST. The Restore method can be called to reallocate the buffer memory. However, the contents of this memory will be invalid, and the audio data must be recopied into the sound buffer.
The following example demonstrates how to create a static sound buffer, load it with audio data from an external WAV file, and play it. Listing 9-5: Creating and playing static wave files
    var

      DXSound: IDirectSound;

      Sounds: array[0..5] of IDirectSoundBuffer;  // holds all of our sound objects

    const

      {the names of the WAV files to be used}

      FileNames: array[0..5] of string = (‘bigz05.wav’, ‘bigzap.wav’, ‘bloop.wav’,

                                          ‘boingg.wav’, ‘bwik.wav’, ‘elslide.wav’);

    procedure TForm1.FormCreate(Sender: TObject);

    var

      iCount: Integer;

    begin

      {create the DirectSound object}

      DirectSoundCreate(nil, DXSound, nil);

      {set its cooperative level (we won’t change the primary buffer format, so

       a cooperative level of Normal is all that is needed)}

      DXSound.SetCooperativeLevel(Handle, DSSCL_NORMAL);

      {load in the six example sounds}

      for iCount := 0 to 5 do

        LoadSound(FileNames[iCount], Sounds[iCount]);

    end;

      .

      .

      .

    {this function is used to load a WAV file and initialize an

     IDirectSoundBuffer object with the audio data}

    procedure TForm1.LoadSound(FileName: string; var Buffer: IDirectSoundBuffer);

    var

      Audio: PByte;

      Junk: Pointer;

      NumBytesLocked: DWORD;

      JunkBytes: DWORD;

      WaveFormat: PWaveFormatEx;

      mmioHndle: HMMIO;

      ChunkInfo,

      ChunkInfoParent: TMMCKInfo;

      BufDesc: TDSBufferDesc;

    begin

      {open the specified WAV file and read its format information}

      WaveOpenFile(PChar(ExtractFilePath(ParamStr(0))+FileName), mmioHndle,

                   WaveFormat, @ChunkInfoParent);

      {advance the file pointer to the beginning of audio data, and retrieve the

       size of the buffer required to hold all of the audio data}

      WaveStartDataRead(mmioHndle, @ChunkInfo, @ChunkInfoParent);

      {initialize a buffer description record, including the size of the audio

       data and its format retrieved from the previous two function calls}

      FillMemory(@BufDesc, SizeOf(TDSBufferDesc), 0);

      BufDesc.dwSize := SizeOf(TDSBufferDesc);

      BufDesc.dwFlags := DSBCAPS_STATIC; // could also use DSBCAPS_LOCHARDWARE to

                                         // force the buffer into hardware memory

      BufDesc.dwBufferBytes := ChunkInfo.cksize;

      BufDesc.lpwfxFormat := WaveFormat;

      {create the sound buffer object}

      DXSound.CreateSoundBuffer(BufDesc, Buffer, nil);

      {lock the entire buffer}

      Buffer.Lock(0, 0, Pointer(Audio), NumBytesLocked, Junk, JunkBytes,

                  DSBLOCK_ENTIREBUFFER);

      {copy the audio data into the sound buffer object}

      WaveReadFile(mmioHndle, NumBytesLocked, Audio, @ChunkInfo, JunkBytes);

      {unlock the buffer}

      Buffer.Unlock(Audio, NumBytesLocked, nil, 0);

      {close the WAV file.  at this point, the IDirectSound buffer has been

       initialized and is ready to be played}

      WaveCloseReadFile(mmioHndle, WaveFormat);

    end;

    procedure TForm1.Button1Click(Sender: TObject);

    begin

      {the Tag property of each button is set to the appropriate index into

       the array of IDirectSoundBuffer objects. when a button is pressed, reset

       the current position of the appropriate buffer, and start playing it}

      Sounds[TButton(Sender).Tag].SetCurrentPosition(0);

      Sounds[TButton(Sender).Tag].Play(0, 0, 0);

    end;
The DSWaveResources.pas unit contains functions similar to those found in the DSWaveFiles.pas unit for loading WAV file information from resources. Internally, dramatically different API functions are called, mainly those used for manipulating resources on a binary level as opposed to multimedia file input/output functions. Specifically, the DSGetWaveResource function is called to initialize both the TDSBufferDesc and the TWaveFormatEx structures. The CreateSoundBuffer method is then called as usual, and the DSFillSoundBuffer function is called to actually copy the audio data into the buffer. The following example demonstrates how to use these functions to create and play static sound buffers from audio data in a resource. This example also demonstrates how to check for a lost sound buffer and restore its contents. Listing 9-6: Creating and playing static wave files from resource information
    var

      DXSound: IDirectSound;

      Sounds: array[0..5] of IDirectSoundBuffer;  // holds all of our sound objects

    const

      {the resource names of the waves to be used}

      ResNames: array[0..5] of PChar = (‘bigz05’, ‘bigzap’, ‘bloop’,

                                        ‘boingg’, ‘bwik’, ‘elslide’);

     {this function is used to load a wave resource and initialize an

     IDirectSoundBuffer object with the audio data}

    procedure LoadSound(ResName: PChar; var Buffer: IDirectSoundBuffer);

    var

      BufDesc: TDSBufferDesc;

      pbWaveData: PByte;

    begin

      {empty the buffer description record}

      FillMemory(@BufDesc, SizeOf(TDSBufferDesc), 0);

      {load the wave resource, initializing the format and required buffer size}

      if DSGetWaveResource(0, ResName, BufDesc.lpwfxFormat, pbWaveData,

                           BufDesc.dwBufferBytes) then

      begin

        {initialize the remaining buffer description members}

        BufDesc.dwSize := SizeOf(TDSBufferDesc);

        BufDesc.dwFlags := DSBCAPS_STATIC; // could also use DSBCAPS_LOCHARDWARE to

                                           // force the buffer into hardware memory

        {create the sound buffer object}

        DXSound.CreateSoundBuffer(BufDesc, Buffer, nil);

        {fill the sound buffer with the audio data from the resource}

        DSFillSoundBuffer(Buffer, pbWaveData, BufDesc.dwBufferBytes);

      end;

    end;

    {this function is used to restore the contents of an IDirectSoundBuffer object

     when its memory has been lost. it is very similar to the LoadSound function}

    procedure ReloadSound(ResName: PChar; var Buffer: IDirectSoundBuffer);

    var

      BufDesc: TDSBufferDesc;

      pbWaveData: PByte;

    begin

      {empty the buffer description record}

      FillMemory(@BufDesc, SizeOf(TDSBufferDesc), 0);

      {load the wave resource, initializing a pointer to the wave data

       and the size of the data}

      if DSGetWaveResource(0, ResName, BufDesc.lpwfxFormat, pbWaveData,

                           BufDesc.dwBufferBytes) then

      begin

        {restore the buffer’s memory}

        Buffer.Restore;

        {fill the sound buffer with the audio data from the resource}

        DSFillSoundBuffer(Buffer, pbWaveData, BufDesc.dwBufferBytes);

      end;

    end;

    procedure TForm1.Button1Click(Sender: TObject);

    begin

      {the Tag property of each button is set to the appropriate index into

       the array of IDirectSoundBuffer objects. when a button is pressed, reset

       the current position of the appropriate buffer, and start playing it}

      Sounds[TButton(Sender).Tag].SetCurrentPosition(0);

      {attempt to play the sound. if the buffer memory has been lost...}

      if Sounds[TButton(Sender).Tag].Play(0, 0, 0) = DSERR_BUFFERLOST then

      begin

        {...restore the sound buffer}

        ReloadSound(ResNames[TButton(Sender).Tag], Sounds[TButton(Sender).Tag]);

        {play the restored sound buffer}

        Sounds[TButton(Sender).Tag].SetCurrentPosition(0);

        Sounds[TButton(Sender).Tag].Play(0, 0, 0);

      end;

    end;

    procedure TForm1.FormCreate(Sender: TObject);

    var

      iCount: Integer;

    begin

      {create the DirectSound object}

      DirectSoundCreate(nil, DXSound, nil);

      {set its cooperative level (we won’t change the primary buffer format, so

       a cooperative level of Normal is all that is needed)}

      DXSound.SetCooperativeLevel(Handle, DSSCL_NORMAL);

      {load in the six example sounds}

      for iCount := 0 to 5 do

        LoadSound(ResNames[iCount], Sounds[iCount]);

    end;
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.