PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/quakeforge/trunk/libs/audio/renderer/snd_channels.c

#
C | 715 lines | 569 code | 87 blank | 59 comment | 136 complexity | 6249dec1ab6d6192d802ccc870ef24a3 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, AGPL-3.0, AGPL-1.0, Unlicense
  1. /*
  2. snd_dma.c
  3. main control for any streaming sound output device
  4. Copyright (C) 1996-1997 Id Software, Inc.
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. See the GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to:
  15. Free Software Foundation, Inc.
  16. 59 Temple Place - Suite 330
  17. Boston, MA 02111-1307, USA
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. # include "config.h"
  21. #endif
  22. static __attribute__ ((used)) const char rcsid[] =
  23. "$Id: snd_dma.c 11380 2007-03-10 14:17:52Z taniwha $";
  24. #ifdef HAVE_STRING_H
  25. # include <string.h>
  26. #endif
  27. #ifdef HAVE_STRINGS_H
  28. # include <strings.h>
  29. #endif
  30. #ifdef HAVE_UNISTD_H
  31. # include <unistd.h>
  32. #endif
  33. #include <stdlib.h>
  34. #include "QF/bspfile.h"
  35. #include "QF/cmd.h"
  36. #include "QF/cvar.h"
  37. #include "QF/dstring.h"
  38. #include "QF/model.h"
  39. #include "QF/quakefs.h"
  40. #include "QF/sys.h"
  41. #include "snd_render.h"
  42. static channel_t *free_channels;
  43. channel_t snd_channels[MAX_CHANNELS];
  44. int snd_total_channels;
  45. static channel_t *ambient_channels[NUM_AMBIENTS];
  46. static channel_t *dynamic_channels;
  47. static channel_t *looped_dynamic_channels;
  48. static channel_t *static_channels[MAX_STATIC_CHANNELS];
  49. static int snd_num_statics;
  50. static qboolean snd_ambient = 1;
  51. static sfx_t *ambient_sfx[NUM_AMBIENTS];
  52. static vec_t sound_nominal_clip_dist = 1000.0;
  53. static vec3_t listener_origin;
  54. static vec3_t listener_forward;
  55. static vec3_t listener_right;
  56. static vec3_t listener_up;
  57. static cvar_t *snd_phasesep;
  58. static cvar_t *snd_volumesep;
  59. static cvar_t *ambient_fade;
  60. static cvar_t *ambient_level;
  61. static inline channel_t *
  62. unlink_channel (channel_t **_ch)
  63. {
  64. channel_t *ch = *_ch;
  65. *_ch = ch->next;
  66. ch->next = 0;
  67. return ch;
  68. }
  69. channel_t *
  70. SND_AllocChannel (void)
  71. {
  72. channel_t **free = &free_channels;
  73. channel_t *chan;
  74. while (*free) {
  75. if (!(*free)->sfx) // free channel
  76. break;
  77. if ((*free)->done) // mixer is finished with this channel
  78. break;
  79. if (!(*free)->stop)
  80. Sys_Error ("SND_AllocChannel: bogus channel free list");
  81. free = &(*free)->next;
  82. }
  83. if (!*free) {
  84. int num_free = 0;
  85. for (free = &free_channels; *free; free = &(*free)->next) {
  86. num_free++;
  87. }
  88. Sys_Printf ("SND_AllocChannel: out of channels. %d\n", num_free);
  89. return 0;
  90. }
  91. chan = *free;
  92. *free = chan->next;
  93. if (chan->sfx) {
  94. chan->sfx->release (chan->sfx);
  95. chan->sfx->close (chan->sfx);
  96. chan->sfx = 0; // make sure mixer doesn't use channel during memset
  97. }
  98. memset (chan, 0, sizeof (*chan));
  99. chan->next = 0;
  100. chan->sfx = 0;
  101. return chan;
  102. }
  103. void
  104. SND_ChannelStop (channel_t *chan)
  105. {
  106. /* if chan->next is set, then this channel may have already been freed.
  107. a rather serious bug as it will create a loop in the free list
  108. */
  109. if (chan->next)
  110. Sys_Error ("Stopping a freed channel");
  111. chan->stop = 1;
  112. chan->next = free_channels;
  113. free_channels = chan;
  114. }
  115. void
  116. SND_ScanChannels (int wait)
  117. {
  118. int i;
  119. channel_t *ch;
  120. int count = 0;
  121. if (!snd_shm || !snd_shm->speed)
  122. return;
  123. if (wait) {
  124. Sys_DPrintf ("scanning channels...\n");
  125. do {
  126. count = 0;
  127. for (i = 0; i < MAX_CHANNELS; i++) {
  128. ch = &snd_channels[i];
  129. if (!ch->sfx || ch->done)
  130. continue;
  131. ch->stop = 1;
  132. count++;
  133. }
  134. Sys_DPrintf ("count = %d\n", count);
  135. #ifdef HAVE_USLEEP
  136. usleep (1000);
  137. #endif
  138. } while (count);
  139. Sys_DPrintf ("scanning done.\n");
  140. } else {
  141. for (i = 0; i < MAX_CHANNELS; i++) {
  142. ch = &snd_channels[i];
  143. if (ch->sfx && ch->stop && !ch->done) {
  144. ch->done = 1;
  145. count++;
  146. }
  147. }
  148. //printf ("count: %d\n", count);
  149. }
  150. for (i = 0; i < MAX_CHANNELS; i++) {
  151. ch = &snd_channels[i];
  152. if (!ch->sfx || !ch->done)
  153. continue;
  154. ch->sfx->release (ch->sfx);
  155. ch->sfx->close (ch->sfx);
  156. ch->sfx = 0;
  157. }
  158. }
  159. void
  160. SND_StopAllSounds (void)
  161. {
  162. int i;
  163. snd_num_statics = 0;
  164. while (dynamic_channels)
  165. SND_ChannelStop (unlink_channel (&dynamic_channels));
  166. while (looped_dynamic_channels)
  167. SND_ChannelStop (unlink_channel (&looped_dynamic_channels));
  168. for (i = 0; i < NUM_AMBIENTS; i++) {
  169. if (ambient_channels[i])
  170. SND_ChannelStop (ambient_channels[i]);
  171. ambient_channels[i] = 0;
  172. }
  173. for (i = 0; i < MAX_STATIC_CHANNELS; i++) {
  174. if (static_channels[i])
  175. SND_ChannelStop (static_channels[i]);
  176. static_channels[i] = 0;
  177. }
  178. if (0) {
  179. channel_t *ch;
  180. Sys_Printf ("SND_StopAllSounds\n");
  181. for (i = 0, ch = free_channels; ch; ch = ch->next)
  182. i++;
  183. Sys_Printf (" free channels:%d\n", i);
  184. for (i = 0, ch = free_channels; ch; ch = ch->next)
  185. if (!ch->sfx || ch->done)
  186. i++;
  187. Sys_Printf (" truely free channels:%d\n", i);
  188. }
  189. }
  190. static void
  191. s_play_f (void)
  192. {
  193. dstring_t *name = dstring_new ();
  194. int i;
  195. static int hash = 345;
  196. sfx_t *sfx;
  197. i = 1;
  198. while (i < Cmd_Argc ()) {
  199. if (!strrchr (Cmd_Argv (i), '.')) {
  200. dsprintf (name, "%s.wav", Cmd_Argv (i));
  201. } else {
  202. dsprintf (name, "%s", Cmd_Argv (i));
  203. }
  204. sfx = SND_PrecacheSound (name->str);
  205. SND_StartSound (hash++, 0, sfx, listener_origin, 1.0, 1.0);
  206. i++;
  207. }
  208. dstring_delete (name);
  209. }
  210. static void
  211. s_playcenter_f (void)
  212. {
  213. dstring_t *name = dstring_new ();
  214. int i;
  215. sfx_t *sfx;
  216. i = 1;
  217. while (i < Cmd_Argc ()) {
  218. if (!strrchr (Cmd_Argv (i), '.')) {
  219. dsprintf (name, "%s.wav", Cmd_Argv (i));
  220. } else {
  221. dsprintf (name, "%s", Cmd_Argv (i));
  222. }
  223. sfx = SND_PrecacheSound (name->str);
  224. SND_StartSound (*snd_render_data.viewentity, 0, sfx, listener_origin,
  225. 1.0, 1.0);
  226. i++;
  227. }
  228. dstring_delete (name);
  229. }
  230. static void
  231. s_playvol_f (void)
  232. {
  233. dstring_t *name = dstring_new ();
  234. float vol;
  235. int i;
  236. static int hash = 543;
  237. sfx_t *sfx;
  238. i = 1;
  239. while (i < Cmd_Argc ()) {
  240. if (!strrchr (Cmd_Argv (i), '.')) {
  241. dsprintf (name, "%s.wav", Cmd_Argv (i));
  242. } else {
  243. dsprintf (name, "%s", Cmd_Argv (i));
  244. }
  245. sfx = SND_PrecacheSound (name->str);
  246. vol = atof (Cmd_Argv (i + 1));
  247. SND_StartSound (hash++, 0, sfx, listener_origin, vol, 1.0);
  248. i += 2;
  249. }
  250. dstring_delete (name);
  251. }
  252. static void
  253. s_channels_gamedir (int phase)
  254. {
  255. //FIXME for some reason, a gamedir change causes semi-random
  256. //"already released" cache errors. fortunatly, servers don't change
  257. //gamedir often, so I'll put this in the too-hard basket for now.
  258. if (phase) {
  259. ambient_sfx[AMBIENT_WATER] = SND_PrecacheSound ("ambience/water1.wav");
  260. ambient_sfx[AMBIENT_SKY] = SND_PrecacheSound ("ambience/wind2.wav");
  261. }
  262. }
  263. void
  264. SND_Channels_Init (void)
  265. {
  266. int i;
  267. snd_phasesep = Cvar_Get ("snd_phasesep", "0.0", CVAR_ARCHIVE, NULL,
  268. "max stereo phase separation in ms. 0.6 is for "
  269. "20cm head");
  270. snd_volumesep = Cvar_Get ("snd_volumesep", "1.0", CVAR_ARCHIVE, NULL,
  271. "max stereo volume separation. 1.0 is max");
  272. ambient_fade = Cvar_Get ("ambient_fade", "100", CVAR_NONE, NULL,
  273. "How quickly ambient sounds fade in or out");
  274. ambient_level = Cvar_Get ("ambient_level", "0.3", CVAR_NONE, NULL,
  275. "Ambient sounds' volume");
  276. Cmd_AddCommand ("play", s_play_f,
  277. "Play selected sound effect (play pathto/sound.wav)");
  278. Cmd_AddCommand ("playcenter", s_playcenter_f,
  279. "Play selected sound effect without 3D spatialization.");
  280. Cmd_AddCommand ("playvol", s_playvol_f, "Play selected sound effect at "
  281. "selected volume (playvol pathto/sound.wav num");
  282. for (i = 0; i < MAX_CHANNELS - 1; i++)
  283. snd_channels[i].next = &snd_channels[i + 1];
  284. free_channels = &snd_channels[0];
  285. snd_total_channels = MAX_CHANNELS;
  286. snd_num_statics = 0;
  287. QFS_GamedirCallback (s_channels_gamedir);
  288. }
  289. static channel_t *
  290. s_pick_channel (int entnum, int entchannel, int looped)
  291. {
  292. channel_t *ch, **_ch;
  293. // check for finished non-looped sounds
  294. for (_ch = &dynamic_channels; *_ch; ) {
  295. if (!(*_ch)->sfx || (*_ch)->done) {
  296. SND_ChannelStop (unlink_channel (_ch));
  297. continue;
  298. }
  299. _ch = &(*_ch)->next;
  300. }
  301. // non-looped sounds are used to stop looped sounds on an ent channel
  302. // also clean out any caught by SND_ScanChannels
  303. for (_ch = &looped_dynamic_channels; *_ch; ) {
  304. if (!(*_ch)->sfx || (*_ch)->done
  305. || ((*_ch)->entnum == entnum
  306. && ((*_ch)->entchannel == entchannel || entchannel == -1))) {
  307. SND_ChannelStop (unlink_channel (_ch));
  308. continue;
  309. }
  310. _ch = &(*_ch)->next;
  311. }
  312. _ch = looped ? &looped_dynamic_channels : &dynamic_channels;
  313. if ((ch = SND_AllocChannel ())) {
  314. ch->next = *_ch;
  315. *_ch = ch;
  316. }
  317. return ch;
  318. }
  319. void
  320. SND_AmbientOff (void)
  321. {
  322. snd_ambient = false;
  323. }
  324. void
  325. SND_AmbientOn (void)
  326. {
  327. snd_ambient = true;
  328. }
  329. static void
  330. s_updateAmbientSounds (void)
  331. {
  332. float vol;
  333. int ambient_channel;
  334. channel_t *chan;
  335. sfx_t *sfx;
  336. mleaf_t *l;
  337. if (!snd_ambient)
  338. return;
  339. // calc ambient sound levels
  340. if (!snd_render_data.worldmodel || !*snd_render_data.worldmodel)
  341. return;
  342. l = Mod_PointInLeaf (listener_origin, *snd_render_data.worldmodel);
  343. if (!l || !ambient_level->value) {
  344. // if we're not in a leaf (huh?) or ambients have been turned off,
  345. // stop all ambient channels.
  346. for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
  347. ambient_channel++) {
  348. chan = ambient_channels[ambient_channel];
  349. if (chan) {
  350. chan->master_vol = 0;
  351. chan->leftvol = chan->rightvol = chan->master_vol;
  352. }
  353. }
  354. return;
  355. }
  356. for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
  357. ambient_channel++) {
  358. sfx = ambient_sfx[ambient_channel];
  359. if (!sfx)
  360. continue;
  361. chan = ambient_channels[ambient_channel];
  362. if (!chan) {
  363. chan = ambient_channels[ambient_channel] = SND_AllocChannel ();
  364. if (!chan)
  365. continue;
  366. }
  367. if (!chan->sfx) {
  368. sfx = sfx->open (sfx);
  369. if (!sfx)
  370. continue;
  371. sfx->retain (sfx);
  372. } else {
  373. sfx = chan->sfx;
  374. //sfx->retain (sfx); //FIXME why is this necessary?
  375. }
  376. // sfx will be written to chan->sfx later to ensure mixer doesn't use
  377. // channel prematurely.
  378. vol = ambient_level->value * l->ambient_sound_level[ambient_channel];
  379. if (vol < 8)
  380. vol = 0;
  381. // don't adjust volume too fast
  382. if (chan->master_vol < vol) {
  383. chan->master_vol += *snd_render_data.host_frametime
  384. * ambient_fade->value;
  385. if (chan->master_vol > vol)
  386. chan->master_vol = vol;
  387. } else if (chan->master_vol > vol) {
  388. chan->master_vol -= *snd_render_data.host_frametime
  389. * ambient_fade->value;
  390. if (chan->master_vol < vol)
  391. chan->master_vol = vol;
  392. }
  393. chan->leftvol = chan->rightvol = chan->master_vol;
  394. chan->sfx = sfx;
  395. }
  396. }
  397. static void
  398. s_spatialize (channel_t *ch)
  399. {
  400. int phase; // in samples
  401. vec_t dist, dot, lscale, rscale, scale;
  402. vec3_t source_vec;
  403. // prepare to lerp from prev to next phase
  404. ch->oldphase = ch->phase;
  405. // anything coming from the view entity will always be full volume
  406. if (!snd_render_data.viewentity
  407. || ch->entnum == *snd_render_data.viewentity) {
  408. ch->leftvol = ch->master_vol;
  409. ch->rightvol = ch->master_vol;
  410. ch->phase = 0;
  411. return;
  412. }
  413. // calculate stereo seperation and distance attenuation
  414. VectorSubtract (ch->origin, listener_origin, source_vec);
  415. dist = VectorNormalize (source_vec) * ch->dist_mult;
  416. dot = DotProduct (listener_right, source_vec);
  417. if (snd_shm->channels == 1) {
  418. rscale = 1.0;
  419. lscale = 1.0;
  420. phase = 0;
  421. } else {
  422. rscale = 1.0 + dot * snd_volumesep->value;
  423. lscale = 1.0 - dot * snd_volumesep->value;
  424. phase = snd_phasesep->value * 0.001 * snd_shm->speed * dot;
  425. }
  426. // add in distance effect
  427. scale = (1.0 - dist) * rscale;
  428. ch->rightvol = (int) (ch->master_vol * scale);
  429. if (ch->rightvol < 0)
  430. ch->rightvol = 0;
  431. scale = (1.0 - dist) * lscale;
  432. ch->leftvol = (int) (ch->master_vol * scale);
  433. if (ch->leftvol < 0)
  434. ch->leftvol = 0;
  435. ch->phase = phase;
  436. }
  437. static inline int
  438. s_update_channel (channel_t *ch)
  439. {
  440. if (!ch->sfx)
  441. return 0;
  442. s_spatialize (ch); // respatialize channel
  443. if (!ch->leftvol && !ch->rightvol)
  444. return 0;
  445. return 1;
  446. }
  447. static void
  448. s_combine_channel (channel_t *combine, channel_t *ch)
  449. {
  450. combine->leftvol += ch->leftvol;
  451. combine->rightvol += ch->rightvol;
  452. ch->leftvol = ch->rightvol = 0;
  453. }
  454. void
  455. SND_SetListener (const vec3_t origin, const vec3_t forward, const vec3_t right,
  456. const vec3_t up)
  457. {
  458. int i, j;
  459. channel_t *combine, *ch;
  460. VectorCopy (origin, listener_origin);
  461. VectorCopy (forward, listener_forward);
  462. VectorCopy (right, listener_right);
  463. VectorCopy (up, listener_up);
  464. // update general area ambient sound sources
  465. s_updateAmbientSounds ();
  466. // update spatialization for dynamic sounds
  467. for (ch = dynamic_channels; ch; ch = ch->next)
  468. s_update_channel (ch);
  469. for (ch = looped_dynamic_channels; ch; ch = ch->next)
  470. s_update_channel (ch);
  471. // update spatialization for static sounds
  472. combine = 0;
  473. for (i = 0; i < snd_num_statics; i++) {
  474. ch = static_channels[i];
  475. if (!s_update_channel (ch))
  476. continue;
  477. // try to combine static sounds with a previous channel of the same
  478. // sound effect so we don't mix five torches every frame
  479. // see if it can just use the last one
  480. if (combine && combine->sfx == ch->sfx) {
  481. s_combine_channel (combine, ch);
  482. continue;
  483. }
  484. // search for one
  485. for (j = 0; j < i; j++) {
  486. combine = static_channels[j];
  487. if (combine->sfx == ch->sfx)
  488. break;
  489. }
  490. if (j == i) {
  491. combine = 0;
  492. } else {
  493. if (combine != ch)
  494. s_combine_channel (combine, ch);
  495. continue;
  496. }
  497. }
  498. }
  499. static int
  500. snd_check_channels (channel_t *target_chan, const channel_t *check,
  501. const sfx_t *osfx)
  502. {
  503. if (!check || check == target_chan)
  504. return 0;
  505. if (check->sfx->owner == osfx->owner && !check->pos) {
  506. int skip = rand () % (int) (0.01 * snd_shm->speed);
  507. target_chan->pos = -skip;
  508. return 1;
  509. }
  510. return 0;
  511. }
  512. void
  513. SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
  514. float fvol, float attenuation)
  515. {
  516. int vol;
  517. int looped;
  518. channel_t *target_chan, *check;
  519. sfx_t *osfx;
  520. if (!sfx || !snd_shm->speed)
  521. return;
  522. // pick a channel to play on
  523. looped = sfx->loopstart != (unsigned) -1;
  524. target_chan = s_pick_channel (entnum, entchannel, looped);
  525. if (!target_chan)
  526. return;
  527. vol = fvol * 255;
  528. // spatialize
  529. VectorCopy (origin, target_chan->origin);
  530. target_chan->dist_mult = attenuation / sound_nominal_clip_dist;
  531. target_chan->master_vol = vol;
  532. target_chan->entnum = entnum;
  533. target_chan->entchannel = entchannel;
  534. s_spatialize (target_chan);
  535. // new channel
  536. if (!(osfx = sfx->open (sfx))) {
  537. SND_ChannelStop (unlink_channel (looped ? &looped_dynamic_channels
  538. : &dynamic_channels));
  539. return;
  540. }
  541. target_chan->pos = 0;
  542. target_chan->end = 0;
  543. // if an identical sound has also been started this frame, offset the pos
  544. // a bit to keep it from just making the first one louder
  545. for (check = dynamic_channels; check; check = check->next)
  546. if (snd_check_channels (target_chan, check, osfx))
  547. break;
  548. for (check = looped_dynamic_channels; check; check = check->next)
  549. if (snd_check_channels (target_chan, check, osfx))
  550. break;
  551. if (!osfx->retain (osfx)) {
  552. SND_ChannelStop (unlink_channel (looped ? &looped_dynamic_channels
  553. : &dynamic_channels));
  554. return; // couldn't load the sound's data
  555. }
  556. target_chan->sfx = osfx;
  557. }
  558. static int
  559. s_check_stop (channel_t **_ch, int entnum, int entchannel)
  560. {
  561. if ((*_ch)->entnum == entnum && (*_ch)->entchannel == entchannel) {
  562. SND_ChannelStop (unlink_channel (_ch));
  563. return 1;
  564. }
  565. return 0;
  566. }
  567. void
  568. SND_StopSound (int entnum, int entchannel)
  569. {
  570. channel_t **_ch;
  571. for (_ch = &dynamic_channels; *_ch; )
  572. if (!s_check_stop (_ch, entnum, entchannel))
  573. _ch = &(*_ch)->next;
  574. for (_ch = &looped_dynamic_channels; *_ch; )
  575. if (!s_check_stop (_ch, entnum, entchannel))
  576. _ch = &(*_ch)->next;
  577. }
  578. void
  579. SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
  580. float attenuation)
  581. {
  582. channel_t *ss;
  583. sfx_t *osfx;
  584. if (!sfx)
  585. return;
  586. if (sfx->loopstart == (unsigned int) -1) {
  587. Sys_Printf ("Sound %s not looped\n", sfx->name);
  588. return;
  589. }
  590. if (!static_channels[snd_num_statics]) {
  591. if (!(static_channels[snd_num_statics] = SND_AllocChannel ())) {
  592. Sys_Printf ("ran out of channels\n");
  593. return;
  594. }
  595. }
  596. ss = static_channels[snd_num_statics];
  597. if (!(osfx = sfx->open (sfx)))
  598. return;
  599. VectorCopy (origin, ss->origin);
  600. ss->master_vol = vol;
  601. ss->dist_mult = (attenuation / 64) / sound_nominal_clip_dist;
  602. ss->end = 0;
  603. s_spatialize (ss);
  604. ss->oldphase = ss->phase;
  605. if (!osfx->retain (osfx))
  606. return;
  607. snd_num_statics++;
  608. ss->sfx = osfx;
  609. }
  610. void
  611. SND_LocalSound (const char *sound)
  612. {
  613. sfx_t *sfx;
  614. sfx = SND_PrecacheSound (sound);
  615. if (!sfx) {
  616. Sys_Printf ("S_LocalSound: can't cache %s\n", sound);
  617. return;
  618. }
  619. SND_StartSound (*snd_render_data.viewentity, -1, sfx, vec3_origin, 1, 1);
  620. }