Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

Sound.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  Sound.c                                                                             */
00003 /*                                                                                      */
00004 /*  Author: Brian Adelberg                                                              */
00005 /*  Description: DirectSound wrapper                                                    */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 #include        <windows.h>
00023 #include        <dsound.h>
00024 #include        <stdio.h>
00025 #include        <assert.h>
00026 
00027 #include        "BaseType.h"
00028 #include        "ErrorLog.h"
00029 #include        "VFile.h"
00030 #include        "Sound.h"
00031 #include        "Ram.h"
00032 
00033 typedef struct  SoundManager    SoundManager;
00034 typedef struct  Channel                 Channel;
00035 
00036 
00037 typedef struct geSound_System
00038 {
00039         geBoolean               Active;
00040         SoundManager    *SoundM;
00041         geFloat                 GlobalVolume;
00042 } geSound_System;
00043 
00044 typedef struct geSound_Cfg
00045 {
00046         geFloat                 Volume;
00047         geFloat                 Pan;
00048         geFloat                 Frequency;
00049 } geSound_Cfg;
00050 
00051 
00052 /*
00053         The interfaces here allow an application to write sound data to
00054         abstract channels which are then to be mixed.  The interfaces here
00055         require two things.  First, that the application create only one
00056         sound manager per instance, and second that the type of sound data
00057         being passed into the sound channels remains constant.  That is,
00058         the format of the binary information is all one format from
00059         one sound to another; the application cannot combine RIFF and WAV
00060         formats in a single channel.
00061 */
00062 /*
00063         Call these ones only once per application:
00064 */
00065 
00066 static SoundManager *   CreateSoundManager(HWND hWnd);
00067 static void             DestroySoundManager(SoundManager *sm);
00068 
00069 //static BOOL           FillSoundChannel(SoundManager *sm, char* Dir, char *Name, unsigned int* Handle );
00070 static BOOL             FillSoundChannel(SoundManager *sm, geVFile *File, unsigned int* Handle );
00071 //static BOOL           FillSoundChannelMemory(SoundManager *sm, const void *Buffer, unsigned int* Handle );
00072 static BOOL             StartSoundChannel( SoundManager *sm, unsigned int Handle, geSound_Cfg *cfg, int loop, unsigned int* sfx);
00073 static BOOL             StopSoundChannel(Channel *channel);
00074 static BOOL             FreeAllChannels(SoundManager *sm);
00075 static BOOL             FreeChannel(SoundManager *sm, Channel *channel);
00076 static BOOL             ModifyChannel( Channel *channel, geSound_Cfg *cfg );
00077 static int              ChannelPlaying( Channel *channel );
00078 static Channel* GetChannel( SoundManager *sm, unsigned int ID );
00079 
00080 
00081 typedef struct Channel
00082 {
00083 //      char*                           name;
00084         LPDIRECTSOUNDBUFFER     buffer;
00085         unsigned int            ID;
00086         int                                     BaseFreq;
00087         geSound_Cfg                     cfg;
00088         void *                          Data;
00089         struct Channel          *next;
00090         struct Channel          *nextDup;
00091 } Channel;
00092 
00093 typedef struct  SoundManager
00094 {
00095         int                                             smChannelCount;
00096         unsigned int                    smNextChannelID;
00097 
00098         LPDIRECTSOUNDBUFFER     smPrimaryChannel;
00099         Channel*                                smChannels;
00100     //LPDIRECTSOUNDNOTIFY *   smNotify;
00101 }   SoundManager;
00102 
00103 static  LPDIRECTSOUND                   lpDirectSound;
00104 // This isn't really safe as a global.  But it's consistent with the global lpDirectSound.
00105 static  HMODULE                                 hmodDirectSound = NULL;
00106 
00107 //      Added 11/08/1999 Ed Averill to expose DSound object for external code
00108 GENESISAPI void *geSound_GetDSound()
00109 {
00110   return (void *)lpDirectSound;
00111 }
00112 //      End 11/08/1999 addition
00113 
00114 //=====================================================================================
00115 //      geSound_SystemCreate
00116 //=====================================================================================
00117 GENESISAPI      geSound_System *geSound_CreateSoundSystem(HWND hWnd)
00118 {
00119         geSound_System          *SoundSystem;
00120 
00121         SoundSystem = GE_RAM_ALLOCATE_STRUCT(geSound_System);
00122 
00123         if (!SoundSystem)
00124         {
00125                 geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL);
00126                 return NULL;
00127         }
00128 
00129         memset(SoundSystem, 0, sizeof(geSound_System));
00130         
00131         // Initialize the sound system
00132         SoundSystem->SoundM = CreateSoundManager(hWnd);
00133 
00134         if (!SoundSystem->SoundM)
00135         {
00136                 geRam_Free(SoundSystem);
00137                 geErrorLog_Add(GE_ERR_CREATE_SOUND_MANAGER_FAILED, NULL);
00138                 return NULL;
00139         }
00140         SoundSystem->GlobalVolume = 1.0f;
00141 
00142         return SoundSystem;
00143 }
00144 
00145 //=====================================================================================
00146 //      geSound_SystemFree
00147 //=====================================================================================
00148 GENESISAPI      void geSound_DestroySoundSystem(geSound_System *Sound)
00149 {
00150         assert(Sound != NULL);
00151 
00152         // Shutdown the sound system
00153         DestroySoundManager(Sound->SoundM);
00154 
00155         Sound->SoundM = NULL;
00156 
00157         geRam_Free(Sound);
00158 }
00159 
00160 //=====================================================================================
00161 //      Sound_LoadSound
00162 //=====================================================================================
00163 //GENESISAPI    geSound_Def *geSound_LoadSoundDef(geSound_System *SoundS, const char *Path, const char *FileName)
00164 GENESISAPI      geSound_Def *geSound_LoadSoundDef(geSound_System *SoundS, geVFile *File)
00165 {
00166         unsigned int SoundDef = 0;
00167 
00168         assert(SoundS != NULL);
00169 
00170 //      if (!FillSoundChannel(SoundS->SoundM, (char*)Path, (char*)FileName, &SoundDef))
00171         if (!FillSoundChannel(SoundS->SoundM, File, &SoundDef))
00172                 return 0;
00173         
00174         return (geSound_Def *)SoundDef;
00175 }
00176 
00177 #if 0
00178 //=====================================================================================
00179 //      Sound_LoadSound
00180 //=====================================================================================
00181 GENESISAPI      geSound_Def *geSound_LoadSoundDefFromMemory(
00182         geSound_System *SoundS,
00183         const void *Buffer)
00184 {
00185         unsigned int SoundDef = 0;
00186 
00187         assert(SoundS != NULL);
00188         assert(Buffer != NULL);
00189 
00190         if (!FillSoundChannelMemory(SoundS->SoundM, Buffer, &SoundDef))
00191                 return 0;
00192         
00193         return (geSound_Def *)SoundDef;
00194 }
00195 #endif
00196 
00197 //=====================================================================================
00198 //      Sound_FreeSound
00199 //=====================================================================================
00200 GENESISAPI      void geSound_FreeSoundDef(geSound_System *SoundS, geSound_Def *SoundDef)
00201 {
00202         Channel*        Channel;
00203 
00204         assert(SoundS != NULL);
00205         assert(SoundDef != 0);
00206 
00207         Channel = GetChannel(SoundS->SoundM, (unsigned int)SoundDef);
00208 
00209         if (!Channel)
00210                 return;
00211 
00212         FreeChannel(SoundS->SoundM, Channel);
00213 }
00214 
00215 //=====================================================================================
00216 //      Sound_FreeAllChannels
00217 //=====================================================================================
00218 GENESISAPI      void geSound_FreeAllChannels(geSound_System *SoundS)
00219 {
00220         if (!SoundS) return;
00221 
00222         FreeAllChannels( SoundS->SoundM );
00223 }
00224 
00225 //=====================================================================================
00226 //      Sound_SetGlobalVolume
00227 //=====================================================================================
00228 GENESISAPI      geBoolean geSound_SetMasterVolume( geSound_System *SoundS, geFloat Volume )
00229 {
00230         if( !SoundS )
00231                 return( GE_FALSE );
00232         SoundS->GlobalVolume = Volume;
00233         return( GE_TRUE );
00234 }
00235         
00236 //=====================================================================================
00237 //      Sound_PlaySound
00238 //=====================================================================================
00239 GENESISAPI      geSound *geSound_PlaySoundDef(geSound_System *SoundS, 
00240                                                         geSound_Def *SoundDef, 
00241                                                         geFloat Volume, 
00242                                                         geFloat Pan, 
00243                                                         geFloat Frequency, 
00244                                                         geBoolean Loop)
00245 {
00246         unsigned int Sound;
00247         geSound_Cfg LocalCfg;
00248 
00249         LocalCfg.Volume         = Volume;
00250         LocalCfg.Pan            = Pan;
00251         LocalCfg.Frequency  = Frequency;
00252 
00253         LocalCfg.Volume *= SoundS->GlobalVolume;
00254         if (!StartSoundChannel(SoundS->SoundM, (unsigned int)SoundDef, &LocalCfg, (BOOL)Loop, &Sound))
00255         {
00256                 return 0;
00257         }
00258 
00259         return (geSound *)Sound;
00260 }
00261         
00262 //=====================================================================================
00263 //      Sound_StopSound
00264 //=====================================================================================
00265 GENESISAPI      geBoolean geSound_StopSound(geSound_System *SoundS, geSound *Sound)
00266 {
00267         Channel*        Channel;
00268 
00269         assert(SoundS != NULL);
00270         assert(Sound  != NULL); 
00271 
00272         Channel = GetChannel(SoundS->SoundM, (unsigned int)Sound);
00273 
00274         if (!Channel)
00275                 return GE_FALSE;
00276 
00277         return StopSoundChannel(Channel);       
00278 }
00279 
00280 //=====================================================================================
00281 //      Sound_ModifySound
00282 //=====================================================================================
00283 GENESISAPI      geBoolean geSound_ModifySound(geSound_System *SoundS, 
00284                                                                 geSound *Sound,geFloat Volume, 
00285                                                                 geFloat Pan, 
00286                                                                 geFloat Frequency)
00287 {
00288         Channel*        Channel;
00289         geSound_Cfg     LocalCfg;
00290 
00291         assert(SoundS != NULL);
00292         assert(Sound  != NULL); 
00293 
00294         Channel = GetChannel(SoundS->SoundM, (unsigned int)Sound);
00295 
00296         if (!Channel)
00297                 return GE_FALSE;
00298         LocalCfg.Volume    = Volume;
00299         LocalCfg.Pan       = Pan;
00300         LocalCfg.Frequency = Frequency;
00301         LocalCfg.Volume *= SoundS->GlobalVolume;
00302         return ModifyChannel(Channel, &LocalCfg);
00303 }
00304 
00305 //=====================================================================================
00306 //      Sound_SoundIsPlaying
00307 //=====================================================================================
00308 GENESISAPI      geBoolean geSound_SoundIsPlaying(geSound_System *SoundS, geSound *Sound)
00309 {
00310         Channel*        Channel;
00311 
00312         assert(SoundS != NULL);
00313   if(Sound == NULL)
00314           return GE_FALSE;                                                                                              // eaa3 05/29/2000 don't assert if NULL handle!
00315 
00316         Channel = GetChannel(SoundS->SoundM, (unsigned int)Sound);
00317 
00318         if (!Channel)
00319                 return GE_FALSE;
00320 
00321         return ChannelPlaying(Channel);
00322 }
00323 
00324 
00325 //=====================================================================================
00326 //=====================================================================================
00327 
00328 static  BOOL DSParseWaveResource(const void *pvRes, WAVEFORMATEX **ppWaveHeader,
00329                          BYTE **ppbWaveData,DWORD *pcbWaveSize)
00330 {
00331     DWORD *pdw;
00332     DWORD *pdwEnd;
00333     DWORD dwRiff;
00334     DWORD dwType;
00335     DWORD dwLength;
00336 
00337     if (ppWaveHeader)
00338         *ppWaveHeader = NULL;
00339 
00340     if (ppbWaveData)
00341         *ppbWaveData = NULL;
00342 
00343     if (pcbWaveSize)
00344         *pcbWaveSize = 0;
00345 
00346     pdw = (DWORD *)pvRes;
00347     dwRiff = *pdw++;
00348     dwLength = *pdw++;
00349     dwType = *pdw++;
00350 
00351     if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
00352         goto exit;      // not even RIFF
00353 
00354     if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
00355         goto exit;      // not a WAV
00356 
00357     pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);
00358 
00359     while (pdw < pdwEnd)
00360     {
00361         dwType = *pdw++;
00362         dwLength = *pdw++;
00363 
00364         switch (dwType)
00365         {
00366         case mmioFOURCC('f', 'm', 't', ' '):
00367             if (ppWaveHeader && !*ppWaveHeader)
00368             {
00369                 if (dwLength < sizeof(WAVEFORMAT))
00370                     goto exit;      // not a WAV
00371 
00372                 *ppWaveHeader = (WAVEFORMATEX *)pdw;
00373 
00374                 if ((!ppbWaveData || *ppbWaveData) &&
00375                     (!pcbWaveSize || *pcbWaveSize))
00376                 {
00377                     return TRUE;
00378                 }
00379             }
00380             break;
00381 
00382         case mmioFOURCC('d', 'a', 't', 'a'):
00383             if ((ppbWaveData && !*ppbWaveData) ||
00384                 (pcbWaveSize && !*pcbWaveSize))
00385             {
00386                 if (ppbWaveData)
00387                     *ppbWaveData = (LPBYTE)pdw;
00388 
00389                 if (pcbWaveSize)
00390                     *pcbWaveSize = dwLength;
00391 
00392                 if (!ppWaveHeader || *ppWaveHeader)
00393                     return TRUE;
00394             }
00395             break;
00396         }
00397 
00398         pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));
00399     }
00400 
00401 exit:
00402     return FALSE;
00403 }
00404 
00405 static  BOOL DSFillSoundBuffer(IDirectSoundBuffer *pDSB, BYTE *pbWaveData, DWORD cbWaveSize)
00406 {
00407 
00408     if (pDSB && pbWaveData && cbWaveSize)
00409     {
00410         LPVOID pMem1, pMem2;
00411         DWORD dwSize1, dwSize2;
00412 
00413         if (SUCCEEDED(IDirectSoundBuffer_Lock(pDSB, 0, cbWaveSize,
00414             &pMem1, &dwSize1, &pMem2, &dwSize2, 0)))
00415         {
00416             ZeroMemory(pMem1, dwSize1);
00417             CopyMemory(pMem1, pbWaveData, dwSize1);
00418 
00419             if ( 0 != dwSize2 )
00420                 CopyMemory(pMem2, pbWaveData+dwSize1, dwSize2);
00421 
00422             IDirectSoundBuffer_Unlock(pDSB, pMem1, dwSize1, pMem2, dwSize2);
00423             return TRUE;
00424         }
00425     }
00426     return FALSE;
00427 }
00428 
00429 
00430 DSCAPS                  dsCaps;
00431 static  SoundManager *  CreateSoundManager(HWND hWnd )
00432 {
00433         typedef HRESULT (WINAPI *DS_CREATE_FUNC)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
00434         PCMWAVEFORMAT   pcmwf;
00435         DSBUFFERDESC    dsbdesc;
00436         HRESULT                 hres;
00437         SoundManager *  sm;
00438         DS_CREATE_FUNC pDirectSoundCreate;
00439 
00440         // load the DirectSound DLL
00441         hmodDirectSound = LoadLibrary ("DSOUND.DLL");
00442         if (hmodDirectSound == NULL)
00443         {
00444                 // Couldn't load DSOUND.DLL
00445                 return NULL;
00446         }
00447 
00448         pDirectSoundCreate = (DS_CREATE_FUNC)GetProcAddress (hmodDirectSound, "DirectSoundCreate");
00449         if (pDirectSoundCreate == NULL)
00450         {
00451                 // couldn't find the DirectSoundCreate function
00452                 FreeLibrary (hmodDirectSound);
00453                 return NULL;
00454         }
00455 
00456         hres = pDirectSoundCreate(NULL, &lpDirectSound, NULL);
00457         if      (hres != DS_OK)
00458         {
00459                 // failed somehow
00460                 FreeLibrary (hmodDirectSound);
00461                 return NULL;
00462         }
00463 
00464 //      sm = malloc(sizeof(*sm));
00465         sm = geRam_Allocate(sizeof(*sm));
00466         if      (!sm)
00467         {
00468                 IDirectSound_Release(lpDirectSound);
00469                 FreeLibrary (hmodDirectSound);
00470                 return NULL;
00471         }
00472         sm->smChannelCount = 0;
00473         sm->smNextChannelID = 1;
00474         sm->smChannels = NULL;
00475 
00476         memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
00477         pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
00478 
00479         //pcmwf.wf.nChannels = 1;
00480         //pcmwf.wf.nSamplesPerSec = 44050;
00481         //pcmwf.wf.nBlockAlign = 2;
00482 #if 1   
00483         pcmwf.wf.nChannels = 2;
00484         pcmwf.wf.nSamplesPerSec = 44100;
00485         pcmwf.wf.nBlockAlign = 4;
00486         pcmwf.wBitsPerSample = 16;
00487         pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
00488 #else
00489         pcmwf.wf.nChannels = 1;
00490         pcmwf.wf.nSamplesPerSec = 22050;
00491         pcmwf.wf.nBlockAlign = 1;
00492         pcmwf.wBitsPerSample = 8;
00493         pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * 2;
00494 #endif
00495 
00496         memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
00497         dsbdesc.dwSize = sizeof(DSBUFFERDESC);
00498         dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;// | DSBCAPS_CTRLDEFAULT;// | DSBCAPS_CTRL3D;
00499         dsbdesc.dwBufferBytes = 0; //dwBufferBytes and lpwfxFormat must be set this way.
00500         dsbdesc.lpwfxFormat = NULL;
00501 
00502 #if 1
00503         if (DS_OK== IDirectSound_SetCooperativeLevel(lpDirectSound, hWnd,DSSCL_NORMAL))
00504 #else
00505         if (DS_OK== IDirectSound_SetCooperativeLevel(lpDirectSound, hWnd,DSSCL_EXCLUSIVE))
00506 #endif
00507         {
00508                 if (DS_OK== IDirectSound_CreateSoundBuffer(lpDirectSound, &dsbdesc, &sm->smPrimaryChannel, NULL))
00509                 {
00510                         return sm;
00511                 }
00512                 IDirectSound_Release(lpDirectSound);
00513                 FreeLibrary (hmodDirectSound);
00514         }
00515 //      free( sm );
00516         geRam_Free(sm);
00517         return NULL;
00518 }
00519 
00520 //static        BOOL CreateChannel( char* Name, DSBUFFERDESC*   dsBD, Channel** chanelPtr)
00521 static  BOOL CreateChannel(DSBUFFERDESC*        dsBD, Channel** chanelPtr)
00522 {
00523         Channel* channel;
00524 
00525 //      channel = malloc( sizeof( Channel ) );
00526         channel = geRam_Allocate( sizeof( Channel ) );
00527         if      ( channel == NULL )
00528         {
00529                 geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL);
00530                 return( FALSE );
00531         }
00532         if(DS_OK != IDirectSound_CreateSoundBuffer(lpDirectSound, dsBD, &channel->buffer, NULL))
00533         {
00534                 geErrorLog_Add(GE_ERR_CREATE_SOUND_BUFFER_FAILED, NULL);
00535                 return FALSE;
00536         }
00537         if(DS_OK != IDirectSoundBuffer_GetFrequency(channel->buffer, &channel->BaseFreq) )
00538         {
00539                 geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
00540                 return FALSE;
00541         }
00542         channel->next = NULL;
00543         channel->nextDup = NULL;
00544         channel->ID = 0;
00545         channel->cfg.Volume = 1.0f;
00546         channel->cfg.Pan = 0.0f;
00547         channel->cfg.Frequency = 0.0f;
00548 //      channel->name = Name;
00549 
00550         *chanelPtr = channel;
00551         return( TRUE );
00552 }
00553 
00554 //static        BOOL GetSoundData( char* Name, unsigned char** dataPtr)
00555 static  BOOL GetSoundData( geVFile *File, unsigned char** dataPtr)
00556 {
00557 //      FILE * f;
00558         int32 Size;
00559         uint8 *data;
00560 //      int32           CurPos;
00561 
00562 #if 0
00563         f = fopen(Name, "rb");
00564         
00565         if (!f)
00566         {
00567                 geErrorLog_Add(GE_ERR_FILE_OPEN_ERROR, NULL);
00568                 return FALSE;
00569         }
00570 #endif
00571 
00572 #if 0
00573         CurPos = ftell (f);                             // Save the startinf pos into this function
00574         fseek (f, 0, SEEK_END);                 // Seek to end
00575         Size = ftell (f);                               // Get End (this will be the size)
00576         fseek (f, CurPos, SEEK_SET);    // Restore file position
00577 #endif
00578 
00579         if      (geVFile_Size(File, &Size) == GE_FALSE)
00580                 return FALSE;
00581 
00582         data = geRam_Allocate(Size);
00583 
00584         if (!data) 
00585         {
00586                 geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL);
00587                 return FALSE;
00588         }
00589         
00590         if      (geVFile_Read(File, data, Size) == GE_FALSE)
00591         {
00592                 geRam_Free(data);
00593                 return FALSE;
00594         }
00595 
00596 //      fread(data, Size, 1, f);
00597 
00598 //      fclose(f);
00599         *dataPtr = data;
00600         return( TRUE );
00601 }
00602 
00603 static  BOOL ParseData( const uint8* data, DSBUFFERDESC* dsBD, BYTE ** pbWaveData )
00604 {
00605 
00606         //Parse the Data
00607         memset(dsBD, 0, sizeof(DSBUFFERDESC));
00608 
00609         dsBD->dwSize = sizeof(DSBUFFERDESC);
00610         dsBD->dwFlags = DSBCAPS_STATIC | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
00611         if      (!DSParseWaveResource(data, &dsBD->lpwfxFormat, pbWaveData, &dsBD->dwBufferBytes))
00612         {
00613                 geErrorLog_Add(GE_ERR_INVALID_WAV, NULL);
00614                 return FALSE;
00615         }
00616         return( TRUE );
00617 
00618 }
00619 
00620 //static        BOOL FillSoundChannel(SoundManager *sm, char* Dir, char *Name, unsigned int* Handle )
00621 static  BOOL FillSoundChannel(SoundManager *sm, geVFile *File, unsigned int* Handle )
00622 {
00623         DSBUFFERDESC    dsBD;
00624         INT NumBytes;
00625         uint8           *data = NULL;
00626         BYTE *                  pbWaveData;
00627 //      char*   Name2;
00628         Channel* channel;
00629 
00630         *Handle = 0;
00631         if (!sm)
00632                 return TRUE;
00633 
00634 #if 0
00635         //Open the file
00636         if (Dir)
00637         {
00638                 Name2 = malloc( strlen( Name ) + strlen( Dir ) + 3);  // 2 for the "//" and 1 for terminator
00639                 if( !Name2 )
00640                         return( 0 );
00641                 sprintf(Name2, "%s\\%s", Dir, Name);
00642         }
00643         else
00644         {
00645                 Name2 = malloc( strlen( Name ) + 3);  // 2 for the "//" and 1 for terminator
00646                 if( !Name2 )
00647                         return( 0 );
00648 
00649                 sprintf(Name2, "%s", Name);
00650         }
00651 #endif
00652         if(!GetSoundData( File, &data ))
00653                 return( FALSE );
00654 
00655         if( !ParseData( data, &dsBD, &pbWaveData ) )
00656         {
00657                 geRam_Free(data);
00658                 return( FALSE );
00659         }
00660 
00661         NumBytes = dsBD.dwBufferBytes;
00662         
00663         //Create the channel
00664 //      if( !CreateChannel( Name2, &dsBD, &channel ) )
00665         if      (!CreateChannel(&dsBD, &channel))
00666         {
00667                 geRam_Free(data);
00668                 return FALSE;
00669         }
00670         channel->next = sm->smChannels;
00671         channel->ID = sm->smNextChannelID++;
00672         channel->Data = data;
00673 
00674         sm->smChannels = channel;
00675         sm->smChannelCount++;
00676 
00677         //Fill the channel
00678         if (!DSFillSoundBuffer(channel->buffer, pbWaveData, NumBytes))
00679                 return FALSE;
00680         
00681 //      free( data );
00682 //      geRam_Free(data);
00683 
00684         *Handle = channel->ID;
00685         return TRUE;
00686 }
00687 
00688 #if 0
00689 static  BOOL FillSoundChannelMemory(SoundManager *sm, const void *Buffer, unsigned int* Handle )
00690 {
00691         DSBUFFERDESC    dsBD;
00692         INT                     NumBytes;
00693         BYTE *                  pbWaveData;
00694         char *                  Name;
00695         Channel *               channel;
00696 
00697         *Handle = 0;
00698         if      (!sm)
00699                 return TRUE;
00700 
00701         if      (!ParseData(Buffer, &dsBD, &pbWaveData))
00702                 return FALSE;
00703 
00704         NumBytes = dsBD.dwBufferBytes;
00705 
00706         Name = malloc(11);
00707         if      (Name == NULL)
00708                 return FALSE;
00709         sprintf(Name, "0x%8x", Buffer);
00710         
00711         //Create the channel
00712 //      if      (!CreateChannel(Name, &dsBD, &channel))
00713         if      (!CreateChannel(&dsBD, &channel))
00714                 return FALSE;
00715 
00716         channel->next = sm->smChannels;
00717         channel->ID   = sm->smNextChannelID++;
00718 
00719         sm->smChannels = channel;
00720         sm->smChannelCount++;
00721 
00722         //Fill the channel
00723         if      (!DSFillSoundBuffer(channel->buffer, pbWaveData, NumBytes))
00724                 return FALSE;
00725         
00726         *Handle = channel->ID;
00727         return TRUE;
00728 }
00729 #endif
00730 
00731 static  void StopDupBuffers( Channel* channel )
00732 {
00733         Channel* dupChannel, *prevChannel;
00734 
00735         assert( channel );
00736 
00737         dupChannel = channel->nextDup;
00738         prevChannel = channel;
00739         while( dupChannel )
00740         {
00741                 IDirectSoundBuffer_Stop(dupChannel->buffer);
00742                 dupChannel = dupChannel->nextDup;
00743         }
00744 }
00745 
00746 static  void ClearDupBuffers( Channel* channel )
00747 {
00748         Channel* dupChannel, *prevChannel;
00749 
00750         if( channel == NULL)
00751                 return;
00752 
00753         dupChannel = channel->nextDup;
00754         prevChannel = channel;
00755         while( dupChannel )
00756         {
00757                 if( !ChannelPlaying( dupChannel ) )
00758                 {
00759                         prevChannel->nextDup = dupChannel->nextDup;
00760                         IDirectSound_Release(dupChannel->buffer);
00761 //                      free( dupChannel );
00762                         geRam_Free(dupChannel);
00763                         dupChannel = prevChannel->nextDup;
00764                 }
00765                 else
00766                 {
00767                         prevChannel = dupChannel;
00768                         dupChannel = dupChannel->nextDup;
00769                 }
00770         }
00771 }
00772 
00773 static  BOOL FreeAllChannels(SoundManager *sm)
00774 {
00775         int Error;
00776         
00777         Channel* channel, *nextChannel;
00778 
00779         channel = sm->smChannels;
00780         while( channel )
00781         {
00782                 nextChannel = channel->next;
00783                 StopDupBuffers( channel );
00784                 ClearDupBuffers( channel );
00785                 Error = IDirectSoundBuffer_Stop(channel->buffer);
00786                 if (Error != DS_OK)
00787                 {
00788                         geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
00789                         return FALSE;
00790                 }
00791                 Error = IDirectSound_Release(channel->buffer);
00792                 if (Error != DS_OK)
00793                 {
00794                         geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
00795                         return FALSE;
00796                 }
00797                 
00798 //              if( channel->name )
00799 //                      geRam_Free(channel->name);
00800 //                      free( channel->name );
00801                 if      (channel->Data)
00802                         geRam_Free(channel->Data);
00803                 geRam_Free(channel);
00804 //              free( channel );
00805                 channel = nextChannel;
00806         }
00807         sm->smChannels = NULL;
00808         sm->smChannelCount = 0;
00809 
00810         return TRUE;
00811 }
00812 
00813 
00814 static  BOOL FreeChannel(SoundManager *sm, Channel* channel)
00815 {
00816         int Error;
00817         Channel*prevChannel = NULL, *curChannel;
00818         if      ( channel )
00819         {
00820                 StopDupBuffers( channel );
00821                 ClearDupBuffers( channel );
00822                 Error = IDirectSoundBuffer_Stop(channel->buffer);
00823                 if (Error != DS_OK)
00824                 {
00825                         geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
00826                         return FALSE;
00827                 }
00828                 Error = IDirectSound_Release(channel->buffer);
00829                 if (Error != DS_OK)
00830                 {
00831                         geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
00832                         return FALSE;
00833                 }
00834 //              if( channel->name )
00835 //                      geRam_Free(channel->name);
00836 //                      free( channel->name );
00837 
00838                 if( channel->Data )
00839                         geRam_Free(channel->Data);
00840 
00841                 curChannel = sm->smChannels;
00842                 while( curChannel && curChannel != channel )
00843                 {
00844                         prevChannel = curChannel;
00845                         curChannel = curChannel->next;
00846                 }
00847                 if( curChannel )
00848                 {
00849                         if( prevChannel )
00850                                 prevChannel->next = curChannel->next;
00851                         else
00852                                 sm->smChannels = curChannel->next;
00853                         geRam_Free(curChannel);
00854 //                      free( curChannel );
00855                 }
00856         }
00857 
00858         return TRUE;
00859 }
00860 
00861 static  Channel* ReloadData(void *Data)
00862 {
00863         DSBUFFERDESC    dsBD;
00864         BYTE *                  pbWaveData;
00865         INT NumBytes;
00866 //      uint8           *data = NULL;
00867         Channel* channel;
00868 
00869 //      if( !Name )
00870 //              return( NULL );
00871 //      if( !GetSoundData( Data, &data ) )
00872 //              return( NULL );
00873 
00874         if( !ParseData( Data, &dsBD, &pbWaveData ) )
00875                 return( NULL );
00876 
00877         NumBytes = dsBD.dwBufferBytes;
00878         
00879         //Create the channel
00880 //      if( !CreateChannel( Name, &dsBD, &channel ) )
00881         if( !CreateChannel(&dsBD, &channel ) )
00882                 return NULL;
00883 
00884         //Fill the channel
00885         if ( !DSFillSoundBuffer(channel->buffer, pbWaveData, NumBytes))
00886                 return NULL;
00887         
00888 //      geRam_Free(data);
00889 //      free( data );
00890         return( channel );
00891 }
00892 
00893 static  BOOL DupChannel( SoundManager *sm, Channel* channel, Channel** dupChannelPtr )
00894 {
00895         Channel* dupChannel;
00896         HRESULT Error;
00897 
00898         *dupChannelPtr = NULL;
00899 //      dupChannel =  malloc( sizeof(Channel ) );
00900         dupChannel =  geRam_Allocate( sizeof(Channel ) );
00901         if( dupChannel == NULL )
00902         {
00903                 geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL );
00904                 return FALSE;
00905         }
00906         Error = IDirectSound_DuplicateSoundBuffer( lpDirectSound, channel->buffer, &dupChannel->buffer );
00907         if( Error != DS_OK )
00908         {
00909                 geRam_Free(dupChannel);
00910 //              free( dupChannel );
00911                 dupChannel = ReloadData( channel->Data );
00912                 if( dupChannel == NULL )
00913                 {
00914                         geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
00915                         return FALSE;
00916                 }
00917         }
00918         dupChannel->ID =  sm->smNextChannelID++;
00919         dupChannel->next = NULL;
00920         dupChannel->nextDup = channel->nextDup;
00921         dupChannel->cfg = channel->cfg;
00922 //      dupChannel->name = NULL;
00923         dupChannel->Data = channel->Data;
00924         channel->nextDup = dupChannel;
00925         *dupChannelPtr = dupChannel;
00926         return( TRUE );
00927 }
00928 
00929 static  BOOL    StartSoundChannel( SoundManager *sm, unsigned int Handle, geSound_Cfg *cfg, int loop, unsigned int* sfx)
00930 {
00931         HRESULT hres;
00932         Channel* channel, *dupChannel;
00933         
00934         if( Handle == 0 )
00935                 return( FALSE );
00936         channel = GetChannel( sm, Handle );
00937         //Clear all non-playing duplicate buffers.
00938         ClearDupBuffers(channel);
00939         //If the main buffer is playing and all non-playing dups have been cleared
00940         //we need a new duplicate.
00941         if( ChannelPlaying( channel ) )
00942         {
00943                 if(!DupChannel( sm,channel, &dupChannel ) )
00944                         return( FALSE );
00945                 channel = dupChannel;
00946         }
00947         if( !ModifyChannel( channel, cfg ) )
00948                 return( FALSE );
00949         IDirectSoundBuffer_SetCurrentPosition(channel->buffer, 0);
00950         hres = IDirectSoundBuffer_Play( channel->buffer,
00951                                                                    0,
00952                                                                    0,
00953                                                                    loop ? DSBPLAY_LOOPING : 0);
00954 
00955         if      (hres == DS_OK)
00956         {
00957                 if( sfx )
00958                         *sfx = channel->ID;
00959                 return TRUE;
00960         }
00961         
00962         geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
00963         return FALSE;
00964 }
00965 
00966 static  BOOL StopSoundChannel(Channel* channel)
00967 {
00968         HRESULT hres;
00969 
00970         assert(channel);
00971 
00972         hres = IDirectSoundBuffer_Stop(channel->buffer);
00973 
00974         if      (hres == DS_OK)
00975                 return TRUE;
00976 
00977         geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
00978         return FALSE;
00979 }
00980 
00981 static  void DestroySoundManager(SoundManager *sm)
00982 {
00983         if (!sm) return;
00984 
00985         FreeAllChannels( sm );
00986         if      (sm->smPrimaryChannel != NULL)
00987                 sm->smPrimaryChannel->lpVtbl->Release(sm->smPrimaryChannel);
00988         if      (lpDirectSound != NULL)
00989                 IDirectSound_Release(lpDirectSound);
00990         if  (hmodDirectSound != NULL)
00991                 FreeLibrary (hmodDirectSound);
00992         geRam_Free(sm);
00993 //      free(sm);
00994 }
00995 
00996 static  BOOL    ModifyChannel( Channel *channel, geSound_Cfg *cfg )
00997 {
00998         int Error, Vol, Pan, Freq;
00999         assert(channel);
01000         
01001         if( !cfg )
01002                 return( TRUE );
01003         ClearDupBuffers(channel);
01004         if( cfg->Volume != channel->cfg.Volume )
01005         {
01006                 Vol = (DWORD)((1.0 - cfg->Volume  ) * DSBVOLUME_MIN);
01007                 Error = IDirectSoundBuffer_SetVolume(channel->buffer, Vol);
01008                 if (Error != DS_OK)
01009                 {
01010                         geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
01011                         return FALSE;
01012                 }
01013                 channel->cfg.Volume = cfg->Volume;
01014         }
01015 
01016         if( cfg->Pan != channel->cfg.Pan )
01017         {
01018                 Pan = (int)(cfg->Pan  * DSBPAN_RIGHT);
01019                 Error = IDirectSoundBuffer_SetPan(channel->buffer, Pan);
01020                 if (Error != DS_OK)
01021                 {
01022                         geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
01023                         return FALSE;
01024                 }
01025                 channel->cfg.Pan = cfg->Pan;
01026         }
01027 
01028 
01029         if( cfg->Frequency != channel->cfg.Frequency )
01030         {
01031 
01032                 Freq = (DWORD)(channel->BaseFreq * cfg->Frequency);
01033                 
01034                 if(Freq < 0)
01035                         Freq = 0;
01036 
01037                 Error = IDirectSoundBuffer_SetFrequency(channel->buffer, Freq);
01038                 if (Error != DS_OK)
01039                 {
01040                         geErrorLog_Add(GE_ERR_DS_ERROR, NULL);
01041                         return FALSE;
01042                 }
01043                 channel->cfg.Frequency = cfg->Frequency;
01044         }
01045 
01046         return TRUE;
01047 }
01048 
01049 static  int     ChannelPlaying( Channel *channel )
01050 {
01051         DWORD status, Error;
01052 
01053         if(!channel)
01054                 return( 0 );
01055 
01056         Error = IDirectSoundBuffer_GetStatus( channel->buffer, &status);
01057         if( Error != DS_OK)
01058                 return 0;
01059         return( status & DSBSTATUS_PLAYING  );
01060 }
01061 
01062 static  Channel* GetChannel( SoundManager *sm, unsigned int ID )
01063 {
01064         Channel* dupChannel;
01065         Channel* channel = sm->smChannels;
01066 
01067         while( channel )
01068         {
01069                 if( channel->ID == ID )
01070                         break;
01071                 dupChannel = channel->nextDup;
01072                 while( dupChannel )
01073                 {
01074                         if( dupChannel->ID == ID )
01075                                 break;
01076                         dupChannel = dupChannel->nextDup;
01077                 }
01078                 if( dupChannel )
01079                         return( dupChannel );
01080                 channel = channel->next;
01081         }
01082         return( channel );
01083 }

Generated on Tue Sep 30 12:36:23 2003 for GTestAndEngine by doxygen 1.3.2