1 /* $Header: /home/yav/catty/fkiss/RCS/sound.c,v 1.21 2000/10/17 05:01:09 yav Exp $
2  * fkiss sound routine for Linux and FreeBSD
3  * written by yav <yav@bigfoot.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 
20 char id_sound[] = "$Id: sound.c,v 1.21 2000/10/17 05:01:09 yav Exp $";
21 
22 #include <stdio.h>
23 #include "config.h"
24 #include "headers.h"
25 
26 #ifdef HAVE_FCNTL_H
27 # include <fcntl.h>
28 #endif
29 
30 #ifdef HAVE_SYS_STAT_H
31 # include <sys/stat.h>
32 #else
33 # ifdef HAVE_STAT_H
34 #  include <stat.h>
35 # endif
36 #endif
37 
38 #ifdef HAVE_UNISTD_H
39 # include <unistd.h>
40 #endif
41 
42 #ifdef linux
43 # define USE_DSP
44 # define DEV_SOUND	"/dev/dsp"
45 # ifdef HAVE_FCNTL_H
46 #   include <fcntl.h>
47 # endif
48 # ifdef HAVE_SYS_IOCTL_H
49 #   include <sys/ioctl.h>
50 # endif
51 # include <linux/soundcard.h>
52 #endif
53 
54 #ifdef __FreeBSD__
55 # define USE_DSP
56 # define DEV_SOUND	"/dev/dsp"
57 # include <sys/soundcard.h>
58 #endif
59 
60 #ifndef DEV_SOUND
61 # define DEV_SOUND	"/dev/audio"
62 #endif
63 
64 #ifdef HAVE_LIBESD
65 # define USE_ESD 1
66 #else  /* HAVE_LIBESD */
67 # define USE_ESD 0
68 #endif /* HAVE_LIBESD */
69 
70 #if USE_ESD
71 # ifdef HAVE_ESD_H
72 #  include <esd.h>
73 # endif /* HAVE_ESD_H */
74 #endif /* USE_ESD */
75 
76 #define PUBLIC_SOUND_C
77 #include "extern.h"
78 
79 #include "ulaw.h"
80 
81 char *midi_player = NULL;
82 char *sound_device = DEV_SOUND;
83 int sound_debug = 1;		/* debug information print level
84 				 * 0: print nothing, silent
85 				 * 1: error messages
86 				 * 2: all messages
87 				 */
88 int sound_output = 1;		/* 0:Not output to device, other:output */
89 static int sound_enable = 0;	/* 0:disable other:enable */
90 int sound_force = 0;		/* no conversion, force write DSP data */
91 
92 int use_esd = USE_ESD;
93 static int esd;
94 unsigned char *esd_host = NULL;
95 
96 
97 typedef struct _sf {
98   int sound_rate;		/* sampling rate Hz */
99   int sound_channels;		/* 1:mono 2:stereo */
100   int sound_bits;		/* bits per sample 8 or 16 */
101   int sound_ulaw_encoded;	/* input ulaw encoded */
102   int sound_little_endian;	/* input little-endian */
103   int sound_unsigned;		/* input zero level 0x80 */
104   int sample_bytes;		/* byts per sample 1 or 2 */
105   int sound_converted;
106   int sound_sample_id;		/* ESD sample ID */
107 } SF;
108 
109 
110 #define SOUND_CACHE_MAX 64
111 
112 typedef struct {
113   char *pathname;
114   char *buffer;
115   long size;
116   long data_ofs;
117   SF sf;
118 } CACHE_TABLE;
119 
120 static CACHE_TABLE *cache_list = NULL;
121 static int cache_n = 0;
122 
123 #ifdef USE_DSP
124 
125 static int dsp_rate;
126 static int dsp_bits;
127 static int dsp_channels;
128 
129 #endif
130 
adjust_parms(sf)131 void adjust_parms(sf)
132      SF *sf;
133 {
134   if (sf->sound_bits < 1)
135     sf->sound_bits = 8;
136 #ifdef USE_DSP
137   sf->sample_bytes = (sf->sound_bits+7) / 8;
138   /* defaut 8bit data zero level 0x80 */
139 #endif
140 }
141 
142 #ifdef USE_DSP
143 
setup_dsp(fd,p)144 int setup_dsp(fd, p)
145      int fd;
146      SF *p;
147 {
148   /* copy to DSP setting parms */
149   dsp_channels = p->sound_channels;
150   dsp_bits = p->sound_bits;
151   dsp_rate = p->sound_rate;
152   ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &dsp_channels);
153   ioctl(fd, SOUND_PCM_WRITE_BITS, &dsp_bits);
154   ioctl(fd, SOUND_PCM_WRITE_RATE, &dsp_rate);
155   return 0;
156 }
157 
conv_center80(buf,n)158 void conv_center80(buf, n)
159      unsigned char *buf;
160      int n;
161 {
162   while (n--) {
163     *buf += 0x80;
164     buf++;
165   }
166 }
167 
get_highest_bytes(sf,buf,n)168 int get_highest_bytes(sf, buf, n)
169      SF *sf;
170      unsigned char *buf;
171      int n;
172 {
173   int i, d;
174   unsigned char *p;
175   unsigned char *p0;
176 
177   d = sf->sample_bytes * sf->sound_channels;
178   p0 = p = buf;
179   if (sf->sound_little_endian)
180     p0 += sf->sample_bytes - 1;
181   if (sf->sound_channels == 1) {
182     for (i = 0; i < n; i += d) {
183       *p++ = *p0;
184       p0 += d;
185     }
186   } else {
187     for (i = 0; i < n; i += d) {
188       *p++ = *p0;
189       *p++ = *(p0 + sf->sample_bytes);
190       p0 += d;
191     }
192   }
193   return (n / sf->sample_bytes);
194 }
195 
196 #endif /* USE_DSP */
197 
198 /* convert ulaw to  0x80 center 8bit linear PCM */
conv_ulaw_dsp(buf,n)199 void conv_ulaw_dsp(buf, n)
200      unsigned char *buf;
201      int n;
202 {
203   while (n--)
204     *buf++ = ulaw_dsp[*buf];
205 }
206 
convert_sound(sf,buf,n)207 int convert_sound(sf, buf, n)
208      SF *sf;
209      char *buf;
210      int n;
211 {
212   if (sound_force)
213     return n;
214   if (sf->sound_converted)
215     return n;
216   if (sf->sound_ulaw_encoded) {
217     conv_ulaw_dsp(buf, n);
218     return n;
219   }
220 #ifdef USE_DSP
221   if (dsp_bits == 8) {
222     if (sf->sample_bytes != 1)
223       n = get_highest_bytes(sf, buf, n);
224     /* adjust zero level 0x80 */
225     if (!sf->sound_unsigned)
226       conv_center80(buf, n);
227   }
228 #endif
229   return n;
230 }
231 
232 #ifdef USE_DSP
play_sync(fd)233 void play_sync(fd)
234      int fd;
235 {
236   if (sound_debug >= 2)
237     fputs("sync", stderr);
238   ioctl(fd, SNDCTL_DSP_SYNC);
239   if (sound_debug >= 2)
240     fputs(" ", stderr);
241 }
242 #endif
243 
play_sound(fd,buf,n)244 int play_sound(fd, buf, n)
245      int fd;
246      char *buf;
247      int n;
248 {
249 #ifdef USE_DSP
250   play_sync(fd);
251 #endif
252   if (sound_debug >= 2)
253     fputs("write", stderr);
254   if (sound_output)
255     write(fd, buf, n);
256   if (sound_debug >= 2)
257     fputs(" ", stderr);
258   return 0;
259 }
260 
get_short(sf,p)261 short get_short(sf, p)
262      SF *sf;
263      unsigned char *p;
264 {
265   return sf->sound_little_endian ?
266     (*(p+1) << 8) | *p :
267     (*p << 8) | *(p+1);
268 }
269 
get_long(sf,p)270 long get_long(sf, p)
271      SF *sf;
272      unsigned char *p;
273 {
274   return sf->sound_little_endian ?
275     (((long)*(p+3)) << 24) | (((long)*(p+2)) << 16) | (*(p+1) << 8) | *p :
276     (((long)*p) << 24) | (((long)*(p+1)) << 16) | (*(p+2) << 8) | *(p+3);
277 }
278 
279 /* check Sun Audio file header
280  * return data offset to play
281  *        == 0  : Not au file
282  *        <  0  : Not supported format
283  */
check_au_header(sf,buf)284 int check_au_header(sf, buf)
285      SF *sf;
286      unsigned char *buf;	/* data buffer */
287 {
288   long data_offset;
289   long data_type;
290   static struct {
291     int bits;			/* bits per sample */
292     int ulaw;			/* 0:linear 1:ulaw encoded */
293   } type_info[] = {
294     { 0, 0},			/* 0: dummy */
295     { 8, 1},			/* 1: 8-bit ISDN u-law */
296     { 8, 0},			/* 2: 8-bit linear PCM */
297     {16, 0},			/* 3:16-bit linear PCM */
298     {24, 0},			/* 4:24-bit linear PCM */
299     {32, 0},			/* 5:32-bit linear PCM */
300   };
301 
302   sf->sound_little_endian = 0;
303   if (strncmp(buf, ".snd", 4) != 0) {
304     if (strncmp(buf, "dns.", 4) != 0)
305       return 0;			/* Not au file! */
306     sf->sound_little_endian = 1;
307   }
308   data_type    = get_long(sf, buf+0x0c);
309   if (data_type < 1 || data_type > 5)
310     return -1;			/* Not supported format */
311   data_offset  = get_long(sf, buf+0x04);
312   /*  data_size    = get_long(buf+0x08); */
313   sf->sound_rate     = get_long(sf, buf+0x10);
314   sf->sound_channels = get_long(sf, buf+0x14);
315 
316   sf->sound_bits = type_info[data_type].bits;
317   sf->sound_ulaw_encoded = type_info[data_type].ulaw;
318   sf->sound_unsigned = 0;	/* xxx */
319   return data_offset;
320 }
321 
322 
323 /* check Microsoft RIFF-WAVE header
324  * return data offset
325  *        == 0 : Not wav file
326  *        < 0  : Not supported format
327  */
check_wav_header(sf,buf,n)328 int check_wav_header(sf, buf, n)
329      SF *sf;
330      unsigned char *buf;
331      int n;
332 {
333   int i;
334   long data_rate;
335   long data_channel;
336   unsigned char *p;
337   long len;
338 
339   sf->sound_little_endian = 1;
340   if (strncmp(buf, "RIFF", 4))
341     return 0;			/* Not wav file */
342   len = get_long(sf, buf+4);
343   if (strncmp(buf+8, "WAVE", 4))
344     return 0;			/* Not wav file */
345 
346   p = buf+12;
347   if ((n -= 12) < 0)
348     return 0;
349   while (strncmp(p, "fmt ", 4) != 0) {
350     len = get_long(sf, p+4);
351     p += 8 + len;
352     if ((n -= 8 + len) < 0)
353       return 0;
354   }
355   len = get_long(sf, p+4);
356 
357   p += 8;
358   if ((n -= 8) < 0)
359     return 0;
360   i = get_short(sf, p);
361   switch (i) {
362   case 0x0001:			/* WAVE_FORMAT_PCM */
363     break;
364   case 0x0000:			/* WAVE_FORMAT_UNKNOWN */
365   case 0x0002:			/* WAVE_FORMAT_ADPCM */
366   case 0x0006:			/* WAVE_FORMAT_ALAW */
367   case 0x0007:			/* WAVE_FORMAT_MULAW */
368   case 0x0010:			/* WAVE_FORMAT_OKI_ADPCM */
369   case 0x0015:			/* WAVE_FORMAT_DIGISTD */
370   case 0x0016:			/* WAVE_FORMAT_DIGIFIX */
371   case 0x0101:			/* IBM_FORMAT_MULAW */
372   case 0x0102:			/* IBM_FORMAT_ALAW */
373   case 0x0103:			/* IBM_FORMAT_ADPCM */
374   default:
375     if (sound_debug)
376       fprintf(stderr, "RIFF-WAVE format 0x%04x not supported!\n", i);
377     return -1;			/* Not supported format */
378   }
379   data_channel = get_short(sf, p+2);
380   data_rate = get_long(sf, p+4);
381   /* long: average bytes/second */
382   /* short: block align */
383   i = get_short(sf, p+14);	/* bits/sample? */
384   if (sound_debug >= 2)
385     fprintf(stderr, "RIFF-WAVE %ld-channels, %ldHz, %d-bits/sample\n",
386 	    data_channel, data_rate, i);
387   switch (i) {
388   case 8:
389     i = 1; sf->sound_bits = 8; sf->sound_unsigned = 1;
390     break;
391   case 16:
392     i = 2; sf->sound_bits = 16; sf->sound_unsigned = 0;
393     break;
394   case 32:
395     i = 4; sf->sound_bits = 32; sf->sound_unsigned = 0;
396     break;
397   default:
398     if (sound_debug)
399       fprintf(stderr, "RIFF-WAVE 0x%04x-bits/sample not supported!\n", i);
400     return -1;			/* Not supported format */
401   }
402   p += len;
403   if ((n -= len) < 0)
404     return 0;
405 
406   while (strncmp(p, "data", 4)) {
407     len = get_long(sf, p+4);
408     if (sound_debug >= 2)
409       fprintf(stderr, "%08x %ld bytes section [%.4s] skip\n", p-buf, len, p);
410     p += 8 + len;
411     if ((n -= 8 + len) < 0)
412       return 0;
413   }
414 
415   /* number of samples = get_long(p+4) / i */
416   sf->sound_channels = data_channel;
417   sf->sound_rate = data_rate;
418   sf->sound_ulaw_encoded = 0;
419   p += 8;
420   if ((n -= 8) < 0)
421     return 0;
422   if (sound_debug >= 2)
423     fprintf(stderr, "RIFF-WAVE offset %d\n", p - buf);
424   return p - buf;		/* return data offset */
425 }
426 
disp_file_info(name)427 void disp_file_info(name)
428      char *name;
429 {
430   if (use_esd)
431     fprintf(stderr, "device: EsounD\n");
432   else
433     fprintf(stderr, "device: %s\n", sound_device);
434   fprintf(stderr, "input: %s\n", name == NULL ? "(stdin)" : name);
435 }
436 
disp_sound_info(sf,name)437 void disp_sound_info(sf, name)
438      SF *sf;
439      char *name;
440 {
441   fprintf(stderr, " %5dHz %2d-bit %d-channel",
442 	  sf->sound_rate, sf->sound_bits, sf->sound_channels);
443   if (sf->sound_ulaw_encoded)
444     fprintf(stderr, " u-law");
445   if (sf->sound_little_endian)
446     fprintf(stderr, " Little-endian");
447   if (!sf->sound_ulaw_encoded)
448     fprintf(stderr, " %s", sf->sound_unsigned ? "unsigned" : "signed");
449   fprintf(stderr, "\n");
450 }
451 
452 #ifdef USE_DSP
disp_dsp_info()453 void disp_dsp_info()
454 {
455   fprintf(stderr, " %5dHz %2d-bit %d-channel\n",
456 	  dsp_rate, dsp_bits, dsp_channels);
457 }
458 
459 #endif /* USE_DSP */
460 
decide_midi_player()461 void decide_midi_player()
462 {
463   char **p;
464   char *midilist[] = {
465     "/usr/bin/midiplay", "",
466     "/usr/bin/playmidi", "",
467     "/usr/local/bin/timidity", "-idq",
468     NULL
469   };
470 
471   if (midi_player == NULL) {
472     for(p = midilist; *p; p += 2) {
473       if (is_regular_file(*p)) {
474 	midi_player = ks_malloc(strlen(*p) + 1 + strlen(*(p+1)) + 1);
475 	sprintf(midi_player, "%s %s", *p, *(p+1));
476 	break;
477       }
478     }
479   }
480 }
481 
482 /* Check sound device
483  * return 0:OK other:NG
484  */
sound_init()485 int sound_init()
486 {
487   int fd;
488   struct stat st;
489 
490   cache_n = 0;
491 
492   decide_midi_player();
493 #if USE_ESD
494   if (use_esd) {
495     esd = esd_open_sound(esd_host);
496     if (sound_debug >= 2)
497       fprintf(stderr, "*esd open %d\n", esd);
498     if (sound_debug >= 2 && esd >= 0) {
499       esd_print_server_info(esd_get_all_info(esd)->server);
500     }
501     if (esd < 0) {
502       fprintf(stderr, "Cannot to connect EsounD server ``%s''.\n",
503 	      (esd_host ? (char *)esd_host : "(localhost)"));
504       use_esd = 0;
505     }
506   }
507 #endif /* USE_ESD */
508   if (!use_esd) {
509     /* sound device exist? */
510     if (stat(sound_device, &st) != 0)
511       return 1;			/* device not found */
512 
513     /* sound device writeble? */
514     fd = open(sound_device, O_WRONLY|O_NONBLOCK);
515     if (fd < 0)
516       return 2;			/* device open error */
517 
518     fcntl(fd, F_SETFL, ~O_NONBLOCK);
519     close(fd);
520   }
521   sound_enable = 1;
522   cache_list = (CACHE_TABLE *)malloc(sizeof(CACHE_TABLE)*SOUND_CACHE_MAX);
523   return 0;
524 }
525 
sound_end()526 void sound_end()
527 {
528   int i;
529 
530   for (i = 0; i < cache_n; i++) {
531     if (use_esd && (cache_list+i)->sf.sound_converted) {
532 #if USE_ESD
533       esd_sample_free(esd, (cache_list+i)->sf.sound_sample_id);
534       esd_sample_stop(esd, (cache_list+i)->sf.sound_sample_id);
535 #endif /* USE_ESD */
536     } else {
537       free((cache_list+i)->buffer);
538     }
539   }
540   if (cache_list != NULL)
541     free(cache_list);
542 #if USE_ESD
543   if (use_esd) {
544     esd_close(esd);
545     if (sound_debug >= 2)
546       fprintf(stderr, "*esd closed\n");
547   }
548 #endif /* USE_ESD */
549 }
550 
551 /* return audio file size
552  *  minus : file not found
553  */
sound_filesize(name)554 long sound_filesize(name)
555      char *name;
556 {
557   long r;
558   struct stat st;
559 
560   r = -1;
561   if (sound_enable && stat(name, &st) == 0)
562     r = st.st_size;
563   return r;
564 }
565 
cached_no(name)566 int cached_no(name)
567      char *name;
568 {
569   int i;
570 
571   for (i = 0; i < cache_n; i++)
572     if (strcmp(name, (cache_list+i)->pathname) == 0)
573       return i;
574   return -1;			/* not cached */
575 }
576 
577 /* cache audio data
578  * return minus cannot to cache
579  */
sound_cache(name)580 int sound_cache(name)
581      char *name;
582 {
583   char *p;
584   FILE *fp;
585   CACHE_TABLE *cp;
586 
587   if (!sound_enable)
588     return -1;
589   if (cached_no(name) >= 0)
590     return 0;			/* already cached */
591   if (cache_n >= SOUND_CACHE_MAX)
592     return -1;
593   cp = cache_list + cache_n;
594   cp->size = sound_filesize(name);
595   if (cp->size < 0)
596     return -1;
597   fp = fopen(name, "rb");
598   if (fp == NULL)
599     return -1;			/* Why? stat success, but fopen fail??? */
600   /* If name will be free, use strdup to keep string */
601   cp->pathname = name;
602   p = malloc(cp->size);
603   if (p == NULL) {
604     fclose(fp);
605     return -1;
606   }
607   fread(p, cp->size, 1, fp);
608   cp->buffer = p;
609   fclose(fp);
610 
611   bzero(&cp->sf, sizeof(cp->sf));
612   cp->data_ofs = check_wav_header(&cp->sf, cp->buffer, cp->size);
613   if (!cp->data_ofs)
614     cp->data_ofs = check_au_header(&cp->sf, cp->buffer, cp->size);
615   if (cp->data_ofs < 0) {
616     free(cp->buffer);
617     return -1;
618   }
619   convert_sound(&cp->sf, cp->buffer + cp->data_ofs, cp->size - cp->data_ofs);
620   cp->sf.sound_converted = 1;
621 
622 #if USE_ESD
623   if (use_esd) {
624     int	confirm_id;
625     esd_format_t format = 0;
626 
627     format = (cp->sf.sound_bits > 8 ? ESD_BITS16 : ESD_BITS8)
628       | (cp->sf.sound_channels > 1 ? ESD_STEREO : ESD_MONO)
629       | ESD_STREAM | ESD_PLAY;
630 
631     cp->sf.sound_sample_id = esd_sample_cache(esd, format,
632 					      cp->sf.sound_rate,
633 					      cp->size - cp->data_ofs,
634 					      name);
635 
636     write(esd, cp->buffer + cp->data_ofs, cp->size - cp->data_ofs);
637 
638     confirm_id = esd_confirm_sample_cache(esd);
639     if (confirm_id != cp->sf.sound_sample_id) {
640       fprintf(stderr, "* confirm_id %d, sample_id %d\n",
641 	      confirm_id, cp->sf.sound_sample_id);
642     }
643 
644 
645     free(cp->buffer);
646     cp->buffer = NULL;
647   }
648 #endif /* USE_ESD */
649 
650   cache_n++;
651   if (sound_debug >= 2)
652     fprintf(stderr, "sound_cache: ``%s'' cached.\n", name);
653   return 0;
654 }
655 
656 
657 /* Play audio file
658  * return 0: No error 1:file open error 2:device open error
659  */
sound_play(name)660 int sound_play(name)
661      char *name;		/* audio filename */
662 {
663   int i;
664   int fd = 0;
665   int cn;
666   long loadbytes;
667   long ofs = 0;
668   FILE *fp;
669   char buf[32*1024];		/* 8 * N bytes */
670   char *bufp;
671   SF sf, *sfp;
672   char *buf2;
673 #if USE_ESD
674   int esd_rate;
675   int sock = -1;
676   esd_format_t format = 0;
677   esd_info_t *esdctl;
678 #endif /* USE_ESD */
679 
680   if (!sound_enable)
681     return 0;
682 
683   bufp = name;
684   while (strstr(bufp + 1, ".mid") != NULL) bufp = strstr(bufp + 1, ".mid");
685   while (strstr(bufp + 1, ".MID") != NULL) bufp = strstr(bufp + 1, ".MID");
686   if ((!strncmp(bufp, ".mid", 4) || !strncmp(bufp, ".MID", 4)) &&
687        strlen(bufp) < 6)
688   {
689     buf2 = ks_malloc(strlen(midi_player) + 1 + strlen(name) + 1);
690     sprintf(buf2, "%s %s", midi_player, name);
691     ks_system2(buf2);
692     return 0;
693   }
694 
695   bzero(&sf, sizeof(sf));
696   bzero(buf, sizeof(buf));
697   if (name == NULL) {
698     fp = stdin;
699     bufp = buf;
700     loadbytes = fread(buf, 1, sizeof(buf), fp);
701     sfp = &sf;
702   } else {
703     cn = cached_no(name);
704     if (cn >= 0) {
705       fp = NULL;
706       sfp = &(cache_list+cn)->sf;
707       bufp = (cache_list+cn)->buffer;
708       loadbytes = (cache_list+cn)->size;
709       ofs = (cache_list+cn)->data_ofs;
710     } else {
711       fp = fopen(name, "rb");
712       if (fp == NULL)
713 	return 1;		/* Sound file open error */
714       bufp = buf;
715       loadbytes = fread(buf, 1, sizeof(buf), fp);
716       sfp = &sf;
717     }
718   }
719   if (sound_debug >= 2)
720     disp_file_info(name);
721 
722   if (!sfp->sound_converted) {
723     ofs = check_wav_header(sfp, bufp, loadbytes);
724     if (ofs == 0)
725       ofs = check_au_header(sfp, bufp);
726     if (ofs < 0) {
727       if (fp != NULL)
728 	fclose(fp);
729       return 3;			/* not supported format */
730     }
731     adjust_parms(sfp);
732   }
733 
734   if (sound_debug >= 2)
735     disp_sound_info(sfp, name);
736 
737   if (use_esd) {
738 #if USE_ESD
739     if (!sfp->sound_converted) {
740       format = (sfp->sound_bits > 8 ? ESD_BITS16 : ESD_BITS8)
741 	| (sfp->sound_channels > 1 ? ESD_STEREO : ESD_MONO)
742 	| ESD_STREAM | ESD_PLAY;
743       esd_rate = sfp->sound_rate;
744       sock = esd_play_stream_fallback(format, esd_rate, esd_host, name);
745       esdctl = esd_get_all_info(esd);
746     }
747 #endif /* USE_ESD */
748   } else {
749     fd = open(sound_device, O_WRONLY|O_NONBLOCK);
750     if (fd < 0) {
751       if (fp != NULL)
752 	fclose(fp);
753       return 2;			/* device open error */
754     }
755     fcntl(fd, F_SETFL, ~O_NONBLOCK);
756 #ifdef USE_DSP
757     setup_dsp(fd, sfp);
758     if (sound_debug >= 2)
759       disp_dsp_info();
760 #endif /* USE_DSP */
761   }
762 
763   if (use_esd && sfp->sound_converted) {
764 #if USE_ESD
765 #if 0
766     fprintf(stderr, "* loop %d\n", sfp->sound_sample_id);
767     esd_sample_loop(esd, sfp->sound_sample_id);
768 #else
769     esd_sample_play(esd, sfp->sound_sample_id);
770 #endif
771 #endif /* USE_ESD */
772   } else {
773     while (loadbytes) {
774       i = convert_sound(sfp, bufp+ofs, loadbytes-ofs);
775       if (sound_debug >= 2)
776 	fprintf(stderr, "%d ", i);
777       if (use_esd) {
778 #if USE_ESD
779 	write(sock, bufp+ofs, i);
780 #endif /* USE_ESD */
781       } else {
782 	play_sound(fd, bufp+ofs, i);
783       }
784       if (fp == NULL) {
785 	loadbytes = 0;
786       } else {
787 	ofs = 0;
788 	loadbytes = fread(buf, 1, sizeof(buf), fp);
789       }
790     }
791   }
792 
793   if (sound_debug >= 2)
794     fputs("fin ", stderr);
795 
796 #if USE_ESD
797   if (use_esd) {
798     if (sock >= 0) {
799       close(sock);
800     }
801   }
802 #endif /* USE_ESD */
803   if (!use_esd) {
804 #ifdef USE_DSP
805     play_sync(fd);
806 #endif
807     if (sound_debug >= 2)
808       fputs("close", stderr);
809     close(fd);
810   }
811 
812   if (sound_debug >= 2)
813     fputs(" \n", stderr);
814   if (fp != NULL)
815     fclose(fp);
816   return 0;
817 }
818 
819 /* End of file */
820