00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 static SoundManager * CreateSoundManager(HWND hWnd);
00066 static void DestroySoundManager(SoundManager *sm);
00067
00068
00069 static BOOL FillSoundChannel(SoundManager *sm, geVFile *File, unsigned int* Handle );
00070
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
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
00100 } SoundManager;
00101
00102 static LPDIRECTSOUND lpDirectSound = NULL;
00103
00104 static HMODULE hmodDirectSound = NULL;
00105
00106
00107 GENESISAPI void *geSound_GetDSound()
00108 {
00109 return (void *)lpDirectSound;
00110 }
00111
00112
00113
00114
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
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
00146
00147 GENESISAPI void geSound_DestroySoundSystem(geSound_System *Sound)
00148 {
00149 assert(Sound != NULL);
00150
00151
00152 DestroySoundManager(Sound->SoundM);
00153
00154 Sound->SoundM = NULL;
00155
00156 geRam_Free(Sound);
00157 }
00158
00159
00160
00161
00162
00163 GENESISAPI geSound_Def *geSound_LoadSoundDef(geSound_System *SoundS, geVFile *File)
00164 {
00165 unsigned int SoundDef = 0;
00166
00167 assert(SoundS != NULL);
00168
00169
00170 if (!FillSoundChannel(SoundS->SoundM, File, &SoundDef))
00171 return 0;
00172
00173 return (geSound_Def *)SoundDef;
00174 }
00175
00176 #if 0
00177
00178
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
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
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
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
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
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
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;
00341
00342 if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
00343 goto exit;
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;
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
00429 hmodDirectSound = LoadLibrary ("DSOUND.DLL");
00430 if (hmodDirectSound == NULL)
00431 {
00432
00433 return NULL;
00434 }
00435
00436 pDirectSoundCreate = (DS_CREATE_FUNC)GetProcAddress (hmodDirectSound, "DirectSoundCreate");
00437 if (pDirectSoundCreate == NULL)
00438 {
00439
00440 FreeLibrary (hmodDirectSound);
00441 return NULL;
00442 }
00443
00444 hres = pDirectSoundCreate(NULL, &lpDirectSound, NULL);
00445 if (hres != DS_OK)
00446 {
00447
00448 FreeLibrary (hmodDirectSound);
00449 return NULL;
00450 }
00451
00452
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
00468
00469
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;
00487 dsbdesc.dwBufferBytes = 0;
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
00504 geRam_Free(sm);
00505 return NULL;
00506 }
00507
00508
00509 static BOOL CreateChannel(DSBUFFERDESC* dsBD, Channel** chanelPtr)
00510 {
00511 Channel* channel;
00512
00513
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
00537
00538 *chanelPtr = channel;
00539 return( TRUE );
00540 }
00541
00542
00543 static BOOL GetSoundData( geVFile *File, unsigned char** dataPtr)
00544 {
00545
00546 int32 Size;
00547 uint8 *data;
00548
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);
00562 fseek (f, 0, SEEK_END);
00563 Size = ftell (f);
00564 fseek (f, CurPos, SEEK_SET);
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
00585
00586
00587 *dataPtr = data;
00588 return( TRUE );
00589 }
00590
00591 static BOOL ParseData( const uint8* data, DSBUFFERDESC* dsBD, BYTE ** pbWaveData )
00592 {
00593
00594
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
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
00617 Channel* channel;
00618
00619 *Handle = 0;
00620 if (!sm)
00621 return TRUE;
00622
00623 #if 0
00624
00625 if (Dir)
00626 {
00627 Name2 = malloc( strlen( Name ) + strlen( Dir ) + 3);
00628 if( !Name2 )
00629 return( 0 );
00630 sprintf(Name2, "%s\\%s", Dir, Name);
00631 }
00632 else
00633 {
00634 Name2 = malloc( strlen( Name ) + 3);
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
00653
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
00667 if (!DSFillSoundBuffer(channel->buffer, pbWaveData, NumBytes))
00668 return FALSE;
00669
00670
00671
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
00701
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
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
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
00788
00789
00790 if (channel->Data)
00791 geRam_Free(channel->Data);
00792 geRam_Free(channel);
00793
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
00824
00825
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
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
00856 Channel* channel;
00857
00858
00859
00860
00861
00862
00863 if( !ParseData( Data, &dsBD, &pbWaveData ) )
00864 return( NULL );
00865
00866 NumBytes = dsBD.dwBufferBytes;
00867
00868
00869
00870 if( !CreateChannel(&dsBD, &channel ) )
00871 return NULL;
00872
00873
00874 if ( !DSFillSoundBuffer(channel->buffer, pbWaveData, NumBytes))
00875 return NULL;
00876
00877
00878
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
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
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
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
00927 ClearDupBuffers(channel);
00928
00929
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
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 }