i_sound.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. // Emacs style mode select -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. // System interface for sound.
  21. //
  22. //-----------------------------------------------------------------------------
  23. static const char
  24. rcsid[] = "$Id: i_unix.c,v 1.5 1997/02/03 22:45:10 b1 Exp $";
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <stdarg.h>
  28. #include <math.h>
  29. #include <sys/time.h>
  30. #include <sys/types.h>
  31. #ifndef LINUX
  32. #include <sys/filio.h>
  33. #endif
  34. #include <fcntl.h>
  35. #include <unistd.h>
  36. #include <sys/ioctl.h>
  37. // Linux voxware output.
  38. #include <linux/soundcard.h>
  39. // Timer stuff. Experimental.
  40. #include <time.h>
  41. #include <signal.h>
  42. #include "z_zone.h"
  43. #include "i_system.h"
  44. #include "i_sound.h"
  45. #include "m_argv.h"
  46. #include "m_misc.h"
  47. #include "w_wad.h"
  48. #include "doomdef.h"
  49. // UNIX hack, to be removed.
  50. #ifdef SNDSERV
  51. // Separate sound server process.
  52. FILE* sndserver=0;
  53. char* sndserver_filename = "./sndserver ";
  54. #elif SNDINTR
  55. // Update all 30 millisecs, approx. 30fps synchronized.
  56. // Linux resolution is allegedly 10 millisecs,
  57. // scale is microseconds.
  58. #define SOUND_INTERVAL 500
  59. // Get the interrupt. Set duration in millisecs.
  60. int I_SoundSetTimer( int duration_of_tick );
  61. void I_SoundDelTimer( void );
  62. #else
  63. // None?
  64. #endif
  65. // A quick hack to establish a protocol between
  66. // synchronous mix buffer updates and asynchronous
  67. // audio writes. Probably redundant with gametic.
  68. static int flag = 0;
  69. // The number of internal mixing channels,
  70. // the samples calculated for each mixing step,
  71. // the size of the 16bit, 2 hardware channel (stereo)
  72. // mixing buffer, and the samplerate of the raw data.
  73. // Needed for calling the actual sound output.
  74. #define SAMPLECOUNT 512
  75. #define NUM_CHANNELS 8
  76. // It is 2 for 16bit, and 2 for two channels.
  77. #define BUFMUL 4
  78. #define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL)
  79. #define SAMPLERATE 11025 // Hz
  80. #define SAMPLESIZE 2 // 16bit
  81. // The actual lengths of all sound effects.
  82. int lengths[NUMSFX];
  83. // The actual output device.
  84. int audio_fd;
  85. // The global mixing buffer.
  86. // Basically, samples from all active internal channels
  87. // are modifed and added, and stored in the buffer
  88. // that is submitted to the audio device.
  89. signed short mixbuffer[MIXBUFFERSIZE];
  90. // The channel step amount...
  91. unsigned int channelstep[NUM_CHANNELS];
  92. // ... and a 0.16 bit remainder of last step.
  93. unsigned int channelstepremainder[NUM_CHANNELS];
  94. // The channel data pointers, start and end.
  95. unsigned char* channels[NUM_CHANNELS];
  96. unsigned char* channelsend[NUM_CHANNELS];
  97. // Time/gametic that the channel started playing,
  98. // used to determine oldest, which automatically
  99. // has lowest priority.
  100. // In case number of active sounds exceeds
  101. // available channels.
  102. int channelstart[NUM_CHANNELS];
  103. // The sound in channel handles,
  104. // determined on registration,
  105. // might be used to unregister/stop/modify,
  106. // currently unused.
  107. int channelhandles[NUM_CHANNELS];
  108. // SFX id of the playing sound effect.
  109. // Used to catch duplicates (like chainsaw).
  110. int channelids[NUM_CHANNELS];
  111. // Pitch to stepping lookup, unused.
  112. int steptable[256];
  113. // Volume lookups.
  114. int vol_lookup[128*256];
  115. // Hardware left and right channel volume lookup.
  116. int* channelleftvol_lookup[NUM_CHANNELS];
  117. int* channelrightvol_lookup[NUM_CHANNELS];
  118. //
  119. // Safe ioctl, convenience.
  120. //
  121. void
  122. myioctl
  123. ( int fd,
  124. int command,
  125. int* arg )
  126. {
  127. int rc;
  128. extern int errno;
  129. rc = ioctl(fd, command, arg);
  130. if (rc < 0)
  131. {
  132. fprintf(stderr, "ioctl(dsp,%d,arg) failed\n", command);
  133. fprintf(stderr, "errno=%d\n", errno);
  134. exit(-1);
  135. }
  136. }
  137. //
  138. // This function loads the sound data from the WAD lump,
  139. // for single sound.
  140. //
  141. void*
  142. getsfx
  143. ( char* sfxname,
  144. int* len )
  145. {
  146. unsigned char* sfx;
  147. unsigned char* paddedsfx;
  148. int i;
  149. int size;
  150. int paddedsize;
  151. char name[20];
  152. int sfxlump;
  153. // Get the sound data from the WAD, allocate lump
  154. // in zone memory.
  155. sprintf(name, "ds%s", sfxname);
  156. // Now, there is a severe problem with the
  157. // sound handling, in it is not (yet/anymore)
  158. // gamemode aware. That means, sounds from
  159. // DOOM II will be requested even with DOOM
  160. // shareware.
  161. // The sound list is wired into sounds.c,
  162. // which sets the external variable.
  163. // I do not do runtime patches to that
  164. // variable. Instead, we will use a
  165. // default sound for replacement.
  166. if ( W_CheckNumForName(name) == -1 )
  167. sfxlump = W_GetNumForName("dspistol");
  168. else
  169. sfxlump = W_GetNumForName(name);
  170. size = W_LumpLength( sfxlump );
  171. // Debug.
  172. // fprintf( stderr, "." );
  173. //fprintf( stderr, " -loading %s (lump %d, %d bytes)\n",
  174. // sfxname, sfxlump, size );
  175. //fflush( stderr );
  176. sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_STATIC );
  177. // Pads the sound effect out to the mixing buffer size.
  178. // The original realloc would interfere with zone memory.
  179. paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT;
  180. // Allocate from zone memory.
  181. paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 );
  182. // ddt: (unsigned char *) realloc(sfx, paddedsize+8);
  183. // This should interfere with zone memory handling,
  184. // which does not kick in in the soundserver.
  185. // Now copy and pad.
  186. memcpy( paddedsfx, sfx, size );
  187. for (i=size ; i<paddedsize+8 ; i++)
  188. paddedsfx[i] = 128;
  189. // Remove the cached lump.
  190. Z_Free( sfx );
  191. // Preserve padded length.
  192. *len = paddedsize;
  193. // Return allocated padded data.
  194. return (void *) (paddedsfx + 8);
  195. }
  196. //
  197. // This function adds a sound to the
  198. // list of currently active sounds,
  199. // which is maintained as a given number
  200. // (eight, usually) of internal channels.
  201. // Returns a handle.
  202. //
  203. int
  204. addsfx
  205. ( int sfxid,
  206. int volume,
  207. int step,
  208. int seperation )
  209. {
  210. static unsigned short handlenums = 0;
  211. int i;
  212. int rc = -1;
  213. int oldest = gametic;
  214. int oldestnum = 0;
  215. int slot;
  216. int rightvol;
  217. int leftvol;
  218. // Chainsaw troubles.
  219. // Play these sound effects only one at a time.
  220. if ( sfxid == sfx_sawup
  221. || sfxid == sfx_sawidl
  222. || sfxid == sfx_sawful
  223. || sfxid == sfx_sawhit
  224. || sfxid == sfx_stnmov
  225. || sfxid == sfx_pistol )
  226. {
  227. // Loop all channels, check.
  228. for (i=0 ; i<NUM_CHANNELS ; i++)
  229. {
  230. // Active, and using the same SFX?
  231. if ( (channels[i])
  232. && (channelids[i] == sfxid) )
  233. {
  234. // Reset.
  235. channels[i] = 0;
  236. // We are sure that iff,
  237. // there will only be one.
  238. break;
  239. }
  240. }
  241. }
  242. // Loop all channels to find oldest SFX.
  243. for (i=0; (i<NUM_CHANNELS) && (channels[i]); i++)
  244. {
  245. if (channelstart[i] < oldest)
  246. {
  247. oldestnum = i;
  248. oldest = channelstart[i];
  249. }
  250. }
  251. // Tales from the cryptic.
  252. // If we found a channel, fine.
  253. // If not, we simply overwrite the first one, 0.
  254. // Probably only happens at startup.
  255. if (i == NUM_CHANNELS)
  256. slot = oldestnum;
  257. else
  258. slot = i;
  259. // Okay, in the less recent channel,
  260. // we will handle the new SFX.
  261. // Set pointer to raw data.
  262. channels[slot] = (unsigned char *) S_sfx[sfxid].data;
  263. // Set pointer to end of raw data.
  264. channelsend[slot] = channels[slot] + lengths[sfxid];
  265. // Reset current handle number, limited to 0..100.
  266. if (!handlenums)
  267. handlenums = 100;
  268. // Assign current handle number.
  269. // Preserved so sounds could be stopped (unused).
  270. channelhandles[slot] = rc = handlenums++;
  271. // Set stepping???
  272. // Kinda getting the impression this is never used.
  273. channelstep[slot] = step;
  274. // ???
  275. channelstepremainder[slot] = 0;
  276. // Should be gametic, I presume.
  277. channelstart[slot] = gametic;
  278. // Separation, that is, orientation/stereo.
  279. // range is: 1 - 256
  280. seperation += 1;
  281. // Per left/right channel.
  282. // x^2 seperation,
  283. // adjust volume properly.
  284. leftvol =
  285. volume - ((volume*seperation*seperation) >> 16); ///(256*256);
  286. seperation = seperation - 257;
  287. rightvol =
  288. volume - ((volume*seperation*seperation) >> 16);
  289. // Sanity check, clamp volume.
  290. if (rightvol < 0 || rightvol > 127)
  291. I_Error("rightvol out of bounds");
  292. if (leftvol < 0 || leftvol > 127)
  293. I_Error("leftvol out of bounds");
  294. // Get the proper lookup table piece
  295. // for this volume level???
  296. channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
  297. channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
  298. // Preserve sound SFX id,
  299. // e.g. for avoiding duplicates of chainsaw.
  300. channelids[slot] = sfxid;
  301. // You tell me.
  302. return rc;
  303. }
  304. //
  305. // SFX API
  306. // Note: this was called by S_Init.
  307. // However, whatever they did in the
  308. // old DPMS based DOS version, this
  309. // were simply dummies in the Linux
  310. // version.
  311. // See soundserver initdata().
  312. //
  313. void I_SetChannels()
  314. {
  315. // Init internal lookups (raw data, mixing buffer, channels).
  316. // This function sets up internal lookups used during
  317. // the mixing process.
  318. int i;
  319. int j;
  320. int* steptablemid = steptable + 128;
  321. // Okay, reset internal mixing channels to zero.
  322. /*for (i=0; i<NUM_CHANNELS; i++)
  323. {
  324. channels[i] = 0;
  325. }*/
  326. // This table provides step widths for pitch parameters.
  327. // I fail to see that this is currently used.
  328. for (i=-128 ; i<128 ; i++)
  329. steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0);
  330. // Generates volume lookup tables
  331. // which also turn the unsigned samples
  332. // into signed samples.
  333. for (i=0 ; i<128 ; i++)
  334. for (j=0 ; j<256 ; j++)
  335. vol_lookup[i*256+j] = (i*(j-128)*256)/127;
  336. }
  337. void I_SetSfxVolume(int volume)
  338. {
  339. // Identical to DOS.
  340. // Basically, this should propagate
  341. // the menu/config file setting
  342. // to the state variable used in
  343. // the mixing.
  344. snd_SfxVolume = volume;
  345. }
  346. // MUSIC API - dummy. Some code from DOS version.
  347. void I_SetMusicVolume(int volume)
  348. {
  349. // Internal state variable.
  350. snd_MusicVolume = volume;
  351. // Now set volume on output device.
  352. // Whatever( snd_MusciVolume );
  353. }
  354. //
  355. // Retrieve the raw data lump index
  356. // for a given SFX name.
  357. //
  358. int I_GetSfxLumpNum(sfxinfo_t* sfx)
  359. {
  360. char namebuf[9];
  361. sprintf(namebuf, "ds%s", sfx->name);
  362. return W_GetNumForName(namebuf);
  363. }
  364. //
  365. // Starting a sound means adding it
  366. // to the current list of active sounds
  367. // in the internal channels.
  368. // As the SFX info struct contains
  369. // e.g. a pointer to the raw data,
  370. // it is ignored.
  371. // As our sound handling does not handle
  372. // priority, it is ignored.
  373. // Pitching (that is, increased speed of playback)
  374. // is set, but currently not used by mixing.
  375. //
  376. int
  377. I_StartSound
  378. ( int id,
  379. int vol,
  380. int sep,
  381. int pitch,
  382. int priority )
  383. {
  384. // UNUSED
  385. priority = 0;
  386. #ifdef SNDSERV
  387. if (sndserver)
  388. {
  389. fprintf(sndserver, "p%2.2x%2.2x%2.2x%2.2x\n", id, pitch, vol, sep);
  390. fflush(sndserver);
  391. }
  392. // warning: control reaches end of non-void function.
  393. return id;
  394. #else
  395. // Debug.
  396. //fprintf( stderr, "starting sound %d", id );
  397. // Returns a handle (not used).
  398. id = addsfx( id, vol, steptable[pitch], sep );
  399. // fprintf( stderr, "/handle is %d\n", id );
  400. return id;
  401. #endif
  402. }
  403. void I_StopSound (int handle)
  404. {
  405. // You need the handle returned by StartSound.
  406. // Would be looping all channels,
  407. // tracking down the handle,
  408. // an setting the channel to zero.
  409. // UNUSED.
  410. handle = 0;
  411. }
  412. int I_SoundIsPlaying(int handle)
  413. {
  414. // Ouch.
  415. return gametic < handle;
  416. }
  417. //
  418. // This function loops all active (internal) sound
  419. // channels, retrieves a given number of samples
  420. // from the raw sound data, modifies it according
  421. // to the current (internal) channel parameters,
  422. // mixes the per channel samples into the global
  423. // mixbuffer, clamping it to the allowed range,
  424. // and sets up everything for transferring the
  425. // contents of the mixbuffer to the (two)
  426. // hardware channels (left and right, that is).
  427. //
  428. // This function currently supports only 16bit.
  429. //
  430. void I_UpdateSound( void )
  431. {
  432. #ifdef SNDINTR
  433. // Debug. Count buffer misses with interrupt.
  434. static int misses = 0;
  435. #endif
  436. // Mix current sound data.
  437. // Data, from raw sound, for right and left.
  438. register unsigned int sample;
  439. register int dl;
  440. register int dr;
  441. // Pointers in global mixbuffer, left, right, end.
  442. signed short* leftout;
  443. signed short* rightout;
  444. signed short* leftend;
  445. // Step in mixbuffer, left and right, thus two.
  446. int step;
  447. // Mixing channel index.
  448. int chan;
  449. // Left and right channel
  450. // are in global mixbuffer, alternating.
  451. leftout = mixbuffer;
  452. rightout = mixbuffer+1;
  453. step = 2;
  454. // Determine end, for left channel only
  455. // (right channel is implicit).
  456. leftend = mixbuffer + SAMPLECOUNT*step;
  457. // Mix sounds into the mixing buffer.
  458. // Loop over step*SAMPLECOUNT,
  459. // that is 512 values for two channels.
  460. while (leftout != leftend)
  461. {
  462. // Reset left/right value.
  463. dl = 0;
  464. dr = 0;
  465. // Love thy L2 chache - made this a loop.
  466. // Now more channels could be set at compile time
  467. // as well. Thus loop those channels.
  468. for ( chan = 0; chan < NUM_CHANNELS; chan++ )
  469. {
  470. // Check channel, if active.
  471. if (channels[ chan ])
  472. {
  473. // Get the raw data from the channel.
  474. sample = *channels[ chan ];
  475. // Add left and right part
  476. // for this channel (sound)
  477. // to the current data.
  478. // Adjust volume accordingly.
  479. dl += channelleftvol_lookup[ chan ][sample];
  480. dr += channelrightvol_lookup[ chan ][sample];
  481. // Increment index ???
  482. channelstepremainder[ chan ] += channelstep[ chan ];
  483. // MSB is next sample???
  484. channels[ chan ] += channelstepremainder[ chan ] >> 16;
  485. // Limit to LSB???
  486. channelstepremainder[ chan ] &= 65536-1;
  487. // Check whether we are done.
  488. if (channels[ chan ] >= channelsend[ chan ])
  489. channels[ chan ] = 0;
  490. }
  491. }
  492. // Clamp to range. Left hardware channel.
  493. // Has been char instead of short.
  494. // if (dl > 127) *leftout = 127;
  495. // else if (dl < -128) *leftout = -128;
  496. // else *leftout = dl;
  497. if (dl > 0x7fff)
  498. *leftout = 0x7fff;
  499. else if (dl < -0x8000)
  500. *leftout = -0x8000;
  501. else
  502. *leftout = dl;
  503. // Same for right hardware channel.
  504. if (dr > 0x7fff)
  505. *rightout = 0x7fff;
  506. else if (dr < -0x8000)
  507. *rightout = -0x8000;
  508. else
  509. *rightout = dr;
  510. // Increment current pointers in mixbuffer.
  511. leftout += step;
  512. rightout += step;
  513. }
  514. #ifdef SNDINTR
  515. // Debug check.
  516. if ( flag )
  517. {
  518. misses += flag;
  519. flag = 0;
  520. }
  521. if ( misses > 10 )
  522. {
  523. fprintf( stderr, "I_SoundUpdate: missed 10 buffer writes\n");
  524. misses = 0;
  525. }
  526. // Increment flag for update.
  527. flag++;
  528. #endif
  529. }
  530. //
  531. // This would be used to write out the mixbuffer
  532. // during each game loop update.
  533. // Updates sound buffer and audio device at runtime.
  534. // It is called during Timer interrupt with SNDINTR.
  535. // Mixing now done synchronous, and
  536. // only output be done asynchronous?
  537. //
  538. void
  539. I_SubmitSound(void)
  540. {
  541. // Write it to DSP device.
  542. write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
  543. }
  544. void
  545. I_UpdateSoundParams
  546. ( int handle,
  547. int vol,
  548. int sep,
  549. int pitch)
  550. {
  551. // I fail too see that this is used.
  552. // Would be using the handle to identify
  553. // on which channel the sound might be active,
  554. // and resetting the channel parameters.
  555. // UNUSED.
  556. handle = vol = sep = pitch = 0;
  557. }
  558. void I_ShutdownSound(void)
  559. {
  560. #ifdef SNDSERV
  561. if (sndserver)
  562. {
  563. // Send a "quit" command.
  564. fprintf(sndserver, "q\n");
  565. fflush(sndserver);
  566. }
  567. #else
  568. // Wait till all pending sounds are finished.
  569. int done = 0;
  570. int i;
  571. // FIXME (below).
  572. fprintf( stderr, "I_ShutdownSound: NOT finishing pending sounds\n");
  573. fflush( stderr );
  574. while ( !done )
  575. {
  576. for( i=0 ; i<8 && !channels[i] ; i++);
  577. // FIXME. No proper channel output.
  578. //if (i==8)
  579. done=1;
  580. }
  581. #ifdef SNDINTR
  582. I_SoundDelTimer();
  583. #endif
  584. // Cleaning up -releasing the DSP device.
  585. close ( audio_fd );
  586. #endif
  587. // Done.
  588. return;
  589. }
  590. void
  591. I_InitSound()
  592. {
  593. #ifdef SNDSERV
  594. char buffer[256];
  595. if (getenv("DOOMWADDIR"))
  596. sprintf(buffer, "%s/%s",
  597. getenv("DOOMWADDIR"),
  598. sndserver_filename);
  599. else
  600. sprintf(buffer, "%s", sndserver_filename);
  601. // start sound process
  602. if ( !access(buffer, X_OK) )
  603. {
  604. strcat(buffer, " -quiet");
  605. sndserver = popen(buffer, "w");
  606. }
  607. else
  608. fprintf(stderr, "Could not start sound server [%s]\n", buffer);
  609. #else
  610. int i;
  611. #ifdef SNDINTR
  612. fprintf( stderr, "I_SoundSetTimer: %d microsecs\n", SOUND_INTERVAL );
  613. I_SoundSetTimer( SOUND_INTERVAL );
  614. #endif
  615. // Secure and configure sound device first.
  616. fprintf( stderr, "I_InitSound: ");
  617. audio_fd = open("/dev/dsp", O_WRONLY);
  618. if (audio_fd<0)
  619. fprintf(stderr, "Could not open /dev/dsp\n");
  620. i = 11 | (2<<16);
  621. myioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i);
  622. myioctl(audio_fd, SNDCTL_DSP_RESET, 0);
  623. i=SAMPLERATE;
  624. myioctl(audio_fd, SNDCTL_DSP_SPEED, &i);
  625. i=1;
  626. myioctl(audio_fd, SNDCTL_DSP_STEREO, &i);
  627. myioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i);
  628. if (i&=AFMT_S16_LE)
  629. myioctl(audio_fd, SNDCTL_DSP_SETFMT, &i);
  630. else
  631. fprintf(stderr, "Could not play signed 16 data\n");
  632. fprintf(stderr, " configured audio device\n" );
  633. // Initialize external data (all sounds) at start, keep static.
  634. fprintf( stderr, "I_InitSound: ");
  635. for (i=1 ; i<NUMSFX ; i++)
  636. {
  637. // Alias? Example is the chaingun sound linked to pistol.
  638. if (!S_sfx[i].link)
  639. {
  640. // Load data from WAD file.
  641. S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] );
  642. }
  643. else
  644. {
  645. // Previously loaded already?
  646. S_sfx[i].data = S_sfx[i].link->data;
  647. lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
  648. }
  649. }
  650. fprintf( stderr, " pre-cached all sound data\n");
  651. // Now initialize mixbuffer with zero.
  652. for ( i = 0; i< MIXBUFFERSIZE; i++ )
  653. mixbuffer[i] = 0;
  654. // Finished initialization.
  655. fprintf(stderr, "I_InitSound: sound module ready\n");
  656. #endif
  657. }
  658. //
  659. // MUSIC API.
  660. // Still no music done.
  661. // Remains. Dummies.
  662. //
  663. void I_InitMusic(void) { }
  664. void I_ShutdownMusic(void) { }
  665. static int looping=0;
  666. static int musicdies=-1;
  667. void I_PlaySong(int handle, int looping)
  668. {
  669. // UNUSED.
  670. handle = looping = 0;
  671. musicdies = gametic + TICRATE*30;
  672. }
  673. void I_PauseSong (int handle)
  674. {
  675. // UNUSED.
  676. handle = 0;
  677. }
  678. void I_ResumeSong (int handle)
  679. {
  680. // UNUSED.
  681. handle = 0;
  682. }
  683. void I_StopSong(int handle)
  684. {
  685. // UNUSED.
  686. handle = 0;
  687. looping = 0;
  688. musicdies = 0;
  689. }
  690. void I_UnRegisterSong(int handle)
  691. {
  692. // UNUSED.
  693. handle = 0;
  694. }
  695. int I_RegisterSong(void* data)
  696. {
  697. // UNUSED.
  698. data = NULL;
  699. return 1;
  700. }
  701. // Is the song playing?
  702. int I_QrySongPlaying(int handle)
  703. {
  704. // UNUSED.
  705. handle = 0;
  706. return looping || musicdies > gametic;
  707. }
  708. //
  709. // Experimental stuff.
  710. // A Linux timer interrupt, for asynchronous
  711. // sound output.
  712. // I ripped this out of the Timer class in
  713. // our Difference Engine, including a few
  714. // SUN remains...
  715. //
  716. #ifdef sun
  717. typedef sigset_t tSigSet;
  718. #else
  719. typedef int tSigSet;
  720. #endif
  721. // We might use SIGVTALRM and ITIMER_VIRTUAL, if the process
  722. // time independend timer happens to get lost due to heavy load.
  723. // SIGALRM and ITIMER_REAL doesn't really work well.
  724. // There are issues with profiling as well.
  725. static int /*__itimer_which*/ itimer = ITIMER_REAL;
  726. static int sig = SIGALRM;
  727. // Interrupt handler.
  728. void I_HandleSoundTimer( int ignore )
  729. {
  730. // Debug.
  731. //fprintf( stderr, "%c", '+' ); fflush( stderr );
  732. // Feed sound device if necesary.
  733. if ( flag )
  734. {
  735. // See I_SubmitSound().
  736. // Write it to DSP device.
  737. write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
  738. // Reset flag counter.
  739. flag = 0;
  740. }
  741. else
  742. return;
  743. // UNUSED, but required.
  744. ignore = 0;
  745. return;
  746. }
  747. // Get the interrupt. Set duration in millisecs.
  748. int I_SoundSetTimer( int duration_of_tick )
  749. {
  750. // Needed for gametick clockwork.
  751. struct itimerval value;
  752. struct itimerval ovalue;
  753. struct sigaction act;
  754. struct sigaction oact;
  755. int res;
  756. // This sets to SA_ONESHOT and SA_NOMASK, thus we can not use it.
  757. // signal( _sig, handle_SIG_TICK );
  758. // Now we have to change this attribute for repeated calls.
  759. act.sa_handler = I_HandleSoundTimer;
  760. #ifndef sun
  761. //ac t.sa_mask = _sig;
  762. #endif
  763. act.sa_flags = SA_RESTART;
  764. sigaction( sig, &act, &oact );
  765. value.it_interval.tv_sec = 0;
  766. value.it_interval.tv_usec = duration_of_tick;
  767. value.it_value.tv_sec = 0;
  768. value.it_value.tv_usec = duration_of_tick;
  769. // Error is -1.
  770. res = setitimer( itimer, &value, &ovalue );
  771. // Debug.
  772. if ( res == -1 )
  773. fprintf( stderr, "I_SoundSetTimer: interrupt n.a.\n");
  774. return res;
  775. }
  776. // Remove the interrupt. Set duration to zero.
  777. void I_SoundDelTimer()
  778. {
  779. // Debug.
  780. if ( I_SoundSetTimer( 0 ) == -1)
  781. fprintf( stderr, "I_SoundDelTimer: failed to remove interrupt. Doh!\n");
  782. }