Merge branch 'master' into dbus
[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                 if ((i = (132 - i)) > 0x7FFF)
508                         i = 0x7FFF;
509                 logi = (i >> ((bits = t_bits[i / 256]) + 4));
510                 return ((bits << 4 | logi) ^ 0x7F);
511         } else {
512                 if ((i = 132 + i) > 0x7FFF)
513                         i = 0x7FFF;
514                 logi = (i >> ((bits = t_bits[i / 256]) + 4));
515                 return (~(bits << 4 | logi));
516         }
517 }
518
519 /* Convert from 8 bit ulaw mono to 8 bit linear mono */
520 size_t sndcnvULaw_2linear(void **data, size_t * sz, void **outbuf)
521 {
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,
556         };
557         unsigned char *p = (unsigned char *)*data;
558
559         *outbuf = *data;
560         while ((*sz)--) {
561                 *p = ulaw_dsp[*p];
562                 p++;
563         }
564         *sz = 0;
565         *data = p;
566         return p - (unsigned char *)*outbuf;
567 }
568
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)
571 {
572
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
607         };
608
609         REGISTER unsigned char *src;
610         REGISTER unsigned char *dest;
611         int rc, count;
612
613         count = *sz / 2;
614         if (count > SNDBUFSZ) {
615                 *sz -= 2 * SNDBUFSZ;
616                 count = SNDBUFSZ;
617         } else
618                 *sz = 0;
619         rc = count;
620         src = (unsigned char *)*data;
621         *outbuf = dest = miscplay_sndbuf;
622         while (count--) {
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)]);
627                 src += 2;
628         }
629         *data = src;
630         return (rc);
631 }
632
633 size_t sndcnv16swap(void **data, size_t * sz, void **outbuf)
634 {
635         size_t cnt = *sz / 2;
636         unsigned short *p;
637
638         *outbuf = *data;
639         p = (unsigned short *)*outbuf;
640         while (cnt--) {
641                 *p = ((*p & 0x00ff) << 8) | (*p >> 8);
642                 p++;
643         }
644         *data = p;
645         cnt = *sz;
646         *sz = 0;
647         return cnt;
648 }
649
650 /* Convert 16 bit little endian signed stereo data to 16 bit little endian
651    signed mono data */
652 size_t sndcnv16_2monoLE(void **data, size_t * sz, void **outbuf)
653 {
654         REGISTER unsigned char *src;
655         REGISTER unsigned char *dest;
656         int rc, count;
657         signed short i;
658
659         count = *sz / 2;
660         if (count > SNDBUFSZ) {
661                 *sz -= 2 * SNDBUFSZ;
662                 count = SNDBUFSZ;
663         } else
664                 *sz = 0;
665         rc = count;
666         src = (unsigned char *)*data;
667         *outbuf = dest = miscplay_sndbuf;
668         for (count /= 2; count--;) {
669                 i = ((int)(src[0]) +
670                      256 * (int)(src[1]) +
671                      (int)(src[2]) + 256 * (int)(src[3])) / 2;
672                 src += 4;
673                 *dest++ = (unsigned char)(i & 0xFF);
674                 *dest++ = (unsigned char)((i / 256) & 0xFF);
675         }
676         *data = src;
677         return (rc);
678 }
679
680 /* Convert 16 bit big endian signed stereo data to 16 bit big endian
681    signed mono data */
682 size_t sndcnv16_2monoBE(void **data, size_t * sz, void **outbuf)
683 {
684         REGISTER unsigned char *src;
685         REGISTER unsigned char *dest;
686         int rc, count;
687         signed short i;
688
689         count = *sz / 2;
690         if (count > SNDBUFSZ) {
691                 *sz -= 2 * SNDBUFSZ;
692                 count = SNDBUFSZ;
693         } else
694                 *sz = 0;
695         rc = count;
696         src = (unsigned char *)*data;
697         *outbuf = dest = miscplay_sndbuf;
698         for (count /= 2; count--;) {
699                 i = ((int)(src[1]) +
700                      256 * (int)(src[0]) +
701                      (int)(src[3]) + 256 * (int)(src[2])) / 2;
702                 src += 4;
703                 *dest++ = (unsigned char)((i / 256) & 0xFF);
704                 *dest++ = (unsigned char)(i & 0xFF);
705         }
706         *data = src;
707         return (rc);
708 }
709
710 /* Convert 16 bit little endian signed data to 8 bit unsigned data */
711 size_t sndcnv2byteLE(void **data, size_t * sz, void **outbuf)
712 {
713         REGISTER unsigned char *src;
714         REGISTER unsigned char *dest;
715         int rc, count;
716
717         count = *sz / 2;
718         if (count > SNDBUFSZ) {
719                 *sz -= 2 * SNDBUFSZ;
720                 count = SNDBUFSZ;
721         } else
722                 *sz = 0;
723         rc = count;
724         src = (unsigned char *)*data;
725         *outbuf = dest = miscplay_sndbuf;
726         while (count--) {
727                 *dest++ =
728                     (unsigned char)(((signed char *)src)[1] ^ (signed char)
729                                     0x80);
730                 src += 2;
731         }
732         *data = src;
733         return (rc);
734 }
735
736 /* Convert 16 bit big endian signed data to 8 bit unsigned data */
737 size_t sndcnv2byteBE(void **data, size_t * sz, void **outbuf)
738 {
739         REGISTER unsigned char *src;
740         REGISTER unsigned char *dest;
741         int rc, count;
742
743         count = *sz / 2;
744         if (count > SNDBUFSZ) {
745                 *sz -= 2 * SNDBUFSZ;
746                 count = SNDBUFSZ;
747         } else
748                 *sz = 0;
749         rc = count;
750         src = (unsigned char *)*data;
751         *outbuf = dest = miscplay_sndbuf;
752         while (count--) {
753                 *dest++ =
754                     (unsigned char)(((signed char *)src)[0] ^ (signed char)
755                                     0x80);
756                 src += 2;
757         }
758         *data = src;
759         return (rc);
760 }
761
762 /* Convert 16 bit little endian signed stereo data to 8 bit unsigned
763    mono data */
764 size_t sndcnv2monobyteLE(void **data, size_t * sz, void **outbuf)
765 {
766         REGISTER unsigned char *src;
767         REGISTER unsigned char *dest;
768         int rc, count;
769
770         count = *sz / 4;
771         if (count > SNDBUFSZ) {
772                 *sz -= 4 * SNDBUFSZ;
773                 count = SNDBUFSZ;
774         } else
775                 *sz = 0;
776         rc = count;
777         src = (unsigned char *)*data;
778         *outbuf = dest = miscplay_sndbuf;
779         while (count--) {
780                 *dest++ = (unsigned char)(((int)((signed char *)src)[1] +
781                                            (int)((signed char *)src)[3]) /
782                                           2 ^ 0x80);
783                 src += 4;
784         }
785         *data = src;
786         return (rc);
787 }
788
789 /* Convert 16 bit big endian signed stereo data to 8 bit unsigned
790    mono data */
791 size_t sndcnv2monobyteBE(void **data, size_t * sz, void **outbuf)
792 {
793         REGISTER unsigned char *src;
794         REGISTER unsigned char *dest;
795         int rc, count;
796
797         count = *sz / 4;
798         if (count > SNDBUFSZ) {
799                 *sz -= 4 * SNDBUFSZ;
800                 count = SNDBUFSZ;
801         } else
802                 *sz = 0;
803         rc = count;
804         src = (unsigned char *)*data;
805         *outbuf = dest = miscplay_sndbuf;
806         while (count--) {
807                 *dest++ = (unsigned char)(((int)((signed char *)src)[0] +
808                                            (int)((signed char *)src)[2]) /
809                                           2 ^ 0x80);
810                 src += 4;
811         }
812         *data = src;
813         return (rc);
814 }
815
816 \f
817 static void
818 media_internal_analyse_data(Lisp_Media_Stream *ms, char *data)
819 {
820         /* we always assume to deal with audio data */
821         media_substream *mss = media_stream_nsub(ms);
822         mtype_audio_properties *mtap;
823         char *name;
824
825         /* initialise */
826         mtap = xnew_and_zero(mtype_audio_properties);
827         name = xmalloc_atomic(20);
828
829         mtap->samplerate = 0;
830
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);
836                 name[3] = '\0';
837                 mtap->name = name;
838                 mtap->channels = 2;
839                 mtap->samplerate = 8000;
840                 mtap->samplewidth = 16;
841                 mtap->framesize = 4;
842                 mtap->endianness = 0;
843         } else if (!memcmp(data, "RIFF", 4) &&
844                    !memcmp(data + 8, "WAVEfmt ", 8)) { /* WAVE */
845                 memcpy(name, "WAV", 3);
846                 name[3] = '\0';
847                 mtap->name = name;
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);
858                         name[8] = '\0';
859                         mtap->name = name;
860                         mtap->channels = 1;
861                         mtap->samplerate = 8000;
862                         mtap->samplewidth = 16;
863                         mtap->framesize = 2;
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);
869                         name[8] = '\0';
870                         mtap->name = name;
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;
878                 }
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);
883                         name[8] = '\0';
884                         mtap->name = name;
885                         mtap->channels = 1;
886                         mtap->samplerate = 8000;
887                         mtap->samplewidth = 16;
888                         mtap->framesize = 2;
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);
894                         name[8] = '\0';
895                         mtap->name = name;
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;
903                 }
904         } else {
905 #if 0
906                 memcpy(name, "Raw", 3);
907                 name[3] = '\0';
908                 mtap->name = name;
909                 mtap->channels = 1;
910                 mtap->samplerate = 8000;
911                 mtap->samplewidth = 16;
912                 mtap->framesize = 2;
913                 mtap->endianness = 0;
914 #endif
915         }
916
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;
921         } else {
922                 xfree(mtap);
923                 xfree(name);
924         }
925 }
926
927 void media_internal_analyse_stream(Lisp_Media_Stream *ms)
928 {
929         /* stuff for file handling */
930         int fd = -1, len;
931         /* data probe for the internal analyser */
932         char *data;
933         /* stream stuff */
934         media_substream *mss;
935
936         data = xmalloc_atomic(48);
937
938         switch (media_stream_kind(ms)) {
939         case MKIND_FILE: {
940                 mkind_file_properties *mkfp = NULL;
941                 const char *file = NULL;
942                 int file_len = 0;
943
944                 /* open the file */
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) {
949                         xfree(data);
950                         return;
951                 }
952
953                 /* take a data probe */
954                 len = read(fd, data, 44);
955                 if (len < 44) {
956                         xfree(data);
957                         close(fd);
958                         return;
959                 }
960                 break;
961         }
962         case MKIND_STRING: {
963                 mkind_string_properties *mksp = NULL;
964
965                 /* prepare our user_data */
966                 mksp = media_stream_kind_properties(ms).sprops;
967                 if (mksp->size < 44) {
968                         xfree(data);
969                         return;
970                 }
971                 memcpy(data, mksp->stream_data, 44);
972                 break;
973         }
974         case MKIND_UNKNOWN:
975         case MKIND_FIFO:
976         case MKIND_STREAM:
977         case NUMBER_OF_MEDIA_KINDS:
978         default:
979                 break;
980         }
981
982         /* create a substream */
983         mss = make_media_substream_append(ms);
984
985         media_internal_analyse_data(ms, data);
986
987         if (media_substream_type(mss) == MTYPE_AUDIO) {
988                 media_stream_driver(ms) = MYSELF;
989         }
990
991         /* shutdown */
992         xfree(data);
993         if( fd >= 0) close(fd);
994 }
995
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,
1000                        int *tracks,
1001                        size_t(**parsesndfile) (void **, size_t * sz, void **))
1002 {
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 */
1007                 *fmt = AFMT_U8;
1008                 *speed = 8000;
1009                 *tracks = 2;
1010                 *parsesndfile = parsevoc;
1011                 return (fmtVoc);
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
1021                  */
1022                 *speed = format[24] + 256 * (format[25] + 256 *
1023                                              (format[26] + 256 * format[27]));
1024                 *parsesndfile = parsewave;
1025                 return (fmtWave);
1026         } else if (!memcmp(format, ".snd", 4)) { /* Sun Audio (big endian) */
1027                 if (format[7] +
1028                     256 * (format[6] + 256 * (format[5] + 256 * format[4])) <
1029                     24) {
1030                         *fmt = AFMT_MU_LAW;
1031                         *speed = 8000;
1032                         *tracks = 1;
1033                         *parsesndfile = parsesundecaudio;
1034                         return (fmtSunAudio);
1035                 }
1036                 if (!memcmp(format + 12, "\000\000\000\001", 4))
1037                         *fmt = AFMT_MU_LAW;
1038                 else if (!memcmp(format + 12, "\000\000\000\002", 4))
1039                         *fmt = AFMT_S8;
1040                 else if (!memcmp(format + 12, "\000\000\000\003", 4))
1041                         *fmt = AFMT_S16_BE;
1042                 else
1043                         return (fmtIllegal);
1044                 /* Keep compatibility with Linux 68k, etc.
1045                  * by not relying on byte-sex
1046                  */
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) */
1053                 if (format[4] +
1054                     256 * (format[5] + 256 * (format[6] + 256 * format[7])) <
1055                     24) {
1056                         *fmt = AFMT_MU_LAW;
1057                         *speed = 8000;
1058                         *tracks = 1;
1059                         *parsesndfile = parsesundecaudio;
1060                         return (fmtSunAudio);
1061                 }
1062                 if (!memcmp(format + 12, "\001\000\000", 4))
1063                         *fmt = AFMT_MU_LAW;
1064                 else if (!memcmp(format + 12, "\002\000\000", 4))
1065                         *fmt = AFMT_S8;
1066                 else if (!memcmp(format + 12, "\003\000\000", 4))
1067                         *fmt = AFMT_S16_LE;
1068                 else
1069                         return (fmtIllegal);
1070                 /* Keep compatibility with Linux 68k, etc.
1071                  * by not relying on byte-sex
1072                  */
1073                 *speed = format[16] + 256 * (format[17] + 256 *
1074                                              (format[18] + 256 * format[19]));
1075                 *tracks = format[20];
1076                 *parsesndfile = parsesundecaudio;
1077                 return (fmtSunAudio);
1078         } else {
1079                 *fmt = AFMT_U8;
1080                 *speed = 8000;
1081                 *tracks = 1;
1082                 *parsesndfile = parseraw;
1083                 return (fmtRaw);
1084         }
1085 }
1086
1087 #undef MYSELF