123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662 |
- /*=============================================================================
- Name : SoundLow.c
- Purpose : Low level sound routines
- Created 7/24/1997 by gshaw
- Copyright Relic Entertainment, Inc. All rights reserved.
- =============================================================================*/
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <mmsystem.h>
- #include <string.h>
- #include <dsound.h>
- #include "switches.h"
- #include "debug.h"
- #include "soundlow.h"
- #include "file.h"
- #include "soundcmn.h"
- #include "main.h"
- #define SOUNDFXDIR "SoundFX\\"
- #define EQ_STEP 0.1
- typedef struct
- {
- void *start;
- void *end;
- } BANKPOINTERS;
- /* function in speechevent.c that needs to be called when shutting down */
- void musicEventUpdateVolume(void);
- /* internal functions */
- sdword SNDgetchannel(sword patchnum, sdword priority);
- /* variables */
- CHANNEL channels[SOUND_MAX_VOICES];
- sword numpatches = 0;
- LPDIRECTSOUND lpDirectSound = NULL;
- LPDIRECTSOUNDBUFFER lpPrimaryBuffer = NULL;
- sdword lasthandle = 0;
- bool soundinited = FALSE;
- BANK *bank;
- PATCH *patches;
- sdword channelsinuse = 0;
- bool bDirectSoundCertified = FALSE;
- real32 masterEQ[FQ_SIZE];
- bool bSoundPaused = FALSE;
- bool bSoundDeactivated = FALSE;
- WAVEFORMATEX waveFormatEX;
- sdword numbanks = 0;
- sdword numchans[4] = {0,0,0,0};
- BANKPOINTERS bankpointers[4];
- SOUNDCOMPONENT mixer;
- SOUNDCOMPONENT streamer;
- sdword soundnumvoices=SOUND_DEF_VOICES;
- sdword soundvoicemode=SOUND_MODE_NORM; // voice panic mode, normal by default
- //streamprintfunction debugfunction = NULL;
- //char debugtext[256];
- extern HWND ghMainWindow;
- extern real32 cardiod[];
- extern udword mixerticks;
- // Get the min and max number of voices
- void soundGetVoiceLimits(sdword *min,sdword *max)
- {
- *min=SOUND_MIN_VOICES;
- *max=SOUND_MAX_VOICES;
- return;
- }
- // Get the current number of voices and mode
- void soundGetNumVoices(sdword *num,sdword *mode)
- {
- *num=soundnumvoices;
- *mode=soundvoicemode;
- return;
- }
- // Set the current number of voices and mode
- void soundSetNumVoices(sdword num,sdword mode)
- {
- if(num < SOUND_MIN_VOICES) num=SOUND_MIN_VOICES;
- if(num > SOUND_MAX_VOICES) num=SOUND_MAX_VOICES;
- soundnumvoices=num;
- soundvoicemode=mode;
- return;
- }
- // Shut down necessary channels for panic
- void soundPanic(void)
- {
- CHANNEL *pchan;
- sdword i;
- sdword lowchannel;
- real32 lowvolume;
- sdword lowticks;
- sdword lowpriority;
- while(channelsinuse > soundnumvoices)
- {
- lowpriority = SOUND_PRIORITY_LOW;
- lowticks = 255;
- lowvolume = (real32)SOUND_VOL_MAX;
- lowchannel = SOUND_DEFAULT;
- /* find the channel to steal */
- for (i = 0; i < SOUND_MAX_VOICES; i++)
- {
- pchan = &channels[i];
- /* don't want one that is already stopping */
- if (pchan->status == SOUND_PLAYING)
- {
- if (pchan->priority < lowpriority)
- {
- if (pchan->volume <= lowvolume)
- {
- if (pchan->volticksleft <= lowticks)
- {
- lowpriority = pchan->priority;
- lowticks = pchan->volticksleft;
- lowvolume = pchan->volume;
- lowchannel = i;
- }
- }
- }
- }
- }
- if (lowchannel > SOUND_DEFAULT)
- {
- /* stop the sound with the lowest priority */
- soundstop(channels[lowchannel].handle, SOUND_FADE_STOPNOW);
- }
- else
- {
- break;
- }
- }
- return;
- }
- // Called by main.c on before and after[Alt]-[Tab]
- void sounddeactivate(bool bDeactivate)
- {
- /* set flag */
- if (soundinited)
- {
- bSoundDeactivated=bDeactivate;
- }
- /* reset panic mode */
- soundPanicReset(); // mixer.c
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- real32 soundusage(void)
- {
- return ((real32)channelsinuse / SOUND_MAX_VOICES);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- void soundupdate(void)
- {
- return;
- }
- sdword soundStartDSound(HWND hWnd)
- {
- DSBUFFERDESC dsbdesc;
- DSCAPS dscaps;
- HRESULT hr;
- if (useWaveout)
- {
- return (SOUND_ERR);
- }
-
- if(DS_OK == DirectSoundCreate(NULL, &lpDirectSound, NULL))
- {
- // Set up DSBUFFERDESC structure.
- memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
- // Buffer size is determined by sound hardware.
- dsbdesc.dwBufferBytes = 0;
- dsbdesc.lpwfxFormat = NULL; // Must be NULL for primary buffers.
- if (coopDSound)
- {
- // Try to set in priority mode so Homeworld will share the wave device
- hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, hWnd, DSSCL_PRIORITY);
- if (hr != DS_OK)
- {
- // Hmmm, couldn't set priority so lets try exclusive
- hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, hWnd, DSSCL_EXCLUSIVE);
- }
- }
- else
- {
- // Try to set in Exclusive mode
- hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, hWnd, DSSCL_EXCLUSIVE);
- if (hr != DS_OK)
- {
- // maybe something already has the wave device so lets try sharing it?
- hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, hWnd, DSSCL_PRIORITY);
- }
- }
-
- if(hr == DS_OK)
- {
- // Get direct sound Caps.
- dscaps.dwSize = sizeof(DSCAPS);
- if (DS_OK == lpDirectSound->lpVtbl->GetCaps(lpDirectSound, &dscaps))
- {
- #ifndef HW_Release
- dbgMessagef("\n***** DIRECT SOUND CAPS *****");
- #endif
- if ((dscaps.dwFlags & DSCAPS_CERTIFIED) || useDSound)
- {
- #ifndef HW_Release
- dbgMessagef("\nDriver is CERTIFIED");
- #endif
- bDirectSoundCertified = TRUE;
- }
- else // if (dscaps.dwFlags & DSCAPS_EMULDRIVER)
- {
- #ifndef HW_Release
- dbgMessagef("\nDriver not certified, using WAVEOUT");
- #endif
- lpDirectSound->lpVtbl->Release(lpDirectSound);
- return (SOUND_ERR);
- }
-
- // Succeeded. Try to create buffer.
- if(DS_OK == lpDirectSound->lpVtbl->CreateSoundBuffer(lpDirectSound, &dsbdesc, &lpPrimaryBuffer, NULL))
- {
- // Succeeded. Set primary buffer to desired format.
- if(DS_OK == (lpPrimaryBuffer)->lpVtbl->SetFormat(lpPrimaryBuffer, &waveFormatEX))
- {
- return (SOUND_OK);
- }
- else
- {
- (lpPrimaryBuffer)->lpVtbl->Release(lpPrimaryBuffer);
- }
- }
- }
- else
- {
- lpDirectSound->lpVtbl->Release(lpDirectSound);
- }
- }
- // SetCooperativeLevel failed.
- // CreateSoundBuffer, or SetFormat.
- lpPrimaryBuffer = NULL;
- }
-
- return (SOUND_ERR);
- }
- void soundStopDSound(void)
- {
- HRESULT hr;
- if (bDirectSoundCertified)
- {
- /* shut down DirectSound */
- hr = lpPrimaryBuffer->lpVtbl->Release(lpPrimaryBuffer);
- hr = lpDirectSound->lpVtbl->Release(lpDirectSound);
- }
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword soundinit(HWND hWnd, sdword mode)
- {
- sdword i;
- // clean up the channels
- for (i = 0; i < soundnumvoices; i++)
- {
- channels[i].status = SOUND_FREE;
- }
- // clean up the masterEQ
- for (i = 0; i < FQ_SIZE; i++)
- {
- masterEQ[i] = 1.0;
- }
- mixer.status = SOUND_FREE;
- mixer.timeout = 0;
- streamer.status = SOUND_FREE;
- streamer.timeout = 0;
- // Set up wave format structure.
- memset(&waveFormatEX, 0, sizeof(WAVEFORMATEX));
- waveFormatEX.wFormatTag = WAVE_FORMAT_PCM;
- waveFormatEX.nChannels = 2;
- waveFormatEX.wBitsPerSample = 16;
- waveFormatEX.nSamplesPerSec = FQ_RATE;
- waveFormatEX.nBlockAlign = waveFormatEX.nChannels * (waveFormatEX.wBitsPerSample / 8);
- waveFormatEX.nAvgBytesPerSec = waveFormatEX.nSamplesPerSec * waveFormatEX.nBlockAlign;
- if (soundStartDSound(hWnd) != SOUND_OK)
- {
- // couldn't init DSound so use Waveout instead
- useWaveout = TRUE;
- useDSound = FALSE;
- coopDSound = FALSE;
- bDirectSoundCertified = FALSE;
- }
-
- if (isoundmixerinit(&waveFormatEX) != SOUND_OK)
- {
- soundinited = FALSE;
- return (SOUND_ERR);
- }
- soundinited = TRUE;
-
- return (SOUND_OK);
- }
- sdword soundreinit(HWND hWnd)
- {
- // need to restart Direct Sound
- if (soundStartDSound(hWnd) != SOUND_OK)
- {
- // couldn't init DSound so use Waveout instead
- useWaveout = TRUE;
- useDSound = FALSE;
- coopDSound = FALSE;
- bDirectSoundCertified = FALSE;
- }
-
- if (bDirectSoundCertified)
- {
- // Create the Direct Sound mix buffer
- if (smixCreateDSoundBuffer(&waveFormatEX) != SOUND_OK)
- {
- return (SOUND_ERR);
- }
- }
-
- // Initialize the mix buffer
- if (smixInitMixBuffer(&waveFormatEX) != SOUND_OK)
- {
- return (SOUND_ERR);
- }
- bSoundPaused = FALSE;
- while(mixer.status != SOUND_PLAYING)
- {
- Sleep(0);
- }
- return (SOUND_OK);
- }
- void soundclose(void)
- {
- // do a quick fade out
- soundstopall(SOUND_FADE_STOPALL);
- // shut down the streamer thread
- streamer.timeout = mixerticks + SOUND_FADE_MIXER;
-
- // shut down the mixer thread
- mixer.timeout = mixerticks + SOUND_FADE_MIXER;
-
- bSoundPaused = TRUE;
- while (mixer.status != SOUND_STOPPED)
- {
- musicEventUpdateVolume();
- Sleep(0);
- }
- // reinit the streams
-
- // clean up the mix buffer
- isoundmixerrestore();
- // need to shutdown Direct Sound
- soundStopDSound();
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- void soundrestore(void)
- {
- /* shut down sounds that are still playing */
- soundpause(TRUE);
- soundinited = FALSE;
-
- while (!((streamer.status == SOUND_FREE) && (mixer.status == SOUND_FREE)))
- {
- Sleep(0);
- }
- isoundmixerrestore();
- if (bDirectSoundCertified)
- {
- /* shut down DirectSound */
- lpPrimaryBuffer->lpVtbl->Release(lpPrimaryBuffer);
- lpDirectSound->lpVtbl->Release(lpDirectSound);
- }
- return;
- }
- void soundpause(bool bPause)
- {
- if (soundinited)
- {
- if (bPause)
- {
- mixer.timeout = mixerticks + SOUND_FADE_MIXER;
- streamer.timeout = mixerticks + SOUND_FADE_MIXER;
- }
-
- bSoundPaused = bPause;
- if (bPause)
- {
- soundstopall(SOUND_FADE_STOPALL);
- while (!(mixer.status == SOUND_STOPPED))
- {
- musicEventUpdateVolume();
- Sleep(0);
- }
- }
- }
- }
- void soundstopallSFX(real32 fadetime, bool stopStreams)
- {
- sdword i;
- for (i = 0; i < soundnumvoices; i++)
- {
- if (channels[i].handle > SOUND_DEFAULT)
- {
- soundstop(channels[i].handle, fadetime);
- }
- }
-
- if (stopStreams)
- {
- soundstreamstopall(fadetime);
- }
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sword soundloadpatch(char *pszFileName, sword looped)
- {
- sword nRetVal = SOUND_ERR;
- #if 0
- HMMIO hmmioIn;
- MMCKINFO ckInRiff;
- MMCKINFO ckIn;
- UINT cbActualRead;
- PATCH *newpatch;
- int ret;
- DWORD samples;
- if (!soundinited)
- {
- return (nRetVal);
- }
- newpatch = &patches[numpatches];
- newpatch->pbdata = NULL;
- newpatch->pwfx = NULL;
- newpatch->cbSize = 0;
- newpatch->looped = looped;
- if ((ret = WaveLoadFile(pszFileName, &newpatch->cbSize, &samples, &newpatch->pwfx, &newpatch->pbdata)) != 0)
- {
- dbgMessagef("\nWaveLoadFile failed %d", ret);
- dbgMessagef(" File: %s", pszFileName);
- }
- else
- nRetVal = numpatches++;
-
- return (nRetVal);
-
- if ((ret = WaveOpenFile(pszFileName, &hmmioIn, &newpatch->pwfx, &ckInRiff)) != 0)
- {
- dbgMessagef("\nWaveOpenFile failed %d", ret);
- goto ERROR_LOADING;
- }
- if (WaveStartDataRead(&hmmioIn, &ckIn, &ckInRiff) != 0)
- {
- dbgMessagef("\nWaveStartDataRead failed");
- goto ERROR_LOADING;
- }
- // Ok, size of wave data is in ckIn, allocate that buffer.
- if ((newpatch->pbdata = (BYTE *)GlobalAlloc(GMEM_FIXED, ckIn.cksize)) == NULL)
- {
- dbgMessagef("\nglobalalloc failed");
- goto ERROR_LOADING;
- }
- if (WaveReadFile(hmmioIn, ckIn.cksize, newpatch->pbdata, &ckIn, &cbActualRead) != 0)
- {
- dbgMessagef("\nWaveReadFile failed");
- goto ERROR_LOADING;
- }
-
- newpatch->cbSize = cbActualRead;
- nRetVal = numpatches++;
-
- goto DONE_LOADING;
- ERROR_LOADING:
- if (newpatch->pbdata != NULL)
- {
- GlobalFree(newpatch->pbdata);
- newpatch->pbdata = NULL;
- }
- if (newpatch->pwfx != NULL)
- {
- GlobalFree(newpatch->pwfx);
- newpatch->pwfx = NULL;
- }
-
- DONE_LOADING:
- // Close the wave file.
- if (hmmioIn != NULL)
- {
- mmioClose(hmmioIn, 0);
- hmmioIn = NULL;
- }
- #endif
- return(nRetVal);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- udword soundbankadd(void *bankaddress)
- {
- sword i;
- sdword numpatches;
- /* point the global bank pointer to the bank header */
- bank = (BANK *)bankaddress;
- /* check bank ID */
- numpatches = bank->numpatches;
- /* point the global patches pointer to the start of the patches */
- patches = (PATCH *)&bank->firstpatch;
- /* figure out where the patch data starts */
- for (i = 0; i < numpatches; i++)
- {
- patches[i].dataoffset = (sdword)bankaddress + patches[i].dataoffset;
- patches[i].loopstart += patches[i].dataoffset;
- patches[i].loopend += patches[i].dataoffset;
- patches[i].datasize += patches[i].dataoffset;
- }
- bankpointers[numbanks].start = bankaddress;
- bankpointers[numbanks++].end = (void *)patches[numpatches - 1].datasize;
- return (bank->checksum);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- bool soundover(sdword handle)
- {
- CHANNEL *pchan;
- if (handle < SOUND_OK)
- {
- return (TRUE);
- }
- pchan = &channels[SNDchannel(handle)];
- if (pchan != NULL)
- {
- if (pchan->handle != handle)
- {
- return (TRUE);
- }
-
- if (pchan->status <= SOUND_STOPPED)
- {
- return (TRUE);
- }
-
- return (FALSE);
- }
-
- return (TRUE);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword soundplayFPRVL(sword patnum, real32 freq, sword pan, sdword priority, sword vol, bool startatloop)
- {
- PATCH *ppatch;
- CHANNEL *pchan;
- sdword channel;
- sdword handle = SOUND_ERR;
- sdword i;
- return (SOUND_ERR);
- if (!soundinited)
- {
- return (handle);
- }
-
- if (patnum < 0)
- {
- return (handle);
- }
- if (patnum > bank->numpatches)
- {
- return (handle);
- }
- if (vol == SOUND_DEFAULT)
- {
- vol = SOUND_VOL_MAX;
- }
- if ((vol <= SOUND_VOL_MIN) || (vol > SOUND_VOL_MAX))
- {
- return (handle);
- }
- if (freq == SOUND_DEFAULT)
- {
- freq = 1.0f;
- }
- #ifdef salfreds
- dbgAssert(patnum >= 0);
- #else
- if ((pan < SOUND_PAN_LEFT) || (pan > SOUND_PAN_RIGHT))
- {
- return (handle);
- }
- #endif
- ppatch = &patches[patnum];
- #if 0
- if (ppatch->dataoffset == NULL)
- {
- return (handle);
- }
- #endif
- channel = SNDgetchannel(patnum, priority);
- #ifdef salfreds
- dbgAssert(channel >= 0);
- #else
- if (channel < SOUND_OK)
- {
- return (handle);
- }
- #endif
- /* create handle here */
- handle = SNDcreatehandle(channel);
- pchan = &channels[channel];
- pchan->handle = handle;
- pchan->ppatch = ppatch;
- pchan->volfactorL = (real32)1.0;
- pchan->volfactorR = (real32)1.0;
- pchan->looping = (ppatch->flags & SOUND_FLAGS_LOOPING);
- pchan->pitch = freq;
- pchan->heading = 0;
- pchan->usecardiod = FALSE;
-
- for (i = 0; i < SOUND_EQ_SIZE; i++)
- {
- pchan->filter[i] = 1.0f;
- pchan->cardiodfilter[i] = 1.0f;
- }
- soundvolume(handle, vol);
-
- soundpan(handle, pan);
- SNDcalcvolpan(pchan);
- soundfrequency(handle, freq);
-
- // NEWLOOP
- if (startatloop)
- {
- pchan->currentpos = (sbyte *)ppatch->loopstart;
- }
- else
- {
- pchan->currentpos = (sbyte *)ppatch->dataoffset;
- }
-
- if (ppatch->waveformat.nSamplesPerSec < FQ_RATE)
- {
- pchan->fqsize = FQ_QSIZE;
- }
- else
- {
- pchan->fqsize = FQ_HSIZE;
- }
- #ifdef DEBUG_SOUNDLOW
- if (DS_OK != hr)
- {
- SNDreleasebuffer(pchan);
- dbgMessagef("\nDirectSound error, could not play patch %d",(udword)patnum);
- }
- else
- #endif
- pchan->status = SOUND_PLAYING;
- return (handle);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword soundstop(sdword handle, real32 fadetime)
- {
- CHANNEL *pchan;
- sdword channel;
- sdword fadeblocks = 0;
- if (!soundinited)
- {
- return (SOUND_ERR);
- }
-
- channel = SNDchannel(handle);
- if (channel < SOUND_OK)
- {
- return (SOUND_ERR);
- }
-
- pchan = &channels[channel];
- if (pchan->handle != handle)
- {
- return (SOUND_ERR);
- }
- if (pchan->status == SOUND_FREE)
- {
- return (SOUND_ERR);
- }
- if (pchan != NULL)
- {
- if ((pchan->looping) && (pchan->ppatch->datasize > pchan->ppatch->loopend) && (fadetime > 0.0f))
- {
- pchan->status = SOUND_LOOPEND;
- }
- else
- {
- fadeblocks = (sdword)(fadetime * SOUND_FADE_TIMETOBLOCKS);
-
- if (fadeblocks < NUM_FADE_BLOCKS)
- {
- fadeblocks = NUM_FADE_BLOCKS;
- }
-
- pchan->status = SOUND_STOPPING;
- pchan->voltarget = -1;
- pchan->volticksleft = fadeblocks;
- pchan->volfade = (real32)(pchan->voltarget - pchan->volume) / (real32)pchan->volticksleft;
- if (pchan->volfade == 0.0f)
- {
- pchan->volfade = 0.01f;
- if (pchan->voltarget < pchan->volume)
- {
- pchan->volfade = -0.01f;
- }
- }
- }
- return (SOUND_OK);
- }
- return (SOUND_ERR);
- }
- /*-----------------------------------------------------------------------------
- Name : soundrestart
- Description : If this is a looping sound, it will reset the play pointer
- to the start of the sound.
- Inputs : handle - the handle to a sound returned by soundplay
- Outputs :
- Return : SOUND_OK if successful, SOUND_ERR on error
- ----------------------------------------------------------------------------*/
- sdword soundrestart(sdword handle)
- {
- CHANNEL *pchan;
- sdword channel;
- if (!soundinited)
- {
- channel = SNDchannel(handle);
- if (channel < SOUND_OK)
- {
- pchan = &channels[channel];
- if (pchan != NULL)
- {
- if (pchan->handle != handle)
- {
- return (SOUND_ERR);
- }
- if ((pchan->looping == TRUE) && (pchan->status == SOUND_PLAYING))
- {
- pchan->status = SOUND_RESTART;
- return (SOUND_OK);
- }
- }
- }
- }
- return (SOUND_ERR);
- }
- /*-----------------------------------------------------------------------------
- Name : soundvolume
- Description :
- Inputs : handle - the handle to a sound returned by soundplay
- vol - the volume to set this sound to (range of SOUND_MIN_VOL - SOUND_MAX_VOL)
- Outputs :
- Return : SOUND_OK if successful, SOUND_ERR on error
- ----------------------------------------------------------------------------*/
- sdword soundvolumeF(sdword handle, sword vol, real32 fadetime)
- {
- CHANNEL *pchan;
- sdword channel;
- sdword fadeblocks = 0;
- if (!soundinited)
- {
- return (SOUND_ERR);
- }
-
- if (vol > SOUND_VOL_MAX)
- {
- vol = SOUND_VOL_MAX;
- }
- else if (vol <= SOUND_VOL_MIN)
- {
- soundstop(handle, TRUE);
- return (SOUND_OK);
- }
- channel = SNDchannel(handle);
- if (channel < SOUND_OK)
- {
- return (SOUND_ERR);
- }
- pchan = &channels[channel];
- if (pchan != NULL)
- {
- if (pchan->handle != handle)
- {
- return (SOUND_ERR);
- }
- if (vol != pchan->voltarget)
- {
- if (vol == (sword)pchan->volume)
- {
- pchan->voltarget = vol;
- pchan->volticksleft = 0;
- pchan->volfade = 0.0f;
- }
- else
- {
- fadeblocks = (sdword)(fadetime * SOUND_FADE_TIMETOBLOCKS);
- if (fadeblocks < NUM_FADE_BLOCKS)
- {
- fadeblocks = NUM_FADE_BLOCKS;
- }
- pchan->voltarget = vol;
- pchan->volticksleft = fadeblocks;
- dbgAssert(pchan->volticksleft != 0);
- pchan->volfade = (real32)(pchan->voltarget - pchan->volume) / (real32)pchan->volticksleft;
- if (pchan->volfade == 0.0f)
- {
- pchan->volfade = 0.01f;
- if (pchan->voltarget < pchan->volume)
- {
- pchan->volfade = -0.01f;
- }
- }
- }
- }
- }
- return (SOUND_OK);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword soundpanF(sdword handle, sword pan, real32 fadetime)
- {
- CHANNEL *pchan;
- sdword channel;
- sdword fadeblocks = 0;
- if (!soundinited)
- {
- return (SOUND_ERR);
- }
-
- channel = SNDchannel(handle);
- if (channel < SOUND_OK)
- {
- return (SOUND_ERR);
- }
-
- pchan = &channels[channel];
- if (pchan != NULL)
- {
- if (pchan->handle != handle)
- {
- return (SOUND_ERR);
- }
- if (pan == pchan->pan)
- {
- pchan->pantarget = pan;
- pchan->panticksleft = 0;
- pchan->panfade = 0;
- }
- else
- {
- fadeblocks = (sdword)(fadetime * SOUND_FADE_TIMETOBLOCKS);
- if (fadeblocks < NUM_FADE_BLOCKS)
- {
- fadeblocks = NUM_FADE_BLOCKS;
- }
- pchan->pantarget = pan;
- pchan->panticksleft = fadeblocks;
- pchan->panfade = (pchan->pantarget - pchan->pan) / pchan->panticksleft;
- if (pchan->panfade > 180)
- {
- pchan->panfade -= (pchan->panfade - 180);
- }
- else if (pchan->panfade < -180)
- {
- pchan->panfade -= (pchan->panfade + 180);
- }
- if (pchan->panfade == 0)
- {
- pchan->panfade = 1;
- if (pchan->pantarget < pchan->pan)
- {
- pchan->panfade = -1;
- }
- }
- }
- }
- return (SOUND_OK);
- }
- /*-----------------------------------------------------------------------------
- Name : soundfrequency
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword soundfrequency(sdword handle, real32 freq)
- {
- CHANNEL *pchan;
- sdword channel;
- if (!soundinited)
- {
- return (SOUND_ERR);
- }
-
- channel = SNDchannel(handle);
- if (channel < SOUND_OK)
- {
- return (SOUND_ERR);
- }
- pchan = &channels[channel];
- if (pchan != NULL)
- {
- if (pchan->handle != handle)
- {
- return (SOUND_ERR);
- }
- if (freq != pchan->pitchtarget)
- {
- if (freq == pchan->pitch)
- {
- pchan->pitchtarget = freq;
- pchan->pitchticksleft = 0;
- pchan->pitchfade = 0.0f;
- }
- else
- {
- pchan->pitchtarget = freq;
- pchan->pitchticksleft = NUM_FADE_BLOCKS;
- pchan->pitchfade = (pchan->pitchtarget - pchan->pitch) / pchan->pitchticksleft;
- }
- }
- }
- return (SOUND_OK);
- }
- /*-----------------------------------------------------------------------------
- Name : soundequalize
- Description :
- Inputs : handle - the handle to a sound returned by soundplay
- eq - array[SOUND_EQ_SIZE] of floats range of 0.0 to 1.0
- Outputs :
- Return : SOUND_OK if successful, SOUND_ERR on error
- ----------------------------------------------------------------------------*/
- sdword soundequalize(sdword handle, real32 *eq)
- {
- CHANNEL *pchan;
- sdword channel, i;
- if (!soundinited)
- {
- return (SOUND_ERR);
- }
-
- if (eq == NULL)
- {
- return (SOUND_ERR);
- }
- channel = SNDchannel(handle);
- if (channel < 0)
- {
- return (SOUND_ERR);
- }
- pchan = &channels[channel];
- if (pchan != NULL)
- {
- if (pchan->handle != handle)
- {
- return (SOUND_ERR);
- }
- for (i = 0; i < SOUND_EQ_SIZE; i++)
- {
- pchan->filter[i] = eq[i];
- }
- }
- return (SOUND_OK);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword soundshipheading(sdword handle, sword heading, sdword highband, sdword lowband, real32 velfactor, real32 shipfactor)
- {
- CHANNEL *pchan;
- sdword channel;
- real32 factor;
- real32 inversefactor;
- real32 diff;
- sdword i;
- if (!soundinited)
- {
- return (SOUND_ERR);
- }
-
- channel = SNDchannel(handle);
- if (channel < SOUND_OK)
- {
- return (SOUND_ERR);
- }
- pchan = &channels[channel];
- if (pchan != NULL)
- {
- if (pchan->heading != handle)
- {
- return (SOUND_ERR);
- }
- // if (heading != pchan->heading)
- {
- pchan->heading = heading;
- factor = ((cardiod[heading] - 1.0f) * velfactor * shipfactor + 1.0f);
- inversefactor = ((cardiod[180 - heading] - 1.0f) * velfactor * shipfactor + 1.0f);
- for (i = 0; i < lowband; i++)
- {
- pchan->cardiodfilter[i] = factor;
- }
- diff = (inversefactor - factor) / (highband - lowband);
- for (i = lowband; i < highband; i++)
- {
- pchan->cardiodfilter[i] = factor + (diff * (i - lowband));
- }
- for (i = highband; i < SOUND_EQ_SIZE; i++)
- {
- pchan->cardiodfilter[i] = inversefactor;
- }
- }
- pchan->usecardiod = TRUE;
- }
- return (SOUND_OK);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword SNDresetchannel(CHANNEL *pchan)
- {
- memset(pchan, 0, sizeof(CHANNEL));
- pchan->priority = SOUND_PRIORITY_NORMAL;
- pchan->handle = SOUND_DEFAULT;
- pchan->numchannels = SOUND_MONO;
- pchan->volfactorL = 1.0f;
- pchan->volfactorR = 1.0f;
-
- memset(pchan->filter, 1, SOUND_EQ_SIZE);
- memset(pchan->cardiodfilter, 1, SOUND_EQ_SIZE);
- pchan->usecardiod = FALSE;
- return (SOUND_OK);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword SNDreleasebuffer(CHANNEL *pchan)
- {
- sdword i;
- for (i = 0; i < numbanks; i++)
- {
- if ((bankpointers[i].start <= (void *)pchan->ppatch) &&
- (bankpointers[i].end >= (void *)pchan->ppatch))
- {
- numchans[i]--;
- break;
- }
- }
-
- pchan->handle = SOUND_DEFAULT;
- pchan->ppatch = NULL;
- pchan->status = SOUND_FREE;
- pchan->priority = SOUND_PRIORITY_MIN;
- channelsinuse--;
- return(0);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword SNDgetchannel(sword patchnum, sdword priority)
- {
- CHANNEL *pchan;
- sdword i;
- sdword newchan = 0,
- dupchan = 0;
- sdword channel = SOUND_DEFAULT;
- DWORD dwStatus = 0;
- sdword lowchannel = SOUND_DEFAULT;
- real32 lowvolume = (real32)SOUND_VOL_MAX;
- sdword lowticks = 255;
- sdword lowpriority = priority;
- if ((channelsinuse < soundnumvoices-2) || (priority > SOUND_PRIORITY_MAX)) // Keep at least 2 voices available
- {
- for (i = 0; i < soundnumvoices; i++)
- {
- if (channels[i].status == SOUND_FREE)
- {
- /* found an unused channel */
- channel = i;
- channels[i].status = SOUND_INUSE;
- channels[i].priority = priority;
- channelsinuse++;
- break;
- }
- }
- }
-
- if (channel == SOUND_DEFAULT)
- {
- if (lowpriority < SOUND_PRIORITY_LOW)
- {
- lowpriority = SOUND_PRIORITY_LOW;
- }
- /* find the channel to steal */
- for (i = 0; i < soundnumvoices; i++)
- {
- pchan = &channels[i];
- /* don't want one that is already stopping */
- if (pchan->status == SOUND_PLAYING)
- {
- if (pchan->priority < lowpriority)
- {
- if (pchan->volume <= lowvolume)
- {
- if (pchan->volticksleft <= lowticks)
- {
- lowpriority = pchan->priority;
- lowticks = pchan->volticksleft;
- lowvolume = pchan->volume;
- lowchannel = i;
- }
- }
- }
- }
- }
- if (lowchannel > SOUND_DEFAULT)
- {
- /* stop the sound with the lowest priority */
- soundstop(channels[lowchannel].handle, SOUND_FADE_STOPNOW);
-
- /* find an empty channel */
- for (i = 0; i < soundnumvoices; i++)
- {
- if (channels[i].status == SOUND_FREE)
- {
- /* found an unused channel */
- channel = i;
- channels[i].status = SOUND_INUSE;
- channels[i].priority = priority;
- channelsinuse++;
- break;
- }
- }
- }
- }
-
- return (channel);
- }
- sdword SNDcreatehandle(sdword channel)
- {
- if ((channel > SOUND_MAX_VOICES) || (channel < SOUND_OK))
- {
- return (SOUND_ERR);
- }
- return ((lasthandle++ << 8) + channel);
- }
- sdword SNDchannel(sdword handle)
- {
- sdword channel;
- if (handle < SOUND_OK)
- return (SOUND_ERR);
- channel = handle & 0xFF;
- if ((channel > SOUND_MAX_VOICES) || (channel < SOUND_OK))
- {
- return (SOUND_ERR);
- }
-
- return (channel);
- }
- void SNDcalcvolpan(CHANNEL *pchan)
- {
- pchan->volfactorL = pchan->volfactorR = pchan->volume / (real32)SOUND_VOL_MAX;
-
- if (pchan->pan < SOUND_PAN_CENTER)
- {
- /* panned left so attenuate right */
- pchan->volfactorR *= (real32)(SOUND_PAN_RIGHT + pchan->pan) / SOUND_PAN_RIGHT;
- }
- else if (pchan->pan > SOUND_PAN_CENTER)
- {
- /* panned right so attenuate left */
- pchan->volfactorL *= (real32)(SOUND_PAN_RIGHT - pchan->pan) / SOUND_PAN_RIGHT;
- }
- #if 0
- if (pchan->pan < SOUND_PAN_CENTER)
- {
- pchan->volfactorR *= (real32)((pchan->pan - SOUND_PAN_RIGHT) * -1) / SOUND_PAN_CENTER;
- }
- else if (pchan->pan > SOUND_PAN_CENTER)
- {
- pchan->volfactorL *= (real32)(pchan->pan - SOUND_PAN_LEFT) / SOUND_PAN_CENTER;
- }
- #endif
- if (pchan->volfactorL > (real32)1.0)
- {
- pchan->volfactorL = (real32)1.0;
- }
- if (pchan->volfactorL < (real32)-1.0)
- {
- pchan->volfactorL = (real32)-1.0;
- }
- if (pchan->volfactorR > (real32)1.0)
- {
- pchan->volfactorR = (real32)1.0;
- }
- if (pchan->volfactorR < (real32)-1.0)
- {
- pchan->volfactorR = (real32)-1.0;
- }
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword splayFPRVL(void *bankaddress, sdword patnum, real32 *eq, real32 freq, sword pan, sdword priority, sword vol, bool startatloop, bool fadein, bool mute)
- {
- PATCH *ppatch;
- CHANNEL *pchan;
- sdword channel;
- sdword handle = SOUND_ERR;
- sdword i;
- if (patnum >= SOUND_OK)
- {
- ppatch = SNDgetpatch(bankaddress, patnum);
- }
- else if (patnum == SOUND_FLAGS_PATCHPOINTER)
- {
- /* compare patch ID */
- ppatch = (PATCH *)bankaddress;
- }
- else
- {
- return (handle);
- }
- if (ppatch == NULL)
- {
- return (handle);
- }
- if (vol == SOUND_DEFAULT)
- {
- vol = SOUND_VOL_MAX;
- }
- if ((vol <= SOUND_VOL_MIN) || (vol > SOUND_VOL_MAX))
- {
- return (handle);
- }
- if (freq == SOUND_DEFAULT)
- {
- freq = 1.0f;
- }
- #if 0
- if (ppatch->dataoffset == NULL)
- {
- return (handle);
- }
- #endif
- channel = SNDgetchannel((sword)patnum, priority);
- if (channel < SOUND_OK)
- {
- return (handle);
- }
- /* create handle here */
- handle = SNDcreatehandle(channel);
- for (i = 0; i < numbanks; i++)
- {
- if ((bankpointers[i].start <= (void *)ppatch) &&
- (bankpointers[i].end >= (void *)ppatch))
- {
- numchans[i]++;
- break;
- }
- }
- pchan = &channels[channel];
- SNDresetchannel(pchan);
- pchan->handle = handle;
- pchan->ppatch = ppatch;
- pchan->looping = ppatch->flags;
- pchan->pitch = freq;
- pchan->mute = mute;
- if (eq != NULL)
- {
- for (i = 0; i < SOUND_EQ_SIZE; i++)
- {
- pchan->filter[i] = eq[i];
- }
- }
- else
- {
- for (i = 0; i < SOUND_EQ_SIZE; i++)
- {
- pchan->filter[i] = (real32)1.0;
- }
- }
-
- for (i = 0; i < SOUND_EQ_SIZE; i++)
- {
- pchan->cardiodfilter[i] = 1.0f;
- }
- pchan->usecardiod = FALSE;
- if (!fadein || !pchan->looping)
- {
- pchan->volume = vol;
- }
- soundvolume(handle, vol);
-
- soundpan(handle, pan);
- SNDcalcvolpan(pchan);
- soundfrequency(handle, freq);
-
- // NEWLOOP
- if (startatloop)
- {
- pchan->currentpos = (sbyte *)ppatch->loopstart;
- }
- else
- {
- pchan->currentpos = (sbyte *)ppatch->dataoffset;
- }
-
- if (ppatch->waveformat.nSamplesPerSec < FQ_RATE)
- {
- pchan->fqsize = FQ_QSIZE;
- }
- else
- {
- pchan->fqsize = FQ_HSIZE;
- }
- #ifdef DEBUG_SOUNDLOW
- if (DS_OK != hr)
- {
- SNDreleasebuffer(pchan);
- dbgMessagef("\nDirectSound error, could not play patch %d",(udword)patnum);
- }
- else
- #endif
- pchan->status = SOUND_PLAYING;
- return (handle);
- }
- PATCH *SNDgetpatch(void *bankaddress, sdword patnum)
- {
- PATCH *ppatch = NULL;
- BANK *tempbank;
- PATCH *temppatches;
- if (soundinited)
- {
- if (patnum >= 0)
- {
- tempbank = (BANK *)bankaddress;
- if (patnum < tempbank->numpatches)
- {
- temppatches = (PATCH *)&tempbank->firstpatch;
- ppatch = &temppatches[patnum];
- }
- }
- }
- return (ppatch);
- }
|