home *** CD-ROM | disk | FTP | other *** search
/ Dream 44 / Amiga_Dream_44.iso / Linux / Apps / xanim.tgz / xanim / xanim27064 / xa_audio.c < prev    next >
Text File  |  1997-01-26  |  151KB  |  5,202 lines

  1.  
  2. /*
  3.  * xa_audio.c
  4.  *
  5.  * Copyright (C) 1994,1995,1996,1997 by Mark Podlipec.
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified and redistributed without
  9.  * fee for non-commerical purposes provided that this copyright notice is
  10.  * preserved intact on all copies and modified copies.
  11.  *
  12.  * There is no warranty or other guarantee of fitness of this software.
  13.  * It is provided solely "as is". The author(s) disclaim(s) all
  14.  * responsibility and liability with respect to this software's usage
  15.  * or its effect upon hardware or computer systems.
  16.  *
  17.  */
  18.  
  19. /***************************************************************************
  20.  * Fixes (Most are sent in by beta testers for which I'm grateful)
  21.  *
  22.  *       - Linux: jixer should be mixer.
  23.  *       - Linux: Added 8 bit converison routines.
  24.  *       - Solaris audioio.h in include/sys not include/sun.
  25.  * 3Aug94  - Signals Suck. Use XtAppAddTimeOut instead.
  26.  * 4Aug94  - Linux 8 bit init incorrectly returning XA_AUDIO_SIGNED_1M.
  27.  *           Now it's XA_AUDIO_LINEAR_1M.
  28.  * 4Aug94  - Solaris opening ioctl using devtype instead of type and
  29.  *         type should be audio_device_t (missing _t before).
  30.  * 4Aug94  - Linux: ioctl call to set volume was be reference only. It's
  31.  *         now properly #ifdef'd depending on XA_LINUX_NEWER_SND.
  32.  * 5Aug94  - Linux: volume ioctl uses SOUND_MIXER_VOLUME now. Did try
  33.  *         SOUND_MIXER_PCM, but some machines didn't like that.
  34.  * 8Aug94  - All: added XA_Audio_Pause routine for those devices that
  35.  *         support pause/resume. Much better that having to flush it.
  36.  *       - Solaris: XA_SOLARIS should've been SOLARIS. was causing
  37.  *         core dumps etc.
  38.  *       - ALL(but only affects Solaris): Solaris doesn't like writes to
  39.  *         the audio buffer that aren't multiples of it's size. Is this
  40.  *         the problem with SGI's? Anyways UpdateRing now enforces this.
  41.  *       - Sparc: Detects if audio device is already in use and continues
  42.  *         on without it. Before it used to hang until audio was freed.
  43.  *       - Sparc: Volume turned off when flushing and then back on after.
  44.  *         Gets rid of clicks/pops when exiting.
  45.  * 10Aug94 - Fixed problem with SGI machines. Samples not bytes and 
  46.  *        - SIGNED_2MB not LINEAR_2MB.
  47.  * 10Aug94 - Change volume to 0-100%. May have broken them all. :^)
  48.  * 11Aug94 - Added code for HP9000/700 series. Have no clue if it works.
  49.  * 31Aug94 - Linux: Finally got the linux docs. I'm not querying the device
  50.  *         to see what volume channel to use.
  51.  * 12Sep94 - SPARC 5: now look for CS4231 Audio devices. Should be treated
  52.  *         the same as  Sparc 10's DBRI device.
  53.  * 21Sep94 - ALL: Closest_Freq() must have ifreq be signed in order for the
  54.  *           comparison's to be done correctly.
  55.  * 22Sep94 - Screw Pausing for now. Will put back later if deemed necessary.
  56.  * 27Sep94 - HP: found serious typo bug that caused the Audio Ring buffers
  57.  *         to be overwritten by a large amount, trashing all sorts of
  58.  *         memory and causing much grief. Thanks to John Atwood for
  59.  *         helping find this one.
  60.  * 13Oct94 - SGI: really change LINEAR_2MB to be SIGNED_2MB this time. Arrgh.
  61.  * 26Oct94 - Added code to support NAS 1.2 p1 
  62.  *                    - Bob Phillips (bobp@syl.nj.nec.com)
  63.  * 28Oct94 - Added code to support NEC EWS 4800/330 - NEC
  64.  *                    - Bob Phillips (bobp@syl.nj.nec.com)
  65.  * 02Nov94 - AF hardware type was set to 16 bit little endian, yet the AF
  66.  *         library was told to expect native endian. This didn't work
  67.  *         on Suns(nor would it on other big endian machines).
  68.  *                            - Andrzej Filinski <andrzej+@POP.CS.CMU.EDU>
  69.  * 13Nov94 - NAS: fine tuned code for less drop out. Fixed up stop/start
  70.  *         problems(echos).
  71.  * 13Jan95 - SGI: sgi volume is exponentional, not linear - Paul Close
  72.  * 19Jan95 - Sparc: Older Sparc can only have 1 audio output at a time
  73.  *           and not 0. This made it impossible to enable the headphones
  74.  *         because the code would first try turning off the speaker and
  75.  *         take an error.
  76.  * 30Jan95 - SONY: added support for Sony NEWS-5000 workstations - code
  77.  *         written by Kazushi Yoshida.
  78.  * 16Mar95 - Finished remodified audio/vidoe sync code to handle more
  79.  *           compute intensive video(large frame or jpeg/mpeg)
  80.  * 17Mar95 - Merged Audio_Outputs into one routine so I didn't have to
  81.  *           keep modifying all of them(95% of the code was the same).
  82.  * 17Mar95 - Fixed bug in NAS audio that caused memory corruption after
  83.  *           an "unable to Toggle" error.
  84.  * 17Mar95 - Added Audio support for IBM AIX S6000 machines - 
  85.  *        Code written by jeffk@watson.ibm.com (Jeff Kusnitz)
  86.  * 06Apr95 - Added Audio support for directly using HP's Audio Device
  87.  *        rather than going through all the upper audio library
  88.  *        layers. (HPDEV) Code written by Tobias Bading.
  89.  * 10Apr95 - Fixed bug where when Audio finished before Video, it wasn't
  90.  *         being turned off before being turned on during the next loop
  91.  *         or for the next animation.
  92.  * 10Apr95 - Fixed where hard_buff size was being set larger than the
  93.  *         allocated buffer size for the following machines(Linux/AIX.
  94.  *           (All sorts of bad behavior - core's dumps etc).
  95.  * 10Apr95 - Fixed MS ADPCM bug when 11Khx and 22Khz ADPCM freq were scaled
  96.  *         to 8Khz.
  97.  * 30Apr95 - Added audio support for Digital Alpha workstations
  98.  *           running MMS (morris@zko.dec.com)
  99.  * 11May95 - Added Audio support for NetBSD - written by Roland C Dowdeswell.
  100.  * 13Jun95 - SONY: modified for SVR4/NEWS-OS 6.x machines 
  101.  *         by Takashi Hagiwara, Sony Corporation (hagiwara@sm.sony.co.jp)
  102.  * 04Sep95 - SOLARIS: replaced SOLARIS define with SVR4. see what happens.
  103.  * 12Apr96 - HPDEV: occasionally audio device reports busy when trying to
  104.  *           set the sample rate. Now loop on this condition.
  105.  * 25Nov96 - HP AServer. Code fixed up by Steve Waterworth.
  106.  *
  107.  ****************************************************************************/
  108.  
  109.  
  110. /****************************************************************************/
  111. /**************** AUDIO DOCUMENTATION ***************************************/
  112. /****************************************************************************/
  113. /*
  114.  In order to support other machines type - XXX, the following routines must
  115.  be created and should be inside an #ifdef XA_XXX_AUDIO.
  116.  
  117.  Currently Needed Routines:
  118.  -----------------------------------
  119.    void  XA_Audio_Setup()
  120.    void  XXX_Audio_Init()
  121.    void  XXX_Audio_Kill()
  122.    void  XXX_Audio_Off()
  123.    void  XXX_Audio_On()
  124.    xaULONG XXX_Closest_Freq(target_freq)
  125.    void  XXX_Set_Audio_Out(flag)   slowly replacing toggles 
  126.    void  XXX_Speaker_Tog(flag)
  127.    void  XXX_Headphone_Tog(flag)
  128.    void  XXX_LineOut_Tog(flag)
  129.    void  XXX_Audio_Output()
  130.  
  131.  Currently Optional Routines:
  132.  -----------------------------------
  133.    XXX_Adjust_Volume(volume)
  134.  
  135.  NOTES: Currently stereo isn't supported. It could/can/will be added
  136.  later.
  137.  
  138.  The routine XA_Audio_Setup is responsible for mapping these routines
  139.  to the same routines(with XXX replaced by XA). See the XA_Audio_Setup
  140.  in the Sun section.
  141.  
  142.  Also the Hardware Audio Type should be defined in xanim.h. See the
  143.  AUDIO SECTION of xanim.h. This is then used in XA_Add_Sound routine
  144.  to determine the correct audio codec routine to convert the anim's
  145.  audio format to the hardware's audio format.
  146. (NOTE: moving toward asking hardware what it can support for each
  147.        type of audio. )
  148.  
  149.  Brief description of how XAnim does the sound(may not be correct or finished
  150.  at the time you read this :^)
  151.  
  152.  As XAnim intially parses through the animations, a link list of SND_HDR's
  153.  is created(with the XA_Add_Sound routine) and attached to that animation
  154.  (in it's ANIM_HDR). These SND_HDR's contain audio information/data as it
  155.  existed in the animation file(it may just have a file postion and length so
  156.  the audio data can be read into memory or it may have a buffer already 
  157.  containing the audio data).
  158.  
  159.  XA_Add_Sound determines if the audio format is support and what routine
  160.  should be used to decompress the audio. It also determines the closest
  161.  hardware frequency(with XA_Closest_Freq) and calculates how much time
  162.  (ms and fractional ms) it will take to play a converted sample that
  163.  is xa_audio_hard_buf(set by XA_Closest_Freq) samples in size along
  164.  with other information.
  165.  
  166.  A Ring of Audio buffers is created at init time(by XA_Audio_Init).
  167.  The XA_Update_Ring routine fills these buffers with identical sized
  168.  chunks of converted audio. The fact they're the same size simplifies
  169.  the keeping of audio time(since each audio chunk takes exactly the
  170.  same amount of time-which has been pre-calculated). audio time is
  171.  used to keep the video in sync with the audio.
  172.  
  173.  XA_Update_Ring is called in XA_Audio_On() just before audio is
  174.  started up and is called in XA_Audio_Output() after a Audio Ring
  175.  buffer has been sent to the audio device.
  176.  
  177.  XA_Update_Ring fills empty ring positions by walking along the list
  178.  of SND_HDRs, converting the anim's audio to the proper audio format
  179.  a chunk at a time. It does this by calling the audio codec function
  180.  for that SND_HDR. The audio codec function converts and moves a set
  181.  number of audio samples into the given ring buffer and then returns
  182.  how many bytes in size that is.
  183.  
  184.  XA_Audio_Output just has to look at the current audio ring pointer,
  185.  send that many bytes to the audio device, update the audio time,
  186.  move along the ring and then call XA_Update_Ring.
  187.  
  188.  I might make XA/XXX_Audio_Output generic and then make machine
  189.  specific sub portions of it. As more machine types are added this
  190.  might make more sense.
  191.  
  192.  ----
  193.  
  194.  NOTE: I'm moving toward a separate audio process, this allows
  195.        blocking when writing to the audio device.  However, the
  196.        audio device should be opened non-blocking so that
  197.        XAnim may continue on without audio if the audio device
  198.        is in use by another program.
  199.  
  200.  XA_Audio_On() should enable and startup the audio. 
  201.  
  202.  XA_Audio_Off() should stop the audio. Ideally this routine should
  203.  immediate stop audio and flush what ever information has piled
  204.  up. Unfortunately, many audio drivers are (deficient?) lacking
  205.  this support.
  206.  
  207.  XA_Audio_Init() opens the audio device and initializes the variables.
  208.  XA_Audio_Kill() closes the device and frees up any hardware specific
  209.  memory structures.
  210.  
  211.  ----
  212.  Mark Podlipec - podlipec@Baynetworks.com  or  podlipec@@shell.portal.com
  213. */
  214.  
  215. /* TOP */
  216.  
  217. #include "xa_audio.h"
  218.  
  219. /* POD note:  For opening audio device non-blocking. Should probably set it
  220.  * back to blocking after successful open, but ONLY if compiling with
  221.  * the audio child.
  222.  */
  223.  
  224. #ifndef O_NDELAY
  225. #ifdef O_NONBLOCK
  226. #define O_NDELAY  O_NONBLOCK
  227. #else
  228. #define O_NDELAY 0
  229. #endif
  230. #endif
  231.  
  232. extern XA_AUD_FLAGS *vaudiof;
  233. extern xaULONG xa_vaudio_present;
  234. extern XtAppContext  theAudContext;
  235.  
  236.  
  237. /***************** ITIMER EXPERIMENTATION ********************************/
  238. /* number of ms we let audio buffer get ahead of actual audio. */
  239. xaLONG xa_out_time = 250; /* PODNOTE: this is actually reset later on */
  240. xaULONG xa_out_init = 0;  /* number of initial audio ring bufs to write ahead*/
  241.  
  242. /* 1000/XA_OUT_FREQADJ is number of extra itimer calls  */
  243. #define XA_OUT_FREQADJ 1000
  244.  
  245. /***************** XtAppAddTimeOut EXPERIMENTATION *************************/
  246. XtIntervalId xa_interval_id = 0;
  247. xaULONG        xa_interval_time = 1;
  248.  
  249. extern Display    *theDisp;
  250. extern xaULONG    xa_kludge900_aud;
  251.  
  252.  
  253. /**** Non Hardware Specific Functions ************/
  254. void XA_Audio_Init_Snd();
  255. void Init_Audio_Ring();
  256. void Kill_Audio_Ring();
  257. void XA_Update_Ring();
  258. void XA_Flush_Ring();
  259. XA_SND *XA_Audio_Next_Snd();
  260. void XA_Read_Audio_Delta();
  261. xaLONG XA_Read_AV_Time();
  262. extern xaLONG xa_time_now;
  263. extern xaUBYTE *xa_audcodec_buf;
  264. extern xaULONG xa_audcodec_maxsize;
  265. extern int xa_aud_fd;
  266.  
  267.  
  268. extern xaULONG XA_ADecode_PCMXM_PCM1M();
  269. extern xaULONG XA_ADecode_PCM1M_PCM2M();
  270. extern xaULONG XA_ADecode_DVIM_PCMxM();
  271. extern xaULONG XA_ADecode_DVIS_PCMxM();
  272. extern xaULONG XA_ADecode_IMA4M_PCMxM();
  273. extern xaULONG XA_ADecode_IMA4S_PCMxM();
  274.  
  275.  
  276. typedef struct AUDIO_RING_STRUCT
  277. {
  278.   xaULONG time;
  279.   xaULONG timelo;
  280.   xaULONG len;
  281.   xaUBYTE *buf;
  282.   struct AUDIO_RING_STRUCT *next;
  283. } XA_AUDIO_RING_HDR;
  284.  
  285. XA_AUDIO_RING_HDR *xa_audio_ring = 0;
  286. XA_AUDIO_RING_HDR *xa_audio_ring_t = 0;
  287.  
  288. #define XA_AUDIO_MAX_RING_BUFF 2048
  289.  
  290. /* NOTE: These must NOT be larger than XA_AUDIO_MAX_RING_BUFF above */
  291. #define XA_HARD_BUFF_2K 2048
  292. #define XA_HARD_BUFF_1K 1024
  293.  
  294.  
  295. void Gen_Ulaw_2_Signed();
  296. void Gen_Signed_2_Ulaw();
  297. void Gen_Arm_2_Signed();
  298.  
  299. xaLONG  XA_Ulaw_to_Signed();
  300. xaUBYTE XA_Signed_To_Ulaw();
  301. xaULONG XA_Audio_Linear_To_AU();
  302.  
  303. /*POD NOTE: Make these tables dynamically allocated */
  304. /* Sun ULAW CONVERSION TABLES/ROUTINES */
  305. xaUBYTE xa_sign_2_ulaw[256];
  306. xaULONG xa_ulaw_2_sign[256];
  307.  
  308. /* ARM VIDC MULAW CONVERSION TABLES/ROUTINES */
  309. xaULONG xa_arm_2_signed[256];
  310.  
  311. /* AUDIO CODEC DELTA ROUTINES */ 
  312. xaULONG XA_Audio_1M_1M();
  313. xaULONG XA_Audio_PCM1M_PCM2M();
  314. xaULONG XA_Audio_PCM1S_PCM2M();
  315. xaULONG XA_Audio_PCMXM_PCM1M();
  316. xaULONG XA_Audio_PCMXS_PCM1M();
  317. xaULONG XA_Audio_PCM2X_PCM2M();
  318.  
  319.  
  320. /* AUDIO CODEC BUFFERING ROUTINES */
  321.  
  322. extern xaULONG xa_audio_present;
  323. extern xaULONG xa_audio_status;
  324.  
  325. extern XA_SND *xa_snd_cur;
  326. extern xaLONG  xa_time_audio;
  327. extern xaLONG  xa_timelo_audio;
  328.  
  329. extern XA_AUD_FLAGS *XAAUD;
  330. /*
  331. extern xaULONG xa_audio_mute;
  332. extern xaLONG  xa_audio_volume;
  333. extern xaULONG xa_audio_newvol;
  334. extern double xa_audio_scale;
  335. extern xaULONG xa_audio_buffer;
  336. extern xaULONG xa_audio_playrate;
  337. extern xaULONG xa_audio_divtest;  Z* testing only *Z
  338. extern xaULONG xa_audio_port;
  339. */
  340.  
  341. xaULONG xa_vaudio_hard_buff = 0;        /* VID Domain snd chunk size */
  342.  
  343. xaULONG xa_audio_hard_freq;        /* hardware frequency */
  344. xaULONG xa_audio_hard_buff;        /* preferred snd chunk size */
  345. xaULONG xa_audio_ring_size;        /* preferred num of ring entries */
  346. xaULONG xa_audio_hard_type;        /* hardware sound encoding type */
  347. xaULONG xa_audio_hard_bps;        /* hardware bytes per sample */
  348. xaULONG xa_audio_hard_chans;        /* hardware number of chan. not yet */
  349. xaULONG xa_audio_flushed = 0;
  350.  
  351. void  XA_Audio_Setup();
  352. void (*XA_Audio_Init)();
  353. void (*XA_Audio_Kill)();
  354. void (*XA_Audio_Off)();
  355. void (*XA_Audio_On)();
  356. void (*XA_Adjust_Volume)();
  357. xaULONG (*XA_Closest_Freq)();
  358. void  (*XA_Set_Output_Port)(); /* POD slowly replacing _Tog's */
  359. void  (*XA_Speaker_Tog)();
  360. void  (*XA_Headphone_Tog)();
  361. void  (*XA_LineOut_Tog)();
  362.  
  363. void New_Merged_Audio_Output();
  364.  
  365.  
  366. /****************************************************************************/
  367. /**************** NULL AUDIO DEFINED ROUTINES********************************/
  368. /****************************************************************************/
  369. /* useful for backing out audio when device opens fails, etc */
  370.  
  371. void  XA_NoAudio_Nop();
  372. xaULONG XA_NoAudio_Nop1();
  373. void  XA_NoAudio_Nop2();
  374. void  XA_Null_Audio_Setup();
  375.  
  376. void XA_Null_Audio_Setup()
  377. {
  378.   XA_Audio_Init        = XA_NoAudio_Nop;
  379.   XA_Audio_Kill        = XA_NoAudio_Nop;
  380.   XA_Audio_Off        = XA_NoAudio_Nop2;
  381.   XA_Audio_On        = XA_NoAudio_Nop;
  382.   XA_Closest_Freq    = XA_NoAudio_Nop1;
  383.   XA_Set_Output_Port    = XA_NoAudio_Nop2;
  384.   XA_Speaker_Tog    = XA_NoAudio_Nop;
  385.   XA_Headphone_Tog    = XA_NoAudio_Nop;
  386.   XA_LineOut_Tog    = XA_NoAudio_Nop;
  387.  
  388.   xa_snd_cur = 0;
  389.   xa_audio_present = XA_AUDIO_UNK;
  390.   xa_audio_status  = XA_AUDIO_STOPPED;
  391.   xa_audio_ring_size  = 8;
  392. }
  393. void XA_NoAudio_Nop()                { return; }
  394. void XA_NoAudio_Nop2(flag)    xaULONG flag;    { return; }
  395. xaULONG XA_NoAudio_Nop1(num)    xaULONG num;    { return(0); }
  396.  
  397. /****************************************************************************/
  398. /**************** NO AUDIO DEFINED ROUTINES *********************************/
  399. /****************************************************************************/
  400. #ifndef XA_AUDIO
  401.  
  402. void XA_No_Audio_Support();
  403.  
  404. void XA_Audio_Setup()
  405.   XA_Null_Audio_Setup();
  406.   XA_Audio_Init    = XA_No_Audio_Support;
  407. }
  408.  
  409. void XA_No_Audio_Support()
  410. {
  411.   fprintf(stderr,"AUDIO SUPPORT NOT COMPILED IN THIS EXECUTABLE.\n");
  412.   return;
  413. }
  414. #endif
  415. /****************************************************************************/
  416. /******************* END OF NO AUDIO SPECIFIC ROUTINES **********************/
  417. /****************************************************************************/
  418.  
  419.  
  420. /****************************************************************************/
  421. /**************** SPARC SPECIFIC ROUTINES ***********************************/
  422. /****************************************************************************/
  423. #ifdef XA_SPARC_AUDIO
  424.  
  425. /******** START OF FIX SUN **********************************/
  426. /* SINCE CC, GCC and SUN can't get their act together, let's do it
  427.  * for them. This is to fix some SERIOUS Bugs with Sun's include files.
  428.  *
  429.  * CC works fine with /usr/include/sys/ioccom.h, but not gnu's
  430.  * GCC works fine with it's version of Sun's ioccom.h, but not sun's
  431.  * You mix them up and your code doesn't run. ARGH!!!
  432.  */
  433.  
  434. /* POD NOTE: We'll NOW HAVE TO RELY ON XA_???_AUDIO defines to determine
  435.  * SUN IO compatiblities. Wadda pain.
  436.  */
  437. #ifndef SVR4    /* was SOLARIS */
  438.  
  439. /* from sys/ioccom.h */
  440. #undef _IO
  441. #define _IO(x,y)        (_IOC_VOID|((x)<<8)|y)
  442. #undef _IOR
  443. #define _IOR(x,y,t)     (_IOC_OUT|((sizeof(t)&_IOCPARM_MASK)<<16)|((x)<<8)|y)
  444. #undef _IOWR
  445. #define _IOWR(x,y,t)    (_IOC_INOUT|((sizeof(t)&_IOCPARM_MASK)<<16)|((x)<<8)|y)
  446.  
  447. /* from audioio.h  A = 0x41 */
  448. #undef AUDIO_GETINFO
  449. #define AUDIO_GETINFO   _IOR(0x41, 1, audio_info_t)
  450. #undef AUDIO_SETINFO
  451. #define AUDIO_SETINFO   _IOWR(0x41, 2, audio_info_t)
  452. #undef AUDIO_DRAIN
  453. #define AUDIO_DRAIN     _IO(0x41, 3)
  454. #undef AUDIO_GETDEV
  455. #define AUDIO_GETDEV    _IOR(0x41, 4, int)
  456.  
  457. /* from stropts.h S = 0x53*/
  458. #undef I_FLUSH
  459. #define I_FLUSH         _IO(0x53,05)
  460. /******** END OF FIX SUN **********************************/
  461. #endif
  462.  
  463. #ifndef AUDIO_ENCODING_LINEAR
  464. #define AUDIO_ENCODING_LINEAR (3)
  465. #endif
  466. #ifndef AUDIO_ENCODING_ULAW
  467. #define AUDIO_ENCODING_ULAW (3)
  468. #endif
  469. #ifndef AUDIO_DEV_UNKNOWN
  470. #define AUDIO_DEV_UNKNOWN (0)
  471. #endif
  472. #ifndef AUDIO_DEV_AMD
  473. #define AUDIO_DEV_AMD (1)
  474. #endif
  475. #ifndef AUDIO_SPEAKER
  476. #define AUDIO_SPEAKER 0x01
  477. #endif
  478. #ifndef AUDIO_HEADPHONE
  479. #define AUDIO_HEADPHONE 0x02
  480. #endif
  481. #ifndef AUDIO_LINE_OUT
  482. #define AUDIO_LINE_OUT 0x04
  483. #endif
  484. #ifndef AUDIO_MIN_GAIN
  485. #define AUDIO_MIN_GAIN (0)
  486. #endif
  487. #ifndef AUDIO_MAX_GAIN
  488. #define AUDIO_MAX_GAIN (255)
  489. #endif
  490.  
  491.  
  492. void  Sparc_Audio_Init();
  493. void  Sparc_Audio_Kill();
  494. void  Sparc_Audio_Off();
  495. void  Sparc_Audio_On();
  496. void  Sparc_Adjust_Volume();
  497. xaULONG Sparc_Closest_Freq();
  498. void Sparc_Set_Output_Port();
  499. void Sparc_Speaker_Toggle();
  500. void Sparc_Headphone_Toggle();
  501.  
  502. #define SPARC_MAX_VOL AUDIO_MAX_GAIN
  503. #define SPARC_MIN_VOL AUDIO_MIN_GAIN
  504.  
  505. static int devAudio;
  506. static audio_info_t audio_info;
  507.  
  508.  
  509. /********** XA_Audio_Setup **********************
  510.  * 
  511.  * Also defines Sparc Specific variables.
  512.  *
  513.  *****/
  514. void XA_Audio_Setup()
  515. {
  516.  
  517.   XA_Audio_Init        = Sparc_Audio_Init;
  518.   XA_Audio_Kill        = Sparc_Audio_Kill;
  519.   XA_Audio_Off        = Sparc_Audio_Off;
  520.   XA_Audio_On        = Sparc_Audio_On;
  521.   XA_Closest_Freq    = Sparc_Closest_Freq;
  522.   XA_Set_Output_Port    = Sparc_Set_Output_Port;
  523.   XA_Speaker_Tog    = Sparc_Speaker_Toggle;
  524.   XA_Headphone_Tog    = Sparc_Headphone_Toggle;
  525.   XA_LineOut_Tog    = Sparc_Headphone_Toggle;
  526.   XA_Adjust_Volume    = Sparc_Adjust_Volume;
  527.  
  528.   xa_snd_cur = 0;
  529.   xa_audio_present = XA_AUDIO_UNK;
  530.   xa_audio_status  = XA_AUDIO_STOPPED;
  531.   xa_audio_ring_size  = 8;
  532. }
  533.  
  534.  
  535. /********** Sparc_Audio_Init **********************
  536.  * Open /dev/audio and /dev/audioctl for Sparc's.
  537.  *
  538.  *****/
  539. void Sparc_Audio_Init()
  540. { int ret;
  541. #ifdef SVR4    /* was SOLARIS */
  542.   audio_device_t type;
  543. #else
  544.   int type;
  545. #endif
  546.   DEBUG_LEVEL2 fprintf(stderr,"Sparc_Audio_Init\n");
  547.   if (xa_audio_present != XA_AUDIO_UNK) return;
  548.   devAudio = open("/dev/audio", O_WRONLY | O_NDELAY);
  549.   if (devAudio == -1)
  550.   {
  551.     if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - ");
  552.     else fprintf(stderr,"Audio_Init: Error %x opening audio device. - ",errno);
  553.     fprintf(stderr,"Will continue without audio\n");
  554.     xa_audio_present = XA_AUDIO_ERR;
  555.     return;
  556.   }
  557.   ret = ioctl(devAudio, AUDIO_GETDEV, &type);
  558.   /* POD NOTE: Sparc 5 has new audio device (CS4231) */
  559. #ifdef SVR4    /* was SOLARIS */
  560.   if ( (   (strcmp(type.name, "SUNW,dbri"))   /* Not DBRI (SS10's) */
  561.         && (strcmp(type.name, "SUNW,CS4231")) /* and not CS4231 (SS5's) */
  562.         && (strcmp(type.name, "SUNW,sb16")))  /* and SoundBlaster 16 */
  563.       || ret) /* or ioctrl failed */
  564. #else
  565.   if (ret || (type==AUDIO_DEV_UNKNOWN) || (type==AUDIO_DEV_AMD) )
  566. #endif
  567.   { /* SPARC AU AUDIO */
  568.     DEBUG_LEVEL1 fprintf(stderr,"SPARC AMD AUDIO\n");
  569.     xa_audio_hard_type  = XA_AUDIO_SUN_AU;
  570.     xa_audio_hard_freq  = 8000;
  571.     xa_audio_hard_buff  = XA_HARD_BUFF_1K;             /* default buffer size */
  572.     xa_audio_hard_bps   = 1;
  573.     xa_audio_hard_chans = 1;
  574.     Gen_Signed_2_Ulaw();
  575.   }
  576.   else /* DBRI or CS4231 or SB16 */
  577.   {
  578.     DEBUG_LEVEL1 fprintf(stderr,"SPARC DBRI or CS4231 or SB16 AUDIO\n");
  579. #ifdef SVR4
  580. #ifdef _LITTLE_ENDIAN
  581.     xa_audio_hard_type  = XA_AUDIO_SIGNED_2ML;
  582. #else
  583.     xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB; /* default to this */
  584. #endif
  585. #else
  586.     xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
  587. #endif
  588.     xa_audio_hard_freq  = 11025;
  589.     xa_audio_hard_buff  = XA_HARD_BUFF_1K;             /* default buffer size */
  590.     xa_audio_hard_bps   = 2;
  591.     xa_audio_hard_chans = 1;
  592.     AUDIO_INITINFO(&audio_info);
  593. #ifdef SVR4    /* was SOLARIS */
  594. /* POD-NOTE: Does this necessarily have to be 1024 (what the upper/lower
  595.  * limits???)
  596.  */
  597.     audio_info.play.buffer_size = XA_HARD_BUFF_1K;
  598.     xa_audio_hard_buff  = XA_HARD_BUFF_1K;   /* default buffer size */
  599. #endif
  600.  
  601.     /* POD NOTE: this is currently used for testing purposes */
  602.     switch(xa_kludge900_aud)
  603.     {
  604.       case 900:
  605. fprintf(stderr,"Sun Audio: uLAW\n");
  606.     xa_audio_hard_type  = XA_AUDIO_SUN_AU;
  607.     xa_audio_hard_freq  = 8000;
  608.     xa_audio_hard_bps   = 1;
  609.     audio_info.play.sample_rate = 8000;
  610.     audio_info.play.channels = 1;
  611.     xa_audio_hard_bps   = 1;
  612.     audio_info.play.encoding = AUDIO_ENCODING_ULAW;
  613.     Gen_Signed_2_Ulaw();
  614.     break;
  615.       case 901:
  616. fprintf(stderr,"Sun Audio: 8 bit PCM\n");
  617.     audio_info.play.sample_rate = 11025;
  618.     audio_info.play.precision = 8;
  619.     audio_info.play.channels = 1;
  620.     audio_info.play.encoding = AUDIO_ENCODING_LINEAR;
  621.     break;
  622.       case 0:
  623.       default:
  624.     audio_info.play.sample_rate = 11025;
  625.     audio_info.play.precision = 16;
  626.     audio_info.play.channels = 1;
  627.     audio_info.play.encoding = AUDIO_ENCODING_LINEAR;
  628.     break;
  629.     }
  630.  
  631.     ret = ioctl(devAudio, AUDIO_SETINFO, &audio_info);
  632.     if (ret)
  633.     {
  634.       fprintf(stderr,"AUDIO BRI FATAL ERROR %d\n",errno);
  635.       xa_audio_present = XA_AUDIO_ERR;
  636.       return;
  637.     }
  638.   }
  639.   xa_interval_id = 0;
  640.   xa_audio_present = XA_AUDIO_OK;
  641.   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
  642.   Init_Audio_Ring(xa_audio_ring_size,
  643.             (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
  644. }
  645.  
  646. /********** Sparc_Audio_Kill **********************
  647.  * Close /dev/audio and /dev/audioctl.
  648.  *
  649.  *****/
  650. void Sparc_Audio_Kill()
  651.   /* TURN AUDIO OFF */
  652.   Sparc_Audio_Off(0);
  653.   xa_audio_present = XA_AUDIO_UNK;
  654.   /* SHUT THINGS DOWN  */
  655.   close(devAudio);
  656.   Kill_Audio_Ring();
  657. }
  658.  
  659. /********** Sparc_Audio_Off **********************
  660.  * Stop Audio Stream
  661.  *
  662.  *****/
  663. void Sparc_Audio_Off(flag)
  664. xaULONG flag;
  665. { long ret;
  666.  
  667.   if (xa_audio_status != XA_AUDIO_STARTED) return;
  668.  
  669.   /* SET FLAG TO STOP OUTPUT ROUTINE */
  670.   xa_audio_status = XA_AUDIO_STOPPED;
  671.  
  672.   /* TURN OFF SOUND ??? */
  673.   Sparc_Adjust_Volume(XA_AUDIO_MINVOL);
  674.  
  675.   /* FLUSH AUDIO DEVICE */
  676.   ret = ioctl(devAudio, I_FLUSH, FLUSHW);
  677.   if (ret == -1) fprintf(stderr,"Sparc Audio: off flush err %d\n",errno);
  678.  
  679.   xa_time_audio = -1;
  680.   xa_audio_flushed = 0;
  681.  
  682.   /* FLUSH AUDIO DEVICE AGAIN */
  683.   ret = ioctl(devAudio, I_FLUSH, FLUSHW);
  684.   if (ret == -1) fprintf(stderr,"Sparc Audio: off flush err %d\n",errno);
  685.  
  686.   /* RESTORE ORIGINAL VOLUME */
  687.   if (XAAUD->mute != xaTRUE) Sparc_Adjust_Volume(XAAUD->volume);
  688. }
  689.  
  690. /********** Sparc_Audio_On **********************
  691.  * Turn On Audio Stream.
  692.  *
  693.  *****/
  694. void Sparc_Audio_On()
  695.   DEBUG_LEVEL2 
  696.   {
  697.     fprintf(stderr,"Sparc_Audio_On \n");
  698.   }
  699.   if (xa_audio_status == XA_AUDIO_STARTED) return;
  700.   else if (xa_audio_present != XA_AUDIO_OK) return;
  701.   else if (xa_snd_cur)
  702.   { int ret;
  703.  
  704.     /* CHANGE FREQUENCY IF NEEDED */
  705.     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
  706.     { audio_info_t a_info;
  707.       AUDIO_INITINFO(&a_info);
  708.       a_info.play.sample_rate = xa_snd_cur->hfreq;
  709.       ret = ioctl(devAudio, AUDIO_SETINFO, &a_info);
  710.       if (ret == -1) fprintf(stderr,"audio setfreq: freq %x errno %d\n",
  711.                         xa_snd_cur->hfreq, errno);
  712.       xa_audio_hard_freq = xa_snd_cur->hfreq;
  713.     }
  714.  
  715.     /* xa_snd_cur gets changes in Update_Ring() */
  716.     xa_out_time = 500;  /* keep audio fed 500ms ahead of video */
  717.     xa_out_init = xa_audio_ring_size - 1;
  718.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  719.  
  720. DEBUG_LEVEL1 fprintf(stderr,"ch_time %d out_time %d int time %d \n",xa_snd_cur->ch_time,xa_out_time,xa_interval_time);
  721.  
  722.     xa_audio_status = XA_AUDIO_STARTED;
  723.     XA_Flush_Ring();
  724.     XA_Update_Ring(1000);
  725.  
  726.     if (xa_interval_time == 0) xa_interval_time = 1;
  727.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  728.     New_Merged_Audio_Output();
  729.   }
  730. }
  731.  
  732.  
  733. /********** Sparc_Closest_Freq **********************************************
  734.  *
  735.  * Global Variable Affect:
  736.  *   xaULONG xa_audio_hard_buff        must set but not larger than
  737.  *                    XA_AUDIO_MAX_RING_BUF size
  738.  ****************************************************************************/
  739. xaULONG Sparc_Closest_Freq(ifreq)
  740. xaLONG ifreq;
  741. {
  742.  
  743. /* POD
  744. fprintf(stderr,"Sparc_Closest_Freq: hardtype %x freq %d\n",
  745.             xa_audio_hard_type,ifreq);
  746. */
  747.  
  748.   if (xa_audio_hard_type==XA_AUDIO_SIGNED_2MB)
  749.   { static int valid[] = { 8000, 9600, 11025, 16000, 18900, 22050, 32000,
  750.                   37800, 44100, 48000, 0};
  751.     xaLONG i = 0;
  752.     xaLONG best = 8000;
  753.  
  754.     xa_audio_hard_buff = XA_HARD_BUFF_1K;
  755.     while(valid[i])
  756.     { 
  757.       if (xaABS(valid[i] - ifreq) < xaABS(best - ifreq)) best = valid[i];
  758.       i++;
  759.     }
  760.     return(best);
  761.   }
  762.   else return(8000);
  763. }
  764.  
  765.  
  766. /* Eventually merge everything to one */
  767. void Sparc_Set_Output_Port(aud_ports)
  768. xaULONG aud_ports;
  769. { audio_info_t a_info;
  770.   xaLONG ret;
  771.   xaULONG sparc_ports = 0;
  772.   if (aud_ports & XA_AUDIO_PORT_INT)  sparc_ports |= AUDIO_SPEAKER;
  773.   if (aud_ports & XA_AUDIO_PORT_HEAD) sparc_ports |= AUDIO_HEADPHONE;
  774.   if (aud_ports & XA_AUDIO_PORT_EXT)  sparc_ports |= AUDIO_LINE_OUT;
  775.   AUDIO_INITINFO(&a_info);
  776.   a_info.play.port = sparc_ports;
  777.   ret = ioctl(devAudio, AUDIO_SETINFO, &a_info);
  778.   if (ret < 0) fprintf(stderr,"Audio: couldn't set speaker port %d\n",errno);
  779. }
  780.  
  781. /************* Sparc_Speaker_Toggle *****************************************
  782.  *
  783.  * flag = 0  turn speaker off
  784.  * flag = 1  turn speaker on
  785.  * flag = 2  toggle speaker
  786.  ****************************************************************************/
  787. void Sparc_Speaker_Toggle(flag)
  788. xaULONG flag;
  789.   switch(flag)
  790.   {
  791.     case  0: XAAUD->port &= ~XA_AUDIO_PORT_INT; break;
  792.     case  1: XAAUD->port |=  XA_AUDIO_PORT_INT; break;
  793.     default:  /* mutually exclusive set for now - never turn off */
  794.     { if ( !(XAAUD->port & XA_AUDIO_PORT_INT)) 
  795.         XAAUD->port = XA_AUDIO_PORT_INT;
  796.     }
  797.   }
  798.   Sparc_Set_Output_Port(XAAUD->port);
  799. }
  800.  
  801. /************* Sparc_Headphone_Toggle *****************************************
  802.  *
  803.  * flag = 0  turn headphones off
  804.  * flag = 1  turn headphones on
  805.  * flag = 2  toggle headphones
  806.  ****************************************************************************/
  807. void Sparc_Headphone_Toggle(flag)
  808. xaULONG flag;
  809.   switch(flag)
  810.   {
  811.     case  0: XAAUD->port &= ~XA_AUDIO_PORT_HEAD; break;
  812.     case  1: XAAUD->port |=  XA_AUDIO_PORT_HEAD; break;
  813.     default:  /* mutually exclusive set for now - never turn off */
  814.     { if ( !(XAAUD->port & XA_AUDIO_PORT_HEAD)) 
  815.         XAAUD->port = XA_AUDIO_PORT_HEAD;
  816.     }
  817.   }
  818.   Sparc_Set_Output_Port(XAAUD->port);
  819. }
  820.  
  821.  
  822. /********** Sparc_Adjust_Volume **********************
  823.  * Routine for Adjusting Volume on a Sparc
  824.  *
  825.  * Volume is in the range [0,XA_AUDIO_MAXVOL]
  826.  ****************************************************************************/
  827. void Sparc_Adjust_Volume(volume)
  828. xaULONG volume;
  829. { audio_info_t a_info;
  830.  
  831.   AUDIO_INITINFO(&a_info);
  832.   a_info.play.gain = SPARC_MIN_VOL +
  833.     ((volume * (SPARC_MAX_VOL - SPARC_MIN_VOL)) / XA_AUDIO_MAXVOL);
  834.   if (a_info.play.gain > SPARC_MAX_VOL) a_info.play.gain = SPARC_MAX_VOL;
  835.   ioctl(devAudio, AUDIO_SETINFO, &a_info);
  836. }
  837. #endif
  838. /****************************************************************************/
  839. /******************* END OF SPARC SPECIFIC ROUTINES *********************/
  840. /****************************************************************************/
  841.  
  842. /****************************************************************************/
  843. /**************** S/6000  SPECIFIC ROUTINES *********************************/
  844. /****************************************************************************/
  845. #ifdef XA_AIX_AUDIO
  846.  
  847. void  AIX_Audio_Init();
  848. void  AIX_Audio_Kill();
  849. void  AIX_Audio_Off();
  850. void  AIX_Audio_On();
  851.  
  852. xaULONG AIX_Closest_Freq();
  853. void  AIX_Speaker_Tog();
  854. void  AIX_Headphone_Tog();
  855. void  AIX_LineOut_Tog();
  856. void  AIX_Adjust_Volume();
  857.  
  858.  
  859. static int     devAudio;
  860. static xaULONG   aix_audio_ports;
  861. extern char  * xa_audio_device;
  862.  
  863. /*----------------------------------------------------------------------------*/
  864. /*                                                                            */
  865. /*----------------------------------------------------------------------------*/
  866. void XA_Audio_Setup ( )
  867. {
  868.   XA_Audio_Init =     AIX_Audio_Init;
  869.   XA_Audio_Kill =     AIX_Audio_Kill;
  870.   XA_Audio_Off =      AIX_Audio_Off;
  871.   XA_Audio_On =       AIX_Audio_On;
  872.   XA_Closest_Freq =   AIX_Closest_Freq;
  873.   XA_Speaker_Tog =    AIX_Speaker_Tog;
  874.   XA_Headphone_Tog =  AIX_Headphone_Tog;
  875.   XA_LineOut_Tog =    AIX_LineOut_Tog;
  876.   XA_Adjust_Volume    = AIX_Adjust_Volume;
  877.  
  878.   xa_snd_cur = 0;
  879.   xa_audio_present = XA_AUDIO_UNK;
  880.   xa_audio_status = XA_AUDIO_STOPPED;
  881.   xa_audio_ring_size = 8;
  882. }
  883.  
  884.  
  885. /*----------------------------------------------------------------------------*/
  886. /*                                                                            */
  887. /*----------------------------------------------------------------------------*/
  888. void AIX_Audio_Init ( )
  889. {
  890.   char         * devname;
  891.   audio_init     init;
  892.   audio_control  control;
  893.   audio_change   change;
  894.   int            rc;
  895.  
  896.   if ( xa_audio_present != XA_AUDIO_UNK )
  897.   {
  898.     return;
  899.   }
  900.  
  901.   devname = xa_audio_device;
  902.   if ( ( devAudio = open ( devname, O_WRONLY | O_NDELAY ) ) < 0 )
  903.   {
  904.     fprintf ( stderr, "AIX_Audio_Init: Open failed for '%s', errno = %d\n",
  905.               devname, errno );
  906.     xa_audio_present = XA_AUDIO_ERR;
  907.     return;
  908.   }
  909.  
  910.   /* Set the codec to some default values (the same ones the sun has   */
  911.   /* seem as good as any)                                              */
  912.  
  913.   xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
  914.   xa_audio_hard_freq  = 11025;
  915.   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
  916.   xa_audio_hard_bps   = 2;
  917.   xa_audio_hard_chans = 1;
  918.  
  919.   memset ( & init, '\0', sizeof ( init ) );
  920.  
  921.   init.srate =           11025;
  922.   init.mode =            PCM;
  923.   init.operation =       PLAY;
  924.   init.channels =        1;
  925.   init.flags =           BIG_ENDIAN | TWOS_COMPLEMENT;
  926.   init.bits_per_sample = 16;
  927.   init.bsize =           AUDIO_IGNORE;
  928.  
  929.   if ( ( rc = ioctl ( devAudio, AUDIO_INIT, & init ) ) < 0 )
  930.   {
  931.     fprintf ( stderr, "AIX_Audio_Init: AUDIO_INIT failed, errno = %d\n",
  932.               errno );
  933.   }
  934.  
  935.  
  936.   memset ( & control, '\0', sizeof ( control ) );
  937.   memset ( & change, '\0', sizeof ( change ) );
  938.  
  939.   aix_audio_ports = EXTERNAL_SPEAKER | INTERNAL_SPEAKER | OUTPUT_1;
  940.   aix_audio_ports = OUTPUT_1;
  941.  
  942.   change.balance       = 0x3fff0000;
  943.   change.balance_delay = 0;
  944.  
  945.   change.volume        = ( long ) ( 0x7fff << 16 );
  946.   change.volume_delay  = 0;
  947.  
  948.   change.input         = AUDIO_IGNORE;
  949.   change.output        = aix_audio_ports;
  950.   change.monitor       = AUDIO_IGNORE;
  951.   change.dev_info      = ( char * ) NULL;
  952.  
  953.   control.ioctl_request = AUDIO_CHANGE;
  954.   control.position =      0;
  955.   control.request_info =  ( char * ) & change;
  956.  
  957.   if ( ( rc = ioctl ( devAudio, AUDIO_CONTROL, & control ) ) < 0 )
  958.   {
  959.     fprintf ( stderr, "AIX_Audio_Init: AUDIO_CONTROL failed, errno = %d\n",
  960.               errno );
  961.   }
  962.  
  963.   xa_interval_id = 0;
  964.   xa_audio_present = XA_AUDIO_OK;
  965.   Init_Audio_Ring ( xa_audio_ring_size,
  966.                     ( XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps ) );
  967. }
  968.  
  969.  
  970. /*----------------------------------------------------------------------------*/
  971. /*                                                                            */
  972. /*----------------------------------------------------------------------------*/
  973. void AIX_Audio_Kill ( )
  974. {
  975.   AIX_Audio_Off ( 0 );
  976.   xa_audio_present = XA_AUDIO_UNK;
  977.   close ( devAudio );
  978.   Kill_Audio_Ring ( );
  979. }
  980.  
  981.  
  982. /*----------------------------------------------------------------------------*/
  983. /*                                                                            */
  984. /*----------------------------------------------------------------------------*/
  985. void AIX_Audio_Off ( )
  986. {
  987.   audio_control control;
  988.   int           rc;
  989.  
  990.   if ( xa_audio_status != XA_AUDIO_STARTED )
  991.   {
  992.     return;
  993.   }
  994.  
  995.   xa_audio_status = XA_AUDIO_STOPPED;
  996.  
  997.   memset ( & control, '\0', sizeof ( control ) );
  998.  
  999.   control.ioctl_request = AUDIO_STOP;
  1000.   control.request_info  = NULL;
  1001.   control.position      = 0;
  1002.  
  1003.   if ( ( rc = ioctl ( devAudio, AUDIO_CONTROL, & control ) ) < 0 )
  1004.   {
  1005.     fprintf ( stderr, "AIX_Audio_Off: AUDIO_STOP failed, errno = %d\n", errno );
  1006.   }
  1007.  
  1008. #ifdef SOME_DAY
  1009.   if ( ( rc = ioctl ( devAudio, AUDIO_WAIT, NULL ) ) != 0 )
  1010.   {
  1011.     fprintf ( stderr, "AIX_Audio_Off: AUDIO_WAIT failed, errno = %d\n", errno );
  1012.   }
  1013. #endif
  1014.  
  1015.   xa_time_audio = -1;
  1016.   xa_audio_flushed = 0;
  1017. }
  1018.  
  1019.  
  1020. /*----------------------------------------------------------------------------*/
  1021. /*                                                                            */
  1022. /*----------------------------------------------------------------------------*/
  1023. void AIX_Audio_On ( )
  1024. {
  1025.   audio_control control;
  1026.   int           rc;
  1027.  
  1028.   if ( xa_audio_status == XA_AUDIO_STARTED )
  1029.   {
  1030.     return;
  1031.   }
  1032.  
  1033.   if ( xa_audio_present != XA_AUDIO_OK )
  1034.   {
  1035.     return;
  1036.   }
  1037.  
  1038.   if ( xa_snd_cur )
  1039.   {
  1040.     /* Change the frequency if needed */
  1041.     if ( xa_audio_hard_freq != xa_snd_cur->hfreq )
  1042.     {
  1043.       audio_init init;
  1044.  
  1045.       printf ( "AIX_Audio_On: setting frequency to %d\n", xa_snd_cur->hfreq );
  1046.  
  1047.       memset ( & init, '\0', sizeof ( init ) );
  1048.  
  1049.       init.srate           = xa_snd_cur->hfreq;
  1050.       init.mode            = PCM;
  1051.       init.operation       = PLAY;
  1052.       init.channels        = 1;
  1053.       init.flags           = BIG_ENDIAN | TWOS_COMPLEMENT;
  1054.       init.bits_per_sample = 16;
  1055.       init.bsize           = AUDIO_IGNORE;
  1056.  
  1057.       if ( ( rc = ioctl ( devAudio, AUDIO_INIT, & init ) ) < 0 )
  1058.       {
  1059.         fprintf ( stderr,
  1060.                   "AIX_Audio_On: AUDIO_INIT failed, rate = %d, errno = %d\n",
  1061.                   init.srate, errno );
  1062.       }
  1063.  
  1064.       xa_audio_hard_freq = xa_snd_cur->hfreq;
  1065.     }
  1066.  
  1067.     /* OLD xa_out_time = xa_snd_cur->ch_time * 4; */
  1068.     xa_out_time = 250;  /* keep audio fed 250ms ahead of video - may be 500*/
  1069.     xa_out_init = xa_audio_ring_size - 1;
  1070.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  1071.  
  1072.     xa_audio_status = XA_AUDIO_STARTED;
  1073.     XA_Flush_Ring();
  1074.     XA_Update_Ring(1000);
  1075.     if ( xa_interval_time == 0 )
  1076.     {
  1077.       xa_interval_time = 1;
  1078.     }
  1079.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  1080.  
  1081.     /* POD: The following 8 lines need to be before Merged_Audio_Output now */
  1082.     memset ( & control, '\0', sizeof ( control ) );
  1083.     control.ioctl_request = AUDIO_START;
  1084.     control.request_info  = NULL;
  1085.     control.position      = 0;
  1086.     if ( ( rc = ioctl ( devAudio, AUDIO_CONTROL, & control ) ) < 0 )
  1087.     {
  1088.       fprintf(stderr,"AIX_Audio_On: AUDIO_START failed, errno = %d\n", errno );
  1089.     }
  1090.     New_Merged_Audio_Output();
  1091.   }
  1092.  
  1093. }
  1094.  
  1095.  
  1096. /*----------------------------------------------------------------------------*/
  1097. /*                                                                            */
  1098. /*----------------------------------------------------------------------------*/
  1099. xaULONG AIX_Closest_Freq ( ifreq )
  1100. xaLONG ifreq;
  1101. {
  1102.   static valid [ ] = {  8000,  9600, 11025, 16000, 18900,
  1103.                        22050, 32000, 37800, 44100, 48000, 0 };
  1104.   int  i = 0;
  1105.   xaLONG best = 8000;
  1106.  
  1107.   xa_audio_hard_buff = XA_HARD_BUFF_1K;
  1108.   while ( valid [ i ] )
  1109.   {
  1110.     if ( xaABS(valid[i] - ifreq) < xaABS(best - ifreq) )
  1111.     {
  1112.       best = valid [ i ];
  1113.     }
  1114.     i = i + 1;
  1115.   }
  1116.   return ( best );
  1117. }
  1118.  
  1119.  
  1120. /*----------------------------------------------------------------------------*/
  1121. /*                                                                            */
  1122. /*----------------------------------------------------------------------------*/
  1123. int AIX_Output_Change ( settings )
  1124. xaULONG settings;
  1125. {
  1126.   audio_control control;
  1127.   audio_change  change;
  1128.   int           rc;
  1129.  
  1130.   memset ( & control, '\0', sizeof ( control ) );
  1131.   memset ( & change, '\0', sizeof ( change ) );
  1132.  
  1133.   change.balance       = 0x3fff0000;
  1134.   change.balance_delay = 0;
  1135.  
  1136.   change.volume        = AUDIO_IGNORE;
  1137.   change.volume_delay  = AUDIO_IGNORE;
  1138.  
  1139.   change.input         = AUDIO_IGNORE;
  1140.   change.output        = settings;
  1141.   change.monitor       = AUDIO_IGNORE;
  1142.   change.dev_info      = ( char * ) NULL;
  1143.  
  1144.   control.ioctl_request = AUDIO_CHANGE;
  1145.   control.position      = 0;
  1146.   control.request_info  = ( char * ) & change;
  1147.  
  1148.   if ( ( rc = ioctl ( devAudio, AUDIO_CONTROL, & control ) ) < 0 )
  1149.   {
  1150.     fprintf ( stderr, "AIX_Output_Change: AUDIO_CONTROL failed, errno = %d\n",
  1151.               errno );
  1152.   }
  1153.   return ( rc );
  1154. }
  1155.  
  1156.  
  1157. /*----------------------------------------------------------------------------*/
  1158. /*                                                                            */
  1159. /*----------------------------------------------------------------------------*/
  1160. void AIX_Speaker_Tog ( flag )
  1161. xaULONG flag;
  1162. {
  1163.   int  rc;
  1164.  
  1165.   switch ( flag )
  1166.   {
  1167.     case 0:
  1168.          aix_audio_ports &= ~INTERNAL_SPEAKER;
  1169.          break;
  1170.  
  1171.     case 1:
  1172.          aix_audio_ports |= INTERNAL_SPEAKER;
  1173.          break;
  1174.  
  1175.     default:
  1176.          aix_audio_ports ^= INTERNAL_SPEAKER;
  1177.          break;
  1178.   }
  1179.  
  1180.   if ( ( rc = AIX_Output_Change ( aix_audio_ports ) ) < 0 )
  1181.   {
  1182.     fprintf ( stderr, 
  1183.     "AIX_Speaker_Tog: AUDIO_CONTROL failed, errno = %d\n", errno );
  1184.   }
  1185. }
  1186.  
  1187.  
  1188. /*----------------------------------------------------------------------------*/
  1189. /*                                                                            */
  1190. /*----------------------------------------------------------------------------*/
  1191. void AIX_Headphone_Tog ( flag )
  1192. xaULONG flag;
  1193. {
  1194.   int  rc;
  1195.  
  1196.   switch ( flag )
  1197.   {
  1198.     case 0:
  1199.          aix_audio_ports &= ~EXTERNAL_SPEAKER;
  1200.          break;
  1201.  
  1202.     case 1:
  1203.          aix_audio_ports |= EXTERNAL_SPEAKER;
  1204.          break;
  1205.  
  1206.     default:
  1207.          aix_audio_ports ^= EXTERNAL_SPEAKER;
  1208.          break;
  1209.   }
  1210.  
  1211.   if ( ( rc = AIX_Output_Change ( aix_audio_ports ) ) < 0 )
  1212.   {
  1213.     fprintf(stderr,
  1214.       "AIX_Headphone_Tog: AUDIO_CONTROL failed, errno = %d\n",errno);
  1215.   }
  1216. }
  1217.  
  1218.  
  1219. /*----------------------------------------------------------------------------*/
  1220. /*                                                                            */
  1221. /*----------------------------------------------------------------------------*/
  1222. void AIX_LineOut_Tog ( flag )
  1223. xaULONG flag;
  1224. {
  1225.   int  rc;
  1226.  
  1227.   switch ( flag )
  1228.   {
  1229.     case 0:
  1230.          aix_audio_ports &= ~OUTPUT_1;
  1231.          break;
  1232.  
  1233.     case 1:
  1234.          aix_audio_ports |= OUTPUT_1;
  1235.          break;
  1236.  
  1237.     default:
  1238.          aix_audio_ports ^= OUTPUT_1;
  1239.          break;
  1240.   }
  1241.  
  1242.   if ( ( rc = AIX_Output_Change ( aix_audio_ports ) ) < 0 )
  1243.   {
  1244.     fprintf ( stderr, "AIX_LineOut_Tog: AUDIO_CONTROL failed, errno = %d\n",
  1245.               errno );
  1246.   }
  1247. }
  1248.  
  1249. /*----------------------------------------------------------------------------*/
  1250. /*                                                                            */
  1251. /*----------------------------------------------------------------------------*/
  1252. void AIX_Adjust_Volume ( volume )
  1253. xaULONG volume;
  1254. {
  1255.   audio_control control;
  1256.   audio_change  change;
  1257.   float         percent;
  1258.   long          new_val;
  1259.   int           rc;
  1260.   float         base_vol = 0x7fff;
  1261.  
  1262.   memset ( & control, '\0', sizeof ( control ) );
  1263.   memset ( & change, '\0', sizeof ( change ) );
  1264.  
  1265.   if ( volume > XA_AUDIO_MAXVOL )
  1266.   {
  1267.     volume = XA_AUDIO_MAXVOL;
  1268.   }
  1269.  
  1270.   if ( volume < XA_AUDIO_MINVOL )
  1271.   {
  1272.     volume = XA_AUDIO_MINVOL;
  1273.   }
  1274.  
  1275.   percent = ( double ) volume / XA_AUDIO_MAXVOL;
  1276.   new_val = base_vol * percent;
  1277.   new_val = new_val << 16;
  1278.  
  1279.   change.balance       = AUDIO_IGNORE;
  1280.   change.balance_delay = AUDIO_IGNORE;
  1281.  
  1282.   change.volume        = new_val;
  1283.   change.volume_delay  = 0;
  1284.  
  1285.   change.input         = AUDIO_IGNORE;
  1286.   change.output        = AUDIO_IGNORE;
  1287.   change.monitor       = AUDIO_IGNORE;
  1288.   change.dev_info      = ( char * ) NULL;
  1289.  
  1290.   control.ioctl_request = AUDIO_CHANGE;
  1291.   control.position =      0;
  1292.   control.request_info =  ( char * ) & change;
  1293.  
  1294.   if ( ( rc = ioctl ( devAudio, AUDIO_CONTROL, & control ) ) < 0 )
  1295.   {
  1296.     fprintf ( stderr, "AIX_Audio_Init: AUDIO_CONTROL failed, errno = %d\n",
  1297.               errno );
  1298.   }
  1299.  
  1300. }
  1301. #endif
  1302.  
  1303. /****************************************************************************/
  1304. /**************** S/6000  SPECIFIC ROUTINES *********************************/
  1305. /****************************************************************************/
  1306.  
  1307.  
  1308.  
  1309. /****************************************************************************/
  1310. /**************** NEC EWS SPECIFIC ROUTINES *********************************/
  1311. /****************************************************************************/
  1312. #ifdef XA_EWS_AUDIO
  1313.  
  1314. /*
  1315.  * EWS port provided by Bob Phillips,
  1316.  *    bobp@syl.nj.nec.com
  1317.  * Heavily stolen from the Sparc port
  1318.  * Friday October 26, 1994
  1319.  */
  1320.  
  1321. xaULONG ews_audio_ports = AUOUT_SP;
  1322.  
  1323. void  EWS_Audio_Init();
  1324. void  EWS_Audio_Kill();
  1325. void  EWS_Audio_Off();
  1326. void  EWS_Audio_On();
  1327. void  EWS_Adjust_Volume();
  1328. xaULONG EWS_Closest_Freq();
  1329. void EWS_Speaker_Toggle();
  1330. void EWS_Headphone_Toggle();
  1331.  
  1332. /* EWS audio output volume is controlled with attenuation, not gain.
  1333.  * The upshot is that the control values run from 62 to 0, with low
  1334.  * numbers representing louder volumes.
  1335.  */
  1336.  
  1337. static int devAudio;
  1338. static struct AU_Volume audio_vol;
  1339. static struct AU_Type audio_type;
  1340. static struct AU_Line audio_line;
  1341. static struct AU_Status audio_status;
  1342.  
  1343.  
  1344. /********** XA_Audio_Setup **********************
  1345.  * 
  1346.  * Also defines NEC Specific variables.
  1347.  *
  1348.  *****/
  1349. void XA_Audio_Setup()
  1350. {
  1351.   XA_Audio_Init        = EWS_Audio_Init;
  1352.   XA_Audio_Kill        = EWS_Audio_Kill;
  1353.   XA_Audio_Off        = EWS_Audio_Off;
  1354.   XA_Audio_On        = EWS_Audio_On;
  1355.   XA_Closest_Freq    = EWS_Closest_Freq;
  1356.   XA_Set_Output_Port    = (void *)(0);
  1357.   XA_Speaker_Tog    = EWS_Speaker_Toggle;
  1358.   XA_Headphone_Tog    = EWS_Headphone_Toggle;
  1359.   XA_LineOut_Tog    = EWS_Headphone_Toggle;
  1360.   XA_Adjust_Volume    = EWS_Adjust_Volume;
  1361.  
  1362.  
  1363.   xa_snd_cur = 0;
  1364.   xa_audio_present = XA_AUDIO_UNK;
  1365.   xa_audio_status  = XA_AUDIO_STOPPED;
  1366.   xa_audio_ring_size  = 8;
  1367. }
  1368.  
  1369.  
  1370. /********** EWS_Audio_Init **********************
  1371.  * Open /dev/audio/audio on EWS.
  1372.  *
  1373.  *****/
  1374. void EWS_Audio_Init()
  1375. { int ret;
  1376.   int type;
  1377.  
  1378.  
  1379.   DEBUG_LEVEL2 fprintf(stderr,"EWS_Audio_Init\n");
  1380. /* The NEC EWS audio driver is very similar to the Sparc, but it does
  1381.  * not use an audio control device.  All ioctls are made directly to
  1382.  * the audio device.  Also, it does not support a wide variety of
  1383.  * ioctls.  In fact, it only supports 
  1384.  * AUIOC_[SG]ETTYPE, AUIOC_[SG]ETLINE, AUIOC_[SG]ETVOLUME, and AUIOC_STATUS.
  1385.  * It doesn't support FLUSH, or any of the other funky Sparc ioctls
  1386.  */
  1387.   if (xa_audio_present != XA_AUDIO_UNK) return;
  1388.   devAudio = open("/dev/audio/audio", O_WRONLY | O_NDELAY);
  1389.   if (devAudio == -1)
  1390.   {
  1391.     if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - ");
  1392.     else fprintf(stderr,"Audio_Init: Error opening audio device. - ");
  1393.     fprintf(stderr,"Will continue without audio\n");
  1394.     xa_audio_present = XA_AUDIO_ERR;
  1395.     return;
  1396.   }
  1397.   DEBUG_LEVEL1 fprintf(stderr,"NEC EWS AUDIO\n");
  1398.     xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
  1399.     xa_audio_hard_freq  = AURATE11_0;
  1400.     xa_audio_hard_bps   = 2;
  1401.     xa_audio_hard_chans = 1;
  1402.     xa_audio_hard_buff  = XA_HARD_BUFF_1K;             /* default buffer size */
  1403.  
  1404.     audio_type.rate=AURATE11_0;
  1405.     audio_type.bit_type=AU_PCM16;
  1406.     audio_type.channel=AU_MONO;
  1407.     ret = ioctl(devAudio, AUIOC_SETTYPE, &audio_type);
  1408.     if (ret)
  1409.     {
  1410.       fprintf(stderr,"EWS: AUIOC_SETTYPE error %d\n",errno);
  1411.       xa_audio_present = XA_AUDIO_ERR;
  1412.       return;
  1413.     }
  1414.  
  1415.   xa_interval_id = 0;
  1416.   xa_audio_present = XA_AUDIO_OK;
  1417.   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
  1418.   Init_Audio_Ring(xa_audio_ring_size,
  1419.             (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
  1420. }
  1421.  
  1422. /********** EWS_Audio_Kill **********************
  1423.  * Close /dev/audio/audio
  1424.  *
  1425.  *****/
  1426. void EWS_Audio_Kill()
  1427.   /* TURN AUDIO OFF */
  1428.   EWS_Audio_Off(0);
  1429.   xa_audio_present = XA_AUDIO_UNK;
  1430.   /* SHUT THINGS DOWN  */
  1431.   close(devAudio);
  1432.   Kill_Audio_Ring();
  1433. }
  1434.  
  1435. /********** EWS_Audio_Off **********************
  1436.  * Stop Audio Stream
  1437.  *
  1438.  *****/
  1439. void EWS_Audio_Off(flag)
  1440. xaULONG flag;
  1441. { long ret;
  1442.  
  1443.   DEBUG_LEVEL1 fprintf(stderr,"EWS_Audio_Off\n");
  1444.   if (xa_audio_status != XA_AUDIO_STARTED) return;
  1445.  
  1446.   /* SET FLAG TO TELL FREE RUNNING OUTPUT ROUTINE */
  1447.   xa_audio_status = XA_AUDIO_STOPPED;
  1448.  
  1449.   /* The Sparc port flushes here.  We cannot. So, just nuke volume.
  1450.    */
  1451.   /* TURN OFF SOUND ??? */
  1452.   EWS_Adjust_Volume(XA_AUDIO_MINVOL);
  1453.  
  1454.  
  1455.   xa_time_audio = -1;
  1456.   xa_audio_flushed = 0;
  1457.  
  1458. }
  1459.  
  1460. /********** EWS_Audio_On **********************
  1461.  * Turn On Audio Stream.
  1462.  *
  1463.  *****/
  1464. void EWS_Audio_On()
  1465.   DEBUG_LEVEL2 
  1466.     fprintf(stderr,"EWS_Audio_On \n");
  1467.   if (xa_audio_status == XA_AUDIO_STARTED) return;
  1468.   else if (xa_audio_present != XA_AUDIO_OK) return;
  1469.   else if (xa_snd_cur)
  1470.   { int ret;
  1471.  
  1472.     /* CHANGE FREQUENCY IF NEEDED */
  1473.     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
  1474.     { 
  1475.       
  1476.       ret = ioctl(devAudio, AUIOC_GETTYPE, &audio_type);
  1477.       if (ret == -1) fprintf(stderr,"AUIOC_GETTYPE: errno %d\n",errno);
  1478.       audio_type.rate=EWS_Closest_Freq(xa_snd_cur->hfreq);
  1479.       ret = ioctl(devAudio, AUIOC_SETTYPE, &audio_type);
  1480.       if (ret == -1) fprintf(stderr,"AUIOC_SETTYPE: freq %x errno %d\n",
  1481.                         xa_snd_cur->hfreq, errno);
  1482.       xa_audio_hard_freq = xa_snd_cur->hfreq;
  1483.     }
  1484.     if (XAAUD->mute != xaTRUE) EWS_Adjust_Volume(XAAUD->volume);
  1485.  
  1486.     /* xa_snd_cur gets changes in Update_Ring() */
  1487.     xa_out_time = 250; /* keep audio fed 250ms ahead of video */
  1488.     xa_out_init = xa_audio_ring_size - 1;
  1489.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  1490.  
  1491.     xa_audio_status = XA_AUDIO_STARTED;
  1492.     XA_Flush_Ring();
  1493.     XA_Update_Ring(1000);
  1494.  
  1495.     if (xa_interval_time == 0) xa_interval_time = 1;
  1496.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  1497.     New_Merged_Audio_Output();
  1498.   }
  1499. }
  1500.  
  1501.  
  1502. /********** EWS_Closest_Freq **********************************************
  1503.  *
  1504.  * Global Variable Affect:
  1505.  *   xaULONG xa_audio_hard_buff        must set but not larger than
  1506.  *                    XA_AUDIO_MAX_RING_BUF size
  1507.  ****************************************************************************/
  1508. xaULONG EWS_Closest_Freq(ifreq)
  1509. xaLONG ifreq;
  1510. {
  1511.   static int valid[] = { AURATE5_5, AURATE6_6, AURATE8_0,
  1512.     AURATE9_6, AURATE11_0, AURATE16_0, AURATE18_9, AURATE22_1,
  1513.     AURATE27_4, AURATE32_0, AURATE33_1, AURATE37_8, AURATE44_1,
  1514.     AURATE48_0,0};
  1515.   xaLONG i = 0;
  1516.   xaLONG best = 8000;
  1517.  
  1518.   xa_audio_hard_buff = XA_HARD_BUFF_1K;
  1519.   while(valid[i])
  1520.   { 
  1521.     if (xaABS(valid[i] - ifreq) < xaABS(best - ifreq)) best = valid[i];
  1522.     i++;
  1523.   }
  1524.   if (valid[i])
  1525.   {
  1526.     if (best >= 25000) xa_audio_hard_buff = XA_HARD_BUFF_2K;
  1527.     return(best);
  1528.   }
  1529.   else return(AURATE8_0);
  1530. }
  1531.  
  1532. /************* EWS_Speaker_Toggle *****************************************
  1533.  *
  1534.  * flag = 0  turn speaker off
  1535.  * flag = 1  turn speaker on
  1536.  * flag = 2  toggle speaker
  1537.  ****************************************************************************/
  1538. void EWS_Speaker_Toggle(flag)
  1539. xaULONG flag;
  1540.   xaULONG old_ports = ews_audio_ports;
  1541.   xaLONG ret;
  1542.  
  1543.   switch(flag)
  1544.   {
  1545.     case  0: ews_audio_ports &= ~AUOUT_SP; break;
  1546.     case  1: ews_audio_ports |=  AUOUT_SP; break;
  1547.     default: ews_audio_ports ^=  AUOUT_SP; break;
  1548.   }
  1549.   audio_line.outline = ews_audio_ports;
  1550.   ret = ioctl(devAudio, AUIOC_SETLINE, &audio_line);
  1551.   if (ret == -1)
  1552.   {
  1553.     fprintf(stderr,"Audio: couldn't toggle speaker %d\n",errno);
  1554.     ews_audio_ports = old_ports;
  1555.   }
  1556. }
  1557.  
  1558. /************* EWS_Headphone_Toggle *****************************************
  1559.  *
  1560.  * flag = 0  turn headphones off
  1561.  * flag = 1  turn headphones on
  1562.  * flag = 2  toggle headphones
  1563.  ****************************************************************************/
  1564. void EWS_Headphone_Toggle(flag)
  1565. xaULONG flag;
  1566.   xaULONG old_ports = ews_audio_ports;
  1567.   xaLONG ret;
  1568.   switch(flag)
  1569.   {
  1570.     case  0: ews_audio_ports &= ~AUOUT_PHONE; break;
  1571.     case  1: ews_audio_ports |=  AUOUT_PHONE; break;
  1572.     default: ews_audio_ports ^=  AUOUT_PHONE; break;
  1573.   }
  1574.   audio_line.outline = ews_audio_ports;
  1575.   ret = ioctl(devAudio, AUIOC_SETLINE, &audio_line);
  1576.   if (ret == -1)
  1577.   {
  1578.     fprintf(stderr,"Audio: couldn't toggle headphone %d\n",errno);
  1579.     ews_audio_ports = old_ports;
  1580.   }
  1581. }
  1582.  
  1583.  
  1584. /********** EWS_Adjust_Volume **********************
  1585.  * Routine for Adjusting Volume on EWS
  1586.  *
  1587.  * Volume is in the range [0,XA_AUDIO_MAXVOL]
  1588.  * EWS Output is a measure of attenuation, so it ranges from [62,0]
  1589.  ****************************************************************************/
  1590. void EWS_Adjust_Volume(volume)
  1591. xaULONG volume;
  1592.   int vol;
  1593.   int ret;
  1594.   
  1595.   ret = ioctl(devAudio, AUIOC_GETVOLUME, &audio_vol);
  1596.   if (ret == -1)
  1597.   {
  1598.     fprintf(stderr,"Audio: couldn't get volume%d\n",errno);
  1599.     return;
  1600.   }
  1601.  
  1602.   vol= AUOUT_ATTEMAX-((volume*AUOUT_ATTEMAX)/XA_AUDIO_MAXVOL);
  1603.   audio_vol.out.left = audio_vol.out.right = vol;
  1604.   ret = ioctl(devAudio, AUIOC_SETVOLUME, &audio_vol);
  1605.   if (ret == -1)
  1606.   {
  1607.     fprintf(stderr,"Audio: couldn't set volume%d\n",errno);
  1608.   }
  1609.  
  1610. }
  1611.  
  1612. #endif
  1613. /****************************************************************************/
  1614. /******************* END OF NEC EWS SPECIFIC ROUTINES ***********************/
  1615. /****************************************************************************/
  1616.  
  1617. /****************************************************************************/
  1618. /**************** SONY SPECIFIC ROUTINES ***********************************/
  1619. /****************************************************************************/
  1620. #ifdef    XA_SONY_AUDIO
  1621. /*
  1622.  * SONY NEWS port provided by Kazushi Yoshida,
  1623.  *    30eem043@keyaki.cc.u-tokai.ac.jp
  1624.  * Heavily stolen from the Sparc port
  1625.  * Thu Jan 26, 1995
  1626.  *
  1627.  * SVR4/NEWS-OS 6.x port by Takashi Hagiwara, Sony Corporation
  1628.  * Add SB device check routine and some fixes
  1629.  *      hagiwara@sm.sony.co.jp
  1630.  */
  1631. void Sony_Audio_Init();
  1632. void Sony_Audio_Kill();
  1633. void Sony_Audio_Off();
  1634. void Sony_Audio_On();
  1635. void Sony_Adjust_Volume();
  1636. xaULONG Sony_Closest_Freq();
  1637. void Sony_Speaker_Toggle();
  1638. void Sony_Headphone_Toggle();
  1639.  
  1640. /*
  1641.  */
  1642. static int sony_audio_rate1[] =  /* NWS-5000,4000 */
  1643.     { RATE8000, RATE9450, RATE11025, RATE12000, RATE16000,
  1644.       RATE18900, RATE22050, RATE24000, RATE32000, RATE37800,
  1645.       RATE44056, RATE44100, RATE48000, 0 } ;
  1646.  
  1647. static int sony_audio_rate2[] =  /* NWS-3200, 3400, 3700, 3800 */
  1648.     { RATE8000, RATE9450, RATE18900, RATE37800, 0 } ;
  1649.  
  1650. static int sony_audio_rate3[] =  /* NWS-3100 */
  1651.     { RATE8000, 0 } ;
  1652.  
  1653. int sony_audio_buf_len ;
  1654. static int devAudio;
  1655. static struct sbparam    audio_info ;
  1656. static int *sony_audio_rate;
  1657. static int sony_max_vol, sony_min_vol;
  1658.  
  1659.  
  1660. /********** XA_Audio_Setup **********************
  1661. *
  1662. * Also defines Sony Specific variables.
  1663. *
  1664. *****/
  1665. void XA_Audio_Setup()
  1666. {
  1667.     XA_Audio_Init        = Sony_Audio_Init;
  1668.     XA_Audio_Kill        = Sony_Audio_Kill;
  1669.     XA_Audio_Off        = Sony_Audio_Off;
  1670.     XA_Audio_On        = Sony_Audio_On;
  1671.     XA_Closest_Freq        = Sony_Closest_Freq;
  1672.     XA_Set_Output_Port    = (void *)(0);
  1673.     XA_Speaker_Tog        = Sony_Speaker_Toggle;
  1674.     XA_Headphone_Tog    = Sony_Headphone_Toggle;
  1675.     XA_LineOut_Tog        = Sony_Headphone_Toggle;
  1676.     XA_Adjust_Volume    = Sony_Adjust_Volume;
  1677.  
  1678.  
  1679.     xa_snd_cur = 0;
  1680.     xa_audio_present = XA_AUDIO_UNK;
  1681.     xa_audio_status  = XA_AUDIO_STOPPED;
  1682.     xa_audio_ring_size  = 8;
  1683. }
  1684.  
  1685. /********** Sony_Audio_Init **********************
  1686. * Open /dev/sb.
  1687. *
  1688. *****/
  1689. void Sony_Audio_Init()
  1690. {
  1691.     int    ret;
  1692.     int    type;
  1693.     int     sbtype;
  1694.  
  1695.     DEBUG_LEVEL2 fprintf(stderr,"Sony_Audio_Init\n");
  1696.  
  1697.     if (xa_audio_present != XA_AUDIO_UNK) 
  1698.         return;
  1699.     devAudio = open("/dev/sb0", O_WRONLY | O_NDELAY);
  1700.     if (devAudio == -1) {
  1701.       if (errno == EBUSY) 
  1702.         fprintf(stderr,"Audio_Init: Audio device is busy. - ");
  1703.       else 
  1704.         fprintf(stderr,"Audio_Init: Error opening audio device. - ");
  1705.       fprintf(stderr,"Will continue without audio\n");
  1706.       xa_audio_present = XA_AUDIO_ERR;
  1707.       return;
  1708.     }
  1709.  
  1710.     /* Under NEWS-OS 6.x SBIOCGETTYPE is supported by all machines. */
  1711.     /* However, NEWS-OS 4.x SBIOCGETYPE is supported by only NEWS 5000 */
  1712.     /* We should guess if SBUICGETTYPE would generate error,  */
  1713.     /* that machine  would be NEWS-3xxxx */ 
  1714.  
  1715.     if (ioctl(devAudio, SBIOCGETTYPE, (char *)&sbtype) < 0) {
  1716. #ifdef SVR4
  1717.         fprintf(stderr,"CANNOT GET SBTYPE ERROR %d\n",errno);
  1718. #endif 
  1719.         sbtype = SBTYPE_AIF2;    /* I guess so */    
  1720.     }
  1721.     switch(sbtype) {
  1722.         case SBTYPE_AIF2:
  1723.         case SBTYPE_AIF2_L:
  1724.         case SBTYPE_AIF2_E:
  1725.             sony_max_vol = 0;
  1726.             sony_min_vol = -32;
  1727.             sony_audio_rate = &sony_audio_rate2[0];
  1728.             break;
  1729.         case SBTYPE_AIF3:
  1730.             sony_max_vol = 8;
  1731.             sony_min_vol = -8;
  1732.             sony_audio_rate = &sony_audio_rate3[0];
  1733.             break;
  1734.         case SBTYPE_AIF5:
  1735.         case SBTYPE_AD1848:
  1736.         default:
  1737.             sony_max_vol = 16;
  1738.             sony_min_vol = -16;
  1739.             sony_audio_rate = &sony_audio_rate1[0];
  1740.             break;
  1741.     }
  1742.  
  1743.     DEBUG_LEVEL1 fprintf(stderr,"SONY AMD AUDIO\n");
  1744.  
  1745.     xa_audio_hard_type  = XA_AUDIO_SUN_AU;
  1746.     xa_audio_hard_freq  = 8000;
  1747.     xa_audio_hard_buff  = 1024;         /* default buffer size */
  1748.     xa_audio_hard_bps   = 1;
  1749.     xa_audio_hard_chans = 1;
  1750.     Gen_Signed_2_Ulaw() ;
  1751.  
  1752.     audio_info.sb_mode    = LOGPCM ;
  1753.     audio_info.sb_format  = 0 ;        /* was BSZ128 */
  1754.     audio_info.sb_compress= MULAW ;
  1755.     audio_info.sb_rate    = RATE8000 ;
  1756.     audio_info.sb_channel = MONO ;
  1757.     audio_info.sb_bitwidth= RES8B ;
  1758.     audio_info.sb_emphasis= 0 ;        /* was EMPH_OFF */
  1759.  
  1760.     ret = ioctl(devAudio, SBIOCSETPARAM, &audio_info);
  1761.     if (ret) {
  1762.         fprintf(stderr,"AUDIO BRI FATAL ERROR %d\n",errno);
  1763.         TheEnd1("SONY AUDIO BRI FATAL ERROR\n");
  1764.     }
  1765.     ret = ioctl(devAudio, SBIOCGETPARAM, &audio_info);
  1766.     if (ret == -1)
  1767.          fprintf(stderr,"Can't get audio_info %d\n",errno);
  1768.     xa_interval_id = 0;
  1769.     xa_audio_present = XA_AUDIO_OK;
  1770.  
  1771.     DEBUG_LEVEL2 fprintf(stderr,"success \n");
  1772.  
  1773.     Init_Audio_Ring(xa_audio_ring_size,
  1774.         (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
  1775.  
  1776.     sony_audio_buf_len = 32 * 1024 ; /* 4 sec... */
  1777. }
  1778.  
  1779.  
  1780. /********** Sony_Audio_Kill **********************
  1781. * Close /dev/sb0.
  1782. *
  1783. *****/
  1784. void Sony_Audio_Kill()
  1785. {
  1786.   DEBUG_LEVEL1 fprintf(stderr,"Sony_Audio_Kill\n");
  1787.   /* TURN AUDIO OFF */
  1788.   Sony_Audio_Off(0);
  1789.   xa_audio_present = XA_AUDIO_UNK;
  1790.   /* SHUT THINGS DOWN  */
  1791.   close(devAudio);
  1792.   Kill_Audio_Ring();
  1793. }
  1794.  
  1795. /********** Sony_Audio_Off **********************
  1796. * Stop Audio Stream
  1797. *
  1798. *****/
  1799. void Sony_Audio_Off(flag)
  1800. xaULONG flag;
  1801. { long ret;
  1802.  
  1803.   DEBUG_LEVEL1 fprintf(stderr,"Sony_Audio_Off\n");
  1804.   if (xa_audio_status != XA_AUDIO_STARTED) return;
  1805.  
  1806.   /* SET FLAG TO TELL FREE RUNNING OUTPUT ROUTINE */
  1807.   xa_audio_status = XA_AUDIO_STOPPED;
  1808.  
  1809.   /* TURN OFF SOUND ??? */ 
  1810.   Sony_Adjust_Volume(XA_AUDIO_MINVOL);
  1811.  
  1812.   /* FLUSH AUDIO DEVICE */
  1813.   ret = ioctl(devAudio, SBIOCFLUSH, 0);
  1814.   if (ret == -1) fprintf(stderr,"Sony Audio: off flush err %d\n",errno);
  1815.  
  1816.   xa_time_audio = -1;
  1817.   xa_audio_flushed = 0;
  1818.  
  1819.   /* OK... Wait for Sound device */
  1820.   ret = ioctl(devAudio, SBIOCWAIT, 0);
  1821.  
  1822.   /* RESTORE ORIGINAL VOLUME */
  1823.   if (XAAUD->mute != xaTRUE) Sony_Adjust_Volume(XAAUD->volume);
  1824. }
  1825.  
  1826. /********** Sony_Audio_On **********************
  1827. * Turn On Audio Stream.
  1828. *
  1829. *****/
  1830. void Sony_Audio_On()
  1831. { int ret ;
  1832.   struct sbparam a_info ;
  1833.  
  1834.   DEBUG_LEVEL1 fprintf(stderr,"SONY AUDIO ON\n");
  1835.  
  1836.   if (xa_audio_status == XA_AUDIO_STARTED) return;
  1837.   else if (xa_audio_present != XA_AUDIO_OK) return;
  1838.   else if (xa_snd_cur)
  1839.   {
  1840.     /* CHANGE FREQUENCY IF NEEDED */
  1841.     if( xa_audio_hard_freq != xa_snd_cur->hfreq )
  1842.     {
  1843.       a_info.sb_mode    = LOGPCM ;
  1844.       a_info.sb_format  = 0 ;
  1845.       a_info.sb_compress= MULAW ;
  1846.       a_info.sb_rate    = xa_snd_cur->hfreq ;
  1847.       a_info.sb_channel = MONO ;
  1848.       a_info.sb_bitwidth= RES8B ;
  1849.       a_info.sb_emphasis= 0 ;
  1850.       ret=ioctl(devAudio, SBIOCSETPARAM, &a_info); 
  1851.       if( ret == -1 )fprintf(stderr,"audio set freq: freq %lf errno %d\n",
  1852.                     xa_snd_cur->hfreq, errno);
  1853.       xa_audio_hard_freq = xa_snd_cur->hfreq;
  1854.     }
  1855.  
  1856.     /* xa_snd_cur gets changes in Update_Ring() */
  1857.     xa_out_time = 250; /* keep audio fed 250ms ahead of video - could be 500*/
  1858.     xa_out_init = xa_audio_ring_size - 1;
  1859.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  1860.  
  1861.     xa_audio_status = XA_AUDIO_STARTED;
  1862.     XA_Flush_Ring();
  1863.     XA_Update_Ring(1000);
  1864.  
  1865.     if (xa_interval_time == 0) xa_interval_time = 1;
  1866.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  1867.     New_Merged_Audio_Output();
  1868.   }
  1869. }
  1870. /********** Sony_Closest_Freq **********************************************
  1871. *
  1872. ****************************************************************************/
  1873. xaULONG Sony_Closest_Freq(ifreq)
  1874. xaLONG    ifreq;
  1875. { xaLONG i = 0 ;
  1876.   xaLONG best = 8000 ;
  1877.  
  1878.   xa_audio_hard_buff = XA_HARD_BUFF_1K;
  1879.   while(sony_audio_rate[i])
  1880.   {
  1881.     if (xaABS(sony_audio_rate[i] - ifreq) < xaABS(best - ifreq)) 
  1882.                 best = sony_audio_rate[i];
  1883.     i++;
  1884.   }
  1885.   return(best);
  1886. }
  1887. /************* Sony_Speaker_Toggle *****************************************
  1888. *
  1889. * flag = 0  turn speaker off
  1890. * flag = 1  turn speaker on
  1891. * flag = 2  toggle speaker
  1892. ****************************************************************************/
  1893. void Sony_Speaker_Toggle(flag)
  1894. xaULONG flag;
  1895. {
  1896.      /* do nothing */return ;
  1897. }
  1898.  
  1899. /************* Sony_Headphone_Toggle *****************************************
  1900. *
  1901. * flag = 0  turn headphones off
  1902. * flag = 1  turn headphones on
  1903. * flag = 2  toggle headphones
  1904. ****************************************************************************/
  1905. void Sony_Headphone_Toggle(flag)
  1906. xaULONG flag ;
  1907. {
  1908.      /* do nothing */return ;
  1909. }
  1910. /********** Sony_Adjust_Volume **********************/
  1911. void Sony_Adjust_Volume(volume)
  1912. xaULONG volume;
  1913.   struct sblevel     gain;
  1914.   int            mflg;
  1915.   int            o_level;
  1916.   mflg = MUTE_OFF;
  1917.   ioctl(devAudio, SBIOCMUTE, &mflg);
  1918.   o_level = sony_min_vol +
  1919.                  ((volume * (sony_max_vol - sony_min_vol)) / XA_AUDIO_MAXVOL);
  1920.   if (o_level > sony_max_vol)    o_level = sony_max_vol;
  1921.   if (o_level < sony_min_vol)    o_level = sony_min_vol;
  1922.  
  1923.   if (o_level == sony_min_vol) 
  1924.   {
  1925.     mflg = MUTE_ON;
  1926.     ioctl(devAudio, SBIOCMUTE, &mflg);
  1927.   }
  1928.   gain.sb_right = gain.sb_left = (o_level << 16);
  1929.   ioctl(devAudio, SBIOCSETOUTLVL, &gain);
  1930. }
  1931. #endif
  1932. /****************************************************************************/
  1933. /******************* END OF SONY SPECIFIC ROUTINES *********************/
  1934. /****************************************************************************/
  1935.  
  1936.  
  1937. /****************************************************************************/
  1938. /**************** LINUX SPECIFIC ROUTINES *******************************/
  1939. /****************************************************************************/
  1940. #ifdef XA_LINUX_AUDIO
  1941.  
  1942.  
  1943. void Linux_Audio_Init();
  1944. void Linux_Audio_Kill();
  1945. void Linux_Audio_Off();
  1946. void Linux_Audio_On();
  1947. xaULONG Linux_Closest_Freq();
  1948. void Linux_Speaker_Toggle();
  1949. void Linux_Headphone_Toggle();
  1950. void Linux_Adjust_Volume();
  1951. xaULONG Linux_Read_Volume();
  1952.  
  1953. int linux_vol_chan;
  1954.  
  1955. #define LINUX_MAX_VOL (100)
  1956. #define LINUX_MIN_VOL (0)
  1957.  
  1958. int devAudio;
  1959. int devMixer;
  1960.  
  1961. /********** XA_Audio_Setup **********************
  1962.  * Sets up Linux specific Routines
  1963.  *****/
  1964. void XA_Audio_Setup()
  1965. {
  1966.   XA_Audio_Init        = Linux_Audio_Init;
  1967.   XA_Audio_Kill        = Linux_Audio_Kill;
  1968.   XA_Audio_Off        = Linux_Audio_Off;
  1969.   XA_Audio_On        = Linux_Audio_On;
  1970.   XA_Closest_Freq    = Linux_Closest_Freq;
  1971.   XA_Set_Output_Port    = (void *)(0);
  1972.   XA_Speaker_Tog    = Linux_Speaker_Toggle;
  1973.   XA_Headphone_Tog    = Linux_Headphone_Toggle;
  1974.   XA_LineOut_Tog    = Linux_Headphone_Toggle;
  1975.   XA_Adjust_Volume    = Linux_Adjust_Volume;
  1976.  
  1977.   xa_snd_cur = 0;
  1978.   xa_audio_present = XA_AUDIO_UNK;
  1979.   xa_audio_status  = XA_AUDIO_STOPPED;
  1980.   xa_audio_ring_size  = 8;
  1981.   linux_vol_chan = SOUND_MIXER_VOLUME;  /* default */
  1982. }
  1983.  
  1984. /********** Linux_Audio_Init **********************
  1985.  * Init Linux Audio, init variables, open Audio Devices.
  1986.  *****/
  1987. void Linux_Audio_Init()
  1988. { int ret,tmp;
  1989.   DEBUG_LEVEL2 fprintf(stderr,"Linux_Audio_Init\n");
  1990.  
  1991.   if (xa_audio_present != XA_AUDIO_UNK) return;
  1992.  
  1993.   devAudio = open(_FILE_DSP, O_WRONLY | O_NDELAY, 0);
  1994.   if (devAudio == -1)
  1995.   { fprintf(stderr,"Can't Open %s device\n",_FILE_DSP);
  1996.     xa_audio_present = XA_AUDIO_ERR;
  1997.     return;
  1998.   }
  1999.   ioctl(devAudio, SNDCTL_DSP_SYNC, NULL);
  2000.   /* SETUP SAMPLE SIZE */
  2001.   if (xa_kludge900_aud == 900) tmp = 8;  /* POD testing purposes */
  2002.   else tmp = 16;
  2003. #ifdef SNDCTL_DSP_SAMPLESIZE
  2004. #ifdef XA_LINUX_NEWER_SND
  2005.   ret = ioctl(devAudio, SNDCTL_DSP_SAMPLESIZE, &tmp);
  2006. #else
  2007.   ret = ioctl(devAudio, SNDCTL_DSP_SAMPLESIZE, tmp);
  2008. #endif
  2009. #else
  2010.   ret = -1;
  2011. #endif
  2012.   if ((ret == -1) || (tmp == 8)) xa_audio_hard_bps = 1;
  2013.   else xa_audio_hard_bps = 2;
  2014.  
  2015.   /* SETUP Mono/Stereo */
  2016.   tmp = 0;  /* mono(0) stereo(1) */ 
  2017. #ifdef XA_LINUX_NEWER_SND
  2018.   ret = ioctl(devAudio, SNDCTL_DSP_STEREO, &tmp);
  2019. #else
  2020.   ret = ioctl(devAudio, SNDCTL_DSP_STEREO, tmp);
  2021. #endif
  2022.   if (ret == -1) fprintf(stderr,"Linux Audio: Error setting mono\n");
  2023.   xa_audio_hard_chans = 1;
  2024.  
  2025.   xa_audio_hard_freq  = 11025;  /* 22050 and sometimes 44100 */
  2026.   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
  2027.  
  2028. #ifdef SNDCTL_DSP_GETBLKSIZE
  2029. #ifdef XA_LINUX_NEWER_SND
  2030.   ret = ioctl(devAudio, SNDCTL_DSP_GETBLKSIZE, &tmp);
  2031. #else
  2032.   ret = ioctl(devAudio, SNDCTL_DSP_GETBLKSIZE, 0);
  2033. #endif
  2034. #else
  2035.   ret = 0;
  2036. #endif
  2037.   if (ret == -1) fprintf(stderr,"Linux Audio: Error getting buf size\n");
  2038.   /* POD NOTE: should probably do something with this value. :^) */
  2039.   /* Maybe XA_AUDIO_MAX_RING_BUFF should be a variable */
  2040.   
  2041.   ioctl(devAudio, SNDCTL_DSP_SYNC, NULL);
  2042.  
  2043.   devMixer = open(_FILE_MIXER,  O_RDONLY | O_NDELAY, 0);
  2044.   /* Mixer only present on SB Pro's and above */
  2045.   /* if not present then it's set to -1 and ignored later */
  2046.   /* THOUGHT: what about doing mixer ioctl to the /dev/dsp device??? */
  2047.   if (devMixer < 0) devMixer = devAudio;
  2048.    /* determine what volume settings exist */
  2049.   { int devices;
  2050. #ifdef XA_LINUX_NEWER_SND
  2051.     ret = ioctl(devMixer, SOUND_MIXER_READ_DEVMASK, &devices);
  2052.     if (ret == -1) devices = 0;
  2053. #else
  2054.     devices = ioctl(devMixer, SOUND_MIXER_READ_DEVMASK, 0 );
  2055.     if (devices == -1) devices = 0;
  2056. #endif
  2057.     if (devices & (1 << SOUND_MIXER_PCM)) 
  2058.         linux_vol_chan = SOUND_MIXER_PCM;
  2059.     else    linux_vol_chan = SOUND_MIXER_VOLUME;
  2060.   }
  2061.  
  2062. /*
  2063.   XAAUD->volume = Linux_Read_Volume();
  2064. */
  2065.  
  2066.   if (xa_audio_hard_bps == 1) xa_audio_hard_type  = XA_AUDIO_LINEAR_1M;
  2067.   else        xa_audio_hard_type  = XA_AUDIO_SIGNED_2ML;
  2068.  
  2069.   xa_interval_id = 0;
  2070.   xa_audio_present = XA_AUDIO_OK;
  2071.   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
  2072.   Init_Audio_Ring(xa_audio_ring_size,
  2073.             (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
  2074. }
  2075.  
  2076. /********** Linux_Audio_Kill *************************************************
  2077.  * Stop Linux Audio and Close Linux Audio Devices. Free up memory.
  2078.  *
  2079.  *****************************************************************************/
  2080. void Linux_Audio_Kill()
  2081. {
  2082.   Linux_Audio_Off(0);
  2083.   xa_audio_present = XA_AUDIO_UNK;
  2084.   if ( (devMixer != -1) && (devMixer != devAudio)) close(devMixer);
  2085.   close(devAudio);
  2086.   Kill_Audio_Ring();
  2087. }
  2088.  
  2089. /********** Linux_Audio_Off *************************************************
  2090.  * Stop Linux Audio
  2091.  *
  2092.  *****************************************************************************/
  2093. void Linux_Audio_Off(flag)
  2094. xaULONG flag;
  2095. {
  2096.   if (xa_audio_status != XA_AUDIO_STARTED) return;
  2097.   /* SET FLAG TO STOP OUTPUT ROUTINE */
  2098.   xa_audio_status = XA_AUDIO_STOPPED;
  2099.  
  2100.   ioctl(devAudio, SNDCTL_DSP_RESET, NULL);
  2101.  
  2102.   /* Linux_Adjust_Volume(XA_AUDIO_MINVOL); */
  2103.   /* ioctl(devAudio, SNDCTL_DSP_SYNC, NULL); */
  2104.   xa_time_audio = -1;
  2105.   xa_audio_flushed = 0;
  2106.   ioctl(devAudio, SNDCTL_DSP_SYNC, NULL);
  2107.   /* if (XAAUD->mute != xaTRUE) Linux_Adjust_Volume(XAAUD->volume); */
  2108.  
  2109. }
  2110.  
  2111. /********** Linux_Audio_On ***************************************************
  2112.  * Startup Linux Audio
  2113.  *
  2114.  *****************************************************************************/
  2115. void Linux_Audio_On()
  2116. {
  2117.   DEBUG_LEVEL2 fprintf(stderr,"Linux_Audio_On \n");
  2118.   if (xa_audio_status == XA_AUDIO_STARTED) return;
  2119.   else if (xa_snd_cur)
  2120.   { int ret,tmp;
  2121.   
  2122.     if (xa_audio_present != XA_AUDIO_OK) return;
  2123.  
  2124.     Linux_Adjust_Volume(XA_AUDIO_MINVOL);
  2125.     ioctl(devAudio, SNDCTL_DSP_SYNC, NULL);
  2126.  
  2127.     /* CHANGE FREQUENCY */
  2128.     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
  2129.     {
  2130.       tmp = xa_snd_cur->hfreq;
  2131. #ifdef XA_LINUX_NEWER_SND
  2132.       ret = ioctl(devAudio, SNDCTL_DSP_SPEED, &tmp);
  2133. #else
  2134.       tmp = ioctl(devAudio, SNDCTL_DSP_SPEED, tmp);
  2135. #endif
  2136.       if ((ret == -1) || (tmp != xa_snd_cur->hfreq))
  2137.     fprintf(stderr,"Linux_Audio: err setting freq %x\n"
  2138.                         ,xa_snd_cur->hfreq);
  2139.       xa_audio_hard_freq = xa_snd_cur->hfreq;
  2140.     }
  2141.     ioctl(devAudio, SNDCTL_DSP_SYNC, NULL);
  2142.     if (XAAUD->mute != xaTRUE) Linux_Adjust_Volume(XAAUD->volume);
  2143.  
  2144.     /* xa_snd_cur gets changes in Update_Ring() */
  2145.     xa_out_time = 250;  /* keep audio 250 ms ahead of video. could be 500ms */
  2146.     xa_out_init = xa_audio_ring_size - 1;
  2147.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  2148.  
  2149.     xa_audio_status = XA_AUDIO_STARTED;
  2150.     XA_Flush_Ring();
  2151.     XA_Update_Ring(1000);
  2152.  
  2153.     if (xa_interval_time == 0) xa_interval_time = 1;
  2154.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  2155.     New_Merged_Audio_Output();
  2156.   }
  2157. }
  2158.  
  2159. /********** Linux_Closest_Freq **********************************************
  2160.  * Return closest support frequeny and set hard_buff.
  2161.  *
  2162.  *****************************************************************************/
  2163. xaULONG Linux_Closest_Freq(ifreq)
  2164. xaLONG ifreq;    /* incoming frequency */
  2165. { static int valid[] = {11025, 22050, 44100, 0};
  2166.   xaLONG i = 0;
  2167.   xaLONG tmp_freq,ofreq = ifreq;
  2168. #ifdef XA_LINUX_NEWER_SND
  2169.   xaLONG ret;
  2170. #endif
  2171.  
  2172.    /* search up for closest frequency */
  2173.   while(valid[i])
  2174.   {
  2175.     if (xaABS(valid[i] - ifreq) < xaABS(ofreq - ifreq)) ofreq = valid[i];
  2176.     i++;
  2177.   }
  2178.  
  2179.   tmp_freq = ofreq;
  2180. #ifdef XA_LINUX_NEWER_SND
  2181.   ret = ioctl(devAudio, SNDCTL_DSP_SPEED, &tmp_freq);
  2182.   if (ret == -1) tmp_freq = 0;
  2183. #else
  2184.   tmp_freq = ioctl(devAudio, SNDCTL_DSP_SPEED, tmp_freq);
  2185.   if (tmp_freq == -1) tmp_freq = 0;
  2186. #endif
  2187.   if (tmp_freq) ofreq = tmp_freq;
  2188.  
  2189.   if (ofreq >= 25000) xa_audio_hard_buff = XA_HARD_BUFF_2K;
  2190.   else xa_audio_hard_buff = XA_HARD_BUFF_1K;
  2191.   return(ofreq);
  2192. }
  2193.  
  2194. /********** Linux_Speaker_Toggle **********************************************
  2195.  * Turn off/on/toggle Linux's Speaker(if possible)
  2196.  * flag= 0   1   2 
  2197.  *****************************************************************************/
  2198. void Linux_Speaker_Toggle(flag)
  2199. xaULONG flag;
  2200. {
  2201.   return;
  2202. }
  2203.  
  2204. /********** Linux_Headphone_Toggle ********************************************
  2205.  * Turn off/on/toggle Linux's Headphone(if possible)
  2206.  * flag= 0   1   2 
  2207.  *****************************************************************************/
  2208. void Linux_Headphone_Toggle(flag)
  2209. xaULONG flag;
  2210. {
  2211.   return;
  2212. }
  2213.  
  2214. /********** Linux_Adjust_Volume ***********************************************
  2215.  * Routine for Adjusting Volume on Linux
  2216.  *
  2217.  *****************************************************************************/
  2218. void Linux_Adjust_Volume(volume)
  2219. xaULONG volume;
  2220. { xaULONG adj_volume;
  2221.  
  2222.   if (devMixer < 0) return;
  2223.   adj_volume = LINUX_MIN_VOL +
  2224.         ((volume * (LINUX_MAX_VOL - LINUX_MIN_VOL)) / XA_AUDIO_MAXVOL);
  2225.   if (adj_volume > LINUX_MAX_VOL) adj_volume = LINUX_MAX_VOL;
  2226.   adj_volume |= adj_volume << 8;    /* left channel | right channel */
  2227. #ifdef XA_LINUX_NEWER_SND
  2228.   ioctl(devMixer, MIXER_WRITE(linux_vol_chan), &adj_volume);
  2229. #else
  2230.   ioctl(devMixer, MIXER_WRITE(linux_vol_chan), adj_volume);
  2231. #endif
  2232. }
  2233.  
  2234. /********** Linux_Adjust_Volume ***********************************************
  2235.  * Routine for Adjusting Volume on Linux
  2236.  *
  2237.  *****************************************************************************/
  2238. xaULONG Linux_Read_Volume()
  2239. { xaLONG ret,the_volume = 0;
  2240.   if (devMixer < 0) return(0);
  2241. #ifdef XA_LINUX_NEWER_SND
  2242.   ret = ioctl(devMixer, MIXER_READ(linux_vol_chan), &the_volume);
  2243.   if (ret < 0) the_volume = 0;
  2244. #else
  2245.   the_volume = ioctl(devMixer, MIXER_READ(linux_vol_chan), 0);
  2246.   if (the_volume < 0) the_volume = 0;
  2247. #endif
  2248.  
  2249.   the_volume =  (XA_AUDIO_MAXVOL * (the_volume - LINUX_MIN_VOL)) 
  2250.                         / (LINUX_MAX_VOL);
  2251.  
  2252.   fprintf(stderr,"volume = %d %d %d",the_volume,LINUX_MIN_VOL,LINUX_MAX_VOL);
  2253.   return(the_volume);
  2254. }
  2255. #endif
  2256. /****************************************************************************/
  2257. /******************* END OF LINUX SPECIFIC ROUTINES *********************/
  2258. /****************************************************************************/
  2259.  
  2260.  
  2261. /****************************************************************************/
  2262. /**************** SGI SPECIFIC ROUTINES *******************************/
  2263. /****************************************************************************/
  2264. #ifdef XA_SGI_AUDIO
  2265.  
  2266. void SGI_Audio_Init();
  2267. void SGI_Audio_Kill();
  2268. void SGI_Audio_Off();
  2269. void SGI_Audio_On();
  2270. xaULONG SGI_Closest_Freq();
  2271. void SGI_Speaker_Toggle();
  2272. void SGI_Headphone_Toggle();
  2273. void SGI_Adjust_Volume();
  2274.  
  2275. #define SGI_MAX_VOL (255)
  2276. #define SGI_MIN_VOL (0)
  2277.  
  2278. static ALport port;
  2279. static ALconfig conf;
  2280.  
  2281. /********** XA_Audio_Setup **********************
  2282.  * Sets up SGI specific Routines
  2283.  *****/
  2284. void XA_Audio_Setup()
  2285. {
  2286.   XA_Audio_Init        = SGI_Audio_Init;
  2287.   XA_Audio_Kill        = SGI_Audio_Kill;
  2288.   XA_Audio_Off        = SGI_Audio_Off;
  2289.   XA_Audio_On        = SGI_Audio_On;
  2290.   XA_Closest_Freq    = SGI_Closest_Freq;
  2291.   XA_Set_Output_Port    = (void *)(0);
  2292.   XA_Speaker_Tog    = SGI_Speaker_Toggle;
  2293.   XA_Headphone_Tog    = SGI_Headphone_Toggle;
  2294.   XA_LineOut_Tog    = SGI_Headphone_Toggle;
  2295.   XA_Adjust_Volume    = SGI_Adjust_Volume;
  2296.  
  2297.   xa_snd_cur = 0;
  2298.   xa_audio_present = XA_AUDIO_UNK;
  2299.   xa_audio_status  = XA_AUDIO_STOPPED;
  2300.   xa_audio_ring_size  = 8;
  2301. }
  2302.  
  2303. /********** SGI_Audio_Init **********************
  2304.  * Init SGI Audio, init variables, open Audio Devices.
  2305.  *****/
  2306. void SGI_Audio_Init()
  2307. { long sgi_params[4];
  2308.   DEBUG_LEVEL2 fprintf(stderr,"SGI_Audio_Init\n");
  2309.  
  2310.   if (xa_audio_present != XA_AUDIO_UNK) return;
  2311.  
  2312.   conf = ALnewconfig();
  2313.   ALsetwidth(conf, AL_SAMPLE_16);
  2314.   ALsetchannels(conf, AL_MONO);
  2315.   ALsetqueuesize(conf, 16384);
  2316.   port = ALopenport("XAnim Mono", "w", conf);
  2317.   if (port == 0)
  2318.   { fprintf(stderr,"Can't Open SGI Audio device\n");
  2319.     xa_audio_present = XA_AUDIO_ERR;
  2320.     return;
  2321.   }
  2322.  
  2323.   /* get default frequency - no really necessary */
  2324.   sgi_params[0] = AL_OUTPUT_RATE;
  2325.   sgi_params[1] = 11025;
  2326.   ALsetparams(AL_DEFAULT_DEVICE, sgi_params, 2);
  2327.   ALgetparams(AL_DEFAULT_DEVICE, sgi_params, 2);
  2328.   xa_audio_hard_freq = sgi_params[1];
  2329.  
  2330.   xa_audio_hard_bps = 2;
  2331.   xa_audio_hard_chans = 1;
  2332.   xa_audio_hard_buff  = XA_HARD_BUFF_2K;   /* was XA_HARD_BUFF_1K */
  2333.   xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
  2334.  
  2335.   xa_interval_id = 0;
  2336.   xa_audio_present = XA_AUDIO_OK;
  2337.   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
  2338.   Init_Audio_Ring(xa_audio_ring_size,
  2339.             (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
  2340. }
  2341. /********** SGI_Audio_Kill **********************
  2342.  * Stop SGI Audio and Close SGI Audio Devices. Free up memory.
  2343.  *****/
  2344. void SGI_Audio_Kill()
  2345. {
  2346.   /* TURN AUDIO OFF */
  2347.   SGI_Audio_Off(0);
  2348.   xa_audio_present = XA_AUDIO_UNK;
  2349.   /* SHUT THINGS DOWN  */
  2350.   ALcloseport(port);
  2351.   ALfreeconfig(conf);
  2352.   Kill_Audio_Ring();
  2353.   return;
  2354. }
  2355.  
  2356. /********** SGI_Audio_Off **********************
  2357.  * Stop SGI Audio
  2358.  *****/
  2359. void SGI_Audio_Off(flag)
  2360. xaULONG flag;
  2361. {
  2362.   DEBUG_LEVEL2 fprintf(stderr,"SGI_Audio_Off\n");
  2363.   if (xa_audio_status != XA_AUDIO_STARTED) return;
  2364.  
  2365.   /* SET FLAG TO STOP OUTPUT ROUTINE */
  2366.   xa_audio_status = XA_AUDIO_STOPPED;
  2367.  
  2368.   /* TURN OFF SOUND ??? */
  2369.   SGI_Adjust_Volume(XA_AUDIO_MINVOL);
  2370.  
  2371.   /* FLUSH DEVICE SHOULD GO HERE */
  2372.   /* POD NOTE: DOES SGI HAVE A FLUSH???? */
  2373.  
  2374.   /* Wait until all samples drained */
  2375.   while(ALgetfilled(port) != 0) sginap(1);
  2376.  
  2377.   xa_time_audio = -1;
  2378.   xa_audio_flushed = 0;
  2379.  
  2380.   /* RESTORE ORIGINAL VOLUME */
  2381.   if (XAAUD->mute != xaTRUE) SGI_Adjust_Volume(XAAUD->volume);
  2382. }
  2383.  
  2384. /********** SGI_Audio_On **********************
  2385.  * Startup SGI Audio
  2386.  *****/
  2387. void SGI_Audio_On()
  2388. {
  2389.   DEBUG_LEVEL2 fprintf(stderr,"SGI_Audio_On \n");
  2390.   if (xa_audio_status == XA_AUDIO_STARTED) return;
  2391.   else if (xa_audio_present != XA_AUDIO_OK) return;
  2392.   else if (xa_snd_cur)
  2393.   { 
  2394.     /* Change Frequency If necessary */
  2395.     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
  2396.     { long sgi_params[2];
  2397.       sgi_params[0] = AL_OUTPUT_RATE;
  2398.       sgi_params[1] = xa_snd_cur->hfreq;
  2399.       ALsetparams(AL_DEFAULT_DEVICE, sgi_params, 2);
  2400.       xa_audio_hard_freq = xa_snd_cur->hfreq;
  2401.     }
  2402.  
  2403.     /* xa_snd_cur gets changes in Update_Ring() */
  2404.     xa_out_time = 500;  /* keep audio fed 500ms ahead of video */
  2405.     xa_out_init = xa_audio_ring_size - 1;
  2406.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  2407.  
  2408.     xa_audio_status = XA_AUDIO_STARTED;
  2409.     XA_Flush_Ring();
  2410.     XA_Update_Ring(1000);
  2411.  
  2412.     if (xa_interval_time == 0) xa_interval_time = 1;
  2413.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  2414.     New_Merged_Audio_Output();
  2415.   }
  2416. }
  2417.  
  2418. /********** SGI_Closest_Freq **********************
  2419.  * Return closest support frequeny and set hard_buff.
  2420.  * The IRIX 4.0.5 audio.h file lists the following frequencies:
  2421.  * {8000,11025,16000,22050,32000,44100,48000}
  2422.  *****/
  2423. xaULONG SGI_Closest_Freq(ifreq)
  2424. xaLONG ifreq;
  2425. { static int valid[] = { 8000,11025,16000,22050,32000,44100,0};
  2426.   xaLONG i = 0;
  2427.   xaLONG ofreq = 8000;
  2428.   long sgi_params[2];
  2429.  
  2430.   while(valid[i])
  2431.   { 
  2432.     if (xaABS(valid[i] - ifreq) < xaABS(ofreq - ifreq)) ofreq = valid[i];
  2433.     i++;
  2434.   }
  2435.   sgi_params[0] = AL_OUTPUT_RATE;
  2436.   sgi_params[1] = ofreq;
  2437.   ALsetparams(AL_DEFAULT_DEVICE, sgi_params, 2); 
  2438.   ALgetparams(AL_DEFAULT_DEVICE, sgi_params, 2); 
  2439.   if (ofreq != sgi_params[1])
  2440.     fprintf(stderr,"SGI AUDIO: freq gotten %d wasn't wanted %d\n",
  2441.         sgi_params[1],ofreq);
  2442.   ofreq = sgi_params[1];
  2443.   xa_audio_hard_buff = XA_HARD_BUFF_2K; /* fixed for SGI */
  2444.   return(ofreq);
  2445. }
  2446.  
  2447.  
  2448. /********** SGI_Speaker_Toggle **********************
  2449.  * Turn off/on/toggle SGI's Speaker(if possible)
  2450.  * flag= 0   1   2 
  2451.  *****/
  2452. void SGI_Speaker_Toggle(flag)
  2453. xaULONG flag;
  2454. {
  2455.   return;
  2456. }
  2457.  
  2458. /********** SGI_Headphone_Toggle **********************
  2459.  * Turn off/on/toggle SGI's Headphone(if possible)
  2460.  * flag= 0   1   2 
  2461.  *****/
  2462. void SGI_Headphone_Toggle(flag)
  2463. xaULONG flag;
  2464. {
  2465.   return;
  2466. }
  2467.  
  2468. /********** SGI_Adjust_Volume **********************
  2469.  * Routine for Adjusting Volume on SGI
  2470.  *
  2471.  *****/
  2472. void SGI_Adjust_Volume(volume)
  2473. xaULONG volume;
  2474. { xaULONG adj_volume;
  2475.   long sgi_params[4];
  2476.   adj_volume =
  2477.       (int)(pow(10.0, (float)volume / XA_AUDIO_MAXVOL * 2.406540183) + 0.5);
  2478.   if (adj_volume > SGI_MAX_VOL) adj_volume = SGI_MAX_VOL;
  2479.   sgi_params[0] = AL_LEFT_SPEAKER_GAIN;
  2480.   sgi_params[1] = adj_volume;
  2481.   sgi_params[2] = AL_RIGHT_SPEAKER_GAIN;
  2482.   sgi_params[3] = adj_volume;
  2483.   ALsetparams(AL_DEFAULT_DEVICE, sgi_params, 4);
  2484. }
  2485.  
  2486. #endif
  2487. /****************************************************************************/
  2488. /******************* END OF SGI SPECIFIC ROUTINES *********************/
  2489. /****************************************************************************/
  2490.  
  2491. /****************************************************************************/
  2492. /**************** HP SPECIFIC ROUTINES *******************************/
  2493. /****************************************************************************/
  2494. #ifdef XA_HP_AUDIO
  2495.  
  2496. void HP_Audio_Init();
  2497. void HP_Audio_Kill();
  2498. void HP_Audio_Off();
  2499. void HP_Audio_On();
  2500. xaULONG HP_Closest_Freq();
  2501. void HP_Speaker_Toggle();
  2502. void HP_Headphone_Toggle();
  2503. void HP_Adjust_Volume();
  2504. void HP_Print_Error();
  2505. void HP_Print_ErrEvent();
  2506. long HP_Audio_Err_Handler();
  2507. void TheEnd();
  2508. int  streamSocket; /*POD NOTE: rename */
  2509.  
  2510.  
  2511. #define HP_MAX_VOL (audio_connection->max_output_gain)
  2512. #define HP_MIN_VOL (audio_connection->min_output_gain)
  2513.  
  2514. Audio        *audio_connection = 0;
  2515.  
  2516. /* structures */
  2517. AudioAttributes    play_attribs;
  2518. SSPlayParams    streamParams;
  2519. SStream     audio_stream;
  2520. /* longs */
  2521. ATransID    hp_trans_id;
  2522. AudioAttrMask    hp_attr_mask;
  2523. AErrorHandler    hp_prev_handler;
  2524. AGainEntry    gainEntry[4];
  2525. long        hp_status;
  2526.  
  2527. long *hp_sample_rates = 0;
  2528. int hp_audio_paused = xaFALSE;
  2529.  
  2530. long HP_Audio_Err_Handler(audio,err_event)
  2531. Audio *audio;
  2532. AErrorEvent *err_event;
  2533. {
  2534.   fprintf(stderr,"HP_Audio_Err_Handler:\n");
  2535.   xa_audio_present = XA_AUDIO_ERR;
  2536.   xa_audio_status  = XA_AUDIO_STOPPED;
  2537.   HP_Print_ErrEvent("HP_Audio_Err_Handler: ","\n",err_event->error_code);
  2538.   /* PODNOTE: temporary: eventually we'll try a gracefull recovery
  2539.    * and shift back to visual only 
  2540.    */
  2541.   TheEnd();
  2542. }
  2543.  
  2544. /********** XA_Audio_Setup **********************
  2545.  * Sets up HP specific Routines
  2546.  *****/
  2547. void XA_Audio_Setup()
  2548. {
  2549.   XA_Audio_Init        = HP_Audio_Init;
  2550.   XA_Audio_Kill        = HP_Audio_Kill;
  2551.   XA_Audio_Off        = HP_Audio_Off;
  2552.   XA_Audio_On        = HP_Audio_On;
  2553.   XA_Closest_Freq    = HP_Closest_Freq;
  2554.   XA_Set_Output_Port    = (void *)(0);
  2555.   XA_Speaker_Tog    = HP_Speaker_Toggle;
  2556.   XA_Headphone_Tog    = HP_Headphone_Toggle;
  2557.   XA_LineOut_Tog    = HP_Headphone_Toggle;
  2558.  
  2559.   xa_snd_cur = 0;
  2560.   xa_audio_present = XA_AUDIO_UNK;
  2561.   xa_audio_status  = XA_AUDIO_STOPPED;
  2562.   xa_audio_ring_size  = 8;
  2563.   hp_audio_paused = xaFALSE;
  2564. }
  2565.  
  2566. /********** HP_Print_Error **********************
  2567.  * print error message
  2568.  *****/
  2569. void HP_Print_Error(pre_str,post_str,status)
  2570. char *pre_str,*post_str;
  2571. AError status;
  2572. { char err_buff[132];
  2573.   if (pre_str) fprintf(stderr,"%s (%d)",pre_str,(int)(status));
  2574.   AGetErrorText(audio_connection,status,err_buff,131);
  2575.   fprintf(stderr,"%s",err_buff);
  2576.   if (post_str) fprintf(stderr,"%s",post_str);
  2577. }
  2578.  
  2579. /********** HP_Print_ErrEvent **********************
  2580.  * print error message
  2581.  *****/
  2582. void HP_Print_ErrEvent(pre_str,post_str,errorCode)
  2583. char *pre_str,*post_str;
  2584. int  errorCode;
  2585. { char err_buff[132];
  2586.   if (pre_str) fprintf(stderr,"%s (%d)",pre_str,(int)(errorCode));
  2587.   AGetErrorText(audio_connection,errorCode,err_buff,131);
  2588.   fprintf(stderr,"%s",err_buff);
  2589.   if (post_str) fprintf(stderr,"%s",post_str);
  2590. }
  2591.  
  2592.  
  2593. /********** HP_Audio_Init ***************************************************
  2594.  * Init HP Audio, init variables, open Audio Devices.
  2595.  *****/
  2596. void HP_Audio_Init()
  2597. { int ret,tmp,type;
  2598.   AudioAttributes req_attribs;
  2599.   AByteOrder  req_byteorder;
  2600.   AudioAttrMask req_mask;
  2601.   char server[256];
  2602.   server[0] = '\0';
  2603.  
  2604.   DEBUG_LEVEL2 fprintf(stderr,"HP_Audio_Init\n");
  2605.   DEBUG_LEVEL2 fprintf(stderr,"HP_Audio_Init: theAudContext = %x\n",
  2606.                         (xaULONG)theAudContext);
  2607.  
  2608.   if (xa_audio_present != XA_AUDIO_UNK) return;
  2609.  
  2610.   /* Setup Error Handler */
  2611.   hp_prev_handler = ASetErrorHandler(HP_Audio_Err_Handler);
  2612.  
  2613.   /* Open Up Audio */
  2614.   audio_connection = AOpenAudio( server, &hp_status);
  2615.   if (audio_connection == NULL)
  2616.   { char buf[256];
  2617.     HP_Print_Error("HP_Audio: couldn't connect to Audio -","\n",hp_status);
  2618.     xa_audio_present = XA_AUDIO_ERR;
  2619.     return;
  2620.   }
  2621.  
  2622.  
  2623.   /* Request the following attributes and see what get's returned */
  2624.   req_attribs.type = ATSampled;
  2625.   req_attribs.attr.sampled_attr.data_format = ADFLin16;
  2626.   req_attribs.attr.sampled_attr.bits_per_sample = 16;
  2627.   req_attribs.attr.sampled_attr.sampling_rate = 8000;
  2628.   req_attribs.attr.sampled_attr.channels = 1;  /* MONO */
  2629.   req_attribs.attr.sampled_attr.interleave = 1; /*???*/
  2630.   req_byteorder = AMSBFirst;
  2631.  
  2632.   play_attribs.type = ATSampled;
  2633.   play_attribs.attr.sampled_attr.data_format = ADFLin16;
  2634.   play_attribs.attr.sampled_attr.bits_per_sample = 16;
  2635.   play_attribs.attr.sampled_attr.sampling_rate = 8000;
  2636.   play_attribs.attr.sampled_attr.channels = 1;  /* MONO */
  2637.   play_attribs.attr.sampled_attr.interleave = 1; /*???*/
  2638.  
  2639.   fprintf(stderr,"REQ- format %d  bits %d  rate %d  chans %d bo %d\n",
  2640.     req_attribs.attr.sampled_attr.data_format,
  2641.     req_attribs.attr.sampled_attr.bits_per_sample,
  2642.     req_attribs.attr.sampled_attr.sampling_rate,
  2643.     req_attribs.attr.sampled_attr.channels,
  2644.     req_byteorder );
  2645.  
  2646. /*
  2647.   req_mask =   ASDataFormatMask | ASBitsPerSampleMask | ASSamplingRateMask
  2648.         | ASChannelsMask;
  2649. */
  2650.   req_mask = ASDurationMask;
  2651.  
  2652.   AChoosePlayAttributes(audio_connection, &req_attribs,req_mask,
  2653.                 &play_attribs, &req_byteorder, NULL);
  2654.  
  2655.   fprintf(stderr,"REQ+ format %d  bits %d  rate %d  chans %d bo %d\n",
  2656.     req_attribs.attr.sampled_attr.data_format,
  2657.     req_attribs.attr.sampled_attr.bits_per_sample,
  2658.     req_attribs.attr.sampled_attr.sampling_rate,
  2659.     req_attribs.attr.sampled_attr.channels,
  2660.     req_byteorder );
  2661.  
  2662.   fprintf(stderr,"PLAY format %d  bits %d  rate %d  chans %d\n",
  2663.     play_attribs.attr.sampled_attr.data_format,
  2664.     play_attribs.attr.sampled_attr.bits_per_sample,
  2665.     play_attribs.attr.sampled_attr.sampling_rate,
  2666.     play_attribs.attr.sampled_attr.channels    );
  2667.  
  2668.   switch(play_attribs.attr.sampled_attr.data_format)
  2669.   {
  2670.     case ADFLin16:    xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB; break;
  2671.     case ADFLin8:    xa_audio_hard_type  = XA_AUDIO_LINEAR_1M; break;
  2672.     case ADFLin8Offset:    xa_audio_hard_type  = XA_AUDIO_SIGNED_1M; break;
  2673.     default:
  2674.     fprintf(stderr,"HP_Audio: unknown hardware format\n");
  2675.     xa_audio_present = XA_AUDIO_ERR;
  2676.     return;
  2677.     break;
  2678.   }
  2679.  
  2680.   if (play_attribs.attr.sampled_attr.bits_per_sample == 16)
  2681.           xa_audio_hard_bps = 2;
  2682.   else        xa_audio_hard_bps = 1;
  2683.  
  2684.   if ( (req_byteorder == AMSBFirst) && (xa_audio_hard_bps > 1) )
  2685.             xa_audio_hard_type |= XA_AUDIO_BIGEND_MSK;
  2686.  
  2687.   xa_audio_hard_chans = play_attribs.attr.sampled_attr.channels;
  2688.   if (xa_audio_hard_chans == 2) 
  2689.             xa_audio_hard_type |= XA_AUDIO_STEREO_MSK;
  2690.  
  2691. DEBUG_LEVEL1 fprintf(stderr,"HP hard_type %x\n",xa_audio_hard_type);
  2692.  
  2693.   xa_audio_hard_freq = play_attribs.attr.sampled_attr.sampling_rate;
  2694.  
  2695.   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
  2696.  
  2697. /* NOT USED FOR NOW, BUT HOPEFULLY EVENTUALLY */
  2698.   { unsigned long *tmp;
  2699.     long num;
  2700.     hp_sample_rates = 0;
  2701.     num = ANumSamplingRates(audio_connection);
  2702.     if (num >= 0)
  2703.     {
  2704.       hp_sample_rates = (long *)malloc( (num + 2) * sizeof(long) );
  2705.       tmp = ASamplingRates(audio_connection);
  2706.       if (tmp)
  2707.       { xaULONG i;
  2708.         for(i=0; i < num; i++) hp_sample_rates[i] = tmp[i];
  2709.         hp_sample_rates[num] = 0;
  2710. /*
  2711. DEBUG_LEVEL1
  2712. */
  2713.   fprintf(stderr,"HP sampling rates: ");
  2714.   for(i=0;i<num;i++) fprintf(stderr,"<%d>",hp_sample_rates[i]);
  2715.   fprintf(stderr,"\n");
  2716. }
  2717.       }
  2718.       else {FREE(hp_sample_rates,0x500); hp_sample_rates=0;}
  2719.       if (hp_sample_rates==0)
  2720.       {
  2721.     fprintf(stderr,"Audio_Init: couldn't get sampling rates\n");
  2722.     xa_audio_present = XA_AUDIO_ERR;
  2723.     return;
  2724.       }
  2725.     }
  2726.   }
  2727.  
  2728.   xa_interval_id = 0;
  2729.   xa_audio_present = XA_AUDIO_OK;
  2730.  
  2731.   Init_Audio_Ring(xa_audio_ring_size,
  2732.             (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
  2733.  
  2734.   switch(play_attribs.attr.sampled_attr.channels)
  2735.   {
  2736.     case 1:
  2737.     gainEntry[0].u.o.out_ch = AOCTMono;
  2738.     gainEntry[0].gain = AUnityGain;
  2739.     if (XAAUD->port & XA_AUDIO_PORT_INT)
  2740.         gainEntry[0].u.o.out_dst = AODTMonoIntSpeaker; /* internal */
  2741.     else    gainEntry[0].u.o.out_dst = AODTMonoJack; /* ext or hdphones */
  2742.     break;
  2743.     case 2:
  2744.     default:
  2745.     fprintf(stderr,"HP_AUDIO: Warning hardware wants stereo\n");
  2746.     gainEntry[0].u.o.out_ch = AOCTLeft;
  2747.     gainEntry[0].gain = AUnityGain;
  2748.     gainEntry[1].u.o.out_ch = AOCTRight;
  2749.     gainEntry[1].gain = AUnityGain;
  2750.     if (XAAUD->port & XA_AUDIO_PORT_INT)
  2751.     {
  2752.       gainEntry[0].u.o.out_dst = AODTLeftIntSpeaker;
  2753.       gainEntry[1].u.o.out_dst = AODTRightIntSpeaker;
  2754.     }
  2755.     else
  2756.     {
  2757.       gainEntry[0].u.o.out_dst = AODTLeftJack;
  2758.       gainEntry[1].u.o.out_dst = AODTRightJack;
  2759.     }
  2760.         break;
  2761.   }
  2762.   streamParams.gain_matrix.type = AGMTOutput;
  2763.   streamParams.gain_matrix.num_entries = 
  2764.             play_attribs.attr.sampled_attr.channels;  
  2765.   streamParams.gain_matrix.gain_entries = gainEntry;
  2766.   streamParams.play_volume = AUnityGain;
  2767.   streamParams.priority = APriorityNormal;
  2768.   streamParams.event_mask = 0;
  2769.    
  2770.  
  2771.   /* START UP SOCKET CONNECTION TO HP's AUDIO DEVICE */
  2772. /*
  2773.   hp_attr_mask = ASDataFormatMask | ASBitsPerSampleMask | 
  2774.             ASSamplingRateMask | ASChannelsMask | ASInterleaveMask;
  2775. */
  2776.   hp_attr_mask = ~0;
  2777.  
  2778.   /* create the stream */
  2779.   hp_trans_id = APlaySStream(audio_connection,hp_attr_mask,&play_attribs,
  2780.                 &streamParams,&audio_stream,NULL);
  2781.  
  2782.   /* create socket */
  2783.   streamSocket = socket(AF_INET, SOCK_STREAM, 0);
  2784.   if (streamSocket < 0) fprintf(stderr,"HP_Audio: socket err %d\n",errno);
  2785.  
  2786.   ret = connect(streamSocket,(struct sockaddr *)&audio_stream.tcp_sockaddr,
  2787.                     sizeof(struct sockaddr_in) );
  2788.   if (ret < 0) fprintf(stderr,"HP_Audio: connect error %d\n",errno);
  2789.  
  2790.   /* Pause Audio Stream */
  2791.   APauseAudio( audio_connection, hp_trans_id, NULL, NULL );
  2792.   hp_audio_paused = xaTRUE;
  2793. }
  2794.  
  2795. /********** HP_Audio_Kill ***************************************************
  2796.  * Stop HP Audio and Close HP Audio Devices. Free up memory.
  2797.  *****/
  2798. void HP_Audio_Kill()
  2799. {
  2800.   DEBUG_LEVEL2 fprintf(stderr,"HP_Audio_Kill\n");
  2801.   HP_Audio_Off(0);
  2802.   close(streamSocket);
  2803.   /* IS THIS NEEDED? need to get man page for ASetCloseDownMode */
  2804.   ASetCloseDownMode(audio_connection, AKeepTransactions, NULL );
  2805.   ACloseAudio(audio_connection,NULL);
  2806.   Kill_Audio_Ring();
  2807. }
  2808.  
  2809. /********** HP_Audio_Off ***************************************************
  2810.  * Stop HP Audio
  2811.  *****/
  2812. void HP_Audio_Off(flag)
  2813. xaULONG flag;
  2814. {
  2815.   DEBUG_LEVEL2 fprintf(stderr,"HP_Audio_Off\n");
  2816.   if (xa_audio_status != XA_AUDIO_STARTED) return;
  2817.   /* SET FLAG TO STOP OUTPUT ROUTINE */
  2818.   xa_audio_status = XA_AUDIO_STOPPED;
  2819.  
  2820.   /* POD NOTE: USE PAUSE FOR NOW */
  2821. /*
  2822.   APauseAudio(audio_connection,hp_trans_id, NULL, NULL);
  2823.   hp_audio_paused = xaTRUE;
  2824. */
  2825.   xa_audio_status = XA_AUDIO_STOPPED;
  2826.   xa_time_audio = -1;
  2827.   xa_audio_flushed = 0;
  2828. }
  2829.  
  2830. /********** HP_Audio_On ***************************************************
  2831.  * Startup HP Audio
  2832.  *****/
  2833. void HP_Audio_On()
  2834. { AudioAttrMask attr_mask;
  2835.   DEBUG_LEVEL2 fprintf(stderr,"HP_Audio_On \n");
  2836.   if (xa_audio_status == XA_AUDIO_STARTED) return;
  2837.   else if (xa_audio_present != XA_AUDIO_OK) return;
  2838.   else if (xa_snd_cur)
  2839.   { int ret,tmp,utime;
  2840.  
  2841.     /* Change Frequency If necessary */
  2842.     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
  2843.     { 
  2844.       play_attribs.attr.sampled_attr.sampling_rate = xa_snd_cur->hfreq;
  2845.       xa_audio_hard_freq = xa_snd_cur->hfreq;
  2846.     }
  2847.  
  2848.     /* xa_snd_cur gets changes in Update_Ring() */
  2849.     xa_out_time = 250;  /* keep audio fed 500ms ahead of video */
  2850.     xa_out_init = xa_audio_ring_size - 1;
  2851.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  2852.  
  2853.     xa_audio_status = XA_AUDIO_STARTED;
  2854.     XA_Flush_Ring();
  2855.     XA_Update_Ring(1000);
  2856.  
  2857.     if (xa_interval_time == 0) xa_interval_time = 1;
  2858.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  2859.     New_Merged_Audio_Output();
  2860.   }
  2861. }
  2862.  
  2863. /********** HP_Closest_Freq **********************
  2864.  * Return closest support frequeny and set hard_buff.
  2865.  *****/
  2866. xaULONG HP_Closest_Freq(ifreq)
  2867. xaLONG ifreq;
  2868. {
  2869.  /* POD TEMPORARY */
  2870.   xa_audio_hard_buff = XA_HARD_BUFF_1K;
  2871.   return(8000);
  2872. }
  2873.  
  2874. /********** HP_Speaker_Toggle **********************
  2875.  * Turn off/on/toggle HP's Speaker(if possible)
  2876.  * flag= 0   1   2 
  2877.  *****/
  2878. void HP_Speaker_Toggle(flag)
  2879. xaULONG flag;
  2880. {
  2881.   return;
  2882. }
  2883.  
  2884. /********** HP_Headphone_Toggle **********************
  2885.  * Turn off/on/toggle HP's Headphone(if possible)
  2886.  * flag= 0   don't use Headphones(defaults to internal speaker)
  2887.  * flag= 1   Use Headphones.
  2888.  * flag= 2   Toggle. If headphone then internal and vice_versa. 
  2889.  *****/
  2890. void HP_Headphone_Toggle(flag)
  2891. xaULONG flag;
  2892. {
  2893.   return;
  2894. }
  2895.  
  2896. /********** HP_Adjust_Volume **********************
  2897.  * Routine for Adjusting Volume on HP
  2898.  *
  2899.  *****/
  2900.  
  2901. /* AUnityGain is 0. AZeroGain is 0x80000000 */
  2902. void HP_Adjust_Volume(volume)
  2903. xaLONG volume;
  2904. { xaLONG adj_volume;
  2905.   AGainDB play_gain,tmp_gain;
  2906.   int ret;
  2907.   adj_volume = HP_MIN_VOL + 
  2908.     ((volume * (HP_MAX_VOL - HP_MIN_VOL)) / XA_AUDIO_MAXVOL);
  2909.   if (adj_volume > HP_MAX_VOL) adj_volume = HP_MAX_VOL;
  2910.   play_gain = (AGainDB)adj_volume;
  2911. /*
  2912.   AGetSystemChannelGain(audio_connection,ASGTPlay,ACTMono,&tmp_gain,NULL);
  2913.   fprintf(stderr,"Get Gain %x adj_vol %x  hpmin %x hpmax %x\n",
  2914.                 tmp_gain,adj_volume,HP_MIN_VOL, HP_MAX_VOL);
  2915.   ASetSystemChannelGain(audio_connection,ASGTPlay,ACTMono,play_gain,NULL);
  2916.   ASetChannelGain(audio_connection,hp_trans_id,ACTMono,play_gain,NULL);
  2917.   ASetGain(audio_connection,hp_trans_id,play_gain,NULL);
  2918. */
  2919.   ASetSystemPlayGain(audio_connection,play_gain,NULL);
  2920. }
  2921.  
  2922. #endif
  2923. /****************************************************************************/
  2924. /******************* END OF HP SPECIFIC ROUTINES ****************************/
  2925. /****************************************************************************/
  2926.  
  2927.  
  2928. /****************************************************************************/
  2929. /**************** HPDEV SPECIFIC ROUTINES ***************************/
  2930. /****************************************************************************/
  2931. #ifdef XA_HPDEV_AUDIO
  2932.  
  2933. void HPDEV_Audio_Init();
  2934. void HPDEV_Audio_Kill();
  2935. void HPDEV_Audio_Off();
  2936. void HPDEV_Audio_On();
  2937. xaULONG HPDEV_Closest_Freq();
  2938. void HPDEV_Speaker_Toggle();
  2939. void HPDEV_Headphone_Toggle();
  2940. void HPDEV_LineOut_Toggle();
  2941. void HPDEV_Adjust_Volume();
  2942. static void HPDEV_Audio_Output();
  2943.  
  2944. static int devAudio;
  2945. static struct audio_describe audioDesc;
  2946.  
  2947.  
  2948. /********** XA_Audio_Setup **********************
  2949.  * Sets up HP specific routines
  2950.  *****/
  2951. void XA_Audio_Setup()
  2952. {
  2953.   XA_Audio_Init        = HPDEV_Audio_Init;
  2954.   XA_Audio_Kill        = HPDEV_Audio_Kill;
  2955.   XA_Audio_Off        = HPDEV_Audio_Off;
  2956.   XA_Audio_On        = HPDEV_Audio_On;
  2957.   XA_Closest_Freq    = HPDEV_Closest_Freq;
  2958.   XA_Set_Output_Port    = (void *)(0);
  2959.   XA_Speaker_Tog    = HPDEV_Speaker_Toggle;
  2960.   XA_Headphone_Tog    = HPDEV_Headphone_Toggle;
  2961.   XA_LineOut_Tog    = HPDEV_LineOut_Toggle;
  2962.   XA_Adjust_Volume    = HPDEV_Adjust_Volume;
  2963.  
  2964.   xa_snd_cur = 0;
  2965.   xa_audio_present = XA_AUDIO_UNK;
  2966.   xa_audio_status = XA_AUDIO_STOPPED;
  2967.   xa_audio_ring_size = 8;
  2968. }
  2969.  
  2970. /********** HPDEV_Audio_Init ***************************************************
  2971.  * open /dev/audio and init
  2972.  *****/
  2973. void HPDEV_Audio_Init()
  2974. {
  2975.   DEBUG_LEVEL2 fprintf(stderr,"HPDEV_Audio_Init\n");
  2976.   if (xa_audio_present != XA_AUDIO_UNK) return;
  2977.  
  2978.   if ((devAudio = open ("/dev/audio", O_WRONLY | O_NDELAY, 0)) < 0)
  2979.   {
  2980.     if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - ");
  2981.     else fprintf(stderr,"Audio_Init: Error opening audio device. - ");
  2982.     fprintf(stderr,"Will continue without audio\n");
  2983.     xa_audio_present = XA_AUDIO_ERR;
  2984.     return;
  2985.   }
  2986.  
  2987.   fcntl(devAudio,F_SETFL,O_NDELAY);
  2988.  
  2989.  
  2990.   /* Get description of /dev/audio: */
  2991.   if (ioctl (devAudio, AUDIO_DESCRIBE, &audioDesc))
  2992.   {
  2993.     perror ("ioctl AUDIO_DESCRIBE on /dev/audio");
  2994.     xa_audio_present = XA_AUDIO_ERR;
  2995.     return;
  2996.   }
  2997.  
  2998.   xa_audio_hard_type  = XA_AUDIO_SIGNED_2MB;
  2999.   xa_audio_hard_freq  = 0;      /* none yet (HPDEV_Audio_On does this job) */
  3000.   xa_audio_hard_bps   = 2;
  3001.   xa_audio_hard_chans = 1;
  3002.   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
  3003.  
  3004.   if (ioctl (devAudio, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT))
  3005.   {
  3006.     perror ("ioctl AUDIO_SET_DATA_FORMAT on /dev/audio");
  3007.     xa_audio_present = XA_AUDIO_ERR;
  3008.     return;
  3009.   }
  3010.   if (ioctl (devAudio, AUDIO_SET_CHANNELS, 1))
  3011.   {
  3012.     perror ("ioctl AUDIO_SET_CHANNELS on /dev/audio");
  3013.     xa_audio_present = XA_AUDIO_ERR;
  3014.     return;
  3015.   }
  3016.  
  3017.   /* set device internal buffer size: */
  3018.   if (ioctl (devAudio, AUDIO_SET_TXBUFSIZE, 16 * 1024))
  3019.     perror ("ioctl AUDIO_SET_TXBUFSIZE on /dev/audio");
  3020.  
  3021.   xa_interval_id = 0;
  3022.   xa_audio_present = XA_AUDIO_OK;
  3023.   Init_Audio_Ring(xa_audio_ring_size, (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
  3024. }
  3025.  
  3026. /********** HPDEV_Audio_Kill ***************************************************
  3027.  * Stop HP Audio and Close HP Audio Devices. Free up memory.
  3028.  *****/
  3029. void HPDEV_Audio_Kill()
  3030. {
  3031.   DEBUG_LEVEL2 fprintf(stderr,"HPDEV_Audio_Kill\n");
  3032.   HPDEV_Audio_Off(0);
  3033.   xa_audio_present = XA_AUDIO_UNK;
  3034.   close(devAudio);
  3035.   Kill_Audio_Ring();
  3036. }
  3037.  
  3038. /********** HPDEV_Audio_Off ***************************************************
  3039.  * Stop HP Audio
  3040.  *****/
  3041. void HPDEV_Audio_Off(flag)
  3042. xaULONG flag;
  3043. {
  3044.   DEBUG_LEVEL2 fprintf(stderr,"HPDEV_Audio_Off\n");
  3045.   if (xa_audio_status != XA_AUDIO_STARTED) return;
  3046.  
  3047.   /* SET FLAG TO STOP OUTPUT ROUTINE */
  3048.   xa_audio_status = XA_AUDIO_STOPPED;
  3049.  
  3050.   if (ioctl (devAudio, AUDIO_DRAIN, 0))
  3051.     perror ("ioctl AUDIO_DRAIN on /dev/audio");
  3052.  
  3053.   xa_time_audio = -1;
  3054.   xa_audio_flushed = 0;
  3055. }
  3056.  
  3057. /********** HPDEV_Audio_On ***************************************************
  3058.  * Startup HP Audio
  3059.  *****/
  3060. void HPDEV_Audio_On()
  3061. {
  3062.   DEBUG_LEVEL2 fprintf(stderr,"HPDEV_Audio_On\n");
  3063.   if (xa_audio_status == XA_AUDIO_STARTED) return;
  3064.   else if (xa_audio_present != XA_AUDIO_OK) return;
  3065.   else if (xa_snd_cur)
  3066.   { int ret,tmp,utime;
  3067.  
  3068.     /* Change frequency if necessary */
  3069.     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
  3070.     { 
  3071.       do { ret = ioctl(devAudio, AUDIO_SET_SAMPLE_RATE, xa_snd_cur->hfreq);
  3072.          } while( (ret < 0) && (errno == EBUSY) );
  3073.       if (ret < 0) perror ("ioctl AUDIO_SET_SAMPLE_RATE on /dev/audio");
  3074.       xa_audio_hard_freq = xa_snd_cur->hfreq;
  3075.     }
  3076.  
  3077.     /* xa_snd_cur gets changes in Update_Ring() */
  3078.     xa_out_time = 250; /* keep audio fed 250ms ahead of video */
  3079.     xa_out_init = xa_audio_ring_size - 1;
  3080.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  3081.  
  3082.     xa_audio_status = XA_AUDIO_STARTED;
  3083.     XA_Flush_Ring();
  3084.     XA_Update_Ring(1000);
  3085.  
  3086.     if (xa_interval_time == 0) xa_interval_time = 1;
  3087.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  3088.     New_Merged_Audio_Output();
  3089.   }
  3090. }
  3091.  
  3092. /********** HPDEV_Closest_Freq **********************
  3093.  * Return closest support frequeny and set hard_buff.
  3094.  *****/
  3095. xaULONG HPDEV_Closest_Freq(ifreq)
  3096. xaLONG ifreq;
  3097. {
  3098.   unsigned int rate_index;
  3099.   long nearest_frequency = 8000;
  3100.   long frequency_diff = 999999;
  3101.  
  3102.   xa_audio_hard_buff = XA_HARD_BUFF_1K;
  3103.  
  3104.   for (rate_index = 0; rate_index < audioDesc.nrates; ++rate_index)
  3105.   { if (abs (audioDesc.sample_rate[rate_index] - ifreq) <= frequency_diff)
  3106.     { nearest_frequency = audioDesc.sample_rate[rate_index];
  3107.       frequency_diff = abs (audioDesc.sample_rate[rate_index] - ifreq);
  3108.     }
  3109.   }
  3110.   return nearest_frequency;
  3111. }
  3112.  
  3113. /********** HPDEV_Speaker_Toggle **********************
  3114.  * Turn off/on/toggle HP's Speaker(if possible)
  3115.  * flag= 0   1   2 
  3116.  *****/
  3117. void HPDEV_Speaker_Toggle(flag)
  3118. xaULONG flag;
  3119. {
  3120.   int output_channel;
  3121.  
  3122.   if (ioctl (devAudio, AUDIO_GET_OUTPUT, &output_channel))
  3123.   {
  3124.     perror ("ioctl AUDIO_GET_OUTPUT on /dev/audio");
  3125.     output_channel = 0;
  3126.   }
  3127.   switch (flag)
  3128.   {
  3129.     case 0:
  3130.       output_channel &= ~AUDIO_OUT_SPEAKER; break;
  3131.     case 1:
  3132.       output_channel |= AUDIO_OUT_SPEAKER; break;
  3133.     case 2:
  3134.       output_channel ^= AUDIO_OUT_SPEAKER;
  3135.   }
  3136.   if (ioctl (devAudio, AUDIO_SET_OUTPUT, output_channel))
  3137.     perror ("ioctl AUDIO_SET_OUTPUT on /dev/audio");
  3138. }
  3139.  
  3140. /********** HPDEV_Headphone_Toggle **********************
  3141.  * Turn off/on/toggle HP's Headphone(if possible)
  3142.  * flag= 0   don't use Headphones(defaults to internal speaker)
  3143.  * flag= 1   Use Headphones.
  3144.  * flag= 2   Toggle. If headphone then internal and vice_versa. 
  3145.  *****/
  3146. void HPDEV_Headphone_Toggle(flag)
  3147. xaULONG flag;
  3148. {
  3149.   int output_channel;
  3150.  
  3151.   if (ioctl (devAudio, AUDIO_GET_OUTPUT, &output_channel))
  3152.   {
  3153.     perror ("ioctl AUDIO_GET_OUTPUT on /dev/audio");
  3154.     output_channel = 0;
  3155.   }
  3156.   switch (flag)
  3157.   {
  3158.     case 0:
  3159.       output_channel &= ~AUDIO_OUT_HEADPHONE; break;
  3160.     case 1:
  3161.       output_channel |= AUDIO_OUT_HEADPHONE; break;
  3162.     case 2:
  3163.       output_channel ^= AUDIO_OUT_HEADPHONE;
  3164.   }
  3165.   if (ioctl (devAudio, AUDIO_SET_OUTPUT, output_channel))
  3166.     perror ("ioctl AUDIO_SET_OUTPUT on /dev/audio");
  3167. }
  3168.  
  3169. /********** HPDEV_LineOut_Toggle **********************
  3170.  * Turn off/on/toggle HP's LineOut(if possible)
  3171.  * flag= 0   don't use LineOut(defaults to internal speaker)
  3172.  * flag= 1   Use LineOut.
  3173.  * flag= 2   Toggle. If LineOut then internal and vice_versa. 
  3174.  *****/
  3175. void HPDEV_LineOut_Toggle(flag)
  3176. xaULONG flag;
  3177. {
  3178.   int output_channel;
  3179.  
  3180.   if (ioctl (devAudio, AUDIO_GET_OUTPUT, &output_channel))
  3181.   {
  3182.     perror ("ioctl AUDIO_GET_OUTPUT on /dev/audio");
  3183.     output_channel = 0;
  3184.   }
  3185.   switch (flag)
  3186.   {
  3187.     case 0:
  3188.       output_channel &= ~AUDIO_OUT_LINE; break;
  3189.     case 1:
  3190.       output_channel |= AUDIO_OUT_LINE; break;
  3191.     case 2:
  3192.       output_channel ^= AUDIO_OUT_LINE;
  3193.   }
  3194.   if (ioctl (devAudio, AUDIO_SET_OUTPUT, output_channel))
  3195.     perror ("ioctl AUDIO_SET_OUTPUT on /dev/audio");
  3196. }
  3197.  
  3198. /********** HPDEV_Adjust_Volume **********************
  3199.  * Routine for Adjusting Volume on HP
  3200.  *
  3201.  *****/
  3202. void HPDEV_Adjust_Volume(volume)
  3203. xaLONG volume;
  3204. {
  3205.   struct audio_describe description;
  3206.   struct audio_gains gains;
  3207.   float floatvolume = ((float)volume - (float)XA_AUDIO_MINVOL) /
  3208.               ((float)XA_AUDIO_MAXVOL - (float)XA_AUDIO_MINVOL);
  3209.  
  3210.   if (ioctl (devAudio, AUDIO_DESCRIBE, &description))
  3211.   {
  3212.     perror ("ioctl AUDIO_DESCRIBE on /dev/audio");
  3213.     return;
  3214.   }
  3215.   if (ioctl (devAudio, AUDIO_GET_GAINS, &gains))
  3216.   {
  3217.     perror ("ioctl AUDIO_GET_GAINS on /dev/audio");
  3218.     return;
  3219.   }
  3220.   gains.transmit_gain = (int)((float)description.min_transmit_gain +
  3221.                   (float)(description.max_transmit_gain
  3222.                       - description.min_transmit_gain) * floatvolume);
  3223.   if (ioctl (devAudio, AUDIO_SET_GAINS, &gains))
  3224.     perror ("ioctl AUDIO_SET_GAINS on /dev/audio");
  3225. }
  3226.  
  3227. #endif
  3228. /****************************************************************************/
  3229. /******************* END OF HPDEV SPECIFIC ROUTINES ******************/
  3230. /****************************************************************************/
  3231.  
  3232. /****************************************************************************/
  3233. /**************** AF SPECIFIC ROUTINES **************************************/
  3234. /****************************************************************************/
  3235. #ifdef XA_AF_AUDIO
  3236.  
  3237. /*
  3238.  * AF port provided by Tom Levergood,
  3239.  *    tml@crl.dec.com
  3240.  * Thu Aug 25 14:05:47 1994
  3241.  * This is a quick hack, I need to stare at the xa buffering
  3242.  * further to clean up the port.
  3243.  */
  3244.  
  3245. void  AF_Audio_Init();
  3246. void  AF_Audio_Kill();
  3247. void  AF_Audio_Off();
  3248. void  AF_Audio_On();
  3249. void  AF_Adjust_Volume();
  3250. xaULONG AF_Closest_Freq();
  3251. void AF_Speaker_Toggle();
  3252. void AF_Headphone_Toggle();
  3253.  
  3254.  
  3255. static AFAudioConn *AFaud;
  3256. static AC ac;
  3257. static AFSetACAttributes AFattributes;
  3258. static int    AFdevice;
  3259. static ATime AFtime0=0;
  3260. static ATime AFbaseT=0;
  3261.  
  3262. /********** XA_Audio_Setup **********************
  3263.  * 
  3264.  * Also defines Sparc Specific variables.
  3265.  *
  3266.  *****/
  3267. void XA_Audio_Setup()
  3268. {
  3269.   XA_Audio_Init        = AF_Audio_Init;
  3270.   XA_Audio_Kill        = AF_Audio_Kill;
  3271.   XA_Audio_Off        = AF_Audio_Off;
  3272.   XA_Audio_On        = AF_Audio_On;
  3273.   XA_Closest_Freq    = AF_Closest_Freq;
  3274.   XA_Set_Output_Port    = (void *)(0);
  3275.   XA_Speaker_Tog    = AF_Speaker_Toggle;
  3276.   XA_Headphone_Tog    = AF_Headphone_Toggle;
  3277.   XA_LineOut_Tog    = AF_Headphone_Toggle;
  3278.   XA_Adjust_Volume    = AF_Adjust_Volume;
  3279.  
  3280.   xa_snd_cur = 0;
  3281.   xa_audio_present = XA_AUDIO_UNK;
  3282.   xa_audio_status  = XA_AUDIO_STOPPED;
  3283.   xa_audio_ring_size  = 8;
  3284. }
  3285.  
  3286.  
  3287. #define    AF_C_MIN    -30
  3288. #define    AF_C_MAX    30
  3289. #define AF_MAP_TO_C_GAIN(vol) (( ((vol)*AF_C_MAX)/XA_AUDIO_MAXVOL) + (AF_C_MIN))
  3290.  
  3291. #define SPU(type)       AF_sample_sizes[type].samps_per_unit
  3292. #define BPU(type)       AF_sample_sizes[type].bytes_per_unit
  3293.  
  3294. #define DPHONE(od) (int)(((AAudioDeviceDescriptor(AFaud, (od)))->outputsToPhone))
  3295. #define DFREQ(od) (int)(((AAudioDeviceDescriptor(AFaud, (od)))->playSampleFreq))
  3296. #define DCHAN(od) (int)((AAudioDeviceDescriptor(AFaud, (od)))->playNchannels)
  3297. #define DTYPE(od) ((AAudioDeviceDescriptor(AFaud, (od)))->playBufType)
  3298.  
  3299. #define    TOFFSET    250
  3300.  
  3301.  
  3302. /*
  3303.  * Find a suitable default device (the first device not connected to the phone),
  3304.  *  returns device number.
  3305.  *
  3306.  * Returns -1 if no suitable device can be found.
  3307.  */
  3308. static int FindDefaultDevice(aud)
  3309. AFAudioConn *aud;
  3310. {
  3311.   int i;
  3312.   char *ep;
  3313.  
  3314.   if ((ep = getenv("AF_DEVICE")) != NULL) 
  3315.   { int udevice;
  3316.     udevice = atoi(ep);
  3317.     if ((udevice >= 0) && (udevice < ANumberOfAudioDevices(aud)))
  3318.     return udevice;
  3319.   }
  3320.   for(i=0; i<ANumberOfAudioDevices(aud); i++) 
  3321.   {
  3322.     if ( DPHONE(i) == 0 && DCHAN(i) == 1 ) return i;
  3323.   }
  3324.   return -1;
  3325. }
  3326.  
  3327. void XA_No_Audio_Support()
  3328. {
  3329.   fprintf(stderr,"AUDIO SUPPORT NOT COMPILED IN THIS EXECUTABLE.\n");
  3330.   return;
  3331. }
  3332.  
  3333. /********** AF_Audio_Init **********************
  3334.  *****/
  3335. void AF_Audio_Init()
  3336.   DEBUG_LEVEL2 fprintf(stderr,"AF_Audio_Init\n");
  3337.   if (xa_audio_present != XA_AUDIO_UNK) return;
  3338.  
  3339.   /* Open connection. */
  3340.   if ( (AFaud = AFOpenAudioConn("")) == NULL) 
  3341.   {
  3342.       fprintf(stderr, "Could not open connection to AF audio server.\n");
  3343.       fprintf(stderr, "Disabling audio service.\n");
  3344.       /* As long as xa_audio_present isn't OK, audio is effectively disabled*/
  3345.       /* but might as well really disable it */
  3346.       XA_Null_Audio_Setup();
  3347.       xa_audio_present = XA_AUDIO_UNK;
  3348.       return;
  3349.   }
  3350.   AFdevice = FindDefaultDevice(AFaud);
  3351.   AFattributes.type = LIN16;
  3352.   AFattributes.endian = ALittleEndian;
  3353.   AFattributes.play_gain = AF_MAP_TO_C_GAIN(XAAUD->volume);
  3354.   ac = AFCreateAC(AFaud, AFdevice, (ACPlayGain | ACEncodingType | ACEndian), &AFattributes);
  3355.   AFSync(AFaud, 0);     /* Make sure we confirm encoding type support. */
  3356.   if (ac == NULL)
  3357.   {
  3358.     fprintf(stderr,"AF: Could not create audio context for device %d\n",AFdevice);
  3359.     xa_audio_present = XA_AUDIO_ERR;
  3360.     return;
  3361.   }
  3362.  
  3363. DEBUG_LEVEL2 fprintf(stderr,"Created audio context, SR %d device %d\n",
  3364.              DFREQ(AFdevice),AFdevice);
  3365.  
  3366.   /* get default frequency - not really necessary */
  3367.   xa_audio_hard_freq = DFREQ(AFdevice);
  3368.  
  3369.   xa_audio_hard_bps = 2;
  3370.   xa_audio_hard_chans = 1;
  3371.   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
  3372.   xa_audio_hard_type  = XA_AUDIO_SIGNED_2ML;
  3373.  
  3374.   xa_interval_id = 0;
  3375.   xa_audio_present = XA_AUDIO_OK;
  3376.   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
  3377.   Init_Audio_Ring(xa_audio_ring_size,
  3378.             (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
  3379. }
  3380.  
  3381. /********** AF_Audio_Kill **********************
  3382.  *****/
  3383. void AF_Audio_Kill()
  3384. DEBUG_LEVEL2 fprintf(stderr,"AF_Audio_Kill\n");
  3385.  
  3386.   AF_Audio_Off(0);
  3387.   xa_audio_present = XA_AUDIO_UNK;
  3388.  
  3389.   /* XXX */
  3390.   AFCloseAudioConn(AFaud);
  3391.  
  3392.   Kill_Audio_Ring();
  3393. }
  3394.  
  3395. /********** AF_Audio_Off **********************
  3396.  * Stop Audio Stream
  3397.  *
  3398.  *****/
  3399. void AF_Audio_Off(flag)
  3400. xaULONG flag;
  3401.   DEBUG_LEVEL2 fprintf(stderr,"AF_Audio_Off\n");
  3402.   if (xa_audio_status == XA_AUDIO_STOPPED) return;
  3403.  
  3404.   /* XXX */
  3405.  
  3406.   xa_audio_status = XA_AUDIO_STOPPED;
  3407. }
  3408.  
  3409. /********** AF_Audio_On **********************
  3410.  * Turn On Audio Stream.
  3411.  *
  3412.  *****/
  3413. void AF_Audio_On()
  3414. {
  3415.   DEBUG_LEVEL2 fprintf(stderr,"AF_Audio_On \n");
  3416.   if (xa_audio_status == XA_AUDIO_STARTED) return;
  3417.   else if (xa_audio_present != XA_AUDIO_OK) return;
  3418.   else if (xa_snd_cur)
  3419.   { 
  3420.     /* Change Frequency If necessary */
  3421.     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
  3422.     { 
  3423.     /* XXX */
  3424.       xa_audio_hard_freq = xa_snd_cur->hfreq;
  3425.     }
  3426.  
  3427.     /* xa_snd_cur gets changes in Update_Ring() */
  3428.     xa_out_time = 250; /* keep audio fed 250ms ahead of video - could be 500*/
  3429.     xa_out_init = xa_audio_ring_size - 1;
  3430.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  3431.  
  3432.     xa_audio_status = XA_AUDIO_STARTED;
  3433.     XA_Flush_Ring();
  3434.     XA_Update_Ring(1000);
  3435.  
  3436.     AFtime0 = AFbaseT = AFGetTime(ac) + TOFFSET;
  3437.     if (xa_interval_time == 0) xa_interval_time = 1;
  3438.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  3439.     New_Merged_Audio_Output();
  3440.   }
  3441. }
  3442.  
  3443. /*************
  3444.  * flag = 0  turn speaker off
  3445.  * flag = 1  turn speaker on
  3446.  * flag = 2  toggle speaker
  3447.  */
  3448. void AF_Speaker_Toggle(flag)
  3449. xaULONG flag;
  3450.   DEBUG_LEVEL2 fprintf(stderr,"AF_Speaker_Toggle\n");
  3451. }
  3452.  
  3453. void AF_Headphone_Toggle(flag)
  3454. xaULONG flag;
  3455.   DEBUG_LEVEL2 fprintf(stderr,"AF_Headphone_Toggle\n");
  3456. }
  3457.  
  3458. /********** AF_Adjust_Volume **********************
  3459.  * Routine for Adjusting Volume on a AF
  3460.  *
  3461.  *****/
  3462. void AF_Adjust_Volume(volume)
  3463. xaULONG volume;
  3464.  DEBUG_LEVEL2 fprintf(stderr,"AF_Audio_Volume %d\n",volume);
  3465.  
  3466.  /* Client gain settings range from -30 to +30 dB. */
  3467.  AFattributes.play_gain = AF_MAP_TO_C_GAIN(volume);
  3468.  AFChangeACAttributes(ac, ACPlayGain, &AFattributes);
  3469.  AFSync(AFaud,0);
  3470. }
  3471.  
  3472. /********** AF_Closest_Freq **********************
  3473.  *
  3474.  * Global Variable Affect:
  3475.  *   xaULONG xa_audio_hard_buff        must set but not larger than
  3476.  *                    XA_AUDIO_MAX_RING_BUF size
  3477.  */
  3478. xaULONG AF_Closest_Freq(ifreq)
  3479. xaLONG ifreq;
  3480. {
  3481.  return (DFREQ(AFdevice));
  3482. }
  3483.  
  3484. #endif
  3485. /****************************************************************************/
  3486. /******************* END OF AF SPECIFIC ROUTINES ****************************/
  3487. /****************************************************************************/
  3488.  
  3489.  
  3490. /****************************************************************************/
  3491. /**************** DEC Multimedia Services SPECIFIC ROUTINES *****************/
  3492. /****************************************************************************/
  3493. #ifdef XA_MMS_AUDIO
  3494.  
  3495. /*
  3496.  * MMS port provided by Tom Morris (morris@zko.dec.com)
  3497.  */
  3498.  
  3499. void  MMS_Audio_Init();
  3500. void  MMS_Audio_Kill();
  3501. void  MMS_Audio_Off();
  3502. void  MMS_Audio_On();
  3503. void  MMS_Adjust_Volume();
  3504. xaULONG MMS_Closest_Freq();
  3505. void MMS_Speaker_Toggle();
  3506. void MMS_Headphone_Toggle();
  3507.  
  3508. /* Global variables */
  3509.  
  3510. static HWAVEOUT        mms_device_handle = 0;
  3511. static UINT        mms_device_id = 0;
  3512. static xaULONG        mms_device_volume = xaFALSE;
  3513. static LPWAVEHDR    mms_lpWaveHeader;
  3514. static LPSTR        mms_audio_buffer;
  3515. static int        mms_buffers_outstanding = 0;
  3516. static int        mms_next_buffer = 0;
  3517.  
  3518. /********** XA_Audio_Setup **********************
  3519.  *
  3520.  *****/
  3521. void XA_Audio_Setup()
  3522. {
  3523.   XA_Audio_Init        = MMS_Audio_Init;
  3524.   XA_Audio_Kill        = MMS_Audio_Kill;
  3525.   XA_Audio_Off        = MMS_Audio_Off;
  3526.   XA_Audio_On        = MMS_Audio_On;
  3527.   XA_Closest_Freq    = MMS_Closest_Freq;
  3528.   XA_Set_Output_Port    = (void *)(0);
  3529.   XA_Speaker_Tog    = MMS_Speaker_Toggle;
  3530.   XA_Headphone_Tog    = MMS_Headphone_Toggle;
  3531.   XA_LineOut_Tog    = MMS_Headphone_Toggle;
  3532.   XA_Adjust_Volume    = MMS_Adjust_Volume;
  3533.  
  3534.   xa_snd_cur = 0;
  3535.   xa_audio_present = XA_AUDIO_UNK;
  3536.   xa_audio_status  = XA_AUDIO_STOPPED;
  3537.   xa_audio_ring_size  = 8;
  3538. }
  3539.  
  3540. void XA_No_Audio_Support()
  3541. {
  3542.   fprintf(stderr,"AUDIO SUPPORT NOT COMPILED IN THIS EXECUTABLE.\n");
  3543.   return;
  3544. }
  3545.  
  3546. /********** MMS_Audio_Init **********************
  3547.  
  3548.   This just does some generic initialization.  The actual audio
  3549.   output device open is done in the Audio_On routine so that we
  3550.   can get a device which matches the requested sample rate & format
  3551.  
  3552.  *****/
  3553. void MMS_Audio_Init()
  3554. {
  3555.   MMRESULT    status;
  3556.   LPWAVEOUTCAPS    lpCaps;
  3557.  
  3558.   DEBUG_LEVEL2 fprintf(stderr,"MMS_Audio_Init\n");
  3559.   if (xa_audio_present != XA_AUDIO_UNK) return;
  3560.  
  3561.   if( waveOutGetNumDevs() < 1 ) 
  3562.   {
  3563.     xa_audio_present = XA_AUDIO_ERR;
  3564.     fprintf(stderr,"Audio disabled - No Multimedia Services compatible audio devices available\n");
  3565.     return;
  3566.   }
  3567.  
  3568.   /* Figure out device capabilities  - Just use device 0 for now */
  3569.  
  3570.   if((lpCaps = (LPWAVEOUTCAPS)mmeAllocMem(sizeof(WAVEOUTCAPS))) == NULL ) {
  3571.       fprintf(stderr,"Failed to allocate WAVEOUTCAPS struct\n");
  3572.       return;
  3573.   }
  3574.   status = waveOutGetDevCaps( 0, lpCaps, sizeof(WAVEOUTCAPS));
  3575.   if( status != MMSYSERR_NOERROR ) {
  3576.       fprintf(stderr,"waveOutGetDevCaps failed - status = %d\n", status);
  3577.   }
  3578.  
  3579.   /* Multimedia Services will do sample rate & format conversion for
  3580.   ** simpler devices, so just go for the max
  3581.   */
  3582. /* No stereo support currently?
  3583.   xa_audio_hard_type  = XA_AUDIO_SIGNED_2SL;
  3584.   xa_audio_hard_chans = 2;
  3585.   xa_audio_hard_bps = 4;
  3586. */
  3587.  
  3588.   xa_audio_hard_type  = XA_AUDIO_SIGNED_2ML;
  3589.   xa_audio_hard_chans = 1;
  3590.   xa_audio_hard_bps = 2;
  3591.  
  3592.   /* Make sure device gets openend first time through */
  3593.   xa_audio_hard_freq = 0;
  3594.  
  3595.  
  3596.   /* Remember whether the volume control will work */
  3597.   if( lpCaps->dwSupport & WAVECAPS_VOLUME )
  3598.     mms_device_volume = xaTRUE;
  3599.   else
  3600.     mms_device_volume = xaFALSE;
  3601.  
  3602.   mmeFreeMem(lpCaps);
  3603.  
  3604.   /*
  3605.   ** We don't really care what this value is - use something easy
  3606.   */
  3607.   xa_audio_hard_buff  = XA_HARD_BUFF_1K;
  3608.  
  3609.   xa_interval_id = 0;
  3610.   xa_audio_present = XA_AUDIO_OK;
  3611.  
  3612.   /* Register our callback routine to be called whenever there is work */
  3613.   XtAppAddInput(theAudContext,
  3614.         mmeServerFileDescriptor(),
  3615.         (XtPointer)XtInputReadMask,
  3616.         (XtInputCallbackProc)mmeProcessCallbacks,
  3617.         0);
  3618.  
  3619.   Init_Audio_Ring(xa_audio_ring_size,
  3620.             (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
  3621. }
  3622.  
  3623. /********** MMS_Audio_Kill **********************
  3624.  *****/
  3625. void MMS_Audio_Kill()
  3626. {
  3627.   MMRESULT status;
  3628.   DEBUG_LEVEL2 fprintf(stderr,"MMS_Audio_Kill\n");
  3629.  
  3630.   MMS_Audio_Off(0);
  3631.   xa_audio_present = XA_AUDIO_UNK;
  3632.  
  3633.   status = waveOutReset(mms_device_handle);
  3634.   if( status != MMSYSERR_NOERROR ) {
  3635.       fprintf(stderr,"waveOutReset failed - status = %d\n", status);
  3636.   }
  3637.   status = waveOutClose(mms_device_handle);
  3638.   if( status != MMSYSERR_NOERROR ) {
  3639.       fprintf(stderr,"waveOutClose failed - status = %d\n", status);
  3640.   }
  3641.  
  3642.   mmeFreeBuffer(mms_audio_buffer);
  3643.   mmeFreeMem(mms_lpWaveHeader);
  3644.  
  3645.   Kill_Audio_Ring();
  3646. }
  3647.  
  3648. /********** MMS_Audio_Off **********************
  3649.  * Stop Audio Stream
  3650.  *
  3651.  *****/
  3652. void MMS_Audio_Off(flag)
  3653. xaULONG flag;
  3654. {
  3655.   DEBUG_LEVEL2 fprintf(stderr,"MMS_Audio_Off\n");
  3656.   if (xa_audio_status == XA_AUDIO_STOPPED) return;
  3657.  
  3658.   /* Just set our flag and let things drain */
  3659.   /* we could use waveOutReset if we were in a hurry */
  3660.   xa_audio_status = XA_AUDIO_STOPPED;
  3661. }
  3662.  
  3663. /********** MMS_Audio_On **********************
  3664.  * Turn On Audio Stream.
  3665.  *
  3666.  *****/
  3667. /*POD TEMP
  3668. static void MMS_wave_callback(HANDLE hWaveOut,
  3669.                   UINT wMsg,
  3670.                   DWORD dwInstance,
  3671.                   LPARAM lParam1,
  3672.                   LPARAM lParam2)
  3673. */
  3674. static void MMS_wave_callback(hWaveOut,wMsg,dwInstance,lParam1,lParam2)
  3675. HANDLE hWaveOut;
  3676. UINT wMsg;
  3677. DWORD dwInstance;
  3678. LPARAM lParam1;
  3679. LPARAM lParam2;
  3680. {
  3681.     switch(wMsg)
  3682.       {
  3683.       case WOM_OPEN:
  3684.       case WOM_CLOSE: {
  3685.           /* Ignore these */
  3686.           break;
  3687.       }
  3688.       case WOM_DONE: {
  3689.           LPWAVEHDR lpwh = (LPWAVEHDR)lParam1;
  3690.           mms_buffers_outstanding--;
  3691.           break;
  3692.       }
  3693.       default: {
  3694.           fprintf(stderr,
  3695.               "Unknown MMS waveOut callback messages receieved.\n");
  3696.           break;
  3697.       }
  3698.       }
  3699. }
  3700.  
  3701. void MMS_Audio_On()
  3702. {
  3703.   MMRESULT status;
  3704.   LPPCMWAVEFORMAT lpWaveFormat;
  3705.  
  3706.   DEBUG_LEVEL2 fprintf(stderr,"MMS_Audio_On \n");
  3707.   if (xa_audio_status == XA_AUDIO_STARTED) return;
  3708.   else if (xa_audio_present != XA_AUDIO_OK) return;
  3709.   else if (xa_snd_cur)
  3710.   {
  3711.     /* Close & Reopen device if necessary */
  3712.     if (xa_audio_hard_freq != xa_snd_cur->hfreq )
  3713.     {
  3714.     if( mms_device_handle != 0 ) {
  3715.         status = waveOutReset(mms_device_handle);
  3716.         if( status != MMSYSERR_NOERROR ) {
  3717.         fprintf(stderr,"waveOutReset failed - status = %d\n", status);
  3718.         }
  3719.         status = waveOutClose(mms_device_handle);
  3720.         if( status != MMSYSERR_NOERROR ) {
  3721.         fprintf(stderr,"waveOutClose failed - status = %d\n", status);
  3722.         }
  3723.     }
  3724.     if((lpWaveFormat = (LPPCMWAVEFORMAT)
  3725.             mmeAllocMem(sizeof(PCMWAVEFORMAT))) == NULL ) 
  3726.     {
  3727.         fprintf(stderr,"Failed to allocate PCMWAVEFORMAT struct\n");
  3728.         return;
  3729.     }
  3730.     lpWaveFormat->wf.nSamplesPerSec = xa_snd_cur->hfreq;
  3731.  
  3732.     lpWaveFormat->wf.nChannels = xa_audio_hard_chans;
  3733.     lpWaveFormat->wBitsPerSample = xa_audio_hard_bps*8/xa_audio_hard_chans;
  3734.     if( xa_audio_hard_type == XA_AUDIO_SUN_AU )
  3735.       lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_MULAW;
  3736.     else if((xa_audio_hard_type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_SIGNED ||
  3737.         (xa_audio_hard_type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_LINEAR )
  3738.       lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
  3739.     else {
  3740.         fprintf(stderr,"Unsupported audio format\n");
  3741.         return;
  3742.     }
  3743.  
  3744.     /* The audio format to convert to has already been picked based on what
  3745.        we said the hardware capabilities were, so don't change now or we'll
  3746.        confuse everyone.  If we were going to take maximum advantage of the
  3747.        MMS & hardware capabilities, we'd do it something like this:
  3748.     */
  3749. #if 0
  3750.     if (xa_audio_hard_freq != xa_snd_cur->hfreq ||
  3751.         xa_audio_hard_type != xa_snd_cur->type );
  3752.      
  3753.     if( xa_snd_cur->type & XA_AUDIO_STEREO_MSK )
  3754.       lpWaveFormat->wf.nChannels = 2;
  3755.     else
  3756.       lpWaveFormat->wf.nChannels = 1;
  3757.     if( xa_snd_cur->type & XA_AUDIO_BPS_2_MSK )
  3758.       lpWaveFormat->wBitsPerSample = 16;
  3759.     else
  3760.       lpWaveFormat->wBitsPerSample = 8;
  3761.     if( (xa_snd_cur->type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_SUN_AU )
  3762.       lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_MULAW;
  3763.     else if(   (xa_snd_cur->type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_SIGNED 
  3764.         || (xa_snd_cur->type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_LINEAR )
  3765.       lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
  3766.     else if( (xa_snd_cur->type & XA_AUDIO_TYPE_MASK) == XA_AUDIO_ADPCM)
  3767.       lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_IMA_ADPCM;
  3768.     else {
  3769.         fprintf(stderr,"Unsupported audio format\n");
  3770.         return;
  3771.     }
  3772. #endif
  3773.  
  3774.     lpWaveFormat->wf.nBlockAlign = lpWaveFormat->wf.nChannels *
  3775.                                    ((lpWaveFormat->wBitsPerSample+7)/8);
  3776.     lpWaveFormat->wf.nAvgBytesPerSec = lpWaveFormat->wf.nBlockAlign *
  3777.                         lpWaveFormat->wf.nSamplesPerSec;
  3778.  
  3779.     /* Open the audio device in the appropriate rate/format */
  3780.     mms_device_handle = 0;
  3781.     status = waveOutOpen( &mms_device_handle,
  3782.                  WAVE_MAPPER,
  3783.                  (LPWAVEFORMAT)lpWaveFormat,
  3784.                  MMS_wave_callback,
  3785.                  NULL,
  3786.                  CALLBACK_FUNCTION | WAVE_OPEN_SHAREABLE );
  3787.     if( status != MMSYSERR_NOERROR ) {
  3788.         fprintf(stderr,"waveOutOpen failed - status = %d\n", status);
  3789.     }
  3790.  
  3791.     /* Get & save the device ID for volume control */
  3792.     status = waveOutGetID( mms_device_handle, &mms_device_id );
  3793.     if( status != MMSYSERR_NOERROR ) {
  3794.         fprintf(stderr,"waveOutGetID failed - status = %d\n", status);
  3795.     }
  3796.  
  3797.     DEBUG_LEVEL2 fprintf(stderr,"Opened waveOut device #%d \n",
  3798.         mms_device_id);
  3799.     DEBUG_LEVEL2 fprintf(stderr,
  3800.                  "Format=%d, Rate=%d, channels=%d, bps=%d \n",
  3801.                  lpWaveFormat->wf.wFormatTag,
  3802.                  lpWaveFormat->wf.nSamplesPerSec,
  3803.                  lpWaveFormat->wf.nChannels,
  3804.                  lpWaveFormat->wBitsPerSample );
  3805.  
  3806.     mmeFreeMem(lpWaveFormat);
  3807.  
  3808.     /* Allocate wave header for use in write */
  3809.     if((mms_lpWaveHeader = (LPWAVEHDR)
  3810.                 mmeAllocMem(sizeof(WAVEHDR))) == NULL ) 
  3811.     {
  3812.         fprintf(stderr,"Failed to allocate WAVEHDR struct\n");
  3813.         return;
  3814.     }
  3815.  
  3816.     /* Allocate shared audio buffer for communicating with audio device */
  3817.     /* NOTE: It's just a matter of convenience that it's the same size  */
  3818.     /*    as  XAnim's audio ring buffer - don't confuse the two        */
  3819.     if ( (mms_audio_buffer = (LPSTR)
  3820.           mmeAllocBuffer(xa_audio_hard_buff*xa_audio_ring_size )) == NULL)
  3821.         {
  3822.       fprintf(stderr,"Failed to allocate shared audio buffer\n");
  3823.       return;
  3824.     }
  3825.  
  3826.     /* Save current hardware settings */
  3827.     xa_audio_hard_freq = xa_snd_cur->hfreq;
  3828.     xa_audio_hard_type = xa_snd_cur->type;
  3829.     }
  3830.  
  3831.     /* These values are all cut & paste from other devices - hope they got
  3832.        them right there! - tfm */
  3833.     xa_out_time = 100;
  3834.     xa_out_init = xa_audio_ring_size - 1;
  3835.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  3836.  
  3837.     xa_audio_status = XA_AUDIO_STARTED;
  3838.     XA_Flush_Ring();
  3839.     XA_Update_Ring(1000);
  3840.  
  3841.     /* initialize time base */
  3842.     if (xa_interval_time == 0) xa_interval_time = 1;
  3843.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  3844.     New_Merged_Audio_Output();
  3845.   }
  3846. }
  3847.  
  3848. /********** MMS_Closest_Freq **********************************************
  3849.  *
  3850.  * Global Variable Affect:
  3851.  *   xaULONG xa_audio_hard_buff        must set but not larger than
  3852.  *                    XA_AUDIO_MAX_RING_BUF size
  3853.  ****************************************************************************/
  3854. xaULONG MMS_Closest_Freq(ifreq)
  3855. xaLONG ifreq;
  3856. {
  3857.   xa_audio_hard_buff = XA_HARD_BUFF_1K;
  3858.  
  3859.   /* Query our audio devices to see what sample rates are supported */
  3860.  
  3861.   if (xa_audio_hard_type == XA_AUDIO_SIGNED_2ML)
  3862.   { static int valid[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000, 0};
  3863.     xaLONG i = 0;
  3864.     xaLONG best = valid[0];
  3865.  
  3866.     while(valid[i])
  3867.     {
  3868.       if (xaABS(valid[i] - ifreq) < xaABS(best - ifreq)) best = valid[i];
  3869.       i++;
  3870.     }
  3871.  
  3872.     return(best);
  3873.   }
  3874.   else return(8000);
  3875. }
  3876.  
  3877. /* Select the appropriate output port */
  3878.  
  3879. void MMS_Set_Output_Port(aud_ports)
  3880. xaULONG aud_ports;
  3881. {
  3882.   MMRESULT status;
  3883.   DWORD ports = 0;
  3884. /* dummy definitions to support pseudo code below - needs to be fixed - tfm */
  3885.   int device_type = 0;
  3886. #define J300 0
  3887. #define BBA 1
  3888.  
  3889.   if (aud_ports & XA_AUDIO_PORT_INT &&
  3890.       device_type == BBA )
  3891.     ports |= MME_PORTMASK_02;
  3892.   if (aud_ports & XA_AUDIO_PORT_HEAD) {
  3893.       if(device_type = BBA)
  3894.     ports |= MME_PORTMASK_02;
  3895.       if(device_type = J300)
  3896.     ports |= MME_PORTMASK_01;
  3897.   }
  3898.   if (aud_ports & XA_AUDIO_PORT_EXT &&
  3899.       device_type == J300)
  3900.     ports |= MME_PORTMASK_02;
  3901.  
  3902.   status = waveOutSelectPorts(mms_device_id,ports);
  3903.   if( status != MMSYSERR_NOERROR ) {
  3904.       fprintf(stderr,"waveOutSelectPorts failed - status = %d\n", status); }
  3905. }
  3906.  
  3907.  
  3908.  
  3909. /*************
  3910.  * flag = 0  turn speaker off
  3911.  * flag = 1  turn speaker on
  3912.  * flag = 2  toggle speaker
  3913.  */
  3914. void MMS_Speaker_Toggle(flag)
  3915. xaULONG flag;
  3916. {
  3917.   DEBUG_LEVEL2 fprintf(stderr,"MMS_Speaker_Toggle\n");
  3918. }
  3919.  
  3920. void MMS_Headphone_Toggle(flag)
  3921. xaULONG flag;
  3922. {
  3923.   DEBUG_LEVEL2 fprintf(stderr,"MMS_Headphone_Toggle\n");
  3924. }
  3925.  
  3926. /********** MMS_Adjust_Volume **********************
  3927.  * Routine for adjusting output volume
  3928.  *
  3929.  * NOTE: It isn't really a good idea to do this on a per application
  3930.  *       basis, particularly at startup where we are going to override
  3931.  *       the value the user has set up
  3932.  *     I've left this disabled for now
  3933.  *
  3934.  * POD NOTE: once xanim leaves default volume alone at startup, remember
  3935.  *           to renable this.
  3936.  *****/
  3937. void MMS_Adjust_Volume(volume)
  3938. xaULONG volume;
  3939. {
  3940.  DWORD vol;
  3941.  DEBUG_LEVEL2 fprintf(stderr,"MMS_Audio_Volume %d\n",volume);
  3942.  
  3943.  vol = (0xFFFF * volume) / 100;    /* convert to 16 bit scale */
  3944.  vol = (vol << 16) | vol;    /* duplicate for left & right channels */
  3945.  
  3946. #ifdef MMS_VOL
  3947.  waveOutSetVolume(mms_device_id, vol);
  3948. #endif
  3949.  
  3950. }
  3951.  
  3952. #endif
  3953. /****************************************************************************/
  3954. /************************* END OF MMS SPECIFIC ROUTINES *********************/
  3955. /****************************************************************************/
  3956.  
  3957. /****************************************************************************/
  3958. /**************** NAS SPECIFIC ROUTINES *************************************/
  3959. /****************************************************************************/
  3960. #ifdef XA_NAS_AUDIO
  3961.  
  3962. /*
  3963.  * NAS port provided by Bob Phillips,
  3964.  *    bobp@syl.nj.nec.com
  3965.  * Adapted from AF port by Tom Levergood
  3966.  * Wednesday October 26, 1994
  3967.  *
  3968.  * Re-written by Greg Renda (greg@ncd.com) 5/10/95
  3969.  */
  3970.   
  3971. static void        NAS_Audio_Init();
  3972. static void        NAS_Audio_Kill();
  3973. static void        NAS_Audio_Off();
  3974. static void        NAS_Audio_On();
  3975. static void        NAS_Adjust_Volume();
  3976. static xaULONG        NAS_Closest_Freq();
  3977. static void        NAS_Speaker_Toggle();
  3978. static void        NAS_Headphone_Toggle();
  3979.  
  3980. static xaULONG        NAS_pod_flag = 0;
  3981.  
  3982. typedef struct _NASChunk
  3983. {
  3984.     xaUBYTE          *buf;
  3985.     xaULONG           len,
  3986.                     offset;
  3987.     struct _NASChunk *next;
  3988. }               NASChunk, *NASChunkPtr;
  3989.  
  3990. typedef struct
  3991. {
  3992.     AuServer       *aud;
  3993.     AuFlowID        flow;
  3994.     AuDeviceID      device;
  3995.     NASChunkPtr     head,
  3996.                     tail;
  3997.     xaULONG           bytes;
  3998.     AuDeviceAttributes *da;
  3999.     AuEventHandlerRec *handler;
  4000.     AuBool flowRunning;
  4001. }               NASInfo, *NASInfoPtr;
  4002.  
  4003. static NASInfo  nas;
  4004.  
  4005. static AuBool
  4006. NAS_Event_Handler(aud, ev, handler)
  4007. AuServer       *aud;
  4008. AuEvent        *ev;
  4009. AuEventHandlerRec *handler;
  4010. {
  4011.     NASInfoPtr      np = (NASInfoPtr) handler->data;
  4012.  
  4013.     switch (ev->type)
  4014.     {
  4015.     case AuEventTypeElementNotify:
  4016.         {
  4017.         AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
  4018.  
  4019.         switch (event->kind)
  4020.         {
  4021.             case AuElementNotifyKindLowWater:
  4022.             np->bytes += event->num_bytes;
  4023.             break;
  4024.             case AuElementNotifyKindState:
  4025.             switch (event->cur_state)
  4026.             {
  4027.                 case AuStatePause:
  4028.                 if (event->reason != AuReasonUser)
  4029.                     np->bytes += event->num_bytes;
  4030.                 break;
  4031.                 case AuStateStop:
  4032.                 np->flowRunning = AuFalse;
  4033.                 break;
  4034.             }
  4035.         }
  4036.         }
  4037.     }
  4038.  
  4039.     return AuTrue;
  4040. }
  4041.  
  4042. static void
  4043. NAS_Audio_Init()
  4044. {
  4045.     char           *errmsg;
  4046.     int             i;
  4047.  
  4048.     DEBUG_LEVEL2    fprintf(stdout, "NAS_Audio_Init\n");
  4049.  
  4050.     if (xa_audio_present != XA_AUDIO_UNK)
  4051.     return;
  4052.  
  4053.     /* Open connection. */
  4054.     if (!(nas.aud = AuOpenServer(NULL, 0, NULL, 0, NULL, &errmsg)))
  4055.     {
  4056.     fprintf(stderr, "Could not open connection to NAS audio server.\n");
  4057.     fprintf(stderr, "Error is \"%s\".\n", errmsg);
  4058.     fprintf(stderr, "Disabling audio service.\n");
  4059.     /*
  4060.      * As long as xa_audio_present isn't OK, audio is effectively
  4061.      * disabled
  4062.      */
  4063.     /* but might as well really disable it */
  4064.     AuFree(errmsg);
  4065.     XA_Null_Audio_Setup();
  4066.     xa_audio_present = XA_AUDIO_UNK;
  4067.     return;
  4068.     }
  4069.  
  4070.     /* look for an output device */
  4071.     for (i = 0; i < AuServerNumDevices(nas.aud); i++)
  4072.     if ((AuDeviceKind(AuServerDevice(nas.aud, i)) ==
  4073.          AuComponentKindPhysicalOutput) &&
  4074.         AuDeviceNumTracks(AuServerDevice(nas.aud, i)) == 1)
  4075.     {
  4076.         nas.device = AuDeviceIdentifier(AuServerDevice(nas.aud, i));
  4077.         nas.da = AuServerDevice(nas.aud, i);
  4078.         break;
  4079.     }
  4080.  
  4081.     if (i == AuServerNumDevices(nas.aud))
  4082.     {
  4083.     fprintf(stderr, "NAS: Couldn't find an appropriate output device\n");
  4084.     XA_Null_Audio_Setup();
  4085.     xa_audio_present = XA_AUDIO_UNK;
  4086.     return;
  4087.     }
  4088.  
  4089.     if (!(nas.flow = AuCreateFlow(nas.aud, NULL)))
  4090.     {
  4091.     fprintf(stderr, "NAS: Couldn't create flow\n");
  4092.     XA_Null_Audio_Setup();
  4093.     xa_audio_present = XA_AUDIO_UNK;
  4094.     return;
  4095.     }
  4096.  
  4097.     nas.handler = AuRegisterEventHandler(nas.aud, AuEventHandlerIDMask, 0,
  4098.                      nas.flow, NAS_Event_Handler,
  4099.                      (AuPointer) &nas);
  4100.  
  4101.     xa_audio_present = XA_AUDIO_OK;
  4102.     xa_audio_hard_type = XA_AUDIO_SIGNED_2MB;
  4103.     xa_audio_hard_bps = 2;
  4104.     xa_audio_hard_chans = 1;
  4105.     NAS_pod_flag = 0;
  4106.     Init_Audio_Ring(xa_audio_ring_size,
  4107.             (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps));
  4108. }
  4109.  
  4110. static void
  4111. NAS_Audio_Kill()
  4112. {
  4113.     DEBUG_LEVEL2    fprintf(stdout, "NAS_Audio_Kill\n");
  4114.  
  4115.     NAS_Audio_Off(0);
  4116.     xa_audio_present = XA_AUDIO_UNK;
  4117.  
  4118.     AuUnregisterEventHandler(nas.aud, nas.handler);
  4119.     AuCloseServer(nas.aud);
  4120.  
  4121.     Kill_Audio_Ring();
  4122. }
  4123.  
  4124.  
  4125. static void
  4126. NAS_Audio_Off(flag)
  4127. xaULONG           flag;
  4128. {
  4129.     NASChunkPtr     p = nas.head,
  4130.                     next;
  4131.  
  4132.     if (NAS_pod_flag) return; NAS_pod_flag = 1; /* POD TEST */
  4133.  
  4134.     DEBUG_LEVEL2    fprintf(stdout, "NAS_Audio_Off\n");
  4135.  
  4136.     if (!nas.flowRunning && xa_audio_status != XA_AUDIO_STARTED)
  4137.     return;
  4138. /* POD new */
  4139.     xa_audio_status = XA_AUDIO_STOPPED;
  4140.  
  4141.     AuStopFlow(nas.aud, nas.flow, NULL);
  4142.  
  4143.     while (nas.flowRunning == AuTrue) AuHandleEvents(nas.aud);
  4144.  
  4145.     while (p)
  4146.     {
  4147.     next = p->next;
  4148.     free(p->buf);
  4149.     free(p);
  4150.     p = next;
  4151.     }
  4152.  
  4153.     nas.head = nas.tail = NULL;
  4154.  
  4155.     /* SET FLAG TO STOP OUTPUT ROUTINE */
  4156. /* POD Was
  4157.     xa_audio_status = XA_AUDIO_STOPPED;
  4158. */
  4159.  
  4160.     xa_time_audio = -1;
  4161.     xa_audio_flushed = 0;
  4162.  
  4163.     NAS_pod_flag = 0; /* POD TEST */
  4164. }
  4165.  
  4166. static void
  4167. NAS_Audio_On()
  4168. {
  4169.     if (NAS_pod_flag) return; NAS_pod_flag = 1; /* POD TEST */
  4170.  
  4171.     DEBUG_LEVEL2    fprintf(stdout, "NAS_Audio_On \n");
  4172.  
  4173.     if ( (xa_audio_status == XA_AUDIO_STARTED) ||
  4174.      (xa_audio_present != XA_AUDIO_OK) || (!xa_snd_cur) )
  4175.     return;
  4176.  
  4177.     if (nas.flowRunning == AuTrue) NAS_Audio_Off(0);
  4178.  
  4179. #define NASBufSize 30000
  4180.     /* Change Frequency If necessary */
  4181.     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
  4182.     {
  4183.     AuElement       elements[3];
  4184.  
  4185.     AuMakeElementImportClient(&elements[0], xa_snd_cur->hfreq,
  4186.                   AuFormatLinearSigned16MSB,
  4187.                   1, AuTrue, NASBufSize,
  4188.                   NASBufSize / 4 * 3, 0, NULL);
  4189.     AuMakeElementMultiplyConstant(&elements[1], 0,
  4190.                       AuFixedPointFromFraction(100, 100));
  4191.     AuMakeElementExportDevice(&elements[2], 1, nas.device,
  4192.                   xa_snd_cur->hfreq, AuUnlimitedSamples,
  4193.                   0, NULL);
  4194.  
  4195.     AuSetElements(nas.aud, nas.flow, AuTrue, 3, elements, NULL);
  4196.  
  4197.     xa_audio_hard_freq = xa_snd_cur->hfreq;
  4198.     }
  4199.  
  4200.     nas.bytes = 0;
  4201.     AuStartFlow(nas.aud, nas.flow, NULL);
  4202.     nas.flowRunning = AuTrue;
  4203.  
  4204.     /* xa_snd_cur gets changes in Update_Ring() */
  4205.     /* FINE TUNED from 4 to 20 */
  4206.     xa_out_time = 250;                   /* keep audio fed XXms ahead
  4207.                             * of video - could be 500 */
  4208.     xa_out_init = xa_audio_ring_size - 1;
  4209.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  4210.  
  4211.     xa_audio_status = XA_AUDIO_STARTED;
  4212.     XA_Flush_Ring();
  4213.     XA_Update_Ring(1000);
  4214.  
  4215.     if (xa_interval_time == 0)
  4216.     xa_interval_time = 1;
  4217.     xa_time_now = XA_Read_AV_Time();           /* get new time */
  4218.     New_Merged_Audio_Output();
  4219.     NAS_pod_flag = 0; /* POD TEST */
  4220. }
  4221.  
  4222. static void
  4223. NAS_Toggle_OutputMode(flag, mode)
  4224. xaULONG flag, mode;
  4225. {
  4226.     if (!(AuDeviceChangableMask(nas.da) & AuCompDeviceOutputModeMask))
  4227.     return;
  4228.  
  4229.     switch(flag)
  4230.     {
  4231.     case 0:
  4232.         AuDeviceOutputMode(nas.da) &= ~mode;
  4233.         break;
  4234.     case 1:
  4235.         AuDeviceOutputMode(nas.da) |= mode;
  4236.         break;
  4237.       case 2:
  4238.         AuDeviceOutputMode(nas.da) ^= mode;
  4239.         break;
  4240.     }
  4241.  
  4242.     AuSetDeviceAttributes(nas.aud, AuDeviceIdentifier(nas.da),
  4243.               AuCompDeviceOutputModeMask, nas.da, NULL);
  4244.     AuFlush(nas.aud);
  4245. }
  4246.  
  4247. /*************
  4248.  * flag = 0  turn speaker off
  4249.  * flag = 1  turn speaker on
  4250.  * flag = 2  toggle speaker
  4251.  */
  4252. static void
  4253. NAS_Speaker_Toggle(flag)
  4254. xaULONG           flag;
  4255. {
  4256.     DEBUG_LEVEL2    fprintf(stdout, "NAS_Speaker_Toggle\n");
  4257.     NAS_Toggle_OutputMode(flag, AuDeviceOutputModeSpeaker);
  4258. }
  4259.  
  4260. static void
  4261. NAS_Headphone_Toggle(flag)
  4262. xaULONG           flag;
  4263. {
  4264.     DEBUG_LEVEL2    fprintf(stdout, "NAS_Headphone_Toggle\n");
  4265.     NAS_Toggle_OutputMode(flag, AuDeviceOutputModeHeadphone);
  4266. }
  4267.  
  4268.  
  4269. /********** NAS_Adjust_Volume **********************
  4270.  * Routine for Adjusting Volume on NAS
  4271.  *
  4272.  *****/
  4273. static void
  4274. NAS_Adjust_Volume(volume)
  4275. xaULONG           volume;
  4276. {
  4277.     AuElementParameters parms;
  4278.  
  4279.     DEBUG_LEVEL2    fprintf(stdout, "NAS_Audio_Volume %d\n", volume);
  4280.     parms.flow = nas.flow;
  4281.     parms.element_num = 1;
  4282.     parms.num_parameters = AuParmsMultiplyConstant;
  4283.     parms.parameters[AuParmsMultiplyConstantConstant] =
  4284.     AuFixedPointFromFraction(volume, 100);
  4285.     AuSetElementParameters(nas.aud, 1, &parms, NULL);
  4286.     AuFlush(nas.aud);
  4287. }
  4288.  
  4289. /********** NAS_Closest_Freq **********************
  4290.  *
  4291.  * Global Variable Affect:
  4292.  *   xaULONG xa_audio_hard_buff        must set but not larger than
  4293.  *                    XA_AUDIO_MAX_RING_BUF size
  4294.  */
  4295. static xaULONG
  4296. NAS_Closest_Freq(ifreq)
  4297. xaLONG            ifreq;
  4298. {
  4299.     xa_audio_hard_buff = XA_AUDIO_MAX_RING_BUFF;
  4300.     return ifreq;
  4301. }
  4302.  
  4303. static void
  4304. NAS_Write_Data(buf, len)
  4305. xaUBYTE          *buf;
  4306. xaULONG           len;
  4307. {
  4308.     NASChunkPtr     p;
  4309.  
  4310.     if (!(p = (NASChunkPtr) malloc(sizeof(NASChunk))))
  4311.     return;
  4312.  
  4313.     if (!(p->buf = (xaUBYTE *) malloc(len)))
  4314.     {
  4315.     free(p);
  4316.     return;
  4317.     }
  4318.  
  4319.     memcpy((char *) p->buf, (char *) buf, (int) len);
  4320.     p->len = len;
  4321.     p->offset = 0;
  4322.     p->next = NULL;
  4323.  
  4324.     if (nas.tail)
  4325.     {
  4326.     nas.tail->next = p;
  4327.     nas.tail = p;
  4328.     }
  4329.     else
  4330.     nas.head = nas.tail = p;
  4331.  
  4332.     AuHandleEvents(nas.aud);
  4333.  
  4334.     while (nas.head && nas.bytes && (xa_audio_status == XA_AUDIO_STARTED) )
  4335.     {
  4336.     int             n = xaMIN(nas.bytes, nas.head->len);
  4337.     AuWriteElement(nas.aud, nas.flow, 0, n,
  4338.                nas.head->buf + nas.head->offset, AuFalse, NULL);
  4339.  
  4340.     nas.bytes -= n;
  4341.     nas.head->len -= n;
  4342.     nas.head->offset += n;
  4343.  
  4344.     if (!nas.head->len)
  4345.     {
  4346.         NASChunkPtr     next = nas.head->next;
  4347.  
  4348.         free(nas.head->buf);
  4349.         free(nas.head);
  4350.  
  4351.         if (!(nas.head = next))
  4352.         nas.tail = nas.head;
  4353.     }
  4354.  
  4355.     AuHandleEvents(nas.aud);
  4356.     }
  4357. }
  4358.  
  4359. void
  4360. XA_Audio_Setup()
  4361. {
  4362.     DEBUG_LEVEL2    fprintf(stdout, "XA_Audio_Setup()\n");
  4363.     XA_Audio_Init = NAS_Audio_Init;
  4364.     XA_Audio_Kill = NAS_Audio_Kill;
  4365.     XA_Audio_Off = NAS_Audio_Off;
  4366.     XA_Audio_On = NAS_Audio_On;
  4367.     XA_Closest_Freq = NAS_Closest_Freq;
  4368.     XA_Set_Output_Port = (void *) (0);
  4369.     XA_Speaker_Tog = NAS_Speaker_Toggle;
  4370.     XA_Headphone_Tog = NAS_Headphone_Toggle;
  4371.     XA_LineOut_Tog = NAS_Headphone_Toggle;
  4372.     XA_Adjust_Volume = NAS_Adjust_Volume;
  4373.  
  4374.     xa_snd_cur = 0;
  4375.     xa_audio_present = XA_AUDIO_UNK;
  4376.     xa_audio_status = XA_AUDIO_STOPPED;
  4377.     xa_audio_ring_size = 8;
  4378. }
  4379.  
  4380. #endif
  4381. /****************************************************************************/
  4382. /******************* END OF NAS SPECIFIC ROUTINES ***************************/
  4383. /****************************************************************************/
  4384.  
  4385.  
  4386. /****************************************************************************/
  4387. /**************** NetBSD SPECIFIC ROUTINES **********************************/
  4388. /****************************************************************************/
  4389.  
  4390. /*
  4391.  * NetBSD port provided by Roland C Dowdeswell
  4392.  * roland@imrryr.org
  4393.  * Heavily stolen from the Sparc port (like the others)
  4394.  * Tuesday 9/May 1995 -- very early -- still dark.
  4395.  */
  4396.  
  4397. #ifdef XA_NetBSD_AUDIO
  4398.  
  4399. void  NetBSD_Audio_Init();
  4400. void  NetBSD_Audio_Kill();
  4401. void  NetBSD_Audio_Off();
  4402. void  NetBSD_Audio_On();
  4403. void  NetBSD_Adjust_Volume();
  4404. xaULONG NetBSD_Closest_Freq();
  4405. void NetBSD_Set_Output_Port();
  4406. void NetBSD_Speaker_Toggle();
  4407. void NetBSD_Headphone_Toggle();
  4408.  
  4409. #define NetBSD_MAX_VOL AUDIO_MAX_GAIN
  4410. #define NetBSD_MIN_VOL AUDIO_MIN_GAIN
  4411.  
  4412. static int devAudio;
  4413.  
  4414. /********** XA_Audio_Setup **********************
  4415.  * 
  4416.  * Also defines NetBSD Specific variables.
  4417.  *
  4418.  *****/
  4419. void XA_Audio_Setup()
  4420. {
  4421.   XA_Audio_Init        = NetBSD_Audio_Init;
  4422.   XA_Audio_Kill        = NetBSD_Audio_Kill;
  4423.   XA_Audio_Off        = NetBSD_Audio_Off;
  4424.   XA_Audio_On        = NetBSD_Audio_On;
  4425.   XA_Closest_Freq    = NetBSD_Closest_Freq;
  4426.   XA_Set_Output_Port    = NetBSD_Set_Output_Port;
  4427.   XA_Speaker_Tog    = NetBSD_Speaker_Toggle;
  4428.   XA_Headphone_Tog    = NetBSD_Headphone_Toggle;
  4429.   XA_LineOut_Tog    = NetBSD_Headphone_Toggle;
  4430.   XA_Adjust_Volume    = NetBSD_Adjust_Volume;
  4431.  
  4432.   xa_snd_cur = 0;
  4433.   xa_audio_present = XA_AUDIO_UNK;
  4434.   xa_audio_status  = XA_AUDIO_STOPPED;
  4435.   xa_audio_ring_size  = 8;
  4436. }
  4437.  
  4438.  
  4439. /********** NetBSD_Audio_Init **********************
  4440.  * Open /dev/audio and NetBSD.
  4441.  *
  4442.  *****/
  4443. void NetBSD_Audio_Init()
  4444. { int ret;
  4445.   int type;
  4446.   audio_info_t a_info;
  4447.   DEBUG_LEVEL2 fprintf(stderr,"NetBSD_Audio_Init\n");
  4448.   if (xa_audio_present != XA_AUDIO_UNK) return;
  4449.   devAudio = open("/dev/audio", O_WRONLY | O_NDELAY);
  4450.   if (devAudio == -1)
  4451.   {
  4452.     if (errno == EBUSY) fprintf(stderr,"Audio_Init: Audio device is busy. - ");
  4453.     else fprintf(stderr,"Audio_Init: Error opening audio device. - ");
  4454.     fprintf(stderr,"Will continue without audio\n");
  4455.     xa_audio_present = XA_AUDIO_ERR;
  4456.     return;
  4457.   }
  4458.  
  4459.   DEBUG_LEVEL1 fprintf(stderr,"NetBSD AUDIO\n");
  4460.  
  4461.   AUDIO_INITINFO(&a_info);
  4462.   a_info.blocksize = 1024;
  4463.   ioctl(devAudio, AUDIO_SETINFO, &a_info);
  4464.   AUDIO_INITINFO(&a_info);
  4465.   a_info.play.encoding = AUDIO_ENCODING_PCM16;
  4466.   ioctl(devAudio, AUDIO_SETINFO, &a_info);
  4467.   AUDIO_INITINFO(&a_info);
  4468.   a_info.mode = AUMODE_PLAY | AUMODE_PLAY_ALL;
  4469.   ioctl(devAudio, AUDIO_SETINFO, &a_info);
  4470.   AUDIO_INITINFO(&a_info);
  4471.   a_info.play.precision = 16;
  4472.   ioctl(devAudio, AUDIO_SETINFO, &a_info);
  4473.   AUDIO_INITINFO(&a_info);
  4474.   a_info.play.sample_rate = 11025;
  4475.   ioctl(devAudio, AUDIO_SETINFO, &a_info);
  4476.   ioctl(devAudio, AUDIO_GETINFO, &a_info);
  4477.  
  4478.   xa_audio_hard_type  = (a_info.play.precision==8)?XA_AUDIO_LINEAR_1M
  4479.                           :XA_AUDIO_SIGNED_2ML;
  4480.   xa_audio_hard_freq  = a_info.play.sample_rate;
  4481.   xa_audio_hard_buff  = a_info.blocksize;
  4482.   xa_audio_hard_bps   = (a_info.play.precision==8)?1:2;
  4483.   xa_audio_hard_chans = 1;
  4484.   Gen_Ulaw_2_Signed();
  4485.   Gen_Signed_2_Ulaw();
  4486.  
  4487.   xa_interval_id = 0;
  4488.   xa_audio_present = XA_AUDIO_OK;
  4489.   DEBUG_LEVEL2 fprintf(stderr,"   success \n");
  4490.   Init_Audio_Ring(xa_audio_ring_size,
  4491.             (XA_AUDIO_MAX_RING_BUFF * xa_audio_hard_bps) );
  4492. }
  4493.  
  4494. /********** NetBSD_Audio_Kill **********************
  4495.  * Close /dev/audio.
  4496.  *
  4497.  *****/
  4498. void NetBSD_Audio_Kill()
  4499.   /* TURN AUDIO OFF */
  4500.   NetBSD_Audio_Off(0);
  4501.   xa_audio_present = XA_AUDIO_UNK;
  4502.   /* SHUT THINGS DOWN  */
  4503.   close(devAudio);
  4504.   Kill_Audio_Ring();
  4505. }
  4506.  
  4507. /********** NetBSD_Audio_Off **********************
  4508.  * Stop Audio Stream
  4509.  *
  4510.  *****/
  4511. void NetBSD_Audio_Off(flag)
  4512. xaULONG flag;
  4513. { /* long ret; */
  4514.  
  4515.   DEBUG_LEVEL1 fprintf(stderr,"NetBSD_Audio_Off\n");
  4516.   if (xa_audio_status != XA_AUDIO_STARTED) return;
  4517.  
  4518.   /* SET FLAG TO STOP OUTPUT ROUTINE */
  4519.   xa_audio_status = XA_AUDIO_STOPPED;
  4520.  
  4521.   /* TURN OFF SOUND ??? */
  4522.   NetBSD_Adjust_Volume(XA_AUDIO_MINVOL);
  4523.  
  4524.   /* FLUSH AUDIO DEVICE */ /* NOT! */
  4525. /*
  4526.   ret = ioctl(devAudio, AUDIO_FLUSH, NULL);
  4527.   if (ret == -1) fprintf(stderr,"NetBSD Audio: off flush err %d\n",errno);
  4528. */
  4529.  
  4530.   xa_time_audio = -1;
  4531.   xa_audio_flushed = 0;
  4532.  
  4533.   /* FLUSH AUDIO DEVICE AGAIN */ /* NOT! */
  4534. /*
  4535.   ret = ioctl(devAudio, AUDIO_FLUSH, NULL);
  4536.   if (ret == -1) fprintf(stderr,"NetBSD Audio: off flush err %d\n",errno);
  4537. */
  4538.  
  4539.   /* RESTORE ORIGINAL VOLUME */
  4540.   if (XAAUD->mute != xaTRUE) NetBSD_Adjust_Volume(XAAUD->volume);
  4541. }
  4542.  
  4543. /********** NetBSD_Audio_On **********************
  4544.  * Turn On Audio Stream.
  4545.  *
  4546.  *****/
  4547. void NetBSD_Audio_On()
  4548. {
  4549.   DEBUG_LEVEL2 
  4550.   {
  4551.     fprintf(stderr,"NetBSD_Audio_On \n");
  4552.   }
  4553.   if (xa_audio_status == XA_AUDIO_STARTED) return;
  4554.   else if (xa_audio_present != XA_AUDIO_OK) return;
  4555.  
  4556.   else if (xa_snd_cur)
  4557.   { int ret;
  4558.  
  4559.     /* CHANGE FREQUENCY IF NEEDED */
  4560.     if (xa_audio_hard_freq != xa_snd_cur->hfreq)
  4561.     { audio_info_t a_info;
  4562.       AUDIO_INITINFO(&a_info);
  4563.       a_info.play.sample_rate = xa_snd_cur->hfreq;
  4564.       ret = ioctl(devAudio, AUDIO_SETINFO, &a_info);
  4565.       if (ret == -1) fprintf(stderr,"audio setfreq: freq %x errno %d\n",
  4566.                         xa_snd_cur->hfreq, errno);
  4567.       xa_audio_hard_freq = xa_snd_cur->hfreq;
  4568.     }
  4569.  
  4570.     /* xa_snd_cur gets changes in Update_Ring() */
  4571.     xa_out_time = 100;  /* keep audio fed 500ms ahead of video */  /* was 500, changed it to 100 - rcd */
  4572.     xa_out_init = xa_audio_ring_size - 1;
  4573.     xa_interval_time = xa_snd_cur->ch_time / XAAUD->divtest;
  4574.  
  4575. DEBUG_LEVEL1 fprintf(stderr,"ch_time %d out_time %d int time %d \n",xa_snd_cur->ch_time,xa_out_time,xa_interval_time);
  4576.  
  4577.     xa_audio_status = XA_AUDIO_STARTED;
  4578.     XA_Flush_Ring();
  4579.     XA_Update_Ring(1000);
  4580.  
  4581.     if (xa_interval_time == 0) xa_interval_time = 1;
  4582.     xa_time_now = XA_Read_AV_Time();  /* get new time */
  4583.     New_Merged_Audio_Output();
  4584.   }
  4585. }
  4586.  
  4587.  
  4588. /********** NetBSD_Closest_Freq **********************************************
  4589.  *
  4590.  * Global Variable Affect:
  4591.  *   xaULONG xa_audio_hard_buff        must set but not larger than
  4592.  *                    XA_AUDIO_MAX_RING_BUF size
  4593.  ****************************************************************************/
  4594. xaULONG NetBSD_Closest_Freq(ifreq)
  4595. xaLONG ifreq;
  4596. { audio_info_t a_info;
  4597.  
  4598.   AUDIO_INITINFO(&a_info);
  4599.   a_info.play.sample_rate = ifreq;
  4600.   ioctl(devAudio, AUDIO_SETINFO, &a_info);
  4601.  
  4602.   ioctl(devAudio, AUDIO_GETINFO, &a_info);
  4603.  
  4604.   xa_audio_hard_buff  = a_info.blocksize;
  4605.   return (a_info.play.sample_rate);
  4606. }
  4607.  
  4608.  
  4609. /* Eventually merge everything to one */
  4610. void NetBSD_Set_Output_Port(aud_ports)
  4611. xaULONG aud_ports;
  4612. {
  4613. /* Commented out for now ;-) */
  4614. /*
  4615. audio_info_t a_info;
  4616.   xaLONG ret;
  4617.   xaULONG NetBSD_ports = 0;
  4618.   if (aud_ports & XA_AUDIO_PORT_INT)  NetBSD_ports |= AUDIO_SPEAKER;
  4619.   if (aud_ports & XA_AUDIO_PORT_HEAD) NetBSD_ports |= AUDIO_HEADPHONE;
  4620.   if (aud_ports & XA_AUDIO_PORT_EXT)  NetBSD_ports |= AUDIO_LINE_OUT;
  4621.   AUDIO_INITINFO(&a_info);
  4622.   a_info.play.port = NetBSD_ports;
  4623.   ret = ioctl(devAudio, AUDIO_SETINFO, &a_info);
  4624.   if (ret < 0) fprintf(stderr,"Audio: couldn't set speaker port %d\n",errno);
  4625. */
  4626. }
  4627.  
  4628. /************* NetBSD_Speaker_Toggle *****************************************
  4629.  *
  4630.  * flag = 0  turn speaker off
  4631.  * flag = 1  turn speaker on
  4632.  * flag = 2  toggle speaker
  4633.  ****************************************************************************/
  4634. void NetBSD_Speaker_Toggle(flag)
  4635. xaULONG flag;
  4636.   switch(flag)
  4637.   {
  4638.     case  0: XAAUD->port &= ~XA_AUDIO_PORT_INT; break;
  4639.     case  1: XAAUD->port |=  XA_AUDIO_PORT_INT; break;
  4640.     default:  /* mutually exclusive set for now - never turn off */
  4641.     { if ( !(XAAUD->port & XA_AUDIO_PORT_INT)) 
  4642.         XAAUD->port = XA_AUDIO_PORT_INT;
  4643.     }
  4644.   }
  4645.   NetBSD_Set_Output_Port(XAAUD->port);
  4646. }
  4647.  
  4648. /************* NetBSD_Headphone_Toggle *****************************************
  4649.  *
  4650.  * flag = 0  turn headphones off
  4651.  * flag = 1  turn headphones on
  4652.  * flag = 2  toggle headphones
  4653.  ****************************************************************************/
  4654. void NetBSD_Headphone_Toggle(flag)
  4655. xaULONG flag;
  4656.   switch(flag)
  4657.   {
  4658.     case  0: XAAUD->port &= ~XA_AUDIO_PORT_HEAD; break;
  4659.     case  1: XAAUD->port |=  XA_AUDIO_PORT_HEAD; break;
  4660.     default:  /* mutually exclusive set for now - never turn off */
  4661.     { if ( !(XAAUD->port & XA_AUDIO_PORT_HEAD)) 
  4662.         XAAUD->port = XA_AUDIO_PORT_HEAD;
  4663.     }
  4664.   }
  4665.   NetBSD_Set_Output_Port(XAAUD->port);
  4666. }
  4667.  
  4668.  
  4669. /********** NetBSD_Adjust_Volume **********************
  4670.  * Routine for Adjusting Volume on NetBSD
  4671.  *
  4672.  * Volume is in the range [0,XA_AUDIO_MAXVOL]
  4673.  ****************************************************************************/
  4674. void NetBSD_Adjust_Volume(volume)
  4675. xaULONG volume;
  4676. { audio_info_t a_info;
  4677.  
  4678.   AUDIO_INITINFO(&a_info);
  4679.   a_info.play.gain = NetBSD_MIN_VOL +
  4680.     ((volume * (NetBSD_MAX_VOL - NetBSD_MIN_VOL)) / XA_AUDIO_MAXVOL);
  4681.   if (a_info.play.gain > NetBSD_MAX_VOL) a_info.play.gain = NetBSD_MAX_VOL;
  4682.   ioctl(devAudio, AUDIO_SETINFO, &a_info);
  4683.  
  4684. }
  4685. #endif
  4686. /****************************************************************************/
  4687. /****************************************************************************/
  4688. /******************* END OF NetBSD SPECIFIC ROUTINES ************************/
  4689. /****************************************************************************/
  4690.  
  4691.  
  4692.  
  4693. XA_SND *XA_Audio_Next_Snd(snd_hdr)
  4694. XA_SND *snd_hdr;
  4695. { DEBUG_LEVEL2 fprintf(stderr,"XA_Audio_Next_Snd: snd_hdr %x \n",
  4696.                             (xaULONG)snd_hdr);
  4697.   xa_snd_cur = snd_hdr->next;
  4698.   /* brief clean up of old header */
  4699.   snd_hdr->inc_cnt = 0;
  4700.   snd_hdr->byte_cnt = 0;
  4701.   snd_hdr->samp_cnt = snd_hdr->tot_samps;
  4702.   if (snd_hdr->fpos >= 0) snd_hdr->snd = 0;
  4703.   if (xa_snd_cur==0) return(0);
  4704.   /* full init of new header */
  4705.   XA_Audio_Init_Snd(xa_snd_cur);
  4706.   /* read in info from file if necessary */
  4707.   if (xa_snd_cur->fpos >= 0)
  4708.   { xa_snd_cur->snd = xa_audcodec_buf;
  4709.     XA_Read_Audio_Delta(xa_aud_fd,xa_snd_cur->fpos,
  4710.                 xa_snd_cur->tot_bytes,xa_audcodec_buf);
  4711.   }
  4712.   return(xa_snd_cur);
  4713. }
  4714.  
  4715. void XA_Read_Audio_Delta(fd,fpos,fsize,buf)
  4716. int fd;
  4717. xaLONG fpos;
  4718. xaULONG fsize;
  4719. char *buf;
  4720. { int ret;
  4721.   ret  = lseek(fd,fpos,SEEK_SET);
  4722.   if (ret != fpos) TheEnd1("XA_Read_Audio_Delta:seek err");
  4723.   ret = read(fd, buf, fsize);
  4724.   if (ret != fsize) TheEnd1("XA_Read_Audio_Delta:read err");
  4725. }
  4726.  
  4727.  
  4728.  
  4729. /*************
  4730.  *  May not be needed
  4731.  *
  4732.  *****/
  4733. xaUBYTE XA_Signed_To_Ulaw(ch)
  4734. xaLONG ch;
  4735. {
  4736.   xaLONG mask;
  4737.   if (ch < 0) { ch = -ch; mask = 0x7f; }
  4738.   else { mask = 0xff; }
  4739.   if (ch < 32)        { ch = 0xF0 | (15 - (ch / 2)); }
  4740.   else if (ch < 96)    { ch = 0xE0 | (15 - (ch - 32) / 4); }
  4741.   else if (ch < 224)    { ch = 0xD0 | (15 - (ch - 96) / 8); }
  4742.   else if (ch < 480)    { ch = 0xC0 | (15 - (ch - 224) / 16); }
  4743.   else if (ch < 992)    { ch = 0xB0 | (15 - (ch - 480) / 32); }
  4744.   else if (ch < 2016)    { ch = 0xA0 | (15 - (ch - 992) / 64); }
  4745.   else if (ch < 4064)    { ch = 0x90 | (15 - (ch - 2016) / 128); }
  4746.   else if (ch < 8160)    { ch = 0x80 | (15 - (ch - 4064) /  256); }
  4747.   else            { ch = 0x80; }
  4748.   return (mask & ch);
  4749. }
  4750.  
  4751. void Gen_Signed_2_Ulaw()
  4752. {
  4753.   xaULONG i;
  4754.   for(i=0;i<256;i++)
  4755.   { xaUBYTE d;
  4756.     xaBYTE ch = i;
  4757.     xaLONG chr = ch;
  4758.     d = XA_Signed_To_Ulaw(chr * 16);
  4759.     xa_sign_2_ulaw[i] = d;
  4760.   }
  4761. }
  4762.  
  4763.  
  4764. /*
  4765. ** This routine converts from ulaw to 16 bit linear.
  4766. **
  4767. ** Craig Reese: IDA/Supercomputing Research Center
  4768. ** 29 September 1989
  4769. **
  4770. ** References:
  4771. ** 1) CCITT Recommendation G.711  (very difficult to follow)
  4772. ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
  4773. **     for Analog-to_Digital Conversion Techniques,"
  4774. **     17 February 1987
  4775. **
  4776. ** Input: 8 bit ulaw sample
  4777. ** Output: signed 16 bit linear sample
  4778. */
  4779.  
  4780. xaLONG XA_Ulaw_to_Signed( ulawbyte )
  4781. xaUBYTE ulawbyte;
  4782. {
  4783.   static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
  4784.   int sign, exponent, mantissa, sample;
  4785.  
  4786.   ulawbyte = ~ ulawbyte;
  4787.   sign = ( ulawbyte & 0x80 );
  4788.   exponent = ( ulawbyte >> 4 ) & 0x07;
  4789.   mantissa = ulawbyte & 0x0F;
  4790.   sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
  4791.   if ( sign != 0 ) sample = -sample;
  4792.  
  4793.   return sample;
  4794. }
  4795.  
  4796. /**************************************
  4797.  *
  4798.  *************************************/
  4799. void Gen_Ulaw_2_Signed()
  4800. { xaULONG i;
  4801.   for(i=0;i<256;i++)
  4802.   { xaUBYTE data = (xaUBYTE)(i);
  4803.     xaLONG d = XA_Ulaw_to_Signed( data );
  4804.     xa_ulaw_2_sign[i] = (xaULONG)((xaULONG)(d) & 0xffff);
  4805.   }
  4806. }
  4807.  
  4808.  
  4809. /* Pod this was 4096, I changed to 32768 */
  4810. #define XA_ARM_VAL_LIMIT       32768
  4811. /* Mu-law format constants */
  4812. #define XA_ARM_SIGN_BIT        1
  4813. #define XA_ARM_NCHORDS         8
  4814. #define XA_ARM_NPOINTS         16
  4815.     /* limit of "magnitude" (logarithmic) */
  4816. #define XA_ARM_DAC_LIMIT       (XA_ARM_NCHORDS*XA_ARM_NPOINTS)  
  4817.  
  4818. xaULONG arm_dac_to_val[XA_ARM_DAC_LIMIT];     /* obsolete */
  4819.  
  4820. /**************************************
  4821.  *
  4822.  * original code courtesy of Mark Taunton, Acorn Computers Ltd, June 1992.
  4823.  * hacked by Mark Podlipec
  4824.  *************************************/
  4825. void Gen_Arm_2_Signed()
  4826. { int c, p, ux, step, curval, max;
  4827.   double adjust;
  4828.  
  4829.   ux = 0; curval = 0;
  4830.   for (c = 0; c < XA_ARM_NCHORDS; ++c)
  4831.   {
  4832.     step = 1 << c;
  4833.     for (p = 0; p < XA_ARM_NPOINTS; ++p)
  4834.     {
  4835.       arm_dac_to_val[ux++] = curval;
  4836.       curval += step;
  4837.     }
  4838.   }
  4839.   
  4840.   /* Now adjust for 0..4095 notional linear range rather than 0..4016 */
  4841.   /* i.e. half-step over max nominal: 3952+128/2 = 4016 */
  4842.   max = curval - step/2;  
  4843.   adjust = (double)(XA_ARM_VAL_LIMIT-1) / (double)max;
  4844.   /* Scale dac_to_val table to give 0..4095 linear range coverage */
  4845.   for (ux = 0; ux < XA_ARM_DAC_LIMIT; ++ux)
  4846.   {                       /* implement rounding */
  4847.     arm_dac_to_val[ux] = (int) (arm_dac_to_val[ux] * adjust + 0.5); 
  4848.         /* Compute signed table values also */
  4849.     xa_arm_2_signed[ux << 1 |        0]        =  arm_dac_to_val[ux];
  4850.     xa_arm_2_signed[ux << 1 | XA_ARM_SIGN_BIT] = -arm_dac_to_val[ux];
  4851.   }
  4852. }
  4853.  
  4854. /********* Init_Audio_Ring ************
  4855.  *
  4856.  * Global Variables:
  4857.  *  xa_audio_ring        pointer to somewhere in the ring
  4858.  *************************************/
  4859. void Init_Audio_Ring(ring_num,buf_size)
  4860. xaULONG ring_num;
  4861. xaULONG buf_size;
  4862. {
  4863.   xaULONG i;
  4864.   XA_AUDIO_RING_HDR *t_ring,*t_first;
  4865.   xaUBYTE *t_buf;
  4866.   if (xa_audio_ring) Kill_Audio_Ring();
  4867.   t_first = xa_audio_ring = 0;
  4868.   for(i=0;i<ring_num;i++)
  4869.   {
  4870.     t_ring = (XA_AUDIO_RING_HDR *)malloc( sizeof(XA_AUDIO_RING_HDR) );
  4871.     if (t_ring==0) TheEnd1("Init Audio Ring: malloc err0");
  4872.     t_buf = (xaUBYTE *)malloc( buf_size );
  4873.     if (t_buf==0) TheEnd1("Init Audio Ring: malloc err1");
  4874.     t_ring->time = t_ring->timelo = 0;
  4875.     t_ring->len = 0;
  4876.     t_ring->buf = t_buf;
  4877.     if (t_first == 0) t_first = xa_audio_ring = t_ring;
  4878.     t_ring->next = t_first;
  4879.     xa_audio_ring->next = t_ring;
  4880.     xa_audio_ring = t_ring;
  4881.   }
  4882.   xa_audio_ring_t = xa_audio_ring;
  4883. }
  4884.  
  4885. /********* Kill_Audio_Ring ************
  4886.  * Move around ring, free'ing up memory structures.
  4887.  *
  4888.  * Global Variables:
  4889.  *  xa_audio_ring        pointer to somewhere in the ring
  4890.  **************************************/
  4891. void Kill_Audio_Ring()
  4892. {
  4893.   XA_AUDIO_RING_HDR *t_first;
  4894.  
  4895.   if (xa_audio_ring==0) return;
  4896.   t_first = xa_audio_ring;
  4897.  
  4898.   do
  4899.   { XA_AUDIO_RING_HDR *t_tmp = xa_audio_ring;
  4900.     if (xa_audio_ring->buf) FREE(xa_audio_ring->buf,0x508);
  4901.     xa_audio_ring->time = xa_audio_ring->timelo = 0;
  4902.     xa_audio_ring->len = 0;
  4903.     xa_audio_ring->buf = 0;
  4904.     xa_audio_ring = xa_audio_ring->next;
  4905.     FREE(t_tmp,0x509);
  4906.   } while(xa_audio_ring != t_first);
  4907.   xa_audio_ring = 0;
  4908.   xa_audio_ring_t = 0;
  4909. }
  4910.  
  4911. /****************************************************************
  4912.  * Fill up any unused Audio Ring Entries with sound.
  4913.  *
  4914.  ****************************************************************/
  4915.  
  4916. void XA_Update_Ring(cnt)
  4917. xaULONG cnt;
  4918. DEBUG_LEVEL1 fprintf(stderr,"UPDATE RING %d\n",cnt);
  4919.   while( (xa_audio_ring_t->len == 0) && (xa_snd_cur) && cnt)
  4920.   { xaULONG tmp_time, tmp_timelo; xaLONG i,xx;
  4921.     cnt--;
  4922.     tmp_time = xa_snd_cur->ch_time;    /* save these */
  4923.     tmp_timelo = xa_snd_cur->ch_timelo;
  4924.     /* uncompress sound chunk */
  4925.     i = xa_audio_ring_t->len = xa_snd_cur->ch_size * xa_audio_hard_bps;
  4926.     /* NOTE: the following delta call may modify xa_snd_cur */
  4927.     xx = xa_snd_cur->delta(xa_snd_cur,xa_audio_ring_t->buf,0,
  4928.                             xa_snd_cur->ch_size);
  4929.     i -= xx * xa_audio_hard_bps;
  4930.     if (i > 0) /* Some system need fixed size chunks */
  4931.     { xaUBYTE *dptr = xa_audio_ring_t->buf;
  4932.       while(i--) *dptr++ = 0;
  4933.     }
  4934.     xa_audio_ring_t->time = tmp_time;
  4935.     xa_audio_ring_t->timelo = tmp_timelo;
  4936.     xa_audio_ring_t = xa_audio_ring_t->next; 
  4937.   }
  4938. }
  4939.  
  4940. /***************************************************************8
  4941.  * Flush Ring of All Conversions
  4942.  * SHOULD ONLY BE CALLED BY OUTPUT ROUTINE.
  4943.  */
  4944.  
  4945. void XA_Flush_Ring()
  4946. { XA_AUDIO_RING_HDR *tring = xa_audio_ring;
  4947.  
  4948. DEBUG_LEVEL1 fprintf(stderr,"FLUSH_RING\n");
  4949.   do
  4950.   { xa_audio_ring->len = 0;
  4951.     xa_audio_ring = xa_audio_ring->next;
  4952.   } while(xa_audio_ring != tring);
  4953.   xa_audio_ring_t = xa_audio_ring;    /* resync  fill and empty */
  4954.   xa_audio_flushed = 1;
  4955. }
  4956.  
  4957.  
  4958. /********** New_Merged_Audio_Output **********************
  4959.  * Set Volume if needed and then write audio data to audio device.
  4960.  *
  4961.  * IS 
  4962.  *****/
  4963. void New_Merged_Audio_Output()
  4964. { xaLONG time_diff, loop_cnt = xa_audio_ring_size;
  4965.  
  4966.   /* normal exit is when audio gets ahead */
  4967.   while(loop_cnt--)
  4968.   {
  4969.     if (xa_audio_status != XA_AUDIO_STARTED) { return; }
  4970.     time_diff = xa_time_audio - xa_time_now; /* how far ahead is audio */
  4971.     if (time_diff > xa_out_time) /* potentially ahead */
  4972.     {
  4973.       xa_time_now = XA_Read_AV_Time();  /* get new time */
  4974.       time_diff = xa_time_audio - xa_time_now;
  4975.       if (time_diff > xa_out_time)  /* definitely ahead */
  4976.       { /* If we're ahead, update the ring. */
  4977.         XA_Update_Ring(2);
  4978.     xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
  4979.         (XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
  4980.         return;
  4981.       }
  4982.     }
  4983.  
  4984.  
  4985.     if (xa_audio_ring->len)
  4986.     { 
  4987.       /* If audio buffer is full, write() can't write all of the data. */
  4988.       /* So, next routine checks the rest length in buffer.            */
  4989. #ifdef XA_SONY_AUDIO
  4990.       { int ret, buf_len;
  4991.     ret = ioctl(devAudio, SBIOCBUFRESID,&buf_len) ;
  4992.     if( ret == -1 ) fprintf(stderr,"SONY_AUDIO: SIOCBUFRESID error.\n");
  4993.     if(buf_len > sony_audio_buf_len - xa_audio_ring->len)
  4994.     {
  4995.       xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
  4996.         (XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
  4997.       return;
  4998.     }
  4999.       }
  5000. #endif
  5001.  
  5002. #ifdef XA_SGI_AUDIO
  5003.       { int buf_len;
  5004.     buf_len = ALgetfillable(port) ;
  5005.     if (buf_len < (xa_audio_ring->len >> 1))
  5006.     { 
  5007.       xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
  5008.         (XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
  5009.       return;
  5010.     }
  5011.       }
  5012. #endif
  5013.  
  5014. #ifdef XA_MMS_AUDIO
  5015.       {
  5016.         mmeProcessCallbacks();
  5017.     /* NOTE: These buffers aren't part of the XAnim audio ring buffer */
  5018.     /*       Our ring buffer just happens to be the same size */
  5019.     if( mms_buffers_outstanding  >= xa_audio_ring_size ) 
  5020.     {
  5021.       xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
  5022.         (XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
  5023.        return ;
  5024.     }
  5025.       }
  5026. #endif
  5027.  
  5028. #ifdef XA_HP_AUDIO
  5029.       if (hp_audio_paused == xaTRUE)
  5030.       { DEBUG_LEVEL1 fprintf(stderr,"HP-out-unpause\n");
  5031.         AResumeAudio( audio_connection, hp_trans_id, NULL, NULL );
  5032.         hp_audio_paused = xaFALSE;
  5033.       }
  5034. #endif
  5035.  
  5036.  
  5037. /*---------------- Now for the Write Segments -------------------------------*/
  5038.  
  5039. #ifdef XA_SPARC_AUDIO
  5040.       write(devAudio,xa_audio_ring->buf,xa_audio_ring->len); 
  5041. #endif
  5042.  
  5043. #ifdef XA_NetBSD_AUDIO
  5044.       write(devAudio,xa_audio_ring->buf,xa_audio_ring->len);
  5045. #endif
  5046.  
  5047. #ifdef XA_AIX_AUDIO
  5048.       { int rc;
  5049.         rc = write ( devAudio, xa_audio_ring->buf, xa_audio_ring->len );
  5050.       }
  5051. #endif
  5052.  
  5053. #ifdef XA_SGI_AUDIO
  5054.       /* # of Samples, not Bytes. Note: assume 16 bit samples. */
  5055.       ALwritesamps(port,xa_audio_ring->buf, (xa_audio_ring->len >> 1) );
  5056. #endif
  5057.  
  5058. #ifdef XA_LINUX_AUDIO
  5059.       write(devAudio,xa_audio_ring->buf,xa_audio_ring->len);
  5060. #endif
  5061.  
  5062. #ifdef XA_NAS_AUDIO
  5063.       NAS_Write_Data(xa_audio_ring->buf, xa_audio_ring->len);
  5064. #endif
  5065.  
  5066. #ifdef XA_SONY_AUDIO
  5067.       { int ret;
  5068.         write(devAudio,xa_audio_ring->buf,xa_audio_ring->len);
  5069.         /* Buffer of Sony audio device is too large */ /* HP needs this */
  5070.         ret = ioctl(devAudio, SBIOCFLUSH, 0);
  5071.         if( ret == -1 ) fprintf(stderr,"audio output:SBIOCFLUSH error.\n");
  5072.       }
  5073. #endif
  5074.  
  5075. #ifdef XA_EWS_AUDIO
  5076.       write(devAudio,xa_audio_ring->buf,xa_audio_ring->len);
  5077. #endif
  5078.  
  5079. #ifdef XA_AF_AUDIO
  5080.       { ATime act, atd = AFtime0;
  5081.     if (XAAUD->mute != xaTRUE)
  5082.       act = AFPlaySamples(ac,AFtime0,xa_audio_ring->len,xa_audio_ring->buf);
  5083.     else act = AFGetTime(ac);
  5084.     if (AFtime0 < act)    AFtime0 = act+TOFFSET;
  5085.     else    AFtime0 += xa_audio_ring->len >> 1; /* Number of samples */
  5086.       }
  5087. #endif
  5088.  
  5089. #ifdef XA_HP_AUDIO
  5090.       write(streamSocket,xa_audio_ring->buf,xa_audio_ring->len);
  5091. /* Some way to flush streamsocket???? */
  5092. #endif
  5093.  
  5094. #ifdef XA_HPDEV_AUDIO
  5095.       write (devAudio, xa_audio_ring->buf, xa_audio_ring->len);
  5096. #endif
  5097.  
  5098. #ifdef XA_MMS_AUDIO
  5099.       /* As currently implemented, this copies the audio data into a separate
  5100.          shared memory buffer for communication with the multimedia server. We
  5101.          could actually work directly out of the audio ring buffer if it was
  5102.          allocated in shared memory, but this keeps things more independent of
  5103.          each other - tfm
  5104.       */
  5105.       {  
  5106.     MMRESULT    status;
  5107.     int        bytes,len;
  5108.     if (XAAUD->mute != xaTRUE) 
  5109.     {
  5110.       bytes = xa_audio_hard_buff * xa_audio_hard_bps;
  5111.       mms_lpWaveHeader->lpData = (LPSTR)(mms_audio_buffer
  5112.                         + mms_next_buffer * bytes);
  5113.       mms_lpWaveHeader->dwBufferLength = xa_audio_ring->len;
  5114.       if(xa_audio_ring->len > bytes) 
  5115.       {
  5116.         len = bytes;
  5117.         fprintf(stderr,"Audio chunk truncated to %d bytes\n",len);
  5118.       }
  5119.       else len = xa_audio_ring->len;
  5120.       memcpy( mms_lpWaveHeader->lpData, xa_audio_ring->buf, len);
  5121.       mms_next_buffer++;
  5122.       if(mms_next_buffer >= xa_audio_ring_size) mms_next_buffer = 0;
  5123.       status = waveOutWrite(mms_device_handle, mms_lpWaveHeader,
  5124.                             sizeof(WAVEHDR));
  5125.       if( status != MMSYSERR_NOERROR ) 
  5126.       {
  5127.         fprintf(stderr,"waveOutWrite failed - status = %d\n",status);
  5128.       }
  5129.       else { mms_buffers_outstanding++; }
  5130.     }
  5131.       }
  5132. #endif
  5133.  
  5134.       /* Don't adjust volume until after write. If we're behind
  5135.        * the extra delay could cause a pop. */
  5136.       if (XAAUD->newvol==xaTRUE)
  5137.       { xaULONG vol = (XAAUD->mute==xaTRUE)?(XA_AUDIO_MINVOL):(XAAUD->volume);
  5138.       XA_Adjust_Volume(vol);
  5139.       XAAUD->newvol = xaFALSE;
  5140.       }
  5141.       xa_time_audio   += xa_audio_ring->time;
  5142.       xa_timelo_audio += xa_audio_ring->timelo;
  5143.       if (xa_timelo_audio & 0xff000000)
  5144.         { xa_time_audio++; xa_timelo_audio &= 0x00ffffff; }
  5145.       xa_audio_ring->len = 0; 
  5146.       xa_audio_ring = xa_audio_ring->next;  /* move to next */
  5147.       if (xa_audio_status != XA_AUDIO_STARTED) { return;}
  5148.  
  5149.       if (xa_out_init) xa_out_init--;
  5150.       else XA_Update_Ring(2);  /* only allow two to be updated */
  5151. /* NOT HERE - loop first
  5152.       xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
  5153.         (XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
  5154.       return;
  5155. */
  5156.     } 
  5157.     else  /* Audio Sample finished */
  5158.     { xa_time_now = XA_Read_AV_Time();
  5159.  
  5160.     /* Is audio still playing buffered samples? */
  5161.       if (xa_time_now < xa_time_audio) 
  5162.       { xaULONG diff = xa_time_audio - xa_time_now;
  5163.     /* POD note 50ms is arbitrarily chosen to be long, but not noticeable*/
  5164.         if (xa_audio_status != XA_AUDIO_STARTED) {return;}
  5165.     xa_interval_id = XtAppAddTimeOut(theAudContext,diff,
  5166.         (XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
  5167.         return;
  5168.       }
  5169.       else 
  5170.       { XA_Audio_Off(0);
  5171.     return;
  5172.       }
  5173.     } /* end of ring_len */
  5174.   } /* end of while ring */
  5175.   xa_interval_id = XtAppAddTimeOut(theAudContext,xa_interval_time,
  5176.         (XtTimerCallbackProc)New_Merged_Audio_Output,(XtPointer)(NULL));
  5177.   return;
  5178. }  /* end of function */
  5179.  
  5180.