1 /* miscplay.c - general routines related to playing sounds
3 ** Copyright (C) 1995,96 by Markus Gutschke (gutschk@math.uni-muenster.de)
4 ** This was sawed out from version 1.3 of linuxplay.c by
5 ** Robert Bihlmeyer <robbe@orcus.priv.at>.
7 ** Parts of this code were inspired by sunplay.c, which is copyright 1989 by
8 ** Jef Poskanzer and 1991,92 by Jamie Zawinski; c.f. sunplay.c for further
11 ** Permission to use, copy, modify, and distribute this software and its
12 ** documentation for any purpose and without fee is hereby granted, provided
13 ** that the above copyright notice appear in all copies and that both that
14 ** copyright notice and this permission notice appear in supporting
15 ** documentation. This software is provided "as is" without express or
25 #include "syssignal.h"
27 #define warn(str) message("audio: %s ",GETTEXT(str))
32 #define UNUSED(x) ((void)(x))
38 /* Maintain global variable for keeping parser state information; this struct
39 is set to zero before the first invocation of the parser. The use of a
40 global variable prevents multiple concurrent executions of this code, but
41 this does not happen anyways... */
57 unsigned char leftover[HEADERSZ];
58 signed long chunklength;
65 unsigned char leftover[HEADERSZ];
69 /* Use a global buffer as scratch-pad for possible conversions of the
71 unsigned char miscplay_sndbuf[SNDBUFSZ];
73 /* Initialize global parser state information to zero */
74 void reset_parsestate()
76 memset(&parsestate,0,sizeof(parsestate));
79 /* Verify that we could fully parse the entire soundfile; this is needed
80 only for files in WAVE format */
81 int parse_wave_complete()
83 if (parsestate.wave.state != wvOutOfBlock &&
84 parsestate.wave.state != wvFatal) {
85 warn("Unexpected end of WAVE file");
91 /* There is no special treatment required for parsing raw data files; we
92 assume that these files contain data in 8bit unsigned format that
93 has been sampled at 8kHz; there is no extra header */
94 static size_t parseraw(void **data,size_t *sz,void **outbuf)
103 /* Currently we cannot cope with files in VOC format; if you really need
104 to play these files, they should be converted by using SOX */
105 static size_t parsevoc(void **data,size_t *sz,void **outbuf)
113 /* We need to perform some look-ahead in order to parse files in WAVE format;
114 this might require re-partioning of the data segments if headers cross the
115 boundaries between two read operations. This is done in a two-step way:
116 first we request a certain amount of bytes... */
117 static __inline__ int waverequire(void **data,size_t *sz,size_t rq)
122 warn("Header size exceeded while parsing WAVE file");
123 parsestate.wave.state = wvFatal;
126 if ((rq -= parsestate.wave.left) <= 0)
128 if (rq > *sz) {rq = *sz; rc = 0;}
129 memcpy(parsestate.wave.leftover+parsestate.wave.left,
131 parsestate.wave.left += rq;
132 (*(unsigned char **)data) += rq;
137 /* ...and next we remove this many bytes from the buffer */
138 static __inline__ void waveremove(size_t rq)
140 if (parsestate.wave.left <= rq)
141 parsestate.wave.left = 0;
143 parsestate.wave.left -= rq;
144 memmove(parsestate.wave.leftover,
145 parsestate.wave.leftover+rq,
146 parsestate.wave.left); }
150 /* Sound files in WAVE format can contain an arbitrary amount of tagged
151 chunks; this requires quite some effort for parsing the data */
152 static size_t parsewave(void **data,size_t *sz,void **outbuf)
155 switch (parsestate.wave.state) {
157 if (!waverequire(data,sz,20))
159 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
160 parsestate.wave.chunklength = parsestate.wave.leftover[16] +
161 256*(parsestate.wave.leftover[17] +
162 256*(parsestate.wave.leftover[18] +
163 256*parsestate.wave.leftover[19]));
165 parsestate.wave.state = wvSubchunk;
168 if (!waverequire(data,sz,parsestate.wave.chunklength))
170 parsestate.wave.align = parsestate.wave.chunklength < 14 ? 1
171 : parsestate.wave.leftover[12];
172 if (parsestate.wave.align != 1 &&
173 parsestate.wave.align != 2 &&
174 parsestate.wave.align != 4) {
175 warn("Illegal datawidth detected while parsing WAVE file");
176 parsestate.wave.state = wvFatal; }
178 parsestate.wave.state = wvOutOfBlock;
179 waveremove(parsestate.wave.chunklength);
182 if (!waverequire(data,sz,8))
184 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
185 parsestate.wave.chunklength = parsestate.wave.leftover[4] +
186 256*(parsestate.wave.leftover[5] +
187 256*(parsestate.wave.leftover[6] +
188 256*(parsestate.wave.leftover[7] & 0x7F)));
189 if (memcmp(parsestate.wave.leftover,"data",4))
190 parsestate.wave.state = wvSkipChunk;
192 parsestate.wave.state = wvSoundChunk;
196 if (parsestate.wave.chunklength > 0 && *sz > 0 &&
197 (signed long)*sz < (signed long)parsestate.wave.chunklength) {
198 parsestate.wave.chunklength -= *sz;
201 if (parsestate.wave.chunklength > 0 && *sz > 0) {
202 *sz -= parsestate.wave.chunklength;
203 (*(unsigned char **)data) += parsestate.wave.chunklength; }
204 parsestate.wave.state = wvOutOfBlock; }
208 if (parsestate.wave.left) { /* handle leftover bytes from last
209 alignment operation */
210 count = parsestate.wave.left;
212 if (rq > (size_t) parsestate.wave.chunklength)
213 rq = parsestate.wave.chunklength;
214 if (!waverequire(data,sz,rq)) {
215 parsestate.wave.chunklength -= parsestate.wave.left - count;
217 parsestate.wave.chunklength -= rq;
218 *outbuf = parsestate.wave.leftover;
219 parsestate.wave.left = 0;
221 if (*sz >= (size_t) parsestate.wave.chunklength) {
222 count = parsestate.wave.chunklength;
226 count -= rq = count % parsestate.wave.align; }
228 (*(unsigned char **)data) += count;
230 if ((parsestate.wave.chunklength -= count) < parsestate.wave.align) {
231 parsestate.wave.state = wvOutOfBlock;
232 /* Some broken software (e.g. SOX) attaches junk to the end of a sound
233 chunk; so, let's ignore this... */
234 if (parsestate.wave.chunklength)
235 parsestate.wave.state = wvSkipChunk; }
237 /* align data length to a multiple of datasize; keep additional data
238 in "leftover" buffer --- this is necessary to ensure proper
239 functioning of the sndcnv... routines */
240 waverequire(data,sz,rq);
243 warn("Irrecoverable error while parsing WAVE file");
244 parsestate.wave.state = wvFatal;
252 /* Strip the header from files in Sun/DEC audio format; this requires some
253 extra processing as the header can be an arbitrary size and it might
254 result in alignment errors for subsequent conversions --- thus we do
255 some buffering, where needed */
256 static size_t parsesundecaudio(void **data,size_t *sz,void **outbuf)
258 /* There is data left over from the last invocation of this function; join
259 it with the new data and return a sound chunk that is as big as a
261 if (parsestate.audio.left) {
262 if (parsestate.audio.left + *sz > (size_t) parsestate.audio.align) {
264 memmove(parsestate.audio.leftover + parsestate.audio.left,
266 count = parsestate.audio.align - parsestate.audio.left);
267 *outbuf = parsestate.audio.leftover;
269 *data = (*(char **)data) + count;
270 parsestate.audio.left = 0;
271 return(parsestate.audio.align); }
273 /* We need even more data in order to get one complete single entry! */
274 memmove(parsestate.audio.leftover + parsestate.audio.left,
277 *data = (*(char **)data) + *sz;
278 parsestate.audio.left += *sz;
282 /* This is the main sound chunk, strip of any extra data that does not fit
283 the alignment requirements and move these bytes into the leftover buffer*/
284 if (parsestate.audio.isdata) {
287 if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) {
288 memmove(parsestate.audio.leftover,
289 (char *)*outbuf + rc - parsestate.audio.left,
290 parsestate.audio.left);
291 rc -= parsestate.audio.left; }
295 /* This is the first invocation of this function; we need to parse the
296 header information and determine how many bytes we need to skip until
297 the start of the sound chunk */
298 if (!parsestate.audio.skipping) {
299 unsigned char *header = (unsigned char *) *data;
301 warn("Irrecoverable error while parsing Sun/DEC audio file");
303 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
304 if (header[3]) { /* Sun audio (big endian) */
305 parsestate.audio.align = ((header[15] > 2)+1)*header[23];
306 parsestate.audio.skipping = header[7]+256*(header[6]+256*
307 (header[5]+256*header[4])); }
308 else { /* DEC audio (little endian) */
309 parsestate.audio.align = ((header[12] > 2)+1)*header[20];
310 parsestate.audio.skipping = header[4]+256*(header[5]+256*
311 (header[6]+256*header[7])); }}
313 /* We are skipping extra data that has been attached to header; most usually
314 this will be just a comment, such as the original filename and/or the
315 creation date. Make sure that we do not return less than one single sound
316 sample entry to the caller; if this happens, rather decide to move those
317 few bytes into the leftover buffer and deal with it later */
318 if (*sz >= (size_t) parsestate.audio.skipping) {
319 /* Skip just the header information and return the sound chunk */
320 int rc = *sz - parsestate.audio.skipping;
321 *outbuf = (char *)*data + parsestate.audio.skipping;
322 if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) {
323 memmove(parsestate.audio.leftover,
324 (char *)*outbuf + rc - parsestate.audio.left,
325 parsestate.audio.left);
326 rc -= parsestate.audio.left; }
328 parsestate.audio.skipping = 0;
329 parsestate.audio.isdata++;
332 /* Skip everything */
333 parsestate.audio.skipping -= *sz;
337 /* If the soundcard could not be set to natively support the data format, we
338 try to do some limited on-the-fly conversion to a different format; if
339 no conversion is needed, though, we can output directly */
340 size_t sndcnvnop(void **data,size_t *sz,void **outbuf)
349 /* Convert 8 bit unsigned stereo data to 8 bit unsigned mono data */
350 size_t sndcnv8U_2mono(void **data,size_t *sz,void **outbuf)
352 REGISTER unsigned char *src;
353 REGISTER unsigned char *dest;
357 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
360 src = (unsigned char *) *data;
362 dest = miscplay_sndbuf;
364 *dest++ = (unsigned char)(((int)*(src)++ +
370 /* Convert 8 bit signed stereo data to 8 bit signed mono data */
371 size_t sndcnv8S_2mono(void **data,size_t *sz,void **outbuf)
373 REGISTER unsigned char *src;
374 REGISTER unsigned char *dest;
378 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
381 src = (unsigned char *) *data;
383 dest = miscplay_sndbuf;
385 *dest++ = (unsigned char)(((int)*((signed char *)(src++)) +
386 (int)*((signed char *)(src++))) / 2);
391 /* Convert 8 bit signed stereo data to 8 bit unsigned mono data */
392 size_t sndcnv2monounsigned(void **data,size_t *sz,void **outbuf)
394 REGISTER unsigned char *src;
395 REGISTER unsigned char *dest;
399 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
402 src = (unsigned char *) *data;
404 dest = miscplay_sndbuf;
406 *dest++ = (unsigned char)(((int)*((signed char *)(src++)) +
407 (int)*((signed char *)(src++))) / 2) ^ 0x80;
412 /* Convert 8 bit signed mono data to 8 bit unsigned mono data */
413 size_t sndcnv2unsigned(void **data,size_t *sz,void **outbuf)
415 REGISTER unsigned char *src;
416 REGISTER unsigned char *dest;
420 if (count > SNDBUFSZ) { *sz -= SNDBUFSZ; count = SNDBUFSZ; }
423 src = (unsigned char *) *data;
425 dest = miscplay_sndbuf;
427 *dest++ = *(src)++ ^ 0x80;
432 /* Convert a number in the range -32768..32767 to an 8 bit ulaw encoded
433 number --- I hope, I got this conversion right :-) */
434 static __inline__ signed char int2ulaw(int i)
436 /* Lookup table for fast calculation of number of bits that need shifting*/
437 static short int t_bits[128] = {
438 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
439 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
440 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
441 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
442 REGISTER int bits,logi;
444 /* unrolling this condition (hopefully) improves execution speed */
446 if ((i = (132-i)) > 0x7FFF) i = 0x7FFF;
447 logi = (i >> ((bits = t_bits[i/256])+4));
448 return((bits << 4 | logi) ^ 0x7F); }
450 if ((i = 132+i) > 0x7FFF) i = 0x7FFF;
451 logi = (i >> ((bits = t_bits[i/256])+4));
452 return(~(bits << 4 | logi)); }
455 /* Convert from 8 bit ulaw mono to 8 bit linear mono */
456 size_t sndcnvULaw_2linear(void **data,size_t *sz,void **outbuf)
458 /* conversion table stolen from Linux's ulaw.h */
459 static unsigned char ulaw_dsp[] = {
460 3, 7, 11, 15, 19, 23, 27, 31,
461 35, 39, 43, 47, 51, 55, 59, 63,
462 66, 68, 70, 72, 74, 76, 78, 80,
463 82, 84, 86, 88, 90, 92, 94, 96,
464 98, 99, 100, 101, 102, 103, 104, 105,
465 106, 107, 108, 109, 110, 111, 112, 113,
466 113, 114, 114, 115, 115, 116, 116, 117,
467 117, 118, 118, 119, 119, 120, 120, 121,
468 121, 121, 122, 122, 122, 122, 123, 123,
469 123, 123, 124, 124, 124, 124, 125, 125,
470 125, 125, 125, 125, 126, 126, 126, 126,
471 126, 126, 126, 126, 127, 127, 127, 127,
472 127, 127, 127, 127, 127, 127, 127, 127,
473 128, 128, 128, 128, 128, 128, 128, 128,
474 128, 128, 128, 128, 128, 128, 128, 128,
475 128, 128, 128, 128, 128, 128, 128, 128,
476 253, 249, 245, 241, 237, 233, 229, 225,
477 221, 217, 213, 209, 205, 201, 197, 193,
478 190, 188, 186, 184, 182, 180, 178, 176,
479 174, 172, 170, 168, 166, 164, 162, 160,
480 158, 157, 156, 155, 154, 153, 152, 151,
481 150, 149, 148, 147, 146, 145, 144, 143,
482 143, 142, 142, 141, 141, 140, 140, 139,
483 139, 138, 138, 137, 137, 136, 136, 135,
484 135, 135, 134, 134, 134, 134, 133, 133,
485 133, 133, 132, 132, 132, 132, 131, 131,
486 131, 131, 131, 131, 130, 130, 130, 130,
487 130, 130, 130, 130, 129, 129, 129, 129,
488 129, 129, 129, 129, 129, 129, 129, 129,
489 128, 128, 128, 128, 128, 128, 128, 128,
490 128, 128, 128, 128, 128, 128, 128, 128,
491 128, 128, 128, 128, 128, 128, 128, 128,
493 unsigned char *p=(unsigned char *)*data;
500 return p - (unsigned char *)*outbuf;
503 /* Convert 8 bit ulaw stereo data to 8 bit ulaw mono data */
504 size_t sndcnvULaw_2mono(void **data,size_t *sz,void **outbuf)
507 static short int ulaw2int[256] = {
508 /* Precomputed lookup table for conversion from ulaw to 15 bit signed */
509 -16062,-15550,-15038,-14526,-14014,-13502,-12990,-12478,
510 -11966,-11454,-10942,-10430, -9918, -9406, -8894, -8382,
511 -7998, -7742, -7486, -7230, -6974, -6718, -6462, -6206,
512 -5950, -5694, -5438, -5182, -4926, -4670, -4414, -4158,
513 -3966, -3838, -3710, -3582, -3454, -3326, -3198, -3070,
514 -2942, -2814, -2686, -2558, -2430, -2302, -2174, -2046,
515 -1950, -1886, -1822, -1758, -1694, -1630, -1566, -1502,
516 -1438, -1374, -1310, -1246, -1182, -1118, -1054, -990,
517 -942, -910, -878, -846, -814, -782, -750, -718,
518 -686, -654, -622, -590, -558, -526, -494, -462,
519 -438, -422, -406, -390, -374, -358, -342, -326,
520 -310, -294, -278, -262, -246, -230, -214, -198,
521 -186, -178, -170, -162, -154, -146, -138, -130,
522 -122, -114, -106, -98, -90, -82, -74, -66,
523 -60, -56, -52, -48, -44, -40, -36, -32,
524 -28, -24, -20, -16, -12, -8, -4, +0,
525 +16062,+15550,+15038,+14526,+14014,+13502,+12990,+12478,
526 +11966,+11454,+10942,+10430, +9918, +9406, +8894, +8382,
527 +7998, +7742, +7486, +7230, +6974, +6718, +6462, +6206,
528 +5950, +5694, +5438, +5182, +4926, +4670, +4414, +4158,
529 +3966, +3838, +3710, +3582, +3454, +3326, +3198, +3070,
530 +2942, +2814, +2686, +2558, +2430, +2302, +2174, +2046,
531 +1950, +1886, +1822, +1758, +1694, +1630, +1566, +1502,
532 +1438, +1374, +1310, +1246, +1182, +1118, +1054, +990,
533 +942, +910, +878, +846, +814, +782, +750, +718,
534 +686, +654, +622, +590, +558, +526, +494, +462,
535 +438, +422, +406, +390, +374, +358, +342, +326,
536 +310, +294, +278, +262, +246, +230, +214, +198,
537 +186, +178, +170, +162, +154, +146, +138, +130,
538 +122, +114, +106, +98, +90, +82, +74, +66,
539 +60, +56, +52, +48, +44, +40, +36, +32,
540 +28, +24, +20, +16, +12, +8, +4, +0};
542 REGISTER unsigned char *src;
543 REGISTER unsigned char *dest;
547 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
550 src = (unsigned char *) *data;
552 dest = miscplay_sndbuf;
554 /* it is not possible to directly interpolate between two ulaw encoded
555 data bytes, thus we need to convert to linear format first and later
556 we convert back to ulaw format */
557 *dest++ = int2ulaw(ulaw2int[*(src)++] +
563 size_t sndcnv16swap(void **data,size_t *sz,void **outbuf)
565 size_t cnt = *sz / 2;
569 p = (unsigned short *) *outbuf;
571 *p++ = ((*p & 0x00ff) << 8) | (*p >> 8);
579 /* Convert 16 bit little endian signed stereo data to 16 bit little endian
581 size_t sndcnv16_2monoLE(void **data,size_t *sz,void **outbuf)
583 REGISTER unsigned char *src;
584 REGISTER unsigned char *dest;
589 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
592 src = (unsigned char *) *data;
594 dest = miscplay_sndbuf;
595 for (count /= 2; count--; ) {
599 256*(int)(src[3])) / 2;
601 *dest++ = (unsigned char)(i & 0xFF);
602 *dest++ = (unsigned char)((i / 256) & 0xFF); }
607 /* Convert 16 bit big endian signed stereo data to 16 bit big endian
609 size_t sndcnv16_2monoBE(void **data,size_t *sz,void **outbuf)
611 REGISTER unsigned char *src;
612 REGISTER unsigned char *dest;
617 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
620 src = (unsigned char *) *data;
622 dest = miscplay_sndbuf;
623 for (count /= 2; count--; ) {
627 256*(int)(src[2])) / 2;
629 *dest++ = (unsigned char)((i / 256) & 0xFF);
630 *dest++ = (unsigned char)(i & 0xFF); }
635 /* Convert 16 bit little endian signed data to 8 bit unsigned data */
636 size_t sndcnv2byteLE(void **data,size_t *sz,void **outbuf)
638 REGISTER unsigned char *src;
639 REGISTER unsigned char *dest;
643 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
646 src = (unsigned char *) *data;
648 dest = miscplay_sndbuf;
650 *dest++ = (unsigned char)(((signed char *)src)[1] ^ (signed char)0x80);
657 /* Convert 16 bit big endian signed data to 8 bit unsigned data */
658 size_t sndcnv2byteBE(void **data,size_t *sz,void **outbuf)
660 REGISTER unsigned char *src;
661 REGISTER unsigned char *dest;
665 if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
668 src = (unsigned char *) *data;
670 dest = miscplay_sndbuf;
672 *dest++ = (unsigned char)(((signed char *)src)[0] ^ (signed char)0x80);
679 /* Convert 16 bit little endian signed stereo data to 8 bit unsigned
681 size_t sndcnv2monobyteLE(void **data,size_t *sz,void **outbuf)
683 REGISTER unsigned char *src;
684 REGISTER unsigned char *dest;
688 if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; }
691 src = (unsigned char *) *data;
693 dest = miscplay_sndbuf;
695 *dest++ = (unsigned char)(((int)((signed char *)src)[1] +
696 (int)((signed char *)src)[3]) / 2 ^ 0x80);
703 /* Convert 16 bit big endian signed stereo data to 8 bit unsigned
705 size_t sndcnv2monobyteBE(void **data,size_t *sz,void **outbuf)
707 REGISTER unsigned char *src;
708 REGISTER unsigned char *dest;
712 if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; }
715 src = (unsigned char *) *data;
717 dest = miscplay_sndbuf;
719 *dest++ = (unsigned char)(((int)((signed char *)src)[0] +
720 (int)((signed char *)src)[2]) / 2 ^ 0x80);
727 /* Look at the header of the sound file and try to determine the format;
728 we can recognize files in VOC, WAVE, and, Sun/DEC-audio format--- everything
729 else is assumed to be raw 8 bit unsigned data sampled at 8kHz */
730 fmtType analyze_format(unsigned char *format,int *fmt,int *speed,
732 size_t (**parsesndfile)(void **,size_t *sz,
735 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
736 if (!memcmp(format,"Creative Voice File\x1A\x1A\x00",22) &&
737 (format[22]+256*format[23]) ==
738 ((0x1233-format[24]-256*format[25])&0xFFFF)) { /* VOC */
742 *parsesndfile = parsevoc;
744 else if (!memcmp(format,"RIFF",4) &&
745 !memcmp(format+8,"WAVEfmt ",8)) { /* WAVE */
746 if (memcmp(format+20,"\001\000\001"/* PCM mono */,4) &&
747 memcmp(format+20,"\001\000\002"/* PCM stereo */,4))
749 *fmt = (format[32]/(*tracks = format[22])) == 1 ?
750 AFMT_U8 : AFMT_S16_LE;
751 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
752 *speed = format[24]+256*(format[25]+256*
753 (format[26]+256*format[27]));
754 *parsesndfile = parsewave;
756 else if (!memcmp(format,".snd",4)) { /* Sun Audio (big endian) */
757 if (format[7]+256*(format[6]+256*(format[5]+256*format[4])) < 24) {
761 *parsesndfile = parsesundecaudio;
762 return(fmtSunAudio); }
763 if (!memcmp(format+12,"\000\000\000\001",4)) *fmt = AFMT_MU_LAW;
764 else if (!memcmp(format+12,"\000\000\000\002",4)) *fmt = AFMT_S8;
765 else if (!memcmp(format+12,"\000\000\000\003",4)) *fmt = AFMT_S16_BE;
766 else return(fmtIllegal);
767 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
768 *speed = format[19]+256*(format[18]+256*
769 (format[17]+256*format[16]));
770 *tracks = format[23];
771 *parsesndfile = parsesundecaudio;
772 return(fmtSunAudio); }
773 else if (!memcmp(format,".sd",4)) { /* DEC Audio (little endian) */
774 if (format[4]+256*(format[5]+256*(format[6]+256*format[7])) < 24) {
778 *parsesndfile = parsesundecaudio;
779 return(fmtSunAudio); }
780 if (!memcmp(format+12,"\001\000\000",4)) *fmt = AFMT_MU_LAW;
781 else if (!memcmp(format+12,"\002\000\000",4)) *fmt = AFMT_S8;
782 else if (!memcmp(format+12,"\003\000\000",4)) *fmt = AFMT_S16_LE;
783 else return(fmtIllegal);
784 /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
785 *speed = format[16]+256*(format[17]+256*
786 (format[18]+256*format[19]));
787 *tracks = format[20];
788 *parsesndfile = parsesundecaudio;
789 return(fmtSunAudio); }
794 *parsesndfile = parseraw;