Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
244 chris 1
#include "DSoundManager.h"
2
#include <io.h>
3
#include <fcntl.h>
4
#include "debug.h"
5
#include "DSoundInstance.h"
6
#include "FModLoader.h"
7
#include <math.h>
8
#include "..\PakLib\PakInterface.h"
9
 
10
using namespace Sexy;
11
 
12
#define USE_OGG_LIB
13
 
14
 
15
#ifdef USE_OGG_LIB
16
#include "ogg/ivorbiscodec.h"
17
#include "ogg/ivorbisfile.h"
18
#endif
19
 
20
#define SOUND_FLAGS (DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME |  DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLFREQUENCY)
21
DSoundManager::DSoundManager(HWND theHWnd, bool haveFMod)
22
{
23
        mHaveFMod = haveFMod;
24
        mLastReleaseTick = 0;
25
        mPrimaryBuffer = NULL;
26
 
27
        int i;
28
 
29
        for (i = 0; i < MAX_SOURCE_SOUNDS; i++)
30
        {
31
                mSourceSounds[i] = NULL;
32
                mBaseVolumes[i] = 1;
33
                mBasePans[i] = 0;
34
        }
35
 
36
        for (i = 0; i < MAX_CHANNELS; i++)
37
                mPlayingSounds[i] = NULL;
38
 
39
        mDirectSound = NULL;
40
 
41
        mMasterVolume = 1.0;
42
 
43
        if (theHWnd != NULL)
44
        {
45
                extern HMODULE gDSoundDLL;
46
                typedef HRESULT (WINAPI *DirectSoundCreateFunc)(LPCGUID lpcGuid, LPDIRECTSOUND * ppDS, LPUNKNOWN  pUnkOuter);
47
                DirectSoundCreateFunc aDirectSoundCreateFunc = (DirectSoundCreateFunc)GetProcAddress(gDSoundDLL,"DirectSoundCreate");
48
 
49
                if (aDirectSoundCreateFunc != NULL && aDirectSoundCreateFunc(NULL, &mDirectSound, NULL) == DS_OK)
50
                {
51
                        //FSOUND_SetOutput(FSOUND_OUTPUT_WINMM);
52
                        if (mHaveFMod)
53
                        {
54
                                LoadFModDLL();
55
 
56
                                gFMod->FSOUND_SetHWND(theHWnd);
57
                                gFMod->FSOUND_SetBufferSize(200); // #LUC
58
                                gFMod->FSOUND_Init(44100, 64, FSOUND_INIT_GLOBALFOCUS);
59
                        }
60
 
61
                        HRESULT aResult = mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_PRIORITY);
62
                        if (SUCCEEDED(aResult))
63
                        {
64
                                // Set primary buffer to 16-bit 44.1Khz
65
                                WAVEFORMATEX aWaveFormat;
66
                                DSBUFFERDESC aBufferDesc;
67
 
68
                                // Set up wave format structure.
69
                                int aBitCount = 16;
70
                                int aChannelCount = 2;
71
                                int aSampleRate = 44100;
72
 
73
                                // Set up wave format structure.
74
                                memset(&aWaveFormat, 0, sizeof(WAVEFORMATEX));
75
                                aWaveFormat.cbSize = sizeof(WAVEFORMATEX);
76
                                aWaveFormat.wFormatTag = WAVE_FORMAT_PCM;
77
                                aWaveFormat.nChannels = aChannelCount;
78
                                aWaveFormat.nSamplesPerSec = aSampleRate;
79
                                aWaveFormat.nBlockAlign = aChannelCount*aBitCount/8;
80
                                aWaveFormat.nAvgBytesPerSec =
81
                                                aWaveFormat.nSamplesPerSec * aWaveFormat.nBlockAlign;
82
                                aWaveFormat.wBitsPerSample = aBitCount;
83
 
84
                                // Set up DSBUFFERDESC structure.
85
                                memset(&aBufferDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
86
                                aBufferDesc.dwSize = sizeof(DSBUFFERDESC1);
87
                                aBufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER;//| DSBCAPS_CTRL3D; // Need default controls (pan, volume, frequency).
88
                                aBufferDesc.dwBufferBytes = 0;
89
                                aBufferDesc.lpwfxFormat =NULL;//(LPWAVEFORMATEX)&aWaveFormat;
90
 
91
                                HRESULT aResult = mDirectSound->CreateSoundBuffer(&aBufferDesc, &mPrimaryBuffer, NULL);
92
                                if (aResult == DS_OK)
93
                                {
94
                                        aResult = mPrimaryBuffer->SetFormat(&aWaveFormat);
95
                                }
96
                        }
97
                        else
98
                        {
99
                                aResult = mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
100
                        }
101
                }
102
        }      
103
}
104
 
105
DSoundManager::~DSoundManager()
106
{
107
        ReleaseChannels();
108
        ReleaseSounds();
109
 
110
        if (mPrimaryBuffer)
111
                mPrimaryBuffer->Release();
112
 
113
        if (mDirectSound != NULL)
114
        {
115
                if (mHaveFMod)
116
                        gFMod->FSOUND_Close();
117
 
118
                mDirectSound->Release();
119
 
120
                if (mHaveFMod)
121
                        FreeFModDLL();
122
        }
123
}
124
 
125
int     DSoundManager::FindFreeChannel()
126
{
127
        DWORD aTick = GetTickCount();
128
        if (aTick-mLastReleaseTick > 1000)
129
        {
130
                ReleaseFreeChannels();
131
                mLastReleaseTick = aTick;
132
        }
133
 
134
        for (int i = 0; i < MAX_CHANNELS; i++)
135
        {              
136
                if (mPlayingSounds[i] == NULL)
137
                        return i;
138
 
139
                if (mPlayingSounds[i]->IsReleased())
140
                {
141
                        delete mPlayingSounds[i];
142
                        mPlayingSounds[i] = NULL;
143
                        return i;
144
                }
145
        }
146
 
147
        return -1;
148
}
149
 
