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 */
507 if ((i = (132 - i)) > 0x7FFF)
509 logi = (i >> ((bits = t_bits[i / 256]) + 4));
510 return ((bits << 4 | logi) ^ 0x7F);
512 if ((i = 132 + i) > 0x7FFF)
514 logi = (i >> ((bits = t_bits[i / 256]) + 4));
515 return (~(bits << 4 | logi));
519 /* Convert from 8 bit ulaw mono to 8 bit linear mono */
520 size_t sndcnvULaw_2linear(void **data, size_t * sz, void **outbuf)
522 /* conversion table stolen from Linux's ulaw.h */
523 static unsigned char ulaw_dsp[] = {
524 3, 7, 11, 15, 19, 23, 27, 31,
525 35, 39, 43, 47, 51, 55, 59, 63,
526 66, 68, 70, 72, 74, 76, 78, 80,
527 82, 84, 86, 88, 90, 92, 94, 96,
528 98, 99, 100, 101, 102, 103, 104, 105,
529 106, 107, 108, 109, 110, 111, 112, 113,
530 113, 114, 114, 115, 115, 116, 116, 117,
531 117, 118, 118, 119, 119, 120, 120, 121,
532 121, 121, 122, 122, 122, 122, 123, 123,
533 123, 123, 124, 124, 124, 124, 125, 125,
534 125, 125, 125, 125, 126, 126, 126, 126,
535 126, 126, 126, 126, 127, 127, 127, 127,
536 127, 127, 127, 127, 127, 127, 127, 127,
537 128, 128, 128, 128, 128, 128, 128, 128,
538 128, 128, 128, 128, 128, 128, 128, 128,
539 128, 128, 128, 128, 128, 128, 128, 128,
540 253, 249, 245, 241, 237, 233, 229, 225,
541 221, 217, 213, 209, 205, 201, 197, 193,
542 190, 188, 186, 184, 182, 180, 178, 176,
543 174, 172, 170, 168, 166, 164, 162, 160,
544 158, 157, 156, 155, 154, 153, 152, 151,
545 150, 149, 148, 147, 146, 145, 144, 143,
546 143, 142, 142, 141, 141, 140, 140, 139,
547 139, 138, 138, 137, 137, 136, 136, 135,
548 135, 135, 134, 134, 134, 134, 133, 133,
549 133, 133, 132, 132, 132, 132, 131, 131,
550 131, 131, 131, 131, 130, 130, 130, 130,
551 130, 130, 130, 130, 129, 129, 129, 129,
552 129, 129, 129, 129, 129, 129, 129, 129,
553 128, 128, 128, 128, 128, 128, 128, 128,
554 128, 128, 128, 128, 128, 128, 128, 128,
555 128, 128, 128, 128, 128, 128, 128, 128,
557 unsigned char *p = (unsigned char *)*data;
566 return p - (unsigned char *)*outbuf;
569 /* Convert 8 bit ulaw stereo data to 8 bit ulaw mono data */
570 size_t sndcnvULaw_2mono(void **data, size_t * sz, void **outbuf)
573 static short int ulaw2int[256] = {
574 /* Precomputed lookup table for conversion from ulaw to 15 bit signed */
575 -16062, -15550, -15038, -14526, -14014, -13502, -12990, -12478,
576 -11966, -11454, -10942, -10430, -9918, -9406, -8894, -8382,
577 -7998, -7742, -7486, -7230, -6974, -6718, -6462, -6206,
578 -5950, -5694, -5438, -5182, -4926, -4670, -4414, -4158,
579 -3966, -3838, -3710, -3582, -3454, -3326, -3198, -3070,
580 -2942, -2814, -2686, -2558, -2430, -2302, -2174, -2046,
581 -1950, -1886, -1822, -1758, -1694, -1630, -1566, -1502,
582 -1438, -1374, -1310, -1246, -1182, -1118, -1054, -990,
583 -942, -910, -878, -846, -814, -782, -750, -718,
584 -686, -654, -622, -590, -558, -526, -494, -462,
585 -438, -422, -406, -390, -374, -358, -342, -326,
586 -310, -294, -278, -262, -246, -230, -214, -198,
587 -186, -178, -170, -162, -154, -146, -138, -130,
588 -122, -114, -106, -98, -90, -82, -74, -66,
589 -60, -56, -52, -48, -44, -40, -36, -32,
590 -28, -24, -20, -16, -12, -8, -4, +0,
591 +16062, +15550, +15038, +14526, +14014, +13502, +12990, +12478,
592 +11966, +11454, +10942, +10430, +9918, +9406, +8894, +8382,
593 +7998, +7742, +7486, +7230, +6974, +6718, +6462, +6206,
594 +5950, +5694, +5438, +5182, +4926, +4670, +4414, +4158,
595 +3966, +3838, +3710, +3582, +3454, +3326, +3198, +3070,
596 +2942, +2814, +2686, +2558, +2430, +2302, +2174, +2046,
597 +1950, +1886, +1822, +1758, +1694, +1630, +1566, +1502,
598 +1438, +1374, +1310, +1246, +1182, +1118, +1054, +990,
599 +942, +910, +878, +846, +814, +782, +750, +718,
600 +686, +654, +622, +590, +558, +526, +494, +462,
601 +438, +422, +406, +390, +374, +358, +342, +326,
602 +310, +294, +278, +262, +246, +230, +214, +198,
603 +186, +178, +170, +162, +154, +146, +138, +130,
604 +122, +114, +106, +98, +90, +82, +74, +66,
605 +60, +56, +52, +48, +44, +40, +36, +32,
606 +28, +24, +20, +16, +12, +8, +4, +0
609 REGISTER unsigned char *src;
610 REGISTER unsigned char *dest;
614 if (count > SNDBUFSZ) {
620 src = (unsigned char *)*data;
621 *outbuf = dest = miscplay_sndbuf;
623 /* it is not possible to directly interpolate between two ulaw encoded
624 data bytes, thus we need to convert to linear format first and later
625 we convert back to ulaw format */
626 *dest++ = int2ulaw(ulaw2int[*src] + ulaw2int[*(src + 1)]);
633 size_t sndcnv16swap(void **data, size_t * sz, void **outbuf)
635 size_t cnt = *sz / 2;
639 p = (unsigned short *)*outbuf;
641 *p = ((*p & 0x00ff) << 8) | (*p >> 8);
650 /* Convert 16 bit little endian signed stereo data to 16 bit little endian
652 size_t sndcnv16_2monoLE(void **data, size_t * sz, void **outbuf)
654 REGISTER unsigned char *src;
655 REGISTER unsigned char *dest;
660 if (count > SNDBUFSZ) {
666 src = (unsigned char *)*data;
667 *outbuf = dest = miscplay_sndbuf;
668 for (count /= 2; count--;) {
670 256 * (int)(src[1]) +
671 (int)(src[2]) + 256 * (int)(src[3])) / 2;
673 *dest++ = (unsigned char)(i & 0xFF);
674 *dest++ = (unsigned char)((i / 256) & 0xFF);
680 /* Convert 16 bit big endian signed stereo data to 16 bit big endian
682 size_t sndcnv16_2monoBE(void **data, size_t * sz, void **outbuf)
684 REGISTER unsigned char *src;
685 REGISTER unsigned char *dest;
690 if (count > SNDBUFSZ) {
696 src = (unsigned char *)*data;
697 *outbuf = dest = miscplay_sndbuf;
698 for (count /= 2; count--;) {
700 256 * (int)(src[0]) +
701 (int)(src[3]) + 256 * (int)(src[2])) / 2;
703 *dest++ = (unsigned char)((i / 256) & 0xFF);
704 *dest++ = (unsigned char)(i & 0xFF);
710 /* Convert 16 bit little endian signed data to 8 bit unsigned data */
711 size_t sndcnv2byteLE(void **data, size_t * sz, void **outbuf)
713 REGISTER unsigned char *src;
714 REGISTER unsigned char *dest;
718 if (count > SNDBUFSZ) {
724 src = (unsigned char *)*data;
725 *outbuf = dest = miscplay_sndbuf;
728 (unsigned char)(((signed char *)src)[1] ^ (signed char)
736 /* Convert 16 bit big endian signed data to 8 bit unsigned data */
737 size_t sndcnv2byteBE(void **data, size_t * sz, void **outbuf)
739 REGISTER unsigned char *src;
740 REGISTER unsigned char *dest;
744 if (count > SNDBUFSZ) {
750 src = (unsigned char *)*data;
751 *outbuf = dest = miscplay_sndbuf;
754 (unsigned char)(((signed char *)src)[0] ^ (signed char)
762 /* Convert 16 bit little endian signed stereo data to 8 bit unsigned
764 size_t sndcnv2monobyteLE(void **data, size_t * sz, void **outbuf)
766 REGISTER unsigned char *src;
767 REGISTER unsigned char *dest;
771 if (count > SNDBUFSZ) {
777 src = (unsigned char *)*data;
778 *outbuf = dest = miscplay_sndbuf;
780 *dest++ = (unsigned char)(((int)((signed char *)src)[1] +
781 (int)((signed char *)src)[3]) /
789 /* Convert 16 bit big endian signed stereo data to 8 bit unsigned
791 size_t sndcnv2monobyteBE(void **data, size_t * sz, void **outbuf)
793 REGISTER unsigned char *src;
794 REGISTER unsigned char *dest;
798 if (count > SNDBUFSZ) {
804 src = (unsigned char *)*data;
805 *outbuf = dest = miscplay_sndbuf;
807 *dest++ = (unsigned char)(((int)((signed char *)src)[0] +
808 (int)((signed char *)src)[2]) /
818 media_internal_analyse_data(Lisp_Media_Stream *ms, char *data)
820 /* we always assume to deal with audio data */
821 media_substream *mss = media_stream_nsub(ms);
822 mtype_audio_properties *mtap;
826 mtap = xnew_and_zero(mtype_audio_properties);
827 name = xmalloc_atomic(20);
829 mtap->samplerate = 0;
831 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
832 if (!memcmp(data, "Creative Voice File\x1A\x1A\x00", 22) &&
833 (data[22] + 256 * data[23]) ==
834 ((0x1233 - data[24] - 256 * data[25]) & 0xFFFF)) { /* VOC */
835 memcpy(name, "VOC", 3);
839 mtap->samplerate = 8000;
840 mtap->samplewidth = 16;
842 mtap->endianness = 0;
843 } else if (!memcmp(data, "RIFF", 4) &&
844 !memcmp(data + 8, "WAVEfmt ", 8)) { /* WAVE */
845 memcpy(name, "WAV", 3);
848 mtap->channels = data[22];
849 mtap->samplerate = data[24] + 256 *
850 (data[25] + 256 * (data[26] + 256 * data[27]));
851 mtap->samplewidth = 16;
852 mtap->framesize = mtap->channels * 2;
853 mtap->endianness = 0;
854 } else if (!memcmp(data, ".snd", 4)) { /* Sun Audio (big endian) */
855 if (data[7] + 256 * (data[6] + 256 *
856 (data[5] + 256 * data[4])) < 24) {
857 memcpy(name, "SunAudio", 8);
861 mtap->samplerate = 8000;
862 mtap->samplewidth = 16;
864 mtap->endianness = 0;
865 } else if (!memcmp(data + 12, "\000\000\000\001", 4) ||
866 !memcmp(data + 12, "\000\000\000\002", 4) ||
867 !memcmp(data + 12, "\000\000\000\003", 4)) {
868 memcpy(name, "SunAudio", 8);
871 mtap->channels = data[23];
872 mtap->samplerate = data[19] +
873 256 * (data[18] + 256 *
874 (data[17] + 256 * data[16]));
875 mtap->samplewidth = 16;
876 mtap->framesize = mtap->channels * 2;
877 mtap->endianness = 0;
879 } else if (!memcmp(data, ".sd", 4)) { /* DEC Audio (little endian) */
880 if (data[4] + 256 * (data[5] + 256 *
881 (data[6] + 256 * data[7])) < 24) {
882 memcpy(name, "SunAudio", 8);
886 mtap->samplerate = 8000;
887 mtap->samplewidth = 16;
889 mtap->endianness = 0;
890 } else if (!memcmp(data + 12, "\001\000\000", 4) ||
891 !memcmp(data + 12, "\002\000\000", 4) ||
892 !memcmp(data + 12, "\003\000\000", 4)) {
893 memcpy(name, "SunAudio", 8);
896 mtap->channels = data[20];
897 mtap->samplerate = data[16] +
898 256 * (data[17] + 256 *
899 (data[18] + 256 * data[19]));
900 mtap->samplewidth = 16;
901 mtap->framesize = mtap->channels * 2;
902 mtap->endianness = 0;
906 memcpy(name, "Raw", 3);
910 mtap->samplerate = 8000;
911 mtap->samplewidth = 16;
913 mtap->endianness = 0;
917 /* create a substream and assign */
918 if (mtap->samplerate) {
919 media_substream_type(mss) = MTYPE_AUDIO;
920 media_substream_type_properties(mss).aprops = mtap;
927 void media_internal_analyse_stream(Lisp_Media_Stream *ms)
929 /* stuff for file handling */
931 /* data probe for the internal analyser */
934 media_substream *mss;
936 data = xmalloc_atomic(48);
938 switch (media_stream_kind(ms)) {
940 mkind_file_properties *mkfp = NULL;
941 const char *file = NULL;
945 mkfp = media_stream_kind_properties(ms).fprops;
946 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
947 ALLOCA, (file, file_len), Qnil);
948 if (file == NULL || (fd = open(file, O_RDONLY, 0)) < 0) {
953 /* take a data probe */
954 len = read(fd, data, 44);
963 mkind_string_properties *mksp = NULL;
965 /* prepare our user_data */
966 mksp = media_stream_kind_properties(ms).sprops;
967 if (mksp->size < 44) {
971 memcpy(data, mksp->stream_data, 44);
977 case NUMBER_OF_MEDIA_KINDS:
982 /* create a substream */
983 mss = make_media_substream_append(ms);
985 media_internal_analyse_data(ms, data);
987 if (media_substream_type(mss) == MTYPE_AUDIO) {
988 media_stream_driver(ms) = MYSELF;
993 if( fd >= 0) close(fd);
996 /* Look at the header of the sound file and try to determine the format;
997 we can recognize files in VOC, WAVE, and, Sun/DEC-audio format--- everything
998 else is assumed to be raw 8 bit unsigned data sampled at 8kHz */
999 fmtType analyze_format(unsigned char *format, int *fmt, int *speed,
1001 size_t(**parsesndfile) (void **, size_t * sz, void **))
1003 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
1004 if (!memcmp(format, "Creative Voice File\x1A\x1A\x00", 22) &&
1005 (format[22] + 256 * format[23]) ==
1006 ((0x1233 - format[24] - 256 * format[25]) & 0xFFFF)) { /* VOC */
1010 *parsesndfile = parsevoc;
1012 } else if (!memcmp(format, "RIFF", 4) &&
1013 !memcmp(format + 8, "WAVEfmt ", 8)) { /* WAVE */
1014 if (memcmp(format + 20, "\001\000\001" /* PCM mono */ , 4) &&
1015 memcmp(format + 20, "\001\000\002" /* PCM stereo */ , 4))
1016 return (fmtIllegal);
1017 *fmt = (format[32] / (*tracks = format[22])) == 1 ?
1018 AFMT_U8 : AFMT_S16_LE;
1019 /* Keep compatibility with Linux 68k, etc.
1020 * by not relying on byte-sex
1022 *speed = format[24] + 256 * (format[25] + 256 *
1023 (format[26] + 256 * format[27]));
1024 *parsesndfile = parsewave;
1026 } else if (!memcmp(format, ".snd", 4)) { /* Sun Audio (big endian) */
1028 256 * (format[6] + 256 * (format[5] + 256 * format[4])) <
1033 *parsesndfile = parsesundecaudio;
1034 return (fmtSunAudio);
1036 if (!memcmp(format + 12, "\000\000\000\001", 4))
1038 else if (!memcmp(format + 12, "\000\000\000\002", 4))
1040 else if (!memcmp(format + 12, "\000\000\000\003", 4))
1043 return (fmtIllegal);
1044 /* Keep compatibility with Linux 68k, etc.
1045 * by not relying on byte-sex
1047 *speed = format[19] + 256 * (format[18] + 256 *
1048 (format[17] + 256 * format[16]));
1049 *tracks = format[23];
1050 *parsesndfile = parsesundecaudio;
1051 return (fmtSunAudio);
1052 } else if (!memcmp(format, ".sd", 4)) { /* DEC Audio (little endian) */
1054 256 * (format[5] + 256 * (format[6] + 256 * format[7])) <
1059 *parsesndfile = parsesundecaudio;
1060 return (fmtSunAudio);
1062 if (!memcmp(format + 12, "\001\000\000", 4))
1064 else if (!memcmp(format + 12, "\002\000\000", 4))
1066 else if (!memcmp(format + 12, "\003\000\000", 4))
1069 return (fmtIllegal);
1070 /* Keep compatibility with Linux 68k, etc.
1071 * by not relying on byte-sex
1073 *speed = format[16] + 256 * (format[17] + 256 *
1074 (format[18] + 256 * format[19]));
1075 *tracks = format[20];
1076 *parsesndfile = parsesundecaudio;
1077 return (fmtSunAudio);
1082 *parsesndfile = parseraw;