+++ /dev/null
-/****************************************************************************************/\r
-/* Sound.c */\r
-/* */\r
-/* Author: Brian Adelberg */\r
-/* Description: DirectSound wrapper */\r
-/* */\r
-/* The contents of this file are subject to the Genesis3D Public License */\r
-/* Version 1.01 (the "License"); you may not use this file except in */\r
-/* compliance with the License. You may obtain a copy of the License at */\r
-/* http://www.genesis3d.com */\r
-/* */\r
-/* Software distributed under the License is distributed on an "AS IS" */\r
-/* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See */\r
-/* the License for the specific language governing rights and limitations */\r
-/* under the License. */\r
-/* */\r
-/* The Original Code is Genesis3D, released March 25, 1999. */\r
-/* Copyright (C) 1996-1999 Eclipse Entertainment, L.L.C. All Rights Reserved */\r
-/* */\r
-/****************************************************************************************/\r
-#include <windows.h>\r
-#include <dsound.h>\r
-#include <stdio.h>\r
-#include <assert.h>\r
-\r
-#include "BaseType.h"\r
-#include "ErrorLog.h"\r
-#include "VFile.h"\r
-#include "Sound.h"\r
-#include "Ram.h"\r
-\r
-typedef struct SoundManager SoundManager;\r
-typedef struct Channel Channel;\r
-\r
-\r
-typedef struct geSound_System\r
-{\r
- geBoolean Active;\r
- SoundManager *SoundM;\r
- geFloat GlobalVolume;\r
-} geSound_System;\r
-\r
-typedef struct geSound_Cfg\r
-{\r
- geFloat Volume;\r
- geFloat Pan;\r
- geFloat Frequency;\r
-} geSound_Cfg;\r
-\r
-\r
-/*\r
- The interfaces here allow an application to write sound data to\r
- abstract channels which are then to be mixed. The interfaces here\r
- require two things. First, that the application create only one\r
- sound manager per instance, and second that the type of sound data\r
- being passed into the sound channels remains constant. That is,\r
- the format of the binary information is all one format from\r
- one sound to another; the application cannot combine RIFF and WAV\r
- formats in a single channel.\r
-*/\r
-/*\r
- Call these ones only once per application:\r
-*/\r
-\r
-static SoundManager * CreateSoundManager(HWND hWnd);\r
-static void DestroySoundManager(SoundManager *sm);\r
-\r
-//static BOOL FillSoundChannel(SoundManager *sm, char* Dir, char *Name, unsigned int* Handle );\r
-static BOOL FillSoundChannel(SoundManager *sm, geVFile *File, unsigned int* Handle );\r
-//static BOOL FillSoundChannelMemory(SoundManager *sm, const void *Buffer, unsigned int* Handle );\r
-static BOOL StartSoundChannel( SoundManager *sm, unsigned int Handle, geSound_Cfg *cfg, int loop, unsigned int* sfx);\r
-static BOOL StopSoundChannel(Channel *channel);\r
-static BOOL FreeAllChannels(SoundManager *sm);\r
-static BOOL FreeChannel(SoundManager *sm, Channel *channel);\r
-static BOOL ModifyChannel( Channel *channel, geSound_Cfg *cfg );\r
-static int ChannelPlaying( Channel *channel );\r
-static Channel* GetChannel( SoundManager *sm, unsigned int ID );\r
-\r
-\r
-typedef struct Channel\r
-{\r
-// char* name;\r
- LPDIRECTSOUNDBUFFER buffer;\r
- unsigned int ID;\r
- int BaseFreq;\r
- geSound_Cfg cfg;\r
- void * Data;\r
- struct Channel *next;\r
- struct Channel *nextDup;\r
-} Channel;\r
-\r
-typedef struct SoundManager\r
-{\r
- int smChannelCount;\r
- unsigned int smNextChannelID;\r
-\r
- LPDIRECTSOUNDBUFFER smPrimaryChannel;\r
- Channel* smChannels;\r
- //LPDIRECTSOUNDNOTIFY * smNotify;\r
-} SoundManager;\r
-\r
-static LPDIRECTSOUND lpDirectSound = NULL;\r
-// This isn't really safe as a global. But it's consistent with the global lpDirectSound.\r
-static HMODULE hmodDirectSound = NULL;\r
-\r
-// Added 11/08/1999 Ed Averill to expose DSound object for external code\r
-GENESISAPI void *geSound_GetDSound()\r
-{\r
- return (void *)lpDirectSound;\r
-}\r
-// End 11/08/1999 addition\r
-\r
-//=====================================================================================\r
-// geSound_SystemCreate\r
-//=====================================================================================\r
-GENESISAPI geSound_System *geSound_CreateSoundSystem(HWND hWnd)\r
-{\r
- geSound_System *SoundSystem;\r
-\r
- SoundSystem = GE_RAM_ALLOCATE_STRUCT(geSound_System);\r
-\r
- if (!SoundSystem)\r
- {\r
- geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL);\r
- return NULL;\r
- }\r
-\r
- memset(SoundSystem, 0, sizeof(geSound_System));\r
- \r
- // Initialize the sound system\r
- SoundSystem->SoundM = CreateSoundManager(hWnd);\r
-\r
- if (!SoundSystem->SoundM)\r
- {\r
- geRam_Free(SoundSystem);\r
- geErrorLog_Add(GE_ERR_CREATE_SOUND_MANAGER_FAILED, NULL);\r
- return NULL;\r
- }\r
- SoundSystem->GlobalVolume = 1.0f;\r
-\r
- return SoundSystem;\r
-}\r
-\r
-//=====================================================================================\r
-// geSound_SystemFree\r
-//=====================================================================================\r
-GENESISAPI void geSound_DestroySoundSystem(geSound_System *Sound)\r
-{\r
- assert(Sound != NULL);\r
-\r
- // Shutdown the sound system\r
- DestroySoundManager(Sound->SoundM);\r
-\r
- Sound->SoundM = NULL;\r
-\r
- geRam_Free(Sound);\r
-}\r
-\r
-//=====================================================================================\r
-// Sound_LoadSound\r
-//=====================================================================================\r
-//GENESISAPI geSound_Def *geSound_LoadSoundDef(geSound_System *SoundS, const char *Path, const char *FileName)\r
-GENESISAPI geSound_Def *geSound_LoadSoundDef(geSound_System *SoundS, geVFile *File)\r
-{\r
- unsigned int SoundDef = 0;\r
-\r
- assert(SoundS != NULL);\r
-\r
-// if (!FillSoundChannel(SoundS->SoundM, (char*)Path, (char*)FileName, &SoundDef))\r
- if (!FillSoundChannel(SoundS->SoundM, File, &SoundDef))\r
- return 0;\r
- \r
- return (geSound_Def *)SoundDef;\r
-}\r
-\r
-#if 0\r
-//=====================================================================================\r
-// Sound_LoadSound\r
-//=====================================================================================\r
-GENESISAPI geSound_Def *geSound_LoadSoundDefFromMemory(\r
- geSound_System *SoundS,\r
- const void *Buffer)\r
-{\r
- unsigned int SoundDef = 0;\r
-\r
- assert(SoundS != NULL);\r
- assert(Buffer != NULL);\r
-\r
- if (!FillSoundChannelMemory(SoundS->SoundM, Buffer, &SoundDef))\r
- return 0;\r
- \r
- return (geSound_Def *)SoundDef;\r
-}\r
-#endif\r
-\r
-//=====================================================================================\r
-// Sound_FreeSound\r
-//=====================================================================================\r
-GENESISAPI void geSound_FreeSoundDef(geSound_System *SoundS, geSound_Def *SoundDef)\r
-{\r
- Channel* Channel;\r
-\r
- assert(SoundS != NULL);\r
- assert(SoundDef != 0);\r
-\r
- Channel = GetChannel(SoundS->SoundM, (unsigned int)SoundDef);\r
-\r
- if (!Channel)\r
- return;\r
-\r
- FreeChannel(SoundS->SoundM, Channel);\r
-}\r
-\r
-//=====================================================================================\r
-// Sound_SetGlobalVolume\r
-//=====================================================================================\r
-GENESISAPI geBoolean geSound_SetMasterVolume( geSound_System *SoundS, geFloat Volume )\r
-{\r
- if( !SoundS )\r
- return( GE_FALSE );\r
- SoundS->GlobalVolume = Volume;\r
- return( GE_TRUE );\r
-}\r
- \r
-//=====================================================================================\r
-// Sound_PlaySound\r
-//=====================================================================================\r
-GENESISAPI geSound *geSound_PlaySoundDef(geSound_System *SoundS, \r
- geSound_Def *SoundDef, \r
- geFloat Volume, \r
- geFloat Pan, \r
- geFloat Frequency, \r
- geBoolean Loop)\r
-{\r
- unsigned int Sound;\r
- geSound_Cfg LocalCfg;\r
-\r
- LocalCfg.Volume = Volume;\r
- LocalCfg.Pan = Pan;\r
- LocalCfg.Frequency = Frequency;\r
-\r
- LocalCfg.Volume *= SoundS->GlobalVolume;\r
- if (!StartSoundChannel(SoundS->SoundM, (unsigned int)SoundDef, &LocalCfg, (BOOL)Loop, &Sound))\r
- {\r
- return 0;\r
- }\r
-\r
- return (geSound *)Sound;\r
-}\r
- \r
-//=====================================================================================\r
-// Sound_StopSound\r
-//=====================================================================================\r
-GENESISAPI geBoolean geSound_StopSound(geSound_System *SoundS, geSound *Sound)\r
-{\r
- Channel* Channel;\r
-\r
- assert(SoundS != NULL);\r
- assert(Sound != NULL); \r
-\r
- Channel = GetChannel(SoundS->SoundM, (unsigned int)Sound);\r
-\r
- if (!Channel)\r
- return GE_FALSE;\r
-\r
- return StopSoundChannel(Channel); \r
-}\r
-\r
-//=====================================================================================\r
-// Sound_ModifySound\r
-//=====================================================================================\r
-GENESISAPI geBoolean geSound_ModifySound(geSound_System *SoundS, \r
- geSound *Sound,geFloat Volume, \r
- geFloat Pan, \r
- geFloat Frequency)\r
-{\r
- Channel* Channel;\r
- geSound_Cfg LocalCfg;\r
-\r
- assert(SoundS != NULL);\r
- assert(Sound != NULL); \r
-\r
- Channel = GetChannel(SoundS->SoundM, (unsigned int)Sound);\r
-\r
- if (!Channel)\r
- return GE_FALSE;\r
- LocalCfg.Volume = Volume;\r
- LocalCfg.Pan = Pan;\r
- LocalCfg.Frequency = Frequency;\r
- LocalCfg.Volume *= SoundS->GlobalVolume;\r
- return ModifyChannel(Channel, &LocalCfg);\r
-}\r
-\r
-//=====================================================================================\r
-// Sound_SoundIsPlaying\r
-//=====================================================================================\r
-GENESISAPI geBoolean geSound_SoundIsPlaying(geSound_System *SoundS, geSound *Sound)\r
-{\r
- Channel* Channel;\r
-\r
- assert(SoundS != NULL);\r
- assert(Sound != NULL); \r
-\r
- Channel = GetChannel(SoundS->SoundM, (unsigned int)Sound);\r
-\r
- if (!Channel)\r
- return GE_FALSE;\r
-\r
- return ChannelPlaying(Channel);\r
-}\r
-\r
-\r
-//=====================================================================================\r
-//=====================================================================================\r
-\r
-static BOOL DSParseWaveResource(const void *pvRes, WAVEFORMATEX **ppWaveHeader,\r
- BYTE **ppbWaveData,DWORD *pcbWaveSize)\r
-{\r
- DWORD *pdw;\r
- DWORD *pdwEnd;\r
- DWORD dwRiff;\r
- DWORD dwType;\r
- DWORD dwLength;\r
-\r
- if (ppWaveHeader)\r
- *ppWaveHeader = NULL;\r
-\r
- if (ppbWaveData)\r
- *ppbWaveData = NULL;\r
-\r
- if (pcbWaveSize)\r
- *pcbWaveSize = 0;\r
-\r
- pdw = (DWORD *)pvRes;\r
- dwRiff = *pdw++;\r
- dwLength = *pdw++;\r
- dwType = *pdw++;\r
-\r
- if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))\r
- goto exit; // not even RIFF\r
-\r
- if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))\r
- goto exit; // not a WAV\r
-\r
- pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);\r
-\r
- while (pdw < pdwEnd)\r
- {\r
- dwType = *pdw++;\r
- dwLength = *pdw++;\r
-\r
- switch (dwType)\r
- {\r
- case mmioFOURCC('f', 'm', 't', ' '):\r
- if (ppWaveHeader && !*ppWaveHeader)\r
- {\r
- if (dwLength < sizeof(WAVEFORMAT))\r
- goto exit; // not a WAV\r
-\r
- *ppWaveHeader = (WAVEFORMATEX *)pdw;\r
-\r
- if ((!ppbWaveData || *ppbWaveData) &&\r
- (!pcbWaveSize || *pcbWaveSize))\r
- {\r
- return TRUE;\r
- }\r
- }\r
- break;\r
-\r
- case mmioFOURCC('d', 'a', 't', 'a'):\r
- if ((ppbWaveData && !*ppbWaveData) ||\r
- (pcbWaveSize && !*pcbWaveSize))\r
- {\r
- if (ppbWaveData)\r
- *ppbWaveData = (LPBYTE)pdw;\r
-\r
- if (pcbWaveSize)\r
- *pcbWaveSize = dwLength;\r
-\r
- if (!ppWaveHeader || *ppWaveHeader)\r
- return TRUE;\r
- }\r
- break;\r
- }\r
-\r
- pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));\r
- }\r
-\r
-exit:\r
- return FALSE;\r
-}\r
-\r
-static BOOL DSFillSoundBuffer(IDirectSoundBuffer *pDSB, BYTE *pbWaveData, DWORD cbWaveSize)\r
-{\r
-\r
- if (pDSB && pbWaveData && cbWaveSize)\r
- {\r
- LPVOID pMem1, pMem2;\r
- DWORD dwSize1, dwSize2;\r
-\r
- if (SUCCEEDED(IDirectSoundBuffer_Lock(pDSB, 0, cbWaveSize,\r
- &pMem1, &dwSize1, &pMem2, &dwSize2, 0)))\r
- {\r
- ZeroMemory(pMem1, dwSize1);\r
- CopyMemory(pMem1, pbWaveData, dwSize1);\r
-\r
- if ( 0 != dwSize2 )\r
- CopyMemory(pMem2, pbWaveData+dwSize1, dwSize2);\r
-\r
- IDirectSoundBuffer_Unlock(pDSB, pMem1, dwSize1, pMem2, dwSize2);\r
- return TRUE;\r
- }\r
- }\r
- return FALSE;\r
-}\r
-\r
-\r
-DSCAPS dsCaps;\r
-static SoundManager * CreateSoundManager(HWND hWnd )\r
-{\r
- typedef HRESULT (WINAPI *DS_CREATE_FUNC)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);\r
- PCMWAVEFORMAT pcmwf;\r
- DSBUFFERDESC dsbdesc;\r
- HRESULT hres;\r
- SoundManager * sm;\r
- DS_CREATE_FUNC pDirectSoundCreate;\r
-\r
- // load the DirectSound DLL\r
- hmodDirectSound = LoadLibrary ("DSOUND.DLL");\r
- if (hmodDirectSound == NULL)\r
- {\r
- // Couldn't load DSOUND.DLL\r
- return NULL;\r
- }\r
-\r
- pDirectSoundCreate = (DS_CREATE_FUNC)GetProcAddress (hmodDirectSound, "DirectSoundCreate");\r
- if (pDirectSoundCreate == NULL)\r
- {\r
- // couldn't find the DirectSoundCreate function\r
- FreeLibrary (hmodDirectSound);\r
- return NULL;\r
- }\r
-\r
- hres = pDirectSoundCreate(NULL, &lpDirectSound, NULL);\r
- if (hres != DS_OK)\r
- {\r
- // failed somehow\r
- FreeLibrary (hmodDirectSound);\r
- return NULL;\r
- }\r
-\r
-// sm = malloc(sizeof(*sm));\r
- sm = geRam_Allocate(sizeof(*sm));\r
- if (!sm)\r
- {\r
- IDirectSound_Release(lpDirectSound);\r
- FreeLibrary (hmodDirectSound);\r
- return NULL;\r
- }\r
- sm->smChannelCount = 0;\r
- sm->smNextChannelID = 1;\r
- sm->smChannels = NULL;\r
-\r
- memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));\r
- pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;\r
-\r
- //pcmwf.wf.nChannels = 1;\r
- //pcmwf.wf.nSamplesPerSec = 44050;\r
- //pcmwf.wf.nBlockAlign = 2;\r
-#if 1 \r
- pcmwf.wf.nChannels = 2;\r
- pcmwf.wf.nSamplesPerSec = 44100;\r
- pcmwf.wf.nBlockAlign = 4;\r
- pcmwf.wBitsPerSample = 16;\r
- pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;\r
-#else\r
- pcmwf.wf.nChannels = 1;\r
- pcmwf.wf.nSamplesPerSec = 22050;\r
- pcmwf.wf.nBlockAlign = 1;\r
- pcmwf.wBitsPerSample = 8;\r
- pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * 2;\r
-#endif\r
-\r
- memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));\r
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);\r
- dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;// | DSBCAPS_CTRLDEFAULT;// | DSBCAPS_CTRL3D;\r
- dsbdesc.dwBufferBytes = 0; //dwBufferBytes and lpwfxFormat must be set this way.\r
- dsbdesc.lpwfxFormat = NULL;\r
-\r
-#if 1\r
- if (DS_OK== IDirectSound_SetCooperativeLevel(lpDirectSound, hWnd,DSSCL_NORMAL))\r
-#else\r
- if (DS_OK== IDirectSound_SetCooperativeLevel(lpDirectSound, hWnd,DSSCL_EXCLUSIVE))\r
-#endif\r
- {\r
- if (DS_OK== IDirectSound_CreateSoundBuffer(lpDirectSound, &dsbdesc, &sm->smPrimaryChannel, NULL))\r
- {\r
- return sm;\r
- }\r
- IDirectSound_Release(lpDirectSound);\r
- FreeLibrary (hmodDirectSound);\r
- }\r
-// free( sm );\r
- geRam_Free(sm);\r
- return NULL;\r
-}\r
-\r
-//static BOOL CreateChannel( char* Name, DSBUFFERDESC* dsBD, Channel** chanelPtr)\r
-static BOOL CreateChannel(DSBUFFERDESC* dsBD, Channel** chanelPtr)\r
-{\r
- Channel* channel;\r
-\r
-// channel = malloc( sizeof( Channel ) );\r
- channel = geRam_Allocate( sizeof( Channel ) );\r
- if ( channel == NULL )\r
- {\r
- geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL);\r
- return( FALSE );\r
- }\r
- if(DS_OK != IDirectSound_CreateSoundBuffer(lpDirectSound, dsBD, &channel->buffer, NULL))\r
- {\r
- geErrorLog_Add(GE_ERR_CREATE_SOUND_BUFFER_FAILED, NULL);\r
- return FALSE;\r
- }\r
- if(DS_OK != IDirectSoundBuffer_GetFrequency(channel->buffer, &channel->BaseFreq) )\r
- {\r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
- }\r
- channel->next = NULL;\r
- channel->nextDup = NULL;\r
- channel->ID = 0;\r
- channel->cfg.Volume = 1.0f;\r
- channel->cfg.Pan = 0.0f;\r
- channel->cfg.Frequency = 0.0f;\r
-// channel->name = Name;\r
-\r
- *chanelPtr = channel;\r
- return( TRUE );\r
-}\r
-\r
-//static BOOL GetSoundData( char* Name, unsigned char** dataPtr)\r
-static BOOL GetSoundData( geVFile *File, unsigned char** dataPtr)\r
-{\r
-// FILE * f;\r
- int32 Size;\r
- uint8 *data;\r
-// int32 CurPos;\r
-\r
-#if 0\r
- f = fopen(Name, "rb");\r
- \r
- if (!f)\r
- {\r
- geErrorLog_Add(GE_ERR_FILE_OPEN_ERROR, NULL);\r
- return FALSE;\r
- }\r
-#endif\r
-\r
-#if 0\r
- CurPos = ftell (f); // Save the startinf pos into this function\r
- fseek (f, 0, SEEK_END); // Seek to end\r
- Size = ftell (f); // Get End (this will be the size)\r
- fseek (f, CurPos, SEEK_SET); // Restore file position\r
-#endif\r
-\r
- if (geVFile_Size(File, &Size) == GE_FALSE)\r
- return FALSE;\r
-\r
- data = geRam_Allocate(Size);\r
-\r
- if (!data) \r
- {\r
- geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL);\r
- return FALSE;\r
- }\r
- \r
- if (geVFile_Read(File, data, Size) == GE_FALSE)\r
- {\r
- geRam_Free(data);\r
- return FALSE;\r
- }\r
-\r
-// fread(data, Size, 1, f);\r
-\r
-// fclose(f);\r
- *dataPtr = data;\r
- return( TRUE );\r
-}\r
-\r
-static BOOL ParseData( const uint8* data, DSBUFFERDESC* dsBD, BYTE ** pbWaveData )\r
-{\r
-\r
- //Parse the Data\r
- memset(dsBD, 0, sizeof(DSBUFFERDESC));\r
-\r
- dsBD->dwSize = sizeof(DSBUFFERDESC);\r
- dsBD->dwFlags = DSBCAPS_STATIC | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPAN |\r
- DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLVOLUME;\r
- if (!DSParseWaveResource(data, &dsBD->lpwfxFormat, pbWaveData, &dsBD->dwBufferBytes))\r
- {\r
- geErrorLog_Add(GE_ERR_INVALID_WAV, NULL);\r
- return FALSE;\r
- }\r
- return( TRUE );\r
-\r
-}\r
-\r
-//static BOOL FillSoundChannel(SoundManager *sm, char* Dir, char *Name, unsigned int* Handle )\r
-static BOOL FillSoundChannel(SoundManager *sm, geVFile *File, unsigned int* Handle )\r
-{\r
- DSBUFFERDESC dsBD;\r
- INT NumBytes;\r
- uint8 *data = NULL;\r
- BYTE * pbWaveData;\r
-// char* Name2;\r
- Channel* channel;\r
-\r
- *Handle = 0;\r
- if (!sm)\r
- return TRUE;\r
-\r
-#if 0\r
- //Open the file\r
- if (Dir)\r
- {\r
- Name2 = malloc( strlen( Name ) + strlen( Dir ) + 3); // 2 for the "//" and 1 for terminator\r
- if( !Name2 )\r
- return( 0 );\r
- sprintf(Name2, "%s\\%s", Dir, Name);\r
- }\r
- else\r
- {\r
- Name2 = malloc( strlen( Name ) + 3); // 2 for the "//" and 1 for terminator\r
- if( !Name2 )\r
- return( 0 );\r
-\r
- sprintf(Name2, "%s", Name);\r
- }\r
-#endif\r
- if(!GetSoundData( File, &data ))\r
- return( FALSE );\r
-\r
- if( !ParseData( data, &dsBD, &pbWaveData ) )\r
- {\r
- geRam_Free(data);\r
- return( FALSE );\r
- }\r
-\r
- NumBytes = dsBD.dwBufferBytes;\r
- \r
- //Create the channel\r
-// if( !CreateChannel( Name2, &dsBD, &channel ) )\r
- if (!CreateChannel(&dsBD, &channel))\r
- {\r
- geRam_Free(data);\r
- return FALSE;\r
- }\r
- channel->next = sm->smChannels;\r
- channel->ID = sm->smNextChannelID++;\r
- channel->Data = data;\r
-\r
- sm->smChannels = channel;\r
- sm->smChannelCount++;\r
-\r
- //Fill the channel\r
- if (!DSFillSoundBuffer(channel->buffer, pbWaveData, NumBytes))\r
- return FALSE;\r
- \r
-// free( data );\r
-// geRam_Free(data);\r
-\r
- *Handle = channel->ID;\r
- return TRUE;\r
-}\r
-\r
-#if 0\r
-static BOOL FillSoundChannelMemory(SoundManager *sm, const void *Buffer, unsigned int* Handle )\r
-{\r
- DSBUFFERDESC dsBD;\r
- INT NumBytes;\r
- BYTE * pbWaveData;\r
- char * Name;\r
- Channel * channel;\r
-\r
- *Handle = 0;\r
- if (!sm)\r
- return TRUE;\r
-\r
- if (!ParseData(Buffer, &dsBD, &pbWaveData))\r
- return FALSE;\r
-\r
- NumBytes = dsBD.dwBufferBytes;\r
-\r
- Name = malloc(11);\r
- if (Name == NULL)\r
- return FALSE;\r
- sprintf(Name, "0x%8x", Buffer);\r
- \r
- //Create the channel\r
-// if (!CreateChannel(Name, &dsBD, &channel))\r
- if (!CreateChannel(&dsBD, &channel))\r
- return FALSE;\r
-\r
- channel->next = sm->smChannels;\r
- channel->ID = sm->smNextChannelID++;\r
-\r
- sm->smChannels = channel;\r
- sm->smChannelCount++;\r
-\r
- //Fill the channel\r
- if (!DSFillSoundBuffer(channel->buffer, pbWaveData, NumBytes))\r
- return FALSE;\r
- \r
- *Handle = channel->ID;\r
- return TRUE;\r
-}\r
-#endif\r
-\r
-static void StopDupBuffers( Channel* channel )\r
-{\r
- Channel* dupChannel, *prevChannel;\r
-\r
- assert( channel );\r
-\r
- dupChannel = channel->nextDup;\r
- prevChannel = channel;\r
- while( dupChannel )\r
- {\r
- IDirectSoundBuffer_Stop(dupChannel->buffer);\r
- dupChannel = dupChannel->nextDup;\r
- }\r
-}\r
-\r
-static void ClearDupBuffers( Channel* channel )\r
-{\r
- Channel* dupChannel, *prevChannel;\r
-\r
- if( channel == NULL)\r
- return;\r
-\r
- dupChannel = channel->nextDup;\r
- prevChannel = channel;\r
- while( dupChannel )\r
- {\r
- if( !ChannelPlaying( dupChannel ) )\r
- {\r
- prevChannel->nextDup = dupChannel->nextDup;\r
- IDirectSound_Release(dupChannel->buffer);\r
-// free( dupChannel );\r
- geRam_Free(dupChannel);\r
- dupChannel = prevChannel->nextDup;\r
- }\r
- else\r
- {\r
- prevChannel = dupChannel;\r
- dupChannel = dupChannel->nextDup;\r
- }\r
- }\r
-}\r
-\r
-static BOOL FreeAllChannels(SoundManager *sm)\r
-{\r
- int Error;\r
- \r
- Channel* channel, *nextChannel;\r
-\r
- channel = sm->smChannels;\r
- while( channel )\r
- {\r
- nextChannel = channel->next;\r
- StopDupBuffers( channel );\r
- ClearDupBuffers( channel );\r
- Error = IDirectSoundBuffer_Stop(channel->buffer);\r
- if (Error != DS_OK)\r
- {\r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
- }\r
- Error = IDirectSound_Release(channel->buffer);\r
- if (Error != DS_OK)\r
- {\r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
- }\r
- \r
-// if( channel->name )\r
-// geRam_Free(channel->name);\r
-// free( channel->name );\r
- if (channel->Data)\r
- geRam_Free(channel->Data);\r
- geRam_Free(channel);\r
-// free( channel );\r
- channel = nextChannel;\r
- }\r
- sm->smChannels = NULL;\r
- sm->smChannelCount = 0;\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-static BOOL FreeChannel(SoundManager *sm, Channel* channel)\r
-{\r
- int Error;\r
- Channel*prevChannel = NULL, *curChannel;\r
- if ( channel )\r
- {\r
- StopDupBuffers( channel );\r
- ClearDupBuffers( channel );\r
- Error = IDirectSoundBuffer_Stop(channel->buffer);\r
- if (Error != DS_OK)\r
- {\r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
- }\r
- Error = IDirectSound_Release(channel->buffer);\r
- if (Error != DS_OK)\r
- {\r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
- }\r
-// if( channel->name )\r
-// geRam_Free(channel->name);\r
-// free( channel->name );\r
-\r
- if( channel->Data )\r
- geRam_Free(channel->Data);\r
-\r
- curChannel = sm->smChannels;\r
- while( curChannel && curChannel != channel )\r
- {\r
- prevChannel = curChannel;\r
- curChannel = curChannel->next;\r
- }\r
- if( curChannel )\r
- {\r
- if( prevChannel )\r
- prevChannel->next = curChannel->next;\r
- else\r
- sm->smChannels = curChannel->next;\r
- geRam_Free(curChannel);\r
-// free( curChannel );\r
- }\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-static Channel* ReloadData(void *Data)\r
-{\r
- DSBUFFERDESC dsBD;\r
- BYTE * pbWaveData;\r
- INT NumBytes;\r
-// uint8 *data = NULL;\r
- Channel* channel;\r
-\r
-// if( !Name )\r
-// return( NULL );\r
-// if( !GetSoundData( Data, &data ) )\r
-// return( NULL );\r
-\r
- if( !ParseData( Data, &dsBD, &pbWaveData ) )\r
- return( NULL );\r
-\r
- NumBytes = dsBD.dwBufferBytes;\r
- \r
- //Create the channel\r
-// if( !CreateChannel( Name, &dsBD, &channel ) )\r
- if( !CreateChannel(&dsBD, &channel ) )\r
- return NULL;\r
-\r
- //Fill the channel\r
- if ( !DSFillSoundBuffer(channel->buffer, pbWaveData, NumBytes))\r
- return NULL;\r
- \r
-// geRam_Free(data);\r
-// free( data );\r
- return( channel );\r
-}\r
-\r
-static BOOL DupChannel( SoundManager *sm, Channel* channel, Channel** dupChannelPtr )\r
-{\r
- Channel* dupChannel;\r
- HRESULT Error;\r
-\r
- *dupChannelPtr = NULL;\r
-// dupChannel = malloc( sizeof(Channel ) );\r
- dupChannel = geRam_Allocate( sizeof(Channel ) );\r
- if( dupChannel == NULL )\r
- {\r
- geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL );\r
- return FALSE;\r
- }\r
- Error = IDirectSound_DuplicateSoundBuffer( lpDirectSound, channel->buffer, &dupChannel->buffer );\r
- if( Error != DS_OK )\r
- {\r
- geRam_Free(dupChannel);\r
-// free( dupChannel );\r
- dupChannel = ReloadData( channel->Data );\r
- if( dupChannel == NULL )\r
- {\r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
- }\r
- }\r
- dupChannel->ID = sm->smNextChannelID++;\r
- dupChannel->next = NULL;\r
- dupChannel->nextDup = channel->nextDup;\r
- dupChannel->cfg = channel->cfg;\r
-// dupChannel->name = NULL;\r
- dupChannel->Data = channel->Data;\r
- channel->nextDup = dupChannel;\r
- *dupChannelPtr = dupChannel;\r
- return( TRUE );\r
-}\r
-\r
-static BOOL StartSoundChannel( SoundManager *sm, unsigned int Handle, geSound_Cfg *cfg, int loop, unsigned int* sfx)\r
-{\r
- HRESULT hres;\r
- Channel* channel, *dupChannel;\r
- \r
- if( Handle == 0 )\r
- return( FALSE );\r
- channel = GetChannel( sm, Handle );\r
- //Clear all non-playing duplicate buffers.\r
- ClearDupBuffers(channel);\r
- //If the main buffer is playing and all non-playing dups have been cleared\r
- //we need a new duplicate.\r
- if( ChannelPlaying( channel ) )\r
- {\r
- if(!DupChannel( sm,channel, &dupChannel ) )\r
- return( FALSE );\r
- channel = dupChannel;\r
- }\r
- if( !ModifyChannel( channel, cfg ) )\r
- return( FALSE );\r
- IDirectSoundBuffer_SetCurrentPosition(channel->buffer, 0);\r
- hres = IDirectSoundBuffer_Play( channel->buffer,\r
- 0,\r
- 0,\r
- loop ? DSBPLAY_LOOPING : 0);\r
-\r
- if (hres == DS_OK)\r
- {\r
- if( sfx )\r
- *sfx = channel->ID;\r
- return TRUE;\r
- }\r
- \r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
-}\r
-\r
-static BOOL StopSoundChannel(Channel* channel)\r
-{\r
- HRESULT hres;\r
-\r
- assert(channel);\r
-\r
- hres = IDirectSoundBuffer_Stop(channel->buffer);\r
-\r
- if (hres == DS_OK)\r
- return TRUE;\r
-\r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
-}\r
-\r
-static void DestroySoundManager(SoundManager *sm)\r
-{\r
- if (!sm) return;\r
-\r
- FreeAllChannels( sm );\r
- if (sm->smPrimaryChannel != NULL)\r
- sm->smPrimaryChannel->lpVtbl->Release(sm->smPrimaryChannel);\r
- if (lpDirectSound != NULL)\r
- IDirectSound_Release(lpDirectSound);\r
- if (hmodDirectSound != NULL)\r
- FreeLibrary (hmodDirectSound);\r
- geRam_Free(sm);\r
-// free(sm);\r
-}\r
-\r
-static BOOL ModifyChannel( Channel *channel, geSound_Cfg *cfg )\r
-{\r
- int Error, Vol, Pan, Freq;\r
- assert(channel);\r
- \r
- if( !cfg )\r
- return( TRUE );\r
- ClearDupBuffers(channel);\r
- if( cfg->Volume != channel->cfg.Volume )\r
- {\r
- Vol = (DWORD)((1.0 - cfg->Volume ) * DSBVOLUME_MIN);\r
- Error = IDirectSoundBuffer_SetVolume(channel->buffer, Vol);\r
- if (Error != DS_OK)\r
- {\r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
- }\r
- channel->cfg.Volume = cfg->Volume;\r
- }\r
-\r
- if( cfg->Pan != channel->cfg.Pan )\r
- {\r
- Pan = (int)(cfg->Pan * DSBPAN_RIGHT);\r
- Error = IDirectSoundBuffer_SetPan(channel->buffer, Pan);\r
- if (Error != DS_OK)\r
- {\r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
- }\r
- channel->cfg.Pan = cfg->Pan;\r
- }\r
-\r
-\r
- if( cfg->Frequency != channel->cfg.Frequency )\r
- {\r
-\r
- Freq = (DWORD)(channel->BaseFreq * cfg->Frequency);\r
- Error = IDirectSoundBuffer_SetFrequency(channel->buffer, Freq);\r
- if (Error != DS_OK)\r
- {\r
- geErrorLog_Add(GE_ERR_DS_ERROR, NULL);\r
- return FALSE;\r
- }\r
- channel->cfg.Frequency = cfg->Frequency;\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-static int ChannelPlaying( Channel *channel )\r
-{\r
- DWORD status, Error;\r
-\r
- if(!channel)\r
- return( 0 );\r
-\r
- Error = IDirectSoundBuffer_GetStatus( channel->buffer, &status);\r
- if( Error != DS_OK)\r
- return 0;\r
- return( status & DSBSTATUS_PLAYING );\r
-}\r
-\r
-static Channel* GetChannel( SoundManager *sm, unsigned int ID )\r
-{\r
- Channel* dupChannel;\r
- Channel* channel = sm->smChannels;\r
-\r
- while( channel )\r
- {\r
- if( channel->ID == ID )\r
- break;\r
- dupChannel = channel->nextDup;\r
- while( dupChannel )\r
- {\r
- if( dupChannel->ID == ID )\r
- break;\r
- dupChannel = dupChannel->nextDup;\r
- }\r
- if( dupChannel )\r
- return( dupChannel );\r
- channel = channel->next;\r
- }\r
- return( channel );\r
-}\r