150
bool DSoundManager::Initialized()
151
{
152
/*
153
        if (mDirectSound!=NULL)
154
        {
155
                mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
156
        }
157
*/
158
 
159
        return (mDirectSound != NULL);
160
}
161
 
162
int DSoundManager::VolumeToDB(double theVolume)
163
{
164
        int aVol = (int) ((log10(1 + theVolume*9) - 1.0) * 2333);
165
        if (aVol < -2000)
166
                aVol = -10000;
167
 
168
        return aVol;
169
}
170
 
171
void DSoundManager::SetVolume(double theVolume)
172
{
173
        mMasterVolume = theVolume;
174
 
175
        for (int i = 0; i < MAX_CHANNELS; i++)
176
                if (mPlayingSounds[i] != NULL)
177
                        mPlayingSounds[i]->RehupVolume();
178
}
179
 
180
bool DSoundManager::LoadWAVSound(unsigned int theSfxID, const std::string& theFilename)
181
{              
182
        int aDataSize;
183
 
184
        PFILE* fp;
185
 
186
        fp = p_fopen(theFilename.c_str(), "rb");
187
 
188
        if (fp <= 0)
189
                return false;  
190
 
191
        char aChunkType[5];    
192
        aChunkType[4] = '\0';
193
        ulong aChunkSize;
194
 
195
        p_fread(aChunkType, 1, 4, fp); 
196
        if (!strcmp(aChunkType, "RIFF") == 0)
197
                return false;
198
        p_fread(&aChunkSize, 4, 1, fp);
199
 
200
        p_fread(aChunkType, 1, 4, fp); 
201
        if (!strcmp(aChunkType, "WAVE") == 0)
202
                return false;
203
 
204
        ushort aBitCount = 16;
205
        ushort aChannelCount = 1;
206
        ulong aSampleRate = 22050;
207
        uchar anXor = 0;
208
 
209
        while (!p_feof(fp))
210
        {
211
                p_fread(aChunkType, 1, 4, fp);         
212
                if (p_fread(&aChunkSize, 4, 1, fp) == 0)
213
                        return false;
214
 
215
                int aCurPos = p_ftell(fp);
216
 
217
                if (strcmp(aChunkType, "fmt ") == 0)
218
                {
219
                        ushort aFormatTag;
220
                        ulong aBytesPerSec;
221
                        ushort aBlockAlign;                    
222
 
223
                        p_fread(&aFormatTag, 2, 1, fp);
224
                        p_fread(&aChannelCount, 2, 1, fp);
225
                        p_fread(&aSampleRate, 4, 1, fp);
226
                        p_fread(&aBytesPerSec, 4, 1, fp);
227
                        p_fread(&aBlockAlign, 2, 1, fp);
228
                        p_fread(&aBitCount, 2, 1, fp);
229
 
230
                        if (aFormatTag != 1)
231
                                return false;
232
                }
233
                else if (strcmp(aChunkType, "dep ") == 0)
234
                {
235
                        char aStr[256];
236
                        ushort aStrLen;
237
 
238
                        p_fread(&aStrLen, 2, 1, fp);
239
                        if (aStrLen > 255)
240
                                aStrLen = 255;
241
                        p_fread(aStr, 1, aStrLen, fp);
242
                        aStr[aStrLen] = '\0';
243
 
244
                        FILETIME aSavedFileTime;
245
                        p_fread(&aSavedFileTime, sizeof(FILETIME), 1, fp);
246
 
247
                        FILETIME anActualFileTime;
248
                        memset(&anActualFileTime, 0, sizeof(FILETIME));
249
                        GetTheFileTime(aStr, &anActualFileTime);
250
 
251
                        if ((aSavedFileTime.dwHighDateTime != anActualFileTime.dwHighDateTime) ||
252
                                (aSavedFileTime.dwLowDateTime  != anActualFileTime.dwLowDateTime ))
253
                                return false;                          
254
                }
255
                else if (strcmp(aChunkType, "xor ") == 0)
256
                {                      
257
                        p_fread(&anXor, 1, 1, fp);                     
258
                }
259
                else if (strcmp(aChunkType, "data") == 0)
260
                {
261
                        aDataSize = aChunkSize;
262
 
263
                        mSourceDataSizes[theSfxID] = aChunkSize;
264
 
265
                        PCMWAVEFORMAT aWaveFormat;
266
                        DSBUFFERDESC aBufferDesc;                      
267
 
268
                        // Set up wave format structure.
269
                        memset(&aWaveFormat, 0, sizeof(PCMWAVEFORMAT));
270
                        aWaveFormat.wf.wFormatTag = WAVE_FORMAT_PCM;
271
                        aWaveFormat.wf.nChannels = aChannelCount;
272
                        aWaveFormat.wf.nSamplesPerSec = aSampleRate;
273
                        aWaveFormat.wf.nBlockAlign = aChannelCount*aBitCount/8;
274
                        aWaveFormat.wf.nAvgBytesPerSec =
275
                                aWaveFormat.wf.nSamplesPerSec * aWaveFormat.wf.nBlockAlign;
276
                        aWaveFormat.wBitsPerSample = aBitCount;
277
                        // Set up DSBUFFERDESC structure.
278
                        memset(&aBufferDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
279
                        aBufferDesc.dwSize = sizeof(DSBUFFERDESC);
280
                        //aBufferDesc.dwFlags = DSBCAPS_CTRL3D; 
281
                        aBufferDesc.dwFlags = SOUND_FLAGS; //DSBCAPS_CTRLDEFAULT;
282
 
283
                        //aBufferDesc.dwFlags = 0;
284
 
285
                        aBufferDesc.dwBufferBytes = aDataSize;                                                            
286
                        aBufferDesc.lpwfxFormat = (LPWAVEFORMATEX)&aWaveFormat;
287
 
288
                        if (mDirectSound->CreateSoundBuffer(&aBufferDesc, &mSourceSounds[theSfxID], NULL) != DS_OK)
289
                        {                              
290
                                p_fclose(fp);
291
                                return false;
292
                        }
293
 
294
 
295
                        void* lpvPtr;
296
                        DWORD dwBytes;
297
                        if (mSourceSounds[theSfxID]->Lock(0, aDataSize, &lpvPtr, &dwBytes, NULL, NULL, 0) != DS_OK)
298
                        {
299
                                p_fclose(fp);
300
                                return false;
301
                        }
302
 
303
                        int aReadSize = p_fread(lpvPtr, 1, aDataSize, fp);
304
                        p_fclose(fp);
305
 
306
                        for (int i = 0; i < aDataSize; i++)
307
                                ((uchar*) lpvPtr)[i] ^= anXor;
308
 
309
                        if (mSourceSounds[theSfxID]->Unlock(lpvPtr, dwBytes, NULL, NULL) != DS_OK)
310
                                return false;
311
 
312
                        if (aReadSize != aDataSize)
313
                                return false;
314
 
315
                        return true;
316
                }
317
 
318
                p_fseek(fp, aCurPos+aChunkSize, SEEK_SET);
319
        }
320
 
321
        return false;
322
}
323
 
324
// Load FMod sound can handle oggs and mp3s and whatever else fmod can decode
325
bool DSoundManager::LoadFModSound(unsigned int theSfxID, const std::string& theFilename)
326
{
327
        if (!mHaveFMod)
328
                return false;
329
 
330
        FSOUND_SAMPLE* aSample = gFMod->FSOUND_Sample_Load(FSOUND_FREE, theFilename.c_str(), 0, 0);
331
 
332
        if (aSample == NULL)
333
        {
334
                return false;  
335
        }
336
 
337
        int aMode = gFMod->FSOUND_Sample_GetMode(aSample);     
338
        int aFreq;
339
        gFMod->FSOUND_Sample_GetDefaults(aSample, &aFreq, NULL, NULL, NULL);
340
 
341
        PCMWAVEFORMAT aWaveFormat;
342
        DSBUFFERDESC aBufferDesc;                      
343
 
344
        // Set up wave format structure.
345
        memset(&aWaveFormat, 0, sizeof(PCMWAVEFORMAT));
346
        aWaveFormat.wf.wFormatTag = WAVE_FORMAT_PCM;
347
        aWaveFormat.wf.nChannels = ((aMode & FSOUND_MONO) != 0) ? 1 : 2;
348
        aWaveFormat.wf.nSamplesPerSec = aFreq;
349
        aWaveFormat.wBitsPerSample = ((aMode & FSOUND_8BITS) != 0) ? 8 : 16;
350
        aWaveFormat.wf.nBlockAlign = aWaveFormat.wf.nChannels*aWaveFormat.wBitsPerSample/8;
351
        aWaveFormat.wf.nAvgBytesPerSec = aWaveFormat.wf.nSamplesPerSec * aWaveFormat.wf.nBlockAlign;   
352
 
353
/*
354
        WAVEFORMATEX rigWave;
355
 
356
        rigWave.cbSize=sizeof(rigWave);
357
        rigWave.nAvgBytesPerSec=aWaveFormat.wf.nAvgBytesPerSec;
358
        rigWave.nBlockAlign=aWaveFormat.wf.nBlockAlign;
359
        rigWave.nChannels=aWaveFormat.wf.nChannels;
360
        rigWave.nSamplesPerSec=aWaveFormat.wf.nSamplesPerSec;
361
        rigWave.wBitsPerSample=aWaveFormat.wBitsPerSample;
362
        rigWave.wFormatTag=aWaveFormat.wf.wFormatTag;
363
*/
364
 
365
        // Set up DSBUFFERDESC structure.
366
 
367
        int aLenBytes = gFMod->FSOUND_Sample_GetLength(aSample) * aWaveFormat.wf.nBlockAlign;  
368
        memset(&aBufferDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
369
 
370
        mSourceDataSizes[theSfxID] = aLenBytes;
371
 
372
        //FUNK
373
        aBufferDesc.dwSize = sizeof(DSBUFFERDESC);
374
        aBufferDesc.dwFlags = SOUND_FLAGS;
375
        aBufferDesc.dwBufferBytes = aLenBytes;
376
        aBufferDesc.lpwfxFormat =(LPWAVEFORMATEX)&aWaveFormat; 
377
 
378
        if (mDirectSound->CreateSoundBuffer(&aBufferDesc, &mSourceSounds[theSfxID], NULL) != DS_OK)
379
        {
380
/*
381
char xmsg[100];
382
sprintf(xmsg,   "WAV STUFF: (%s)\n"
383
                                "nAvgBytesPerSec: %d\n"
384
                                "nBlockAlign: %d\n"
385
                                "nChannels: %d\n"
386
                                "nSamplesPerSec: %d\n"
387
                                "wBitsPerSample: %d\n"
388
                                "wFormatTag: %d\n",
389
 
390
                                theFilename.c_str(),
391
                                aWaveFormat.wf.nAvgBytesPerSec,
392
                                aWaveFormat.wf.nBlockAlign,
393
                                aWaveFormat.wf.nChannels,
394
                                aWaveFormat.wf.nSamplesPerSec,
395
                                aWaveFormat.wBitsPerSample,
396
                                aWaveFormat.wf.wFormatTag);
397
 
398
MessageBox(0,xmsg,xmsg,MB_OK);
399
 
400
HRESULT error=mDirectSound->CreateSoundBuffer(&aBufferDesc, &mSourceSounds[theSfxID], NULL);
401
switch (error)
402
{
403
case DSERR_ALLOCATED:MessageBox(0,"DSERR_ALLOCATED","Ugh",MB_OK);break;
404
case DSERR_BADFORMAT:MessageBox(0,"DSERR_BADFORMAT","Ugh",MB_OK);break;
405
case DSERR_INVALIDPARAM:MessageBox(0,"DSERR_INVALIDPARAM(XXX)","Ugh",MB_OK);break;
406
case DSERR_NOAGGREGATION:MessageBox(0,"DSERR_NOAGGREGATION","Ugh",MB_OK);break;
407
case DSERR_OUTOFMEMORY:MessageBox(0,"DSERR_OUTOFMEMORY","Ugh",MB_OK);break;
408
case DSERR_UNINITIALIZED:MessageBox(0,"DSERR_UNINITIALIZED","Ugh",MB_OK);break;
409
case DSERR_UNSUPPORTED:MessageBox(0,"DSERR_UNSUPPORTED","Ugh",MB_OK);break;
410
}
411
 
412
 
413
exit(0);
414
*/
415
                // Delete
416
                gFMod->FSOUND_Sample_Free(aSample);
417
                return false;
418
        }
419
 
420
        void* lpvPtr;
421
        DWORD dwBytes;
422
        if (mSourceSounds[theSfxID]->Lock(0, aLenBytes, &lpvPtr, &dwBytes, NULL, NULL, 0) == DS_OK)
423
        {              
424
 
425
                void* aPtr1;
426
                void* aPtr2;
427
                uint aLen1;
428
                uint aLen2;
429
 
430
                if (gFMod->FSOUND_Sample_Lock(aSample, 0, aLenBytes, &aPtr1, &aPtr2, &aLen1, &aLen2))
431
                {                      
432
                        memcpy(lpvPtr, aPtr1, aLen1);
433
 
434
                        mSourceSounds[theSfxID]->Unlock(lpvPtr, dwBytes, NULL, NULL);
435
                        gFMod->FSOUND_Sample_Unlock(aSample, aPtr1, aPtr2, aLen1, aLen2);
436
                }
437
        }
438
        else
439
        {
440
        }
441
 
442
        mSourceSounds[theSfxID]->Unlock(lpvPtr, dwBytes, NULL, 0);
443
 
444
        gFMod->FSOUND_Sample_Free(aSample);
445
 
446
        return true;
447
}
448
 
449
#ifdef USE_OGG_LIB
450
 
451
static int p_fseek64_wrap(PFILE *f,ogg_int64_t off,int whence){
452
        if(f==NULL)return(-1);
453
        return p_fseek(f,(long)off,whence);
454
}
455
 
456
int ov_pak_open(PFILE *f,OggVorbis_File *vf,char *initial,long ibytes){
457
        ov_callbacks callbacks = {
458
                (size_t (*)(void *, size_t, size_t, void *))  p_fread,
459
                (int (*)(void *, ogg_int64_t, int))             p_fseek64_wrap,
460
                (int (*)(void *))                             p_fclose,
461
                (long (*)(void *))                            p_ftell
462
        };
463
 
464
        return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
465
}
466
 
467
bool DSoundManager::LoadOGGSound(unsigned int theSfxID, const std::string& theFilename)
468
{
469
        OggVorbis_File vf;
470
        int current_section;
471
 
472
        PFILE *aFile = p_fopen(theFilename.c_str(),"rb");
473
        if (aFile==NULL)
474
                return false;
475
 
476
        if(ov_pak_open(aFile, &vf, NULL, 0) < 0)
477
        {
478
                p_fclose(aFile);
479
                return false;
480
        }
481
 
482
        vorbis_info *anInfo = ov_info(&vf,-1);
483
 
484
        PCMWAVEFORMAT aWaveFormat;
485
        DSBUFFERDESC aBufferDesc;                      
486
 
487
        // Set up wave format structure.
488
        memset(&aWaveFormat, 0, sizeof(PCMWAVEFORMAT));
489
        aWaveFormat.wf.wFormatTag = WAVE_FORMAT_PCM;
490
        aWaveFormat.wf.nChannels = anInfo->channels;
491
        aWaveFormat.wf.nSamplesPerSec = anInfo->rate;
492
        aWaveFormat.wBitsPerSample = 16;
493
        aWaveFormat.wf.nBlockAlign = aWaveFormat.wf.nChannels*aWaveFormat.wBitsPerSample/8;
494
        aWaveFormat.wf.nAvgBytesPerSec = aWaveFormat.wf.nSamplesPerSec * aWaveFormat.wf.nBlockAlign;   
495
 
496
        int aLenBytes = (int) (ov_pcm_total(&vf,-1) * aWaveFormat.wf.nBlockAlign);     
497
        memset(&aBufferDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
498
 
499
        mSourceDataSizes[theSfxID] = aLenBytes;
500
 
501
        //FUNK
502
        aBufferDesc.dwSize = sizeof(DSBUFFERDESC);
503
        aBufferDesc.dwFlags = SOUND_FLAGS;
504
        aBufferDesc.dwBufferBytes = aLenBytes;
505
        aBufferDesc.lpwfxFormat =(LPWAVEFORMATEX)&aWaveFormat; 
506
 
507
        if (mDirectSound->CreateSoundBuffer(&aBufferDesc, &mSourceSounds[theSfxID], NULL) != DS_OK)
508
        {
509
                ov_clear(&vf);
510
                return false;
511
        }
512
 
513
        char* aBuf;
514
        DWORD dwBytes;
515
        if (mSourceSounds[theSfxID]->Lock(0, aLenBytes, (LPVOID*)&aBuf, &dwBytes, NULL, NULL, 0) != DS_OK)
516
        {
517
                ov_clear(&vf);
518
                return false;
519
        }
520
 
521
        char *aPtr = aBuf;
522
        int aNumBytes = dwBytes;
523
        while(aNumBytes > 0)
524
        {              
525
                long ret=ov_read(&vf,aPtr,aNumBytes,&current_section);
526
                if (ret == 0)
527
                        break;
528
                else if (ret < 0)
529
                        break;
530
                else
531
                {
532
                        aPtr += ret;
533
                        aNumBytes -= ret;
534
                }
535
        }
536
 
537
        mSourceSounds[theSfxID]->Unlock(aBuf, dwBytes, NULL, 0);
538
        ov_clear(&vf);
539
        return aNumBytes==0;  
540
}
541
#else
542
bool DSoundManager::LoadOGGSound(unsigned int theSfxID, const std::string& theFilename)
543
{
544
        return false;
545
}
546
#endif
547
 
548
 
549
bool DSoundManager::LoadAUSound(unsigned int theSfxID, const std::string& theFilename)
550
{
551
        PFILE* fp;
552
 
553
        fp = p_fopen(theFilename.c_str(), "rb");       
554
 
555
        if (fp <= 0)
556
                return false;  
557
 
558
        char aHeaderId[5];     
559
        aHeaderId[4] = '\0';   
560
        p_fread(aHeaderId, 1, 4, fp);  
561
        if (!strcmp(aHeaderId, ".snd") == 0)
562
                return false;
563
 
564
        ulong aHeaderSize;     
565
        p_fread(&aHeaderSize, 4, 1, fp);
566
        aHeaderSize = LONG_BIGE_TO_NATIVE(aHeaderSize);
567
 
568
        ulong aDataSize;
569
        p_fread(&aDataSize, 4, 1, fp);
570
        aDataSize = LONG_BIGE_TO_NATIVE(aDataSize);
571
 
572
        ulong anEncoding;
573
        p_fread(&anEncoding, 4, 1, fp);
574
        anEncoding = LONG_BIGE_TO_NATIVE(anEncoding);
575
 
576
        ulong aSampleRate;
577
        p_fread(&aSampleRate, 4, 1, fp);
578
        aSampleRate = LONG_BIGE_TO_NATIVE(aSampleRate);
579
 
580
        ulong aChannelCount;
581
        p_fread(&aChannelCount, 4, 1, fp);
582
        aChannelCount = LONG_BIGE_TO_NATIVE(aChannelCount);
583
 
584
        p_fseek(fp, aHeaderSize, SEEK_SET);    
585
 
586
        bool ulaw = false;
587
 
588
        ulong aSrcBitCount = 8;
589
        ulong aBitCount = 16;                  
590
        switch (anEncoding)
591
        {
592
        case 1:
593
                aSrcBitCount = 8;
594
                aBitCount = 16;
595
                ulaw = true;
596
                break;
597
        case 2:
598
                aSrcBitCount = 8;
599
                aBitCount = 8;
600
                break;
601
 
602
        /*
603
        Support these formats?
604
 
605
        case 3:
606
                aBitCount = 16;
607
                break;
608
        case 4:
609
                aBitCount = 24;
610
                break;
611
        case 5:
612
                aBitCount = 32;
613
                break;*/
614
 
615
        default:
616
                return false;          
617
        }
618
 
619
 
620
        ulong aDestSize = aDataSize * aBitCount/aSrcBitCount;
621
        mSourceDataSizes[theSfxID] = aDestSize;
622
 
623
        PCMWAVEFORMAT aWaveFormat;
624
        DSBUFFERDESC aBufferDesc;                      
625
 
626
        // Set up wave format structure.
627
        memset(&aWaveFormat, 0, sizeof(PCMWAVEFORMAT));
628
        aWaveFormat.wf.wFormatTag = WAVE_FORMAT_PCM;
629
        aWaveFormat.wf.nChannels = (WORD) aChannelCount;
630
        aWaveFormat.wf.nSamplesPerSec = aSampleRate;
631
        aWaveFormat.wf.nBlockAlign = (WORD) (aChannelCount*aBitCount/8);
632
        aWaveFormat.wf.nAvgBytesPerSec =
633
                aWaveFormat.wf.nSamplesPerSec * aWaveFormat.wf.nBlockAlign;
634
        aWaveFormat.wBitsPerSample = (WORD) aBitCount;
635
        // Set up DSBUFFERDESC structure.
636
        memset(&aBufferDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
637
        aBufferDesc.dwSize = sizeof(DSBUFFERDESC);
638
        //aBufferDesc.dwFlags = DSBCAPS_CTRL3D; 
639
        aBufferDesc.dwFlags = SOUND_FLAGS;
640
        aBufferDesc.dwBufferBytes = aDestSize;
641
        aBufferDesc.lpwfxFormat = (LPWAVEFORMATEX)&aWaveFormat;
642
 
643
        if (mDirectSound->CreateSoundBuffer(&aBufferDesc, &mSourceSounds[theSfxID], NULL) != DS_OK)
644
        {
645
                p_fclose(fp);
646
                return false;
647
        }              
648
 
649
        void* lpvPtr;
650
        DWORD dwBytes;
651
        if (mSourceSounds[theSfxID]->Lock(0, aDestSize, &lpvPtr, &dwBytes, NULL, NULL, 0) != DS_OK)
652
        {
653
                p_fclose(fp);
654
                return false;
655
        }
656
 
657
        uchar* aSrcBuffer = new uchar[aDataSize];
658
 
659
        int aReadSize = p_fread(aSrcBuffer, 1, aDataSize, fp);
660
        p_fclose(fp);
661
 
662
        if (ulaw)
663
        {
664
                short* aDestBuffer = (short*) lpvPtr;
665
 
666
                for (ulong i = 0; i < aDataSize; i++)
667
                {
668
                        int ch = aSrcBuffer[i];
669
 
670
                        int sign = (ch < 128) ? -1 : 1;
671
                        ch = ch | 0x80;
672
                        if (ch > 239)
673
                                ch = ((0xF0 | 15) - ch) * 2;
674
                        else if (ch > 223)
675
                                ch = (((0xE0 | 15) - ch) * 4) + 32;
676
                        else if (ch > 207)
677
                                ch = (((0xD0 | 15) - ch) * 8) + 96;
678
                        else if (ch > 191)
679
                                ch = (((0xC0 | 15) - ch) * 16) + 224;
680
                        else if (ch > 175)
681
                                ch = (((0xB0 | 15) - ch) * 32) + 480;
682
                        else if (ch > 159)
683
                                ch = (((0xA0 | 15) - ch) * 64) + 992;
684
                        else if (ch > 143)
685
                                ch = (((0x90 | 15) - ch) * 128) + 2016;
686
                        else if (ch > 128)
687
                                ch = (((0x80 | 15) - ch) * 256) + 4064;
688
                        else
689
                                ch = 0xff;                     
690
 
691
                        aDestBuffer[i] = sign * ch * 4;
692
                }              
693
        }
694
        else
695
                memcpy(lpvPtr, aSrcBuffer, aDataSize); 
696
 
697
        delete [] aSrcBuffer;          
698
 
699
        if (mSourceSounds[theSfxID]->Unlock(lpvPtr, dwBytes, NULL, NULL) != DS_OK)
700
                return false;
701
 
702
        if (aReadSize != aDataSize)
703
                return false;
704
 
705
        return true;
706
}
707
 
708
bool DSoundManager::LoadSound(unsigned int theSfxID, const std::string& theFilename)
709
{
710
        if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS))
711
                return false;
712
 
713
        ReleaseSound(theSfxID);
714
 
715
        if (!mDirectSound)
716
                return true; // sounds just     won't play, but this is not treated as a failure condition
717
 
718
        mSourceFileNames[theSfxID] = theFilename;
719
 
720
        std::string aFilename = theFilename;
721
        std::string aCachedName;
722
 
723
        if ((aFilename.length() > 2) && (aFilename[0] != '\\') && (aFilename[0] != '/') &&
724
                (aFilename[1] != ':'))
725
        {
726
                // Not an absolute path
727
                aCachedName = GetAppDataFolder() + "cached\\" + aFilename + ".wav";
728
                if (LoadWAVSound(theSfxID, aCachedName))
729
                        return true;
730
                MkDir(GetFileDir(aCachedName));
731
        }              
732
 
733
        if (LoadWAVSound(theSfxID, aFilename + ".wav"))
734
                return true;
735
 
736
        if (mHaveFMod)
737
        {
738
                if (LoadFModSound(theSfxID, aFilename + ".mp3"))
739
                {
740
                        WriteWAV(theSfxID, aCachedName, aFilename + ".mp3");
741
                        return true;
742
                }
743
#ifndef USE_OGG_LIB
744
                if (LoadFModSound(theSfxID, aFilename + ".ogg"))
745
                {              
746
                        WriteWAV(theSfxID, aCachedName, aFilename + ".ogg");
747
                        return true;
748
                }
749
#endif
750
        }
751
 
752
#ifdef USE_OGG_LIB
753
        if (LoadOGGSound(theSfxID, aFilename + ".ogg"))
754
        {              
755
                WriteWAV(theSfxID, aCachedName, aFilename + ".ogg");
756
                return true;
757
        }
758
#endif
759
 
760
        if (LoadAUSound(theSfxID, aFilename + ".au"))
761
        {
762
                WriteWAV(theSfxID, aCachedName, aFilename + ".au");
763
                return true;
764
        }
765
 
766
        return false;
767
}
768
 
769
int DSoundManager::LoadSound(const std::string& theFilename)
770
{
771
        int i;
772
        for (i = 0; i < MAX_SOURCE_SOUNDS; i++)
773
                if (mSourceFileNames[i] == theFilename)
774
                        return i;
775
 
776
        for (i = MAX_SOURCE_SOUNDS-1; i >= 0; i--)
777
        {              
778
                if (mSourceSounds[i] == NULL)
779
                {
780
                        if (!LoadSound(i, theFilename))
781
                                return -1;
782
                        else
783
                                return i;
784
                }
785
        }      
786
 
787
        return -1;
788
}
789
 
790
void DSoundManager::ReleaseSound(unsigned int theSfxID)
791
{
792
        if (mSourceSounds[theSfxID] != NULL)
793
        {
794
                mSourceSounds[theSfxID]->Release();
795
                mSourceSounds[theSfxID] = NULL;
796
                mSourceFileNames[theSfxID] = "";
797
        }
798
}
799
 
800
int DSoundManager::GetFreeSoundId()
801
{
802
        for (int i=0; i<MAX_SOURCE_SOUNDS; i++)
803
        {
804
                if (mSourceSounds[i]==NULL)
805
                        return i;
806
        }
807
 
808
        return -1;
809
}
810
 
811
int DSoundManager::GetNumSounds()
812
{
813
        int aCount = 0;
814
        for (int i=0; i<MAX_SOURCE_SOUNDS; i++)
815
        {
816
                if (mSourceSounds[i]!=NULL)
817
                        aCount++;
818
        }
819
 
820
        return aCount;
821
}
822
 
823
bool DSoundManager::SetBaseVolume(unsigned int theSfxID, double theBaseVolume)
824
{
825
        if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS))
826
                return false;
827
 
828
        mBaseVolumes[theSfxID] = theBaseVolume;
829
        return true;
830
}
831
 
