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