soundlow.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662
  1. /*=============================================================================
  2. Name : SoundLow.c
  3. Purpose : Low level sound routines
  4. Created 7/24/1997 by gshaw
  5. Copyright Relic Entertainment, Inc. All rights reserved.
  6. =============================================================================*/
  7. #define WIN32_LEAN_AND_MEAN
  8. #include <windows.h>
  9. #include <mmsystem.h>
  10. #include <string.h>
  11. #include <dsound.h>
  12. #include "switches.h"
  13. #include "debug.h"
  14. #include "soundlow.h"
  15. #include "file.h"
  16. #include "soundcmn.h"
  17. #include "main.h"
  18. #define SOUNDFXDIR "SoundFX\\"
  19. #define EQ_STEP 0.1
  20. typedef struct
  21. {
  22. void *start;
  23. void *end;
  24. } BANKPOINTERS;
  25. /* function in speechevent.c that needs to be called when shutting down */
  26. void musicEventUpdateVolume(void);
  27. /* internal functions */
  28. sdword SNDgetchannel(sword patchnum, sdword priority);
  29. /* variables */
  30. CHANNEL channels[SOUND_MAX_VOICES];
  31. sword numpatches = 0;
  32. LPDIRECTSOUND lpDirectSound = NULL;
  33. LPDIRECTSOUNDBUFFER lpPrimaryBuffer = NULL;
  34. sdword lasthandle = 0;
  35. bool soundinited = FALSE;
  36. BANK *bank;
  37. PATCH *patches;
  38. sdword channelsinuse = 0;
  39. bool bDirectSoundCertified = FALSE;
  40. real32 masterEQ[FQ_SIZE];
  41. bool bSoundPaused = FALSE;
  42. bool bSoundDeactivated = FALSE;
  43. WAVEFORMATEX waveFormatEX;
  44. sdword numbanks = 0;
  45. sdword numchans[4] = {0,0,0,0};
  46. BANKPOINTERS bankpointers[4];
  47. SOUNDCOMPONENT mixer;
  48. SOUNDCOMPONENT streamer;
  49. sdword soundnumvoices=SOUND_DEF_VOICES;
  50. sdword soundvoicemode=SOUND_MODE_NORM; // voice panic mode, normal by default
  51. //streamprintfunction debugfunction = NULL;
  52. //char debugtext[256];
  53. extern HWND ghMainWindow;
  54. extern real32 cardiod[];
  55. extern udword mixerticks;
  56. // Get the min and max number of voices
  57. void soundGetVoiceLimits(sdword *min,sdword *max)
  58. {
  59. *min=SOUND_MIN_VOICES;
  60. *max=SOUND_MAX_VOICES;
  61. return;
  62. }
  63. // Get the current number of voices and mode
  64. void soundGetNumVoices(sdword *num,sdword *mode)
  65. {
  66. *num=soundnumvoices;
  67. *mode=soundvoicemode;
  68. return;
  69. }
  70. // Set the current number of voices and mode
  71. void soundSetNumVoices(sdword num,sdword mode)
  72. {
  73. if(num < SOUND_MIN_VOICES) num=SOUND_MIN_VOICES;
  74. if(num > SOUND_MAX_VOICES) num=SOUND_MAX_VOICES;
  75. soundnumvoices=num;
  76. soundvoicemode=mode;
  77. return;
  78. }
  79. // Shut down necessary channels for panic
  80. void soundPanic(void)
  81. {
  82. CHANNEL *pchan;
  83. sdword i;
  84. sdword lowchannel;
  85. real32 lowvolume;
  86. sdword lowticks;
  87. sdword lowpriority;
  88. while(channelsinuse > soundnumvoices)
  89. {
  90. lowpriority = SOUND_PRIORITY_LOW;
  91. lowticks = 255;
  92. lowvolume = (real32)SOUND_VOL_MAX;
  93. lowchannel = SOUND_DEFAULT;
  94. /* find the channel to steal */
  95. for (i = 0; i < SOUND_MAX_VOICES; i++)
  96. {
  97. pchan = &channels[i];
  98. /* don't want one that is already stopping */
  99. if (pchan->status == SOUND_PLAYING)
  100. {
  101. if (pchan->priority < lowpriority)
  102. {
  103. if (pchan->volume <= lowvolume)
  104. {
  105. if (pchan->volticksleft <= lowticks)
  106. {
  107. lowpriority = pchan->priority;
  108. lowticks = pchan->volticksleft;
  109. lowvolume = pchan->volume;
  110. lowchannel = i;
  111. }
  112. }
  113. }
  114. }
  115. }
  116. if (lowchannel > SOUND_DEFAULT)
  117. {
  118. /* stop the sound with the lowest priority */
  119. soundstop(channels[lowchannel].handle, SOUND_FADE_STOPNOW);
  120. }
  121. else
  122. {
  123. break;
  124. }
  125. }
  126. return;
  127. }
  128. // Called by main.c on before and after[Alt]-[Tab]
  129. void sounddeactivate(bool bDeactivate)
  130. {
  131. /* set flag */
  132. if (soundinited)
  133. {
  134. bSoundDeactivated=bDeactivate;
  135. }
  136. /* reset panic mode */
  137. soundPanicReset(); // mixer.c
  138. }
  139. /*-----------------------------------------------------------------------------
  140. Name :
  141. Description :
  142. Inputs :
  143. Outputs :
  144. Return :
  145. ----------------------------------------------------------------------------*/
  146. real32 soundusage(void)
  147. {
  148. return ((real32)channelsinuse / SOUND_MAX_VOICES);
  149. }
  150. /*-----------------------------------------------------------------------------
  151. Name :
  152. Description :
  153. Inputs :
  154. Outputs :
  155. Return :
  156. ----------------------------------------------------------------------------*/
  157. void soundupdate(void)
  158. {
  159. return;
  160. }
  161. sdword soundStartDSound(HWND hWnd)
  162. {
  163. DSBUFFERDESC dsbdesc;
  164. DSCAPS dscaps;
  165. HRESULT hr;
  166. if (useWaveout)
  167. {
  168. return (SOUND_ERR);
  169. }
  170. if(DS_OK == DirectSoundCreate(NULL, &lpDirectSound, NULL))
  171. {
  172. // Set up DSBUFFERDESC structure.
  173. memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
  174. dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  175. dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
  176. // Buffer size is determined by sound hardware.
  177. dsbdesc.dwBufferBytes = 0;
  178. dsbdesc.lpwfxFormat = NULL; // Must be NULL for primary buffers.
  179. if (coopDSound)
  180. {
  181. // Try to set in priority mode so Homeworld will share the wave device
  182. hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, hWnd, DSSCL_PRIORITY);
  183. if (hr != DS_OK)
  184. {
  185. // Hmmm, couldn't set priority so lets try exclusive
  186. hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, hWnd, DSSCL_EXCLUSIVE);
  187. }
  188. }
  189. else
  190. {
  191. // Try to set in Exclusive mode
  192. hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, hWnd, DSSCL_EXCLUSIVE);
  193. if (hr != DS_OK)
  194. {
  195. // maybe something already has the wave device so lets try sharing it?
  196. hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, hWnd, DSSCL_PRIORITY);
  197. }
  198. }
  199. if(hr == DS_OK)
  200. {
  201. // Get direct sound Caps.
  202. dscaps.dwSize = sizeof(DSCAPS);
  203. if (DS_OK == lpDirectSound->lpVtbl->GetCaps(lpDirectSound, &dscaps))
  204. {
  205. #ifndef HW_Release
  206. dbgMessagef("\n***** DIRECT SOUND CAPS *****");
  207. #endif
  208. if ((dscaps.dwFlags & DSCAPS_CERTIFIED) || useDSound)
  209. {
  210. #ifndef HW_Release
  211. dbgMessagef("\nDriver is CERTIFIED");
  212. #endif
  213. bDirectSoundCertified = TRUE;
  214. }
  215. else // if (dscaps.dwFlags & DSCAPS_EMULDRIVER)
  216. {
  217. #ifndef HW_Release
  218. dbgMessagef("\nDriver not certified, using WAVEOUT");
  219. #endif
  220. lpDirectSound->lpVtbl->Release(lpDirectSound);
  221. return (SOUND_ERR);
  222. }
  223. // Succeeded. Try to create buffer.
  224. if(DS_OK == lpDirectSound->lpVtbl->CreateSoundBuffer(lpDirectSound, &dsbdesc, &lpPrimaryBuffer, NULL))
  225. {
  226. // Succeeded. Set primary buffer to desired format.
  227. if(DS_OK == (lpPrimaryBuffer)->lpVtbl->SetFormat(lpPrimaryBuffer, &waveFormatEX))
  228. {
  229. return (SOUND_OK);
  230. }
  231. else
  232. {
  233. (lpPrimaryBuffer)->lpVtbl->Release(lpPrimaryBuffer);
  234. }
  235. }
  236. }
  237. else
  238. {
  239. lpDirectSound->lpVtbl->Release(lpDirectSound);
  240. }
  241. }
  242. // SetCooperativeLevel failed.
  243. // CreateSoundBuffer, or SetFormat.
  244. lpPrimaryBuffer = NULL;
  245. }
  246. return (SOUND_ERR);
  247. }
  248. void soundStopDSound(void)
  249. {
  250. HRESULT hr;
  251. if (bDirectSoundCertified)
  252. {
  253. /* shut down DirectSound */
  254. hr = lpPrimaryBuffer->lpVtbl->Release(lpPrimaryBuffer);
  255. hr = lpDirectSound->lpVtbl->Release(lpDirectSound);
  256. }
  257. }
  258. /*-----------------------------------------------------------------------------
  259. Name :
  260. Description :
  261. Inputs :
  262. Outputs :
  263. Return :
  264. ----------------------------------------------------------------------------*/
  265. sdword soundinit(HWND hWnd, sdword mode)
  266. {
  267. sdword i;
  268. // clean up the channels
  269. for (i = 0; i < soundnumvoices; i++)
  270. {
  271. channels[i].status = SOUND_FREE;
  272. }
  273. // clean up the masterEQ
  274. for (i = 0; i < FQ_SIZE; i++)
  275. {
  276. masterEQ[i] = 1.0;
  277. }
  278. mixer.status = SOUND_FREE;
  279. mixer.timeout = 0;
  280. streamer.status = SOUND_FREE;
  281. streamer.timeout = 0;
  282. // Set up wave format structure.
  283. memset(&waveFormatEX, 0, sizeof(WAVEFORMATEX));
  284. waveFormatEX.wFormatTag = WAVE_FORMAT_PCM;
  285. waveFormatEX.nChannels = 2;
  286. waveFormatEX.wBitsPerSample = 16;
  287. waveFormatEX.nSamplesPerSec = FQ_RATE;
  288. waveFormatEX.nBlockAlign = waveFormatEX.nChannels * (waveFormatEX.wBitsPerSample / 8);
  289. waveFormatEX.nAvgBytesPerSec = waveFormatEX.nSamplesPerSec * waveFormatEX.nBlockAlign;
  290. if (soundStartDSound(hWnd) != SOUND_OK)
  291. {
  292. // couldn't init DSound so use Waveout instead
  293. useWaveout = TRUE;
  294. useDSound = FALSE;
  295. coopDSound = FALSE;
  296. bDirectSoundCertified = FALSE;
  297. }
  298. if (isoundmixerinit(&waveFormatEX) != SOUND_OK)
  299. {
  300. soundinited = FALSE;
  301. return (SOUND_ERR);
  302. }
  303. soundinited = TRUE;
  304. return (SOUND_OK);
  305. }
  306. sdword soundreinit(HWND hWnd)
  307. {
  308. // need to restart Direct Sound
  309. if (soundStartDSound(hWnd) != SOUND_OK)
  310. {
  311. // couldn't init DSound so use Waveout instead
  312. useWaveout = TRUE;
  313. useDSound = FALSE;
  314. coopDSound = FALSE;
  315. bDirectSoundCertified = FALSE;
  316. }
  317. if (bDirectSoundCertified)
  318. {
  319. // Create the Direct Sound mix buffer
  320. if (smixCreateDSoundBuffer(&waveFormatEX) != SOUND_OK)
  321. {
  322. return (SOUND_ERR);
  323. }
  324. }
  325. // Initialize the mix buffer
  326. if (smixInitMixBuffer(&waveFormatEX) != SOUND_OK)
  327. {
  328. return (SOUND_ERR);
  329. }
  330. bSoundPaused = FALSE;
  331. while(mixer.status != SOUND_PLAYING)
  332. {
  333. Sleep(0);
  334. }
  335. return (SOUND_OK);
  336. }
  337. void soundclose(void)
  338. {
  339. // do a quick fade out
  340. soundstopall(SOUND_FADE_STOPALL);
  341. // shut down the streamer thread
  342. streamer.timeout = mixerticks + SOUND_FADE_MIXER;
  343. // shut down the mixer thread
  344. mixer.timeout = mixerticks + SOUND_FADE_MIXER;
  345. bSoundPaused = TRUE;
  346. while (mixer.status != SOUND_STOPPED)
  347. {
  348. musicEventUpdateVolume();
  349. Sleep(0);
  350. }
  351. // reinit the streams
  352. // clean up the mix buffer
  353. isoundmixerrestore();
  354. // need to shutdown Direct Sound
  355. soundStopDSound();
  356. }
  357. /*-----------------------------------------------------------------------------
  358. Name :
  359. Description :
  360. Inputs :
  361. Outputs :
  362. Return :
  363. ----------------------------------------------------------------------------*/
  364. void soundrestore(void)
  365. {
  366. /* shut down sounds that are still playing */
  367. soundpause(TRUE);
  368. soundinited = FALSE;
  369. while (!((streamer.status == SOUND_FREE) && (mixer.status == SOUND_FREE)))
  370. {
  371. Sleep(0);
  372. }
  373. isoundmixerrestore();
  374. if (bDirectSoundCertified)
  375. {
  376. /* shut down DirectSound */
  377. lpPrimaryBuffer->lpVtbl->Release(lpPrimaryBuffer);
  378. lpDirectSound->lpVtbl->Release(lpDirectSound);
  379. }
  380. return;
  381. }
  382. void soundpause(bool bPause)
  383. {
  384. if (soundinited)
  385. {
  386. if (bPause)
  387. {
  388. mixer.timeout = mixerticks + SOUND_FADE_MIXER;
  389. streamer.timeout = mixerticks + SOUND_FADE_MIXER;
  390. }
  391. bSoundPaused = bPause;
  392. if (bPause)
  393. {
  394. soundstopall(SOUND_FADE_STOPALL);
  395. while (!(mixer.status == SOUND_STOPPED))
  396. {
  397. musicEventUpdateVolume();
  398. Sleep(0);
  399. }
  400. }
  401. }
  402. }
  403. void soundstopallSFX(real32 fadetime, bool stopStreams)
  404. {
  405. sdword i;
  406. for (i = 0; i < soundnumvoices; i++)
  407. {
  408. if (channels[i].handle > SOUND_DEFAULT)
  409. {
  410. soundstop(channels[i].handle, fadetime);
  411. }
  412. }
  413. if (stopStreams)
  414. {
  415. soundstreamstopall(fadetime);
  416. }
  417. }
  418. /*-----------------------------------------------------------------------------
  419. Name :
  420. Description :
  421. Inputs :
  422. Outputs :
  423. Return :
  424. ----------------------------------------------------------------------------*/
  425. sword soundloadpatch(char *pszFileName, sword looped)
  426. {
  427. sword nRetVal = SOUND_ERR;
  428. #if 0
  429. HMMIO hmmioIn;
  430. MMCKINFO ckInRiff;
  431. MMCKINFO ckIn;
  432. UINT cbActualRead;
  433. PATCH *newpatch;
  434. int ret;
  435. DWORD samples;
  436. if (!soundinited)
  437. {
  438. return (nRetVal);
  439. }
  440. newpatch = &patches[numpatches];
  441. newpatch->pbdata = NULL;
  442. newpatch->pwfx = NULL;
  443. newpatch->cbSize = 0;
  444. newpatch->looped = looped;
  445. if ((ret = WaveLoadFile(pszFileName, &newpatch->cbSize, &samples, &newpatch->pwfx, &newpatch->pbdata)) != 0)
  446. {
  447. dbgMessagef("\nWaveLoadFile failed %d", ret);
  448. dbgMessagef(" File: %s", pszFileName);
  449. }
  450. else
  451. nRetVal = numpatches++;
  452. return (nRetVal);
  453. if ((ret = WaveOpenFile(pszFileName, &hmmioIn, &newpatch->pwfx, &ckInRiff)) != 0)
  454. {
  455. dbgMessagef("\nWaveOpenFile failed %d", ret);
  456. goto ERROR_LOADING;
  457. }
  458. if (WaveStartDataRead(&hmmioIn, &ckIn, &ckInRiff) != 0)
  459. {
  460. dbgMessagef("\nWaveStartDataRead failed");
  461. goto ERROR_LOADING;
  462. }
  463. // Ok, size of wave data is in ckIn, allocate that buffer.
  464. if ((newpatch->pbdata = (BYTE *)GlobalAlloc(GMEM_FIXED, ckIn.cksize)) == NULL)
  465. {
  466. dbgMessagef("\nglobalalloc failed");
  467. goto ERROR_LOADING;
  468. }
  469. if (WaveReadFile(hmmioIn, ckIn.cksize, newpatch->pbdata, &ckIn, &cbActualRead) != 0)
  470. {
  471. dbgMessagef("\nWaveReadFile failed");
  472. goto ERROR_LOADING;
  473. }
  474. newpatch->cbSize = cbActualRead;
  475. nRetVal = numpatches++;
  476. goto DONE_LOADING;
  477. ERROR_LOADING:
  478. if (newpatch->pbdata != NULL)
  479. {
  480. GlobalFree(newpatch->pbdata);
  481. newpatch->pbdata = NULL;
  482. }
  483. if (newpatch->pwfx != NULL)
  484. {
  485. GlobalFree(newpatch->pwfx);
  486. newpatch->pwfx = NULL;
  487. }
  488. DONE_LOADING:
  489. // Close the wave file.
  490. if (hmmioIn != NULL)
  491. {
  492. mmioClose(hmmioIn, 0);
  493. hmmioIn = NULL;
  494. }
  495. #endif
  496. return(nRetVal);
  497. }
  498. /*-----------------------------------------------------------------------------
  499. Name :
  500. Description :
  501. Inputs :
  502. Outputs :
  503. Return :
  504. ----------------------------------------------------------------------------*/
  505. udword soundbankadd(void *bankaddress)
  506. {
  507. sword i;
  508. sdword numpatches;
  509. /* point the global bank pointer to the bank header */
  510. bank = (BANK *)bankaddress;
  511. /* check bank ID */
  512. numpatches = bank->numpatches;
  513. /* point the global patches pointer to the start of the patches */
  514. patches = (PATCH *)&bank->firstpatch;
  515. /* figure out where the patch data starts */
  516. for (i = 0; i < numpatches; i++)
  517. {
  518. patches[i].dataoffset = (sdword)bankaddress + patches[i].dataoffset;
  519. patches[i].loopstart += patches[i].dataoffset;
  520. patches[i].loopend += patches[i].dataoffset;
  521. patches[i].datasize += patches[i].dataoffset;
  522. }
  523. bankpointers[numbanks].start = bankaddress;
  524. bankpointers[numbanks++].end = (void *)patches[numpatches - 1].datasize;
  525. return (bank->checksum);
  526. }
  527. /*-----------------------------------------------------------------------------
  528. Name :
  529. Description :
  530. Inputs :
  531. Outputs :
  532. Return :
  533. ----------------------------------------------------------------------------*/
  534. bool soundover(sdword handle)
  535. {
  536. CHANNEL *pchan;
  537. if (handle < SOUND_OK)
  538. {
  539. return (TRUE);
  540. }
  541. pchan = &channels[SNDchannel(handle)];
  542. if (pchan != NULL)
  543. {
  544. if (pchan->handle != handle)
  545. {
  546. return (TRUE);
  547. }
  548. if (pchan->status <= SOUND_STOPPED)
  549. {
  550. return (TRUE);
  551. }
  552. return (FALSE);
  553. }
  554. return (TRUE);
  555. }
  556. /*-----------------------------------------------------------------------------
  557. Name :
  558. Description :
  559. Inputs :
  560. Outputs :
  561. Return :
  562. ----------------------------------------------------------------------------*/
  563. sdword soundplayFPRVL(sword patnum, real32 freq, sword pan, sdword priority, sword vol, bool startatloop)
  564. {
  565. PATCH *ppatch;
  566. CHANNEL *pchan;
  567. sdword channel;
  568. sdword handle = SOUND_ERR;
  569. sdword i;
  570. return (SOUND_ERR);
  571. if (!soundinited)
  572. {
  573. return (handle);
  574. }
  575. if (patnum < 0)
  576. {
  577. return (handle);
  578. }
  579. if (patnum > bank->numpatches)
  580. {
  581. return (handle);
  582. }
  583. if (vol == SOUND_DEFAULT)
  584. {
  585. vol = SOUND_VOL_MAX;
  586. }
  587. if ((vol <= SOUND_VOL_MIN) || (vol > SOUND_VOL_MAX))
  588. {
  589. return (handle);
  590. }
  591. if (freq == SOUND_DEFAULT)
  592. {
  593. freq = 1.0f;
  594. }
  595. #ifdef salfreds
  596. dbgAssert(patnum >= 0);
  597. #else
  598. if ((pan < SOUND_PAN_LEFT) || (pan > SOUND_PAN_RIGHT))
  599. {
  600. return (handle);
  601. }
  602. #endif
  603. ppatch = &patches[patnum];
  604. #if 0
  605. if (ppatch->dataoffset == NULL)
  606. {
  607. return (handle);
  608. }
  609. #endif
  610. channel = SNDgetchannel(patnum, priority);
  611. #ifdef salfreds
  612. dbgAssert(channel >= 0);
  613. #else
  614. if (channel < SOUND_OK)
  615. {
  616. return (handle);
  617. }
  618. #endif
  619. /* create handle here */
  620. handle = SNDcreatehandle(channel);
  621. pchan = &channels[channel];
  622. pchan->handle = handle;
  623. pchan->ppatch = ppatch;
  624. pchan->volfactorL = (real32)1.0;
  625. pchan->volfactorR = (real32)1.0;
  626. pchan->looping = (ppatch->flags & SOUND_FLAGS_LOOPING);
  627. pchan->pitch = freq;
  628. pchan->heading = 0;
  629. pchan->usecardiod = FALSE;
  630. for (i = 0; i < SOUND_EQ_SIZE; i++)
  631. {
  632. pchan->filter[i] = 1.0f;
  633. pchan->cardiodfilter[i] = 1.0f;
  634. }
  635. soundvolume(handle, vol);
  636. soundpan(handle, pan);
  637. SNDcalcvolpan(pchan);
  638. soundfrequency(handle, freq);
  639. // NEWLOOP
  640. if (startatloop)
  641. {
  642. pchan->currentpos = (sbyte *)ppatch->loopstart;
  643. }
  644. else
  645. {
  646. pchan->currentpos = (sbyte *)ppatch->dataoffset;
  647. }
  648. if (ppatch->waveformat.nSamplesPerSec < FQ_RATE)
  649. {
  650. pchan->fqsize = FQ_QSIZE;
  651. }
  652. else
  653. {
  654. pchan->fqsize = FQ_HSIZE;
  655. }
  656. #ifdef DEBUG_SOUNDLOW
  657. if (DS_OK != hr)
  658. {
  659. SNDreleasebuffer(pchan);
  660. dbgMessagef("\nDirectSound error, could not play patch %d",(udword)patnum);
  661. }
  662. else
  663. #endif
  664. pchan->status = SOUND_PLAYING;
  665. return (handle);
  666. }
  667. /*-----------------------------------------------------------------------------
  668. Name :
  669. Description :
  670. Inputs :
  671. Outputs :
  672. Return :
  673. ----------------------------------------------------------------------------*/
  674. sdword soundstop(sdword handle, real32 fadetime)
  675. {
  676. CHANNEL *pchan;
  677. sdword channel;
  678. sdword fadeblocks = 0;
  679. if (!soundinited)
  680. {
  681. return (SOUND_ERR);
  682. }
  683. channel = SNDchannel(handle);
  684. if (channel < SOUND_OK)
  685. {
  686. return (SOUND_ERR);
  687. }
  688. pchan = &channels[channel];
  689. if (pchan->handle != handle)
  690. {
  691. return (SOUND_ERR);
  692. }
  693. if (pchan->status == SOUND_FREE)
  694. {
  695. return (SOUND_ERR);
  696. }
  697. if (pchan != NULL)
  698. {
  699. if ((pchan->looping) && (pchan->ppatch->datasize > pchan->ppatch->loopend) && (fadetime > 0.0f))
  700. {
  701. pchan->status = SOUND_LOOPEND;
  702. }
  703. else
  704. {
  705. fadeblocks = (sdword)(fadetime * SOUND_FADE_TIMETOBLOCKS);
  706. if (fadeblocks < NUM_FADE_BLOCKS)
  707. {
  708. fadeblocks = NUM_FADE_BLOCKS;
  709. }
  710. pchan->status = SOUND_STOPPING;
  711. pchan->voltarget = -1;
  712. pchan->volticksleft = fadeblocks;
  713. pchan->volfade = (real32)(pchan->voltarget - pchan->volume) / (real32)pchan->volticksleft;
  714. if (pchan->volfade == 0.0f)
  715. {
  716. pchan->volfade = 0.01f;
  717. if (pchan->voltarget < pchan->volume)
  718. {
  719. pchan->volfade = -0.01f;
  720. }
  721. }
  722. }
  723. return (SOUND_OK);
  724. }
  725. return (SOUND_ERR);
  726. }
  727. /*-----------------------------------------------------------------------------
  728. Name : soundrestart
  729. Description : If this is a looping sound, it will reset the play pointer
  730. to the start of the sound.
  731. Inputs : handle - the handle to a sound returned by soundplay
  732. Outputs :
  733. Return : SOUND_OK if successful, SOUND_ERR on error
  734. ----------------------------------------------------------------------------*/
  735. sdword soundrestart(sdword handle)
  736. {
  737. CHANNEL *pchan;
  738. sdword channel;
  739. if (!soundinited)
  740. {
  741. channel = SNDchannel(handle);
  742. if (channel < SOUND_OK)
  743. {
  744. pchan = &channels[channel];
  745. if (pchan != NULL)
  746. {
  747. if (pchan->handle != handle)
  748. {
  749. return (SOUND_ERR);
  750. }
  751. if ((pchan->looping == TRUE) && (pchan->status == SOUND_PLAYING))
  752. {
  753. pchan->status = SOUND_RESTART;
  754. return (SOUND_OK);
  755. }
  756. }
  757. }
  758. }
  759. return (SOUND_ERR);
  760. }
  761. /*-----------------------------------------------------------------------------
  762. Name : soundvolume
  763. Description :
  764. Inputs : handle - the handle to a sound returned by soundplay
  765. vol - the volume to set this sound to (range of SOUND_MIN_VOL - SOUND_MAX_VOL)
  766. Outputs :
  767. Return : SOUND_OK if successful, SOUND_ERR on error
  768. ----------------------------------------------------------------------------*/
  769. sdword soundvolumeF(sdword handle, sword vol, real32 fadetime)
  770. {
  771. CHANNEL *pchan;
  772. sdword channel;
  773. sdword fadeblocks = 0;
  774. if (!soundinited)
  775. {
  776. return (SOUND_ERR);
  777. }
  778. if (vol > SOUND_VOL_MAX)
  779. {
  780. vol = SOUND_VOL_MAX;
  781. }
  782. else if (vol <= SOUND_VOL_MIN)
  783. {
  784. soundstop(handle, TRUE);
  785. return (SOUND_OK);
  786. }
  787. channel = SNDchannel(handle);
  788. if (channel < SOUND_OK)
  789. {
  790. return (SOUND_ERR);
  791. }
  792. pchan = &channels[channel];
  793. if (pchan != NULL)
  794. {
  795. if (pchan->handle != handle)
  796. {
  797. return (SOUND_ERR);
  798. }
  799. if (vol != pchan->voltarget)
  800. {
  801. if (vol == (sword)pchan->volume)
  802. {
  803. pchan->voltarget = vol;
  804. pchan->volticksleft = 0;
  805. pchan->volfade = 0.0f;
  806. }
  807. else
  808. {
  809. fadeblocks = (sdword)(fadetime * SOUND_FADE_TIMETOBLOCKS);
  810. if (fadeblocks < NUM_FADE_BLOCKS)
  811. {
  812. fadeblocks = NUM_FADE_BLOCKS;
  813. }
  814. pchan->voltarget = vol;
  815. pchan->volticksleft = fadeblocks;
  816. dbgAssert(pchan->volticksleft != 0);
  817. pchan->volfade = (real32)(pchan->voltarget - pchan->volume) / (real32)pchan->volticksleft;
  818. if (pchan->volfade == 0.0f)
  819. {
  820. pchan->volfade = 0.01f;
  821. if (pchan->voltarget < pchan->volume)
  822. {
  823. pchan->volfade = -0.01f;
  824. }
  825. }
  826. }
  827. }
  828. }
  829. return (SOUND_OK);
  830. }
  831. /*-----------------------------------------------------------------------------
  832. Name :
  833. Description :
  834. Inputs :
  835. Outputs :
  836. Return :
  837. ----------------------------------------------------------------------------*/
  838. sdword soundpanF(sdword handle, sword pan, real32 fadetime)
  839. {
  840. CHANNEL *pchan;
  841. sdword channel;
  842. sdword fadeblocks = 0;
  843. if (!soundinited)
  844. {
  845. return (SOUND_ERR);
  846. }
  847. channel = SNDchannel(handle);
  848. if (channel < SOUND_OK)
  849. {
  850. return (SOUND_ERR);
  851. }
  852. pchan = &channels[channel];
  853. if (pchan != NULL)
  854. {
  855. if (pchan->handle != handle)
  856. {
  857. return (SOUND_ERR);
  858. }
  859. if (pan == pchan->pan)
  860. {
  861. pchan->pantarget = pan;
  862. pchan->panticksleft = 0;
  863. pchan->panfade = 0;
  864. }
  865. else
  866. {
  867. fadeblocks = (sdword)(fadetime * SOUND_FADE_TIMETOBLOCKS);
  868. if (fadeblocks < NUM_FADE_BLOCKS)
  869. {
  870. fadeblocks = NUM_FADE_BLOCKS;
  871. }
  872. pchan->pantarget = pan;
  873. pchan->panticksleft = fadeblocks;
  874. pchan->panfade = (pchan->pantarget - pchan->pan) / pchan->panticksleft;
  875. if (pchan->panfade > 180)
  876. {
  877. pchan->panfade -= (pchan->panfade - 180);
  878. }
  879. else if (pchan->panfade < -180)
  880. {
  881. pchan->panfade -= (pchan->panfade + 180);
  882. }
  883. if (pchan->panfade == 0)
  884. {
  885. pchan->panfade = 1;
  886. if (pchan->pantarget < pchan->pan)
  887. {
  888. pchan->panfade = -1;
  889. }
  890. }
  891. }
  892. }
  893. return (SOUND_OK);
  894. }
  895. /*-----------------------------------------------------------------------------
  896. Name : soundfrequency
  897. Description :
  898. Inputs :
  899. Outputs :
  900. Return :
  901. ----------------------------------------------------------------------------*/
  902. sdword soundfrequency(sdword handle, real32 freq)
  903. {
  904. CHANNEL *pchan;
  905. sdword channel;
  906. if (!soundinited)
  907. {
  908. return (SOUND_ERR);
  909. }
  910. channel = SNDchannel(handle);
  911. if (channel < SOUND_OK)
  912. {
  913. return (SOUND_ERR);
  914. }
  915. pchan = &channels[channel];
  916. if (pchan != NULL)
  917. {
  918. if (pchan->handle != handle)
  919. {
  920. return (SOUND_ERR);
  921. }
  922. if (freq != pchan->pitchtarget)
  923. {
  924. if (freq == pchan->pitch)
  925. {
  926. pchan->pitchtarget = freq;
  927. pchan->pitchticksleft = 0;
  928. pchan->pitchfade = 0.0f;
  929. }
  930. else
  931. {
  932. pchan->pitchtarget = freq;
  933. pchan->pitchticksleft = NUM_FADE_BLOCKS;
  934. pchan->pitchfade = (pchan->pitchtarget - pchan->pitch) / pchan->pitchticksleft;
  935. }
  936. }
  937. }
  938. return (SOUND_OK);
  939. }
  940. /*-----------------------------------------------------------------------------
  941. Name : soundequalize
  942. Description :
  943. Inputs : handle - the handle to a sound returned by soundplay
  944. eq - array[SOUND_EQ_SIZE] of floats range of 0.0 to 1.0
  945. Outputs :
  946. Return : SOUND_OK if successful, SOUND_ERR on error
  947. ----------------------------------------------------------------------------*/
  948. sdword soundequalize(sdword handle, real32 *eq)
  949. {
  950. CHANNEL *pchan;
  951. sdword channel, i;
  952. if (!soundinited)
  953. {
  954. return (SOUND_ERR);
  955. }
  956. if (eq == NULL)
  957. {
  958. return (SOUND_ERR);
  959. }
  960. channel = SNDchannel(handle);
  961. if (channel < 0)
  962. {
  963. return (SOUND_ERR);
  964. }
  965. pchan = &channels[channel];
  966. if (pchan != NULL)
  967. {
  968. if (pchan->handle != handle)
  969. {
  970. return (SOUND_ERR);
  971. }
  972. for (i = 0; i < SOUND_EQ_SIZE; i++)
  973. {
  974. pchan->filter[i] = eq[i];
  975. }
  976. }
  977. return (SOUND_OK);
  978. }
  979. /*-----------------------------------------------------------------------------
  980. Name :
  981. Description :
  982. Inputs :
  983. Outputs :
  984. Return :
  985. ----------------------------------------------------------------------------*/
  986. sdword soundshipheading(sdword handle, sword heading, sdword highband, sdword lowband, real32 velfactor, real32 shipfactor)
  987. {
  988. CHANNEL *pchan;
  989. sdword channel;
  990. real32 factor;
  991. real32 inversefactor;
  992. real32 diff;
  993. sdword i;
  994. if (!soundinited)
  995. {
  996. return (SOUND_ERR);
  997. }
  998. channel = SNDchannel(handle);
  999. if (channel < SOUND_OK)
  1000. {
  1001. return (SOUND_ERR);
  1002. }
  1003. pchan = &channels[channel];
  1004. if (pchan != NULL)
  1005. {
  1006. if (pchan->heading != handle)
  1007. {
  1008. return (SOUND_ERR);
  1009. }
  1010. // if (heading != pchan->heading)
  1011. {
  1012. pchan->heading = heading;
  1013. factor = ((cardiod[heading] - 1.0f) * velfactor * shipfactor + 1.0f);
  1014. inversefactor = ((cardiod[180 - heading] - 1.0f) * velfactor * shipfactor + 1.0f);
  1015. for (i = 0; i < lowband; i++)
  1016. {
  1017. pchan->cardiodfilter[i] = factor;
  1018. }
  1019. diff = (inversefactor - factor) / (highband - lowband);
  1020. for (i = lowband; i < highband; i++)
  1021. {
  1022. pchan->cardiodfilter[i] = factor + (diff * (i - lowband));
  1023. }
  1024. for (i = highband; i < SOUND_EQ_SIZE; i++)
  1025. {
  1026. pchan->cardiodfilter[i] = inversefactor;
  1027. }
  1028. }
  1029. pchan->usecardiod = TRUE;
  1030. }
  1031. return (SOUND_OK);
  1032. }
  1033. /*-----------------------------------------------------------------------------
  1034. Name :
  1035. Description :
  1036. Inputs :
  1037. Outputs :
  1038. Return :
  1039. ----------------------------------------------------------------------------*/
  1040. sdword SNDresetchannel(CHANNEL *pchan)
  1041. {
  1042. memset(pchan, 0, sizeof(CHANNEL));
  1043. pchan->priority = SOUND_PRIORITY_NORMAL;
  1044. pchan->handle = SOUND_DEFAULT;
  1045. pchan->numchannels = SOUND_MONO;
  1046. pchan->volfactorL = 1.0f;
  1047. pchan->volfactorR = 1.0f;
  1048. memset(pchan->filter, 1, SOUND_EQ_SIZE);
  1049. memset(pchan->cardiodfilter, 1, SOUND_EQ_SIZE);
  1050. pchan->usecardiod = FALSE;
  1051. return (SOUND_OK);
  1052. }
  1053. /*-----------------------------------------------------------------------------
  1054. Name :
  1055. Description :
  1056. Inputs :
  1057. Outputs :
  1058. Return :
  1059. ----------------------------------------------------------------------------*/
  1060. sdword SNDreleasebuffer(CHANNEL *pchan)
  1061. {
  1062. sdword i;
  1063. for (i = 0; i < numbanks; i++)
  1064. {
  1065. if ((bankpointers[i].start <= (void *)pchan->ppatch) &&
  1066. (bankpointers[i].end >= (void *)pchan->ppatch))
  1067. {
  1068. numchans[i]--;
  1069. break;
  1070. }
  1071. }
  1072. pchan->handle = SOUND_DEFAULT;
  1073. pchan->ppatch = NULL;
  1074. pchan->status = SOUND_FREE;
  1075. pchan->priority = SOUND_PRIORITY_MIN;
  1076. channelsinuse--;
  1077. return(0);
  1078. }
  1079. /*-----------------------------------------------------------------------------
  1080. Name :
  1081. Description :
  1082. Inputs :
  1083. Outputs :
  1084. Return :
  1085. ----------------------------------------------------------------------------*/
  1086. sdword SNDgetchannel(sword patchnum, sdword priority)
  1087. {
  1088. CHANNEL *pchan;
  1089. sdword i;
  1090. sdword newchan = 0,
  1091. dupchan = 0;
  1092. sdword channel = SOUND_DEFAULT;
  1093. DWORD dwStatus = 0;
  1094. sdword lowchannel = SOUND_DEFAULT;
  1095. real32 lowvolume = (real32)SOUND_VOL_MAX;
  1096. sdword lowticks = 255;
  1097. sdword lowpriority = priority;
  1098. if ((channelsinuse < soundnumvoices-2) || (priority > SOUND_PRIORITY_MAX)) // Keep at least 2 voices available
  1099. {
  1100. for (i = 0; i < soundnumvoices; i++)
  1101. {
  1102. if (channels[i].status == SOUND_FREE)
  1103. {
  1104. /* found an unused channel */
  1105. channel = i;
  1106. channels[i].status = SOUND_INUSE;
  1107. channels[i].priority = priority;
  1108. channelsinuse++;
  1109. break;
  1110. }
  1111. }
  1112. }
  1113. if (channel == SOUND_DEFAULT)
  1114. {
  1115. if (lowpriority < SOUND_PRIORITY_LOW)
  1116. {
  1117. lowpriority = SOUND_PRIORITY_LOW;
  1118. }
  1119. /* find the channel to steal */
  1120. for (i = 0; i < soundnumvoices; i++)
  1121. {
  1122. pchan = &channels[i];
  1123. /* don't want one that is already stopping */
  1124. if (pchan->status == SOUND_PLAYING)
  1125. {
  1126. if (pchan->priority < lowpriority)
  1127. {
  1128. if (pchan->volume <= lowvolume)
  1129. {
  1130. if (pchan->volticksleft <= lowticks)
  1131. {
  1132. lowpriority = pchan->priority;
  1133. lowticks = pchan->volticksleft;
  1134. lowvolume = pchan->volume;
  1135. lowchannel = i;
  1136. }
  1137. }
  1138. }
  1139. }
  1140. }
  1141. if (lowchannel > SOUND_DEFAULT)
  1142. {
  1143. /* stop the sound with the lowest priority */
  1144. soundstop(channels[lowchannel].handle, SOUND_FADE_STOPNOW);
  1145. /* find an empty channel */
  1146. for (i = 0; i < soundnumvoices; i++)
  1147. {
  1148. if (channels[i].status == SOUND_FREE)
  1149. {
  1150. /* found an unused channel */
  1151. channel = i;
  1152. channels[i].status = SOUND_INUSE;
  1153. channels[i].priority = priority;
  1154. channelsinuse++;
  1155. break;
  1156. }
  1157. }
  1158. }
  1159. }
  1160. return (channel);
  1161. }
  1162. sdword SNDcreatehandle(sdword channel)
  1163. {
  1164. if ((channel > SOUND_MAX_VOICES) || (channel < SOUND_OK))
  1165. {
  1166. return (SOUND_ERR);
  1167. }
  1168. return ((lasthandle++ << 8) + channel);
  1169. }
  1170. sdword SNDchannel(sdword handle)
  1171. {
  1172. sdword channel;
  1173. if (handle < SOUND_OK)
  1174. return (SOUND_ERR);
  1175. channel = handle & 0xFF;
  1176. if ((channel > SOUND_MAX_VOICES) || (channel < SOUND_OK))
  1177. {
  1178. return (SOUND_ERR);
  1179. }
  1180. return (channel);
  1181. }
  1182. void SNDcalcvolpan(CHANNEL *pchan)
  1183. {
  1184. pchan->volfactorL = pchan->volfactorR = pchan->volume / (real32)SOUND_VOL_MAX;
  1185. if (pchan->pan < SOUND_PAN_CENTER)
  1186. {
  1187. /* panned left so attenuate right */
  1188. pchan->volfactorR *= (real32)(SOUND_PAN_RIGHT + pchan->pan) / SOUND_PAN_RIGHT;
  1189. }
  1190. else if (pchan->pan > SOUND_PAN_CENTER)
  1191. {
  1192. /* panned right so attenuate left */
  1193. pchan->volfactorL *= (real32)(SOUND_PAN_RIGHT - pchan->pan) / SOUND_PAN_RIGHT;
  1194. }
  1195. #if 0
  1196. if (pchan->pan < SOUND_PAN_CENTER)
  1197. {
  1198. pchan->volfactorR *= (real32)((pchan->pan - SOUND_PAN_RIGHT) * -1) / SOUND_PAN_CENTER;
  1199. }
  1200. else if (pchan->pan > SOUND_PAN_CENTER)
  1201. {
  1202. pchan->volfactorL *= (real32)(pchan->pan - SOUND_PAN_LEFT) / SOUND_PAN_CENTER;
  1203. }
  1204. #endif
  1205. if (pchan->volfactorL > (real32)1.0)
  1206. {
  1207. pchan->volfactorL = (real32)1.0;
  1208. }
  1209. if (pchan->volfactorL < (real32)-1.0)
  1210. {
  1211. pchan->volfactorL = (real32)-1.0;
  1212. }
  1213. if (pchan->volfactorR > (real32)1.0)
  1214. {
  1215. pchan->volfactorR = (real32)1.0;
  1216. }
  1217. if (pchan->volfactorR < (real32)-1.0)
  1218. {
  1219. pchan->volfactorR = (real32)-1.0;
  1220. }
  1221. }
  1222. /*-----------------------------------------------------------------------------
  1223. Name :
  1224. Description :
  1225. Inputs :
  1226. Outputs :
  1227. Return :
  1228. ----------------------------------------------------------------------------*/
  1229. sdword splayFPRVL(void *bankaddress, sdword patnum, real32 *eq, real32 freq, sword pan, sdword priority, sword vol, bool startatloop, bool fadein, bool mute)
  1230. {
  1231. PATCH *ppatch;
  1232. CHANNEL *pchan;
  1233. sdword channel;
  1234. sdword handle = SOUND_ERR;
  1235. sdword i;
  1236. if (patnum >= SOUND_OK)
  1237. {
  1238. ppatch = SNDgetpatch(bankaddress, patnum);
  1239. }
  1240. else if (patnum == SOUND_FLAGS_PATCHPOINTER)
  1241. {
  1242. /* compare patch ID */
  1243. ppatch = (PATCH *)bankaddress;
  1244. }
  1245. else
  1246. {
  1247. return (handle);
  1248. }
  1249. if (ppatch == NULL)
  1250. {
  1251. return (handle);
  1252. }
  1253. if (vol == SOUND_DEFAULT)
  1254. {
  1255. vol = SOUND_VOL_MAX;
  1256. }
  1257. if ((vol <= SOUND_VOL_MIN) || (vol > SOUND_VOL_MAX))
  1258. {
  1259. return (handle);
  1260. }
  1261. if (freq == SOUND_DEFAULT)
  1262. {
  1263. freq = 1.0f;
  1264. }
  1265. #if 0
  1266. if (ppatch->dataoffset == NULL)
  1267. {
  1268. return (handle);
  1269. }
  1270. #endif
  1271. channel = SNDgetchannel((sword)patnum, priority);
  1272. if (channel < SOUND_OK)
  1273. {
  1274. return (handle);
  1275. }
  1276. /* create handle here */
  1277. handle = SNDcreatehandle(channel);
  1278. for (i = 0; i < numbanks; i++)
  1279. {
  1280. if ((bankpointers[i].start <= (void *)ppatch) &&
  1281. (bankpointers[i].end >= (void *)ppatch))
  1282. {
  1283. numchans[i]++;
  1284. break;
  1285. }
  1286. }
  1287. pchan = &channels[channel];
  1288. SNDresetchannel(pchan);
  1289. pchan->handle = handle;
  1290. pchan->ppatch = ppatch;
  1291. pchan->looping = ppatch->flags;
  1292. pchan->pitch = freq;
  1293. pchan->mute = mute;
  1294. if (eq != NULL)
  1295. {
  1296. for (i = 0; i < SOUND_EQ_SIZE; i++)
  1297. {
  1298. pchan->filter[i] = eq[i];
  1299. }
  1300. }
  1301. else
  1302. {
  1303. for (i = 0; i < SOUND_EQ_SIZE; i++)
  1304. {
  1305. pchan->filter[i] = (real32)1.0;
  1306. }
  1307. }
  1308. for (i = 0; i < SOUND_EQ_SIZE; i++)
  1309. {
  1310. pchan->cardiodfilter[i] = 1.0f;
  1311. }
  1312. pchan->usecardiod = FALSE;
  1313. if (!fadein || !pchan->looping)
  1314. {
  1315. pchan->volume = vol;
  1316. }
  1317. soundvolume(handle, vol);
  1318. soundpan(handle, pan);
  1319. SNDcalcvolpan(pchan);
  1320. soundfrequency(handle, freq);
  1321. // NEWLOOP
  1322. if (startatloop)
  1323. {
  1324. pchan->currentpos = (sbyte *)ppatch->loopstart;
  1325. }
  1326. else
  1327. {
  1328. pchan->currentpos = (sbyte *)ppatch->dataoffset;
  1329. }
  1330. if (ppatch->waveformat.nSamplesPerSec < FQ_RATE)
  1331. {
  1332. pchan->fqsize = FQ_QSIZE;
  1333. }
  1334. else
  1335. {
  1336. pchan->fqsize = FQ_HSIZE;
  1337. }
  1338. #ifdef DEBUG_SOUNDLOW
  1339. if (DS_OK != hr)
  1340. {
  1341. SNDreleasebuffer(pchan);
  1342. dbgMessagef("\nDirectSound error, could not play patch %d",(udword)patnum);
  1343. }
  1344. else
  1345. #endif
  1346. pchan->status = SOUND_PLAYING;
  1347. return (handle);
  1348. }
  1349. PATCH *SNDgetpatch(void *bankaddress, sdword patnum)
  1350. {
  1351. PATCH *ppatch = NULL;
  1352. BANK *tempbank;
  1353. PATCH *temppatches;
  1354. if (soundinited)
  1355. {
  1356. if (patnum >= 0)
  1357. {
  1358. tempbank = (BANK *)bankaddress;
  1359. if (patnum < tempbank->numpatches)
  1360. {
  1361. temppatches = (PATCH *)&tempbank->firstpatch;
  1362. ppatch = &temppatches[patnum];
  1363. }
  1364. }
  1365. }
  1366. return (ppatch);
  1367. }