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

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