home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 106 / EnigmaAmiga106CD.iso / software / sviluppo / ahisrc / device / sound.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-31  |  43.0 KB  |  1,386 lines

  1. /* $Id: sound.c,v 4.20 1999/08/31 21:44:30 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/memory.h>
  27. #include <utility/tagitem.h>
  28. #include <proto/exec.h>
  29. #include <proto/utility.h>
  30. #include <clib/ahi_protos.h>
  31. #include <pragmas/ahi_pragmas.h>
  32. #include <proto/ahi_sub.h>
  33. #include <stdlib.h>
  34.  
  35. #include "ahi_def.h"
  36. #include "debug.h"
  37. #include "effectinit.h"
  38. #include "mixer.h"
  39.  
  40. /******************************************************************************
  41. ** AHI_SetVol *****************************************************************
  42. ******************************************************************************/
  43.  
  44. /***** ahi.device/AHI_SetVol ***********************************************
  45. *
  46. *   NAME
  47. *       AHI_SetVol -- set volume and stereo panning for a channel
  48. *
  49. *   SYNOPSIS
  50. *       AHI_SetVol( channel, volume, pan, audioctrl, flags );
  51. *                   D0:16    D1      D2   A2         D3
  52. *
  53. *       void AHI_SetVol( UWORD, Fixed, sposition, struct AHIAudioCtrl *,
  54. *                        ULONG );
  55. *
  56. *   FUNCTION
  57. *       Changes the volume and stereo panning for a channel.
  58. *
  59. *   INPUTS
  60. *       channel - The channel to set volume for.
  61. *       volume - The desired volume. Fixed is a LONG fixed-point value with
  62. *           16 bits to the left of the point and 16 to the right
  63. *           (typedef LONG Fixed; from IFF-8SVX docs).
  64. *           Maximum volume is 1.0 (0x10000L) and 0.0 (0x0L) will turn off
  65. *           this channel. Note: The sound will continue to play, but you
  66. *           wont hear it. To stop a sound completely, use AHI_SetSound().
  67. *           Starting with V4 volume can also be negative, which tells AHI
  68. *           to invert the samples before playing. Note that all drivers
  69. *           may not be able to handle negative volume. In that case the
  70. *           absolute volume will be used.
  71. *       pan - The desired panning. sposition is the same as Fixed
  72. *           (typedef Fixed sposition; from IFF-8SVX.PAN docs).
  73. *           1.0 (0x10000L) means that the sound is panned all the way to
  74. *           the right, 0.5 (0x8000L) means the sound is centered and 0.0
  75. *           (0x0L) means that the sound is panned all the way to the left.
  76. *           Try to set Pan to the 'correct' value even if you know it has no
  77. *           effect. For example, if you know you use a mono mode, set pan to
  78. *           0.5 even if it does not matter.
  79. *           Starting with V4 pan can also be negative, which tells AHI to
  80. *           use the surround speaker for this channel. Note that all drivers
  81. *           may not be able to handle negative pan. In that case the absolute
  82. *           pan will be used.
  83. *       audioctrl - A pointer to an AHIAudioCtrl structure.
  84. *       flags - Only one flag is defined
  85. *           AHISF_IMM - Set this flag if this command should take effect
  86. *               immediately. If this bit is not set, the command will not
  87. *               take effect until the current sound is finished. MUST NOT
  88. *               be set if called from a SoundFunc. See the programming
  89. *               guidelines for more information about this flag.
  90. *
  91. *   RESULT
  92. *
  93. *   EXAMPLE
  94. *
  95. *   NOTES
  96. *       It is safe to call this function from an interrupt.
  97. *
  98. *       Negative volume or negative pan may use more CPU time than positive.
  99. *
  100. *       Using both negative volume and negative pan will play the inverted
  101. *       sound on the surround speaker.
  102. *
  103. *   BUGS
  104. *
  105. *   SEE ALSO
  106. *       AHI_SetEffect(), AHI_SetFreq(), AHI_SetSound(), AHI_LoadSound()
  107. *       
  108. *
  109. ****************************************************************************
  110. *
  111. */
  112.  
  113. ULONG ASMCALL
  114. SetVol ( REG(d0, UWORD channel),
  115.          REG(d1, Fixed volume),
  116.          REG(d2, sposition pan),
  117.          REG(a2, struct AHIPrivAudioCtrl *audioctrl),
  118.          REG(d3, ULONG flags),
  119.          REG(a6, struct AHIBase *AHIBase) )
  120. {
  121.   struct AHIChannelData *cd;
  122.   struct Library        *AHIsubBase;
  123.   ULONG                  rc;
  124.  
  125.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_ALL)
  126.   {
  127.     Debug_SetVol(channel, volume, pan, audioctrl, flags);
  128.   }
  129.  
  130.   if(AHIBase->ahib_Flags & AHIBF_NOSURROUND)
  131.   {
  132.     volume = abs(volume);
  133.     pan    = abs(pan);
  134.   }
  135.  
  136.   AHIsubBase = audioctrl->ahiac_SubLib;
  137.  
  138.   rc = AHIsub_SetVol(channel, volume, pan, &audioctrl->ac, flags);
  139.  
  140.   if(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING
  141.      || rc != AHIS_UNKNOWN)
  142.   {
  143.     return 0;   /* We're done! */
  144.   }
  145.  
  146.   cd = &audioctrl->ahiac_ChannelDatas[channel];
  147.  
  148.   if((audioctrl->ac.ahiac_Flags & AHIACF_VOL) == 0)
  149.   {
  150.     volume = volume & 0x10000;  /* |volume|=0 or 0x10000 */
  151.   }
  152.  
  153.   if((audioctrl->ac.ahiac_Flags & AHIACF_PAN) == 0)
  154.   {
  155.     pan = (channel & 1) << 16;  /* pan = 0 or 0x10000 */
  156.   }
  157.  
  158.   AHIsub_Disable(&audioctrl->ac);
  159.  
  160.   cd->cd_NextVolumeLeft  = ((volume >> 1) * ((0x10000 - abs(pan)) >> 1)) >> (16 - 2);
  161.   cd->cd_NextVolumeRight = ((volume >> 1) * (pan >> 1)) >> (16 - 2);
  162.  
  163.   SelectAddRoutine( cd->cd_NextVolumeLeft,
  164.                     cd->cd_NextVolumeRight,
  165.                     cd->cd_NextType,
  166.                     audioctrl,
  167.                    &cd->cd_NextScaleLeft,
  168.                    &cd->cd_NextScaleRight,
  169.        (ADDFUNC**) &cd->cd_NextAddRoutine );
  170.  
  171.   if(flags & AHISF_IMM)
  172.   {
  173. #ifdef VERSION68K
  174.     cd->cd_VolumeLeft  = cd->cd_NextVolumeLeft;
  175.     cd->cd_VolumeRight = cd->cd_NextVolumeRight;
  176.     
  177.     SelectAddRoutine( cd->cd_VolumeLeft,
  178.                       cd->cd_VolumeRight, 
  179.                       cd->cd_Type, 
  180.                       audioctrl,
  181.                      &cd->cd_ScaleLeft,
  182.                      &cd->cd_ScaleRight, 
  183.          (ADDFUNC**) &cd->cd_AddRoutine );
  184. #else
  185.     cd->cd_DelayedVolumeLeft  = cd->cd_NextVolumeLeft;
  186.     cd->cd_DelayedVolumeRight = cd->cd_NextVolumeRight;
  187.  
  188.     SelectAddRoutine( cd->cd_DelayedVolumeLeft,
  189.                       cd->cd_DelayedVolumeRight, 
  190.                       cd->cd_DelayedType, 
  191.                       audioctrl,
  192.                      &cd->cd_DelayedScaleLeft,
  193.                      &cd->cd_DelayedScaleRight, 
  194.          (ADDFUNC**) &cd->cd_DelayedAddRoutine );
  195.  
  196.     /* Enable anti-click routine */
  197.     cd->cd_AntiClickCount = audioctrl->ac.ahiac_AntiClickSamples;
  198.       if( ( flags & AHISF_NODELAY ) || 
  199.           ( cd->cd_AntiClickCount == 0 ) ||
  200.            !cd->cd_FreqOK || !cd->cd_SoundOK )
  201.     {
  202.       cd->cd_VolumeLeft  = cd->cd_DelayedVolumeLeft;
  203.       cd->cd_VolumeRight = cd->cd_DelayedVolumeRight;
  204.       cd->cd_ScaleLeft   = cd->cd_DelayedScaleLeft;
  205.       cd->cd_ScaleRight  = cd->cd_DelayedScaleRight;
  206.       cd->cd_AddRoutine  = cd->cd_DelayedAddRoutine;
  207.  
  208.       cd->cd_AntiClickCount = 0;
  209.     }
  210.     else
  211.     {
  212.       cd->cd_VolDelayed = TRUE;
  213.     }
  214. #endif
  215.   }
  216.  
  217.   AHIsub_Enable(&audioctrl->ac);
  218.  
  219.   return 0;
  220. }
  221.  
  222.  
  223.  
  224. /******************************************************************************
  225. ** AHI_SetFreq ****************************************************************
  226. ******************************************************************************/
  227.  
  228. /***** ahi.device/AHI_SetFreq **********************************************
  229. *
  230. *   NAME
  231. *       AHI_SetFreq -- set frequency for a channel
  232. *
  233. *   SYNOPSIS
  234. *       AHI_SetFreq( channel, freq, audioctrl, flags );
  235. *                    D0:16    D1    A2         D2
  236. *
  237. *       void AHI_SetFreq( UWORD, ULONG, struct AHIAudioCtrl *, ULONG );
  238. *
  239. *   FUNCTION
  240. *       Sets the playback frequency for a channel.
  241. *
  242. *   INPUTS
  243. *       channel - The channel to set playback frequency for.
  244. *       freq - The playback frequency in Hertz. Can also be AHI_MIXFREQ,
  245. *           which is the current mixing frequency, or 0 to temporary stop
  246. *           the sound (it will restart at the same point when its frequency
  247. *           changed).
  248. *       audioctrl - A pointer to an AHIAudioCtrl structure.
  249. *       flags - Only one flag is defined
  250. *           AHISF_IMM - Set this flag if this command should take effect
  251. *               immediately. If this bit is not set, the command will not
  252. *               take effect until the current sound is finished. MUST NOT
  253. *               be set if called from a SoundFunc. See the programming
  254. *               guidelines for more information about this flag.
  255. *
  256. *   RESULT
  257. *
  258. *   EXAMPLE
  259. *
  260. *   NOTES
  261. *       It is safe to call this function from an interrupt.
  262. *
  263. *   BUGS
  264. *
  265. *   SEE ALSO
  266. *       AHI_SetEffect(),  AHI_SetSound(), AHI_SetVol(), AHI_LoadSound()
  267. *
  268. ****************************************************************************
  269. *
  270. */
  271.  
  272. ULONG ASMCALL
  273. SetFreq ( REG( d0, UWORD channel ),
  274.           REG( d1, ULONG freq ),
  275.           REG( a2, struct AHIPrivAudioCtrl *audioctrl ),
  276.           REG( d2, ULONG flags ),
  277.           REG( a6, struct AHIBase *AHIBase ) )
  278. {
  279.   struct AHIChannelData *cd;
  280.   struct Library        *AHIsubBase;
  281.   ULONG                  rc;
  282.   ULONG                  add;
  283.  
  284.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_ALL)
  285.   {
  286.     Debug_SetFreq(channel, freq, audioctrl, flags);
  287.   }
  288.  
  289.   AHIsubBase = audioctrl->ahiac_SubLib;
  290.  
  291.   rc = AHIsub_SetFreq(channel, freq, &audioctrl->ac, flags);
  292.  
  293.   if(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING
  294.      || rc != AHIS_UNKNOWN)
  295.   {
  296.     return 0;   /* We're done! */
  297.   }
  298.  
  299.   cd = &audioctrl->ahiac_ChannelDatas[channel];
  300.  
  301.   if(freq == 0)
  302.   {
  303.     cd->cd_NextFreqOK = FALSE;
  304.  
  305.     add = 0;
  306.   }
  307.   else
  308.   {
  309.     cd->cd_NextFreqOK = TRUE;
  310.  
  311.     if(freq == AHI_MIXFREQ)
  312.     {
  313.       add = 0x10000;
  314.     }
  315.     else
  316.     {
  317.       int shift = 0;
  318.       
  319.       while(freq >= 65536)
  320.       {
  321.         shift++;
  322.         freq >>= 1;
  323.       }
  324.  
  325.       add = ((freq << 16) / audioctrl->ac.ahiac_MixFreq) << shift;
  326.     }
  327.   }
  328.  
  329.   AHIsub_Disable(&audioctrl->ac);
  330.  
  331. #ifdef VERSION68K
  332.   cd->cd_NextAdd.I = add >> 16;
  333.   cd->cd_NextAdd.F = (add & 0xffff) << 16;
  334. #else
  335.   cd->cd_NextAdd = (Fixed64) add << 16;
  336. #endif
  337.  
  338.   if(flags & AHISF_IMM)
  339.   {
  340. #ifdef VERSION68K
  341.     cd->cd_Add.I   = cd->cd_NextAdd.I;
  342.     cd->cd_Add.F   = cd->cd_NextAdd.F;
  343.     cd->cd_FreqOK  = cd->cd_NextFreqOK;
  344.  
  345.     cd->cd_Samples = CalcSamples( cd->cd_Add.I, cd->cd_Add.F,
  346.                                   cd->cd_Type,
  347.                                   cd->cd_LastOffset.I, cd->cd_LastOffset.F,
  348.                                   cd->cd_Offset.I, cd->cd_Offset.F );
  349. #else
  350.     cd->cd_DelayedAdd     = cd->cd_NextAdd;
  351.     cd->cd_DelayedFreqOK  = cd->cd_NextFreqOK;
  352.  
  353.     // cd->cd_Samples is also calculated when it actually happens¹...
  354.  
  355.     cd->cd_DelayedSamples = CalcSamples( cd->cd_DelayedAdd,
  356.                                          cd->cd_DelayedType,
  357.                                          cd->cd_DelayedLastOffset,
  358.                                          cd->cd_DelayedOffset );
  359.  
  360.     /* Enable anti-click routine */
  361.     cd->cd_AntiClickCount = audioctrl->ac.ahiac_AntiClickSamples;
  362.  
  363.     if( ( flags & AHISF_NODELAY ) || 
  364.         ( cd->cd_AntiClickCount == 0 ) ||
  365.         !cd->cd_FreqOK || !cd->cd_SoundOK )
  366.     {
  367.       cd->cd_Add     = cd->cd_DelayedAdd;
  368.       cd->cd_FreqOK  = cd->cd_DelayedFreqOK;
  369.  
  370.       // ¹) Unless we're not using any delay, in which case it's recalculated
  371.       //    here instead.
  372.  
  373.       cd->cd_Samples = CalcSamples( cd->cd_Add,
  374.                                     cd->cd_Type,
  375.                                     cd->cd_LastOffset,
  376.                                     cd->cd_Offset );
  377.  
  378.       cd->cd_AntiClickCount = 0;
  379.     }
  380.     else
  381.     {
  382.       cd->cd_FreqDelayed = TRUE;
  383.     }
  384. #endif
  385.  
  386.   }
  387.  
  388.   AHIsub_Enable(&audioctrl->ac);
  389.  
  390.   return 0;
  391. }
  392.  
  393.  
  394. /******************************************************************************
  395. ** AHI_SetSound ***************************************************************
  396. ******************************************************************************/
  397.  
  398. /***** ahi.device/AHI_SetSound *********************************************
  399. *
  400. *   NAME
  401. *       AHI_SetSound -- set what sound to play for a channel
  402. *
  403. *   SYNOPSIS
  404. *       AHI_SetSound( channel, sound, offset, length, audioctrl, flags );
  405. *                      D0:16   D1:16   D2      D3      A2         D4
  406. *
  407. *       void AHI_SetSound( UWORD, UWORD, ULONG, LONG,
  408. *                          struct AHIAudioCtrl *, ULONG );
  409. *
  410. *   FUNCTION
  411. *       Sets a sound to be played on a channel.
  412. *
  413. *   INPUTS
  414. *       channel - The channel to set sound for.
  415. *       sound - Sound to be played, or AHI_NOSOUND to turn the channel off.
  416. *       offset - Only available if the sound type is AHIST_SAMPLE or
  417. *           AHIST_DYNAMICSAMPLE. Must be 0 otherwise.
  418. *           Specifies an offset (in samples) where the playback will begin.
  419. *           If you wish to play the whole sound, set offset to 0.
  420. *       length - Only available if the sound type is AHIST_SAMPLE or
  421. *           AHIST_DYNAMICSAMPLE. Must be 0 otherwise.
  422. *           Specifies how many samples that should be played. If you
  423. *           wish to play the whole sound forwards, set offset to 0 and length
  424. *           to either 0 or the length of the sample array. You may not set
  425. *           length to 0 if offset is not 0! To play a sound backwards, just
  426. *           set length to a negative number.
  427. *       audioctrl - A pointer to an AHIAudioCtrl structure.
  428. *       flags - Only one flag is defined
  429. *           AHISF_IMM - Set this flag if this command should take effect
  430. *               immediately. If this bit is not set, the command will not
  431. *               take effect until the current sound is finished. MUST NOT
  432. *               be set if called from a SoundFunc. See the programming
  433. *               guidelines for more information about this flag.
  434. *
  435. *   RESULT
  436. *
  437. *   EXAMPLE
  438. *
  439. *   NOTES
  440. *       It is safe to call this function from an interrupt.
  441. *
  442. *       If offset or length is not zero, make sure you do not exceed the
  443. *       sample limits.
  444. *
  445. *   BUGS
  446. *
  447. *   SEE ALSO
  448. *       AHI_SetEffect(),  AHI_SetFreq(), AHI_SetVol(), AHI_LoadSound()
  449. *
  450. ****************************************************************************
  451. *
  452. */
  453.  
  454. ULONG ASMCALL
  455. SetSound ( REG(d0, UWORD channel),
  456.            REG(d1, UWORD sound),
  457.            REG(d2, ULONG offset),
  458.            REG(d3, LONG length),
  459.            REG(a2, struct AHIPrivAudioCtrl *audioctrl),
  460.            REG(d4, ULONG flags),
  461.            REG(a6, struct AHIBase *AHIBase) )
  462. {
  463.   struct AHIChannelData *cd;
  464.   struct AHISoundData   *sd;
  465.   struct Library        *AHIsubBase;
  466.   ULONG                  rc;
  467.  
  468.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_ALL)
  469.   {
  470.     Debug_SetSound(channel, sound, offset, length, audioctrl, flags);
  471.   }
  472.  
  473.   AHIsubBase = audioctrl->ahiac_SubLib;
  474.  
  475.   rc = AHIsub_SetSound(channel, sound, offset, length, &audioctrl->ac, flags);
  476.  
  477.   if(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING
  478.      || rc != AHIS_UNKNOWN)
  479.   {
  480.     return 0;   /* We're done! */
  481.   }
  482.  
  483.   cd = &audioctrl->ahiac_ChannelDatas[channel];
  484.   sd = &audioctrl->ahiac_SoundDatas[sound];
  485.  
  486.   AHIsub_Disable(&audioctrl->ac);
  487.  
  488.   if(sound == AHI_NOSOUND)
  489.   {
  490.     cd->cd_NextSoundOK    = FALSE;
  491.  
  492.     if(flags & AHISF_IMM)
  493.     {
  494.       cd->cd_EOS          = TRUE;  /* Signal End-Of-Sample */
  495.       cd->cd_SoundOK      = FALSE;
  496.     }
  497.   }
  498.   else if(sd->sd_Type != AHIST_NOTYPE) /* This is a user error, shouldn't happen! */
  499.   {
  500.     if(length == 0) length = sd->sd_Length;
  501.  
  502.     cd->cd_NextDataStart = sd->sd_Addr;
  503.     cd->cd_NextType      = sd->sd_Type;
  504. #ifdef VERSION68K
  505.     cd->cd_NextOffset.I  = offset;
  506. #else
  507.     cd->cd_NextOffset    = (Fixed64) offset << 32 ;
  508. #endif
  509.  
  510.     cd->cd_NextSoundOK   = TRUE;
  511.  
  512.     if(length < 0)
  513.     {
  514.       cd->cd_NextType         |= AHIST_BW;
  515.  
  516. #ifdef VERSION68K
  517.       cd->cd_NextLastOffset.I  = offset + length + 1;
  518.       cd->cd_NextLastOffset.F  = 0;
  519.       cd->cd_NextOffset.F      = 0xffffffff;
  520. #else
  521.       cd->cd_NextLastOffset    = (Fixed64) ( offset + length + 1 ) << 32;
  522.       cd->cd_NextOffset       |= 0xffffffffLL;
  523. #endif
  524.  
  525.     }
  526.     else
  527.     {
  528. #ifdef VERSION68K
  529.       cd->cd_NextLastOffset.I  = offset + length - 1;
  530.       cd->cd_NextLastOffset.F  = 0xffffffff;
  531.       cd->cd_NextOffset.F      = 0;
  532. #else
  533.       cd->cd_NextLastOffset    = ( (Fixed64) ( offset + length - 1 ) << 32 )
  534.                                  | 0xffffffffLL;
  535.       /* Low cd->cd_NextOffset already 0 */
  536. #endif
  537.     }
  538.  
  539.     SelectAddRoutine( cd->cd_NextVolumeLeft,
  540.                       cd->cd_NextVolumeRight,
  541.                       cd->cd_NextType,
  542.                       audioctrl,
  543.                      &cd->cd_NextScaleLeft,
  544.                      &cd->cd_NextScaleRight,
  545.          (ADDFUNC**) &cd->cd_NextAddRoutine );
  546.  
  547.     if(flags & AHISF_IMM)
  548.     {
  549. #ifdef VERSION68K
  550.       cd->cd_Offset.I      = cd->cd_NextOffset.I;
  551.       cd->cd_FirstOffsetI  = cd->cd_NextOffset.I; /* for linear interpol. */
  552.       cd->cd_Offset.F      = cd->cd_NextOffset.F;
  553.       cd->cd_LastOffset.I  = cd->cd_NextLastOffset.I;
  554.       cd->cd_LastOffset.F  = cd->cd_NextLastOffset.F;
  555.       cd->cd_DataStart     = cd->cd_NextDataStart;
  556.       cd->cd_Type          = cd->cd_NextType;
  557.       cd->cd_SoundOK       = cd->cd_NextSoundOK;
  558.  
  559.       SelectAddRoutine( cd->cd_VolumeLeft,
  560.                         cd->cd_VolumeRight,
  561.                         cd->cd_Type,
  562.                         audioctrl,
  563.                        &cd->cd_ScaleLeft,
  564.                        &cd->cd_ScaleRight,
  565.            (ADDFUNC**) &cd->cd_AddRoutine );
  566.  
  567.       cd->cd_Samples = CalcSamples( cd->cd_Add.I, cd->cd_Add.F,
  568.                                     cd->cd_Type,
  569.                                     cd->cd_LastOffset.I, cd->cd_LastOffset.F,
  570.                                     cd->cd_Offset.I, cd->cd_Offset.F);
  571. #else
  572.       cd->cd_DelayedOffset        = cd->cd_NextOffset;
  573.       cd->cd_DelayedFirstOffsetI  = cd->cd_NextOffset >> 32; /* for linear interpol. */
  574.       cd->cd_DelayedLastOffset    = cd->cd_NextLastOffset;
  575.       cd->cd_DelayedDataStart     = cd->cd_NextDataStart;
  576.       cd->cd_DelayedType          = cd->cd_NextType;
  577.       cd->cd_DelayedSoundOK       = cd->cd_NextSoundOK;
  578.  
  579.       SelectAddRoutine( cd->cd_DelayedVolumeLeft,
  580.                         cd->cd_DelayedVolumeRight,
  581.                         cd->cd_DelayedType,
  582.                         audioctrl,
  583.                        &cd->cd_DelayedScaleLeft,
  584.                        &cd->cd_DelayedScaleRight,
  585.            (ADDFUNC**) &cd->cd_DelayedAddRoutine );
  586.  
  587.       cd->cd_DelayedSamples = CalcSamples( cd->cd_DelayedAdd,
  588.                                            cd->cd_DelayedType,
  589.                                            cd->cd_DelayedLastOffset,
  590.                                            cd->cd_DelayedOffset );
  591.  
  592.       /* Enable anti-click routine */
  593.       cd->cd_AntiClickCount = audioctrl->ac.ahiac_AntiClickSamples;
  594.  
  595.       if( ( flags & AHISF_NODELAY ) || 
  596.           ( cd->cd_AntiClickCount == 0 ) ||
  597.            !cd->cd_FreqOK || !cd->cd_SoundOK )
  598.       {
  599.         cd->cd_Offset        = cd->cd_DelayedOffset;
  600.         cd->cd_FirstOffsetI  = cd->cd_DelayedFirstOffsetI;
  601.         cd->cd_LastOffset    = cd->cd_DelayedLastOffset;
  602.         cd->cd_DataStart     = cd->cd_DelayedDataStart;
  603.         cd->cd_Type          = cd->cd_DelayedType;
  604.         cd->cd_SoundOK       = cd->cd_DelayedSoundOK;
  605.         cd->cd_ScaleLeft     = cd->cd_DelayedScaleLeft;
  606.         cd->cd_ScaleRight    = cd->cd_DelayedScaleRight;
  607.         cd->cd_AddRoutine    = cd->cd_DelayedAddRoutine;
  608.         cd->cd_Samples       = cd->cd_DelayedSamples;
  609.  
  610.         cd->cd_AntiClickCount = 0;
  611.       }
  612.       else
  613.       {
  614.         cd->cd_SoundDelayed = TRUE;
  615.       }
  616. #endif
  617.  
  618.       cd->cd_EOS = TRUE;  /* Signal End-Of-Sample */
  619.     }
  620.   }
  621.  
  622.   AHIsub_Enable(&audioctrl->ac);
  623.  
  624.   return 0;
  625. }
  626.  
  627.  
  628. /******************************************************************************
  629. ** AHI_SetEffect **************************************************************
  630. ******************************************************************************/
  631.  
  632. /***** ahi.device/AHI_SetEffect ********************************************
  633. *
  634. *   NAME
  635. *       AHI_SetEffect -- set effect
  636. *
  637. *   SYNOPSIS
  638. *       error = AHI_SetEffect( effect, audioctrl );
  639. *       d0                     A0      A2
  640. *
  641. *       ULONG AHI_SetEffect( APTR, struct AHIAudioCtrl * );
  642. *
  643. *   FUNCTION
  644. *       Selects an effect to be used, described by a structure.
  645. *
  646. *   INPUTS
  647. *       effect - A pointer to an effect data structure, as defined in
  648. *           <devices/ahi.h>. The following effects are defined:
  649. *           AHIET_MASTERVOLUME - Changes the volume for all channels. Can
  650. *               also be used to boost volume over 100%.
  651. *           AHIET_OUTPUTBUFFER - Gives READ-ONLY access to the mixed output.
  652. *               Can be used to show nice scopes and VU-meters.
  653. *           AHIET_DSPMASK - Select which channels will be affected by the
  654. *               DSP effects. (V4)
  655. *           AHIET_DSPECHO - A DSP effects that adds (cross-)echo and delay.
  656. *               (V4)
  657. *           AHIET_CHANNELINFO - Get info about all channels. (V4)
  658. *       audioctrl - A pointer to an AHIAudioCtrl structure.
  659. *
  660. *   EFFECTS
  661. *       AHIET_MASTERVOLUME - Effect is a struct AHIEffMasterVolume, with
  662. *           ahiemv_Volume set to the desired volume. The range is 0 to
  663. *           (channels/hardware channel). Assume you have 4 channels in
  664. *           mono mode. The range is then 0.0 to 4.0. The range is the same
  665. *           if the mode is stereo with panning. However, assume you have 4
  666. *           channels with a stereo mode *without* panning. Then you have two
  667. *           channels to the left and two to the right => range is 0.0 - 2.0.
  668. *           Setting the volume outside the range will give an unpredictable
  669. *           result!
  670. *
  671. *       AHIET_OUTPUTBUFFER - Effect is a struct AHIEffOutputBuffer, with
  672. *           ahieob_Func pointing to a hook that will be called with the
  673. *           following parameters:
  674. *               A0 - (struct Hook *)
  675. *               A2 - (struct AHIAudioCtrl *)
  676. *               A1 - (struct AHIEffOutputBuffer *)
  677. *           The information you are looking for then is in ahieob_Type,
  678. *           ahieob_Buffer and ahieob_Length. Always check ahieob_Type!
  679. *           ahieob_Length is neither in bytes nor samples, but sample frames.
  680. *
  681. *       AHIET_DSPMASK - Effect is a struct AHIEffDSPMask, where ahiedm_Mask
  682. *           is an array with ahiedm_Channels elements. Each UBYTE in the
  683. *           array can either make the channel 'wet' (affected by the DSP
  684. *           effects), by using the AHIEDM_WET constant or 'dry' (not
  685. *           affected by the DSP effects) by using the AHIEDM_DRY constant.
  686. *           The default is all channels wet. If ahiedm_Channels does not
  687. *           equal the current number of channels allocated, the result of
  688. *           this call is undefined (crash warning!). (V4)
  689. *
  690. *       AHIET_DSPECHO - Effect is a struct AHIEffDSPEcho.
  691. *           ahiede_Delay is the delay in samples (and thus depends on the
  692. *           mixing rate).
  693. *
  694. *           ahiede_Feedback is a Fixed value between 0 and 1.0, and defines
  695. *           how much of the delayed signal should be feed back to the delay
  696. *           stage. Setting this to 0 gives a delay effect, otherwise echo.
  697. *
  698. *           ahiede_Mix tells how much of the delayed signal should be mixed
  699. *           with the normal signal. Setting this to 0 disables delay/echo,
  700. *           and setting it to 1.0 outputs only the delay/echo signal.
  701. *
  702. *           ahiede_Cross only has effect of the current playback mode is
  703. *           stereo. It tells how the delayed signal should be panned to
  704. *           the other channel. 0 means no cross echo, 1.0 means full
  705. *           cross echo.
  706. *
  707. *           If the user has enabled "Fast Echo", AHI may take several short-
  708. *           cuts to increase the performance. This could include rounding the
  709. *           parameters to a power of two, or even to the extremes. 
  710. *
  711. *           If you set ahiede_Mix to 0x10000 and ahiede_Cross to 0x0, much
  712. *           faster mixing routines will be used, and "Fast Echo" will improve
  713. *           that even more.
  714. *
  715. *           Otherwise, even with "Fast Echo" turned on, this effect will 
  716. *           probably suck some major CPU cycles on most sound hardware. (V4)
  717. *
  718. *       AHIET_CHANNELINFO - Effect is a struct AHIEffChannelInfo, where
  719. *           ahieci_Func is pointing to a hook that will be called with the
  720. *           following parameters:
  721. *               A0 - (struct Hook *)
  722. *               A2 - (struct AHIAudioCtrl *)
  723. *               A1 - (struct AHIEffChannelInfo *)
  724. *           ahieci_Channels must equal the current number of channels used.
  725. *           ahieci_Offset is an array of ULONGs, which will be filled by
  726. *           AHI before the hook is called (the offset is specified in sample
  727. *           frames). The array must have at least ahieci_Channels elements.
  728. *
  729. *           This "effect" can be used to find out how far each channel has
  730. *           played. You must probably keep track of the other parameters
  731. *           yourself (like which sound is playing, it's volume, balance and
  732. *           frequency etc) in order have meaningful usage of the information.
  733. *           (V4)
  734. *
  735. *
  736. *       NOTE! To turn off an effect, call again with ahie_Effect OR:ed
  737. *       with AHIET_CANCEL. For example, it is NOT correct to disable
  738. *       the AHIET_MASTERVOLUME effect by setting ahiemv_Volume to 1.0!
  739. *
  740. *       It is important that you always turn off effects before you
  741. *       deallocate the audio hardware. Otherwise memory may be lost.
  742. *       It is safe to turn off an effect that has never been turned on
  743. *       in the first place.
  744. *
  745. *       Never count on that an effect will be available. For example,
  746. *       AHIET_OUTPUTBUFFER is impossible to implement with some sound
  747. *       cards.
  748. *
  749. *   RESULT
  750. *       An error code, defined in <devices/ahi.h>.
  751. *
  752. *   EXAMPLE
  753. *
  754. *   NOTES
  755. *       Unlike the other functions whose names begin with "AHI_Set", this
  756. *       function may NOT be called from an interrupt (or AHI Hook).
  757. *
  758. *       Previous to V4, this call always returned AHIE_OK.
  759. *
  760. *   BUGS
  761. *       The idea of updating the source structure instead of allocating
  762. *       a new one that is passed the hook it pretty flawed. The reason is
  763. *       that AHI_SetEffect() originally could be called from interrupts,
  764. *       and memory allocation is not allowed from within interrupts.
  765. *
  766. *   SEE ALSO
  767. *       AHI_SetFreq(), AHI_SetSound(), AHI_SetVol(), AHI_LoadSound(),
  768. *       <devices/ahi.h>
  769. *
  770. ****************************************************************************
  771. *
  772. */
  773.  
  774.  
  775. ULONG ASMCALL
  776. SetEffect ( REG(a0, ULONG *effect),
  777.             REG(a2, struct AHIPrivAudioCtrl *audioctrl),
  778.             REG(a6, struct AHIBase *AHIBase) )
  779. {
  780.   struct Library        *AHIsubBase;
  781.   ULONG                  rc;
  782.  
  783.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_ALL)
  784.   {
  785.     Debug_SetEffect(effect, audioctrl);
  786.   }
  787.  
  788.   AHIsubBase = audioctrl->ahiac_SubLib;
  789.  
  790.   rc = AHIsub_SetEffect(effect, &audioctrl->ac);
  791.  
  792.   if(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING
  793.      || rc != AHIS_UNKNOWN)
  794.   {
  795.     return rc;   /* We're done! */
  796.   }
  797.  
  798.  
  799.   switch(*effect)
  800.   {
  801.  
  802.   /*
  803.    *  MASTERVOLUME
  804.    */
  805.  
  806.     case AHIET_MASTERVOLUME:
  807.     {
  808.       struct AHIEffMasterVolume *emv = (struct AHIEffMasterVolume *) effect;
  809.       
  810.       if(audioctrl->ahiac_SetMasterVolume != emv->ahiemv_Volume)
  811.       {
  812.         audioctrl->ahiac_SetMasterVolume = emv->ahiemv_Volume;
  813.         rc = update_MasterVolume( audioctrl );
  814.       }
  815.       break;
  816.     }
  817.  
  818.     case AHIET_MASTERVOLUME|AHIET_CANCEL:
  819.  
  820.       if(audioctrl->ahiac_SetMasterVolume != 0x10000)
  821.       {
  822.         audioctrl->ahiac_SetMasterVolume = 0x10000;
  823.         rc = update_MasterVolume( audioctrl );
  824.       }
  825.       break;    
  826.  
  827.   /*
  828.    *  OUTPUTBUFFER
  829.    */
  830.  
  831.     case AHIET_OUTPUTBUFFER:
  832.       audioctrl->ahiac_EffOutputBufferStruct = (struct AHIEffOutputBuffer *) effect;
  833.       rc = AHIE_OK;
  834.       break;
  835.  
  836.     case AHIET_OUTPUTBUFFER|AHIET_CANCEL:
  837.       audioctrl->ahiac_EffOutputBufferStruct = NULL;
  838.       rc = AHIE_OK;
  839.       break;
  840.  
  841.  
  842.   /*
  843.    *  DSPMASK
  844.    */
  845.  
  846.     case AHIET_DSPMASK:
  847.       rc = update_DSPMask( (struct AHIEffDSPMask *) effect, audioctrl );
  848.       break;
  849.       
  850.     case AHIET_DSPMASK|AHIET_CANCEL:
  851.       clear_DSPMask( audioctrl );
  852.       rc = AHIE_OK;
  853.       break;
  854.  
  855.  
  856.   /*
  857.    *  DSPECHO
  858.    */
  859.  
  860.     case AHIET_DSPECHO:
  861.       rc = update_DSPEcho( (struct AHIEffDSPEcho *) effect, audioctrl );
  862.       break;
  863.       
  864.     case AHIET_DSPECHO|AHIET_CANCEL:
  865.       free_DSPEcho( audioctrl );
  866.       rc = AHIE_OK;
  867.       break;
  868.  
  869.  
  870.   /*
  871.    *  CHANNELINFO
  872.    */
  873.  
  874.     case AHIET_CHANNELINFO:
  875.       audioctrl->ahiac_EffChannelInfoStruct = (struct AHIEffChannelInfo *) effect;
  876.       rc = AHIE_OK;
  877.       break;
  878.       
  879.     case AHIET_CHANNELINFO|AHIET_CANCEL:
  880.       audioctrl->ahiac_EffChannelInfoStruct = NULL;
  881.       rc = AHIE_OK;
  882.       break;
  883.   }
  884.  
  885.   return rc;
  886. }
  887.  
  888.  
  889. /******************************************************************************
  890. ** AHI_LoadSound **************************************************************
  891. ******************************************************************************/
  892.  
  893. /****** ahi.device/AHI_LoadSound ********************************************
  894. *
  895. *   NAME
  896. *       AHI_LoadSound -- prepare a sound for playback
  897. *
  898. *   SYNOPSIS
  899. *       error = AHI_LoadSound( sound, type, info, audioctrl );
  900. *       D0                     D0:16  D1    A0    A2
  901. *
  902. *       ULONG AHI_LoadSound( UWORD, ULONG, APTR, struct AHIAudioCtrl * );
  903. *
  904. *   FUNCTION
  905. *       Defines an ID number for the sound and prepares it for playback.
  906. *
  907. *   INPUTS
  908. *       sound - The numeric ID to be used as a reference to this sound.
  909. *           The ID is a number greater or equal to 0 and less than what you
  910. *           specified with AHIA_Sounds when you called AHI_AllocAudioA().
  911. *       type - The type of the sound. Currently four types are supported:
  912. *           AHIST_SAMPLE - array of 8 or 16 bit samples. Note that the
  913. *               portion of memory where the sample is stored must NOT be
  914. *               altered until AHI_UnloadSound() has been called! This is
  915. *               because some audio drivers may wish to upload the samples
  916. *               to local RAM. It is OK to read, though.
  917. *
  918. *           AHIST_DYNAMICSAMPLE - array of 8 or 16 bit samples, which can be
  919. *               updated dynamically. Typically used to play data that is
  920. *               loaded from disk or calculated realtime.
  921. *               Avoid using this sound type as much as possible; it will
  922. *               use much more CPU power than AHIST_SAMPLE on a DMA/DSP
  923. *               sound card.
  924. *
  925. *       info - Depends on type:
  926. *           AHIST_SAMPLE - A pointer to a struct AHISampleInfo, filled with:
  927. *               ahisi_Type - Format of samples (four formats are supported).
  928. *                   AHIST_M8S: Mono, 8 bit signed (BYTEs).
  929. *                   AHIST_S8S: Stereo, 8 bit signed (2×BYTEs) (V4). 
  930. *                   AHIST_M16S: Mono, 16 bit signed (WORDs).
  931. *                   AHIST_S16S: Stereo, 16 bit signed (2×WORDs) (V4).
  932. *               ahisi_Address - Address to the sample array.
  933. *               ahisi_Length - The size of the array, in samples.
  934. *               Don't even think of setting ahisi_Address to 0 and
  935. *               ahisi_Length to 0xffffffff as you can do with
  936. *               AHIST_DYNAMICSAMPLE! Very few DMA/DSP cards have 4 GB onboard
  937. *               RAM...
  938. *
  939. *           AHIST_DYNAMICSAMPLE A pointer to a struct AHISampleInfo, filled
  940. *               as described above (AHIST_SAMPLE).
  941. *               If ahisi_Address is 0 and ahisi_Length is 0xffffffff
  942. *               AHI_SetSound() can take the real address of an 8 bit sample
  943. *               to be played as offset argument. Unfortunately, this does not
  944. *               work for 16 bit samples.
  945. *
  946. *       audioctrl - A pointer to an AHIAudioCtrl structure.
  947. *
  948. *   RESULT
  949. *       An error code, defined in <devices/ahi.h>.
  950. *
  951. *   EXAMPLE
  952. *
  953. *   NOTES
  954. *       There is no need to place a sample array in Chip memory, but it
  955. *       MUST NOT be swapped out! Allocate your sample memory with the
  956. *       MEMF_PUBLIC flag set. 
  957. *
  958. *   BUGS
  959. *
  960. *   SEE ALSO
  961. *       AHI_UnloadSound(), AHI_SetEffect(), AHI_SetFreq(), AHI_SetSound(),
  962. *       AHI_SetVol(), <devices/ahi.h>
  963. *
  964. ****************************************************************************
  965. *
  966. */
  967.  
  968. ULONG ASMCALL
  969. LoadSound ( REG(d0, UWORD sound),
  970.             REG(d1, ULONG type),
  971.             REG(a0, APTR info),
  972.             REG(a2, struct AHIPrivAudioCtrl *audioctrl),
  973.             REG(a6, struct AHIBase *AHIBase) )
  974. {
  975.  
  976.   struct Library *AHIsubBase;
  977.   ULONG rc;
  978.  
  979.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  980.   {
  981.     Debug_LoadSound(sound, type, info, audioctrl);
  982.   }
  983.  
  984.   AHIsubBase = audioctrl->ahiac_SubLib;
  985.  
  986.   rc = AHIsub_LoadSound(sound, type, info, (struct AHIAudioCtrlDrv *) audioctrl);
  987.  
  988.   if((audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING) || (rc != AHIS_UNKNOWN))
  989.   {
  990.     return rc;
  991.   }
  992.  
  993.   rc = AHIE_OK;
  994.  
  995.   switch(type)
  996.   {
  997.     case AHIST_DYNAMICSAMPLE:
  998.     case AHIST_SAMPLE:
  999.     {
  1000.       struct AHISampleInfo *si = (struct AHISampleInfo *) info;
  1001.  
  1002.       switch(si->ahisi_Type)
  1003.       {
  1004.         case AHIST_M8S:
  1005.         case AHIST_M16S:
  1006. #ifdef HAVE_HIFI
  1007.         case AHIST_S8S:
  1008.         case AHIST_S16S:
  1009. #endif
  1010.           /* AHI_FreeAudio() will deallocate...  */
  1011.  
  1012.           if( initSignedTable( audioctrl ) )
  1013.           {
  1014.             audioctrl->ahiac_SoundDatas[sound].sd_Type   = si->ahisi_Type;
  1015.             audioctrl->ahiac_SoundDatas[sound].sd_Addr   = si->ahisi_Address;
  1016.             audioctrl->ahiac_SoundDatas[sound].sd_Length = si->ahisi_Length;
  1017.           }
  1018.           else rc = AHIE_NOMEM;
  1019.  
  1020.           break;
  1021.  
  1022.         /* Obsolete, present for compability only. FIXIT! */
  1023.  
  1024.         case AHIST_M8U:
  1025.  
  1026.           /* AHI_FreeAudio() will deallocate...  */
  1027.  
  1028.           if( ((audioctrl->ac.ahiac_Flags & AHIACF_HIFI) == 0) && 
  1029.               initUnsignedTable( audioctrl ) )
  1030.           {
  1031.             audioctrl->ahiac_SoundDatas[sound].sd_Type   = si->ahisi_Type;
  1032.             audioctrl->ahiac_SoundDatas[sound].sd_Addr   = si->ahisi_Address;
  1033.             audioctrl->ahiac_SoundDatas[sound].sd_Length = si->ahisi_Length;
  1034.           }
  1035.           else rc = AHIE_NOMEM;
  1036.  
  1037.           break;
  1038.  
  1039.         default:
  1040.           rc = AHIE_BADSAMPLETYPE;
  1041.       }
  1042.       
  1043.       break;
  1044.     }
  1045.  
  1046.     default:
  1047.       rc = AHIE_BADSOUNDTYPE;
  1048.       break;
  1049.   }
  1050.  
  1051.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  1052.   {
  1053.     KPrintF("=>%ld\n", rc);
  1054.   }
  1055.   return rc;
  1056. }
  1057.  
  1058.  
  1059. /******************************************************************************
  1060. ** AHI_UnloadSound ************************************************************
  1061. ******************************************************************************/
  1062.  
  1063. /****** ahi.device/AHI_UnloadSound *****************************************
  1064. *
  1065. *   NAME
  1066. *       AHI_UnloadSound -- discard a sound
  1067. *
  1068. *   SYNOPSIS
  1069. *       AHI_UnloadSound( sound, audioctrl );
  1070. *                        D0:16  A2
  1071. *
  1072. *       void AHI_UnloadSound( UWORD, struct AHIAudioCtrl * );
  1073. *
  1074. *   FUNCTION
  1075. *       Tells 'ahi.device' that this sound will not be used anymore.
  1076. *
  1077. *   INPUTS
  1078. *       sound - The ID of the sound to unload.
  1079. *       audioctrl - A pointer to an AHIAudioCtrl structure.
  1080. *
  1081. *   RESULT
  1082. *
  1083. *   EXAMPLE
  1084. *
  1085. *   NOTES
  1086. *       This call will not break a Forbid() state.
  1087. *
  1088. *   BUGS
  1089. *
  1090. *   SEE ALSO
  1091. *       AHI_LoadSound()
  1092. *
  1093. ****************************************************************************
  1094. *
  1095. */
  1096.  
  1097. ULONG ASMCALL
  1098. UnloadSound ( REG(d0, UWORD sound),
  1099.               REG(a2, struct AHIPrivAudioCtrl *audioctrl),
  1100.               REG(a6, struct AHIBase *AHIBase) )
  1101. {
  1102.   struct Library *AHIsubBase;
  1103.   ULONG rc;
  1104.  
  1105.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  1106.   {
  1107.     Debug_UnloadSound(sound, audioctrl);
  1108.   }
  1109.  
  1110.   AHIsubBase = audioctrl->ahiac_SubLib;
  1111.  
  1112.   rc = AHIsub_UnloadSound(sound, (struct AHIAudioCtrlDrv *) audioctrl);
  1113.  
  1114.   if((audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING) || (rc != AHIS_UNKNOWN))
  1115.   {
  1116.     return 0;
  1117.   }
  1118.   
  1119.   audioctrl->ahiac_SoundDatas[sound].sd_Type = AHIST_NOTYPE;
  1120.   
  1121.   return 0;
  1122. }
  1123.  
  1124.  
  1125. /******************************************************************************
  1126. ** AHI_PlayA ******************************************************************
  1127. ******************************************************************************/
  1128.  
  1129. /****** ahi.device/AHI_PlayA ************************************************
  1130. *
  1131. *   NAME
  1132. *       AHI_PlayA -- Start multiple sounds in one call (V4)
  1133. *       AHI_Play -- varargs stub for AHI_PlayA()
  1134. *
  1135. *   SYNOPSIS
  1136. *       AHI_PlayA( audioctrl, tags );
  1137. *                  A2         A1
  1138. *
  1139. *       void AHI_PlayA( struct AHIAudioCtrl *, struct TagItem * );
  1140. *
  1141. *       AHI_Play( AudioCtrl, tag1, ...);
  1142. *
  1143. *       void AHI_Play( struct AHIAudioCtrl *, Tag, ... );
  1144. *
  1145. *   FUNCTION
  1146. *       This function performs the same actions as multiple calls to
  1147. *       AHI_SetFreq(), AHI_SetSound() and AHI_SetVol(). The advantages
  1148. *       of using only one call is that simple loops can be set without
  1149. *       using a SoundFunc (see AHI_AllocAudioA(), tag AHIA_SoundFunc) and
  1150. *       that sounds on different channels can be synchronized even when the
  1151. *       sounds are not started from a PlayerFunc (see AHI_AllocAudioA(), tag
  1152. *       AHIA_PlayerFunc). The disadvantage is that this call has more
  1153. *       overhead than AHI_SetFreq(), AHI_SetSound() and AHI_SetVol(). It is
  1154. *       therefore recommended that you only use this call if you are not
  1155. *       calling from a SoundFunc or PlayerFunc.
  1156. *
  1157. *       The supplied tag list works like a 'program'. This means that
  1158. *       the order of tags matter.
  1159. *
  1160. *   INPUTS
  1161. *       audioctrl - A pointer to an AHIAudioCtrl structure.
  1162. *       tags - A pointer to a tag list.
  1163. *
  1164. *   TAGS
  1165. *       AHIP_BeginChannel (UWORD) - Before you start setting attributes
  1166. *           for a sound to play, you have to use this tag to chose a
  1167. *           channel to operate on. If AHIP_BeginChannel is omitted, the
  1168. *           result is undefined.
  1169. *
  1170. *       AHIP_EndChannel (ULONG) - Signals the end of attributes for
  1171. *           the current channel. If AHIP_EndChannel is omitted, the result
  1172. *           is undefined. ti_Data MUST BE NULL!
  1173. *
  1174. *       AHIP_Freq (ULONG) - The playback frequency in Hertz or AHI_MIXFREQ.
  1175. *
  1176. *       AHIP_Vol (Fixed) - The desired volume. If omitted, but AHIP_Pan is
  1177. *           present, AHIP_Vol defaults to 0.
  1178. *
  1179. *       AHIP_Pan (sposition) - The desired panning. If omitted, but AHIP_Vol
  1180. *           is present, AHIP_Pan defaults to 0 (extreme left).
  1181. *
  1182. *       AHIP_Sound (UWORD) - Sound to be played, or AHI_NOSOUND.
  1183. *
  1184. *       AHIP_Offset (ULONG) - Specifies an offset (in samples) into the
  1185. *           sound. If this tag is present, AHIP_Length MUST be present too!
  1186. *
  1187. *       AHIP_Length (LONG) - Specifies how many samples that should be
  1188. *           player.
  1189. *
  1190. *       AHIP_LoopFreq (ULONG)
  1191. *       AHIP_LoopVol (Fixed)
  1192. *       AHIP_LoopPan (sposition)
  1193. *       AHIP_LoopSound (UWORD)
  1194. *       AHIP_LoopOffset (ULONG)
  1195. *       AHIP_LoopLength (LONG) - These tags can be used to set simple loop
  1196. *          attributes. They default to their sisters. These tags must be
  1197. *          after the other tags.
  1198. *
  1199. *   RESULT
  1200. *
  1201. *   EXAMPLE
  1202. *
  1203. *   NOTES
  1204. *
  1205. *   BUGS
  1206. *
  1207. *   SEE ALSO
  1208. *       AHI_SetFreq(), AHI_SetSound(), AHI_SetVol()
  1209. *
  1210. ****************************************************************************
  1211. *
  1212. */
  1213.  
  1214. ULONG ASMCALL 
  1215. PlayA( REG(a2, struct AHIAudioCtrl *audioctrl),
  1216.        REG(a1, struct TagItem *tags),
  1217.        REG(a6, struct AHIBase *AHIBase) )
  1218. {
  1219.   struct TagItem *tag,*tstate=tags;
  1220.   struct Library *AHIsubBase;
  1221.   BOOL  setfreq = FALSE, setvol = FALSE, setsound = FALSE,
  1222.         loopsetfreq = FALSE, loopsetvol = FALSE, loopsetsound = FALSE;
  1223.   ULONG channel = 0,
  1224.         freq = 0, vol = 0, pan = 0, sound = 0, offset = 0, length = 0;
  1225.   ULONG loopfreq = 0, loopvol = 0, looppan = 0, loopsound = 0,
  1226.         loopoffset = 0, looplength = 0;
  1227.  
  1228.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_ALL)
  1229.   {
  1230.     Debug_PlayA(audioctrl,tags);
  1231.   }
  1232.  
  1233.   AHIsubBase = ((struct AHIPrivAudioCtrl *)audioctrl)->ahiac_SubLib;
  1234.  
  1235.   AHIsub_Disable((struct AHIAudioCtrlDrv *)audioctrl);
  1236.  
  1237.   for( tag = NextTagItem( &tstate );
  1238.        tag != NULL;
  1239.        tag = NextTagItem( &tstate ) )
  1240.   {
  1241.     switch(tag->ti_Tag)
  1242.     {
  1243.     case AHIP_BeginChannel:
  1244.       channel=tag->ti_Data;
  1245.       setfreq=setvol=setsound=loopsetfreq=loopsetvol=loopsetsound= \
  1246.       vol=pan=offset=length=loopvol=looppan=loopoffset=looplength=0;
  1247.       break;
  1248.     case AHIP_Freq:
  1249.       loopfreq=
  1250.       freq=tag->ti_Data;
  1251.       setfreq=TRUE;
  1252.       break;
  1253.     case AHIP_Vol:
  1254.       loopvol=
  1255.       vol=tag->ti_Data;
  1256.       setvol=TRUE;
  1257.       break;
  1258.     case AHIP_Pan:
  1259.       looppan=
  1260.       pan=tag->ti_Data;
  1261.       setvol=TRUE;
  1262.       break;
  1263.     case AHIP_Sound:
  1264.       loopsound=
  1265.       sound=tag->ti_Data;
  1266.       setsound=TRUE;
  1267.       break;
  1268.     case AHIP_Offset:
  1269.       loopoffset=
  1270.       offset=tag->ti_Data;
  1271.       break;
  1272.     case AHIP_Length:
  1273.       looplength=
  1274.       length=tag->ti_Data;
  1275.       break;
  1276.     case AHIP_LoopFreq:
  1277.       loopfreq=tag->ti_Data;
  1278.       loopsetfreq=TRUE;
  1279.       break;
  1280.     case AHIP_LoopVol:
  1281.       loopvol=tag->ti_Data;
  1282.       loopsetvol=TRUE;
  1283.       break;
  1284.     case AHIP_LoopPan:
  1285.       looppan=tag->ti_Data;
  1286.       loopsetvol=TRUE;
  1287.       break;
  1288.     case AHIP_LoopSound:
  1289.       loopsound=tag->ti_Data;
  1290.       loopsetsound=TRUE;
  1291.       break;
  1292.     case AHIP_LoopOffset:
  1293.       loopoffset=tag->ti_Data;
  1294.       loopsetsound=TRUE;           // AHIP_LoopSound: doesn't have to be present
  1295.       break;
  1296.     case AHIP_LoopLength:
  1297.       looplength=tag->ti_Data;
  1298.       break;
  1299.     case AHIP_EndChannel:
  1300.       if(setfreq)
  1301.         AHI_SetFreq(channel,freq,audioctrl,AHISF_IMM);
  1302.       if(loopsetfreq)
  1303.         AHI_SetFreq(channel,loopfreq,audioctrl,NULL);
  1304.       if(setvol)
  1305.         AHI_SetVol(channel,vol,pan,audioctrl,AHISF_IMM);
  1306.       if(loopsetvol)
  1307.         AHI_SetVol(channel,loopvol,looppan,audioctrl,NULL);
  1308.       if(setsound)
  1309.         AHI_SetSound(channel,sound,offset,length,audioctrl,AHISF_IMM);
  1310.       if(loopsetsound)
  1311.         AHI_SetSound(channel,loopsound,loopoffset,looplength,audioctrl,NULL);
  1312.       break;
  1313.     }
  1314.   }
  1315.  
  1316.   AHIsub_Enable((struct AHIAudioCtrlDrv *)audioctrl);
  1317.   return NULL;
  1318. }
  1319.  
  1320.  
  1321. /******************************************************************************
  1322. ** AHI_SampleFrameSize ********************************************************
  1323. ******************************************************************************/
  1324.  
  1325. /****** ahi.device/AHI_SampleFrameSize **************************************
  1326. *
  1327. *   NAME
  1328. *       AHI_SampleFrameSize -- get the size of a sample frame (V4)
  1329. *
  1330. *   SYNOPSIS
  1331. *       size = AHI_SampleFrameSize( sampletype );
  1332. *       D0                          D0
  1333. *
  1334. *       ULONG AHI_SampleFrameSize( ULONG );
  1335. *
  1336. *   FUNCTION
  1337. *       Returns the size in bytes of a sample frame for a given sample type.
  1338. *
  1339. *   INPUTS
  1340. *       sampletype - The sample type to examine. See <devices/ahi.h> for
  1341. *           possible types.
  1342. *
  1343. *   RESULT
  1344. *
  1345. *   EXAMPLE
  1346. *
  1347. *   NOTES
  1348. *
  1349. *   BUGS
  1350. *
  1351. *   SEE ALSO
  1352. *      <devices/ahi.h>
  1353. *
  1354. ****************************************************************************
  1355. *
  1356. */
  1357.  
  1358. static const UBYTE type2bytes[]=
  1359. {
  1360.   1,    // AHIST_M8S  (0)
  1361.   2,    // AHIST_M16S (1)
  1362.   2,    // AHIST_S8S  (2)
  1363.   4,    // AHIST_S16S (3)
  1364.   1,    // AHIST_M8U  (4)
  1365.   0,
  1366.   0,
  1367.   0,
  1368.   4,    // AHIST_M32S (8)
  1369.   0,
  1370.   8     // AHIST_S32S (10)
  1371. };
  1372.  
  1373. ULONG ASMCALL
  1374. SampleFrameSize( REG(d0, ULONG sampletype),
  1375.                  REG(a6, struct AHIBase *AHIBase) )
  1376.  
  1377. {
  1378.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  1379.   {
  1380.     Debug_SampleFrameSize(sampletype);
  1381.     KPrintF("=>%ld\n",type2bytes[sampletype]);
  1382.   }
  1383.  
  1384.   return type2bytes[sampletype];
  1385. }
  1386.