1 /* media-internal.c - general routines related to playing sounds
3 ** Copyright (C) 1995,96 by Markus Gutschke (gutschk@math.uni-muenster.de)
4 ** This was sawed out from version 1.3 of linuxplay.c by
5 ** Robert Bihlmeyer <robbe@orcus.priv.at>.
9 ** Parts of this code were inspired by sunplay.c, which is copyright 1989 by
10 ** Jef Poskanzer and 1991,92 by Jamie Zawinski; c.f. sunplay.c for further
13 ** Permission to use, copy, modify, and distribute this software and its
14 ** documentation for any purpose and without fee is hereby granted, provided
15 ** that the above copyright notice appear in all copies and that both that
16 ** copyright notice and this permission notice appear in supporting
17 ** documentation. This software is provided "as is" without express or
26 #include "syssignal.h"
28 #define warn(str) message("audio: %s ",GETTEXT(str))
32 #include "media-internal.h"
34 #define MYSELF MDRIVER_INTERNAL
36 /* Maintain global variable for keeping parser state information; this struct
37 is set to zero before the first invocation of the parser. The use of a
38 global variable prevents multiple concurrent executions of this code, but
39 this does not happen anyways... */
40 enum wvState { wvMain,
54 unsigned char leftover[HEADERSZ];
55 signed long chunklength;
62 unsigned char leftover[HEADERSZ];
66 /* Use a global buffer as scratch-pad for possible conversions of the
68 unsigned char miscplay_sndbuf[SNDBUFSZ];
70 /* Initialize global parser state information to zero */
71 void reset_parsestate()
73 memset(&parsestate, 0, sizeof(parsestate));
76 /* Verify that we could fully parse the entire soundfile; this is needed
77 only for files in WAVE format */
78 int parse_wave_complete()
80 if (parsestate.wave.state != wvOutOfBlock &&
81 parsestate.wave.state != wvFatal) {
82 warn("Unexpected end of WAVE file");
88 /* There is no special treatment required for parsing raw data files; we
89 assume that these files contain data in 8bit unsigned format that
90 has been sampled at 8kHz; there is no extra header */
91 static size_t parseraw(void **data, size_t * sz, void **outbuf)
100 /* Currently we cannot cope with files in VOC format; if you really need
101 to play these files, they should be converted by using SOX */
102 static size_t parsevoc(void **SXE_UNUSED(data), size_t *SXE_UNUSED(sz),
103 void **SXE_UNUSED(outbuf))
108 /* We need to perform some look-ahead in order to parse files in WAVE format;
109 this might require re-partioning of the data segments if headers cross the
110 boundaries between two read operations. This is done in a two-step way:
111 first we request a certain amount of bytes... */
112 static inline int waverequire(void **data, size_t * sz, size_t rq)
117 warn("Header size exceeded while parsing WAVE file");
118 parsestate.wave.state = wvFatal;
122 if ((rq -= parsestate.wave.left) <= 0)
128 memcpy(parsestate.wave.leftover + parsestate.wave.left, *data, rq);
129 parsestate.wave.left += rq;
130 (*(unsigned char **)data) += rq;
135 /* ...and next we remove this many bytes from the buffer */
136 static inline void waveremove(size_t rq)
138 if (parsestate.wave.left <= rq)
139 parsestate.wave.left = 0;
141 parsestate.wave.left -= rq;
142 memmove(parsestate.wave.leftover,
143 parsestate.wave.leftover + rq, parsestate.wave.left);
148 /* Sound files in WAVE format can contain an arbitrary amount of tagged
149 chunks; this requires quite some effort for parsing the data */
150 static size_t parsewave(void **data, size_t * sz, void **outbuf)
153 switch (parsestate.wave.state) {
155 if (!waverequire(data, sz, 20))
157 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
158 parsestate.wave.chunklength =
159 parsestate.wave.leftover[16] +
160 256 * (parsestate.wave.leftover[17] +
161 256 * (parsestate.wave.leftover[18] +
162 256 * parsestate.wave.leftover[19]));
164 parsestate.wave.state = wvSubchunk;
167 if (!waverequire(data, sz, parsestate.wave.chunklength))
169 parsestate.wave.align =
170 parsestate.wave.chunklength <
171 14 ? 1 : parsestate.wave.leftover[12];
172 if (parsestate.wave.align != 1
173 && parsestate.wave.align != 2
174 && parsestate.wave.align != 4) {
175 warn("Illegal datawidth detected while parsing WAVE file");
176 parsestate.wave.state = wvFatal;
178 parsestate.wave.state = wvOutOfBlock;
179 waveremove(parsestate.wave.chunklength);
182 if (!waverequire(data, sz, 8))
184 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
185 parsestate.wave.chunklength =
186 parsestate.wave.leftover[4] +
187 256 * (parsestate.wave.leftover[5] +
188 256 * (parsestate.wave.leftover[6] +
191 leftover[7] & 0x7F)));
192 if (memcmp(parsestate.wave.leftover, "data", 4))
193 parsestate.wave.state = wvSkipChunk;
195 parsestate.wave.state = wvSoundChunk;
199 if (parsestate.wave.chunklength > 0 && *sz > 0 &&
201 (signed long)parsestate.wave.chunklength) {
202 parsestate.wave.chunklength -= *sz;
205 if (parsestate.wave.chunklength > 0 && *sz > 0) {
206 *sz -= parsestate.wave.chunklength;
207 (*(unsigned char **)data) +=
208 parsestate.wave.chunklength;
210 parsestate.wave.state = wvOutOfBlock;
215 if (parsestate.wave.left) { /* handle leftover bytes from last
216 alignment operation */
217 count = parsestate.wave.left;
218 rq = HEADERSZ - count;
220 (size_t) parsestate.wave.
222 rq = parsestate.wave.
224 if (!waverequire(data, sz, rq)) {
225 parsestate.wave.chunklength -=
226 parsestate.wave.left -
230 parsestate.wave.chunklength -= rq;
231 *outbuf = parsestate.wave.leftover;
232 parsestate.wave.left = 0;
235 if (*sz >= (size_t) parsestate.wave.chunklength) {
236 count = parsestate.wave.chunklength;
241 count % parsestate.wave.align;
244 (*(unsigned char **)data) += count;
246 if ((parsestate.wave.chunklength -=
247 count) < parsestate.wave.align) {
248 parsestate.wave.state = wvOutOfBlock;
249 /* Some broken software (e.g. SOX) attaches junk to the end of a sound
250 chunk; so, let's ignore this... */
251 if (parsestate.wave.chunklength)
252 parsestate.wave.state =
255 /* align data length to a multiple of datasize; keep additional data
256 in "leftover" buffer --- this is necessary to ensure proper
257 functioning of the sndcnv... routines */
258 if(waverequire(data, sz, rq) != 0)
266 warn("Irrecoverable error while parsing WAVE file");
267 parsestate.wave.state = wvFatal;
276 /* Strip the header from files in Sun/DEC audio format; this requires some
277 extra processing as the header can be an arbitrary size and it might
278 result in alignment errors for subsequent conversions --- thus we do
279 some buffering, where needed */
280 static size_t parsesundecaudio(void **data, size_t * sz, void **outbuf)
282 /* There is data left over from the last invocation of this function; join
283 it with the new data and return a sound chunk that is as big as a
285 if (parsestate.audio.left) {
286 if (parsestate.audio.left + *sz >
287 (size_t) parsestate.audio.align) {
289 memmove(parsestate.audio.leftover +
290 parsestate.audio.left, *data, count =
291 parsestate.audio.align - parsestate.audio.left);
292 *outbuf = parsestate.audio.leftover;
294 *data = (*(char **)data) + count;
295 parsestate.audio.left = 0;
296 return (parsestate.audio.align);
298 /* We need even more data in order to get one complete single entry! */
299 memmove(parsestate.audio.leftover +
300 parsestate.audio.left, *data, *sz);
301 *data = (*(char **)data) + *sz;
302 parsestate.audio.left += *sz;
308 /* This is the main sound chunk, strip of any extra data that does not fit
309 the alignment requirements and move these bytes into the leftover buffer */
310 if (parsestate.audio.isdata) {
313 if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) {
314 memmove(parsestate.audio.leftover,
315 (char *)*outbuf + rc - parsestate.audio.left,
316 parsestate.audio.left);
317 rc -= parsestate.audio.left;
323 /* This is the first invocation of this function; we need to parse the
324 header information and determine how many bytes we need to skip until
325 the start of the sound chunk */
326 if (!parsestate.audio.skipping) {
327 unsigned char *header = (unsigned char *)*data;
329 warn("Irrecoverable error while parsing Sun/DEC audio file");
332 /* Keep compatibility with Linux 68k, etc. by not relying on
334 if (header[3]) { /* Sun audio (big endian) */
335 parsestate.audio.align =
336 ((header[15] > 2) + 1) * header[23];
337 parsestate.audio.skipping =
338 header[7] + 256 * (header[6] +
341 } else { /* DEC audio (little endian) */
342 parsestate.audio.align =
343 ((header[12] > 2) + 1) * header[20];
344 parsestate.audio.skipping =
345 header[4] + 256 * (header[5] +
351 /* We are skipping extra data that has been attached to header; most
352 usually this will be just a comment, such as the original filename
353 and/or the creation date. Make sure that we do not return less than
354 one single sound sample entry to the caller; if this happens, rather
355 decide to move those few bytes into the leftover buffer and deal with
357 if (*sz >= (size_t) parsestate.audio.skipping) {
358 /* Skip just the header information and return the sound chunk */
359 int rc = *sz - parsestate.audio.skipping;
360 *outbuf = (char *)*data + parsestate.audio.skipping;
361 if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) {
362 memmove(parsestate.audio.leftover,
363 (char *)*outbuf + rc - parsestate.audio.left,
364 parsestate.audio.left);
365 rc -= parsestate.audio.left;
368 parsestate.audio.skipping = 0;
369 parsestate.audio.isdata++;
372 /* Skip everything */
373 parsestate.audio.skipping -= *sz;
378 /* If the soundcard could not be set to internally support the data format, we
379 try to do some limited on-the-fly conversion to a different format; if
380 no conversion is needed, though, we can output directly */
381 size_t sndcnvnop(void **data, size_t * sz, void **outbuf)
390 /* Convert 8 bit unsigned stereo data to 8 bit unsigned mono data */
391 size_t sndcnv8U_2mono(void **data, size_t * sz, void **outbuf)
393 REGISTER unsigned char *src;
394 REGISTER unsigned char *dest;
398 if (count > SNDBUFSZ) {
404 src = (unsigned char *)*data;
405 *outbuf = dest = miscplay_sndbuf;
407 *dest++ = (unsigned char)(((int)*(src) + (int)*(src + 1)) / 2);
414 /* Convert 8 bit signed stereo data to 8 bit signed mono data */
415 size_t sndcnv8S_2mono(void **data, size_t * sz, void **outbuf)
417 REGISTER unsigned char *src;
418 REGISTER unsigned char *dest;
422 if (count > SNDBUFSZ) {
428 src = (unsigned char *)*data;
429 *outbuf = dest = miscplay_sndbuf;
431 *dest++ = (unsigned char)(((int)*((signed char *)(src)) +
432 (int)*((signed char *)(src + 1))) /
440 /* Convert 8 bit signed stereo data to 8 bit unsigned mono data */
441 size_t sndcnv2monounsigned(void **data, size_t * sz, void **outbuf)
443 REGISTER unsigned char *src;
444 REGISTER unsigned char *dest;
448 if (count > SNDBUFSZ) {
454 src = (unsigned char *)*data;
455 *outbuf = dest = miscplay_sndbuf;
457 *dest++ = (unsigned char)(((int)*((signed char *)(src)) +
458 (int)*((signed char *)(src + 1))) /
466 /* Convert 8 bit signed mono data to 8 bit unsigned mono data */
467 size_t sndcnv2unsigned(void **data, size_t * sz, void **outbuf)
469 REGISTER unsigned char *src;
470 REGISTER unsigned char *dest;
474 if (count > SNDBUFSZ) {
480 src = (unsigned char *)*data;
481 *outbuf = dest = miscplay_sndbuf;
483 *dest++ = *(src)++ ^ 0x80;
488 /* Convert a number in the range -32768..32767 to an 8 bit ulaw encoded
489 number --- I hope, I got this conversion right :-) */
490 static inline signed char int2ulaw(int i)
492 /* Lookup table for fast calculation of number of bits that need shifting */
493 static short int t_bits[128] = {
494 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
495 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
496 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
497 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
498 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
499 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
500 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
501 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
503 REGISTER int bits, logi;
505 /* unrolling this condition (hopefully) improves execution speed */
510 logi = (i >> ((bits = t_bits[i / 256]) + 4));
511 return ((bits << 4 | logi) ^ 0x7F);
516 logi = (i >> ((bits = t_bits[i / 256]) + 4));
517 return (~(bits << 4 | logi));
521 /* Convert from 8 bit ulaw mono to 8 bit linear mono */
522 size_t sndcnvULaw_2linear(void **data, size_t * sz, void **outbuf)
524 /* conversion table stolen from Linux's ulaw.h */
525 static unsigned char ulaw_dsp[] = {
526 3, 7, 11, 15, 19, 23, 27, 31,
527 35, 39, 43, 47, 51, 55, 59, 63,
528 66, 68, 70, 72, 74, 76, 78, 80,
529 82, 84, 86, 88, 90, 92, 94, 96,
530 98, 99, 100, 101, 102, 103, 104, 105,
531 106, 107, 108, 109, 110, 111, 112, 113,
532 113, 114, 114, 115, 115, 116, 116, 117,
533 117, 118, 118, 119, 119, 120, 120, 121,
534 121, 121, 122, 122, 122, 122, 123, 123,
535 123, 123, 124, 124, 124, 124, 125, 125,
536 125, 125, 125, 125, 126, 126, 126, 126,
537 126, 126, 126, 126, 127, 127, 127, 127,
538 127, 127, 127, 127, 127, 127, 127, 127,
539 128, 128, 128, 128, 128, 128, 128, 128,
540 128, 128, 128, 128, 128, 128, 128, 128,
541 128, 128, 128, 128, 128, 128, 128, 128,
542 253, 249, 245, 241, 237, 233, 229, 225,
543 221, 217, 213, 209, 205, 201, 197, 193,
544 190, 188, 186, 184, 182, 180, 178, 176,
545 174, 172, 170, 168, 166, 164, 162, 160,
546 158, 157, 156, 155, 154, 153, 152, 151,
547 150, 149, 148, 147, 146, 145, 144, 143,
548 143, 142, 142, 141, 141, 140, 140, 139,
549 139, 138, 138, 137, 137, 136, 136, 135,
550 135, 135, 134, 134, 134, 134, 133, 133,
551 133, 133, 132, 132, 132, 132, 131, 131,
552 131, 131, 131, 131, 130, 130, 130, 130,
553 130, 130, 130, 130, 129, 129, 129, 129,
554 129, 129, 129, 129, 129, 129, 129, 129,
555 128, 128, 128, 128, 128, 128, 128, 128,
556 128, 128, 128, 128, 128, 128, 128, 128,
557 128, 128, 128, 128, 128, 128, 128, 128,
559 unsigned char *p = (unsigned char *)*data;
568 return p - (unsigned char *)*outbuf;
571 /* Convert 8 bit ulaw stereo data to 8 bit ulaw mono data */
572 size_t sndcnvULaw_2mono(void **data, size_t * sz, void **outbuf)
575 static short int ulaw2int[256] = {
576 /* Precomputed lookup table for conversion from ulaw to 15 bit signed */
577 -16062, -15550, -15038, -14526, -14014, -13502, -12990, -12478,
578 -11966, -11454, -10942, -10430, -9918, -9406, -8894, -8382,
579 -7998, -7742, -7486, -7230, -6974, -6718, -6462, -6206,
580 -5950, -5694, -5438, -5182, -4926, -4670, -4414, -4158,
581 -3966, -3838, -3710, -3582, -3454, -3326, -3198, -3070,
582 -2942, -2814, -2686, -2558, -2430, -2302, -2174, -2046,
583 -1950, -1886, -1822, -1758, -1694, -1630, -1566, -1502,
584 -1438, -1374, -1310, -1246, -1182, -1118, -1054, -990,
585 -942, -910, -878, -846, -814, -782, -750, -718,
586 -686, -654, -622, -590, -558, -526, -494, -462,
587 -438, -422, -406, -390, -374, -358, -342, -326,
588 -310, -294, -278, -262, -246, -230, -214, -198,
589 -186, -178, -170, -162, -154, -146, -138, -130,
590 -122, -114, -106, -98, -90, -82, -74, -66,
591 -60, -56, -52, -48, -44, -40, -36, -32,
592 -28, -24, -20, -16, -12, -8, -4, +0,
593 +16062, +15550, +15038, +14526, +14014, +13502, +12990, +12478,
594 +11966, +11454, +10942, +10430, +9918, +9406, +8894, +8382,
595 +7998, +7742, +7486, +7230, +6974, +6718, +6462, +6206,
596 +5950, +5694, +5438, +5182, +4926, +4670, +4414, +4158,
597 +3966, +3838, +3710, +3582, +3454, +3326, +3198, +3070,
598 +2942, +2814, +2686, +2558, +2430, +2302, +2174, +2046,
599 +1950, +1886, +1822, +1758, +1694, +1630, +1566, +1502,
600 +1438, +1374, +1310, +1246, +1182, +1118, +1054, +990,
601 +942, +910, +878, +846, +814, +782, +750, +718,
602 +686, +654, +622, +590, +558, +526, +494, +462,
603 +438, +422, +406, +390, +374, +358, +342, +326,
604 +310, +294, +278, +262, +246, +230, +214, +198,
605 +186, +178, +170, +162, +154, +146, +138, +130,
606 +122, +114, +106, +98, +90, +82, +74, +66,
607 +60, +56, +52, +48, +44, +40, +36, +32,
608 +28, +24, +20, +16, +12, +8, +4, +0
611 REGISTER unsigned char *src;
612 REGISTER unsigned char *dest;
616 if (count > SNDBUFSZ) {
622 src = (unsigned char *)*data;
623 *outbuf = dest = miscplay_sndbuf;
625 /* it is not possible to directly interpolate between two ulaw encoded
626 data bytes, thus we need to convert to linear format first and later
627 we convert back to ulaw format */
628 *dest++ = int2ulaw(ulaw2int[*src] + ulaw2int[*(src + 1)]);
635 size_t sndcnv16swap(void **data, size_t * sz, void **outbuf)
637 size_t cnt = *sz / 2;
641 p = (unsigned short *)*outbuf;
643 *p = ((*p & 0x00ff) << 8) | (*p >> 8);
652 /* Convert 16 bit little endian signed stereo data to 16 bit little endian
654 size_t sndcnv16_2monoLE(void **data, size_t * sz, void **outbuf)
656 REGISTER unsigned char *src;
657 REGISTER unsigned char *dest;
662 if (count > SNDBUFSZ) {
668 src = (unsigned char *)*data;
669 *outbuf = dest = miscplay_sndbuf;
670 for (count /= 2; count--;) {
672 256 * (int)(src[1]) +
673 (int)(src[2]) + 256 * (int)(src[3])) / 2;
675 *dest++ = (unsigned char)(i & 0xFF);
676 *dest++ = (unsigned char)((i / 256) & 0xFF);
682 /* Convert 16 bit big endian signed stereo data to 16 bit big endian
684 size_t sndcnv16_2monoBE(void **data, size_t * sz, void **outbuf)
686 REGISTER unsigned char *src;
687 REGISTER unsigned char *dest;
692 if (count > SNDBUFSZ) {
698 src = (unsigned char *)*data;
699 *outbuf = dest = miscplay_sndbuf;
700 for (count /= 2; count--;) {
702 256 * (int)(src[0]) +
703 (int)(src[3]) + 256 * (int)(src[2])) / 2;
705 *dest++ = (unsigned char)((i / 256) & 0xFF);
706 *dest++ = (unsigned char)(i & 0xFF);
712 /* Convert 16 bit little endian signed data to 8 bit unsigned data */
713 size_t sndcnv2byteLE(void **data, size_t * sz, void **outbuf)
715 REGISTER unsigned char *src;
716 REGISTER unsigned char *dest;
720 if (count > SNDBUFSZ) {
726 src = (unsigned char *)*data;
727 *outbuf = dest = miscplay_sndbuf;
730 (unsigned char)(((signed char *)src)[1] ^ (signed char)
738 /* Convert 16 bit big endian signed data to 8 bit unsigned data */
739 size_t sndcnv2byteBE(void **data, size_t * sz, void **outbuf)
741 REGISTER unsigned char *src;
742 REGISTER unsigned char *dest;
746 if (count > SNDBUFSZ) {
752 src = (unsigned char *)*data;
753 *outbuf = dest = miscplay_sndbuf;
756 (unsigned char)(((signed char *)src)[0] ^ (signed char)
764 /* Convert 16 bit little endian signed stereo data to 8 bit unsigned
766 size_t sndcnv2monobyteLE(void **data, size_t * sz, void **outbuf)
768 REGISTER unsigned char *src;
769 REGISTER unsigned char *dest;
773 if (count > SNDBUFSZ) {
779 src = (unsigned char *)*data;
780 *outbuf = dest = miscplay_sndbuf;
782 *dest++ = (unsigned char)(((int)((signed char *)src)[1] +
783 (int)((signed char *)src)[3]) /
791 /* Convert 16 bit big endian signed stereo data to 8 bit unsigned
793 size_t sndcnv2monobyteBE(void **data, size_t * sz, void **outbuf)
795 REGISTER unsigned char *src;
796 REGISTER unsigned char *dest;
800 if (count > SNDBUFSZ) {
806 src = (unsigned char *)*data;
807 *outbuf = dest = miscplay_sndbuf;
809 *dest++ = (unsigned char)(((int)((signed char *)src)[0] +
810 (int)((signed char *)src)[2]) /
820 media_internal_analyse_data(Lisp_Media_Stream *ms, char *data)
822 /* we always assume to deal with audio data */
823 media_substream *mss = media_stream_nsub(ms);
824 mtype_audio_properties *mtap;
828 mtap = xnew_and_zero(mtype_audio_properties);
829 name = xmalloc_atomic(20);
831 mtap->samplerate = 0;
833 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
834 if (!memcmp(data, "Creative Voice File\x1A\x1A\x00", 22) &&
835 (data[22] + 256 * data[23]) ==
836 ((0x1233 - data[24] - 256 * data[25]) & 0xFFFF)) { /* VOC */
837 memcpy(name, "VOC", 3);
841 mtap->samplerate = 8000;
842 mtap->samplewidth = 16;
844 mtap->endianness = 0;
845 } else if (!memcmp(data, "RIFF", 4) &&
846 !memcmp(data + 8, "WAVEfmt ", 8)) { /* WAVE */
847 memcpy(name, "WAV", 3);
850 mtap->channels = data[22];
851 mtap->samplerate = data[24] + 256 *
852 (data[25] + 256 * (data[26] + 256 * data[27]));
853 mtap->samplewidth = 16;
854 mtap->framesize = mtap->channels * 2;
855 mtap->endianness = 0;
856 } else if (!memcmp(data, ".snd", 4)) { /* Sun Audio (big endian) */
857 if (data[7] + 256 * (data[6] + 256 *
858 (data[5] + 256 * data[4])) < 24) {
859 memcpy(name, "SunAudio", 8);
863 mtap->samplerate = 8000;
864 mtap->samplewidth = 16;
866 mtap->endianness = 0;
867 } else if (!memcmp(data + 12, "\000\000\000\001", 4) ||
868 !memcmp(data + 12, "\000\000\000\002", 4) ||
869 !memcmp(data + 12, "\000\000\000\003", 4)) {
870 memcpy(name, "SunAudio", 8);
873 mtap->channels = data[23];
874 mtap->samplerate = data[19] +
875 256 * (data[18] + 256 *
876 (data[17] + 256 * data[16]));
877 mtap->samplewidth = 16;
878 mtap->framesize = mtap->channels * 2;
879 mtap->endianness = 0;
881 } else if (!memcmp(data, ".sd", 4)) { /* DEC Audio (little endian) */
882 if (data[4] + 256 * (data[5] + 256 *
883 (data[6] + 256 * data[7])) < 24) {
884 memcpy(name, "SunAudio", 8);
888 mtap->samplerate = 8000;
889 mtap->samplewidth = 16;
891 mtap->endianness = 0;
892 } else if (!memcmp(data + 12, "\001\000\000", 4) ||
893 !memcmp(data + 12, "\002\000\000", 4) ||
894 !memcmp(data + 12, "\003\000\000", 4)) {
895 memcpy(name, "SunAudio", 8);
898 mtap->channels = data[20];
899 mtap->samplerate = data[16] +
900 256 * (data[17] + 256 *
901 (data[18] + 256 * data[19]));
902 mtap->samplewidth = 16;
903 mtap->framesize = mtap->channels * 2;
904 mtap->endianness = 0;
908 memcpy(name, "Raw", 3);
912 mtap->samplerate = 8000;
913 mtap->samplewidth = 16;
915 mtap->endianness = 0;
919 /* create a substream and assign */
920 if (mtap->samplerate) {
921 media_substream_type(mss) = MTYPE_AUDIO;
922 media_substream_type_properties(mss).aprops = mtap;
929 void media_internal_analyse_stream(Lisp_Media_Stream *ms)
931 /* stuff for file handling */
933 /* data probe for the internal analyser */
936 media_substream *mss;
938 data = xmalloc_atomic(48);
940 switch (media_stream_kind(ms)) {
942 mkind_file_properties *mkfp = NULL;
943 const char *file = NULL;
947 mkfp = media_stream_kind_properties(ms).fprops;
948 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
949 ALLOCA, (file, file_len), Qnil);
950 SXE_SET_UNUSED(file_len);
952 if (file == NULL || (fd = open(file, O_RDONLY, 0)) < 0) {
957 /* take a data probe */
958 len = read(fd, data, 44);
967 mkind_string_properties *mksp = NULL;
969 /* prepare our user_data */
970 mksp = media_stream_kind_properties(ms).sprops;
971 if (mksp->size < 44) {
975 memcpy(data, mksp->stream_data, 44);
981 case NUMBER_OF_MEDIA_KINDS:
986 /* create a substream */
987 mss = make_media_substream_append(ms);
989 media_internal_analyse_data(ms, data);
991 if (media_substream_type(mss) == MTYPE_AUDIO) {
992 media_stream_driver(ms) = MYSELF;
997 if( fd >= 0) close(fd);
1000 /* Look at the header of the sound file and try to determine the format;
1001 we can recognize files in VOC, WAVE, and, Sun/DEC-audio format--- everything
1002 else is assumed to be raw 8 bit unsigned data sampled at 8kHz */
1003 fmtType analyze_format(unsigned char *format, int *fmt, int *speed,
1005 size_t(**parsesndfile) (void **, size_t * sz, void **))
1007 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
1008 if (!memcmp(format, "Creative Voice File\x1A\x1A\x00", 22) &&
1009 (format[22] + 256 * format[23]) ==
1010 ((0x1233 - format[24] - 256 * format[25]) & 0xFFFF)) { /* VOC */
1014 *parsesndfile = parsevoc;
1016 } else if (!memcmp(format, "RIFF", 4) &&
1017 !memcmp(format + 8, "WAVEfmt ", 8)) { /* WAVE */
1018 if (memcmp(format + 20, "\001\000\001" /* PCM mono */ , 4) &&
1019 memcmp(format + 20, "\001\000\002" /* PCM stereo */ , 4))
1020 return (fmtIllegal);
1021 *fmt = (format[32] / (*tracks = format[22])) == 1 ?
1022 AFMT_U8 : AFMT_S16_LE;
1023 /* Keep compatibility with Linux 68k, etc.
1024 * by not relying on byte-sex
1026 *speed = format[24] + 256 * (format[25] + 256 *
1027 (format[26] + 256 * format[27]));
1028 *parsesndfile = parsewave;
1030 } else if (!memcmp(format, ".snd", 4)) { /* Sun Audio (big endian) */
1032 256 * (format[6] + 256 * (format[5] + 256 * format[4])) <
1037 *parsesndfile = parsesundecaudio;
1038 return (fmtSunAudio);
1040 if (!memcmp(format + 12, "\000\000\000\001", 4))
1042 else if (!memcmp(format + 12, "\000\000\000\002", 4))
1044 else if (!memcmp(format + 12, "\000\000\000\003", 4))
1047 return (fmtIllegal);
1048 /* Keep compatibility with Linux 68k, etc.
1049 * by not relying on byte-sex
1051 *speed = format[19] + 256 * (format[18] + 256 *
1052 (format[17] + 256 * format[16]));
1053 *tracks = format[23];
1054 *parsesndfile = parsesundecaudio;
1055 return (fmtSunAudio);
1056 } else if (!memcmp(format, ".sd", 4)) { /* DEC Audio (little endian) */
1058 256 * (format[5] + 256 * (format[6] + 256 * format[7])) <
1063 *parsesndfile = parsesundecaudio;
1064 return (fmtSunAudio);
1066 if (!memcmp(format + 12, "\001\000\000", 4))
1068 else if (!memcmp(format + 12, "\002\000\000", 4))
1070 else if (!memcmp(format + 12, "\003\000\000", 4))
1073 return (fmtIllegal);
1074 /* Keep compatibility with Linux 68k, etc.
1075 * by not relying on byte-sex
1077 *speed = format[16] + 256 * (format[17] + 256 *
1078 (format[18] + 256 * format[19]));
1079 *tracks = format[20];
1080 *parsesndfile = parsesundecaudio;
1081 return (fmtSunAudio);
1086 *parsesndfile = parseraw;