home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #2 / amigaacscoverdisc1998-021998.iso / games / doom / adoom / src / amiga_sound.c < prev    next >
C/C++ Source or Header  |  1998-01-07  |  17KB  |  583 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. #include <string.h>
  5.  
  6. #include <exec/exec.h>
  7. #include <graphics/gfxbase.h>
  8. #include <devices/audio.h>
  9.  
  10. #include <proto/exec.h>
  11. #include <proto/graphics.h>
  12.  
  13. /* #include <math.h> */
  14.  
  15. #include "z_zone.h"
  16.  
  17. #include "i_system.h"
  18. #include "i_sound.h"
  19. #include "m_argv.h"
  20. #include "m_misc.h"
  21. #include "w_wad.h"
  22.  
  23. #include "doomdef.h"
  24.  
  25. // Any value of numChannels set
  26. // by the defaults code in M_misc is now clobbered by I_InitSound().
  27. // number of channels available for sound effects
  28. extern int numChannels;
  29.  
  30. /**********************************************************************/
  31. #define MAXNUMCHANNELS   4   /* max number of Amiga sound channels */
  32. #define CHIP_CACHE_SIZE 12   /* number of waveforms allowed in chipmem */
  33.  
  34. struct chip_cache_info {
  35.   int id;
  36.   ULONG age;
  37.   char *chip_data;
  38.   int len;
  39. };
  40.  
  41. struct channel_info {
  42.   struct MsgPort *audio_mp;
  43.   struct IOAudio *audio_io;
  44.   BOOL sound_in_progress;
  45. };
  46.  
  47. /**********************************************************************/
  48. // The actual lengths of all sound effects.
  49. static int lengths[NUMSFX];
  50.  
  51. static struct MsgPort *audio_mp = NULL;
  52. static struct IOAudio *audio_io = NULL;
  53. static BOOL audio_is_open = FALSE;
  54.  
  55. static struct channel_info channel_info[MAXNUMCHANNELS] = {
  56.   {FALSE, NULL, NULL},
  57.   {FALSE, NULL, NULL},
  58.   {FALSE, NULL, NULL},
  59.   {FALSE, NULL, NULL},
  60. };
  61.  
  62. /* cache up to CHIP_CACHE_SIZE sound effects in chipmem, rest in fastmem */
  63. static struct chip_cache_info chip_cache_info[CHIP_CACHE_SIZE] = {
  64.   {-1, 0, NULL, -1},
  65.   {-1, 0, NULL, -1},
  66.   {-1, 0, NULL, -1},
  67.   {-1, 0, NULL, -1},
  68.   {-1, 0, NULL, -1},
  69.   {-1, 0, NULL, -1},
  70.   {-1, 0, NULL, -1},
  71.   {-1, 0, NULL, -1},
  72.   {-1, 0, NULL, -1},
  73.   {-1, 0, NULL, -1},
  74.   {-1, 0, NULL, -1},
  75.   {-1, 0, NULL, -1}
  76. };
  77.  
  78. static ULONG age = 1;
  79. static UWORD period_table[256];
  80.  
  81. /**********************************************************************/
  82. //
  83. // This function loads the sound data for sfxname from the WAD lump,
  84. // and returns a ptr to the data in fastmem and its length in len.
  85. //
  86. static void *getsfx (char *sfxname, int *len)
  87. {
  88.   unsigned char*      sfx;
  89.   unsigned char*      paddedsfx;
  90.   int                 i;
  91.   int                 size;
  92.   int                 paddedsize;
  93.   char                name[20];
  94.   int                 sfxlump;
  95.  
  96.   // Get the sound data from the WAD, allocate lump
  97.   //  in zone memory.
  98.   sprintf(name, "ds%s", sfxname);
  99.  
  100.   // Now, there is a severe problem with the
  101.   //  sound handling, in it is not (yet/anymore)
  102.   //  gamemode aware. That means, sounds from
  103.   //  DOOM II will be requested even with DOOM
  104.   //  shareware.
  105.   // The sound list is wired into sounds.c,
  106.   //  which sets the external variable.
  107.   // I do not do runtime patches to that
  108.   //  variable. Instead, we will use a
  109.   //  default sound for replacement.
  110.   if (W_CheckNumForName(name) == -1)
  111.     sfxlump = W_GetNumForName("dspistol");
  112.   else
  113.     sfxlump = W_GetNumForName (name);
  114.  
  115.   size = W_LumpLength (sfxlump);
  116.  
  117.   // Debug.
  118.   // fprintf( stderr, "." );
  119.   // fprintf( stderr, " -loading  %s (lump %d, %d bytes)\n",
  120.   //         sfxname, sfxlump, size );
  121.   //fflush( stderr );
  122.  
  123.   sfx = (unsigned char*)W_CacheLumpNum (sfxlump, PU_STATIC);
  124.  
  125.   // Allocate from zone memory.
  126.   paddedsfx = (unsigned char*)Z_Malloc (size, PU_STATIC, 0);
  127.   // ddt: (unsigned char *) realloc(sfx, paddedsize+8);
  128.   // This should interfere with zone memory handling,
  129.   //  which does not kick in in the soundserver.
  130.  
  131.   // Now copy and pad.
  132.   for (i = 0; i < size; i++)
  133.     paddedsfx[i] = sfx[i] ^ 0x80;
  134.   /* memcpy (paddedsfx, sfx, size); */
  135.  
  136.   // Remove the cached lump.
  137.   Z_Free( sfx );
  138.  
  139.   // Preserve padded length.
  140.   *len = size;
  141.  
  142.   // Return allocated padded data.
  143.   return (void *) (paddedsfx /* + 8 */);
  144. }
  145.  
  146. /**********************************************************************/
  147. // Init at program start...
  148. void I_InitSound (void)
  149. {
  150.   int i;
  151.   struct channel_info *c;
  152.   UBYTE chans[1];
  153.   ULONG clock_constant;   /* see Amiga Hardware Manual page 141 */
  154.   int changepitch;
  155.   /* sampling freq (Hz) for each pitch step
  156.      calculated from (2^((i-128)/64))*11025
  157.      I'm not sure if this is the right formula */
  158.   static const UWORD freqs[256] = {
  159.     2756, 2786, 2817, 2847, 2878, 2910, 2941, 2973,
  160.     3006, 3038, 3072, 3105, 3139, 3173, 3208, 3242,
  161.     3278, 3313, 3350, 3386, 3423, 3460, 3498, 3536,
  162.     3574, 3613, 3653, 3692, 3733, 3773, 3814, 3856,
  163.     3898, 3940, 3983, 4027, 4071, 4115, 4160, 4205,
  164.     4251, 4297, 4344, 4391, 4439, 4487, 4536, 4586,
  165.     4635, 4686, 4737, 4789, 4841, 4893, 4947, 5001,
  166.     5055, 5110, 5166, 5222, 5279, 5336, 5394, 5453,
  167.     5513, 5573, 5633, 5695, 5757, 5819, 5883, 5947,
  168.     6011, 6077, 6143, 6210, 6278, 6346, 6415, 6485,
  169.     6556, 6627, 6699, 6772, 6846, 6920, 6996, 7072,
  170.     7149, 7227, 7305, 7385, 7465, 7547, 7629, 7712,
  171.     7796, 7881, 7967, 8053, 8141, 8230, 8319, 8410,
  172.     8501, 8594, 8688, 8782, 8878, 8975, 9072, 9171,
  173.     9271, 9372, 9474, 9577, 9681, 9787, 9893, 10001,
  174.     10110, 10220, 10331, 10444, 10558, 10673, 10789, 10906,
  175.     11025, 11145, 11266, 11389, 11513, 11638, 11765, 11893,
  176.     12023, 12154, 12286, 12420, 12555, 12692, 12830, 12970,
  177.     13111, 13254, 13398, 13544, 13691, 13841, 13991, 14144,
  178.     14298, 14453, 14611, 14770, 14931, 15093, 15258, 15424,
  179.     15592, 15761, 15933, 16107, 16282, 16459, 16639, 16820,
  180.     17003, 17188, 17375, 17564, 17756, 17949, 18144, 18342,
  181.     18542, 18744, 18948, 19154, 19363, 19574, 19787, 20002,
  182.     20220, 20440, 20663, 20888, 21115, 21345, 21578, 21812,
  183.     22050, 22290, 22533, 22778, 23026, 23277, 23530, 23787,
  184.     24046, 24308, 24572, 24840, 25110, 25384, 25660, 25940,
  185.     26222, 26508, 26796, 27088, 27383, 27681, 27983, 28287,
  186.     28595, 28907, 29221, 29540, 29861, 30187, 30515, 30848,
  187.     31183, 31523, 31866, 32213, 32564, 32919, 33277, 33639,
  188.     34006, 34376, 34750, 35129, 35511, 35898, 36289, 36684,
  189.     37084, 37487, 37896, 38308, 38725, 39147, 39573, 40004,
  190.     40440, 40880, 41325, 41775, 42230, 42690, 43155, 43625
  191.   };
  192.  
  193.   // Secure and configure sound device first.
  194.   fprintf( stderr, "I_InitSound: ");
  195.  
  196.   if (M_CheckParm("-music"))
  197.     numChannels = 2;          /* leave 2 channels free for music */
  198.   else
  199.     numChannels = 4;
  200.  
  201.   if ((audio_mp = CreatePort (NULL, 0)) == NULL ||
  202.       (audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  203.                                              MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  204.     I_Error ("CreatePort() or AllocMem() failed");
  205.  
  206.   chans[0] = (1 << numChannels) - 1; /* numchannels Amiga audio channels */
  207.   audio_io->ioa_Request.io_Message.mn_ReplyPort = audio_mp;
  208.   audio_io->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
  209.   audio_io->ioa_AllocKey = 0;
  210.   audio_io->ioa_Data = chans;
  211.   audio_io->ioa_Length = sizeof(chans);
  212.  
  213.   if (OpenDevice (AUDIONAME, 0, (struct IORequest *)audio_io, 0) != 0)
  214.     I_Error ("OpenDevice(\"audio.device\") failed");
  215.   audio_is_open = TRUE;
  216.  
  217.   for (i = 0; i < numChannels; i++) {
  218.     c = &channel_info[i];
  219.     if ((c->audio_mp = CreatePort (NULL, 0)) == NULL ||
  220.         (c->audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  221.                                              MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  222.       I_Error ("CreatePort() or AllocMem() failed");
  223.     *c->audio_io = *audio_io;
  224.     c->audio_io->ioa_Request.io_Message.mn_ReplyPort = c->audio_mp;
  225.     c->audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << i);
  226.   }
  227.  
  228.   if ((GfxBase->DisplayFlags & NTSC) != 0)
  229.     clock_constant = 3579545;   /* NTSC */
  230.   else
  231.     clock_constant = 3546895;   /* PAL */
  232.   changepitch = M_CheckParm ("-changepitch");
  233.   for (i = 0; i < 256; i++) {
  234.     if (changepitch)
  235.       period_table[i] = ((clock_constant << 1) + freqs[i]) /
  236.                         (((ULONG)freqs[i]) << 1);
  237.     else
  238.       period_table[i] = ((clock_constant << 1) + 11025) / ((11025) << 1);
  239.   }
  240.  
  241.   fprintf (stderr, " configured audio device\n" );
  242.  
  243.  
  244.   // Initialize external data (all sounds) at start, keep static.
  245.   fprintf (stderr, "I_InitSound: ");
  246.  
  247.   for (i = 1; i < NUMSFX; i++) {
  248.     // Alias? Example is the chaingun sound linked to pistol.
  249.     if (!S_sfx[i].link) {
  250.       // Load data from WAD file.
  251.       S_sfx[i].data = getsfx (S_sfx[i].name, &lengths[i]);
  252.     } else {
  253.       // Previously loaded already?
  254.       S_sfx[i].data = S_sfx[i].link->data;
  255.       lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
  256.     }
  257.   }
  258.  
  259.   fprintf (stderr, " pre-cached all sound data\n");
  260.  
  261.   // Finished initialization.
  262.   fprintf (stderr, "I_InitSound: sound module ready\n");
  263. }
  264.  
  265. /**********************************************************************/
  266. // ... update sound buffer and audio device at runtime...
  267. void I_UpdateSound (void)
  268. {
  269.   /* fprintf (stderr, "I_UpdateSound()\n"); */
  270. }
  271.  
  272. /**********************************************************************/
  273. // ... update sound buffer and audio device at runtime...
  274. void I_SubmitSound (void)
  275. {
  276.   /* fprintf (stderr, "I_SubmitSound()\n"); */
  277.   // Write it to DSP device.
  278.   // write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
  279. }
  280.  
  281. /**********************************************************************/
  282. // ... shut down and relase at program termination.
  283. void I_ShutdownSound (void)
  284. {
  285.   int i;
  286.  
  287.   fprintf (stderr, "I_ShutdownSound()\n");
  288.   if (audio_is_open) {
  289.     for (i = 0; i < numChannels; i++)
  290.       I_StopSound (i);
  291.     audio_io->ioa_Request.io_Unit = (struct Unit *)
  292.                      ((1 << numChannels) - 1);  /* free numChannels channels */
  293.     CloseDevice ((struct IORequest *)audio_io);
  294.     audio_is_open = FALSE;
  295.   }
  296.   for (i = 0; i < CHIP_CACHE_SIZE; i++) {
  297.     if (chip_cache_info[i].chip_data != NULL) {
  298.       FreeMem (chip_cache_info[i].chip_data, chip_cache_info[i].len);
  299.       chip_cache_info[i].chip_data = NULL;
  300.     }
  301.   }
  302.   for (i = 0; i < numChannels; i++) {
  303.     if (channel_info[i].audio_io != NULL) {
  304.       FreeMem (channel_info[i].audio_io, sizeof(struct IOAudio));
  305.       channel_info[i].audio_io = NULL;
  306.     }
  307.     if (channel_info[i].audio_mp != NULL) {
  308.       DeletePort (channel_info[i].audio_mp);
  309.       channel_info[i].audio_mp = NULL;
  310.     }
  311.   }
  312.   if (audio_io != NULL) {
  313.     FreeMem (audio_io, sizeof(struct IOAudio));
  314.     audio_io = NULL;
  315.   }
  316.   if (audio_mp != NULL) {
  317.     DeletePort (audio_mp);
  318.     audio_mp = NULL;
  319.   }
  320. }
  321.  
  322. /**********************************************************************/
  323. /**********************************************************************/
  324. //
  325. //  SFX I/O
  326. //
  327.  
  328. /**********************************************************************/
  329. // Initialize number of channels
  330. void I_SetChannels (void)
  331. {
  332. }
  333.  
  334. /**********************************************************************/
  335. // Get raw data lump index for sound descriptor.
  336. int I_GetSfxLumpNum (sfxinfo_t *sfx)
  337. {
  338.   char namebuf[9];
  339.  
  340.   /* fprintf (stderr, "I_GetSfxLumpNum()\n"); */
  341.   sprintf(namebuf, "ds%s", sfx->name);
  342.   return W_GetNumForName(namebuf);
  343. }
  344.  
  345. /**********************************************************************/
  346. // Find chip cache entry used longest ago and re-use it.
  347. static int cache_chip_data (int id)
  348. {
  349.   int i, mini;
  350.   ULONG minage;
  351.   struct chip_cache_info *c;
  352.  
  353.   if (age == 0xfffffffe)
  354.     I_Error ("Age overflow in cache_chip_data()");
  355.   minage = 0xffffffff;
  356.   mini = 0;
  357.   for (i = 0; i < CHIP_CACHE_SIZE; i++) {
  358.     c = &chip_cache_info[i];
  359.     if (c->id == id) {
  360.       c->age = age++;
  361.       return i;
  362.     }
  363.     if (c->age < minage) {
  364.       minage = c->age;
  365.       mini = i;
  366.     }
  367.   }
  368.   c = &chip_cache_info[mini];
  369.   if (c->chip_data != NULL) {
  370.     FreeMem (c->chip_data, c->len);
  371.     c->chip_data = NULL;
  372.   }
  373.   c->id = id;
  374.   c->age = age++;
  375.   if ((c->chip_data = AllocMem (lengths[id], MEMF_CHIP)) == NULL)
  376.     I_Error ("Out of CHIP memory allocating %d bytes", lengths[id]);
  377.   memcpy (c->chip_data, S_sfx[id].data, lengths[id]);
  378.   c->len = lengths[id];
  379.   return mini;
  380. }
  381.  
  382. /**********************************************************************/
  383. // Starts a sound in a particular sound channel.
  384. int I_StartSound (
  385.   int id,
  386.   int cnum,
  387.   int vol,
  388.   int sep,
  389.   int pitch,
  390.   int priority )
  391. {
  392.   struct channel_info *c;
  393.  
  394.   /* fprintf (stderr, "I_StartSound(%d,%d,%d,%d,%d,%d)\n", id, cnum, vol, sep,
  395.               pitch, priority); */
  396.   I_StopSound (cnum);
  397.   c = &channel_info[cnum];
  398.   c->audio_io->ioa_Request.io_Command = CMD_WRITE;
  399.   c->audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  400.   c->audio_io->ioa_Data = &chip_cache_info[cache_chip_data (id)].chip_data[8];
  401.   c->audio_io->ioa_Length = lengths[id] - 8;
  402.   c->audio_io->ioa_Period = period_table[pitch];
  403.   c->audio_io->ioa_Volume = vol << 3;
  404.   c->audio_io->ioa_Cycles = 1;
  405.   BeginIO ((struct IORequest *)c->audio_io);
  406.   c->sound_in_progress = TRUE;
  407.   return cnum;
  408. }
  409.  
  410. /**********************************************************************/
  411. // Stops a sound channel.
  412. void I_StopSound(int handle)
  413. {
  414.   /* fprintf (stderr, "I_StopSound(%d)\n", handle); */
  415.   if (channel_info[handle].sound_in_progress) {
  416.     AbortIO ((struct IORequest *)channel_info[handle].audio_io);
  417.     WaitPort (channel_info[handle].audio_mp);
  418.     GetMsg (channel_info[handle].audio_mp);
  419.     channel_info[handle].sound_in_progress = FALSE;
  420.   }
  421. }
  422.  
  423. /**********************************************************************/
  424. // Called by S_*() functions
  425. //  to see if a channel is still playing.
  426. // Returns 0 if no longer playing, 1 if playing.
  427. int I_SoundIsPlaying(int handle)
  428. {
  429.   /* fprintf (stderr, "I_SoundIsPlaying(%d)\n", handle); */
  430.   if (channel_info[handle].sound_in_progress) {
  431.     if (CheckIO ((struct IORequest *)channel_info[handle].audio_io)) {
  432.       WaitPort (channel_info[handle].audio_mp);  /* clears signal & returns immediately */
  433.       GetMsg (channel_info[handle].audio_mp);
  434.       channel_info[handle].sound_in_progress = FALSE;
  435.       return 0;
  436.     } else {
  437.       return 1;
  438.     }
  439.   }
  440.   return 0;
  441. }
  442.  
  443. /**********************************************************************/
  444. // Updates the volume, separation,
  445. //  and pitch of a sound channel.
  446. void
  447. I_UpdateSoundParams
  448. ( int        handle,
  449.   int        vol,
  450.   int        sep,
  451.   int        pitch )
  452. {
  453. /*
  454.   fprintf (stderr, "I_UpdateSoundParams(%d,%d,%d,%d)\n", handle, vol,
  455.            sep, pitch);
  456. */
  457.   if (channel_info[handle].sound_in_progress) {
  458.     audio_io->ioa_Request.io_Command = ADCMD_PERVOL;
  459.     audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  460.     audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << handle);
  461.     audio_io->ioa_Period = period_table[pitch];
  462.     audio_io->ioa_Volume = vol << 3;
  463.     BeginIO ((struct IORequest *)audio_io);
  464.     WaitPort (audio_mp);
  465.     GetMsg (audio_mp);
  466.   }
  467. }
  468.  
  469. #if 0
  470.  
  471. /**********************************************************************/
  472. /**********************************************************************/
  473. //
  474. // MUSIC API.
  475. // Still no music done.
  476. // Remains. Dummies.
  477. //
  478.  
  479. static int    looping=0;
  480. static int    musicdies=-1;
  481.  
  482.  
  483. /**********************************************************************/
  484. //
  485. //  MUSIC I/O
  486. //
  487. void I_InitMusic(void)
  488. {
  489.   fprintf (stderr, "I_InitMusic()\n");
  490. }
  491.  
  492. /**********************************************************************/
  493. void I_ShutdownMusic(void)
  494. {
  495.   fprintf (stderr, "I_ShutdownMusic()\n");
  496. }
  497.  
  498. /**********************************************************************/
  499. // Volume.
  500. void I_SetMusicVolume(int volume)
  501. {
  502.   fprintf (stderr, "I_SetMusicVolume(%d)\n", volume);
  503.   snd_MusicVolume = volume;
  504. }
  505.  
  506. /**********************************************************************/
  507. // PAUSE game handling.
  508. void I_PauseSong(int handle)
  509. {
  510.   fprintf (stderr, "I_PauseSong(%d)\n", handle);
  511.   // UNUSED.
  512.   handle = 0;
  513. }
  514.  
  515. /**********************************************************************/
  516. void I_ResumeSong(int handle)
  517. {
  518.   fprintf (stderr, "I_ResumeSong(%d)\n", handle);
  519.   // UNUSED.
  520.   handle = 0;
  521. }
  522.  
  523. /**********************************************************************/
  524. // Registers a song handle to song data.
  525. int I_RegisterSong(void *data)
  526. {
  527.   fprintf (stderr, "I_RegisterSong(%08x)\n", data);
  528.   // UNUSED.
  529.   data = NULL;
  530.  
  531.   return 1;
  532. }
  533.  
  534. /**********************************************************************/
  535. // Called by anything that wishes to start music.
  536. //  plays a song, and when the song is done,
  537. //  starts playing it again in an endless loop.
  538. // Horrible thing to do, considering.
  539. void
  540. I_PlaySong
  541. ( int        handle,
  542.   int        looping )
  543. {
  544.   fprintf (stderr, "I_PlaySong(%d,%d)\n", handle, looping);
  545.   // UNUSED.
  546.   handle = looping = 0;
  547.   musicdies = gametic + TICRATE*30;
  548. }
  549.  
  550. /**********************************************************************/
  551. // Stops a song over 3 seconds.
  552. void I_StopSong(int handle)
  553. {
  554.   fprintf (stderr, "I_StopSong(%d)\n", handle);
  555.   // UNUSED.
  556.   handle = 0;
  557.  
  558.   looping = 0;
  559.   musicdies = 0;
  560. }
  561.  
  562. /**********************************************************************/
  563. // See above (register), then think backwards
  564. void I_UnRegisterSong(int handle)
  565. {
  566.   fprintf (stderr, "I_UnRegisterSong(%d)\n", handle);
  567.   // UNUSED.
  568.   handle = 0;
  569. }
  570.  
  571. /**********************************************************************/
  572.  
  573. #endif
  574.  
  575. /**********************************************************************/
  576. void _STDaudio_cleanup (void)
  577. {
  578.   I_ShutdownSound ();
  579.   I_ShutdownMusic ();
  580. }
  581.  
  582. /**********************************************************************/
  583.