Minor package-get cleanup + bldchain tweak
[sxemacs] / src / media / media-internal.c
1 /* media-internal.c - general routines related to playing sounds
2  **
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>.
6  **
7  ** Copyright (C) 2006
8  **
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
11  ** information.
12  **
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
18  ** implied warranty.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include "lisp.h"
26 #include "syssignal.h"
27 #include "sysfile.h"
28 #define warn(str)   message("audio: %s ",GETTEXT(str))
29
30 #include <stdlib.h>
31
32 #include "media-internal.h"
33
34 #define MYSELF MDRIVER_INTERNAL
35
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,
41         wvSubchunk,
42         wvOutOfBlock,
43         wvSkipChunk,
44         wvSoundChunk,
45         wvFatal,
46         wvFatalNotify
47 };
48
49 static union {
50         struct {
51                 int align;
52                 enum wvState state;
53                 size_t left;
54                 unsigned char leftover[HEADERSZ];
55                 signed long chunklength;
56         } wave;
57         struct {
58                 int align;
59                 int isdata;
60                 int skipping;
61                 size_t left;
62                 unsigned char leftover[HEADERSZ];
63         } audio;
64 } parsestate;
65
66 /* Use a global buffer as scratch-pad for possible conversions of the
67    sampling format */
68 unsigned char miscplay_sndbuf[SNDBUFSZ];
69
70 /* Initialize global parser state information to zero */
71 void reset_parsestate()
72 {
73         memset(&parsestate, 0, sizeof(parsestate));
74 }
75
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()
79 {
80         if (parsestate.wave.state != wvOutOfBlock &&
81             parsestate.wave.state != wvFatal) {
82                 warn("Unexpected end of WAVE file");
83                 return 0;
84         } else
85                 return 1;
86 }
87
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)
92 {
93         int rc = *sz;
94
95         *outbuf = *data;
96         *sz = 0;
97         return (rc);
98 }
99
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))
104 {
105         return (0);
106 }
107
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)
113 {
114         int rc = 1;
115
116         if (rq > HEADERSZ) {
117                 warn("Header size exceeded while parsing WAVE file");
118                 parsestate.wave.state = wvFatal;
119                 *sz = 0;
120                 return (0);
121         }
122         if ((rq -= parsestate.wave.left) <= 0)
123                 return (rc);
124         if (rq > *sz) {
125                 rq = *sz;
126                 rc = 0;
127         }
128         memcpy(parsestate.wave.leftover + parsestate.wave.left, *data, rq);
129         parsestate.wave.left += rq;
130         (*(unsigned char **)data) += rq;
131         *sz -= rq;
132         return (rc);
133 }
134
135 /* ...and next we remove this many bytes from the buffer */
136 static inline void waveremove(size_t rq)
137 {
138         if (parsestate.wave.left <= rq)
139                 parsestate.wave.left = 0;
140         else {
141                 parsestate.wave.left -= rq;
142                 memmove(parsestate.wave.leftover,
143                         parsestate.wave.leftover + rq, parsestate.wave.left);
144         }
145         return;
146 }
147
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)
151 {
152         for (;;)
153                 switch (parsestate.wave.state) {
154                 case wvMain:
155                         if (!waverequire(data, sz, 20))
156                                 return (0);
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]));
163                         waveremove(20);
164                         parsestate.wave.state = wvSubchunk;
165                         break;
166                 case wvSubchunk:
167                         if (!waverequire(data, sz, parsestate.wave.chunklength))
168                                 return (0);
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;
177                         } else
178                                 parsestate.wave.state = wvOutOfBlock;
179                         waveremove(parsestate.wave.chunklength);
180                         break;
181                 case wvOutOfBlock:
182                         if (!waverequire(data, sz, 8))
183                                 return (0);
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] +
189                                           256 *
190                                           (parsestate.wave.
191                                            leftover[7] & 0x7F)));
192                         if (memcmp(parsestate.wave.leftover, "data", 4))
193                                 parsestate.wave.state = wvSkipChunk;
194                         else
195                                 parsestate.wave.state = wvSoundChunk;
196                         waveremove(8);
197                         break;
198                 case wvSkipChunk:
199                         if (parsestate.wave.chunklength > 0 && *sz > 0 &&
200                             (signed long)*sz <
201                             (signed long)parsestate.wave.chunklength) {
202                                 parsestate.wave.chunklength -= *sz;
203                                 *sz = 0;
204                         } else {
205                                 if (parsestate.wave.chunklength > 0 && *sz > 0) {
206                                         *sz -= parsestate.wave.chunklength;
207                                         (*(unsigned char **)data) +=
208                                             parsestate.wave.chunklength;
209                                 }
210                                 parsestate.wave.state = wvOutOfBlock;
211                         }
212                         break;
213                 case wvSoundChunk:{
214                                 size_t count, rq;
215                                 if (parsestate.wave.left) {     /* handle leftover bytes from last
216                                                                    alignment operation */
217                                         count = parsestate.wave.left;
218                                         rq = HEADERSZ - count;
219                                         if (rq >
220                                             (size_t) parsestate.wave.
221                                             chunklength)
222                                                 rq = parsestate.wave.
223                                                     chunklength;
224                                         if (!waverequire(data, sz, rq)) {
225                                                 parsestate.wave.chunklength -=
226                                                     parsestate.wave.left -
227                                                     count;
228                                                 return (0);
229                                         }
230                                         parsestate.wave.chunklength -= rq;
231                                         *outbuf = parsestate.wave.leftover;
232                                         parsestate.wave.left = 0;
233                                         return (rq);
234                                 }
235                                 if (*sz >= (size_t) parsestate.wave.chunklength) {
236                                         count = parsestate.wave.chunklength;
237                                         rq = 0;
238                                 } else {
239                                         count = *sz;
240                                         count -= rq =
241                                             count % parsestate.wave.align;
242                                 }
243                                 *outbuf = *data;
244                                 (*(unsigned char **)data) += count;
245                                 *sz -= 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 =
253                                                     wvSkipChunk;
254                                 } else if (rq) {
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)
259                                                 return (count);
260                                         else
261                                                 return 0;
262                                 }
263                         }
264                         break;
265                 case wvFatalNotify:
266                         warn("Irrecoverable error while parsing WAVE file");
267                         parsestate.wave.state = wvFatal;
268                         return 0;
269                 case wvFatal:
270                 default:
271                         *sz = 0;
272                         return (0);
273                 }
274 }
275
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)
281 {
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
284            single entry */
285         if (parsestate.audio.left) {
286                 if (parsestate.audio.left + *sz >
287                     (size_t) parsestate.audio.align) {
288                         int count;
289                         memmove(parsestate.audio.leftover +
290                                 parsestate.audio.left, *data, count =
291                                 parsestate.audio.align - parsestate.audio.left);
292                         *outbuf = parsestate.audio.leftover;
293                         *sz -= count;
294                         *data = (*(char **)data) + count;
295                         parsestate.audio.left = 0;
296                         return (parsestate.audio.align);
297                 } else {
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;
303                         *sz = 0;
304                         return (0);
305                 }
306         }
307
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) {
311                 int rc = *sz;
312                 *outbuf = *data;
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;
318                 }
319                 *sz = 0;
320                 return (rc);
321         }
322
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;
328                 if (*sz < 8) {
329                         warn("Irrecoverable error while parsing Sun/DEC audio file");
330                         return (0);
331                 }
332                 /* Keep compatibility with Linux 68k, etc. by not relying on
333                    byte-sex  */
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] +
339                                                256 * (header[5] +
340                                                       256 * header[4]));
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] +
346                                                256 * (header[6] +
347                                                       256 * header[7]));
348                 }
349         }
350
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
356            it later */
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;
366                 }
367                 *sz = 0;
368                 parsestate.audio.skipping = 0;
369                 parsestate.audio.isdata++;
370                 return (rc);
371         } else {
372                 /* Skip everything */
373                 parsestate.audio.skipping -= *sz;
374                 return (0);
375         }
376 }
377
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)
382 {
383         int rc = *sz;
384
385         *outbuf = *data;
386         *sz = 0;
387         return (rc);
388 }
389
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)
392 {
393         REGISTER unsigned char *src;
394         REGISTER unsigned char *dest;
395         int rc, count;
396
397         count = *sz / 2;
398         if (count > SNDBUFSZ) {
399                 *sz -= 2 * SNDBUFSZ;
400                 count = SNDBUFSZ;
401         } else
402                 *sz = 0;
403         rc = count;
404         src = (unsigned char *)*data;
405         *outbuf = dest = miscplay_sndbuf;
406         while (count--) {
407                 *dest++ = (unsigned char)(((int)*(src) + (int)*(src + 1)) / 2);
408                 src += 2;
409         }
410         *data = src;
411         return (rc);
412 }
413
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)
416 {
417         REGISTER unsigned char *src;
418         REGISTER unsigned char *dest;
419         int rc, count;
420
421         count = *sz / 2;
422         if (count > SNDBUFSZ) {
423                 *sz -= 2 * SNDBUFSZ;
424                 count = SNDBUFSZ;
425         } else
426                 *sz = 0;
427         rc = count;
428         src = (unsigned char *)*data;
429         *outbuf = dest = miscplay_sndbuf;
430         while (count--) {
431                 *dest++ = (unsigned char)(((int)*((signed char *)(src)) +
432                                            (int)*((signed char *)(src + 1))) /
433                                           2);
434                 src += 2;
435         }
436         *data = src;
437         return (rc);
438 }
439
440 /* Convert 8 bit signed stereo data to 8 bit unsigned mono data */
441 size_t sndcnv2monounsigned(void **data, size_t * sz, void **outbuf)
442 {
443         REGISTER unsigned char *src;
444         REGISTER unsigned char *dest;
445         int rc, count;
446
447         count = *sz / 2;
448         if (count > SNDBUFSZ) {
449                 *sz -= 2 * SNDBUFSZ;
450                 count = SNDBUFSZ;
451         } else
452                 *sz = 0;
453         rc = count;
454         src = (unsigned char *)*data;
455         *outbuf = dest = miscplay_sndbuf;
456         while (count--) {
457                 *dest++ = (unsigned char)(((int)*((signed char *)(src)) +
458                                            (int)*((signed char *)(src + 1))) /
459                                           2) ^ 0x80;
460                 src += 2;
461         }
462         *data = src;
463         return (rc);
464 }
465
466 /* Convert 8 bit signed mono data to 8 bit unsigned mono data */
467 size_t sndcnv2unsigned(void **data, size_t * sz, void **outbuf)
468 {
469         REGISTER unsigned char *src;
470         REGISTER unsigned char *dest;
471         int rc, count;
472
473         count = *sz;
474         if (count > SNDBUFSZ) {
475                 *sz -= SNDBUFSZ;
476                 count = SNDBUFSZ;
477         } else
478                 *sz = 0;
479         rc = count;
480         src = (unsigned char *)*data;
481         *outbuf = dest = miscplay_sndbuf;
482         while (count--)
483                 *dest++ = *(src)++ ^ 0x80;
484         *data = src;
485         return (rc);
486 }
487
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)
491 {
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
502         };
503         REGISTER int bits, logi;
504
505         /* unrolling this condition (hopefully) improves execution speed */
506         if (i < 0) {
507                 i = 132 - i;
508                 if (i > 0x7FFF)
509                         i = 0x7FFF;
510                 logi = (i >> ((bits = t_bits[i / 256]) + 4));
511                 return ((bits << 4 | logi) ^ 0x7F);
512         } else {
513                 i = 132 + i;
514                 if ( i > 0x7FFF)
515                         i = 0x7FFF;
516                 logi = (i >> ((bits = t_bits[i / 256]) + 4));
517                 return (~(bits << 4 | logi));
518         }
519 }
520
521 /* Convert from 8 bit ulaw mono to 8 bit linear mono */
522 size_t sndcnvULaw_2linear(void **data, size_t * sz, void **outbuf)
523 {
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,
558         };
559         unsigned char *p = (unsigned char *)*data;
560
561         *outbuf = *data;
562         while ((*sz)--) {
563                 *p = ulaw_dsp[*p];
564                 p++;
565         }
566         *sz = 0;
567         *data = p;
568         return p - (unsigned char *)*outbuf;
569 }
570
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)
573 {
574
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
609         };
610
611         REGISTER unsigned char *src;
612         REGISTER unsigned char *dest;
613         int rc, count;
614
615         count = *sz / 2;
616         if (count > SNDBUFSZ) {
617                 *sz -= 2 * SNDBUFSZ;
618                 count = SNDBUFSZ;
619         } else
620                 *sz = 0;
621         rc = count;
622         src = (unsigned char *)*data;
623         *outbuf = dest = miscplay_sndbuf;
624         while (count--) {
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)]);
629                 src += 2;
630         }
631         *data = src;
632         return (rc);
633 }
634
635 size_t sndcnv16swap(void **data, size_t * sz, void **outbuf)
636 {
637         size_t cnt = *sz / 2;
638         unsigned short *p;
639
640         *outbuf = *data;
641         p = (unsigned short *)*outbuf;
642         while (cnt--) {
643                 *p = ((*p & 0x00ff) << 8) | (*p >> 8);
644                 p++;
645         }
646         *data = p;
647         cnt = *sz;
648         *sz = 0;
649         return cnt;
650 }
651
652 /* Convert 16 bit little endian signed stereo data to 16 bit little endian
653    signed mono data */
654 size_t sndcnv16_2monoLE(void **data, size_t * sz, void **outbuf)
655 {
656         REGISTER unsigned char *src;
657         REGISTER unsigned char *dest;
658         int rc, count;
659         signed short i;
660
661         count = *sz / 2;
662         if (count > SNDBUFSZ) {
663                 *sz -= 2 * SNDBUFSZ;
664                 count = SNDBUFSZ;
665         } else
666                 *sz = 0;
667         rc = count;
668         src = (unsigned char *)*data;
669         *outbuf = dest = miscplay_sndbuf;
670         for (count /= 2; count--;) {
671                 i = ((int)(src[0]) +
672                      256 * (int)(src[1]) +
673                      (int)(src[2]) + 256 * (int)(src[3])) / 2;
674                 src += 4;
675                 *dest++ = (unsigned char)(i & 0xFF);
676                 *dest++ = (unsigned char)((i / 256) & 0xFF);
677         }
678         *data = src;
679         return (rc);
680 }
681
682 /* Convert 16 bit big endian signed stereo data to 16 bit big endian
683    signed mono data */
684 size_t sndcnv16_2monoBE(void **data, size_t * sz, void **outbuf)
685 {
686         REGISTER unsigned char *src;
687         REGISTER unsigned char *dest;
688         int rc, count;
689         signed short i;
690
691         count = *sz / 2;
692         if (count > SNDBUFSZ) {
693                 *sz -= 2 * SNDBUFSZ;
694                 count = SNDBUFSZ;
695         } else
696                 *sz = 0;
697         rc = count;
698         src = (unsigned char *)*data;
699         *outbuf = dest = miscplay_sndbuf;
700         for (count /= 2; count--;) {
701                 i = ((int)(src[1]) +
702                      256 * (int)(src[0]) +
703                      (int)(src[3]) + 256 * (int)(src[2])) / 2;
704                 src += 4;
705                 *dest++ = (unsigned char)((i / 256) & 0xFF);
706                 *dest++ = (unsigned char)(i & 0xFF);
707         }
708         *data = src;
709         return (rc);
710 }
711
712 /* Convert 16 bit little endian signed data to 8 bit unsigned data */
713 size_t sndcnv2byteLE(void **data, size_t * sz, void **outbuf)
714 {
715         REGISTER unsigned char *src;
716         REGISTER unsigned char *dest;
717         int rc, count;
718
719         count = *sz / 2;
720         if (count > SNDBUFSZ) {
721                 *sz -= 2 * SNDBUFSZ;
722                 count = SNDBUFSZ;
723         } else
724                 *sz = 0;
725         rc = count;
726         src = (unsigned char *)*data;
727         *outbuf = dest = miscplay_sndbuf;
728         while (count--) {
729                 *dest++ =
730                     (unsigned char)(((signed char *)src)[1] ^ (signed char)
731                                     0x80);
732                 src += 2;
733         }
734         *data = src;
735         return (rc);
736 }
737
738 /* Convert 16 bit big endian signed data to 8 bit unsigned data */
739 size_t sndcnv2byteBE(void **data, size_t * sz, void **outbuf)
740 {
741         REGISTER unsigned char *src;
742         REGISTER unsigned char *dest;
743         int rc, count;
744
745         count = *sz / 2;
746         if (count > SNDBUFSZ) {
747                 *sz -= 2 * SNDBUFSZ;
748                 count = SNDBUFSZ;
749         } else
750                 *sz = 0;
751         rc = count;
752         src = (unsigned char *)*data;
753         *outbuf = dest = miscplay_sndbuf;
754         while (count--) {
755                 *dest++ =
756                     (unsigned char)(((signed char *)src)[0] ^ (signed char)
757                                     0x80);
758                 src += 2;
759         }
760         *data = src;
761         return (rc);
762 }
763
764 /* Convert 16 bit little endian signed stereo data to 8 bit unsigned
765    mono data */
766 size_t sndcnv2monobyteLE(void **data, size_t * sz, void **outbuf)
767 {
768         REGISTER unsigned char *src;
769         REGISTER unsigned char *dest;
770         int rc, count;
771
772         count = *sz / 4;
773         if (count > SNDBUFSZ) {
774                 *sz -= 4 * SNDBUFSZ;
775                 count = SNDBUFSZ;
776         } else
777                 *sz = 0;
778         rc = count;
779         src = (unsigned char *)*data;
780         *outbuf = dest = miscplay_sndbuf;
781         while (count--) {
782                 *dest++ = (unsigned char)(((int)((signed char *)src)[1] +
783                                            (int)((signed char *)src)[3]) /
784                                           2 ^ 0x80);
785                 src += 4;
786         }
787         *data = src;
788         return (rc);
789 }
790
791 /* Convert 16 bit big endian signed stereo data to 8 bit unsigned
792    mono data */
793 size_t sndcnv2monobyteBE(void **data, size_t * sz, void **outbuf)
794 {
795         REGISTER unsigned char *src;
796         REGISTER unsigned char *dest;
797         int rc, count;
798
799         count = *sz / 4;
800         if (count > SNDBUFSZ) {
801                 *sz -= 4 * SNDBUFSZ;
802                 count = SNDBUFSZ;
803         } else
804                 *sz = 0;
805         rc = count;
806         src = (unsigned char *)*data;
807         *outbuf = dest = miscplay_sndbuf;
808         while (count--) {
809                 *dest++ = (unsigned char)(((int)((signed char *)src)[0] +
810                                            (int)((signed char *)src)[2]) /
811                                           2 ^ 0x80);
812                 src += 4;
813         }
814         *data = src;
815         return (rc);
816 }
817
818 \f
819 static void
820 media_internal_analyse_data(Lisp_Media_Stream *ms, char *data)
821 {
822         /* we always assume to deal with audio data */
823         media_substream *mss = media_stream_nsub(ms);
824         mtype_audio_properties *mtap;
825         char *name;
826
827         /* initialise */
828         mtap = xnew_and_zero(mtype_audio_properties);
829         name = xmalloc_atomic(20);
830
831         mtap->samplerate = 0;
832
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);
838                 name[3] = '\0';
839                 mtap->name = name;
840                 mtap->channels = 2;
841                 mtap->samplerate = 8000;
842                 mtap->samplewidth = 16;
843                 mtap->framesize = 4;
844                 mtap->endianness = 0;
845         } else if (!memcmp(data, "RIFF", 4) &&
846                    !memcmp(data + 8, "WAVEfmt ", 8)) { /* WAVE */
847                 memcpy(name, "WAV", 3);
848                 name[3] = '\0';
849                 mtap->name = name;
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);
860                         name[8] = '\0';
861                         mtap->name = name;
862                         mtap->channels = 1;
863                         mtap->samplerate = 8000;
864                         mtap->samplewidth = 16;
865                         mtap->framesize = 2;
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);
871                         name[8] = '\0';
872                         mtap->name = name;
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;
880                 }
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);
885                         name[8] = '\0';
886                         mtap->name = name;
887                         mtap->channels = 1;
888                         mtap->samplerate = 8000;
889                         mtap->samplewidth = 16;
890                         mtap->framesize = 2;
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);
896                         name[8] = '\0';
897                         mtap->name = name;
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;
905                 }
906         } else {
907 #if 0
908                 memcpy(name, "Raw", 3);
909                 name[3] = '\0';
910                 mtap->name = name;
911                 mtap->channels = 1;
912                 mtap->samplerate = 8000;
913                 mtap->samplewidth = 16;
914                 mtap->framesize = 2;
915                 mtap->endianness = 0;
916 #endif
917         }
918
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;
923         } else {
924                 xfree(mtap);
925                 xfree(name);
926         }
927 }
928
929 void media_internal_analyse_stream(Lisp_Media_Stream *ms)
930 {
931         /* stuff for file handling */
932         int fd = -1, len;
933         /* data probe for the internal analyser */
934         char *data;
935         /* stream stuff */
936         media_substream *mss;
937
938         data = xmalloc_atomic(48);
939
940         switch (media_stream_kind(ms)) {
941         case MKIND_FILE: {
942                 mkind_file_properties *mkfp = NULL;
943                 const char *file = NULL;
944                 int file_len = 0;
945
946                 /* open the file */
947                 mkfp = media_stream_kind_properties(ms).fprops;
948                 TO_EXTERNAL_FORMAT(LISP_STRING, mkfp->filename,
949                                    ALLOCA, (file, file_len), Qnil);
950                 if (file == NULL || (fd = open(file, O_RDONLY, 0)) < 0) {
951                         xfree(data);
952                         return;
953                 }
954
955                 /* take a data probe */
956                 len = read(fd, data, 44);
957                 if (len < 44) {
958                         xfree(data);
959                         close(fd);
960                         return;
961                 }
962                 break;
963         }
964         case MKIND_STRING: {
965                 mkind_string_properties *mksp = NULL;
966
967                 /* prepare our user_data */
968                 mksp = media_stream_kind_properties(ms).sprops;
969                 if (mksp->size < 44) {
970                         xfree(data);
971                         return;
972                 }
973                 memcpy(data, mksp->stream_data, 44);
974                 break;
975         }
976         case MKIND_UNKNOWN:
977         case MKIND_FIFO:
978         case MKIND_STREAM:
979         case NUMBER_OF_MEDIA_KINDS:
980         default:
981                 break;
982         }
983
984         /* create a substream */
985         mss = make_media_substream_append(ms);
986
987         media_internal_analyse_data(ms, data);
988
989         if (media_substream_type(mss) == MTYPE_AUDIO) {
990                 media_stream_driver(ms) = MYSELF;
991         }
992
993         /* shutdown */
994         xfree(data);
995         if( fd >= 0) close(fd);
996 }
997
998 /* Look at the header of the sound file and try to determine the format;
999    we can recognize files in VOC, WAVE, and, Sun/DEC-audio format--- everything
1000    else is assumed to be raw 8 bit unsigned data sampled at 8kHz */
1001 fmtType analyze_format(unsigned char *format, int *fmt, int *speed,
1002                        int *tracks,
1003                        size_t(**parsesndfile) (void **, size_t * sz, void **))
1004 {
1005         /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
1006         if (!memcmp(format, "Creative Voice File\x1A\x1A\x00", 22) &&
1007             (format[22] + 256 * format[23]) ==
1008             ((0x1233 - format[24] - 256 * format[25]) & 0xFFFF)) { /* VOC */
1009                 *fmt = AFMT_U8;
1010                 *speed = 8000;
1011                 *tracks = 2;
1012                 *parsesndfile = parsevoc;
1013                 return (fmtVoc);
1014         } else if (!memcmp(format, "RIFF", 4) &&
1015                    !memcmp(format + 8, "WAVEfmt ", 8)) { /* WAVE */
1016                 if (memcmp(format + 20, "\001\000\001" /* PCM mono */ , 4) &&
1017                     memcmp(format + 20, "\001\000\002" /* PCM stereo */ , 4))
1018                         return (fmtIllegal);
1019                 *fmt = (format[32] / (*tracks = format[22])) == 1 ?
1020                     AFMT_U8 : AFMT_S16_LE;
1021                 /* Keep compatibility with Linux 68k, etc.
1022                  * by not relying on byte-sex
1023                  */
1024                 *speed = format[24] + 256 * (format[25] + 256 *
1025                                              (format[26] + 256 * format[27]));
1026                 *parsesndfile = parsewave;
1027                 return (fmtWave);
1028         } else if (!memcmp(format, ".snd", 4)) { /* Sun Audio (big endian) */
1029                 if (format[7] +
1030                     256 * (format[6] + 256 * (format[5] + 256 * format[4])) <
1031                     24) {
1032                         *fmt = AFMT_MU_LAW;
1033                         *speed = 8000;
1034                         *tracks = 1;
1035                         *parsesndfile = parsesundecaudio;
1036                         return (fmtSunAudio);
1037                 }
1038                 if (!memcmp(format + 12, "\000\000\000\001", 4))
1039                         *fmt = AFMT_MU_LAW;
1040                 else if (!memcmp(format + 12, "\000\000\000\002", 4))
1041                         *fmt = AFMT_S8;
1042                 else if (!memcmp(format + 12, "\000\000\000\003", 4))
1043                         *fmt = AFMT_S16_BE;
1044                 else
1045                         return (fmtIllegal);
1046                 /* Keep compatibility with Linux 68k, etc.
1047                  * by not relying on byte-sex
1048                  */
1049                 *speed = format[19] + 256 * (format[18] + 256 *
1050                                              (format[17] + 256 * format[16]));
1051                 *tracks = format[23];
1052                 *parsesndfile = parsesundecaudio;
1053                 return (fmtSunAudio);
1054         } else if (!memcmp(format, ".sd", 4)) { /* DEC Audio (little endian) */
1055                 if (format[4] +
1056                     256 * (format[5] + 256 * (format[6] + 256 * format[7])) <
1057                     24) {
1058                         *fmt = AFMT_MU_LAW;
1059                         *speed = 8000;
1060                         *tracks = 1;
1061                         *parsesndfile = parsesundecaudio;
1062                         return (fmtSunAudio);
1063                 }
1064                 if (!memcmp(format + 12, "\001\000\000", 4))
1065                         *fmt = AFMT_MU_LAW;
1066                 else if (!memcmp(format + 12, "\002\000\000", 4))
1067                         *fmt = AFMT_S8;
1068                 else if (!memcmp(format + 12, "\003\000\000", 4))
1069                         *fmt = AFMT_S16_LE;
1070                 else
1071                         return (fmtIllegal);
1072                 /* Keep compatibility with Linux 68k, etc.
1073                  * by not relying on byte-sex
1074                  */
1075                 *speed = format[16] + 256 * (format[17] + 256 *
1076                                              (format[18] + 256 * format[19]));
1077                 *tracks = format[20];
1078                 *parsesndfile = parsesundecaudio;
1079                 return (fmtSunAudio);
1080         } else {
1081                 *fmt = AFMT_U8;
1082                 *speed = 8000;
1083                 *tracks = 1;
1084                 *parsesndfile = parseraw;
1085                 return (fmtRaw);
1086         }
1087 }
1088
1089 #undef MYSELF