home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 15 / MA_Cover_15.iso / source / winquake / snd_amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-29  |  16.4 KB  |  552 lines

  1. /*
  2. Copyright (C) 2000 Peter McGavin.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  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.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // snd_amiga.c
  21.  
  22. #include <exec/exec.h>
  23. #include <dos/dos.h>
  24. #include <graphics/gfxbase.h>
  25. #include <devices/audio.h>
  26. #include <devices/ahi.h>
  27.  
  28. #if defined(__VBCC__) || (defined(__STORM__) && defined(__PPC__))
  29. #include <powerpc/powerpc.h>
  30. #include <clib/exec_protos.h>
  31. #include <clib/dos_protos.h>
  32. #include <clib/graphics_protos.h>
  33. #include <clib/ahi_protos.h>
  34. #include <clib/powerpc_protos.h>
  35. extern struct GfxBase *GfxBase;
  36. #else
  37. #include <proto/exec.h>
  38. #include <proto/dos.h>
  39. #include <proto/graphics.h>
  40. #include <proto/ahi.h>
  41. #endif
  42. #if defined(__SASC) && defined(__PPC__)
  43. #include <powerup/ppclib/memory.h>
  44. #endif
  45.  
  46. #include "quakedef.h"
  47.  
  48. #if defined(__SASC) && defined(__PPC__)
  49.  
  50. #define    BeginIO(ioRequest)    _BeginIO(ioRequest)
  51. static __inline void _BeginIO (struct IORequest *ioRequest)
  52. {
  53.   struct Caos MyCaos;
  54.   MyCaos.M68kCacheMode    = IF_CACHEFLUSHALL;
  55.   MyCaos.PPCCacheMode    = IF_CACHEFLUSHALL;
  56.   MyCaos.a1        = (ULONG)ioRequest;
  57.   MyCaos.caos_Un.Offset    = (-30);
  58.   MyCaos.a6        = (ULONG)ioRequest->io_Device;
  59.   PPCCallOS (&MyCaos);
  60. }
  61.  
  62. #define    CheckIO(ioRequest) _MyCheckIO(EXEC_BASE_NAME, ioRequest)
  63. static __inline struct IORequest *_MyCheckIO (void *SysBase, struct IORequest *ioRequest)
  64. {
  65.   struct Caos MyCaos;
  66.   MyCaos.M68kCacheMode    = IF_CACHEFLUSHNO;
  67.   MyCaos.PPCCacheMode    = IF_CACHEFLUSHNO;
  68.   MyCaos.a1        = (ULONG)ioRequest;
  69.   MyCaos.caos_Un.Offset    = (-468);
  70.   MyCaos.a6        = (ULONG)SysBase;    
  71.   return (struct IORequest *)PPCCallOS (&MyCaos);
  72. }
  73.  
  74. #define    WaitIO(ioRequest) _MyWaitIO(EXEC_BASE_NAME, ioRequest)
  75. static __inline struct IORequest *_MyWaitIO (void *SysBase, struct IORequest *ioRequest)
  76. {
  77.   struct Caos MyCaos;
  78.   MyCaos.M68kCacheMode    = IF_CACHEFLUSHNO;
  79.   MyCaos.PPCCacheMode    = IF_CACHEFLUSHNO;
  80.   MyCaos.a1        = (ULONG)ioRequest;
  81.   MyCaos.caos_Un.Offset    = (-474);
  82.   MyCaos.a6        = (ULONG)SysBase;    
  83.   return (struct IORequest *)PPCCallOS (&MyCaos);
  84. }
  85.  
  86. #define    WaitPort(port) _MyWaitPort(EXEC_BASE_NAME, port)
  87. static __inline struct Message *_MyWaitPort (void *SysBase, struct MsgPort *port)
  88. {
  89.   struct Caos    MyCaos;
  90.   MyCaos.M68kCacheMode    = IF_CACHEFLUSHNO;
  91.   MyCaos.PPCCacheMode    = IF_CACHEFLUSHNO;
  92.   MyCaos.a0        = (ULONG) port;
  93.   MyCaos.caos_Un.Offset    = (-384);
  94.   MyCaos.a6        = (ULONG)SysBase;    
  95.   return (struct Message *)PPCCallOS (&MyCaos);
  96. }
  97.  
  98. #define    AbortIO(ioRequest) _MyAbortIO(EXEC_BASE_NAME, ioRequest)
  99. static __inline void _MyAbortIO (void *SysBase, struct IORequest *ioRequest)
  100. {
  101.   struct Caos    MyCaos;
  102.   MyCaos.M68kCacheMode    = IF_CACHEFLUSHNO;
  103.   MyCaos.PPCCacheMode    = IF_CACHEFLUSHNO;
  104.   MyCaos.a1        = (ULONG)ioRequest;
  105.   MyCaos.caos_Un.Offset    = (-480);
  106.   MyCaos.a6        = (ULONG)SysBase;    
  107.   PPCCallOS (&MyCaos);
  108. }
  109.  
  110. #endif
  111.  
  112. #if defined(__STORM__) && defined(__PPC__)
  113. #define    BeginIO(ioRequest) _BeginIO(ioRequest)
  114. __inline void _BeginIO(struct IORequest *ioRequest)
  115. {
  116.   struct PPCArgs args;
  117.   memset (&args,0,sizeof(args));
  118.   args.PP_Code        = (APTR)ioRequest->io_Device;
  119.   args.PP_Offset    = (-30);
  120.   args.PP_Flags        = 0;
  121.   args.PP_Regs[PPREG_A1]= (ULONG)ioRequest;
  122.   args.PP_Regs[PPREG_A6]= (ULONG)ioRequest->io_Device;
  123.   Run68K (&args);
  124. }
  125. #endif
  126.  
  127. /**********************************************************************/
  128.  
  129. extern int desired_speed;
  130. extern int desired_bits;
  131. int using_ahi = FALSE;
  132.  
  133. /**********************************************************************/
  134.  
  135. /* AHI */
  136.  
  137. #define AHIBUFFERSIZE 262144
  138.  
  139. struct ahi_channel_info {
  140.   struct AHIRequest *AHIio;
  141.   double starttime;
  142.   BOOL sound_in_progress;
  143. };
  144.  
  145. struct Library *AHIBase = NULL;
  146. static struct MsgPort *AHImp = NULL;
  147. static struct ahi_channel_info ahi_channel_info[2] = {
  148.   {NULL, 0.0, FALSE},
  149.   {NULL, 0.0, FALSE}
  150. };
  151. static BYTE AHIDevice = -1;
  152. static BOOL ahidevice_is_open = FALSE;
  153. static double ahi_playtime;
  154. static int which_buffer;
  155.  
  156.  
  157. /* audio.device */
  158.  
  159. /* #define BUFFERSIZE 16384 */
  160. #define BUFFERSIZE 4096
  161.  
  162. #define MAXNUMCHANNELS   4   /* max number of Amiga sound channels */
  163.  
  164. struct channel_info {
  165.   struct MsgPort *audio_mp;
  166.   struct IOAudio *audio_io;
  167.   double starttime;
  168.   BOOL sound_in_progress;
  169. };
  170.  
  171. static struct channel_info channel_info[MAXNUMCHANNELS] = {
  172.   {NULL, NULL, 0.0, FALSE},
  173.   {NULL, NULL, 0.0, FALSE},
  174.   {NULL, NULL, 0.0, FALSE},
  175.   {NULL, NULL, 0.0, FALSE},
  176. };
  177.  
  178. static int size;
  179. static struct MsgPort *audio_mp = NULL;
  180. static struct IOAudio *audio_io = NULL;
  181. static BOOL audio_is_open = FALSE;
  182. static ULONG clock_constant;   /* see Amiga Hardware Manual page 141 */
  183. static UWORD period;
  184. static double twice_real_speed;
  185.  
  186. /**********************************************************************/
  187. static void stop_ahi_sound (struct ahi_channel_info *c)
  188. {
  189.   if (!ahidevice_is_open)
  190.     return;
  191.   if (c->sound_in_progress) {
  192.     AbortIO ((struct IORequest *)c->AHIio);
  193.     WaitPort (AHImp);
  194.     GetMsg (AHImp);
  195.     c->sound_in_progress = FALSE;
  196.   }
  197. }
  198.  
  199. /**********************************************************************/
  200. // Starts an AHI sound in a particular sound channel.
  201. // Use link for double-buffering.
  202.  
  203. static void start_ahi_sound (struct ahi_channel_info *c,
  204.                              char *buffer, int length,
  205.                              struct AHIRequest *link)
  206. {
  207.   if (!ahidevice_is_open)
  208.     return;
  209.   stop_ahi_sound (c);
  210.   c->AHIio->ahir_Std.io_Command = CMD_WRITE;
  211.   c->AHIio->ahir_Std.io_Flags = 0;
  212.   c->AHIio->ahir_Std.io_Message.mn_Node.ln_Pri = -50;   /* sound effects */
  213.   c->AHIio->ahir_Std.io_Data = buffer;
  214.   c->AHIio->ahir_Std.io_Length = length;
  215.   c->AHIio->ahir_Type = AHIST_S16S;
  216.   c->AHIio->ahir_Frequency = shm->speed;
  217.   c->AHIio->ahir_Volume = 0x10000;
  218.   c->AHIio->ahir_Position = 0x8000;
  219.   c->AHIio->ahir_Link = link;
  220.   SendIO ((struct IORequest *)c->AHIio);
  221.   c->sound_in_progress = TRUE;
  222. }
  223.  
  224. /**********************************************************************/
  225. // Stops an audio.device sound channel.
  226.  
  227. static void stopsound (int cnum)
  228. {
  229.   if (!audio_is_open)
  230.     return;
  231.   if (channel_info[cnum].sound_in_progress) {
  232.     AbortIO ((struct IORequest *)channel_info[cnum].audio_io);
  233.     WaitPort (channel_info[cnum].audio_mp);
  234.     GetMsg (channel_info[cnum].audio_mp);
  235.     channel_info[cnum].sound_in_progress = FALSE;
  236.   }
  237. }
  238.  
  239. /**********************************************************************/
  240. // Starts an audio.device sound in a particular sound channel.
  241.  
  242. static int startsound (int cnum, char *buffer, int length)
  243. {
  244.   struct channel_info *c;
  245.  
  246.   if (!audio_is_open)
  247.     return 1;
  248.   stopsound (cnum);
  249.   c = &channel_info[cnum];
  250.   c->audio_io->ioa_Request.io_Command = CMD_WRITE;
  251.   c->audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  252.   c->audio_io->ioa_Data = buffer;
  253.   c->audio_io->ioa_Length = length;
  254.   c->audio_io->ioa_Period = period;
  255.   c->audio_io->ioa_Volume = 64;
  256.   c->audio_io->ioa_Cycles = 0;
  257.   BeginIO ((struct IORequest *)c->audio_io);
  258.   c->starttime = Sys_FloatTime ();
  259.   c->sound_in_progress = TRUE;
  260.   return cnum;
  261. }
  262.  
  263. /**********************************************************************/
  264.  
  265. qboolean SNDDMA_Init (void)
  266. {
  267.   int i;
  268.   struct channel_info *c;
  269.   UBYTE chans[1];
  270.  
  271. //  printf ("SNDDMA_Init()\n");
  272.  
  273.   if ((shm = (dma_t *)malloc (sizeof(dma_t))) == NULL)
  274.     Sys_Error ("malloc() failed");
  275.   memset((void*)shm, 0, sizeof(dma_t));
  276.  
  277.   if (COM_CheckParm ("-ahi")) {
  278.  
  279.     Con_Printf("Using AHI unit 0.\n");
  280.     using_ahi = TRUE;
  281.  
  282. //#if defined(__SASC) && defined(__PPC__)
  283. //    if ((shm->buffer = PPCAllocMem (AHIBUFFERSIZE, MEMF_NOCACHESYNCPPC |
  284. //                                MEMF_NOCACHESYNCM68K | MEMF_PUBLIC)) == NULL)
  285. //#else
  286.     if ((shm->buffer = malloc (AHIBUFFERSIZE)) == NULL)
  287. //#endif
  288.       Sys_Error ("malloc() failed");
  289.     memset (shm->buffer, 0, AHIBUFFERSIZE);
  290.  
  291.     shm->channels = 2;
  292.     shm->speed = desired_speed;
  293.     shm->samplebits = 16;
  294.     shm->samples = AHIBUFFERSIZE / (shm->samplebits / 8);
  295.     shm->submission_chunk = 1;
  296.  
  297.     if ((AHImp = CreateMsgPort ()) == NULL)
  298.       Sys_Error ("CreateMsgPort() failed");
  299.     for (i = 0; i < 2; i++)
  300.       if ((ahi_channel_info[i].AHIio = (struct AHIRequest *)CreateIORequest
  301.                                    (AHImp, sizeof(struct AHIRequest))) == NULL)
  302.         Sys_Error ("CreateIORequest() failed");
  303.     ahi_channel_info[0].AHIio->ahir_Version = 4;
  304.     if ((AHIDevice = OpenDevice (AHINAME, AHI_DEFAULT_UNIT,
  305.                                  (struct IORequest *)ahi_channel_info[0].AHIio,
  306.                                  0)) != 0)
  307.       Sys_Error ("OpenDevice() failed");
  308.     ahidevice_is_open = TRUE;
  309.     AHIBase = (struct Library *)ahi_channel_info[0].AHIio->ahir_Std.io_Device;
  310.     *ahi_channel_info[1].AHIio = *ahi_channel_info[0].AHIio;
  311.  
  312.     twice_real_speed = 2.0 * (double)shm->speed;
  313.     ahi_playtime = ((double)(AHIBUFFERSIZE >> 2)) / (double)shm->speed;
  314.     //printf ("ahi_playtime = %f\n", ahi_playtime);
  315.  
  316.     ahi_channel_info[0].starttime = Sys_FloatTime ();
  317.     start_ahi_sound (&ahi_channel_info[0], shm->buffer, AHIBUFFERSIZE, NULL);
  318.     //printf ("start[0] = %f  %f\n", ahi_channel_info[0].starttime,
  319.     //                               ahi_channel_info[0].starttime + ahi_playtime);
  320.     ahi_channel_info[1].starttime = ahi_channel_info[0].starttime + ahi_playtime;
  321.     start_ahi_sound (&ahi_channel_info[1], shm->buffer, AHIBUFFERSIZE,
  322.                      ahi_channel_info[0].AHIio);
  323.     //printf ("start[1] = %f  %f\n", ahi_channel_info[1].starttime,
  324.     //                               ahi_channel_info[1].starttime + ahi_playtime);
  325.     which_buffer = 0;
  326.  
  327.   } else { /* audio.device */
  328.  
  329.     Con_Printf("Using audio.device.\n");
  330.     using_ahi = FALSE;
  331.  
  332.     if ((shm->buffer = AllocMem (BUFFERSIZE, MEMF_CHIP | MEMF_CLEAR)) == NULL)
  333.       Sys_Error ("Out of CHIP memory for sound");
  334. //    memset(shm->buffer, 0x80, BUFFERSIZE);
  335.  
  336. //    printf ("Sound buffer at 0x%08x\n", shm->buffer);
  337.  
  338.     shm->channels = 2;
  339.     shm->speed = desired_speed;
  340.     shm->samplebits = 8;
  341.     shm->samples = BUFFERSIZE / (shm->samplebits / 8);
  342.     shm->submission_chunk = 1;
  343.  
  344.     if ((audio_mp = CreateMsgPort ()) == NULL ||
  345.         (audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  346.                                              MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  347.       Sys_Error ("CreateMsgPort() or AllocMem() failed");
  348.  
  349.     chans[0] = (1 << shm->channels) - 1; /* shm->channels Amiga audio channels */
  350.     audio_io->ioa_Request.io_Message.mn_ReplyPort = audio_mp;
  351.     audio_io->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
  352.     audio_io->ioa_AllocKey = 0;
  353.     audio_io->ioa_Data = chans;
  354.     audio_io->ioa_Length = sizeof(chans);
  355.  
  356.     if (OpenDevice (AUDIONAME, 0, (struct IORequest *)audio_io, 0) != 0)
  357.       Sys_Error ("OpenDevice(\"audio.device\") failed");
  358.     audio_is_open = TRUE;
  359.  
  360.     for (i = 0; i < shm->channels; i++) {
  361.       c = &channel_info[i];
  362.       if ((c->audio_mp = CreateMsgPort ()) == NULL ||
  363.           (c->audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  364.                                              MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  365.         Sys_Error ("CreateMsgPort() or AllocMem() failed");
  366.       *c->audio_io = *audio_io;
  367.       c->audio_io->ioa_Request.io_Message.mn_ReplyPort = c->audio_mp;
  368.       c->audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << i);
  369.     }
  370.  
  371.     if ((GfxBase->DisplayFlags & REALLY_PAL) == 0)
  372.       clock_constant = 3579545;   /* NTSC */
  373.     else
  374.       clock_constant = 3546895;   /* PAL */
  375.  
  376.     period = ((clock_constant << 1) + shm->speed) / ((shm->speed) << 1);
  377.  
  378.     twice_real_speed = 2.0 * ((double)clock_constant) / (double)period;
  379.  
  380.     startsound (0, shm->buffer, BUFFERSIZE >> 1);
  381.     startsound (1, shm->buffer + (BUFFERSIZE >> 1), BUFFERSIZE >> 1);
  382.   }
  383.  
  384.   return 1;
  385. }
  386.  
  387. /**********************************************************************/
  388.  
  389. int SNDDMA_GetDMAPos (void)
  390. {
  391.   if (shm == NULL || shm->buffer == NULL)
  392.     return 0;
  393.  
  394.   if (using_ahi) {
  395.  
  396.     if (!ahi_channel_info[0].sound_in_progress)
  397.       shm->samplepos = 0;
  398.     else {
  399.       struct ahi_channel_info *c, *c2;
  400.       double now;
  401.  
  402.       now = Sys_FloatTime ();
  403.       c = &ahi_channel_info[which_buffer];
  404.       if (now >= c->starttime + ahi_playtime - 0.1 &&
  405.           CheckIO ((struct IORequest *)c->AHIio)) {
  406.         //printf ("finished[%d] = %f  %f\n", which_buffer, now,
  407.         //                                   now - (c->starttime + ahi_playtime));
  408.         c2 = &ahi_channel_info[1 - which_buffer];
  409.         if (c2->starttime > now) {
  410.           c2->starttime = now;
  411.           //printf ("changed[%d] = %f  %f\n", 1 - which_buffer, c2->starttime,
  412.           //                                  c2->starttime + ahi_playtime);
  413.         }
  414.         WaitPort (AHImp);
  415.         GetMsg (AHImp);
  416.         c->sound_in_progress = FALSE;
  417.         if ((now = Sys_FloatTime ()) > (c->starttime =
  418.                                         c2->starttime + ahi_playtime))
  419.           c->starttime = now;
  420.         start_ahi_sound (c, shm->buffer, AHIBUFFERSIZE,
  421.                          ahi_channel_info[1 - which_buffer].AHIio);
  422.         //printf ("start[%d] = %f  %f\n", which_buffer, c->starttime,
  423.         //                                c->starttime + ahi_playtime);
  424.         which_buffer = 1 - which_buffer;
  425.         c = &ahi_channel_info[which_buffer];
  426.       }
  427.       shm->samplepos = ((int)((now + ahi_playtime - c->starttime) *
  428.                               twice_real_speed + 0.5)) & (AHIBUFFERSIZE - 1);
  429.     }
  430.  
  431.   } else {  /* audio.device */
  432.  
  433.     if (!channel_info[0].sound_in_progress)
  434.       shm->samplepos = 0;
  435.     else
  436.       shm->samplepos = ((int)((Sys_FloatTime() - channel_info[0].starttime)
  437.                               * twice_real_speed + 0.5))
  438.                        & (BUFFERSIZE - 1);
  439.  
  440.   }
  441.  
  442.   return shm->samplepos;
  443. }
  444.  
  445. /**********************************************************************/
  446.  
  447. void SNDDMA_Shutdown (void)
  448. {
  449.   int i;
  450.  
  451. //  printf ("SNDDMA_Shutdown()\n");
  452.  
  453.   for (i = 0; i < 2; i++)
  454.     stop_ahi_sound (&ahi_channel_info[i]);
  455.   if (ahidevice_is_open) {
  456.     CloseDevice ((struct IORequest *)ahi_channel_info[0].AHIio);
  457.     ahidevice_is_open = FALSE;
  458.   }
  459.   for (i = 0; i < 2; i++) {
  460.     if (ahi_channel_info[i].AHIio != NULL) {
  461.       DeleteIORequest ((struct IORequest *)ahi_channel_info[i].AHIio);
  462.       ahi_channel_info[i].AHIio = NULL;
  463.     }
  464.   }
  465.   if (AHImp != NULL) {
  466.     DeleteMsgPort (AHImp);
  467.     AHImp = NULL;
  468.   }
  469.   if (audio_is_open) {
  470.     if (shm != NULL) {
  471.       for (i = 0; i < shm->channels; i++)
  472.         stopsound (i);
  473.       audio_io->ioa_Request.io_Unit = (struct Unit *)
  474.                        ((1 << shm->channels) - 1);  /* free shm->channels channels */
  475.     }
  476.     CloseDevice ((struct IORequest *)audio_io);
  477.     audio_is_open = FALSE;
  478.   }
  479.   for (i = 0; i < MAXNUMCHANNELS; i++) {
  480.     if (channel_info[i].audio_io != NULL) {
  481.       FreeMem (channel_info[i].audio_io, sizeof(struct IOAudio));
  482.       channel_info[i].audio_io = NULL;
  483.     }
  484.     if (channel_info[i].audio_mp != NULL) {
  485.       DeleteMsgPort (channel_info[i].audio_mp);
  486.       channel_info[i].audio_mp = NULL;
  487.     }
  488.   }
  489.   if (audio_io != NULL) {
  490.     FreeMem (audio_io, sizeof(struct IOAudio));
  491.     audio_io = NULL;
  492.   }
  493.   if (audio_mp != NULL) {
  494.     DeleteMsgPort (audio_mp);
  495.     audio_mp = NULL;
  496.   }
  497.   if (shm != NULL) {
  498.     if (shm->buffer != NULL) {
  499.       if (using_ahi)
  500. //#if defined(__SASC) && defined(__PPC__)
  501. //        PPCFreeMem (shm->buffer, AHIBUFFERSIZE);
  502. //#else
  503.         free (shm->buffer);
  504. //#endif
  505.       else
  506.         FreeMem (shm->buffer, BUFFERSIZE);
  507.       shm->buffer = NULL;
  508.     }
  509.     free ((char *)shm);
  510.     shm = NULL;
  511.   }
  512. }
  513.  
  514. /**********************************************************************/
  515. void SNDDMA_Submit (void)
  516. {
  517. //  printf ("SNDDMA_Submit()\n");
  518. }
  519.  
  520. /**********************************************************************/
  521.  
  522. #ifdef __SASC
  523. void _STD_SNDDMA_Shutdown (void)
  524. {
  525. //  printf ("_STD_SNDDMA_Shutdown()\n");
  526.  
  527.   SNDDMA_Shutdown ();
  528. }
  529. #endif
  530.  
  531. /**********************************************************************/
  532. #ifdef __STORM__
  533. void EXIT_9_SNDDMA_Shutdown (void)
  534. {
  535. //  printf ("EXIT_9_SNDDMA_Shutdown()\n");
  536.  
  537.   SNDDMA_Shutdown ();
  538. }
  539. #endif
  540.  
  541. /**********************************************************************/
  542. #ifdef __VBCC__
  543. void _EXIT_9_SNDDMA_Shutdown (void)
  544. {
  545. //  printf ("_EXIT_9_SNDDMA_Shutdown()\n");
  546.  
  547.   SNDDMA_Shutdown ();
  548. }
  549. #endif
  550.  
  551. /**********************************************************************/
  552.