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 waverequire(data, sz, rq);
262 warn("Irrecoverable error while parsing WAVE file");
263 parsestate.wave.state = wvFatal;
272 /* Strip the header from files in Sun/DEC audio format; this requires some
273 extra processing as the header can be an arbitrary size and it might
274 result in alignment errors for subsequent conversions --- thus we do
275 some buffering, where needed */
276 static size_t parsesundecaudio(void **data, size_t * sz, void **outbuf)
278 /* There is data left over from the last invocation of this function; join
279 it with the new data and return a sound chunk that is as big as a
281 if (parsestate.audio.left) {
282 if (parsestate.audio.left + *sz >
283 (size_t) parsestate.audio.align) {
285 memmove(parsestate.audio.leftover +
286 parsestate.audio.left, *data, count =
287 parsestate.audio.align - parsestate.audio.left);
288 *outbuf = parsestate.audio.leftover;
290 *data = (*(char **)data) + count;
291 parsestate.audio.left = 0;
292 return (parsestate.audio.align);
294 /* We need even more data in order to get one complete single entry! */
295 memmove(parsestate.audio.leftover +
296 parsestate.audio.left, *data, *sz);
297 *data = (*(char **)data) + *sz;
298 parsestate.audio.left += *sz;
304 /* This is the main sound chunk, strip of any extra data that does not fit
305 the alignment requirements and move these bytes into the leftover buffer */
306 if (parsestate.audio.isdata) {
309 if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) {
310 memmove(parsestate.audio.leftover,
311 (char *)*outbuf + rc - parsestate.audio.left,
312 parsestate.audio.left);
313 rc -= parsestate.audio.left;
319 /* This is the first invocation of this function; we need to parse the
320 header information and determine how many bytes we need to skip until
321 the start of the sound chunk */
322 if (!parsestate.audio.skipping) {
323 unsigned char *header = (unsigned char *)*data;
325 warn("Irrecoverable error while parsing Sun/DEC audio file");
328 /* Keep compatibility with Linux 68k, etc. by not relying on
330 if (header[3]) { /* Sun audio (big endian) */
331 parsestate.audio.align =
332 ((header[15] > 2) + 1) * header[23];
333 parsestate.audio.skipping =
334 header[7] + 256 * (header[6] +
337 } else { /* DEC audio (little endian) */
338 parsestate.audio.align =
339 ((header[12] > 2) + 1) * header[20];
340 parsestate.audio.skipping =
341 header[4] + 256 * (header[5] +
347 /* We are skipping extra data that has been attached to header; most
348 usually this will be just a comment, such as the original filename
349 and/or the creation date. Make sure that we do not return less than
350 one single sound sample entry to the caller; if this happens, rather
351 decide to move those few bytes into the leftover buffer and deal with
353 if (*sz >= (size_t) parsestate.audio.skipping) {
354 /* Skip just the header information and return the sound chunk */
355 int rc = *sz - parsestate.audio.skipping;
356 *outbuf = (char *)*data + parsestate.audio.skipping;
357 if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) {
358 memmove(parsestate.audio.leftover,
359 (char *)*outbuf + rc - parsestate.audio.left,
360 parsestate.audio.left);
361 rc -= parsestate.audio.left;
364 parsestate.audio.skipping = 0;
365 parsestate.audio.isdata++;
368 /* Skip everything */
369 parsestate.audio.skipping -= *sz;
374 /* If the soundcard could not be set to internally support the data format, we
375 try to do some limited on-the-fly conversion to a different format; if
376 no conversion is needed, though, we can output directly */
377 size_t sndcnvnop(void **data, size_t * sz, void **outbuf)
386 /* Convert 8 bit unsigned stereo data to 8 bit unsigned mono data */
387 size_t sndcnv8U_2mono(void **data, size_t * sz, void **outbuf)
389 REGISTER unsigned char *src;
390 REGISTER unsigned char *dest;
394 if (count > SNDBUFSZ) {
400 src = (unsigned char *)*data;
401 *outbuf = dest = miscplay_sndbuf;
403 *dest++ = (unsigned char)(((int)*(src) + (int)*(src + 1)) / 2);
410 /* Convert 8 bit signed stereo data to 8 bit signed mono data */
411 size_t sndcnv8S_2mono(void **data, size_t * sz, void **outbuf)
413 REGISTER unsigned char *src;
414 REGISTER unsigned char *dest;
418 if (count > SNDBUFSZ) {
424 src = (unsigned char *)*data;
425 *outbuf = dest = miscplay_sndbuf;
427 *dest++ = (unsigned char)(((int)*((signed char *)(src)) +
428 (int)*((signed char *)(src + 1))) /
436 /* Convert 8 bit signed stereo data to 8 bit unsigned mono data */
437 size_t sndcnv2monounsigned(void **data, size_t * sz, void **outbuf)
439 REGISTER unsigned char *src;
440 REGISTER unsigned char *dest;
444 if (count > SNDBUFSZ) {
450 src = (unsigned char *)*data;
451 *outbuf = dest = miscplay_sndbuf;
453 *dest++ = (unsigned char)(((int)*((signed char *)(src)) +
454 (int)*((signed char *)(src + 1))) /
462 /* Convert 8 bit signed mono data to 8 bit unsigned mono data */
463 size_t sndcnv2unsigned(void **data, size_t * sz, void **outbuf)
465 REGISTER unsigned char *src;
466 REGISTER unsigned char *dest;
470 if (count > SNDBUFSZ) {
476 src = (unsigned char *)*data;
477 *outbuf = dest = miscplay_sndbuf;
479 *dest++ = *(src)++ ^ 0x80;
484 /* Convert a number in the range -32768..32767 to an 8 bit ulaw encoded
485 number --- I hope, I got this conversion right :-) */
486 static inline signed char int2ulaw(int i)
488 /* Lookup table for fast calculation of number of bits that need shifting */
489 static short int t_bits[128] = {
490 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
491 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
492 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
493 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
494 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
495 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
496 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
497 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
499 REGISTER int bits, logi;
501 /* unrolling this condition (hopefully) improves execution speed */
503 if ((i = (132 - i)) > 0x7FFF)
505 logi = (i >> ((bits = t_bits[i / 256]) + 4));
506 return ((bits << 4 | logi) ^ 0x7F);
508 if ((i = 132 + i) > 0x7FFF)
510 logi = (i >> ((bits = t_bits[i / 256]) + 4));
511 return (~(bits << 4 | logi));
515 /* Convert from 8 bit ulaw mono to 8 bit linear mono */
516 size_t sndcnvULaw_2linear(void **data, size_t * sz, void **outbuf)
518 /* conversion table stolen from Linux's ulaw.h */
519 static unsigned char ulaw_dsp[] = {
520 3, 7, 11, 15, 19, 23, 27, 31,
521 35, 39, 43, 47, 51, 55, 59, 63,
522 66, 68, 70, 72, 74, 76, 78, 80,
523 82, 84, 86, 88, 90, 92, 94, 96,
524 98, 99, 100, 101, 102, 103, 104, 105,
525 106, 107, 108, 109, 110, 111, 112, 113,
526 113, 114, 114, 115, 115, 116, 116, 117,
527 117, 118, 118, 119, 119, 120, 120, 121,
528 121, 121, 122, 122, 122, 122, 123, 123,
529 123, 123, 124, 124, 124, 124, 125, 125,
530 125, 125, 125, 125, 126, 126, 126, 126,
531 126, 126, 126, 126, 127, 127, 127, 127,
532 127, 127, 127, 127, 127, 127, 127, 127,
533 128, 128, 128, 128, 128, 128, 128, 128,
534 128, 128, 128, 128, 128, 128, 128, 128,
535 128, 128, 128, 128, 128, 128, 128, 128,
536 253, 249, 245, 241, 237, 233, 229, 225,
537 221, 217, 213, 209, 205, 201, 197, 193,
538 190, 188, 186, 184, 182, 180, 178, 176,
539 174, 172, 170, 168, 166, 164, 162, 160,
540 158, 157, 156, 155, 154, 153, 152, 151,
541 150, 149, 148, 147, 146, 145, 144, 143,
542 143, 142, 142, 141, 141, 140, 140, 139,
543 139, 138, 138, 137, 137, 136, 136, 135,
544 135, 135, 134, 134, 134, 134, 133, 133,
545 133, 133, 132, 132, 132, 132, 131, 131,
546 131, 131, 131, 131, 130, 130, 130, 130,
547 130, 130, 130, 130, 129, 129, 129, 129,
548 129, 129, 129, 129, 129, 129, 129, 129,
549 128, 128, 128, 128, 128, 128, 128, 128,
550 128, 128, 128, 128, 128, 128, 128, 128,
551 128, 128, 128, 128, 128, 128, 128, 128,
553 unsigned char *p = (unsigned char *)*data;
562 return p - (unsigned char *)*outbuf;
565 /* Convert 8 bit ulaw stereo data to 8 bit ulaw mono data */
566 size_t sndcnvULaw_2mono(void **data, size_t * sz, void **outbuf)
569 static short int ulaw2int[256] = {
570 /* Precomputed lookup table for conversion from ulaw to 15 bit signed */
571 -16062, -15550, -15038, -14526, -14014, -13502, -12990, -12478,
572 -11966, -11454, -10942, -10430, -9918, -9406, -8894, -8382,
573 -7998, -7742, -7486, -7230, -6974, -6718, -6462, -6206,
574 -5950, -5694, -5438, -5182, -4926, -4670, -4414, -4158,
575 -3966, -3838, -3710, -3582, -3454, -3326, -3198, -3070,
576 -2942, -2814, -2686, -2558, -2430, -2302, -2174, -2046,
577 -1950, -1886, -1822, -1758, -1694, -1630, -1566, -1502,
578 -1438, -1374, -1310, -1246, -1182, -1118, -1054, -990,
579 -942, -910, -878, -846, -814, -782, -750, -718,
580 -686, -654, -622, -590, -558, -526, -494, -462,
581 -438, -422, -406, -390, -374, -358, -342, -326,
582 -310, -294, -278, -262, -246, -230, -214, -198,
583 -186, -178, -170, -162, -154, -146, -138, -130,
584 -122, -114, -106, -98, -90, -82, -74, -66,
585 -60, -56, -52, -48, -44, -40, -36, -32,
586 -28, -24, -20, -16, -12, -8, -4, +0,
587 +16062, +15550, +15038, +14526, +14014, +13502, +12990, +12478,
588 +11966, +11454, +10942, +10430, +9918, +9406, +8894, +8382,
589 +7998, +7742, +7486, +7230, +6974, +6718, +6462, +6206,
590 +5950, +5694, +5438, +5182, +4926, +4670, +4414, +4158,
591 +3966, +3838, +3710, +3582, +3454, +3326, +3198, +3070,
592 +2942, +2814, +2686, +2558, +2430, +2302, +2174, +2046,
593 +1950, +1886, +1822, +1758, +1694, +1630, +1566, +1502,
594 +1438, +1374, +1310, +1246, +1182, +1118, +1054, +990,
595 +942, +910, +878, +846, +814, +782, +750, +718,
596 +686, +654, +622, +590, +558, +526, +494, +462,
597 +438, +422, +406, +390, +374, +358, +342, +326,
598 +310, +294, +278, +262, +246, +230, +214, +198,
599 +186, +178, +170, +162, +154, +146, +138, +130,
600 +122, +114, +106, +98, +90, +82, +74, +66,
601 +60, +56, +52, +48, +44, +40, +36, +32,
602 +28, +24, +20, +16, +12, +8, +4, +0
605 REGISTER unsigned char *src;
606 REGISTER unsigned char *dest;
610 if (count > SNDBUFSZ) {
616 src = (unsigned char *)*data;
617 *outbuf = dest = miscplay_sndbuf;
619 /* it is not possible to directly interpolate between two ulaw encoded
620 data bytes, thus we need to convert to linear format first and later
621 we convert back to ulaw format */
622 *dest++ = int2ulaw(ulaw2int[*src] + ulaw2int[*(src + 1)]);
629 size_t sndcnv16swap(void **data, size_t * sz, void **outbuf)
631 size_t cnt = *sz / 2;
635 p = (unsigned short *)*outbuf;
637 *p = ((*p & 0x00ff) << 8) | (*p >> 8);
646 /* Convert 16 bit little endian signed stereo data to 16 bit little endian
648 size_t sndcnv16_2monoLE(void **data, size_t * sz, void **outbuf)
650 REGISTER unsigned char *src;
651 REGISTER unsigned char *dest;
656 if (count > SNDBUFSZ) {
662 src = (unsigned char *)*data;
663 *outbuf = dest = miscplay_sndbuf;
664 for (count /= 2; count--;) {
666 256 * (int)(src[1]) +
667 (int)(src[2]) + 256 * (int)(src[3])) / 2;
669 *dest++ = (unsigned char)(i & 0xFF);
670 *dest++ = (unsigned char)((i / 256) & 0xFF);
676 /* Convert 16 bit big endian signed stereo data to 16 bit big endian
678 size_t sndcnv16_2monoBE(void **data, size_t * sz, void **outbuf)
680 REGISTER unsigned char *src;
681 REGISTER unsigned char *dest;
686 if (count > SNDBUFSZ) {
692 src = (unsigned char *)*data;
693 *outbuf = dest = miscplay_sndbuf;
694 for (count /= 2; count--;) {
696 256 * (int)(src[0]) +
697 (int)(src[3]) + 256 * (int)(src[2])) / 2;
699 *dest++ = (unsigned char)((i / 256) & 0xFF);
700 *dest++ = (unsigned char)(i & 0xFF);
706 /* Convert 16 bit little endian signed data to 8 bit unsigned data */
707 size_t sndcnv2byteLE(void **data, size_t * sz, void **outbuf)
709 REGISTER unsigned char *src;
710 REGISTER unsigned char *dest;
714 if (count > SNDBUFSZ) {
720 src = (unsigned char *)*data;
721 *outbuf = dest = miscplay_sndbuf;
724 (unsigned char)(((signed char *)src)[1] ^ (signed char)
732 /* Convert 16 bit big endian signed data to 8 bit unsigned data */
733 size_t sndcnv2byteBE(void **data, size_t * sz, void **outbuf)
735 REGISTER unsigned char *src;
736 REGISTER unsigned char *dest;
740 if (count > SNDBUFSZ) {
746 src = (unsigned char *)*data;
747 *outbuf = dest = miscplay_sndbuf;
750 (unsigned char)(((signed char *)src)[0] ^ (signed char)
758 /* Convert 16 bit little endian signed stereo data to 8 bit unsigned
760 size_t sndcnv2monobyteLE(void **data, size_t * sz, void **outbuf)
762 REGISTER unsigned char *src;
763 REGISTER unsigned char *dest;
767 if (count > SNDBUFSZ) {
773 src = (unsigned char *)*data;
774 *outbuf = dest = miscplay_sndbuf;
776 *dest++ = (unsigned char)(((int)((signed char *)src)[1] +
777 (int)((signed char *)src)[3]) /
785 /* Convert 16 bit big endian signed stereo data to 8 bit unsigned
787 size_t sndcnv2monobyteBE(void **data, size_t * sz, void **outbuf)
789 REGISTER unsigned char *src;
790 REGISTER unsigned char *dest;
794 if (count > SNDBUFSZ) {
800 src = (unsigned char *)*data;
801 *outbuf = dest = miscplay_sndbuf;
803 *dest++ = (unsigned char)(((int)((signed char *)src)[0] +
804 (int)((signed char *)src)[2]) /
814 media_internal_analyse_data(Lisp_Media_Stream *ms, char *data)
816 /* we always assume to deal with audio data */
817 media_substream *mss = media_stream_nsub(ms);
818 mtype_audio_properties *mtap;
822 mtap = xnew_and_zero(mtype_audio_properties);
823 name = xmalloc_atomic(20);
825 mtap->samplerate = 0;
827 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
828 if (!memcmp(data, "Creative Voice File\x1A\x1A\x00", 22) &&
829 (data[22] + 256 * data[23]) ==
830 ((0x1233 - data[24] - 256 * data[25]) & 0xFFFF)) { /* VOC */
831 memcpy(name, "VOC", 3);
835 mtap->samplerate = 8000;
836 mtap->samplewidth = 16;
838 mtap->endianness = 0;
839 } else if (!memcmp(data, "RIFF", 4) &&
840 !memcmp(data + 8, "WAVEfmt ", 8)) { /* WAVE */
841 memcpy(name, "WAV", 3);
844 mtap->channels = data[22];
845 mtap->samplerate = data[24] + 256 *
846 (data[25] + 256 * (data[26] + 256 * data[27]));
847 mtap->samplewidth = 16;
848 mtap->framesize = mtap->channels * 2;
849 mtap->endianness = 0;
850 } else if (!memcmp(data, ".snd", 4)) { /* Sun Audio (big endian) */
851 if (data[7] + 256 * (data[6] + 256 *
852 (data[5] + 256 * data[4])) < 24) {
853 memcpy(name, "SunAudio", 8);
857 mtap->samplerate = 8000;
858 mtap->samplewidth = 16;
860 mtap->endianness = 0;
861 } else if (!memcmp(data + 12, "\000\000\000\001", 4) ||
862 !memcmp(data + 12, "\000\000\000\002", 4) ||
863 !memcmp(data + 12, "\000\000\000\003", 4)) {
864 memcpy(name, "SunAudio", 8);
867 mtap->channels = data[23];
868 mtap->samplerate = data[19] +
869 256 * (data[18] + 256 *
870 (data[17] + 256 * data[16]));
871 mtap->samplewidth = 16;
872 mtap->framesize = mtap->channels * 2;
873 mtap->endianness = 0;
875 } else if (!memcmp(data, ".sd", 4)) { /* DEC Audio (little endian) */
876 if (data[4] + 256 * (data[5] + 256 *
877 (data[6] + 256 * data[7])) < 24) {
878 memcpy(name, "SunAudio", 8);
882 mtap->samplerate = 8000;
883 mtap->samplewidth = 16;
885 mtap->endianness = 0;
886 } else if (!memcmp(data + 12, "\001\000\000", 4) ||
887 !memcmp(data + 12, "\002\000\000", 4) ||
888 !memcmp(data + 12, "\003\000\000", 4)) {
889 memcpy(name, "SunAudio", 8);
892 mtap->channels = data[20];
893 mtap->samplerate = data[16] +
894 256 * (data[17] + 256 *
895 (data[18] + 256 * data[19]));
896 mtap->samplewidth = 16;
897 mtap->framesize = mtap->channels * 2;
898 mtap->endianness = 0;
902 memcpy(name, "Raw", 3);
906 mtap->samplerate = 8000;
907 mtap->samplewidth = 16;
909 mtap->endianness = 0;
913 /* create a substream and assign */
914 if (mtap->samplerate) {
915 media_substream_type(mss) = MTYPE_AUDIO;
916 media_substream_type_properties(mss).aprops = mtap;
923 void media_internal_analyse_stream(Lisp_Media_Stream *ms)
925 /* stuff for file handling */
927 /* data probe for the internal analyser */
930 media_substream *mss;
932 data = xmalloc_atomic(48);
934 switch (media_stream_kind(ms)) {
936 mkind_file_properties *mkfp = NULL;
937 const char *file = NULL;
941 mkfp = media_stream_kind_properties(ms).fprops;
942 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
943 ALLOCA, (file, file_len), Qnil);
944 if (file == NULL || (fd = open(file, O_RDONLY, 0)) < 0) {
949 /* take a data probe */
950 len = read(fd, data, 44);
959 mkind_string_properties *mksp = NULL;
961 /* prepare our user_data */
962 mksp = media_stream_kind_properties(ms).sprops;
963 if (mksp->size < 44) {
967 memcpy(data, mksp->stream_data, 44);
973 case NUMBER_OF_MEDIA_KINDS:
978 /* create a substream */
979 mss = make_media_substream_append(ms);
981 media_internal_analyse_data(ms, data);
983 if (media_substream_type(mss) == MTYPE_AUDIO) {
984 media_stream_driver(ms) = MYSELF;
992 /* Look at the header of the sound file and try to determine the format;
993 we can recognize files in VOC, WAVE, and, Sun/DEC-audio format--- everything
994 else is assumed to be raw 8 bit unsigned data sampled at 8kHz */
995 fmtType analyze_format(unsigned char *format, int *fmt, int *speed,
997 size_t(**parsesndfile) (void **, size_t * sz, void **))
999 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
1000 if (!memcmp(format, "Creative Voice File\x1A\x1A\x00", 22) &&
1001 (format[22] + 256 * format[23]) ==
1002 ((0x1233 - format[24] - 256 * format[25]) & 0xFFFF)) { /* VOC */
1006 *parsesndfile = parsevoc;
1008 } else if (!memcmp(format, "RIFF", 4) &&
1009 !memcmp(format + 8, "WAVEfmt ", 8)) { /* WAVE */
1010 if (memcmp(format + 20, "\001\000\001" /* PCM mono */ , 4) &&
1011 memcmp(format + 20, "\001\000\002" /* PCM stereo */ , 4))
1012 return (fmtIllegal);
1013 *fmt = (format[32] / (*tracks = format[22])) == 1 ?
1014 AFMT_U8 : AFMT_S16_LE;
1015 /* Keep compatibility with Linux 68k, etc.
1016 * by not relying on byte-sex
1018 *speed = format[24] + 256 * (format[25] + 256 *
1019 (format[26] + 256 * format[27]));
1020 *parsesndfile = parsewave;
1022 } else if (!memcmp(format, ".snd", 4)) { /* Sun Audio (big endian) */
1024 256 * (format[6] + 256 * (format[5] + 256 * format[4])) <
1029 *parsesndfile = parsesundecaudio;
1030 return (fmtSunAudio);
1032 if (!memcmp(format + 12, "\000\000\000\001", 4))
1034 else if (!memcmp(format + 12, "\000\000\000\002", 4))
1036 else if (!memcmp(format + 12, "\000\000\000\003", 4))
1039 return (fmtIllegal);
1040 /* Keep compatibility with Linux 68k, etc.
1041 * by not relying on byte-sex
1043 *speed = format[19] + 256 * (format[18] + 256 *
1044 (format[17] + 256 * format[16]));
1045 *tracks = format[23];
1046 *parsesndfile = parsesundecaudio;
1047 return (fmtSunAudio);
1048 } else if (!memcmp(format, ".sd", 4)) { /* DEC Audio (little endian) */
1050 256 * (format[5] + 256 * (format[6] + 256 * format[7])) <
1055 *parsesndfile = parsesundecaudio;
1056 return (fmtSunAudio);
1058 if (!memcmp(format + 12, "\001\000\000", 4))
1060 else if (!memcmp(format + 12, "\002\000\000", 4))
1062 else if (!memcmp(format + 12, "\003\000\000", 4))
1065 return (fmtIllegal);
1066 /* Keep compatibility with Linux 68k, etc.
1067 * by not relying on byte-sex
1069 *speed = format[16] + 256 * (format[17] + 256 *
1070 (format[18] + 256 * format[19]));
1071 *tracks = format[20];
1072 *parsesndfile = parsesundecaudio;
1073 return (fmtSunAudio);
1078 *parsesndfile = parseraw;