home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 13 / MA_Cover_13.bin / source / c / ahisrc / device / sound.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-10  |  41.1 KB  |  1,321 lines

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