832
bool DSoundManager::SetBasePan(unsigned int theSfxID, int theBasePan)
833
{
834
        if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS))
835
                return false;
836
 
837
        mBasePans[theSfxID] = theBasePan;
838
        return true;
839
}
840
 
841
bool DSoundManager::GetTheFileTime(const std::string& theDepFile, FILETIME* theFileTime)
842
{      
843
        memset(theFileTime, 0, sizeof(FILETIME));
844
        HANDLE aDepFileHandle = CreateFile(theDepFile.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
845
        if (aDepFileHandle == INVALID_HANDLE_VALUE)
846
                return false;
847
 
848
        GetFileTime(aDepFileHandle, NULL, NULL, theFileTime);  
849
        CloseHandle(aDepFileHandle);
850
        return true;
851
}
852
 
853
bool DSoundManager::WriteWAV(unsigned int theSfxID, const std::string& theFilename, const std::string& theDepFile)
854
{
855
        if ((theFilename.length() == 0) || (theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS))
856
                return false;
857
 
858
        ulong aDataSize = mSourceDataSizes[theSfxID];
859
 
860
        void* lpvPtr;
861
        DWORD dwBytes;
862
        if (mSourceSounds[theSfxID]->Lock(0, aDataSize, &lpvPtr, &dwBytes, NULL, NULL, 0) != DS_OK)
863
                return false;
864
 
865
        FILE* fp;
866
        fp = fopen(theFilename.c_str(), "wb");
867
 
868
        if (fp <= 0)
869
        {
870
                mSourceSounds[theSfxID]->Unlock(lpvPtr, dwBytes, NULL, NULL);
871
                return false;
872
        }      
873
 
874
        char aChunkType[5];    
875
        aChunkType[4] = '\0';
876
        ulong aChunkSize = 4 + 8 + 16 + 8 + aDataSize;
877
 
878
        fwrite("RIFF", 1, 4, fp);      
879
        fwrite(&aChunkSize, 4, 1, fp);
880
        fwrite("WAVE", 1, 4, fp);
881
 
882
        ulong aBufferSize;
883
        mSourceSounds[theSfxID]->GetFormat(NULL, 0, &aBufferSize);
884
 
885
        WAVEFORMATEX* aWaveFormat = (WAVEFORMATEX*) new char[aBufferSize];
886
        memset(aWaveFormat, 0, sizeof(WAVEFORMATEX));  
887
        mSourceSounds[theSfxID]->GetFormat(aWaveFormat, aBufferSize, NULL);
888
 
889
        ushort aFormatTag = 1;
890
        ushort aChannelCount = aWaveFormat->nChannels;
891
        ulong aSampleRate = aWaveFormat->nSamplesPerSec;       
892
        ushort aBitCount = aWaveFormat->wBitsPerSample;
893
        ushort aBlockAlign = (aBitCount * aChannelCount) / 8;
894
        ulong aBytesPerSec = aSampleRate * aBlockAlign;
895
 
896
        delete aWaveFormat;
897
 
898
        aChunkSize = 16;
899
        fwrite("fmt ", 1, 4, fp);
900
        fwrite(&aChunkSize, 1, 4, fp);
901
        fwrite(&aFormatTag, 2, 1, fp);
902
        fwrite(&aChannelCount, 2, 1, fp);
903
        fwrite(&aSampleRate, 4, 1, fp);
904
        fwrite(&aBytesPerSec, 4, 1, fp);
905
        fwrite(&aBlockAlign, 2, 1, fp);
906
        fwrite(&aBitCount, 2, 1, fp);
907
 
908
        FILETIME aFileTime;
909
        memset(&aFileTime, 0, sizeof(FILETIME));
910
        GetTheFileTime(theDepFile, &aFileTime);
911
 
912
        ushort aStrLen = theDepFile.length();
913
        aChunkSize = 2 + aStrLen + sizeof(FILETIME);
914
        fwrite("dep ", 1, 4, fp);
915
        fwrite(&aChunkSize,4, 1, fp);
916
        fwrite(&aStrLen, 2, 1, fp);
917
        fwrite(theDepFile.c_str(), 1, aStrLen, fp);
918
        fwrite(&aFileTime, sizeof(FILETIME), 1, fp);
919
 
920
        aChunkSize = 1;
921
        uchar anXor = 0xF7;
922
        fwrite("xor ", 1, 4, fp);
923
        fwrite(&aChunkSize, 4, 1, fp);
924
        fwrite(&anXor, 1, 1, fp);      
925
 
926
        for (DWORD i = 0; i < dwBytes; i++)
927
                ((uchar*) lpvPtr)[i] ^= anXor;
928
 
929
        fwrite("data", 1, 4, fp);
930
        fwrite(&aDataSize, 4, 1, fp);
931
        fwrite(lpvPtr, 1, aDataSize, fp);
932
        fclose(fp);
933
 
934
        for (DWORD i = 0; i < dwBytes; i++)
935
                ((uchar*) lpvPtr)[i] ^= anXor;
936
 
937
        if (mSourceSounds[theSfxID]->Unlock(lpvPtr, dwBytes, NULL, NULL) != DS_OK)
938
                return false;
939
 
940
        return true;
941
}
942
 
943
SoundInstance* DSoundManager::GetSoundInstance(unsigned int theSfxID)
944
{
945
        if (theSfxID > MAX_SOURCE_SOUNDS)
946
                return NULL;
947
 
948
        int aFreeChannel = FindFreeChannel();
949
        if (aFreeChannel < 0)
950
                return NULL;
951
 
952
        if (mDirectSound==NULL)
953
        {
954
                mPlayingSounds[aFreeChannel] = new DSoundInstance(this, NULL);
955
        }
956
        else
957
        {
958
                if (mSourceSounds[theSfxID] == NULL)
959
                        return NULL;
960
 
961
                mPlayingSounds[aFreeChannel] = new DSoundInstance(this, mSourceSounds[theSfxID]);
962
        }
963
 
964
        mPlayingSounds[aFreeChannel]->SetBasePan(mBasePans[theSfxID]);
965
        mPlayingSounds[aFreeChannel]->SetBaseVolume(mBaseVolumes[theSfxID]);
966
 
967
        return mPlayingSounds[aFreeChannel];
968
}
969
 
970
void DSoundManager::ReleaseSounds()
971
{
972
        for (int i = 0; i < MAX_SOURCE_SOUNDS; i++)
973
                if (mSourceSounds[i] != NULL)
974
                {
975
                        mSourceSounds[i]->Release();
976
                        mSourceSounds[i] = NULL;
977
                }
978
}
979
 
980
void DSoundManager::ReleaseChannels()
981
{
982
        for (int i = 0; i < MAX_CHANNELS; i++)
983
                if (mPlayingSounds[i] != NULL)
984
                {
985
                        delete mPlayingSounds[i];
986
                        mPlayingSounds[i] = NULL;
987
                }
988
}
989
 
990
void DSoundManager::ReleaseFreeChannels()
991
{
992
        for (int i = 0; i < MAX_CHANNELS; i++)
993
                if (mPlayingSounds[i] != NULL && mPlayingSounds[i]->IsReleased())
994
                {
995
                        delete mPlayingSounds[i];
996
                        mPlayingSounds[i] = NULL;
997
                }
998
}
999
 
1000
void DSoundManager::StopAllSounds()
1001
{
1002
        for (int i = 0; i < MAX_CHANNELS; i++)
1003
                if (mPlayingSounds[i] != NULL)
1004
                {
1005
                        bool isAutoRelease = mPlayingSounds[i]->mAutoRelease;
1006
                        mPlayingSounds[i]->Stop();
1007
                        mPlayingSounds[i]->mAutoRelease = isAutoRelease;
1008
                }
1009
}
1010
 
1011
 
1012
double DSoundManager::GetMasterVolume()
1013
{
1014
        MIXERCONTROLDETAILS mcd;
1015
        MIXERCONTROLDETAILS_UNSIGNED mxcd_u;
1016
        MIXERLINECONTROLS mxlc;
1017
        MIXERCONTROL mlct;
1018
        MIXERLINE mixerLine;
1019
        HMIXER hmx;
1020
        MIXERCAPS pmxcaps;     
1021
 
1022
        mixerOpen((HMIXER*) &hmx, 0, 0, 0, MIXER_OBJECTF_MIXER);
1023
        mixerGetDevCaps(0, &pmxcaps, sizeof(pmxcaps));
1024
 
1025
        mxlc.cbStruct = sizeof(mxlc);  
1026
        mxlc.cbmxctrl = sizeof(mlct);
1027
        mxlc.pamxctrl = &mlct;
1028
        mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1029
        mixerLine.cbStruct = sizeof(mixerLine);
1030
        mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
1031
        mixerGetLineInfo((HMIXEROBJ) hmx, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE);
1032
        mxlc.dwLineID = mixerLine.dwLineID;
1033
        mixerGetLineControls((HMIXEROBJ) hmx, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
1034
 
1035
        mcd.cbStruct = sizeof(mcd);
1036
        mcd.dwControlID = mlct.dwControlID;
1037
        mcd.cChannels = 1;
1038
        mcd.cMultipleItems = 0;
1039
        mcd.cbDetails = sizeof(mxcd_u);
1040
        mcd.paDetails = &mxcd_u;
1041
 
1042
        mixerGetControlDetails((HMIXEROBJ) hmx, &mcd, 0L);     
1043
 
1044
        mixerClose(hmx);
1045
 
1046
        return mxcd_u.dwValue / (double) 0xFFFF;
1047
}
1048
 
1049
void DSoundManager::SetMasterVolume(double theVolume)
1050
{
1051
        MIXERCONTROLDETAILS mcd;
1052
        MIXERCONTROLDETAILS_UNSIGNED mxcd_u;
1053
        MIXERLINECONTROLS mxlc;
1054
        MIXERCONTROL mlct;
1055
        MIXERLINE mixerLine;
1056
        HMIXER hmx;
1057
        MIXERCAPS pmxcaps;     
1058
 
1059
        mixerOpen((HMIXER*) &hmx, 0, 0, 0, MIXER_OBJECTF_MIXER);
1060
        mixerGetDevCaps(0, &pmxcaps, sizeof(pmxcaps));
1061
 
1062
        mxlc.cbStruct = sizeof(mxlc);  
1063
        mxlc.cbmxctrl = sizeof(mlct);
1064
        mxlc.pamxctrl = &mlct;
1065
        mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
1066
        mixerLine.cbStruct = sizeof(mixerLine);
1067
        mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
1068
        mixerGetLineInfo((HMIXEROBJ) hmx, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE);
1069
        mxlc.dwLineID = mixerLine.dwLineID;
1070
        mixerGetLineControls((HMIXEROBJ) hmx, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
1071
 
1072
        mcd.cbStruct = sizeof(mcd);
1073
        mcd.dwControlID = mlct.dwControlID;
1074
        mcd.cChannels = 1;
1075
        mcd.cMultipleItems = 0;
1076
        mcd.cbDetails = sizeof(mxcd_u);
1077
        mcd.paDetails = &mxcd_u;
1078
 
1079
        mxcd_u.dwValue = (int) (0xFFFF * theVolume);
1080
        mixerSetControlDetails((HMIXEROBJ) hmx, &mcd, 0L);
1081
 
1082
        mixerClose(hmx);
1083
}
1084
 
1085
void DSoundManager::Flush()
1086
{
1087
}
1088
 
1089
void DSoundManager::SetCooperativeWindow(HWND theHWnd, bool isWindowed)
1090
{
1091
        if (mDirectSound != NULL)
1092
                mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
1093
/*
1094
        if (isWindowed==true) mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
1095
        else mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_EXCLUSIVE);
1096
        */
1097
}
1098
#undef SOUND_FLAGS