123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- #pragma warning(disable:4996)
- #include "DSoundManager.h"
- #include <io.h>
- #include <fcntl.h>
- #include "DSoundInstance.h"
- #include <math.h>
- using namespace Beefy;
- static HMODULE gDSoundDLL;
- #pragma comment(lib, "dsound.lib")
- #define SOUND_FLAGS (DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLFREQUENCY)
- DSoundManager::DSoundManager(HWND theHWnd)
- {
- mLastReleaseTick = 0;
- mPrimaryBuffer = NULL;
- int i;
- for (i = 0; i < MAX_SOURCE_SOUNDS; i++)
- {
- mSourceSounds[i] = NULL;
- mBaseVolumes[i] = 1;
- mBasePans[i] = 0;
- }
- for (i = 0; i < MAX_CHANNELS; i++)
- mPlayingSounds[i] = NULL;
- mDirectSound = NULL;
- mMasterVolume = 1.0;
-
- //typedef HRESULT (WINAPI *DirectSoundCreateFunc)(LPCGUID lpcGuid, LPDIRECTSOUND * ppDS, LPUNKNOWN pUnkOuter);
- //DirectSoundCreateFunc aDirectSoundCreateFunc = (DirectSoundCreateFunc)GetProcAddress(gDSoundDLL,"DirectSoundCreate");
- // Seems crazy but this was even suggested in MSDN docs for windowless applications
- if (theHWnd == NULL)
- theHWnd = ::GetDesktopWindow();
- //if (aDirectSoundCreateFunc != NULL && aDirectSoundCreateFunc(NULL, &mDirectSound, NULL) == DS_OK)
- if (DirectSoundCreate(NULL, &mDirectSound, NULL) == DS_OK)
- {
- bool handled = false;
- if (theHWnd != NULL)
- {
- HRESULT aResult = mDirectSound->SetCooperativeLevel(theHWnd, DSSCL_PRIORITY);
- if (SUCCEEDED(aResult))
- {
- // Set primary buffer to 16-bit 44.1Khz
- WAVEFORMATEX aWaveFormat;
- DSBUFFERDESC aBufferDesc;
- // Set up wave format structure.
- int aBitCount = 16;
- int aChannelCount = 2;
- int aSampleRate = 44100;
- // Set up wave format structure.
- memset(&aWaveFormat, 0, sizeof(WAVEFORMATEX));
- aWaveFormat.cbSize = sizeof(WAVEFORMATEX);
- aWaveFormat.wFormatTag = WAVE_FORMAT_PCM;
- aWaveFormat.nChannels = aChannelCount;
- aWaveFormat.nSamplesPerSec = aSampleRate;
- aWaveFormat.nBlockAlign = aChannelCount * aBitCount / 8;
- aWaveFormat.nAvgBytesPerSec =
- aWaveFormat.nSamplesPerSec * aWaveFormat.nBlockAlign;
- aWaveFormat.wBitsPerSample = aBitCount;
- // Set up DSBUFFERDESC structure.
- memset(&aBufferDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
- aBufferDesc.dwSize = sizeof(DSBUFFERDESC1);
- aBufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER;//| DSBCAPS_CTRL3D; // Need default controls (pan, volume, frequency).
- aBufferDesc.dwBufferBytes = 0;
- aBufferDesc.lpwfxFormat = NULL;//(LPWAVEFORMATEX)&aWaveFormat;
- HRESULT aResult = mDirectSound->CreateSoundBuffer(&aBufferDesc, &mPrimaryBuffer, NULL);
- if (aResult == DS_OK)
- {
- aResult = mPrimaryBuffer->SetFormat(&aWaveFormat);
- }
- handled = true;
- }
- }
-
- if (!handled)
- {
- HRESULT aResult = mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
- }
- }
- }
- DSoundManager::~DSoundManager()
- {
- ReleaseChannels();
- ReleaseSounds();
- if (mPrimaryBuffer)
- mPrimaryBuffer->Release();
- if (mDirectSound != NULL)
- {
- mDirectSound->Release();
- }
- }
- int DSoundManager::FindFreeChannel()
- {
- DWORD aTick = GetTickCount();
- if (aTick-mLastReleaseTick > 1000)
- {
- ReleaseFreeChannels();
- mLastReleaseTick = aTick;
- }
- for (int i = 0; i < MAX_CHANNELS; i++)
- {
- if (mPlayingSounds[i] == NULL)
- return i;
-
- if (mPlayingSounds[i]->IsReleased())
- {
- delete mPlayingSounds[i];
- mPlayingSounds[i] = NULL;
- return i;
- }
- }
-
- return -1;
- }
- bool DSoundManager::Initialized()
- {
- /*
- if (mDirectSound!=NULL)
- {
- mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
- }
- */
- return (mDirectSound != NULL);
- }
- int DSoundManager::VolumeToDB(float theVolume)
- {
- int aVol = (int) ((log10(1 + theVolume*9) - 1.0) * 2333);
- if (aVol < -2000)
- aVol = -10000;
- return aVol;
- }
- void DSoundManager::SetVolume(float theVolume)
- {
- mMasterVolume = theVolume;
- for (int i = 0; i < MAX_CHANNELS; i++)
- if (mPlayingSounds[i] != NULL)
- mPlayingSounds[i]->RehupVolume();
- }
- bool DSoundManager::LoadWAVSound(unsigned int theSfxID, const StringImpl& theFilename)
- {
- int aDataSize;
- FILE* fp;
- fp = fopen(theFilename.c_str(), "rb");
- if (fp <= 0)
- return false;
- char aChunkType[5];
- aChunkType[4] = '\0';
- uint32 aChunkSize;
- fread(aChunkType, 1, 4, fp);
- if (!strcmp(aChunkType, "RIFF") == 0)
- return false;
- fread(&aChunkSize, 4, 1, fp);
- fread(aChunkType, 1, 4, fp);
- if (!strcmp(aChunkType, "WAVE") == 0)
- return false;
- uint16 aBitCount = 16;
- uint16 aChannelCount = 1;
- uint32 aSampleRate = 22050;
- uint8 anXor = 0;
- while (!feof(fp))
- {
- fread(aChunkType, 1, 4, fp);
- if (fread(&aChunkSize, 4, 1, fp) == 0)
- return false;
- int aCurPos = ftell(fp);
- if (strcmp(aChunkType, "fmt ") == 0)
- {
- uint16 aFormatTag;
- uint32 aBytesPerSec;
- uint16 aBlockAlign;
- fread(&aFormatTag, 2, 1, fp);
- fread(&aChannelCount, 2, 1, fp);
- fread(&aSampleRate, 4, 1, fp);
- fread(&aBytesPerSec, 4, 1, fp);
- fread(&aBlockAlign, 2, 1, fp);
- fread(&aBitCount, 2, 1, fp);
- if (aFormatTag != 1)
- return false;
- }
- else if (strcmp(aChunkType, "data") == 0)
- {
- aDataSize = aChunkSize;
- mSourceDataSizes[theSfxID] = aChunkSize;
- PCMWAVEFORMAT aWaveFormat;
- DSBUFFERDESC aBufferDesc;
- // Set up wave format structure.
- memset(&aWaveFormat, 0, sizeof(PCMWAVEFORMAT));
- aWaveFormat.wf.wFormatTag = WAVE_FORMAT_PCM;
- aWaveFormat.wf.nChannels = aChannelCount;
- aWaveFormat.wf.nSamplesPerSec = aSampleRate;
- aWaveFormat.wf.nBlockAlign = aChannelCount*aBitCount/8;
- aWaveFormat.wf.nAvgBytesPerSec =
- aWaveFormat.wf.nSamplesPerSec * aWaveFormat.wf.nBlockAlign;
- aWaveFormat.wBitsPerSample = aBitCount;
- // Set up DSBUFFERDESC structure.
- memset(&aBufferDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
- aBufferDesc.dwSize = sizeof(DSBUFFERDESC);
- //aBufferDesc.dwFlags = DSBCAPS_CTRL3D;
- aBufferDesc.dwFlags = SOUND_FLAGS; //DSBCAPS_CTRLDEFAULT;
- //aBufferDesc.dwFlags = 0;
- aBufferDesc.dwBufferBytes = aDataSize;
- aBufferDesc.lpwfxFormat = (LPWAVEFORMATEX)&aWaveFormat;
- if (mDirectSound->CreateSoundBuffer(&aBufferDesc, &mSourceSounds[theSfxID], NULL) != DS_OK)
- {
- fclose(fp);
- return false;
- }
- void* lpvPtr;
- DWORD dwBytes;
- if (mSourceSounds[theSfxID]->Lock(0, aDataSize, &lpvPtr, &dwBytes, NULL, NULL, 0) != DS_OK)
- {
- fclose(fp);
- return false;
- }
- int aReadSize = (int)fread(lpvPtr, 1, aDataSize, fp);
- fclose(fp);
- for (int i = 0; i < aDataSize; i++)
- ((uint8*) lpvPtr)[i] ^= anXor;
- if (mSourceSounds[theSfxID]->Unlock(lpvPtr, dwBytes, NULL, NULL) != DS_OK)
- return false;
- if (aReadSize != aDataSize)
- return false;
- return true;
- }
- fseek(fp, aCurPos+aChunkSize, SEEK_SET);
- }
-
- return false;
- }
- bool DSoundManager::LoadSound(unsigned int theSfxID, const StringImpl& theFilename)
- {
- if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS))
- return false;
- ReleaseSound(theSfxID);
- if (!mDirectSound)
- return true; // sounds just won't play, but this is not treated as a failure condition
- mSourceFileNames[theSfxID] = theFilename;
- StringImpl aFilename = theFilename;
-
- if (aFilename.EndsWith(".wav", StringImpl::CompareKind_OrdinalIgnoreCase))
- {
- if (LoadWAVSound(theSfxID, aFilename))
- return true;
- }
- return false;
- }
- int DSoundManager::LoadSound(const StringImpl& theFilename)
- {
- int i;
- for (i = 0; i < MAX_SOURCE_SOUNDS; i++)
- if (mSourceFileNames[i] == theFilename)
- return i;
- for (i = MAX_SOURCE_SOUNDS-1; i >= 0; i--)
- {
- if (mSourceSounds[i] == NULL)
- {
- if (!LoadSound(i, theFilename))
- return -1;
- else
- return i;
- }
- }
- return -1;
- }
- void DSoundManager::ReleaseSound(unsigned int theSfxID)
- {
- if (mSourceSounds[theSfxID] != NULL)
- {
- mSourceSounds[theSfxID]->Release();
- mSourceSounds[theSfxID] = NULL;
- mSourceFileNames[theSfxID] = "";
- }
- }
- int DSoundManager::GetFreeSoundId()
- {
- for (int i=0; i<MAX_SOURCE_SOUNDS; i++)
- {
- if (mSourceSounds[i]==NULL)
- return i;
- }
- return -1;
- }
- int DSoundManager::GetNumSounds()
- {
- int aCount = 0;
- for (int i=0; i<MAX_SOURCE_SOUNDS; i++)
- {
- if (mSourceSounds[i]!=NULL)
- aCount++;
- }
- return aCount;
- }
- bool DSoundManager::SetBaseVolume(unsigned int theSfxID, float theBaseVolume)
- {
- if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS))
- return false;
- mBaseVolumes[theSfxID] = theBaseVolume;
- return true;
- }
- bool DSoundManager::SetBasePan(unsigned int theSfxID, int theBasePan)
- {
- if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS))
- return false;
- mBasePans[theSfxID] = theBasePan;
- return true;
- }
- BFSoundInstance* DSoundManager::GetSoundInstance(unsigned int theSfxID)
- {
- if (theSfxID > MAX_SOURCE_SOUNDS)
- return NULL;
- int aFreeChannel = FindFreeChannel();
- if (aFreeChannel < 0)
- return NULL;
- if (mDirectSound==NULL)
- {
- mPlayingSounds[aFreeChannel] = new DSoundInstance(this, NULL);
- }
- else
- {
- if (mSourceSounds[theSfxID] == NULL)
- return NULL;
- mPlayingSounds[aFreeChannel] = new DSoundInstance(this, mSourceSounds[theSfxID]);
- }
- mPlayingSounds[aFreeChannel]->SetBasePan(mBasePans[theSfxID]);
- mPlayingSounds[aFreeChannel]->SetBaseVolume(mBaseVolumes[theSfxID]);
- return mPlayingSounds[aFreeChannel];
- }
- void DSoundManager::ReleaseSounds()
- {
- for (int i = 0; i < MAX_SOURCE_SOUNDS; i++)
- if (mSourceSounds[i] != NULL)
- {
- mSourceSounds[i]->Release();
- mSourceSounds[i] = NULL;
- }
- }
- void DSoundManager::ReleaseChannels()
- {
- for (int i = 0; i < MAX_CHANNELS; i++)
- if (mPlayingSounds[i] != NULL)
- {
- delete mPlayingSounds[i];
- mPlayingSounds[i] = NULL;
- }
- }
- void DSoundManager::ReleaseFreeChannels()
- {
- for (int i = 0; i < MAX_CHANNELS; i++)
- if (mPlayingSounds[i] != NULL && mPlayingSounds[i]->IsReleased())
- {
- delete mPlayingSounds[i];
- mPlayingSounds[i] = NULL;
- }
- }
- void DSoundManager::StopAllSounds()
- {
- for (int i = 0; i < MAX_CHANNELS; i++)
- if (mPlayingSounds[i] != NULL)
- {
- bool isAutoRelease = mPlayingSounds[i]->mAutoRelease;
- mPlayingSounds[i]->Stop();
- mPlayingSounds[i]->mAutoRelease = isAutoRelease;
- }
- }
- float DSoundManager::GetMasterVolume()
- {
- MIXERCONTROLDETAILS mcd;
- MIXERCONTROLDETAILS_UNSIGNED mxcd_u;
- MIXERLINECONTROLS mxlc;
- MIXERCONTROL mlct;
- MIXERLINE mixerLine;
- HMIXER hmx;
- MIXERCAPS pmxcaps;
- mixerOpen((HMIXER*) &hmx, 0, 0, 0, MIXER_OBJECTF_MIXER);
- mixerGetDevCaps(0, &pmxcaps, sizeof(pmxcaps));
- mxlc.cbStruct = sizeof(mxlc);
- mxlc.cbmxctrl = sizeof(mlct);
- mxlc.pamxctrl = &mlct;
- mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
- mixerLine.cbStruct = sizeof(mixerLine);
- mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
- mixerGetLineInfo((HMIXEROBJ) hmx, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE);
- mxlc.dwLineID = mixerLine.dwLineID;
- mixerGetLineControls((HMIXEROBJ) hmx, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
- mcd.cbStruct = sizeof(mcd);
- mcd.dwControlID = mlct.dwControlID;
- mcd.cChannels = 1;
- mcd.cMultipleItems = 0;
- mcd.cbDetails = sizeof(mxcd_u);
- mcd.paDetails = &mxcd_u;
-
- mixerGetControlDetails((HMIXEROBJ) hmx, &mcd, 0L);
- mixerClose(hmx);
- return mxcd_u.dwValue / (float) 0xFFFF;
- }
- void DSoundManager::SetMasterVolume(float theVolume)
- {
- MIXERCONTROLDETAILS mcd;
- MIXERCONTROLDETAILS_UNSIGNED mxcd_u;
- MIXERLINECONTROLS mxlc;
- MIXERCONTROL mlct;
- MIXERLINE mixerLine;
- HMIXER hmx;
- MIXERCAPS pmxcaps;
- mixerOpen((HMIXER*) &hmx, 0, 0, 0, MIXER_OBJECTF_MIXER);
- mixerGetDevCaps(0, &pmxcaps, sizeof(pmxcaps));
- mxlc.cbStruct = sizeof(mxlc);
- mxlc.cbmxctrl = sizeof(mlct);
- mxlc.pamxctrl = &mlct;
- mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
- mixerLine.cbStruct = sizeof(mixerLine);
- mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
- mixerGetLineInfo((HMIXEROBJ) hmx, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE);
- mxlc.dwLineID = mixerLine.dwLineID;
- mixerGetLineControls((HMIXEROBJ) hmx, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
- mcd.cbStruct = sizeof(mcd);
- mcd.dwControlID = mlct.dwControlID;
- mcd.cChannels = 1;
- mcd.cMultipleItems = 0;
- mcd.cbDetails = sizeof(mxcd_u);
- mcd.paDetails = &mxcd_u;
-
- mxcd_u.dwValue = (int) (0xFFFF * theVolume);
- mixerSetControlDetails((HMIXEROBJ) hmx, &mcd, 0L);
- mixerClose(hmx);
- }
- void DSoundManager::Flush()
- {
- }
- void DSoundManager::SetCooperativeWindow(HWND theHWnd, bool isWindowed)
- {
- if (mDirectSound != NULL)
- mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
- /*
- if (isWindowed==true) mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
- else mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_EXCLUSIVE);
- */
- }
- #undef SOUND_FLAGS
|