home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 106 / EnigmaAmiga106CD.iso / software / sviluppo / ahisrc / device / mixer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-12  |  41.8 KB  |  1,490 lines

  1. /* $Id: mixer.c,v 4.34 1999/09/12 10:40:10 lcs Exp $ */
  2.  
  3. /*
  4.      AHI - Hardware independent audio subsystem
  5.      Copyright (C) 1996-1999 Martin Blom <martin@blom.org>
  6.      
  7.      This library is free software; you can redistribute it and/or
  8.      modify it under the terms of the GNU Library General Public
  9.      License as published by the Free Software Foundation; either
  10.      version 2 of the License, or (at your option) any later version.
  11.      
  12.      This library is distributed in the hope that it will be useful,
  13.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.      Library General Public License for more details.
  16.      
  17.      You should have received a copy of the GNU Library General Public
  18.      License along with this library; if not, write to the
  19.      Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
  20.      MA 02139, USA.
  21. */
  22.  
  23. #include <config.h>
  24. #include <CompilerSpecific.h>
  25.  
  26. # include <exec/interrupts.h>
  27. # include <hardware/intbits.h>
  28.  
  29. #if !defined( VERSIONPPC )
  30. # include <exec/memory.h>
  31. # include <exec/execbase.h>
  32. # include <powerup/ppclib/memory.h>
  33. # include <powerup/ppclib/interface.h>
  34. # include <powerup/ppclib/object.h>
  35. # include <powerpc/powerpc.h>
  36.  
  37. # include <proto/exec.h>
  38. # include <proto/utility.h>
  39. # include <proto/ppc.h> 
  40. # include <proto/powerpc.h> 
  41. # include <clib/ahi_protos.h>
  42. # include <pragmas/ahi_pragmas.h>
  43. #endif
  44.  
  45. #include <string.h>
  46. #include <stddef.h>
  47.  
  48. #include "ahi_def.h"
  49. #include "dsp.h"
  50. #include "mixer.h"
  51. #include "addroutines.h"
  52. #include "misc.h"
  53. #include "header.h"
  54.  
  55.  
  56. /******************************************************************************
  57. ** Prototypes *****************************************************************
  58. ******************************************************************************/
  59.  
  60. static void
  61. DoMasterVolume ( void *buffer,
  62.                  struct AHIPrivAudioCtrl *audioctrl );
  63.  
  64. #if !defined( VERSIONPPC )
  65.  
  66. static void
  67. DoOutputBuffer ( void *buffer,
  68.                  struct AHIPrivAudioCtrl *audioctrl );
  69.  
  70. static void
  71. DoChannelInfo ( struct AHIPrivAudioCtrl *audioctrl );
  72.  
  73. #endif /* !defined( VERSIONPPC ) */
  74.  
  75.  
  76. #if 1
  77.  
  78. ADDFUNC* AddByteMonoPtr     = NULL;
  79. ADDFUNC* AddByteStereoPtr   = NULL;
  80. ADDFUNC* AddBytesMonoPtr    = NULL;
  81. ADDFUNC* AddBytesStereoPtr  = NULL;
  82. ADDFUNC* AddWordMonoPtr     = NULL;
  83. ADDFUNC* AddWordStereoPtr   = NULL;
  84. ADDFUNC* AddWordsMonoPtr    = NULL;
  85. ADDFUNC* AddWordsStereoPtr  = NULL;
  86. ADDFUNC* AddByteMonoBPtr    = NULL;
  87. ADDFUNC* AddByteStereoBPtr  = NULL;
  88. ADDFUNC* AddBytesMonoBPtr   = NULL;
  89. ADDFUNC* AddBytesStereoBPtr = NULL;
  90. ADDFUNC* AddWordMonoBPtr    = NULL;
  91. ADDFUNC* AddWordStereoBPtr  = NULL;
  92. ADDFUNC* AddWordsMonoBPtr   = NULL;
  93. ADDFUNC* AddWordsStereoBPtr = NULL;
  94.  
  95. ADDFUNC* AddLofiByteMonoPtr     = NULL;
  96. ADDFUNC* AddLofiByteStereoPtr   = NULL;
  97. ADDFUNC* AddLofiBytesMonoPtr    = NULL;
  98. ADDFUNC* AddLofiBytesStereoPtr  = NULL;
  99. ADDFUNC* AddLofiWordMonoPtr     = NULL;
  100. ADDFUNC* AddLofiWordStereoPtr   = NULL;
  101. ADDFUNC* AddLofiWordsMonoPtr    = NULL;
  102. ADDFUNC* AddLofiWordsStereoPtr  = NULL;
  103. ADDFUNC* AddLofiByteMonoBPtr    = NULL;
  104. ADDFUNC* AddLofiByteStereoBPtr  = NULL;
  105. ADDFUNC* AddLofiBytesMonoBPtr   = NULL;
  106. ADDFUNC* AddLofiBytesStereoBPtr = NULL;
  107. ADDFUNC* AddLofiWordMonoBPtr    = NULL;
  108. ADDFUNC* AddLofiWordStereoBPtr  = NULL;
  109. ADDFUNC* AddLofiWordsMonoBPtr   = NULL;
  110. ADDFUNC* AddLofiWordsStereoBPtr = NULL;
  111.  
  112. #else
  113.  
  114. ADDFUNC* AddByteMonoPtr     = AddByteMono;
  115. ADDFUNC* AddByteStereoPtr   = AddByteStereo;
  116. ADDFUNC* AddBytesMonoPtr    = AddBytesMono;
  117. ADDFUNC* AddBytesStereoPtr  = AddBytesStereo;
  118. ADDFUNC* AddWordMonoPtr     = AddWordMono;
  119. ADDFUNC* AddWordStereoPtr   = AddWordStereo;
  120. ADDFUNC* AddWordsMonoPtr    = AddWordsMono;
  121. ADDFUNC* AddWordsStereoPtr  = AddWordsStereo;
  122. ADDFUNC* AddByteMonoBPtr    = AddByteMonoB;
  123. ADDFUNC* AddByteStereoBPtr  = AddByteStereoB;
  124. ADDFUNC* AddBytesMonoBPtr   = AddBytesMonoB;
  125. ADDFUNC* AddBytesStereoBPtr = AddBytesStereoB;
  126. ADDFUNC* AddWordMonoBPtr    = AddWordMonoB;
  127. ADDFUNC* AddWordStereoBPtr  = AddWordStereoB;
  128. ADDFUNC* AddWordsMonoBPtr   = AddWordsMonoB;
  129. ADDFUNC* AddWordsStereoBPtr = AddWordsStereoB;
  130.  
  131. ADDFUNC* AddLofiByteMonoPtr     = AddLofiByteMonoPtr;
  132. ADDFUNC* AddLofiByteStereoPtr   = AddLofiByteStereoPtr;
  133. ADDFUNC* AddLofiBytesMonoPtr    = AddLofiBytesMonoPtr;
  134. ADDFUNC* AddLofiBytesStereoPtr  = AddLofiBytesStereoPtr;
  135. ADDFUNC* AddLofiWordMonoPtr     = AddLofiWordMonoPtr;
  136. ADDFUNC* AddLofiWordStereoPtr   = AddLofiWordStereoPtr;
  137. ADDFUNC* AddLofiWordsMonoPtr    = AddLofiWordsMonoPtr;
  138. ADDFUNC* AddLofiWordsStereoPtr  = AddLofiWordsStereoPtr;
  139. ADDFUNC* AddLofiByteMonoBPtr    = AddLofiByteMonoBPtr;
  140. ADDFUNC* AddLofiByteStereoBPtr  = AddLofiByteStereoBPtr;
  141. ADDFUNC* AddLofiBytesMonoBPtr   = AddLofiBytesMonoBPtr;
  142. ADDFUNC* AddLofiBytesStereoBPtr = AddLofiBytesStereoBPtr;
  143. ADDFUNC* AddLofiWordMonoBPtr    = AddLofiWordMonoBPtr;
  144. ADDFUNC* AddLofiWordStereoBPtr  = AddLofiWordStereoBPtr;
  145. ADDFUNC* AddLofiWordsMonoBPtr   = AddLofiWordsMonoBPtr;
  146. ADDFUNC* AddLofiWordsStereoBPtr = AddLofiWordsStereoBPtr;
  147.  
  148. #endif
  149.  
  150. static const UBYTE type2bytes[]=
  151. {
  152.   1,    // AHIST_M8S  (0)
  153.   2,    // AHIST_M16S (1)
  154.   2,    // AHIST_S8S  (2)
  155.   4,    // AHIST_S16S (3)
  156.   1,    // AHIST_M8U  (4)
  157.   0,
  158.   0,
  159.   0,
  160.   4,    // AHIST_M32S (8)
  161.   0,
  162.   8     // AHIST_S32S (10)
  163. };
  164.  
  165. inline ULONG
  166. InternalSampleFrameSize( ULONG sampletype )
  167. {
  168.   return type2bytes[sampletype];
  169. }
  170.  
  171. /******************************************************************************
  172. ** PowerUp Support code *******************************************************
  173. ******************************************************************************/
  174.  
  175. #if defined( VERSIONPPC )
  176.  
  177. /* PPC code ******************************************************************/
  178.  
  179. static void
  180. CallSoundHook( struct AHIPrivAudioCtrl *audioctrl,
  181.                void* arg )
  182. {
  183.   audioctrl->ahiac_PPCCommand  = AHIAC_COM_SOUNDFUNC;
  184.   audioctrl->ahiac_PPCArgument = arg;
  185. //  *((WORD*) 0xdff09C)  = INTF_SETCLR | INTF_PORTS;
  186.   while( audioctrl->ahiac_PPCCommand != AHIAC_COM_ACK );
  187. }
  188.  
  189. static void
  190. CallDebug( struct AHIPrivAudioCtrl *audioctrl, long value )
  191. {
  192.   audioctrl->ahiac_PPCCommand  = AHIAC_COM_DEBUG;
  193.   audioctrl->ahiac_PPCArgument = (void*) value;
  194. //  *((WORD*) 0xdff09C)  = INTF_SETCLR | INTF_PORTS;
  195.   while( audioctrl->ahiac_PPCCommand != AHIAC_COM_ACK );
  196. }
  197.  
  198. #else
  199.  
  200. /* M68k code *****************************************************************/
  201.  
  202. static void
  203. CallSoundHook( struct AHIPrivAudioCtrl *audioctrl,
  204.                void* arg )
  205. {
  206.   CallHookPkt( audioctrl->ac.ahiac_SoundFunc,
  207.                audioctrl,
  208.                arg );
  209. }
  210.  
  211. static void
  212. CallDebug( struct AHIPrivAudioCtrl *audioctrl, long value )
  213. {
  214.   kprintf( "%lx ", value );
  215. }
  216.  
  217.  
  218. INTERRUPT SAVEDS int
  219. Interrupt( struct AHIPrivAudioCtrl *audioctrl __asm( "a1" ) )
  220. {
  221.  
  222.   if( audioctrl->ahiac_PPCCommand != AHIAC_COM_INIT )
  223.   {
  224.     /* Not for us, continue */
  225.     return 0;
  226.   }
  227.   else
  228.   {
  229.     BOOL running = TRUE;
  230.  
  231.     while( running )
  232.     {
  233.       switch( audioctrl->ahiac_PPCCommand )
  234.       {
  235.         case AHIAC_COM_INIT:
  236.           // Keep looping
  237.           audioctrl->ahiac_PPCCommand = AHIAC_COM_ACK;
  238.           break;
  239.  
  240.         case AHIAC_COM_ACK:
  241.           // Keep looping
  242. //          asm( "stop #(1<<13) | (2<<8)" : );
  243.           break;
  244.  
  245.         case AHIAC_COM_SOUNDFUNC:
  246.           CallHookPkt( audioctrl->ac.ahiac_SoundFunc,
  247.                        (struct AHIPrivAudioCtrl*) audioctrl,
  248.                        (APTR) audioctrl->ahiac_PPCArgument );
  249.           audioctrl->ahiac_PPCCommand = AHIAC_COM_ACK;
  250.           break;
  251.  
  252.         case AHIAC_COM_DEBUG:
  253.           CallDebug( audioctrl, (ULONG) audioctrl->ahiac_PPCArgument );
  254.           audioctrl->ahiac_PPCCommand = AHIAC_COM_ACK;
  255.           break;
  256.  
  257.         case AHIAC_COM_QUIT:
  258.           running = FALSE;
  259.           audioctrl->ahiac_PPCCommand = AHIAC_COM_ACK;
  260.           break;
  261.         
  262.         case AHIAC_COM_NONE:
  263.         default:
  264.           // Error
  265.           running  = FALSE;
  266.           audioctrl->ahiac_PPCCommand = AHIAC_COM_ACK;
  267.           break;
  268.       }
  269.     }
  270.  
  271.     /* End chain! */
  272.     return 1;
  273.   }
  274. };
  275.  
  276. void ASMCALL
  277. MixPowerUp( REG(a0, struct Hook *Hook), 
  278.             REG(a1, void *dst), 
  279.             REG(a2, struct AHIPrivAudioCtrl *audioctrl) )
  280. {
  281.   struct AHISoundData *sd;
  282.   int                  i;
  283.   BOOL                 flushed = FALSE;
  284.  
  285.   struct ModuleArgs mod =
  286.   {
  287.     IF_CACHEFLUSHNO, 0, 0,
  288.     IF_CACHEFLUSHNO | IF_ASYNC, 0, 0,
  289.  
  290.     (ULONG) Hook, (ULONG) audioctrl->ahiac_PPCMixBuffer, (ULONG) audioctrl,
  291.     0, 0, 0, 0, 0,
  292.     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
  293.   };
  294.  
  295.   // Flush all DYNAMICSAMPLE's
  296.  
  297.   sd = audioctrl->ahiac_SoundDatas;
  298.  
  299.   for( i = 0; i < audioctrl->ac.ahiac_Sounds; i++)
  300.   {
  301.     if( sd->sd_Type == AHIST_DYNAMICSAMPLE )
  302.     {
  303.       if( sd->sd_Addr == NULL )
  304.       {
  305.         // Flush all and exit
  306.         CacheClearU();
  307.         flushed = TRUE;
  308.         break;
  309.       }
  310.       else
  311.       {
  312.         if( PPCLibBase != NULL )
  313.         {
  314.           PPCCacheClearE( sd->sd_Addr,
  315.                           sd->sd_Length * InternalSampleFrameSize( sd->sd_Type ),
  316.                           CACRF_ClearD );
  317.         }
  318.         else
  319.         {
  320.           SetCache68K( CACHE_DCACHEFLUSH,
  321.                        sd->sd_Addr,
  322.                        sd->sd_Length * InternalSampleFrameSize( sd->sd_Type ) );
  323.         }
  324.       }
  325.     }
  326.     sd++;
  327.   }
  328.  
  329.   if( ! flushed && PPCLibBase == NULL )
  330.   {
  331.  
  332.     /* Since the PPC mix buffer is m68k cacheable in WarpUp, we have to
  333.        flush the cache before mixing starts. :( */
  334.  
  335.     SetCache68K( CACHE_DCACHEFLUSH,
  336.                  audioctrl->ahiac_PPCMixBuffer,
  337.                  audioctrl->ahiac_BuffSizeNow );
  338.   }
  339.  
  340.  
  341.   audioctrl->ahiac_PPCCommand = AHIAC_COM_NONE;
  342.  
  343.   if( PPCLibBase != NULL )
  344.   {
  345.     PPCRunKernelObject( PPCObject, &mod );
  346.   }
  347.   else
  348.   {
  349. //kprintf( "." );
  350. //    CausePPCInterrupt();
  351.   }
  352.  
  353.   audioctrl->ahiac_PPCCommand = AHIAC_COM_START;
  354.   while( audioctrl->ahiac_PPCCommand != AHIAC_COM_FINISHED );
  355.  
  356.   // The PPC mix buffer is not m68k-cachable (or cleared); just read from it.
  357.  
  358.   memcpy( dst, audioctrl->ahiac_PPCMixBuffer, audioctrl->ahiac_BuffSizeNow );
  359.  
  360.   /*** AHIET_OUTPUTBUFFER ***/
  361.  
  362.   DoOutputBuffer(dst, audioctrl);
  363.  
  364.   /*** AHIET_CHANNELINFO ***/
  365.  
  366.   DoChannelInfo(audioctrl);
  367.  
  368.   return;
  369. }
  370.  
  371. #endif /* defined( VERSIONPPC ) */
  372.  
  373.  
  374. #if !defined( VERSIONPPC )
  375.  
  376. /******************************************************************************
  377. ** InitMixroutine *************************************************************
  378. ******************************************************************************/
  379.  
  380. // This function is used to initialize the mixer routine (called from 
  381. // AHI_AllocAudio()).
  382.  
  383. BOOL
  384. InitMixroutine ( struct AHIPrivAudioCtrl *audioctrl )
  385. {
  386.   BOOL rc = FALSE;
  387.  
  388.   // Allocate and initialize the AHIChannelData structures
  389.   // This structure could be accessed from from interrupts!
  390.  
  391.   audioctrl->ahiac_ChannelDatas = AHIAllocVec(
  392.       audioctrl->ac.ahiac_Channels * sizeof(struct AHIChannelData),
  393.       MEMF_PUBLIC | MEMF_CLEAR | MEMF_NOCACHESYNCPPC | MEMF_NOCACHESYNCM68K );
  394.  
  395.   // Allocate and initialize the AHISoundData structures
  396.   // This structure could be accessed from from interrupts!
  397.  
  398.   audioctrl->ahiac_SoundDatas = AHIAllocVec(
  399.       audioctrl->ac.ahiac_Sounds * sizeof(struct AHISoundData),
  400.       MEMF_PUBLIC | MEMF_CLEAR | MEMF_NOCACHESYNCPPC | MEMF_NOCACHESYNCM68K );
  401.  
  402.   // Allocate structures specific to the PPC version
  403.  
  404.   if( PPCObject != NULL )
  405.   {
  406.     audioctrl->ahiac_PPCMixBuffer = AHIAllocVec(
  407.         audioctrl->ac.ahiac_BuffSize,
  408.         MEMF_PUBLIC | MEMF_NOCACHEM68K );
  409.  
  410.     audioctrl->ahiac_PPCMixInterrupt = AllocVec(
  411.         sizeof( struct Interrupt ),
  412.         MEMF_PUBLIC | MEMF_CLEAR );
  413.   }
  414.  
  415.   // Now link the list and fill in the channel number for each structure.
  416.  
  417.   if( audioctrl->ahiac_ChannelDatas != NULL &&
  418.       audioctrl->ahiac_SoundDatas != NULL &&
  419.       ( PPCObject == NULL || audioctrl->ahiac_PPCMixBuffer != NULL ) &&
  420.       ( PPCObject == NULL || audioctrl->ahiac_PPCMixInterrupt != NULL ) )
  421.   {
  422.     struct AHIChannelData *cd;
  423.     struct AHISoundData   *sd;
  424.     int                    i;
  425.  
  426.     cd = audioctrl->ahiac_ChannelDatas;
  427.  
  428.     audioctrl->ahiac_WetList = cd;
  429.     audioctrl->ahiac_DryList = NULL;
  430.  
  431.     for(i = 0; i < audioctrl->ac.ahiac_Channels - 1; i++)
  432.     {
  433.       // Set Channel No
  434.       cd->cd_ChannelNo = i;
  435.  
  436.       // Set link to next channel
  437.       cd->cd_Succ = cd + 1;
  438.       cd++;
  439.     }
  440.  
  441.     // Set the last No
  442.     cd->cd_ChannelNo = i;
  443.  
  444.     // Clear the last link;
  445.     cd->cd_Succ = NULL;
  446.  
  447.  
  448.     sd = audioctrl->ahiac_SoundDatas;
  449.  
  450.     for( i = 0; i < audioctrl->ac.ahiac_Sounds; i++)
  451.     {
  452.       sd->sd_Type = AHIST_NOTYPE;
  453.       sd++;
  454.     }
  455.  
  456.     if( PPCObject != NULL )
  457.     {
  458.       int r = ~0;
  459.  
  460.       audioctrl->ahiac_PPCMixInterrupt->is_Node.ln_Type = NT_INTERRUPT;
  461.       audioctrl->ahiac_PPCMixInterrupt->is_Node.ln_Pri  = 127;
  462.       audioctrl->ahiac_PPCMixInterrupt->is_Node.ln_Name = (STRPTR) DevName;
  463.       audioctrl->ahiac_PPCMixInterrupt->is_Data         = audioctrl;
  464.       audioctrl->ahiac_PPCMixInterrupt->is_Code         = (void(*)(void)) Interrupt;
  465.  
  466.       AddIntServer( INTB_PORTS, audioctrl->ahiac_PPCMixInterrupt );
  467.  
  468. #define GetSymbol( name ) r &= AHIGetELFSymbol( #name, (void*) &name ## Ptr )
  469.  
  470.       GetSymbol( AddByteMono     );
  471.       GetSymbol( AddByteStereo   );
  472.       GetSymbol( AddBytesMono    );
  473.       GetSymbol( AddBytesStereo  );
  474.       GetSymbol( AddWordMono     );
  475.       GetSymbol( AddWordStereo   );
  476.       GetSymbol( AddWordsMono    );
  477.       GetSymbol( AddWordsStereo  );
  478.       GetSymbol( AddByteMonoB    );
  479.       GetSymbol( AddByteStereoB  );
  480.       GetSymbol( AddBytesMonoB   );
  481.       GetSymbol( AddBytesStereoB );
  482.       GetSymbol( AddWordMonoB    );
  483.       GetSymbol( AddWordStereoB  );
  484.       GetSymbol( AddWordsMonoB   );
  485.       GetSymbol( AddWordsStereoB );
  486.  
  487.       GetSymbol( AddLofiByteMono     );
  488.       GetSymbol( AddLofiByteStereo   );
  489.       GetSymbol( AddLofiBytesMono    );
  490.       GetSymbol( AddLofiBytesStereo  );
  491.       GetSymbol( AddLofiWordMono     );
  492.       GetSymbol( AddLofiWordStereo   );
  493.       GetSymbol( AddLofiWordsMono    );
  494.       GetSymbol( AddLofiWordsStereo  );
  495.       GetSymbol( AddLofiByteMonoB    );
  496.       GetSymbol( AddLofiByteStereoB  );
  497.       GetSymbol( AddLofiBytesMonoB   );
  498.       GetSymbol( AddLofiBytesStereoB );
  499.       GetSymbol( AddLofiWordMonoB    );
  500.       GetSymbol( AddLofiWordStereoB  );
  501.       GetSymbol( AddLofiWordsMonoB   );
  502.       GetSymbol( AddLofiWordsStereoB );
  503.  
  504. #undef GetSymbol
  505.  
  506.       // Sucess?
  507.  
  508.       if( r != 0 )
  509.       {
  510.         if( PPCLibBase != NULL )
  511.         {
  512.           rc = TRUE;
  513.         }
  514.         else
  515.         {
  516.           // Initialize the WarpUp side
  517.         
  518.           struct PPCArgs args = 
  519.           {
  520.             NULL,
  521.             0,
  522.             0,
  523.             NULL,
  524.             0,
  525.             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  526.             { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }
  527.           };
  528.  
  529.           if( AHIGetELFSymbol( "WarpInit", &args.PP_Code ) )
  530.           {
  531.             int status;
  532.  
  533. //            status = RunPPC( &args );
  534.             
  535. //            if( status == PPERR_SUCCESS )
  536.             {
  537.               rc = TRUE;
  538.             }
  539.           }
  540.  
  541.         }
  542.       }
  543.     }
  544.     else // PPCObject
  545.     {
  546.  
  547. #define GetSymbol( name ) name ## Ptr = name;
  548.  
  549.       GetSymbol( AddByteMono     );
  550.       GetSymbol( AddByteStereo   );
  551.       GetSymbol( AddBytesMono    );
  552.       GetSymbol( AddBytesStereo  );
  553.       GetSymbol( AddWordMono     );
  554.       GetSymbol( AddWordStereo   );
  555.       GetSymbol( AddWordsMono    );
  556.       GetSymbol( AddWordsStereo  );
  557.       GetSymbol( AddByteMonoB    );
  558.       GetSymbol( AddByteStereoB  );
  559.       GetSymbol( AddBytesMonoB   );
  560.       GetSymbol( AddBytesStereoB );
  561.       GetSymbol( AddWordMonoB    );
  562.       GetSymbol( AddWordStereoB  );
  563.       GetSymbol( AddWordsMonoB   );
  564.       GetSymbol( AddWordsStereoB );
  565.  
  566.       GetSymbol( AddLofiByteMono     );
  567.       GetSymbol( AddLofiByteStereo   );
  568.       GetSymbol( AddLofiBytesMono    );
  569.       GetSymbol( AddLofiBytesStereo  );
  570.       GetSymbol( AddLofiWordMono     );
  571.       GetSymbol( AddLofiWordStereo   );
  572.       GetSymbol( AddLofiWordsMono    );
  573.       GetSymbol( AddLofiWordsStereo  );
  574.       GetSymbol( AddLofiByteMonoB    );
  575.       GetSymbol( AddLofiByteStereoB  );
  576.       GetSymbol( AddLofiBytesMonoB   );
  577.       GetSymbol( AddLofiBytesStereoB );
  578.       GetSymbol( AddLofiWordMonoB    );
  579.       GetSymbol( AddLofiWordStereoB  );
  580.       GetSymbol( AddLofiWordsMonoB   );
  581.       GetSymbol( AddLofiWordsStereoB );
  582.  
  583. #undef GetSymbol
  584.  
  585.       // Sucess!
  586.     
  587.       rc = TRUE;
  588.     }
  589.   }
  590.  
  591.   return rc;
  592. }
  593.  
  594. /******************************************************************************
  595. ** CleanUpMixroutine **********************************************************
  596. ******************************************************************************/
  597.  
  598. // This function is used to clean up after the mixer routine (called from 
  599. // AHI_FreeAudio()).
  600.  
  601. void
  602. CleanUpMixroutine( struct AHIPrivAudioCtrl *audioctrl )
  603. {
  604.   if( audioctrl->ahiac_PPCMixInterrupt != NULL )
  605.   {
  606.     RemIntServer( INTB_PORTS, audioctrl->ahiac_PPCMixInterrupt );
  607.   }
  608.   FreeVec( audioctrl->ahiac_PPCMixInterrupt );
  609.   AHIFreeVec( audioctrl->ahiac_PPCMixBuffer );
  610.   AHIFreeVec( audioctrl->ahiac_SoundDatas );
  611.   AHIFreeVec( audioctrl->ahiac_ChannelDatas );
  612. }
  613.  
  614. /******************************************************************************
  615. ** calcMasterVolumeTable ******************************************************
  616. ******************************************************************************/
  617.  
  618. // This function is called each time the master volume changes.
  619.  
  620. void
  621. calcMasterVolumeTable ( struct AHIPrivAudioCtrl *audioctrl )
  622. {
  623.   // Do nothing, no tables are used!
  624. }
  625.  
  626.  
  627. /******************************************************************************
  628. ** initSignedTable ************************************************************
  629. ******************************************************************************/
  630.  
  631. // This function sets up the multiplication tables used when mixing signed
  632. // samples.
  633.  
  634. BOOL
  635. initSignedTable ( struct AHIPrivAudioCtrl *audioctrl )
  636. {
  637.   // No tables are used, return success.
  638.   return TRUE;
  639. }
  640.  
  641.  
  642. /******************************************************************************
  643. ** calcSignedTable ************************************************************
  644. ******************************************************************************/
  645.  
  646. // This function is called each time the master volume changes
  647.  
  648. void
  649. calcSignedTable ( struct AHIPrivAudioCtrl *audioctrl )
  650. {
  651.   // Do nothing, no tables are used!
  652. }
  653.  
  654.  
  655. /******************************************************************************
  656. ** initUnsignedTable **********************************************************
  657. ******************************************************************************/
  658.  
  659. // This function sets up the multiplication tables used when mixing unsigned
  660. // samples (obsolete since V4, but kept for backward compability with
  661. // Delitracker II).
  662.  
  663. BOOL
  664. initUnsignedTable ( struct AHIPrivAudioCtrl *audioctrl )
  665. {
  666.   // No tables are used, return success.
  667.   return TRUE;
  668. }
  669.  
  670.  
  671. /******************************************************************************
  672. ** calcUnsignedTable **********************************************************
  673. ******************************************************************************/
  674.  
  675. // This function is called each time the master volume changes
  676.  
  677. void
  678. calcUnsignedTable ( struct AHIPrivAudioCtrl *audioctrl )
  679. {
  680.   // Do nothing, no tables are used!
  681. }
  682.  
  683.  
  684. /******************************************************************************
  685. ** SelectAddRoutine ***********************************************************
  686. ******************************************************************************/
  687.  
  688. // This routine gets called each time there is reason to believe that a new
  689. // add-routine should be used (new sound selected, volume changed,
  690. // mastervolume changed)
  691.  
  692. // Based on VolumeLeft, VolumeRight and SampleType, fill in ScaleLeft,
  693. // ScaleRight and AddRoutine.
  694.  
  695. void
  696. SelectAddRoutine ( Fixed     VolumeLeft,
  697.                    Fixed     VolumeRight,
  698.                    ULONG     SampleType,
  699.                    struct    AHIPrivAudioCtrl *audioctrl,
  700.                    LONG     *ScaleLeft,
  701.                    LONG     *ScaleRight,
  702.                    ADDFUNC **AddRoutine )
  703.  
  704. {
  705.   // This version only cares about the sample format and does not use any
  706.   // optimized add-routines.
  707.  
  708.   // Scale the volume
  709.  
  710.   VolumeLeft  = VolumeLeft  * (audioctrl->ahiac_MasterVolume >> 8) / 
  711.                               (audioctrl->ahiac_Channels2 << 8);
  712.  
  713.   VolumeRight = VolumeRight * (audioctrl->ahiac_MasterVolume >> 8) / 
  714.                               (audioctrl->ahiac_Channels2 << 8);
  715.  
  716.   // First, select HiFi or LoFi...
  717.  
  718.   if( audioctrl->ac.ahiac_Flags & AHIACF_HIFI )
  719.   {
  720.  
  721.     // Then, check the output format...
  722.  
  723.     switch(audioctrl->ac.ahiac_BuffType)
  724.     {
  725.  
  726.       case AHIST_M32S:
  727.  
  728.         // ...and then the source format.
  729.  
  730.         switch(SampleType)
  731.         {
  732.           case AHIST_M8S:
  733.           case AHIST_BW|AHIST_M8S:
  734.             *ScaleLeft  = VolumeLeft + VolumeRight;
  735.             *ScaleRight = 0;
  736.             if(SampleType & AHIST_BW)
  737.               *AddRoutine = AddByteMonoBPtr;
  738.             else
  739.               *AddRoutine = AddByteMonoPtr;
  740.             break;
  741.  
  742.           case AHIST_S8S:
  743.           case AHIST_BW|AHIST_S8S:
  744.             *ScaleLeft  = VolumeLeft;
  745.             *ScaleRight = VolumeRight;
  746.             if(SampleType & AHIST_BW)
  747.               *AddRoutine = AddBytesMonoBPtr;
  748.             else
  749.               *AddRoutine = AddBytesMonoPtr;
  750.             break;
  751.  
  752.           case AHIST_M16S:
  753.           case AHIST_BW|AHIST_M16S:
  754.             *ScaleLeft  = VolumeLeft + VolumeRight;
  755.             *ScaleRight = 0;
  756.             if(SampleType & AHIST_BW)
  757.               *AddRoutine = AddWordMonoBPtr;
  758.             else
  759.               *AddRoutine = AddWordMonoPtr;
  760.             break;
  761.  
  762.           case AHIST_S16S:
  763.           case AHIST_BW|AHIST_S16S:
  764.             *ScaleLeft  = VolumeLeft;
  765.             *ScaleRight = VolumeRight;
  766.             if(SampleType & AHIST_BW)
  767.               *AddRoutine = AddWordsMonoBPtr;
  768.             else
  769.               *AddRoutine = AddWordsMonoPtr;
  770.             break;
  771.  
  772.           default:
  773.             *ScaleLeft  = 0;
  774.             *ScaleRight = 0;
  775.             *AddRoutine = NULL;
  776.             break;
  777.         }
  778.         break;
  779.  
  780.       case AHIST_S32S:
  781.  
  782.         // ...and then the source format.
  783.  
  784.         switch(SampleType)
  785.         {
  786.           case AHIST_M8S:
  787.           case AHIST_BW|AHIST_M8S:
  788.             *ScaleLeft  = VolumeLeft;
  789.             *ScaleRight = VolumeRight;
  790.             if(SampleType & AHIST_BW)
  791.               *AddRoutine = AddByteStereoBPtr;
  792.             else
  793.               *AddRoutine = AddByteStereoPtr;
  794.             break;
  795.  
  796.           case AHIST_S8S:
  797.           case AHIST_BW|AHIST_S8S:
  798.             *ScaleLeft  = VolumeLeft;
  799.             *ScaleRight = VolumeRight;
  800.             if(SampleType & AHIST_BW)
  801.               *AddRoutine = AddBytesStereoBPtr;
  802.             else
  803.               *AddRoutine = AddBytesStereoPtr;
  804.             break;
  805.  
  806.           case AHIST_M16S:
  807.           case AHIST_BW|AHIST_M16S:
  808.             *ScaleLeft  = VolumeLeft;
  809.             *ScaleRight = VolumeRight;
  810.             if(SampleType & AHIST_BW)
  811.               *AddRoutine = AddWordStereoBPtr;
  812.             else
  813.               *AddRoutine = AddWordStereoPtr;
  814.             break;
  815.  
  816.           case AHIST_S16S:
  817.           case AHIST_BW|AHIST_S16S:
  818.             *ScaleLeft  = VolumeLeft;
  819.             *ScaleRight = VolumeRight;
  820.             if(SampleType & AHIST_BW)
  821.               *AddRoutine = AddWordsStereoBPtr;
  822.             else
  823.               *AddRoutine = AddWordsStereoPtr;
  824.             break;
  825.  
  826.           default:
  827.             *ScaleLeft  = 0;
  828.             *ScaleRight = 0;
  829.             *AddRoutine = NULL;
  830.             break;
  831.         }
  832.         break;
  833.  
  834.       default:
  835.         *ScaleLeft  = 0;
  836.         *ScaleRight = 0;
  837.         *AddRoutine = NULL;
  838.         break;
  839.     }
  840.   }
  841.   else
  842.   {
  843.  
  844.     // Then, check the output format...
  845.  
  846.     switch(audioctrl->ac.ahiac_BuffType)
  847.     {
  848.  
  849.       case AHIST_M16S:
  850.  
  851.         // ...and then the source format.
  852.  
  853.         switch(SampleType)
  854.         {
  855.           case AHIST_M8S:
  856.           case AHIST_BW|AHIST_M8S:
  857.             *ScaleLeft  = VolumeLeft + VolumeRight;
  858.             *ScaleRight = 0;
  859.             if(SampleType & AHIST_BW)
  860.               *AddRoutine = AddLofiByteMonoBPtr;
  861.             else
  862.               *AddRoutine = AddLofiByteMonoPtr;
  863.             break;
  864.  
  865.           case AHIST_S8S:
  866.           case AHIST_BW|AHIST_S8S:
  867.             *ScaleLeft  = VolumeLeft;
  868.             *ScaleRight = VolumeRight;
  869.             if(SampleType & AHIST_BW)
  870.               *AddRoutine = AddLofiBytesMonoBPtr;
  871.             else
  872.               *AddRoutine = AddLofiBytesMonoPtr;
  873.             break;
  874.  
  875.           case AHIST_M16S:
  876.           case AHIST_BW|AHIST_M16S:
  877.             *ScaleLeft  = VolumeLeft + VolumeRight;
  878.             *ScaleRight = 0;
  879.             if(SampleType & AHIST_BW)
  880.               *AddRoutine = AddLofiWordMonoBPtr;
  881.             else
  882.               *AddRoutine = AddLofiWordMonoPtr;
  883.             break;
  884.  
  885.           case AHIST_S16S:
  886.           case AHIST_BW|AHIST_S16S:
  887.             *ScaleLeft  = VolumeLeft;
  888.             *ScaleRight = VolumeRight;
  889.             if(SampleType & AHIST_BW)
  890.               *AddRoutine = AddLofiWordsMonoBPtr;
  891.             else
  892.               *AddRoutine = AddLofiWordsMonoPtr;
  893.             break;
  894.  
  895.           default:
  896.             *ScaleLeft  = 0;
  897.             *ScaleRight = 0;
  898.             *AddRoutine = NULL;
  899.             break;
  900.         }
  901.         break;
  902.  
  903.       case AHIST_S16S:
  904.  
  905.         // ...and then the source format.
  906.  
  907.         switch(SampleType)
  908.         {
  909.           case AHIST_M8S:
  910.           case AHIST_BW|AHIST_M8S:
  911.             *ScaleLeft  = VolumeLeft;
  912.             *ScaleRight = VolumeRight;
  913.             if(SampleType & AHIST_BW)
  914.               *AddRoutine = AddLofiByteStereoBPtr;
  915.             else
  916.               *AddRoutine = AddLofiByteStereoPtr;
  917.             break;
  918.  
  919.           case AHIST_S8S:
  920.           case AHIST_BW|AHIST_S8S:
  921.             *ScaleLeft  = VolumeLeft;
  922.             *ScaleRight = VolumeRight;
  923.             if(SampleType & AHIST_BW)
  924.               *AddRoutine = AddLofiBytesStereoBPtr;
  925.             else
  926.               *AddRoutine = AddLofiBytesStereoPtr;
  927.             break;
  928.  
  929.           case AHIST_M16S:
  930.           case AHIST_BW|AHIST_M16S:
  931.             *ScaleLeft  = VolumeLeft;
  932.             *ScaleRight = VolumeRight;
  933.             if(SampleType & AHIST_BW)
  934.               *AddRoutine = AddLofiWordStereoBPtr;
  935.             else
  936.               *AddRoutine = AddLofiWordStereoPtr;
  937.             break;
  938.  
  939.           case AHIST_S16S:
  940.           case AHIST_BW|AHIST_S16S:
  941.             *ScaleLeft  = VolumeLeft;
  942.             *ScaleRight = VolumeRight;
  943.             if(SampleType & AHIST_BW)
  944.               *AddRoutine = AddLofiWordsStereoBPtr;
  945.             else
  946.               *AddRoutine = AddLofiWordsStereoPtr;
  947.             break;
  948.  
  949.           default:
  950.             *ScaleLeft  = 0;
  951.             *ScaleRight = 0;
  952.             *AddRoutine = NULL;
  953.             break;
  954.         }
  955.         break;
  956.  
  957.       default:
  958.         *ScaleLeft  = 0;
  959.         *ScaleRight = 0;
  960.         *AddRoutine = NULL;
  961.         break;
  962.     }
  963.   }
  964. }
  965.  
  966. #endif /* !defined( VERSIONPPC ) */
  967.  
  968.  
  969. /******************************************************************************
  970. ** Mix ************************************************************************
  971. ******************************************************************************/
  972.  
  973. // This is the function that the driver calls each time it want more data
  974. // to play. 
  975.  
  976. // There is a stub function in asmfuncs.s called Mix() that saves d0-d1/a0-a1
  977. // and calls MixGeneric. This stub is only assembled if VERSIONGEN is set.
  978.  
  979. #if !defined( VERSIONPPC )
  980. void ASMCALL
  981. MixGeneric ( REG(a0, struct Hook *Hook), 
  982.              REG(a1, void *dst), 
  983.              REG(a2, struct AHIPrivAudioCtrl *audioctrl) )
  984. #else
  985. void
  986. MixGeneric ( struct Hook *Hook, 
  987.              void *dst, 
  988.              struct AHIPrivAudioCtrl *audioctrl )
  989. #endif
  990. {
  991.   struct AHIChannelData    *cd;
  992.   void                  *dstptr;
  993.   LONG                   samplesleft;
  994.  
  995.   /* Clear the buffer */
  996.  
  997.   memset( dst, 0, audioctrl->ahiac_BuffSizeNow );
  998.  
  999.   /* Mix the samples */
  1000.  
  1001.   audioctrl->ahiac_WetOrDry = AHIEDM_WET;
  1002.  
  1003.   cd = audioctrl->ahiac_WetList;
  1004.  
  1005.   while(TRUE)
  1006.   {
  1007.     while(cd != NULL) // .nextchannel
  1008.     {
  1009.       samplesleft = audioctrl->ac.ahiac_BuffSamples;
  1010.       dstptr      = dst;
  1011.  
  1012.       while(TRUE) // .contchannel
  1013.       {
  1014.         LONG samples;
  1015.         LONG processed;
  1016.  
  1017.         /* Call Sound Hook */
  1018.  
  1019.         if(cd->cd_EOS)
  1020.         {
  1021.           cd->cd_EOS = FALSE;
  1022.           if(audioctrl->ac.ahiac_SoundFunc != NULL)
  1023.           {
  1024.             CallSoundHook( audioctrl, &cd->cd_ChannelNo );
  1025.           }
  1026.         }
  1027.  
  1028.         processed = 0;
  1029.  
  1030.         if( cd->cd_AntiClickCount > 0 && cd->cd_FreqOK && cd->cd_SoundOK )
  1031.         {
  1032.           // Sound is ok and we're looking for a zero-crossing.
  1033.  
  1034.           LONG try_samples;
  1035.  
  1036.           samples     = min( samplesleft, cd->cd_Samples );
  1037.           try_samples = min( samples, cd->cd_AntiClickCount );
  1038.  
  1039.           if( try_samples > 0 )
  1040.           {
  1041.             cd->cd_TempStartPointL = cd->cd_StartPointL;
  1042.             cd->cd_TempStartPointR = cd->cd_StartPointR;
  1043.  
  1044.             processed = ((ADDFUNC *) cd->cd_AddRoutine)( try_samples,
  1045.                                                          cd->cd_ScaleLeft,
  1046.                                                          cd->cd_ScaleRight,
  1047.                                                         &cd->cd_TempStartPointL,
  1048.                                                         &cd->cd_TempStartPointR,
  1049.                                                          cd->cd_DataStart,
  1050.                                                         &dstptr,
  1051.                                                          cd->cd_FirstOffsetI,
  1052.                                                          cd->cd_Add,
  1053.                                                         &cd->cd_Offset, 
  1054.                                                          TRUE );
  1055.             cd->cd_Samples -= processed;
  1056.             samplesleft    -= processed;
  1057.           }
  1058.           else
  1059.           {
  1060.             processed = 0;
  1061.           }
  1062.  
  1063.           if( try_samples == cd->cd_AntiClickCount ||
  1064.               processed != samples )
  1065.           {
  1066.             // We either found a zero-crossing or looked as far as
  1067.             // we were allowed to.
  1068.             
  1069.             // Note that the sample end was NOT reached! If it was,
  1070.             // cd_Samples will be zero and the second cd_AddRoutine
  1071.             // call below will have no effect, and the cd_Next#?
  1072.             // variables will be copied instead.
  1073.  
  1074.             // Now start the delayed sound.
  1075.  
  1076.             if( cd->cd_VolDelayed )
  1077.             {
  1078.               cd->cd_VolDelayed = FALSE;
  1079.               cd->cd_VolumeLeft  = cd->cd_DelayedVolumeLeft;
  1080.               cd->cd_VolumeRight = cd->cd_DelayedVolumeRight;
  1081.               cd->cd_ScaleLeft   = cd->cd_DelayedScaleLeft;
  1082.               cd->cd_ScaleRight  = cd->cd_DelayedScaleRight;
  1083.               cd->cd_AddRoutine  = cd->cd_DelayedAddRoutine;
  1084.             }
  1085.  
  1086.             if( cd->cd_FreqDelayed )
  1087.             {
  1088.               cd->cd_FreqDelayed = FALSE;
  1089.               cd->cd_FreqOK      = cd->cd_DelayedFreqOK;
  1090.               cd->cd_Add         = cd->cd_DelayedAdd;
  1091.               
  1092.               // Since we have advanced, cd_Samples must be recalculated!
  1093.               cd->cd_Samples     = CalcSamples( cd->cd_Add,
  1094.                                                 cd->cd_Type,
  1095.                                                 cd->cd_LastOffset,
  1096.                                                 cd->cd_Offset );
  1097.             }
  1098.  
  1099.             if( cd->cd_SoundDelayed )
  1100.             {
  1101.               cd->cd_SoundDelayed = FALSE;
  1102.  
  1103.               cd->cd_SoundOK       = cd->cd_DelayedSoundOK;
  1104.  
  1105.               cd->cd_Offset        = cd->cd_DelayedOffset;
  1106.               cd->cd_FirstOffsetI  = cd->cd_DelayedFirstOffsetI;
  1107.               cd->cd_LastOffset    = cd->cd_DelayedLastOffset;
  1108.               cd->cd_DataStart     = cd->cd_DelayedDataStart;
  1109.  
  1110.               cd->cd_Type          = cd->cd_DelayedType;
  1111.               cd->cd_AddRoutine    = cd->cd_DelayedAddRoutine;
  1112.  
  1113.               cd->cd_Samples       = cd->cd_DelayedSamples;
  1114.  
  1115.               cd->cd_ScaleLeft     = cd->cd_DelayedScaleLeft;
  1116.               cd->cd_ScaleRight    = cd->cd_DelayedScaleRight;
  1117.               cd->cd_AddRoutine    = cd->cd_DelayedAddRoutine;
  1118.             }
  1119.           }
  1120.  
  1121.           if( cd->cd_VolDelayed || cd->cd_FreqDelayed || cd->cd_SoundDelayed )
  1122.           {
  1123.             cd->cd_AntiClickCount -= processed;
  1124.           }
  1125.           else
  1126.           {
  1127.             cd->cd_AntiClickCount = 0;
  1128.           }
  1129.         }
  1130.  
  1131.         if( cd->cd_FreqOK && cd->cd_SoundOK )
  1132.         {
  1133.           // Sound is still ok, let's rock'n roll.
  1134.  
  1135.           samples = min( samplesleft, cd->cd_Samples );
  1136.  
  1137.           if( samples > 0 )
  1138.           {
  1139.             cd->cd_TempStartPointL = cd->cd_StartPointL;
  1140.             cd->cd_TempStartPointR = cd->cd_StartPointR;
  1141.  
  1142.             processed = ((ADDFUNC *) cd->cd_AddRoutine)( samples,
  1143.                                                          cd->cd_ScaleLeft,
  1144.                                                          cd->cd_ScaleRight,
  1145.                                                         &cd->cd_TempStartPointL,
  1146.                                                         &cd->cd_TempStartPointR,
  1147.                                                          cd->cd_DataStart,
  1148.                                                         &dstptr,
  1149.                                                          cd->cd_FirstOffsetI,
  1150.                                                          cd->cd_Add,
  1151.                                                         &cd->cd_Offset,
  1152.                                                          FALSE );
  1153.             cd->cd_Samples -= processed;
  1154.             samplesleft    -= processed;
  1155.           }
  1156.  
  1157.           if( cd->cd_Samples == 0 )
  1158.           {
  1159.             /* Linear interpol. stuff */
  1160.  
  1161.             cd->cd_StartPointL = cd->cd_TempStartPointL;
  1162.             cd->cd_StartPointR = cd->cd_TempStartPointR;
  1163.  
  1164.             /*
  1165.             ** Offset always points OUTSIDE the sample after this
  1166.             ** call.  Ie, if we read a sample at offset (Offset.I)
  1167.             ** now, it does not belong to the sample just played.
  1168.             ** This is true for both backward and forward mixing.
  1169.             */
  1170.  
  1171.  
  1172.             /* What we do now is to calculate how much futher we have
  1173.                advanced. */
  1174.  
  1175.               cd->cd_Offset -= cd->cd_LastOffset;
  1176.  
  1177.             /*
  1178.             ** Offset should now be added to the NEXT Offset. Offset
  1179.             ** is positive of the sample was mixed forwards, and
  1180.             ** negative if the sample was mixed backwards.  There is
  1181.             ** one catch, however.  If the direction is about to
  1182.             ** change now, Offset should instead be SUBTRACTED.
  1183.             ** Let's check:
  1184.             */
  1185.  
  1186.             if( (cd->cd_Type ^ cd->cd_NextType) & AHIST_BW )
  1187.             {
  1188.               cd->cd_Offset = -cd->cd_Offset;
  1189.             }
  1190.  
  1191.             cd->cd_Offset += cd->cd_NextOffset;
  1192.  
  1193.             cd->cd_FirstOffsetI = cd->cd_Offset >> 32;
  1194.  
  1195.             /*
  1196.             ** But what if the next sample is so short that we just
  1197.             ** passed it!?  Here is the nice part.  CalcSamples
  1198.             ** checks this, and sets cd_Samples to 0 in that case.
  1199.             ** And the add routines doesn't do anything when asked to
  1200.             ** mix 0 samples.  Assume we have passed a sample with 4
  1201.             ** samples, and the next one is only 3.  CalcSamples
  1202.             ** returns 0.  The (ADDFUNC) call above does not do
  1203.             ** anything at all, OffsetI is still 4.  Now we subtract
  1204.             ** LastOffsetI, which is 3.  Result:  We have passed the
  1205.             ** sample with 1.  And guess what?  That's in range.
  1206.             */
  1207.  
  1208.             /* Now, let's copy the rest of the cd_Next#? stuff... */
  1209.  
  1210.             cd->cd_FreqOK        = cd->cd_NextFreqOK;
  1211.             cd->cd_SoundOK       = cd->cd_NextSoundOK;
  1212.             cd->cd_Add           = cd->cd_NextAdd;
  1213.             cd->cd_DataStart     = cd->cd_NextDataStart;
  1214.             cd->cd_LastOffset    = cd->cd_NextLastOffset;
  1215.             cd->cd_ScaleLeft     = cd->cd_NextScaleLeft;
  1216.             cd->cd_ScaleRight    = cd->cd_NextScaleRight;
  1217.             cd->cd_AddRoutine    = cd->cd_NextAddRoutine;
  1218.             cd->cd_VolumeLeft    = cd->cd_NextVolumeLeft;
  1219.             cd->cd_VolumeRight   = cd->cd_NextVolumeRight;
  1220.             cd->cd_Type          = cd->cd_NextType;
  1221.  
  1222.             cd->cd_Samples = CalcSamples( cd->cd_Add,
  1223.                                           cd->cd_Type,
  1224.                                           cd->cd_LastOffset,
  1225.                                           cd->cd_Offset );
  1226.  
  1227.             /* Also update all cd_Delayed#? stuff */
  1228.  
  1229.             if( !cd->cd_VolDelayed )
  1230.             {
  1231.               cd->cd_DelayedVolumeLeft    = cd->cd_NextVolumeLeft;
  1232.               cd->cd_DelayedVolumeRight   = cd->cd_NextVolumeRight;
  1233.             }
  1234.  
  1235.             if( !cd->cd_FreqDelayed )
  1236.             {
  1237.               cd->cd_DelayedFreqOK        = cd->cd_NextFreqOK;
  1238.               cd->cd_DelayedAdd           = cd->cd_NextAdd;
  1239.             }
  1240.  
  1241.             if( !cd->cd_SoundDelayed )
  1242.             {
  1243.               cd->cd_DelayedSoundOK       = cd->cd_NextSoundOK;
  1244.               cd->cd_DelayedOffset        = cd->cd_NextOffset;
  1245.               cd->cd_DelayedFirstOffsetI  = cd->cd_FirstOffsetI;  // See above
  1246.               cd->cd_DelayedLastOffset    = cd->cd_NextLastOffset;
  1247.               cd->cd_DelayedType          = cd->cd_NextType;
  1248.               cd->cd_DelayedDataStart     = cd->cd_NextDataStart;
  1249.             }
  1250.  
  1251.             if( !cd->cd_VolDelayed && !cd->cd_SoundDelayed )
  1252.             {
  1253.               cd->cd_DelayedScaleLeft     = cd->cd_NextScaleLeft;
  1254.               cd->cd_DelayedScaleRight    = cd->cd_NextScaleRight;
  1255.               cd->cd_DelayedAddRoutine    = cd->cd_NextAddRoutine;
  1256.             }
  1257.  
  1258.             if( !cd->cd_FreqDelayed && !cd->cd_SoundDelayed )
  1259.             {
  1260.               cd->cd_DelayedSamples       = cd->cd_Samples;
  1261.             }
  1262.  
  1263.             cd->cd_EOS = TRUE;      // signal End-Of-Sample
  1264.             continue;               // .contchannel (same channel, new sound)
  1265.           }
  1266.         } // FreqOK && SoundOK
  1267.  
  1268.         break; // .contchannel
  1269.  
  1270.       } // while(TRUE)
  1271.  
  1272.       cd = cd->cd_Succ;
  1273.     } // while(cd)
  1274.  
  1275.     if(audioctrl->ahiac_WetOrDry == AHIEDM_WET)
  1276.     {
  1277.       audioctrl->ahiac_WetOrDry = AHIEDM_DRY;
  1278.  
  1279.       /*** AHIET_DSPECHO ***/
  1280.       if(audioctrl->ahiac_EffDSPEchoStruct != NULL)
  1281.       {
  1282.         audioctrl->ahiac_EffDSPEchoStruct->ahiecho_Code(
  1283.             audioctrl->ahiac_EffDSPEchoStruct, dst, audioctrl);
  1284.       }
  1285.  
  1286.       cd = audioctrl->ahiac_DryList;
  1287.  
  1288.       if(audioctrl->ac.ahiac_Flags & AHIACF_POSTPROC)
  1289.       {
  1290.         /*** AHIET_MASTERVOLUME ***/
  1291.  
  1292.         DoMasterVolume(dst, audioctrl);
  1293.  
  1294.         /*
  1295.         ** When AHIACB_POSTPROC is set, the dry data shall be placed
  1296.         ** immediate after the wet data. This is done by modifying the
  1297.         ** dst pointer
  1298.         */
  1299.  
  1300.         dst = (char *) dst + audioctrl->ac.ahiac_BuffSamples * 
  1301.                              InternalSampleFrameSize(audioctrl->ac.ahiac_BuffType);
  1302.       }
  1303.  
  1304.       continue; /* while(TRUE) */
  1305.     }
  1306.     else
  1307.     {
  1308.       break; /* while(TRUE) */
  1309.     }
  1310.   } // while(TRUE)
  1311.  
  1312.   /*** AHIET_MASTERVOLUME ***/
  1313.  
  1314.   DoMasterVolume(dst, audioctrl);
  1315.  
  1316. #if !defined( VERSIONPPC )
  1317.  
  1318.   // This is handled in m68k code, in order to minimize cache flushes.
  1319.  
  1320.   /*** AHIET_OUTPUTBUFFER ***/
  1321.  
  1322.   DoOutputBuffer(dst, audioctrl);
  1323.  
  1324.   /*** AHIET_CHANNELINFO ***/
  1325.  
  1326.   DoChannelInfo(audioctrl);
  1327.  
  1328. #endif /* !defined( VERSIONPPC ) */
  1329.  
  1330.   return;
  1331. }
  1332.  
  1333. /*
  1334. ** This function would be better if it was written in assembler,
  1335. ** since overflow could then be detected. Instead we reduce the
  1336. ** number of bits to 20 and then scale and compare.
  1337. */
  1338.  
  1339. static void
  1340. DoMasterVolume ( void *buffer,
  1341.                  struct AHIPrivAudioCtrl *audioctrl )
  1342. {
  1343.   int   cnt;
  1344.   LONG  vol;
  1345.   LONG  sample;
  1346.  
  1347.   cnt = audioctrl->ac.ahiac_BuffSamples;
  1348.  
  1349.   switch(audioctrl->ac.ahiac_BuffType)
  1350.   {
  1351.  
  1352.     case AHIST_M16S:
  1353.     case AHIST_M32S:
  1354.       break;
  1355.  
  1356.     case AHIST_S16S:
  1357.     case AHIST_S32S:
  1358.       cnt *= 2;
  1359.       break;
  1360.  
  1361.     default:
  1362.       return; // Panic
  1363.   }
  1364.  
  1365.   if( audioctrl->ac.ahiac_BuffType == AHIST_M32S
  1366.       || audioctrl->ac.ahiac_BuffType == AHIST_S32S )
  1367.   {
  1368.     LONG *dst = buffer;
  1369.  
  1370.     vol = audioctrl->ahiac_SetMasterVolume >> 8;
  1371.  
  1372.     while(cnt > 0)
  1373.     {
  1374.       cnt--;
  1375.     
  1376.       sample = (*dst >> 12) * vol;
  1377.  
  1378.       if(sample > (LONG) 0x07ffffff)
  1379.         sample = 0x07ffffff;
  1380.       else if(sample < (LONG) 0xf8000000)
  1381.         sample = 0xf8000000;
  1382.  
  1383.       *dst++ = sample << 4;
  1384.     }
  1385.   }
  1386.   else
  1387.   {
  1388.     WORD *dst = buffer;
  1389.  
  1390.     vol = audioctrl->ahiac_SetMasterVolume >> 4;
  1391.  
  1392.     while(cnt > 0)
  1393.     {
  1394.       cnt--;
  1395.     
  1396.       sample = *dst * vol;
  1397.  
  1398.       if(sample > (LONG) 0x07ffffff)
  1399.         sample = 0x07ffffff;
  1400.       else if(sample < (LONG) 0xf8000000)
  1401.         sample = 0xf8000000;
  1402.  
  1403.       *dst++ = sample >> 12;
  1404.     }
  1405.   
  1406.   }
  1407. }
  1408.  
  1409.  
  1410. #if !defined( VERSIONPPC )
  1411.  
  1412. static void
  1413. DoOutputBuffer ( void *buffer,
  1414.                  struct AHIPrivAudioCtrl *audioctrl )
  1415. {
  1416.   struct AHIEffOutputBuffer *ob;
  1417.  
  1418.   ob = audioctrl->ahiac_EffOutputBufferStruct;
  1419.  
  1420.   if(ob != NULL)
  1421.   {
  1422.     ob->ahieob_Buffer = buffer;
  1423.     ob->ahieob_Length = audioctrl->ac.ahiac_BuffSamples;
  1424.     ob->ahieob_Type   = audioctrl->ac.ahiac_BuffType;
  1425.  
  1426.     CallHookPkt( ob->ahieob_Func,
  1427.                  audioctrl,
  1428.                  ob);
  1429.   }
  1430. }
  1431.  
  1432. static void
  1433. DoChannelInfo ( struct AHIPrivAudioCtrl *audioctrl )
  1434. {
  1435.   struct AHIEffChannelInfo *ci;
  1436.   struct AHIChannelData    *cd;
  1437.   ULONG                    *offsets;
  1438.  
  1439.   ci = audioctrl->ahiac_EffChannelInfoStruct;
  1440.  
  1441.   if(ci != NULL)
  1442.   {
  1443.     int i;
  1444.     
  1445.     cd      = audioctrl->ahiac_ChannelDatas;
  1446.     offsets = ci->ahieci_Offset;
  1447.  
  1448.     for(i = ci->ahieci_Channels; i > 0; i--)
  1449.     {
  1450.       *offsets++ = cd->cd_Offset >> 32;
  1451.       cd++;
  1452.     }
  1453.     
  1454.     CallHookPkt( ci->ahieci_Func,
  1455.                  audioctrl,
  1456.                  ci );
  1457.   }
  1458. }
  1459.  
  1460. #endif /* !defined( VERSIONPPC ) */
  1461.  
  1462.  
  1463. /******************************************************************************
  1464. ** CalcSamples ****************************************************************
  1465. ******************************************************************************/
  1466.  
  1467. LONG
  1468. CalcSamples ( Fixed64 Add,
  1469.               ULONG   Type,
  1470.               Fixed64 LastOffset,
  1471.               Fixed64 Offset )
  1472.  
  1473. {
  1474.   Fixed64 len;
  1475.  
  1476.   if(Type & AHIST_BW)
  1477.   {
  1478.     len = Offset - LastOffset; 
  1479.   }
  1480.   else
  1481.   {
  1482.     len = LastOffset - Offset;
  1483.   }
  1484.  
  1485.   if(len < 0 || Add == 0) return 0; // Error!
  1486.  
  1487.   return (LONG) (len / Add) + 1;
  1488. }
  1489.  
  1490.