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