00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 static SoundManager * CreateSoundManager(HWND hWnd);
00067 static void DestroySoundManager(SoundManager *sm);
00068
00069
00070 static BOOL FillSoundChannel(SoundManager *sm, geVFile *File, unsigned int* Handle );
00071
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
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
00101 } SoundManager;
00102
00103 static LPDIRECTSOUND lpDirectSound;
00104
00105 static HMODULE hmodDirectSound = NULL;
00106
00107
00108 GENESISAPI void *geSound_GetDSound()
00109 {
00110 return (void *)lpDirectSound;
00111 }
00112
00113
00114
00115
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
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
00147
00148 GENESISAPI void geSound_DestroySoundSystem(geSound_System *Sound)
00149 {
00150 assert(Sound != NULL);
00151
00152
00153 DestroySoundManager(Sound->SoundM);
00154
00155 Sound->SoundM = NULL;
00156
00157 geRam_Free(Sound);
00158 }
00159
00160
00161
00162
00163
00164 GENESISAPI geSound_Def *geSound_LoadSoundDef(geSound_System *SoundS, geVFile *File)
00165 {
00166 unsigned int SoundDef = 0;
00167
00168 assert(SoundS != NULL);
00169
00170
00171 if (!FillSoundChannel(SoundS->SoundM, File, &SoundDef))
00172 return 0;
00173
00174 return (geSound_Def *)SoundDef;
00175 }
00176
00177 #if 0
00178
00179
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
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
00217
00218 GENESISAPI void geSound_FreeAllChannels(geSound_System *SoundS)
00219 {
00220 if (!SoundS) return;
00221
00222 FreeAllChannels( SoundS->SoundM );
00223 }
00224
00225
00226
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
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
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
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
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;
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;
00353
00354 if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
00355 goto exit;
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;
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
00441 hmodDirectSound = LoadLibrary ("DSOUND.DLL");
00442 if (hmodDirectSound == NULL)
00443 {
00444
00445 return NULL;
00446 }
00447
00448 pDirectSoundCreate = (DS_CREATE_FUNC)GetProcAddress (hmodDirectSound, "DirectSoundCreate");
00449 if (pDirectSoundCreate == NULL)
00450 {
00451
00452 FreeLibrary (hmodDirectSound);
00453 return NULL;
00454 }
00455
00456 hres = pDirectSoundCreate(NULL, &lpDirectSound, NULL);
00457 if (hres != DS_OK)
00458 {
00459
00460 FreeLibrary (hmodDirectSound);
00461 return NULL;
00462 }
00463
00464
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
00480
00481
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;
00499 dsbdesc.dwBufferBytes = 0;
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
00516 geRam_Free(sm);
00517 return NULL;
00518 }
00519
00520
00521 static BOOL CreateChannel(DSBUFFERDESC* dsBD, Channel** chanelPtr)
00522 {
00523 Channel* channel;
00524
00525
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
00549
00550 *chanelPtr = channel;
00551 return( TRUE );
00552 }
00553
00554
00555 static BOOL GetSoundData( geVFile *File, unsigned char** dataPtr)
00556 {
00557
00558 int32 Size;
00559 uint8 *data;
00560
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);
00574 fseek (f, 0, SEEK_END);
00575 Size = ftell (f);
00576 fseek (f, CurPos, SEEK_SET);
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
00597
00598
00599 *dataPtr = data;
00600 return( TRUE );
00601 }
00602
00603 static BOOL ParseData( const uint8* data, DSBUFFERDESC* dsBD, BYTE ** pbWaveData )
00604 {
00605
00606
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
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
00628 Channel* channel;
00629
00630 *Handle = 0;
00631 if (!sm)
00632 return TRUE;
00633
00634 #if 0
00635
00636 if (Dir)
00637 {
00638 Name2 = malloc( strlen( Name ) + strlen( Dir ) + 3);
00639 if( !Name2 )
00640 return( 0 );
00641 sprintf(Name2, "%s\\%s", Dir, Name);
00642 }
00643 else
00644 {
00645 Name2 = malloc( strlen( Name ) + 3);
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
00664
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
00678 if (!DSFillSoundBuffer(channel->buffer, pbWaveData, NumBytes))
00679 return FALSE;
00680
00681
00682
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
00712
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
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
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
00799
00800
00801 if (channel->Data)
00802 geRam_Free(channel->Data);
00803 geRam_Free(channel);
00804
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
00835
00836
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
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
00867 Channel* channel;
00868
00869
00870
00871
00872
00873
00874 if( !ParseData( Data, &dsBD, &pbWaveData ) )
00875 return( NULL );
00876
00877 NumBytes = dsBD.dwBufferBytes;
00878
00879
00880
00881 if( !CreateChannel(&dsBD, &channel ) )
00882 return NULL;
00883
00884
00885 if ( !DSFillSoundBuffer(channel->buffer, pbWaveData, NumBytes))
00886 return NULL;
00887
00888
00889
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
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
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
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
00938 ClearDupBuffers(channel);
00939
00940
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
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 }