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

  1. /* $Id: audioctrl.c,v 4.33 1999/09/12 10:40:08 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 <powerup/ppclib/memory.h>
  28. #include <exec/alerts.h>
  29. #include <utility/utility.h>
  30. #include <utility/tagitem.h>
  31.  
  32. #include <proto/exec.h>
  33. #include <proto/utility.h>
  34. #include <clib/ahi_protos.h>
  35. #include <pragmas/ahi_pragmas.h>
  36. #include <proto/ahi_sub.h>
  37. #include <strings.h>
  38.  
  39. #include "ahi_def.h"
  40. #include "audioctrl.h"
  41. #include "mixer.h"
  42. #include "asmfuncs.h"
  43. #include "database.h"
  44. #include "debug.h"
  45. #include "misc.h"
  46. #include "header.h"
  47.  
  48.  
  49. // Makes 'in' fit the given bounds.
  50.  
  51. #define inbounds(in,min,max) \
  52.     ( (in > max) ? max : ( (in < min) ? min : in ) )
  53.  
  54.  
  55. /******************************************************************************
  56. ** RecalcBuff *****************************************************************
  57. ******************************************************************************/
  58.  
  59. // Calculates how many samples to mix each mixer pass. The result it 
  60. // both returned and stored in ahiac_BuffSamples.
  61. // ahiac_BuffSizeNow will also be updated (For mixing routine)
  62.  
  63. static ULONG
  64. RecalcBuff ( Fixed freq, struct AHIPrivAudioCtrl *audioctrl )
  65. {
  66.   int length;
  67.  
  68.   // If ULONG, convert to Fixed
  69. //  if(freq < 65536) freq <<= 16;
  70.  
  71.   // Sanity check
  72.   if(freq == 0) return 0;
  73.  
  74.   audioctrl->ac.ahiac_BuffSamples = (audioctrl->ac.ahiac_MixFreq << 8) /
  75.                                     (freq >> 8);
  76.  
  77.   // ahiac_BuffSamples *must* fit a WORD according to the driver autodocs!
  78.   if(audioctrl->ac.ahiac_BuffSamples > 65535)
  79.   {
  80.     audioctrl->ac.ahiac_BuffSamples = 65535;
  81.   }
  82.  
  83.   // Now, calculate the required mixing buffer size.
  84.  
  85.   length = audioctrl->ac.ahiac_BuffSamples * 
  86.            AHI_SampleFrameSize(audioctrl->ac.ahiac_BuffType);
  87.  
  88.   if(audioctrl->ac.ahiac_Flags & AHIACF_POSTPROC)
  89.   {
  90.     length <<= 1;  // 2 buffers
  91.   }
  92.  
  93.   // Pad to even 8 and add some more (because of an old Mungwall hit, but I
  94.   // think that bug was fixed a long, long time ago..?)
  95.  
  96.   length = ((length + 7) & (~7) ) + 80;
  97.  
  98.   audioctrl->ahiac_BuffSizeNow = length;
  99.  
  100.   return audioctrl->ac.ahiac_BuffSamples;
  101.  
  102. }
  103.  
  104.  
  105. /******************************************************************************
  106. ** CreateAudioCtrl & UpdateAudioCtrl ******************************************
  107. ******************************************************************************/
  108.  
  109. #define DEFPLAYERFREQ (50<<16)
  110.  
  111. static ULONG
  112. DummyHook( void )
  113. {
  114.   return 0;
  115. }
  116.  
  117.  
  118. static struct Hook DefPlayerHook =
  119. {
  120.   {0, 0},
  121.   DummyHook,
  122.   0,
  123.   0
  124. };
  125.  
  126.  
  127. static struct TagItem boolmap[] =
  128. {
  129.   { AHIDB_Volume,    AHIACF_VOL },
  130.   { AHIDB_Panning,   AHIACF_PAN },
  131.   { AHIDB_Stereo,    AHIACF_STEREO },
  132.   { AHIDB_HiFi,      AHIACF_HIFI },
  133.   { AHIDB_PingPong,  AHIACF_PINGPONG },
  134.   { AHIDB_Record,    AHIACF_RECORD },
  135.   { AHIDB_MultTable, AHIACF_MULTTAB },
  136.   { TAG_DONE,        NULL }
  137. };
  138.  
  139.  
  140. struct AHIPrivAudioCtrl *
  141. CreateAudioCtrl(struct TagItem *tags)
  142. {
  143.   struct AHIPrivAudioCtrl *audioctrl;
  144.   struct AHI_AudioDatabase *audiodb;
  145.   struct TagItem *dbtags;
  146.   BOOL   error=TRUE;
  147.  
  148.   audioctrl = AHIAllocVec( sizeof( struct AHIPrivAudioCtrl ),
  149.                            MEMF_PUBLIC | MEMF_CLEAR |
  150.                            MEMF_NOCACHESYNCPPC | MEMF_NOCACHESYNCM68K );
  151.  
  152.   if( audioctrl != NULL )
  153.   {
  154.     audioctrl->ac.ahiac_AudioCtrl.ahiac_UserData =
  155.       (APTR)GetTagData(AHIA_UserData,NULL,tags);
  156.     audioctrl->ahiac_AudioID =
  157.       GetTagData(AHIA_AudioID,AHI_DEFAULT_ID,tags);
  158.     audioctrl->ac.ahiac_MixFreq =
  159.       GetTagData(AHIA_MixFreq,AHI_DEFAULT_FREQ,tags);
  160.     audioctrl->ac.ahiac_Channels =
  161.       GetTagData(AHIA_Channels,0,tags);
  162.     audioctrl->ac.ahiac_Sounds =
  163.       GetTagData(AHIA_Sounds,0,tags);
  164.     audioctrl->ac.ahiac_SoundFunc =
  165.       (struct Hook *)GetTagData(AHIA_SoundFunc,NULL,tags);
  166.     audioctrl->ahiac_RecordFunc =
  167.       (struct Hook *)GetTagData(AHIA_RecordFunc,NULL,tags);
  168.     audioctrl->ac.ahiac_PlayerFunc =
  169.       (struct Hook *)GetTagData(AHIA_PlayerFunc,NULL,tags);
  170.     audioctrl->ac.ahiac_PlayerFreq =
  171.       GetTagData(AHIA_PlayerFreq,0,tags);
  172.     audioctrl->ac.ahiac_MinPlayerFreq =
  173.       GetTagData(AHIA_MinPlayerFreq,0,tags);
  174.     audioctrl->ac.ahiac_MaxPlayerFreq =
  175.       GetTagData(AHIA_MaxPlayerFreq,0,tags);
  176.     audioctrl->ac.ahiac_AntiClickSamples = 
  177.       GetTagData(AHIA_AntiClickSamples,~0,tags);
  178.  
  179.     audioctrl->ahiac_MasterVolume=0x00010000;
  180.     audioctrl->ahiac_SetMasterVolume=0x00010000;
  181.     audioctrl->ahiac_EchoMasterVolume=0x00010000;
  182.  
  183.     if(audioctrl->ahiac_AudioID == AHI_DEFAULT_ID)
  184.       audioctrl->ahiac_AudioID = AHIBase->ahib_AudioMode;
  185.  
  186.     if(audioctrl->ac.ahiac_MixFreq == AHI_DEFAULT_FREQ)
  187.       audioctrl->ac.ahiac_MixFreq = AHIBase->ahib_Frequency;
  188.  
  189.     if(audioctrl->ac.ahiac_PlayerFunc == NULL)
  190.       audioctrl->ac.ahiac_PlayerFunc=&DefPlayerHook;
  191.  
  192.     if(audioctrl->ac.ahiac_PlayerFreq == 0)
  193.       audioctrl->ac.ahiac_PlayerFreq = DEFPLAYERFREQ;
  194.     if(audioctrl->ac.ahiac_MinPlayerFreq == 0)
  195.       audioctrl->ac.ahiac_MinPlayerFreq = DEFPLAYERFREQ;
  196.     if(audioctrl->ac.ahiac_MaxPlayerFreq == 0)
  197.       audioctrl->ac.ahiac_MaxPlayerFreq = DEFPLAYERFREQ;
  198.  
  199.     if(audioctrl->ac.ahiac_PlayerFreq < 65536)
  200.       audioctrl->ac.ahiac_PlayerFreq <<= 16;
  201.     if(audioctrl->ac.ahiac_MinPlayerFreq < 65536)
  202.       audioctrl->ac.ahiac_MinPlayerFreq <<= 16;
  203.     if(audioctrl->ac.ahiac_MaxPlayerFreq < 65536)
  204.       audioctrl->ac.ahiac_MaxPlayerFreq <<= 16;
  205.  
  206.     if(audioctrl->ac.ahiac_AntiClickSamples == ~0UL)
  207.       audioctrl->ac.ahiac_AntiClickSamples = 
  208.           ( AHIBase->ahib_AntiClickTime * audioctrl->ac.ahiac_MixFreq ) >> 16;
  209.  
  210.     if((audiodb=LockDatabase()))
  211.     {
  212.       if((dbtags=GetDBTagList(audiodb,audioctrl->ahiac_AudioID)))
  213.       {
  214.         audioctrl->ac.ahiac_Flags=PackBoolTags(GetTagData(AHIDB_Flags,NULL,dbtags),dbtags,boolmap);
  215. #ifdef HAVE_CLIPPING
  216.         if(AHIBase->ahib_Flags & AHIBF_CLIPPING)
  217.         {
  218.           audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
  219.         }
  220. #endif
  221.         strcpy( audioctrl->ahiac_DriverName,
  222.                 "DEVS:AHI/" );
  223.         strcat( audioctrl->ahiac_DriverName,
  224.                 (char *) GetTagData( AHIDB_Driver, (ULONG) "", dbtags ) );
  225.         strcat( audioctrl->ahiac_DriverName,
  226.                 ".audio" );
  227.  
  228.         error=FALSE;
  229.       }
  230.       UnlockDatabase(audiodb);
  231.     }
  232.   }
  233.  
  234.   if(error)
  235.   {
  236.     AHIFreeVec(audioctrl);
  237.     return NULL;
  238.   }
  239.   else
  240.     return audioctrl;
  241. }
  242.  
  243. static void
  244. UpdateAudioCtrl(struct AHIPrivAudioCtrl *audioctrl)
  245. {
  246.   ULONG  temp;
  247.  
  248.   temp=audioctrl->ac.ahiac_MinPlayerFreq;
  249.   if(temp>=65536)
  250.     temp >>=16;
  251.   if(temp)
  252.     audioctrl->ac.ahiac_MaxBuffSamples=audioctrl->ac.ahiac_MixFreq/temp;
  253.   else
  254.     audioctrl->ac.ahiac_MaxBuffSamples=AHIBase->ahib_Frequency/audioctrl->ac.ahiac_PlayerFreq;
  255.  
  256.   temp=audioctrl->ac.ahiac_MaxPlayerFreq;
  257.   if(temp>=65536)
  258.     temp = (temp + 65535) >> 16;
  259.   if(temp)
  260.     audioctrl->ac.ahiac_MinBuffSamples=audioctrl->ac.ahiac_MixFreq/temp;
  261.   else
  262.     audioctrl->ac.ahiac_MinBuffSamples=AHIBase->ahib_Frequency/audioctrl->ac.ahiac_PlayerFreq;
  263. }
  264.  
  265.  
  266.  
  267. /******************************************************************************
  268. ** Sampler ********************************************************************
  269. ******************************************************************************/
  270.  
  271. static void ASMCALL INTERRUPT 
  272. Sampler ( REG(a0, struct Hook *hook),
  273.           REG(a2, struct AHIPrivAudioCtrl *actrl),
  274.           REG(a1, struct AHIRecordMessage *recmsg) )
  275. {
  276.   if(actrl->ahiac_RecordFunc)
  277.   {
  278.     CallHookPkt(actrl->ahiac_RecordFunc, actrl, recmsg);
  279.   }
  280. }
  281.  
  282. /******************************************************************************
  283. ** AHI_AllocAudioA ************************************************************
  284. ******************************************************************************/
  285.  
  286. /****** ahi.device/AHI_AllocAudioA ******************************************
  287. *
  288. *   NAME
  289. *       AHI_AllocAudioA -- allocates and initializes the audio hardware
  290. *       AHI_AllocAudio -- varargs stub for AHI_AllocAudioA()
  291. *
  292. *   SYNOPSIS
  293. *       audioctrl = AHI_AllocAudioA( tags );
  294. *       D0                           A1
  295. *
  296. *       struct AHIAudioCtrl *AHI_AllocAudioA( struct TagItem * );
  297. *
  298. *       audioctrl = AHI_AllocAudio( tag1, ... );
  299. *
  300. *       struct AHIAudioCtrl *AHI_AllocAudio( Tag, ... );
  301. *
  302. *   FUNCTION
  303. *       Allocates and initializes the audio hardware, selects the best
  304. *       mixing routine (if necessary) according to the supplied tags.
  305. *       To start playing you first need to call AHI_ControlAudioA().
  306. *
  307. *   INPUTS
  308. *       tags - A pointer to a tag list.
  309. *
  310. *   TAGS
  311. *
  312. *       AHIA_AudioID (ULONG) - The audio mode to use. Default is
  313. *           AHI_DEFAULT_ID. (AHI_DEFAULT_ID is the ID the user has selected
  314. *           in the preferences program. It's a good value to use the first
  315. *           time she starts your application.)
  316. *
  317. *       AHIA_MixFreq (ULONG) - Desired mixing frequency. The actual
  318. *           mixing rate may or may not be exactly what you asked for.
  319. *           Default is AHI_DEFAULT_FREQ. (AHI_DEFAULT_FREQ is the user's
  320. *           prefered frequency.)
  321. *
  322. *       AHIA_Channels (UWORD) - Number of channel to use. The actual
  323. *           number of channels used will be equal or grater than the
  324. *           requested. If too many channels were requested, this function
  325. *           will fail. This tag must be supplied.
  326. *
  327. *       AHIA_Sounds (UWORD) - Number of sounds to use. This tag must be
  328. *           supplied.
  329. *
  330. *       AHIA_SoundFunc (struct Hook *) - A function to call each time
  331. *           when a sound has been started. The function receives the
  332. *           following parameters:
  333. *               A0 - (struct Hook *)
  334. *               A2 - (struct AHIAudioCtrl *)
  335. *               A1 - (struct AHISoundMessage *)
  336. *           The hook may be called from an interrupt, so normal interrupt
  337. *           restrictions apply.
  338. *
  339. *           The called function should follow normal register conventions,
  340. *           which means that d2-d7 and a2-a6 must be preserved.
  341. *
  342. *           Default is NULL.
  343. *
  344. *       AHIA_PlayerFunc (struct Hook *) - A function to be called at regular
  345. *           intervals. By using this hook there is no need for music players
  346. *           to use other timing, such as VBLANK or CIA timers. But the real
  347. *           reason it's present is that it makes it possible to do non-
  348. *           realtime mixing to disk.
  349. *
  350. *           Using this interrupt source is currently the only supported way
  351. *           to ensure that no mixing occurs between calls to AHI_SetVol(),
  352. *           AHI_SetFreq() or AHI_SetSound().
  353. *
  354. *           If the sound playback is done without mixing, 'realtime.library'
  355. *           is used to provide timing. The function receives the following
  356. *           parameters:
  357. *               A0 - (struct Hook *)
  358. *               A2 - (struct AHIAudioCtrl *)
  359. *               A1 - Undefined.
  360. *           Do not assume A1 contains any particular value!
  361. *           The hook may be called from an interrupt, so normal interrupt
  362. *           restrictions apply.
  363. *
  364. *           The called function should follow normal register conventions,
  365. *           which means that d2-d7 and a2-a6 must be preserved.
  366. *
  367. *           Default is NULL.
  368. *
  369. *       AHIA_PlayerFreq (Fixed) - If non-zero, enables timing and specifies
  370. *           how many times per second PlayerFunc will be called. This must
  371. *           be specified if AHIA_PlayerFunc is! Do not use any extreme
  372. *           frequencies. The result of MixFreq/PlayerFreq must fit an UWORD,
  373. *           ie it must be less or equal to 65535. It is also suggested that
  374. *           you keep the result over 80. For normal use this should not be a
  375. *           problem. Note that the data type is Fixed, not integer. 50 Hz is
  376. *           50<<16.
  377. *
  378. *           Default is a reasonable value. Don't depend on it.
  379. *
  380. *       AHIA_MinPlayerFreq (Fixed) - The minimum frequency (AHIA_PlayerFreq)
  381. *           you will use. You MUST supply this if you are using the device's
  382. *           interrupt feature!
  383. *
  384. *       AHIA_MaxPlayerFreq (Fixed) - The maximum frequency (AHIA_PlayerFreq)
  385. *           you will use. You MUST supply this if you are using the device's
  386. *           interrupt feature!
  387. *
  388. *       AHIA_RecordFunc (struct Hook *) - This function will be called
  389. *           regularly when sampling is turned on (see AHI_ControlAudioA())
  390. *           with the following parameters:
  391. *               A0 - (struct Hook *)
  392. *               A2 - (struct AHIAudioCtrl *)
  393. *               A1 - (struct AHIRecordMessage *)
  394. *           The message (AHIRecordMessage) is filled as follows:
  395. *               ahirm_Buffer - Pointer to the samples. The buffer is valid
  396. *                   until next time the Hook is called.
  397. *               ahirm_Length - Number of sample FRAMES in buffer.
  398. *                   To get the size in bytes, multiply by 4 if ahiim_Type is
  399. *                   AHIST_S16S.
  400. *               ahirm_Type - Always AHIST_S16S at the moment, but you *must*
  401. *                   check this, since it may change in the future!
  402. *           The hook may be called from an interrupt, so normal interrupt
  403. *           restrictions apply. Signal a process if you wish to save the
  404. *           buffer to disk. The called function should follow normal register
  405. *           conventions, which means that d2-d7 and a2-a6 must be preserved.
  406. *
  407. *           NOTE: The function MUST return NULL (in d0). This was previously
  408. *           not documented. Now you know.
  409. *
  410. *           Default is NULL.
  411. *
  412. *       AHIA_UserData (APTR) - Can be used to initialize the ahiac_UserData
  413. *           field. Default is 0.
  414. *
  415. *   RESULT
  416. *       A pointer to an AHIAudioCtrl structure or NULL if an error occured.
  417. *
  418. *   EXAMPLE
  419. *
  420. *   NOTES
  421. *       SoundFunc will be called in the same manner as Paula interrupts
  422. *       occur; when the device has updated its internal variables and can
  423. *       accept new commands.
  424. *
  425. *   BUGS
  426. *
  427. *   SEE ALSO
  428. *       AHI_FreeAudio(), AHI_ControlAudioA()
  429. *
  430. ****************************************************************************
  431. *
  432. */
  433.  
  434. struct AHIAudioCtrl * ASMCALL
  435. AllocAudioA( REG(a1, struct TagItem *tags),
  436.              REG(a6, struct AHIBase *AHIBase) )
  437. {
  438.   struct AHIPrivAudioCtrl* audioctrl;
  439.   struct Library *AHIsubBase;
  440.   struct AHI_AudioDatabase *audiodb;
  441.   struct TagItem *dbtags;
  442.  
  443.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  444.   {
  445.     Debug_AllocAudioA(tags);
  446.   }
  447.  
  448.   audioctrl = CreateAudioCtrl( tags );
  449.   if(!audioctrl)
  450.     goto error;
  451.  
  452.   AHIBase->ahib_AudioCtrl=audioctrl;                      // Save latest (for KillAudio)
  453.  
  454.   if(!audioctrl->ac.ahiac_Channels || !audioctrl->ac.ahiac_Sounds)
  455.     goto error;
  456.  
  457.   audioctrl->ahiac_SubAllocRC = AHISF_ERROR;
  458.   audioctrl->ahiac_SubLib=
  459.   AHIsubBase = OpenLibrary(audioctrl->ahiac_DriverName,DriverVersion);
  460.  
  461.   if(!AHIsubBase)
  462.     goto error;
  463.  
  464.   // Never allow drivers that are newer than ahi.device.
  465.   if(AHIsubBase->lib_Version > Version)
  466.     goto error;
  467.  
  468.   audiodb=LockDatabase();
  469.   if(!audiodb)
  470.     goto error;
  471.  
  472.   dbtags=GetDBTagList(audiodb,audioctrl->ahiac_AudioID);
  473.   if(dbtags)
  474.     audioctrl->ahiac_SubAllocRC=AHIsub_AllocAudio(dbtags,(struct AHIAudioCtrlDrv *)audioctrl);
  475.  
  476.   UnlockDatabase(audiodb);
  477.  
  478.   if(!dbtags)
  479.     goto error;
  480.  
  481.   UpdateAudioCtrl(audioctrl);
  482.  
  483.   if(audioctrl->ahiac_SubAllocRC & AHISF_ERROR)
  484.     goto error;
  485.  
  486. // Mixing
  487.   if(!(audioctrl->ahiac_SubAllocRC & AHISF_MIXING))
  488.     audioctrl->ac.ahiac_Flags |= AHIACF_NOMIXING;
  489.  
  490. // Timing    
  491.   if(!(audioctrl->ahiac_SubAllocRC & AHISF_TIMING))
  492.     audioctrl->ac.ahiac_Flags |= AHIACF_NOTIMING;
  493.  
  494. // Stereo
  495.   if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWSTEREO))
  496.     audioctrl->ac.ahiac_Flags &= ~AHIACF_STEREO;
  497.  
  498. // HiFi
  499. #ifdef HAVE_HIFI
  500.   if(!(audioctrl->ahiac_SubAllocRC & AHISF_KNOWHIFI))
  501.     audioctrl->ac.ahiac_Flags &= ~AHIACF_HIFI;
  502. #else
  503.   // If plain 68k, unconditionally clear the HIFI bit
  504.     audioctrl->ac.ahiac_Flags &= ~AHIACF_HIFI;
  505. #endif
  506.  
  507. // Post-processing
  508.   if(audioctrl->ahiac_SubAllocRC & AHISF_CANPOSTPROCESS)
  509.     audioctrl->ac.ahiac_Flags |= AHIACF_POSTPROC;
  510.  
  511.   if(!(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING))
  512.   {
  513.     switch(audioctrl->ac.ahiac_Flags & (AHIACF_STEREO | AHIACF_HIFI))
  514.     {
  515.       case NULL:
  516.         audioctrl->ac.ahiac_BuffType=AHIST_M16S;
  517.         break;
  518.       case AHIACF_STEREO:
  519.         audioctrl->ac.ahiac_BuffType=AHIST_S16S;
  520.         break;
  521.       case AHIACF_HIFI:
  522.         audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
  523.         audioctrl->ac.ahiac_BuffType=AHIST_M32S;
  524.         break;
  525.       case (AHIACF_STEREO | AHIACF_HIFI):
  526.         audioctrl->ac.ahiac_Flags |= AHIACF_CLIPPING;
  527.         audioctrl->ac.ahiac_BuffType=AHIST_S32S;
  528.         break;
  529.       default:
  530.         Alert(AT_Recovery|AG_BadParm);
  531.         goto error;
  532.     }
  533.  
  534. /* Max channels/2 channels per hardware channel if stereo w/o pan */
  535.     if((audioctrl->ac.ahiac_Flags & (AHIACF_STEREO | AHIACF_PAN)) == AHIACF_STEREO)
  536.       audioctrl->ahiac_Channels2=(audioctrl->ac.ahiac_Channels+1)/2;
  537.     else
  538.       audioctrl->ahiac_Channels2=audioctrl->ac.ahiac_Channels;
  539. /*
  540.     KPrintF("Mode: 0x%08lx, channels: %ld (%ld), flags: 0x%08lx\n",
  541.         audioctrl->ac.ahiac_BuffType, audioctrl->ac.ahiac_Channels,
  542.         audioctrl->ahiac_Channels2, audioctrl->ac.ahiac_Flags);
  543. */
  544.  
  545.     if(!(audioctrl->ac.ahiac_Flags & AHIACF_NOTIMING))
  546.     {
  547.       RecalcBuff(audioctrl->ac.ahiac_MinPlayerFreq,audioctrl);
  548.       audioctrl->ac.ahiac_BuffSize=audioctrl->ahiac_BuffSizeNow;
  549.       RecalcBuff(audioctrl->ac.ahiac_PlayerFreq,audioctrl);
  550.     }
  551.     else // No timing
  552.     {
  553.       ULONG size;
  554.  
  555.       size=audioctrl->ac.ahiac_BuffSamples*\
  556.            AHI_SampleFrameSize(audioctrl->ac.ahiac_BuffType)*\
  557.            (audioctrl->ac.ahiac_Flags & AHIACF_POSTPROC ? 2 : 1);
  558.  
  559.       size +=7;
  560.       size &= ~7;  // byte align
  561.  
  562.       audioctrl->ahiac_BuffSizeNow=size;
  563.     }
  564.  
  565.     audioctrl->ac.ahiac_MixerFunc=AllocVec(sizeof(struct Hook),MEMF_PUBLIC|MEMF_CLEAR);
  566.     if(!audioctrl->ac.ahiac_MixerFunc)
  567.       goto error;
  568.  
  569.  
  570.     audioctrl->ac.ahiac_MixerFunc->h_Entry = (HOOKFUNC) Mix;
  571.  
  572.     if((AHIBase->ahib_MaxCPU >= 0x10000) || (AHIBase->ahib_MaxCPU <= 0x0))
  573.     {
  574.       audioctrl->ac.ahiac_PreTimer  = (BOOL (*)(void)) DummyPreTimer;
  575.       audioctrl->ac.ahiac_PostTimer = (void (*)(void)) DummyPostTimer;
  576.     }
  577.     else
  578.     {
  579.       audioctrl->ahiac_MaxCPU       = AHIBase->ahib_MaxCPU >> 8;
  580.       audioctrl->ac.ahiac_PreTimer  = (BOOL (*)(void)) PreTimer;
  581.       audioctrl->ac.ahiac_PostTimer = (void (*)(void)) PostTimer;
  582.     }
  583.  
  584.     if( !InitMixroutine( audioctrl ) ) goto error;
  585.   }
  586.  
  587.   audioctrl->ac.ahiac_SamplerFunc = AllocVec(sizeof(struct Hook),
  588.       MEMF_PUBLIC|MEMF_CLEAR);
  589.   if(!audioctrl->ac.ahiac_SamplerFunc)
  590.     goto error;
  591.   audioctrl->ac.ahiac_SamplerFunc->h_Entry = (HOOKFUNC) Sampler;
  592.  
  593.   /* Set default hardware properties, only if AHI_DEFAULT_ID was used!*/
  594.   if(GetTagData(AHIA_AudioID, AHI_DEFAULT_ID, tags) == AHI_DEFAULT_ID)
  595.   {
  596.     AHI_ControlAudio((struct AHIAudioCtrl *)audioctrl,
  597.         AHIC_MonitorVolume,   AHIBase->ahib_MonitorVolume,
  598.         AHIC_InputGain,       AHIBase->ahib_InputGain,
  599.         AHIC_OutputVolume,    AHIBase->ahib_OutputVolume,
  600.         AHIC_Input,           AHIBase->ahib_Input,
  601.         AHIC_Output,          AHIBase->ahib_Output,
  602.         TAG_DONE);
  603.   }
  604.  
  605. exit:
  606.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  607.   {
  608.     KPrintF("=>0x%08lx\n",audioctrl);
  609.   }
  610.   return (struct AHIAudioCtrl *) audioctrl;
  611.  
  612.  
  613. error:
  614.   AHI_FreeAudio((struct AHIAudioCtrl *)audioctrl);
  615.   audioctrl=NULL;
  616.   goto exit;
  617. }
  618.  
  619.  
  620. /******************************************************************************
  621. ** AHI_FreeAudio **************************************************************
  622. ******************************************************************************/
  623.  
  624. /****** ahi.device/AHI_FreeAudio *******************************************
  625. *
  626. *   NAME
  627. *       AHI_FreeAudio -- deallocates the audio hardware
  628. *
  629. *   SYNOPSIS
  630. *       AHI_FreeAudio( audioctrl );
  631. *                      A2
  632. *
  633. *       void AHI_FreeAudio( struct AHIAudioCtrl * );
  634. *
  635. *   FUNCTION
  636. *       Deallocates the AHIAudioCtrl structure and any other resources
  637. *       allocated by AHI_AllocAudioA(). After this call it must not be used
  638. *       by any other functions anymore. AHI_UnloadSound() is automatically
  639. *       called for every sound.
  640. *
  641. *   INPUTS
  642. *       audioctrl - A pointer to an AHIAudioCtrl structure obtained from
  643. *           AHI_AllocAudioA(). If NULL, this function does nothing.
  644. *
  645. *   EXAMPLE
  646. *
  647. *   NOTES
  648. *
  649. *   BUGS
  650. *
  651. *   SEE ALSO
  652. *       AHI_AllocAudioA(), AHI_UnloadSound()
  653. *
  654. ****************************************************************************
  655. *
  656. */
  657.  
  658. ULONG ASMCALL
  659. FreeAudio( REG(a2, struct AHIPrivAudioCtrl *audioctrl),
  660.            REG(a6, struct AHIBase *AHIBase) )
  661. {
  662.   struct Library *AHIsubBase;
  663.   int i;
  664.  
  665.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  666.   {
  667.     Debug_FreeAudio(audioctrl);
  668.   }
  669.  
  670.   if(audioctrl)
  671.   {
  672.     if((AHIsubBase=audioctrl->ahiac_SubLib))
  673.     {
  674.       if(!(audioctrl->ahiac_SubAllocRC & AHISF_ERROR))
  675.       {
  676.         AHIsub_Stop(AHISF_PLAY|AHISF_RECORD,(struct AHIAudioCtrlDrv *)audioctrl);
  677.  
  678.         for(i=audioctrl->ac.ahiac_Sounds-1;i>=0;i--)
  679.         {
  680.           AHI_UnloadSound(i,(struct AHIAudioCtrl *)audioctrl);
  681.         }
  682.       }
  683.       AHIsub_FreeAudio((struct AHIAudioCtrlDrv *) audioctrl);
  684.       CloseLibrary(AHIsubBase);
  685.     }
  686.  
  687.     if(!(audioctrl->ac.ahiac_Flags & AHIACF_NOMIXING))
  688.     {
  689.       CleanUpMixroutine( audioctrl );
  690.     }
  691.  
  692.     FreeVec( audioctrl->ahiac_MasterVolumeTable );
  693.     FreeVec( audioctrl->ahiac_MultTableS );
  694.     FreeVec( audioctrl->ahiac_MultTableU );
  695.     FreeVec( audioctrl->ac.ahiac_SamplerFunc );
  696.     FreeVec( audioctrl->ac.ahiac_MixerFunc );
  697.  
  698.     AHIFreeVec( audioctrl );
  699.   }
  700.   return NULL;
  701. }
  702.  
  703.  
  704. /******************************************************************************
  705. ** AHI_KillAudio **************************************************************
  706. ******************************************************************************/
  707.  
  708. /****i* ahi.device/AHI_KillAudio *******************************************
  709. *
  710. *   NAME
  711. *      AHI_KillAudio -- clean up
  712. *
  713. *   SYNOPSIS
  714. *      AHI_KillAudio();
  715. *
  716. *      void AHI_KillAudio( void );
  717. *
  718. *   FUNCTION
  719. *      'ahi.device' keeps track of most of what the user does. This call is
  720. *      used to clean up as much as possible. It must never, ever, be used
  721. *      in an application. It is included for development use only, and can
  722. *      be used to avoid rebooting the computer if your program has allocated
  723. *      the audio hardware and crashed. This call can lead to a system crash,
  724. *      so don't use it if you don't have to.
  725. *
  726. *   INPUTS
  727. *
  728. *   RESULT
  729. *      This function returns nothing. In fact, it may never return.
  730. *
  731. *   EXAMPLE
  732. *
  733. *   NOTES
  734. *
  735. *   BUGS
  736. *
  737. *   SEE ALSO
  738. *      AHI_FreeAudio()
  739. *
  740. ****************************************************************************
  741. *
  742. */
  743.  
  744. ULONG ASMCALL
  745. KillAudio( REG(a6, struct AHIBase *AHIBase) )
  746. {
  747.   UWORD i;
  748.  
  749.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  750.   {
  751.     Debug_KillAudio();
  752.   }
  753.  
  754.   for(i=0xffff;i != 0; i--)
  755.   {
  756.     *((UWORD *) 0xdff102)=i;
  757.   }
  758.  
  759.   AHI_FreeAudio(AHIBase->ahib_AudioCtrl);
  760.   AHIBase->ahib_AudioCtrl=NULL;
  761.   return NULL;
  762. }
  763.  
  764.  
  765. /******************************************************************************
  766. ** AHI_ControlAudioA **********************************************************
  767. ******************************************************************************/
  768.  
  769. /****** ahi.device/AHI_ControlAudioA ***************************************
  770. *
  771. *   NAME
  772. *       AHI_ControlAudioA -- change audio attributes
  773. *       AHI_ControlAudio -- varargs stub for AHI_ControlAudioA()
  774. *
  775. *   SYNOPSIS
  776. *       error = AHI_ControlAudioA( audioctrl, tags );
  777. *       D0                         A2         A1
  778. *
  779. *       ULONG AHI_ControlAudioA( struct AHIAudioCtrl *, struct TagItem * );
  780. *
  781. *       error = AHI_ControlAudio( AudioCtrl, tag1, ...);
  782. *
  783. *       ULONG AHI_ControlAudio( struct AHIAudioCtrl *, Tag, ... );
  784. *
  785. *   FUNCTION
  786. *       This function should be used to change attributes for a given
  787. *       AHIAudioCtrl structure. It is also used to start and stop playback,
  788. *       and to control special hardware found on some sound cards.
  789. *
  790. *   INPUTS
  791. *       audioctrl - A pointer to an AHIAudioCtrl structure.
  792. *       tags - A pointer to a tag list.
  793. *
  794. *   TAGS
  795. *       AHIC_Play (BOOL) - Starts (TRUE) and stops (FALSE) playback and
  796. *           PlayerFunc. NOTE: If the audio hardware cannot play at the same
  797. *           time as recording samples, the recording will be stopped.
  798. *
  799. *       AHIC_Record (BOOL) - Starts (TRUE) and stops (FALSE) sampling and
  800. *           RecordFunc. NOTE: If the audio hardware cannot record at the same
  801. *           time as playing samples, the playback will be stopped.
  802. *
  803. *       AHIC_MonitorVolume (Fixed) - Sets the input monitor volume, i.e. how
  804. *           much of the input signal is mixed with the output signal while
  805. *           recording. Use AHI_GetAudioAttrsA() to find the available range.
  806. *
  807. *       AHIC_MonitorVolume_Query (Fixed *) - Get the current input monitor
  808. *           volume. ti_Data is a pointer to a Fixed variable, where the result
  809. *           will be stored.
  810. *
  811. *       AHIC_MixFreq_Query (ULONG *) - Get the current mixing frequency.
  812. *           ti_Data is a pointer to an ULONG variable, where the result will
  813. *           be stored.
  814. *
  815. *       AHIC_InputGain (Fixed) - Set the input gain. Use AHI_GetAudioAttrsA()
  816. *           to find the available range. (V2)
  817. *
  818. *       AHIC_InputGain_Query (Fixed *) - Get current input gain. (V2)
  819. *
  820. *       AHIC_OutputVolume (Fixed) - Set the output volume. Use
  821. *           AHI_GetAudioAttrsA() to find the available range. (V2)
  822. *
  823. *       AHIC_OutputVolume_Query (Fixed *) - Get current output volume. (V2)
  824. *
  825. *       AHIC_Input (ULONG) - Select input source. See AHI_GetAudioAttrsA().
  826. *           (V2)
  827. *
  828. *       AHIC_Input_Query (ULONG *) - Get current input source. (V2)
  829. *
  830. *       AHIC_Output (ULONG) - Select destination for output. See
  831. *           AHI_GetAudioAttrsA(). (V2)
  832. *
  833. *       AHIC_Output_Query (ULONG *) - Get destination for output. (V2)
  834. *
  835. *       The following tags are also recognized by AHI_ControlAudioA(). See
  836. *       AHI_AllocAudioA() for what they do. They may be used from interrupts.
  837. *
  838. *       AHIA_SoundFunc (struct Hook *)
  839. *       AHIA_PlayerFunc (struct Hook *)
  840. *       AHIA_PlayerFreq (Fixed)
  841. *       AHIA_RecordFunc (struct Hook *)
  842. *       AHIA_UserData (APTR)
  843. *
  844. *       Note that AHIA_PlayerFreq must never be outside the limits specified
  845. *       with AHIA_MinPlayerFreq and AHIA_MaxPlayerFreq! Also note that the
  846. *       timing feature is designed to be used for music. When you change the
  847. *       frequency, be reasonable. Using 50 Hz one moment and 5 the other is
  848. *       to ask for trouble.
  849. *
  850. *   RESULT
  851. *       An error code, defined in <devices/ahi.h>.
  852. *
  853. *   EXAMPLE
  854. *
  855. *   NOTES
  856. *       The AHIC_Play and AHIC_Record tags *must not* be used from
  857. *       interrupts.
  858. *
  859. *   BUGS
  860. *
  861. *   SEE ALSO
  862. *       AHI_AllocAudioA(), AHI_GetAudioAttrsA(), <devices/ahi.h>
  863. *
  864. ****************************************************************************
  865. *
  866. */
  867.  
  868. ULONG ASMCALL
  869. ControlAudioA( REG(a2, struct AHIPrivAudioCtrl *audioctrl),
  870.                REG(a1, struct TagItem *tags),
  871.                REG(a6, struct AHIBase *AHIBase) )
  872. {
  873.   ULONG *ptr, playflags=NULL, stopflags=NULL, rc=AHIE_OK;
  874.   UBYTE update=FALSE;
  875.   struct TagItem *tag,*tstate=tags;
  876.   struct Library *AHIsubBase=audioctrl->ahiac_SubLib;
  877.  
  878.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  879.   {
  880.     Debug_ControlAudioA(audioctrl,tags);
  881.   }
  882.  
  883.   while((tag=NextTagItem(&tstate)))
  884.   {
  885.     ptr=(ULONG *)tag->ti_Data;  // For ..._Query tags
  886.     switch(tag->ti_Tag)
  887.     {
  888.     case AHIA_SoundFunc:
  889.       audioctrl->ac.ahiac_SoundFunc=(struct Hook *) tag->ti_Data;
  890.       update=TRUE;
  891.       break;
  892.     case AHIA_RecordFunc:
  893.       audioctrl->ahiac_RecordFunc=(struct Hook *) tag->ti_Data;
  894.       update=TRUE;
  895.       break;
  896.     case AHIA_PlayerFunc:
  897.       audioctrl->ac.ahiac_PlayerFunc=(struct Hook *) tag->ti_Data;
  898.       update=TRUE;
  899.       break;
  900.     case AHIA_PlayerFreq:
  901.       audioctrl->ac.ahiac_PlayerFreq=tag->ti_Data;
  902.  
  903.       if(audioctrl->ac.ahiac_PlayerFreq < 65536)
  904.         audioctrl->ac.ahiac_PlayerFreq <<= 16;
  905.  
  906.       if(!(audioctrl->ac.ahiac_Flags & AHIACF_NOTIMING)) // Dont call unless timing is used.
  907.         RecalcBuff(audioctrl->ac.ahiac_PlayerFreq,audioctrl);
  908.       update=TRUE;
  909.       break;
  910.     case AHIA_UserData:
  911.       audioctrl->ac.ahiac_AudioCtrl.ahiac_UserData=(void *)tag->ti_Data;
  912.       break;
  913.     case AHIC_Play:
  914.       if(tag->ti_Data)
  915.       {
  916.         playflags |= AHISF_PLAY;
  917.         stopflags &= ~AHISF_PLAY;
  918.       }
  919.       else
  920.       {
  921.         playflags &= ~AHISF_PLAY;
  922.         stopflags |= AHISF_PLAY;
  923.       }
  924.       update=FALSE;
  925.       break;
  926.     case AHIC_Record:
  927.       if(tag->ti_Data)
  928.       {
  929.         playflags |= AHISF_RECORD;
  930.         stopflags &= ~AHISF_RECORD;
  931.       }
  932.       else
  933.       {
  934.         playflags &= ~AHISF_RECORD;
  935.         stopflags |= AHISF_RECORD;
  936.       }
  937.       update=FALSE;
  938.       break;
  939.     case AHIC_MixFreq_Query:
  940.       *ptr=audioctrl->ac.ahiac_MixFreq;
  941.       break;
  942.     case AHIC_MonitorVolume:
  943.     case AHIC_InputGain:
  944.     case AHIC_OutputVolume:
  945.     case AHIC_Input:
  946.     case AHIC_Output:
  947.       AHIsub_HardwareControl(tag->ti_Tag, tag->ti_Data, (struct AHIAudioCtrlDrv *)audioctrl);
  948.       break;
  949.     case AHIC_MonitorVolume_Query:
  950.     case AHIC_InputGain_Query:
  951.     case AHIC_OutputVolume_Query:
  952.     case AHIC_Input_Query:
  953.     case AHIC_Output_Query:
  954.       *ptr=AHIsub_HardwareControl(tag->ti_Tag, NULL, (struct AHIAudioCtrlDrv *)audioctrl);
  955.       break;
  956.     }
  957.   }
  958.  
  959. // Let's act!
  960.   if(update)
  961.   {
  962.     AHIsub_Update(NULL,(struct AHIAudioCtrlDrv *)audioctrl);
  963.   }
  964.   
  965.   if(playflags)
  966.   {
  967.     rc=AHIsub_Start(playflags,(struct AHIAudioCtrlDrv *)audioctrl);
  968.   }
  969.   
  970.   if(stopflags)
  971.   {
  972.     AHIsub_Stop(stopflags,(struct AHIAudioCtrlDrv *)audioctrl);
  973.   }
  974.  
  975.   if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  976.   {
  977.     KPrintF("=>%ld\n",rc);
  978.   }
  979.  
  980.   return rc;
  981. }
  982.