1 
2 /*
3 #    Sfront, a SAOL to C translator
4 #    This file: merged linux/freebsd audio driver for sfront
5 #    Copyright (C) 2000  Bertrand Petit
6 #
7 # Copyright (c) 1999-2006, Regents of the University of California
8 # All rights reserved.
9 #
10 # Redistribution and use in source and binary forms, with or without
11 # modification, are permitted provided that the following conditions are
12 # met:
13 #
14 #  Redistributions of source code must retain the above copyright
15 #  notice, this list of conditions and the following disclaimer.
16 #
17 #  Redistributions in binary form must reproduce the above copyright
18 #  notice, this list of conditions and the following disclaimer in the
19 #  documentation and/or other materials provided with the distribution.
20 #
21 #  Neither the name of the University of California, Berkeley nor the
22 #  names of its contributors may be used to endorse or promote products
23 #  derived from this software without specific prior written permission.
24 #
25 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #
37 #    Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu
38 */
39 
40 
41 #define ASYSIO_LINUX   0
42 #define ASYSIO_FREEBSD 1
43 
44 #define ASYSIO_OSTYPE  ASYSIO_LINUX
45 
46 /****************************************************************/
47 /****************************************************************/
48 /*                linux audio driver for sfront                 */
49 /****************************************************************/
50 
51 /**************************************************/
52 /* define flags for fifo mode, and for a timer to */
53 /* catch SAOL infinite loops                      */
54 /**************************************************/
55 
56 #if (defined(ASYS_HASOUTPUT) && (ASYSIO_OSTYPE == ASYSIO_LINUX) && \
57      defined(CSYS_CDRIVER_LINMIDI) && (ASYS_TIMEOPTION == ASYS_TIMESYNC) && \
58      !defined(ASYS_HASINPUT))
59 #define ASYSIO_USEFIFO 1
60 #endif
61 
62 #if (defined(ASYS_HASOUTPUT) && (ASYSIO_OSTYPE == ASYSIO_LINUX) && \
63     (ASYS_TIMEOPTION != ASYS_TIMESYNC))
64 #define ASYSIO_USEFIFO 1
65 #endif
66 
67 #ifndef ASYSIO_USEFIFO
68 #define ASYSIO_USEFIFO 0
69 #endif
70 
71 /**************************************************/
72 /* include headers, based on flags set above      */
73 /**************************************************/
74 
75 #include <unistd.h>
76 #include <sys/ioctl.h>
77 #include <fcntl.h>
78 
79 #if (ASYSIO_OSTYPE == ASYSIO_LINUX)
80 #include <sys/soundcard.h>
81 #include <endian.h>
82 #endif
83 
84 #if (ASYSIO_OSTYPE == ASYSIO_FREEBSD)
85 #include <machine/soundcard.h>
86 #include <machine/endian.h>
87 #endif
88 
89 #include <signal.h>
90 #include <sys/time.h>
91 
92 #if ASYSIO_USEFIFO
93 #include <sched.h>
94 #if (ASYS_TIMEOPTION == ASYS_TIMESYNC)
95 #include <time.h>
96 #endif
97 #endif
98 
99 /******************************/
100 /* other constant definitions */
101 /******************************/
102 
103 #ifndef ASYSIO_DSPDEV
104 #define ASYSIO_DSPDEV "/dev/dsp"
105 #endif
106 
107 /* determines native audio format */
108 
109 #if (BYTE_ORDER == BIG_ENDIAN)
110 # define ASYSIO_AFORMAT AFMT_S16_BE
111 #else
112 # if (BYTE_ORDER == LITTLE_ENDIAN)
113 #  define ASYSIO_AFORMAT AFMT_S16_LE
114 # else
115 #  error "BYTE_ORDER not defined?"
116 # endif
117 #endif
118 
119 /* codes for IO types */
120 
121 #define ASYSIO_I  0
122 #define ASYSIO_O  1
123 #define ASYSIO_IO 2
124 
125 /* minimum fragment size */
126 
127 #define ASYSIO_FRAGMIN    16
128 #define ASYSIO_LOGFRAGMIN 4
129 
130 /* number of silence buffers */
131 
132 #define ASYSO_LNUMBUFF 4
133 
134 /* maximum number of I/O retries before termination */
135 
136 #define ASYSIO_MAXRETRY 256
137 
138 #if ASYSIO_USEFIFO                      /* SCHED_FIFO constants for ksync()  */
139 
140 #if (ASYS_TIMEOPTION == ASYS_TIMESYNC)
141 #define ASYSIO_SYNC_TIMEOUT    5        /* idle time to leave SCHED_FIFO     */
142 #define ASYSIO_SYNC_ACTIVE     0        /* machine states for noteon timeout */
143 #define ASYSIO_SYNC_WAITING    1
144 #define ASYSIO_SYNC_SCHEDOTHER 2
145 #else
146 #define ASYSIO_MAXBLOCK ((int)EV(KRATE))*2  /* max wait tor let SCHED_OTHERs run */
147 #endif
148 
149 #endif
150 
151 /************************/
152 /* variable definitions */
153 /************************/
154 
155 int  asysio_fd;                    /* device pointer */
156 int asysio_srate;                 /* sampling rate */
157 int asysio_channels;              /* number of channels */
158 int asysio_size;                  /* # samples in a buffer */
159 int asysio_bsize;                 /* actual # bytes in a buffer */
160 int asysio_requested_bsize;       /* requested # bytes in a buffer */
161 int asysio_input;                 /* 1 if ASYSIO */
162 int asysio_blocktime;             /* time (in bytes) blocked in kcycle */
163 
164 struct count_info asysio_ptr;      /* for GET{I,O}*PTR  ioctl calls */
165 struct audio_buf_info asysio_info; /* for GET{I,O}SPACE ioctl calls */
166 
167 #if defined(ASYS_HASOUTPUT)
168 short * asyso_buf = NULL;          /* output buffer */
169 int asysio_puts;                   /* total number of putbufs */
170 int asysio_reset;                  /* flags an overrun */
171 #endif
172 
173 #if defined(ASYS_HASINPUT)
174 short * asysi_buf = NULL;          /* input buffer */
175 struct audio_buf_info asysi_info;  /* input dma status */
176 #endif
177 
178 sigset_t asysio_iloop_mask;            /* for masking off iloop interrupt */
179 struct sigaction asysio_iloop_action;  /* for setting up iloop interrupt  */
180 struct itimerval asysio_iloop_timer;   /* for setting up iloop timer      */
181 
182 #if ASYSIO_USEFIFO
183 int asysio_fifo;                       /* can get into sched_fifo mode */
184 struct sched_param asysio_fifoparam;   /* param block for fifo mode */
185 struct sched_param asysio_otherparam;  /* param block for other mode */
186 
187 #if (ASYS_TIMEOPTION == ASYS_TIMESYNC)
188 
189 /* state machine variables for noteon timeout */
190 int    asysio_sync_state;
191 time_t asysio_sync_waitstart;
192 extern int csysi_newnote;       /* from linmidi */
193 
194 #else
195 
196 /* state to detect long periods w/o blocking */
197 int asysio_sync_noblock;                /* how many acycles since last block */
198 struct timespec asysio_sync_sleeptime;  /* time to wait during forced block  */
199 
200 #endif
201 
202 #endif
203 
204 #if defined(ASYS_KSYNC)                      /* ksync() state */
205 struct count_info asysio_sync_ptr;
206 int asysio_sync_target, asysio_sync_incr;
207 float asysio_sync_cpuscale;
208 #endif
209 
210 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
211 /*                      shutdown routines                       */
212 /*______________________________________________________________*/
213 
214 
215 /****************************************************************/
216 /*                    shuts down soundcard                      */
217 /****************************************************************/
218 
asysio_shutdown(void)219 void asysio_shutdown(void)
220 
221 {
222   if (ioctl(asysio_fd, SNDCTL_DSP_SYNC, 0) == -1)
223     {
224       fprintf(stderr, "\nSoundcard Error: SNDCTL_DSP_SYNC Ioctl Problem\n");
225       fprintf(stderr, "Errno Message: %s\n\n", strerror(errno));
226     }
227   close(asysio_fd);
228 
229   /* so that a slow exit doesn't trigger timer */
230 
231   asysio_iloop_timer.it_value.tv_sec = 0;
232   asysio_iloop_timer.it_value.tv_usec = 0;
233   asysio_iloop_timer.it_interval.tv_sec = 0;
234   asysio_iloop_timer.it_interval.tv_usec = 0;
235 
236   if (setitimer(ITIMER_PROF, &asysio_iloop_timer, NULL) < 0)
237     {
238       fprintf(stderr, "\nSoundcard Driver Error:\n\n");
239       fprintf(stderr, "  Couldn't set up ITIMER_PROF timer.\n");
240       fprintf(stderr, "  Errno Message: %s\n\n", strerror(errno));
241     }
242 }
243 
244 
245 #if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT)))
246 
247 /****************************************************************/
248 /*                    shuts down audio output                   */
249 /****************************************************************/
250 
asys_oshutdown(void)251 void asys_oshutdown(void)
252 
253 {
254   asysio_shutdown();
255   if (asyso_buf != NULL)
256     free(asyso_buf);
257 }
258 
259 #endif
260 
261 #if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT)))
262 
263 /****************************************************************/
264 /*                    shuts down audio input                    */
265 /****************************************************************/
266 
asys_ishutdown(void)267 void asys_ishutdown(void)
268 
269 {
270   asysio_shutdown();
271   if (asysi_buf != NULL)
272     free(asysi_buf);
273 }
274 
275 #endif
276 
277 
278 #if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT)))
279 
280 /****************************************************************/
281 /*              shuts down audio input and output               */
282 /****************************************************************/
283 
asys_ioshutdown(void)284 void asys_ioshutdown(void)
285 
286 {
287   asysio_shutdown();
288   if (asyso_buf != NULL)
289     free(asyso_buf);
290   if (asysi_buf != NULL)
291     free(asysi_buf);
292 }
293 
294 #endif
295 
296 
297 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
298 /*                 initialization routines                      */
299 /*______________________________________________________________*/
300 
301 
302 /****************************************************************/
303 /*          generic error-checking ioctl wrapper                */
304 /****************************************************************/
305 
306 #define ASYSIO_IOCTL_CALL(x,y,z)  do { if (ioctl(x,y,z) == -1){\
307       fprintf(stderr, "  Error: %s Ioctl Problem\n", #y ); \
308       fprintf(stderr, "  Errno Message: %s\n\n", strerror(errno));\
309       close(asysio_fd); return ASYS_ERROR;}} while (0)
310 
311 #define  ASYSIO_ERROR_RETURN(x) do {\
312       fprintf(stderr, "  Error: %s.\n", x);\
313       fprintf(stderr, "  Errno Message: %s\n\n", strerror(errno));\
314       close(asysio_fd);\
315       return ASYS_ERROR; } while (0)
316 
317 #define  ASYSIO_ERROR_RETURN_NOERRNO(x) do {\
318       fprintf(stderr, "  Error: %s.\n", x);\
319       close(asysio_fd);\
320       return ASYS_ERROR; } while (0)
321 
322 
323 /****************************************************************/
324 /*               opens the soudcard device                      */
325 /****************************************************************/
326 
asysio_opendevice(int dir,int toption)327 int asysio_opendevice(int dir, int toption)
328 
329 {
330 
331   switch(dir) {
332   case ASYSIO_I:
333     asysio_fd = open(ASYSIO_DSPDEV, O_RDONLY, 0);
334     asysio_input = 1;
335     break;
336   case ASYSIO_O:
337     asysio_fd = open(ASYSIO_DSPDEV, O_WRONLY, 0);
338     asysio_input = 0;
339     break;
340   case ASYSIO_IO:
341     asysio_fd = open(ASYSIO_DSPDEV, O_RDWR, 0);
342     asysio_input = 1;
343     break;
344   default:
345     fprintf(stderr, "  Error: Unexpected dir parameter value in \n");
346     fprintf(stderr, "         asysio_setup.\n\n");
347     return ASYS_ERROR;
348   }
349 
350   if (asysio_fd == -1)
351     {
352       fprintf(stderr, "  Error: Can't open device %s (%s)\n\n", ASYSIO_DSPDEV,
353 	      strerror(errno));
354       return ASYS_ERROR;
355     }
356   return ASYS_DONE;
357 
358 }
359 
360 /****************************************************************/
361 /*         signal handler for trapping SAOL infinite loops      */
362 /****************************************************************/
363 
asysio_iloop_handler(int signum)364 void asysio_iloop_handler(int signum)
365 {
366   fprintf(stderr, "  Error: Either\n\n");
367   fprintf(stderr, "    [1] The SAOL program has an infinite loop in it, or\n");
368   fprintf(stderr, "    [2] Content is too complex for real-time work.\n\n");
369   fprintf(stderr, "  Exiting program ...\n\n");
370   exit(0);
371 }
372 
373 
374 /****************************************************************/
375 /*         initializes iloop (heartbeat) interrupt              */
376 /****************************************************************/
377 
asysio_initiloop(void)378 int asysio_initiloop(void)
379 
380 {
381 
382   /*********************************************************/
383   /* set up signal handler for infinite-loop (iloop) timer */
384   /*********************************************************/
385 
386   if (sigemptyset(&asysio_iloop_action.sa_mask) < 0)
387     ASYSIO_ERROR_RETURN("Couldn't run sigemptyset(iloop) OS call");
388 
389   /* infinite-loop timer wins over midi overrun timer */
390 
391   if (sigaddset(&asysio_iloop_action.sa_mask, SIGALRM) < 0)
392     ASYSIO_ERROR_RETURN("Couldn't run sigaddset(iloop) OS call");
393 
394   asysio_iloop_action.sa_flags = SA_RESTART;
395   asysio_iloop_action.sa_handler = asysio_iloop_handler;
396 
397   if (sigaction(SIGPROF, &asysio_iloop_action, NULL) < 0)
398     ASYSIO_ERROR_RETURN("Couldn't set up SIGPROF signal handler");
399 
400 
401   /************************/
402   /* set up timer and arm */
403   /************************/
404 
405   asysio_iloop_timer.it_value.tv_sec = 3;
406   asysio_iloop_timer.it_value.tv_usec = 0;
407   asysio_iloop_timer.it_interval.tv_sec = 0;
408   asysio_iloop_timer.it_interval.tv_usec = 0;
409 
410   if (setitimer(ITIMER_PROF, &asysio_iloop_timer, NULL) < 0)
411     ASYSIO_ERROR_RETURN("Couldn't set up ITIMER_PROF timer");
412 
413   return ASYS_DONE;
414 }
415 
416 /****************************************************************/
417 /*                 initializes sched_fifo                       */
418 /****************************************************************/
419 
asysio_initscheduler(void)420 int asysio_initscheduler(void)
421 
422 {
423 
424 #if ASYSIO_USEFIFO
425 
426   /*******************************/
427   /* set up sched_fifo variables */
428   /*******************************/
429 
430   memset(&asysio_otherparam, 0, sizeof(struct sched_param));
431   memset(&asysio_fifoparam, 0, sizeof(struct sched_param));
432 
433   if ((asysio_fifoparam.sched_priority =
434        sched_get_priority_max(SCHED_FIFO)) < 0)
435     ASYSIO_ERROR_RETURN("Couldn't get scheduling priority");
436 
437   asysio_fifoparam.sched_priority--;
438 
439   /********************************/
440   /* try to enter sched-fifo mode */
441   /********************************/
442 
443   asysio_fifo = !sched_setscheduler(0, SCHED_FIFO, &asysio_fifoparam);
444 
445 #endif
446 
447   return ASYS_DONE;
448 }
449 
450 /****************************************************************/
451 /*                 prints startup screen                        */
452 /****************************************************************/
453 
asysio_screenwriter(void)454 int asysio_screenwriter(void)
455 
456 {
457   int i, found;
458   int haslinmidi = 0;
459   float actual_latency;
460 
461 
462   fprintf(stderr, "%s ",  (ASYS_LATENCYTYPE == ASYS_HIGHLATENCY)?
463 	  "Streaming" : "Interactive");
464 
465   fprintf(stderr, "%s Audio ", (asysio_channels == 2) ? "Stereo" : "Mono");
466 
467 #if defined(ASYS_HASOUTPUT)
468   fprintf(stderr, "%s", asysio_input ? "Input/Output" : "Output");
469 #else
470   fprintf(stderr, "Input");
471 #endif
472 
473   found = i = 0;
474   while (i < csys_sfront_argc)
475     {
476       if (!(strcmp(csys_sfront_argv[i],"-bitc") &&
477 	    strcmp(csys_sfront_argv[i],"-bit") &&
478 	    strcmp(csys_sfront_argv[i],"-orc")))
479 	{
480 	  i++;
481 	  fprintf(stderr, " for %s", csys_sfront_argv[i]);
482 	  found = 1;
483 	  break;
484 	}
485       i++;
486     }
487   if (!found)
488     fprintf(stderr, " for UNKNOWN");
489 
490 
491   i = 0;
492   while (i < csys_sfront_argc)
493     {
494       if (!strcmp(csys_sfront_argv[i],"-cin"))
495 	{
496 	  i++;
497 	  fprintf(stderr, " (-cin %s)", csys_sfront_argv[i]);
498 	  break;
499 	}
500       i++;
501     }
502   fprintf(stderr, "\n\n");
503 
504 
505 #if defined(CSYS_CDRIVER_LINMIDI)
506 
507   haslinmidi = 1;
508 
509 #endif
510 
511 #if (defined(CSYS_CDRIVER_LINMIDI) || defined(CSYS_CDRIVER_ALSAMIDI)\
512       || defined(CSYS_CDRIVER_ALSASEQ) || defined(CSYS_CDRIVER_ASCII))
513 
514   /* list midi presets available */
515 
516   fprintf(stderr,
517 	  "MIDI Preset Numbers (use MIDI controller to select):\n\n");
518 
519   for (i = 0; i < CSYS_PRESETNUM; i++)
520     {
521       fprintf(stderr, "%3i. %s",
522 	      csys_presets[i].preset,
523 	      csys_instr[csys_presets[i].index].name);
524       if ((i&1))
525 	fprintf(stderr, "\n");
526       else
527 	{
528 	  fprintf(stderr, "\t\t");
529 	  if (i == (CSYS_PRESETNUM-1))
530 	    fprintf(stderr, "\n");
531 	}
532     }
533   fprintf(stderr, "\n");
534 
535 #endif
536 
537 #if defined(CSYS_CDRIVER_ASCII)
538 
539   fprintf(stderr,
540   "To play tunes on ASCII keyboard: a-z for notes, 0-9 for MIDI presets,\n");
541   fprintf(stderr,
542   "cntrl-C exits. If autorepeat interferes, exit and run 'xset -r' (in X).\n\n");
543 
544 #endif
545 
546   /* diagnose best flags to use, and if they are used */
547 
548 #ifdef ASYS_HASOUTPUT
549 
550   if ((ASYS_LATENCYTYPE == ASYS_HIGHLATENCY) || asysio_input ||
551       (!haslinmidi))
552     {
553       if (geteuid() || (ASYS_TIMEOPTION == ASYS_TIMESYNC))
554 	{
555 	  fprintf(stderr, "For best results, make these changes:\n");
556 	  fprintf(stderr, "\n");
557 	  if (ASYS_TIMEOPTION == ASYS_TIMESYNC)
558 	    fprintf(stderr, "   * Remove sfront -timesync flag\n");
559 	  if (geteuid())
560 	    fprintf(stderr, "   * Run sa.c executable as root.\n");
561 	  fprintf(stderr, "\n");
562 	}
563     }
564   else
565     {
566       fprintf(stderr, "This application runs best as root (%s), with:\n",
567 	      !geteuid() ? "which you are": "which you aren't");
568       fprintf(stderr, "\n");
569       fprintf(stderr, "  [1] Sfront -playback flag. Good audio quality, keeps\n");
570       fprintf(stderr, "      the mouse/kbd alive");
571       fprintf(stderr, "%s.\n", (ASYS_TIMEOPTION == ASYS_PLAYBACK) ?
572 	      " (currently chosen)":"");
573       fprintf(stderr, "  [2] Sfront -timesync flag. Better quality, console\n");
574       fprintf(stderr, "      freezes during MIDI input");
575       fprintf(stderr, "%s.\n", (ASYS_TIMEOPTION == ASYS_TIMESYNC) ?
576 	      " (currently chosen)":"");
577       fprintf(stderr, "\n");
578     }
579 
580 #endif
581 
582   /* latency information */
583 
584 #if (defined(ASYS_HASOUTPUT))
585 
586   ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOSPACE, &asysio_info);
587 
588   fprintf(stderr, "If audio artifacts still occur, try");
589 
590   actual_latency = ATIME*ASYSO_LNUMBUFF*(asysio_size >> (asysio_channels - 1));
591 
592   if (asysio_info.fragstotal < ASYSO_LNUMBUFF)
593     {
594       fprintf(stderr, " sfront -latency %f flag, and see\n",
595 	      0.5F*actual_latency);
596     }
597   else
598     {
599       fprintf(stderr, " sfront -latency %f flag, and see\n",
600 	      2.0F*actual_latency);
601 
602     }
603   if (ASYS_LATENCYTYPE == ASYS_LOWLATENCY)
604     fprintf(stderr, "http://www.cs.berkeley.edu/"
605 	    "~lazzaro/sa/sfman/user/use/index.html#interact\n") ;
606   else
607     fprintf(stderr, "http://www.cs.berkeley.edu/"
608 	    "~lazzaro/sa/sfman/user/use/index.html#stream\n") ;
609 
610   fprintf(stderr, "\n");
611 
612   if ((asysio_bsize != ASYSIO_FRAGMIN) &&
613       (asysio_bsize == asysio_requested_bsize) &&
614       (ASYS_LATENCYTYPE == ASYS_LOWLATENCY))
615   {
616     fprintf(stderr, "If interactive response is slow, try ");
617     fprintf(stderr, "sfront -latency %f flag.\n", 0.5F*actual_latency);
618     fprintf(stderr, "\n");
619   }
620 
621 #endif
622 
623   fprintf(stderr,
624   "USE AT YOUR OWN RISK. Running as root may damage your file system,\n");
625   fprintf(stderr,
626   "and network use may result in a malicious attack on your machine.\n\n");
627 
628 #if (ASYSIO_USEFIFO && (ASYS_TIMEOPTION == ASYS_TIMESYNC))
629 
630   if (!geteuid())
631     {
632       fprintf(stderr,
633       "NOTE: Mouse and keyboard are frozen for %i seconds after a MIDI\n",
634 	      ASYSIO_SYNC_TIMEOUT);
635       fprintf(stderr,
636 	      "NoteOn or NoteOff is received. Do not be alarmed.\n");
637     }
638 
639 #endif
640 
641   if (NSYS_NET)
642     fprintf(stderr, "Network status: Contacting SIP server\n");
643 
644   return ASYS_DONE;
645 
646 }
647 
648 
649 /****************************************************************/
650 /*        setup operations common to input and output           */
651 /****************************************************************/
652 
asysio_setup(int srate,int channels,int dir,int toption)653 int asysio_setup(int srate, int channels, int dir, int toption)
654 
655 {
656   int i, j, maxfrag;
657 
658   /******************/
659   /* open soundcard */
660   /******************/
661 
662   if (asysio_opendevice(dir, toption) == ASYS_ERROR)
663     return ASYS_ERROR;
664 
665   /**************************************/
666   /* set up bidirectional I/O if needed */
667   /**************************************/
668 
669   if (dir == ASYSIO_IO)
670     {
671 
672 #if (ASYSIO_OSTYPE != ASYSIO_FREEBSD)
673 
674       ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_SETDUPLEX, 0);
675 
676 #endif
677 
678       ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETCAPS, &j);
679 
680       if (!(j & DSP_CAP_DUPLEX))
681 	ASYSIO_ERROR_RETURN_NOERRNO("Sound card can't do bidirectional audio");
682     }
683 
684   /************************/
685   /* range check channels */
686   /************************/
687 
688   if (channels > 2)
689     ASYSIO_ERROR_RETURN_NOERRNO("Sound card can't handle > 2 channels");
690 
691   /*********************/
692   /* set fragment size */
693   /*********************/
694 
695   j = ASYSIO_LOGFRAGMIN;
696   i = ASYSIO_FRAGMIN >> channels;   /* only works for channels = 1, 2 */
697 
698   /* find closest power-of-two fragment size to latency request */
699 
700   while (2*ATIME*i*ASYSO_LNUMBUFF < ASYS_LATENCY)
701     {
702       i <<= 1;
703       j++;
704     }
705   if ((ATIME*2*i*ASYSO_LNUMBUFF - ASYS_LATENCY) <
706       (ASYS_LATENCY - ATIME*i*ASYSO_LNUMBUFF))
707     {
708       i <<= 1;
709       j++;
710     }
711 
712   asysio_requested_bsize = 2*i*channels;
713 
714   maxfrag = (ASYS_TIMEOPTION != ASYS_TIMESYNC) ? ASYSO_LNUMBUFF :
715              ASYSO_LNUMBUFF + ((ACYCLE/i) + 1);
716 
717   j |= (maxfrag << 16);
718   ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_SETFRAGMENT, &j);
719 
720   /********************/
721   /* set audio format */
722   /********************/
723 
724   j = ASYSIO_AFORMAT;
725   ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_SETFMT, &j);
726 
727   if (j != ASYSIO_AFORMAT)
728     ASYSIO_ERROR_RETURN_NOERRNO("Soundcard can't handle native shorts");
729 
730   /****************************************************/
731   /* set number of channels -- later add channels > 2 */
732   /****************************************************/
733 
734   asysio_channels = channels--;
735   ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_STEREO, &channels);
736 
737   if (channels != (asysio_channels-1))
738     ASYSIO_ERROR_RETURN_NOERRNO("Soundcard can't handle number of channels");
739 
740   /*********************/
741   /* set sampling rate */
742   /*********************/
743 
744   asysio_srate = srate;
745   ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_SPEED, &srate);
746 
747   if (abs(asysio_srate - srate) > 1000)
748     ASYSIO_ERROR_RETURN_NOERRNO("Soundcard can't handle sampling rate");
749 
750   /******************************/
751   /* compute actual buffer size */
752   /******************************/
753 
754   ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETBLKSIZE, &asysio_bsize);
755   asysio_size = asysio_bsize >> 1;
756 
757   /*************************/
758   /* print out info screen */
759   /*************************/
760 
761   if (asysio_screenwriter() == ASYS_ERROR)
762     return ASYS_ERROR;
763 
764   /*********************************/
765   /* set SCHED_FIFO if appropriate */
766   /*********************************/
767 
768   if (asysio_initscheduler() == ASYS_ERROR)
769     return ASYS_ERROR;
770 
771   /**********************************/
772   /* set up iloop (heartbeat) timer */
773   /**********************************/
774 
775   if (asysio_initiloop() == ASYS_ERROR)
776     return ASYS_ERROR;
777 
778   return ASYS_DONE;
779 }
780 
781 
782 
783 #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT))
784 
785 /****************************************************************/
786 /*        sets up audio output for a given srate/channels       */
787 /****************************************************************/
788 
asys_osetup(int srate,int ochannels,int osample,char * oname,int toption)789 int asys_osetup(int srate, int ochannels, int osample,
790                 char * oname, int toption)
791 
792 {
793   if (asysio_setup(srate, ochannels, ASYSIO_O, toption) == ASYS_ERROR)
794     return ASYS_ERROR;
795 
796   if (!(asyso_buf = (short *)calloc(asysio_size, sizeof(short))))
797     ASYSIO_ERROR_RETURN("Can't allocate output buffer");
798 
799   return ASYS_DONE;
800 }
801 
802 #endif
803 
804 
805 #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT))
806 
807 /****************************************************************/
808 /*        sets up audio input for a given srate/channels       */
809 /****************************************************************/
810 
asys_isetup(int srate,int ichannels,int isample,char * iname,int toption)811 int asys_isetup(int srate, int ichannels, int isample,
812                 char * iname, int toption)
813 
814 {
815   if (asysio_setup(srate, ichannels, ASYSIO_I, toption) == ASYS_ERROR)
816     return ASYS_ERROR;
817   if (!(asysi_buf = (short *)malloc(asysio_bsize)))
818     ASYSIO_ERROR_RETURN("Can't allocate input buffer");
819 
820   return ASYS_DONE;
821 }
822 
823 #endif
824 
825 
826 #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT))
827 
828 /****************************************************************/
829 /*   sets up audio input and output for a given srate/channels  */
830 /****************************************************************/
831 
asys_iosetup(int srate,int ichannels,int ochannels,int isample,int osample,char * iname,char * oname,int toption)832 int asys_iosetup(int srate, int ichannels, int ochannels,
833                  int isample, int osample,
834                  char * iname, char * oname, int toption)
835 
836 
837 {
838 
839   if (ichannels != ochannels)
840     ASYSIO_ERROR_RETURN_NOERRNO
841       ("Soundcard needs SAOL inchannels == outchannels");
842 
843   if (asysio_setup(srate, ichannels, ASYSIO_IO, toption) == ASYS_ERROR)
844     return ASYS_ERROR;
845 
846   if (!(asysi_buf = (short *)malloc(asysio_bsize)))
847     ASYSIO_ERROR_RETURN("Can't allocate input buffer");
848 
849   if (!(asyso_buf = (short *)calloc(asysio_size, sizeof(short))))
850     ASYSIO_ERROR_RETURN("Can't allocate output buffer");
851 
852   return ASYS_DONE;
853 }
854 
855 #endif
856 
857 
858 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
859 /*            input, output, and recovery routines              */
860 /*______________________________________________________________*/
861 
862 
863 #if defined(ASYS_HASINPUT)
864 
865 /****************************************************************/
866 /*               gets one frame of audio from input             */
867 /****************************************************************/
868 
asys_getbuf(ASYS_ITYPE * asys_ibuf[],int * isize)869 int asys_getbuf(ASYS_ITYPE * asys_ibuf[], int * isize)
870 
871 {
872   int diffcompute, starttime;
873   int size, recv, bptr, retry;
874 
875   *isize = asysio_size;
876 
877   if (*asys_ibuf == NULL)
878     *asys_ibuf = asysi_buf;
879 
880   ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETISPACE, &asysio_info);
881 
882 #if defined(ASYS_HASOUTPUT)
883 
884   if (diffcompute = (asysio_info.bytes < asysio_bsize))
885     {
886       ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_ptr);
887       starttime = asysio_ptr.bytes;
888     }
889 
890 #endif
891 
892   retry = bptr = 0;
893   size = asysio_bsize;
894 
895   while ((recv = read(asysio_fd, &((*asys_ibuf)[bptr]), size)) != size)
896     {
897       if (++retry > ASYSIO_MAXRETRY)
898 	ASYSIO_ERROR_RETURN("Too many I/O retries -- asys_getbuf");
899 
900       if (recv < 0)  /* errors */
901 	{
902 	  if ((errno == EAGAIN) || (errno == EINTR))
903 	    continue;
904 	  else
905 	    ASYSIO_ERROR_RETURN("Read error on output audio device");
906 	}
907       else
908 	{
909 	  bptr += recv; /* partial read */
910 	  size -= recv;
911 	}
912     }
913 
914 #if defined(ASYS_HASOUTPUT)
915 
916   if (diffcompute)
917     {
918       ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_ptr);
919       asysio_blocktime += (asysio_ptr.bytes - starttime);
920     }
921 
922 #endif
923 
924   return ASYS_DONE;
925 }
926 
927 #endif
928 
929 
930 #if defined(ASYS_HASOUTPUT)
931 
932 /****************************************************************/
933 /*               sends one frame of audio to output             */
934 /****************************************************************/
935 
asys_putbuf(ASYS_OTYPE * asys_obuf[],int * osize)936 int asys_putbuf(ASYS_OTYPE * asys_obuf[], int * osize)
937 
938 
939 {
940   int size, sent, bptr, retry;
941   int diffcompute, starttime;
942 
943   size = (*osize)*2;
944 
945 
946   if (asysio_reset)
947     return ASYS_DONE;
948 
949   ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOSPACE, &asysio_info);
950 
951   asysio_reset = (++asysio_puts > ASYSO_LNUMBUFF) &&
952     (asysio_info.fragments == asysio_info.fragstotal);
953   if (asysio_reset)
954     return ASYS_DONE;
955 
956 #if (ASYS_TIMEOPTION != ASYS_TIMESYNC)
957 
958   if (diffcompute = (asysio_info.bytes < size))
959     {
960       ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_ptr);
961       starttime = asysio_ptr.bytes;
962     }
963 
964 #endif
965 
966   retry = bptr = 0;
967   while ((sent = write(asysio_fd, &((*asys_obuf)[bptr]), size)) != size)
968     {
969       if (++retry > ASYSIO_MAXRETRY)
970 	ASYSIO_ERROR_RETURN("Too many I/O retries -- asys_putbuf");
971 
972       if (sent < 0)  /* errors */
973 	{
974 	  if ((errno == EAGAIN) || (errno == EINTR))
975 	    continue;
976 	  else
977 	    ASYSIO_ERROR_RETURN("Write error on output audio device");
978 	}
979       else
980 	{
981 	  bptr += sent;  /* partial write */
982 	  size -= sent;
983 	}
984     }
985 
986 #if (ASYS_TIMEOPTION != ASYS_TIMESYNC)
987 
988   if (diffcompute)
989     {
990       ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_ptr);
991       asysio_blocktime += (asysio_ptr.bytes - starttime);
992     }
993 
994 #endif
995 
996   *osize = asysio_size;
997   return ASYS_DONE;
998 }
999 
1000 
1001 /****************************************************************/
1002 /*        creates buffer, and generates starting silence        */
1003 /****************************************************************/
1004 
asys_preamble(ASYS_OTYPE * asys_obuf[],int * osize)1005 int asys_preamble(ASYS_OTYPE * asys_obuf[], int * osize)
1006 
1007 {
1008   int i;
1009 
1010   *asys_obuf = asyso_buf;
1011   *osize = asysio_size;
1012 
1013   for(i = 0; i < ASYSO_LNUMBUFF; i++)
1014     if (asys_putbuf(asys_obuf, osize) == ASYS_ERROR)
1015       return ASYS_ERROR;
1016 
1017   return ASYS_DONE;
1018 }
1019 
1020 
1021 /****************************************************************/
1022 /*               recovers from an overrun                       */
1023 /****************************************************************/
1024 
asysio_recover(void)1025 int asysio_recover(void)
1026 
1027 {
1028   int size, recv, bptr, retry;
1029   int i;
1030 
1031   asysio_reset = 0;
1032 
1033   memset(asyso_buf, 0, asysio_bsize);
1034 
1035   /*************************/
1036   /* flush input if needed */
1037   /*************************/
1038 
1039 #if defined(ASYS_HASINPUT)
1040 
1041   ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETISPACE, &asysi_info);
1042 
1043   while (asysi_info.fragments > 0)
1044     {
1045       retry = bptr = 0;
1046       size = asysio_bsize;
1047 
1048       while ((recv = read(asysio_fd, &(asysi_buf[bptr]), size)) != size)
1049 	{
1050 	  if (++retry > ASYSIO_MAXRETRY)
1051 	    ASYSIO_ERROR_RETURN("Too many I/O retries -- asysio_recover");
1052 
1053 	  if (recv < 0)  /* errors */
1054 	    {
1055 	      if ((errno == EAGAIN) || (errno == EINTR))
1056 		continue;
1057 	      else
1058 		ASYSIO_ERROR_RETURN("Read error on output audio device");
1059 	    }
1060 	  else
1061 	    {
1062 	      bptr += recv; /* partial read */
1063 	      size -= recv;
1064 	    }
1065 	}
1066 
1067       ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETISPACE, &asysi_info);
1068     }
1069 
1070   ibusidx = 0;
1071   if (asys_getbuf(&asys_ibuf, &EV(asys_isize))==ASYS_ERROR)
1072     return ASYS_ERROR;
1073 
1074 #endif
1075 
1076   /**************************************/
1077   /* fill latency interval with silence */
1078   /**************************************/
1079 
1080   asysio_puts = 0;
1081   for(i = 0; i < ASYSO_LNUMBUFF; i++)
1082     if (asys_putbuf(&asyso_buf, &asysio_size) == ASYS_ERROR)
1083       return ASYS_ERROR;
1084 
1085   return ASYS_DONE;
1086 
1087 }
1088 
1089 
1090 #endif
1091 
1092 
1093 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1094 /*        ksync() system for time synchronization          */
1095 /*_________________________________________________________*/
1096 
1097 #if defined(ASYS_KSYNC)
1098 
1099 /***********************************************************/
1100 /*         initializes k-rate boundaries sync              */
1101 /***********************************************************/
1102 
ksyncinit()1103 void ksyncinit()
1104 
1105 {
1106   asysio_sync_target = asysio_sync_incr = ACYCLE*asysio_channels*2;
1107   asysio_sync_cpuscale = 1.0F/asysio_sync_incr;
1108 
1109   /* for -timesync, set up SCHED_FIFO watchdog state machine */
1110 
1111 #if (ASYSIO_USEFIFO && (ASYS_TIMEOPTION == ASYS_TIMESYNC))
1112 
1113   if (asysio_fifo)
1114 
1115     {
1116       asysio_sync_state = ASYSIO_SYNC_SCHEDOTHER;
1117       if (sched_setscheduler(0, SCHED_OTHER, &asysio_otherparam))
1118 	epr(0,NULL,NULL,"internal error -- sched_other unavailable");
1119     }
1120 
1121 #endif
1122 
1123   /* elsewise, set up SCHED_FIFO monitor to force blocking */
1124 
1125 #if (ASYSIO_USEFIFO && (ASYS_TIMEOPTION != ASYS_TIMESYNC))
1126 
1127   asysio_sync_noblock = 0;
1128   asysio_sync_sleeptime.tv_sec = 0;
1129   asysio_sync_sleeptime.tv_nsec = 2000001;  /* 2ms + epsilon forces block */
1130 
1131 #endif
1132 
1133 }
1134 
1135 
1136 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1137 /*     different ksync()s for -timesync and -playback       */
1138 /*__________________________________________________________*/
1139 
1140 
1141 #if (ASYS_TIMEOPTION != ASYS_TIMESYNC)
1142 
1143 /***********************************************************/
1144 /*         synchronizes on k-rate boundaries               */
1145 /***********************************************************/
1146 
ksync()1147 float ksync()
1148 
1149 {
1150   float ret;
1151   int comptime;
1152 
1153   if (asysio_reset)
1154     {
1155       if (asysio_recover()==ASYS_ERROR)
1156 	epr(0,NULL,NULL, "Soundcard error -- failed recovery.");
1157       asysio_sync_target = asysio_sync_incr;
1158       ret = 1.0F;
1159     }
1160   else
1161     {
1162 
1163       ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_sync_ptr);
1164 
1165       if (asysio_sync_target == asysio_sync_incr)
1166 	ret = 0.0F;
1167       else
1168 	{
1169 	  comptime = asysio_sync_ptr.bytes - asysio_blocktime;
1170 	  if (comptime > asysio_sync_target)
1171 	    ret = 1.0F;
1172 	  else
1173 	    ret = (asysio_sync_cpuscale*
1174 		   (asysio_sync_incr - (asysio_sync_target - comptime)));
1175 	}
1176 
1177       if ((asysio_sync_target = asysio_sync_incr + asysio_sync_ptr.bytes) < 0)
1178 	epr(0,NULL,NULL,"Soundcard error -- rollover.");
1179     }
1180 
1181   /* reset infinite-loop timer */
1182 
1183   if (setitimer(ITIMER_PROF, &asysio_iloop_timer, NULL) < 0)
1184     {
1185       fprintf(stderr, "  Runtime Errno Message: %s\n", strerror(errno));
1186       epr(0,NULL,NULL, "Soundcard error -- Couldn't reset ITIMER_PROF");
1187     }
1188 
1189 #if ASYSIO_USEFIFO
1190 
1191   if (asysio_fifo)
1192     {
1193       /* let other processes run if pending too long */
1194 
1195       if (asysio_blocktime)
1196 	asysio_sync_noblock = 0;
1197       else
1198 	asysio_sync_noblock++;
1199 
1200       if (asysio_sync_noblock > ASYSIO_MAXBLOCK)
1201 	{
1202 	  nanosleep(&asysio_sync_sleeptime, NULL);
1203 	  asysio_sync_noblock = 0;
1204 	}
1205     }
1206 
1207 #endif
1208 
1209   asysio_blocktime = 0;
1210   return ret;
1211 }
1212 
1213 #endif
1214 
1215 
1216 #if (ASYS_TIMEOPTION == ASYS_TIMESYNC)
1217 
1218 /***********************************************************/
1219 /*         synchronizes on k-rate boundaries               */
1220 /***********************************************************/
1221 
ksync()1222 float ksync()
1223 
1224 {
1225   float ret;
1226   int comptime;
1227 
1228   if (!asysio_reset)
1229     {
1230       ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_sync_ptr);
1231       if (asysio_sync_ptr.bytes > asysio_sync_target)
1232 	{
1233 	  comptime = asysio_sync_ptr.bytes - asysio_blocktime;
1234 	  if (comptime < asysio_sync_target)
1235 	    ret = (asysio_sync_cpuscale*
1236 		   (asysio_sync_incr - (asysio_sync_target - comptime)));
1237 	  else
1238 	    ret = 1.0F;
1239 	  ret = (asysio_sync_target != asysio_sync_incr) ? ret : 0.0F;
1240 	}
1241       else
1242 	{
1243 	  comptime = asysio_sync_ptr.bytes - asysio_blocktime;
1244 	  ret = (asysio_sync_cpuscale*
1245 		 (asysio_sync_incr - (asysio_sync_target - comptime)));
1246 	  asysio_reset = asysio_input &&
1247 	    ((asysio_sync_target-asysio_sync_ptr.bytes) == asysio_sync_incr);
1248 	  while ((asysio_sync_ptr.bytes < asysio_sync_target) && !asysio_reset)
1249 	    {
1250 	      ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOSPACE, &asysio_info);
1251 	      asysio_reset = (asysio_info.fragments == asysio_info.fragstotal);
1252 	      ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR,&asysio_sync_ptr);
1253 	    }
1254 	}
1255     }
1256   if (asysio_reset)
1257     {
1258       if (asysio_recover()==ASYS_ERROR)
1259 	epr(0,NULL,NULL,"Sound driver error -- failed recovery.");
1260       ASYSIO_IOCTL_CALL(asysio_fd, SNDCTL_DSP_GETOPTR, &asysio_sync_ptr);
1261       asysio_sync_target = asysio_sync_ptr.bytes;
1262       ret = 1.0F;
1263     }
1264   if ((asysio_sync_target += asysio_sync_incr) < 0)
1265     epr(0,NULL,NULL,"Sound driver error -- rollover.");
1266 
1267   /* reset infinite-loop timer */
1268 
1269   if (setitimer(ITIMER_PROF, &asysio_iloop_timer, NULL) < 0)
1270     {
1271       fprintf(stderr, "  Runtime Errno Message: %s\n", strerror(errno));
1272       epr(0,NULL,NULL, "Soundcard error -- Couldn't reset ITIMER_PROF");
1273     }
1274 
1275 #if ASYSIO_USEFIFO
1276 
1277   if (asysio_fifo)
1278     {
1279       switch (asysio_sync_state) {
1280       case ASYSIO_SYNC_ACTIVE:
1281 	if (!csysi_newnote)
1282 	  {
1283 	    asysio_sync_state = ASYSIO_SYNC_WAITING;
1284 	    asysio_sync_waitstart = time(NULL);
1285 	  }
1286 	break;
1287       case ASYSIO_SYNC_WAITING:
1288 	if (csysi_newnote)
1289 	  asysio_sync_state = ASYSIO_SYNC_ACTIVE;
1290 	else
1291 	  if ((time(NULL) - asysio_sync_waitstart) >= ASYSIO_SYNC_TIMEOUT)
1292 	    {
1293 	      asysio_sync_state = ASYSIO_SYNC_SCHEDOTHER;
1294 	      if (sched_setscheduler(0, SCHED_OTHER, &asysio_otherparam))
1295 		epr(0,NULL,NULL,"internal error -- sched_other unavailable");
1296 	    }
1297 	break;
1298       case ASYSIO_SYNC_SCHEDOTHER:
1299 	if (csysi_newnote)
1300 	  {
1301 	    asysio_sync_state = ASYSIO_SYNC_ACTIVE;
1302 	    if (sched_setscheduler(0, SCHED_FIFO, &asysio_fifoparam))
1303 	      fprintf(stderr, "  Note: Process no longer root, "
1304 		      "improved audio quality no longer possible.\n");
1305 	  }
1306 	break;
1307       }
1308     }
1309 
1310 #endif
1311 
1312   asysio_blocktime = 0;
1313   return ret;
1314 }
1315 
1316 #endif
1317 
1318 #endif /* ASYS_KSYNC */
1319 
1320 #undef ASYSIO_IOCTL_CALL
1321 #undef ASYSIO_ERROR_RETURN
1322 #undef ASYSIO_ERROR_RETURN_NOERRNO
1323 #undef ASYSIO_LINUX
1324 #undef ASYSIO_FREEBSD
1325 #undef ASYSIO_OSTYPE
1326 #undef ASYSIO_DSPDEV
1327 #undef ASYSIO_AFORMAT
1328 #undef ASYSIO_I
1329 #undef ASYSIO_O
1330 #undef ASYSIO_IO
1331 #undef ASYSIO_FRAGMIN
1332 #undef ASYSIO_LOGFRAGMIN
1333 #undef ASYSO_LNUMBUFF
1334 #undef ASYSIO_MAXRETRY
1335 
1336 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1337 /*                    end of soundcard driver                   */
1338 /*______________________________________________________________*/
1339 
1340 
1341