25003
|
1 /* sound.c -- sound support.
|
|
2 Copyright (C) 1998 Free Software Foundation.
|
|
3
|
|
4 This file is part of GNU Emacs.
|
|
5
|
|
6 GNU Emacs is free software; you can redistribute it and/or modify
|
|
7 it under the terms of the GNU General Public License as published by
|
|
8 the Free Software Foundation; either version 2, or (at your option)
|
|
9 any later version.
|
|
10
|
|
11 GNU Emacs is distributed in the hope that it will be useful,
|
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 GNU General Public License for more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License
|
|
17 along with GNU Emacs; see the file COPYING. If not, write to
|
|
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
19 Boston, MA 02111-1307, USA. */
|
|
20
|
|
21 /* Written by Gerd Moellmann <gerd@gnu.org>. Tested with Luigi's
|
|
22 driver on FreeBSD 2.2.7 with a SoundBlaster 16. */
|
|
23
|
|
24 #include <config.h>
|
|
25
|
|
26 #if defined HAVE_SOUND
|
|
27
|
|
28 #include <lisp.h>
|
|
29 #include <fcntl.h>
|
|
30 #include <unistd.h>
|
|
31 #include <sys/types.h>
|
|
32 #include <dispextern.h>
|
|
33 #include <errno.h>
|
|
34
|
|
35 /* FreeBSD has machine/soundcard.h. Voxware sound driver docs mention
|
|
36 sys/soundcard.h. So, let's try whatever's there. */
|
|
37
|
|
38 #ifdef HAVE_MACHINE_SOUNDCARD_H
|
|
39 #include <machine/soundcard.h>
|
|
40 #endif
|
|
41 #ifdef HAVE_SYS_SOUNDCARD_H
|
|
42 #include <sys/soundcard.h>
|
|
43 #endif
|
|
44
|
|
45 #define max(X, Y) ((X) > (Y) ? (X) : (Y))
|
|
46 #define min(X, Y) ((X) < (Y) ? (X) : (Y))
|
|
47 #define abs(X) ((X) < 0 ? -(X) : (X))
|
|
48
|
|
49 /* Structure forward declarations. */
|
|
50
|
|
51 struct sound_file;
|
|
52 struct sound_device;
|
|
53
|
|
54 /* The file header of RIFF-WAVE files (*.wav). Files are always in
|
|
55 little-endian byte-order. */
|
|
56
|
|
57 struct wav_header
|
|
58 {
|
|
59 u_int32_t magic;
|
|
60 u_int32_t length;
|
|
61 u_int32_t chunk_type;
|
|
62 u_int32_t chunk_format;
|
|
63 u_int32_t chunk_length;
|
|
64 u_int16_t format;
|
|
65 u_int16_t channels;
|
|
66 u_int32_t sample_rate;
|
|
67 u_int32_t bytes_per_second;
|
|
68 u_int16_t sample_size;
|
|
69 u_int16_t precision;
|
|
70 u_int32_t chunk_data;
|
|
71 u_int32_t data_length;
|
|
72 };
|
|
73
|
|
74 /* The file header of Sun adio files (*.au). Files are always in
|
|
75 big-endian byte-order. */
|
|
76
|
|
77 struct au_header
|
|
78 {
|
|
79 /* ASCII ".snd" */
|
|
80 u_int32_t magic_number;
|
|
81
|
|
82 /* Offset of data part from start of file. Minimum value is 24. */
|
|
83 u_int32_t data_offset;
|
|
84
|
|
85 /* Size of data part, 0xffffffff if unknown. */
|
|
86 u_int32_t data_size;
|
|
87
|
|
88 /* Data encoding format.
|
|
89 1 8-bit ISDN u-law
|
|
90 2 8-bit linear PCM (REF-PCM)
|
|
91 3 16-bit linear PCM
|
|
92 4 24-bit linear PCM
|
|
93 5 32-bit linear PCM
|
|
94 6 32-bit IEEE floating-point
|
|
95 7 64-bit IEEE floating-point
|
|
96 23 8-bit u-law compressed using CCITT 0.721 ADPCM voice data
|
|
97 encoding scheme. */
|
|
98 u_int32_t encoding;
|
|
99
|
|
100 /* Number of samples per second. */
|
|
101 u_int32_t sample_rate;
|
|
102
|
|
103 /* Number of interleaved channels. */
|
|
104 u_int32_t channels;
|
|
105 };
|
|
106
|
|
107 /* Maximum of all sound file headers sizes. */
|
|
108
|
|
109 #define MAX_SOUND_HEADER_BYTES \
|
|
110 max (sizeof (struct wav_header), sizeof (struct au_header))
|
|
111
|
|
112 /* Interface structure for sound devices. */
|
|
113
|
|
114 struct sound_device
|
|
115 {
|
|
116 /* The name of the device or null meaning use a default device name. */
|
|
117 char *file;
|
|
118
|
|
119 /* File descriptor of the device. */
|
|
120 int fd;
|
|
121
|
|
122 /* Device-dependent format. */
|
|
123 int format;
|
|
124
|
|
125 /* Volume (0..100). Zero means unspecified. */
|
|
126 int volume;
|
|
127
|
|
128 /* Sample size. */
|
|
129 int sample_size;
|
|
130
|
|
131 /* Sample rate. */
|
|
132 int sample_rate;
|
|
133
|
|
134 /* Bytes per second. */
|
|
135 int bps;
|
|
136
|
|
137 /* 1 = mono, 2 = stereo, 0 = don't set. */
|
|
138 int channels;
|
|
139
|
|
140 /* Open device SD. */
|
|
141 void (* open) P_ ((struct sound_device *sd));
|
|
142
|
|
143 /* Close device SD. */
|
|
144 void (* close) P_ ((struct sound_device *sd));
|
|
145
|
|
146 /* Configure SD accoring to device-dependent parameters. */
|
|
147 void (* configure) P_ ((struct sound_device *device));
|
|
148
|
|
149 /* Choose a device-dependent format for outputting sound file SF. */
|
|
150 void (* choose_format) P_ ((struct sound_device *sd,
|
|
151 struct sound_file *sf));
|
|
152
|
|
153 /* Write NYBTES bytes from BUFFER to device SD. */
|
|
154 void (* write) P_ ((struct sound_device *sd, char *buffer, int nbytes));
|
|
155
|
|
156 /* A place for devices to store additional data. */
|
|
157 void *data;
|
|
158 };
|
|
159
|
|
160 /* An enumerator for each supported sound file type. */
|
|
161
|
|
162 enum sound_type
|
|
163 {
|
|
164 RIFF,
|
|
165 SUN_AUDIO
|
|
166 };
|
|
167
|
|
168 /* Interface structure for sound files. */
|
|
169
|
|
170 struct sound_file
|
|
171 {
|
|
172 /* The type of the file. */
|
|
173 enum sound_type type;
|
|
174
|
|
175 /* File descriptor of the file. */
|
|
176 int fd;
|
|
177
|
|
178 /* Pointer to sound file header. This contains the first
|
|
179 MAX_SOUND_HEADER_BYTES read from the file. */
|
|
180 char *header;
|
|
181
|
|
182 /* Play sound file SF on device SD. */
|
|
183 void (* play) P_ ((struct sound_file *sf, struct sound_device *sd));
|
|
184 };
|
|
185
|
|
186 /* Indices of attributes in a sound attributes vector. */
|
|
187
|
|
188 enum sound_attr
|
|
189 {
|
|
190 SOUND_FILE,
|
|
191 SOUND_DEVICE,
|
|
192 SOUND_VOLUME,
|
|
193 SOUND_ATTR_SENTINEL
|
|
194 };
|
|
195
|
|
196 /* Symbols. */
|
|
197
|
|
198 extern Lisp_Object QCfile;
|
|
199 Lisp_Object QCvolume, QCdevice;
|
|
200 Lisp_Object Qsound;
|
|
201 Lisp_Object Qplay_sound_hook;
|
|
202
|
|
203 /* These are set during `play-sound' so that sound_cleanup has
|
|
204 access to them. */
|
|
205
|
|
206 struct sound_device *sound_device;
|
|
207 struct sound_file *sound_file;
|
|
208
|
|
209 /* Function prototypes. */
|
|
210
|
|
211 static void vox_open P_ ((struct sound_device *));
|
|
212 static void vox_configure P_ ((struct sound_device *));
|
|
213 static void vox_close P_ ((struct sound_device *sd));
|
|
214 static void vox_choose_format P_ ((struct sound_device *, struct sound_file *));
|
|
215 static void vox_init P_ ((struct sound_device *));
|
|
216 static void vox_write P_ ((struct sound_device *, char *, int));
|
|
217 static void sound_perror P_ ((char *));
|
|
218 static int parse_sound P_ ((Lisp_Object, Lisp_Object *));
|
|
219 static void find_sound_file_type P_ ((struct sound_file *));
|
|
220 static u_int32_t le2hl P_ ((u_int32_t));
|
|
221 static u_int16_t le2hs P_ ((u_int16_t));
|
|
222 static u_int32_t be2hl P_ ((u_int32_t));
|
|
223 static u_int16_t be2hs P_ ((u_int16_t));
|
|
224 static int wav_init P_ ((struct sound_file *));
|
|
225 static void wav_play P_ ((struct sound_file *, struct sound_device *));
|
|
226 static int au_init P_ ((struct sound_file *));
|
|
227 static void au_play P_ ((struct sound_file *, struct sound_device *));
|
|
228
|
|
229
|
|
230
|
|
231 /***********************************************************************
|
|
232 General
|
|
233 ***********************************************************************/
|
|
234
|
|
235 /* Like perror, but signals an error. */
|
|
236
|
|
237 static void
|
|
238 sound_perror (msg)
|
|
239 char *msg;
|
|
240 {
|
|
241 error ("%s: %s", msg, strerror (errno));
|
|
242 }
|
|
243
|
|
244
|
|
245 /* Parse sound specification SOUND, and fill ATTRS with what is
|
|
246 found. Value is non-zero if SOUND Is a valid sound specification.
|
|
247 A valid sound specification is a list starting with the symbol
|
|
248 `sound'. The rest of the list is a property list which may
|
|
249 contain the following key/value pairs:
|
|
250
|
|
251 - `:file FILE'
|
|
252
|
|
253 FILE is the sound file to play. If it isn't an absolute name,
|
|
254 it's searched under `data-directory'.
|
|
255
|
|
256 - `:device DEVICE'
|
|
257
|
|
258 DEVICE is the name of the device to play on, e.g. "/dev/dsp2".
|
|
259 If not specified, a default device is used.
|
|
260
|
|
261 - `:volume VOL'
|
|
262
|
|
263 VOL must be an integer in the range 0..100. */
|
|
264
|
|
265 static int
|
|
266 parse_sound (sound, attrs)
|
|
267 Lisp_Object sound;
|
|
268 Lisp_Object *attrs;
|
|
269 {
|
|
270 /* SOUND must be a list starting with the symbol `sound'. */
|
|
271 if (!CONSP (sound) || !EQ (XCAR (sound), Qsound))
|
|
272 return 0;
|
|
273
|
|
274 sound = XCDR (sound);
|
|
275 attrs[SOUND_FILE] = Fplist_get (sound, QCfile);
|
|
276 attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice);
|
|
277 attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume);
|
|
278
|
|
279 /* File name must be specified. */
|
|
280 if (!STRINGP (attrs[SOUND_FILE]))
|
|
281 return 0;
|
|
282
|
|
283 /* Volume must be in the range 0..100 or unspecified. */
|
|
284 if (!NILP (attrs[SOUND_VOLUME]))
|
|
285 {
|
|
286 if (!INTEGERP (attrs[SOUND_VOLUME]))
|
|
287 return 0;
|
|
288 if (XINT (attrs[SOUND_VOLUME]) < 0
|
|
289 || XINT (attrs[SOUND_VOLUME]) > 100)
|
|
290 return 0;
|
|
291 }
|
|
292
|
|
293 /* Device must be a string or unspecified. */
|
|
294 if (!NILP (attrs[SOUND_DEVICE])
|
|
295 && !STRINGP (attrs[SOUND_DEVICE]))
|
|
296 return 0;
|
|
297
|
|
298 return 1;
|
|
299 }
|
|
300
|
|
301
|
|
302 /* Find out the type of the sound file whose file descriptor is FD.
|
|
303 SF is the sound file structure to fill in. */
|
|
304
|
|
305 static void
|
|
306 find_sound_file_type (sf)
|
|
307 struct sound_file *sf;
|
|
308 {
|
|
309 if (!wav_init (sf)
|
|
310 && !au_init (sf))
|
|
311 error ("Unknown sound file format");
|
|
312 }
|
|
313
|
|
314
|
|
315 /* Function installed by play-sound with record_unwind_protect. */
|
|
316
|
|
317 static Lisp_Object
|
|
318 sound_cleanup (arg)
|
|
319 Lisp_Object arg;
|
|
320 {
|
|
321 if (sound_device)
|
|
322 {
|
|
323 sound_device->close (sound_device);
|
|
324 if (sound_file->fd > 0)
|
|
325 close (sound_file->fd);
|
|
326 }
|
|
327 }
|
|
328
|
|
329
|
|
330 DEFUN ("play-sound", Fplay_sound, Splay_sound, 1, 1, 0,
|
|
331 "Play sound SOUND.")
|
|
332 (sound)
|
|
333 Lisp_Object sound;
|
|
334 {
|
|
335 Lisp_Object attrs[SOUND_ATTR_SENTINEL];
|
|
336 char *header;
|
|
337 Lisp_Object file;
|
|
338 struct gcpro gcpro1, gcpro2;
|
|
339 int nbytes;
|
|
340 char *msg;
|
|
341 struct sound_device sd;
|
|
342 struct sound_file sf;
|
|
343 Lisp_Object args[2];
|
|
344 int count = specpdl_ptr - specpdl;
|
|
345
|
|
346 file = Qnil;
|
|
347 GCPRO2 (sound, file);
|
|
348 bzero (&sd, sizeof sd);
|
|
349 bzero (&sf, sizeof sf);
|
|
350 sf.header = (char *) alloca (MAX_SOUND_HEADER_BYTES);
|
|
351
|
|
352 sound_device = &sd;
|
|
353 sound_file = &sf;
|
|
354 record_unwind_protect (sound_cleanup, Qnil);
|
|
355
|
|
356 /* Parse the sound specification. Give up if it is invalid. */
|
|
357 if (!parse_sound (sound, attrs))
|
|
358 {
|
|
359 UNGCPRO;
|
|
360 error ("Invalid sound specification");
|
|
361 }
|
|
362
|
|
363 /* Open the sound file. */
|
|
364 sf.fd = openp (Fcons (Vdata_directory, Qnil),
|
|
365 attrs[SOUND_FILE], "", &file, 0);
|
|
366 if (sf.fd < 0)
|
|
367 sound_perror ("Open sound file");
|
|
368
|
|
369 /* Read the first bytes from the file. */
|
|
370 nbytes = read (sf.fd, sf.header, MAX_SOUND_HEADER_BYTES);
|
|
371 if (nbytes < 0)
|
|
372 sound_perror ("Reading sound file header");
|
|
373
|
|
374 /* Find out the type of sound file. Give up if we can't tell. */
|
|
375 find_sound_file_type (&sf);
|
|
376
|
|
377 /* Set up a device. */
|
|
378 if (STRINGP (attrs[SOUND_DEVICE]))
|
|
379 {
|
|
380 int len = XSTRING (attrs[SOUND_DEVICE])->size;
|
|
381 sd.file = (char *) alloca (len + 1);
|
|
382 strcpy (sd.file, XSTRING (attrs[SOUND_DEVICE])->data);
|
|
383 }
|
|
384 if (INTEGERP (attrs[SOUND_VOLUME]))
|
|
385 sd.volume = XFASTINT (attrs[SOUND_VOLUME]);
|
|
386
|
|
387 args[0] = Qplay_sound_hook;
|
|
388 args[1] = sound;
|
|
389 Frun_hook_with_args (make_number (2), args);
|
|
390
|
|
391 vox_init (&sd);
|
|
392 sd.open (&sd);
|
|
393
|
|
394 sf.play (&sf, &sd);
|
|
395 close (sf.fd);
|
|
396 sf.fd = -1;
|
|
397 sd.close (&sd);
|
|
398 sound_device = NULL;
|
|
399 sound_file = NULL;
|
|
400 UNGCPRO;
|
|
401 unbind_to (count, Qnil);
|
|
402 return Qnil;
|
|
403 }
|
|
404
|
|
405
|
|
406 /***********************************************************************
|
|
407 Byte-order Conversion
|
|
408 ***********************************************************************/
|
|
409
|
|
410 /* Convert 32-bit value VALUE which is in little-endian byte-order
|
|
411 to host byte-order. */
|
|
412
|
|
413 static u_int32_t
|
|
414 le2hl (value)
|
|
415 u_int32_t value;
|
|
416 {
|
|
417 #ifdef WORDS_BIG_ENDIAN
|
|
418 unsigned char *p = (unsigned char *) &value;
|
|
419 value = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
|
|
420 #endif
|
|
421 return value;
|
|
422 }
|
|
423
|
|
424
|
|
425 /* Convert 16-bit value VALUE which is in little-endian byte-order
|
|
426 to host byte-order. */
|
|
427
|
|
428 static u_int16_t
|
|
429 le2hs (value)
|
|
430 u_int16_t value;
|
|
431 {
|
|
432 #ifdef WORDS_BIG_ENDIAN
|
|
433 unsigned char *p = (unsigned char *) &value;
|
|
434 value = p[0] + (p[1] << 8);
|
|
435 #endif
|
|
436 return value;
|
|
437 }
|
|
438
|
|
439
|
|
440 /* Convert 32-bit value VALUE which is in big-endian byte-order
|
|
441 to host byte-order. */
|
|
442
|
|
443 static u_int32_t
|
|
444 be2hl (value)
|
|
445 u_int32_t value;
|
|
446 {
|
|
447 #ifndef WORDS_BIG_ENDIAN
|
|
448 unsigned char *p = (unsigned char *) &value;
|
|
449 value = p[3] + (p[2] << 8) + (p[1] << 16) + (p[0] << 24);
|
|
450 #endif
|
|
451 return value;
|
|
452 }
|
|
453
|
|
454
|
|
455 /* Convert 16-bit value VALUE which is in big-endian byte-order
|
|
456 to host byte-order. */
|
|
457
|
|
458 static u_int16_t
|
|
459 be2hs (value)
|
|
460 u_int16_t value;
|
|
461 {
|
|
462 #ifndef WORDS_BIG_ENDIAN
|
|
463 unsigned char *p = (unsigned char *) &value;
|
|
464 value = p[1] + (p[0] << 8);
|
|
465 #endif
|
|
466 return value;
|
|
467 }
|
|
468
|
|
469
|
|
470
|
|
471 /***********************************************************************
|
|
472 RIFF-WAVE (*.wav)
|
|
473 ***********************************************************************/
|
|
474
|
|
475 /* Try to initialize sound file SF from SF->header. SF->header
|
|
476 contains the first MAX_SOUND_HEADER_BYTES number of bytes from the
|
|
477 sound file. If the file is a WAV-format file, set up interface
|
|
478 functions in SF and convert header fields to host byte-order.
|
|
479 Value is non-zero if the file is a WAV file. */
|
|
480
|
|
481 static int
|
|
482 wav_init (sf)
|
|
483 struct sound_file *sf;
|
|
484 {
|
|
485 struct wav_header *header = (struct wav_header *) sf->header;
|
|
486
|
|
487 if (bcmp (sf->header, "RIFF", 4) != 0)
|
|
488 return 0;
|
|
489
|
|
490 /* WAV files are in little-endian order. Convert the header
|
|
491 if on a big-endian machine. */
|
|
492 header->magic = le2hl (header->magic);
|
|
493 header->length = le2hl (header->length);
|
|
494 header->chunk_type = le2hl (header->chunk_type);
|
|
495 header->chunk_format = le2hl (header->chunk_format);
|
|
496 header->chunk_length = le2hl (header->chunk_length);
|
|
497 header->format = le2hs (header->format);
|
|
498 header->channels = le2hs (header->channels);
|
|
499 header->sample_rate = le2hl (header->sample_rate);
|
|
500 header->bytes_per_second = le2hl (header->bytes_per_second);
|
|
501 header->sample_size = le2hs (header->sample_size);
|
|
502 header->precision = le2hs (header->precision);
|
|
503 header->chunk_data = le2hl (header->chunk_data);
|
|
504 header->data_length = le2hl (header->data_length);
|
|
505
|
|
506 /* Set up the interface functions for WAV. */
|
|
507 sf->type = RIFF;
|
|
508 sf->play = wav_play;
|
|
509
|
|
510 return 1;
|
|
511 }
|
|
512
|
|
513
|
|
514 /* Play RIFF-WAVE audio file SF on sound device SD. */
|
|
515
|
|
516 static void
|
|
517 wav_play (sf, sd)
|
|
518 struct sound_file *sf;
|
|
519 struct sound_device *sd;
|
|
520 {
|
|
521 struct wav_header *header = (struct wav_header *) sf->header;
|
|
522 char *buffer;
|
|
523 int nbytes;
|
|
524 int blksize = 2048;
|
|
525
|
|
526 /* Let the device choose a suitable device-dependent format
|
|
527 for the file. */
|
|
528 sd->choose_format (sd, sf);
|
|
529
|
|
530 /* Configure the device. */
|
|
531 sd->sample_size = header->sample_size;
|
|
532 sd->sample_rate = header->sample_rate;
|
|
533 sd->bps = header->bytes_per_second;
|
|
534 sd->channels = header->channels;
|
|
535 sd->configure (sd);
|
|
536
|
|
537 /* Copy sound data to the device. The WAV file specification is
|
|
538 actually more complex. This simple scheme worked with all WAV
|
|
539 files I found so far. If someone feels inclined to implement the
|
|
540 whole RIFF-WAVE spec, please do. */
|
|
541 buffer = (char *) alloca (blksize);
|
|
542 lseek (sf->fd, sizeof *header, SEEK_SET);
|
|
543
|
|
544 while ((nbytes = read (sf->fd, buffer, blksize)) > 0)
|
|
545 sd->write (sd, buffer, nbytes);
|
|
546
|
|
547 if (nbytes < 0)
|
|
548 sound_perror ("Reading sound file");
|
|
549 }
|
|
550
|
|
551
|
|
552
|
|
553 /***********************************************************************
|
|
554 Sun Audio (*.au)
|
|
555 ***********************************************************************/
|
|
556
|
|
557 /* Sun audio file encodings. */
|
|
558
|
|
559 enum au_encoding
|
|
560 {
|
|
561 AU_ENCODING_ULAW_8 = 1,
|
|
562 AU_ENCODING_8,
|
|
563 AU_ENCODING_16,
|
|
564 AU_ENCODING_24,
|
|
565 AU_ENCODING_32,
|
|
566 AU_ENCODING_IEEE32,
|
|
567 AU_ENCODING_IEEE64,
|
|
568 AU_COMPRESSED = 23
|
|
569 };
|
|
570
|
|
571
|
|
572 /* Try to initialize sound file SF from SF->header. SF->header
|
|
573 contains the first MAX_SOUND_HEADER_BYTES number of bytes from the
|
|
574 sound file. If the file is a AU-format file, set up interface
|
|
575 functions in SF and convert header fields to host byte-order.
|
|
576 Value is non-zero if the file is an AU file. */
|
|
577
|
|
578 static int
|
|
579 au_init (sf)
|
|
580 struct sound_file *sf;
|
|
581 {
|
|
582 struct au_header *header = (struct au_header *) sf->header;
|
|
583
|
|
584 if (bcmp (sf->header, ".snd", 4) != 0)
|
|
585 return 0;
|
|
586
|
|
587 header->magic_number = be2hl (header->magic_number);
|
|
588 header->data_offset = be2hl (header->data_offset);
|
|
589 header->data_size = be2hl (header->data_size);
|
|
590 header->encoding = be2hl (header->encoding);
|
|
591 header->sample_rate = be2hl (header->sample_rate);
|
|
592 header->channels = be2hl (header->channels);
|
|
593
|
|
594 /* Set up the interface functions for AU. */
|
|
595 sf->type = SUN_AUDIO;
|
|
596 sf->play = au_play;
|
|
597
|
|
598 return 1;
|
|
599 }
|
|
600
|
|
601
|
|
602 /* Play Sun audio file SF on sound device SD. */
|
|
603
|
|
604 static void
|
|
605 au_play (sf, sd)
|
|
606 struct sound_file *sf;
|
|
607 struct sound_device *sd;
|
|
608 {
|
|
609 struct au_header *header = (struct au_header *) sf->header;
|
|
610 int blksize = 2048;
|
|
611 char *buffer;
|
|
612 int nbytes;
|
|
613
|
|
614 sd->sample_size = 0;
|
|
615 sd->sample_rate = header->sample_rate;
|
|
616 sd->bps = 0;
|
|
617 sd->channels = header->channels;
|
|
618 sd->choose_format (sd, sf);
|
|
619 sd->configure (sd);
|
|
620
|
|
621 /* Seek */
|
|
622 lseek (sf->fd, header->data_offset, SEEK_SET);
|
|
623
|
|
624 /* Copy sound data to the device. */
|
|
625 buffer = (char *) alloca (blksize);
|
|
626 while ((nbytes = read (sf->fd, buffer, blksize)) > 0)
|
|
627 sd->write (sd, buffer, nbytes);
|
|
628
|
|
629 if (nbytes < 0)
|
|
630 sound_perror ("Reading sound file");
|
|
631 }
|
|
632
|
|
633
|
|
634
|
|
635 /***********************************************************************
|
|
636 Voxware Driver Interface
|
|
637 ***********************************************************************/
|
|
638
|
|
639 /* This driver is available on GNU/Linux, and the free BSDs. FreeBSD
|
|
640 has a compatible own driver aka Luigi's driver. */
|
|
641
|
|
642
|
|
643 /* Open device SD. If SD->file is non-null, open that device,
|
|
644 otherwise use a default device name. */
|
|
645
|
|
646 static void
|
|
647 vox_open (sd)
|
|
648 struct sound_device *sd;
|
|
649 {
|
|
650 char *file;
|
|
651
|
|
652 /* Open the sound device. Default is /dev/dsp. */
|
|
653 if (sd->file)
|
|
654 file = sd->file;
|
|
655 else
|
|
656 file = "/dev/dsp";
|
|
657
|
|
658 sd->fd = open (file, O_WRONLY);
|
|
659 if (sd->fd < 0)
|
|
660 sound_perror (file);
|
|
661 }
|
|
662
|
|
663
|
|
664 /* Configure device SD from parameters in it. */
|
|
665
|
|
666 static void
|
|
667 vox_configure (sd)
|
|
668 struct sound_device *sd;
|
|
669 {
|
|
670 int requested;
|
|
671
|
|
672 xassert (sd->fd >= 0);
|
|
673
|
|
674 /* Device parameters apparently depend on each other in undocumented
|
|
675 ways (not to imply that there is any real documentation). Be
|
|
676 careful when reordering the calls below. */
|
|
677 if (sd->sample_size > 0
|
|
678 && ioctl (sd->fd, SNDCTL_DSP_SAMPLESIZE, &sd->sample_size) < 0)
|
|
679 sound_perror ("Setting sample size");
|
|
680
|
|
681 if (sd->bps > 0
|
|
682 && ioctl (sd->fd, SNDCTL_DSP_SPEED, &sd->bps) < 0)
|
|
683 sound_perror ("Setting speed");
|
|
684
|
|
685 if (sd->sample_rate > 0
|
|
686 && ioctl (sd->fd, SOUND_PCM_WRITE_RATE, &sd->sample_rate) < 0)
|
|
687 sound_perror ("Setting sample rate");
|
|
688
|
|
689 requested = sd->format;
|
|
690 if (ioctl (sd->fd, SNDCTL_DSP_SETFMT, &sd->format) < 0)
|
|
691 sound_perror ("Setting format");
|
|
692 else if (requested != sd->format)
|
|
693 error ("Setting format");
|
|
694
|
|
695 if (sd->channels > 1
|
|
696 && ioctl (sd->fd, SNDCTL_DSP_STEREO, &sd->channels) < 0)
|
|
697 sound_perror ("Setting channels");
|
|
698
|
|
699 if (sd->volume > 0
|
|
700 && ioctl (sd->fd, SOUND_MIXER_WRITE_PCM, &sd->volume) < 0)
|
|
701 sound_perror ("Setting volume");
|
|
702 }
|
|
703
|
|
704
|
|
705 /* Close device SD if it is open. */
|
|
706
|
|
707 static void
|
|
708 vox_close (sd)
|
|
709 struct sound_device *sd;
|
|
710 {
|
|
711 if (sd->fd >= 0)
|
|
712 {
|
|
713 /* Flush sound data, and reset the device. */
|
|
714 ioctl (sd->fd, SNDCTL_DSP_SYNC, NULL);
|
|
715 ioctl (sd->fd, SNDCTL_DSP_RESET, NULL);
|
|
716
|
|
717 /* Close the device. */
|
|
718 close (sd->fd);
|
|
719 sd->fd = -1;
|
|
720 }
|
|
721 }
|
|
722
|
|
723
|
|
724 /* Choose device-dependent format for device SD from sound file SF. */
|
|
725
|
|
726 static void
|
|
727 vox_choose_format (sd, sf)
|
|
728 struct sound_device *sd;
|
|
729 struct sound_file *sf;
|
|
730 {
|
|
731 if (sf->type == RIFF)
|
|
732 {
|
|
733 struct wav_header *h = (struct wav_header *) sf->header;
|
|
734 if (h->precision == 8)
|
|
735 sd->format = AFMT_U8;
|
|
736 else if (h->precision == 16)
|
|
737 sd->format = AFMT_S16_LE;
|
|
738 else
|
|
739 error ("Unsupported WAV file format");
|
|
740 }
|
|
741 else if (sf->type == SUN_AUDIO)
|
|
742 {
|
|
743 struct au_header *header = (struct au_header *) sf->header;
|
|
744 switch (header->encoding)
|
|
745 {
|
|
746 case AU_ENCODING_ULAW_8:
|
|
747 case AU_ENCODING_IEEE32:
|
|
748 case AU_ENCODING_IEEE64:
|
|
749 sd->format = AFMT_MU_LAW;
|
|
750 break;
|
|
751
|
|
752 case AU_ENCODING_8:
|
|
753 case AU_ENCODING_16:
|
|
754 case AU_ENCODING_24:
|
|
755 case AU_ENCODING_32:
|
|
756 sd->format = AFMT_S16_LE;
|
|
757 break;
|
|
758
|
|
759 default:
|
|
760 error ("Unsupported AU file format");
|
|
761 }
|
|
762 }
|
|
763 else
|
|
764 abort ();
|
|
765 }
|
|
766
|
|
767
|
|
768 /* Initialize device SD. Set up the interface functions in the device
|
|
769 structure. */
|
|
770
|
|
771 static void
|
|
772 vox_init (sd)
|
|
773 struct sound_device *sd;
|
|
774 {
|
|
775 sd->fd = -1;
|
|
776 sd->open = vox_open;
|
|
777 sd->close = vox_close;
|
|
778 sd->configure = vox_configure;
|
|
779 sd->choose_format = vox_choose_format;
|
|
780 sd->write = vox_write;
|
|
781 }
|
|
782
|
|
783
|
|
784 /* Write NBYTES bytes from BUFFER to device SD. */
|
|
785
|
|
786 static void
|
|
787 vox_write (sd, buffer, nbytes)
|
|
788 struct sound_device *sd;
|
|
789 char *buffer;
|
|
790 int nbytes;
|
|
791 {
|
|
792 int nwritten = write (sd->fd, buffer, nbytes);
|
|
793 if (nwritten < 0)
|
|
794 sound_perror ("Writing to sound device");
|
|
795 }
|
|
796
|
|
797
|
|
798
|
|
799 /***********************************************************************
|
|
800 Initialization
|
|
801 ***********************************************************************/
|
|
802
|
|
803 void
|
|
804 syms_of_sound ()
|
|
805 {
|
|
806 QCdevice = intern (":device");
|
|
807 staticpro (&QCdevice);
|
|
808 QCvolume = intern (":volume");
|
|
809 staticpro (&QCvolume);
|
|
810 Qsound = intern ("sound");
|
|
811 staticpro (&Qsound);
|
|
812 Qplay_sound_hook = intern ("play-sound-hook");
|
|
813 staticpro (&Qplay_sound_hook);
|
|
814
|
|
815 defsubr (&Splay_sound);
|
|
816 }
|
|
817
|
|
818
|
|
819 void
|
|
820 init_sound ()
|
|
821 {
|
|
822 }
|
|
823
|
|
824 #endif /* HAVE_SOUND */
|