-/* There is no special treatment required for parsing raw data files; we
- assume that these files contain data in 8bit unsigned format that
- has been sampled at 8kHz; there is no extra header */
-static size_t parseraw(void **data,size_t *sz,void **outbuf)
-{
- int rc = *sz;
-
- *outbuf = *data;
- *sz = 0;
- return(rc);
-}
-
-/* Currently we cannot cope with files in VOC format; if you really need
- to play these files, they should be converted by using SOX */
-static size_t parsevoc(void **data,size_t *sz,void **outbuf)
-{
- UNUSED(data);
- UNUSED(sz);
- UNUSED(outbuf);
- return(0);
-}
-
-/* We need to perform some look-ahead in order to parse files in WAVE format;
- this might require re-partioning of the data segments if headers cross the
- boundaries between two read operations. This is done in a two-step way:
- first we request a certain amount of bytes... */
-static __inline__ int waverequire(void **data,size_t *sz,size_t rq)
-{
- int rc = 1;
-
- if (rq > HEADERSZ) {
- warn("Header size exceeded while parsing WAVE file");
- parsestate.wave.state = wvFatal;
- *sz = 0;
- return(0); }
- if ((rq -= parsestate.wave.left) <= 0)
- return(rc);
- if (rq > *sz) {rq = *sz; rc = 0;}
- memcpy(parsestate.wave.leftover+parsestate.wave.left,
- *data,rq);
- parsestate.wave.left += rq;
- (*(unsigned char **)data) += rq;
- *sz -= rq;
- return(rc);
-}
-
-/* ...and next we remove this many bytes from the buffer */
-static __inline__ void waveremove(size_t rq)
-{
- if (parsestate.wave.left <= rq)
- parsestate.wave.left = 0;
- else {
- parsestate.wave.left -= rq;
- memmove(parsestate.wave.leftover,
- parsestate.wave.leftover+rq,
- parsestate.wave.left); }
- return;
-}
-
-/* Sound files in WAVE format can contain an arbitrary amount of tagged
- chunks; this requires quite some effort for parsing the data */
-static size_t parsewave(void **data,size_t *sz,void **outbuf)
-{
- for (;;)
- switch (parsestate.wave.state) {
- case wvMain:
- if (!waverequire(data,sz,20))
- return(0);
- /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
- parsestate.wave.chunklength = parsestate.wave.leftover[16] +
- 256*(parsestate.wave.leftover[17] +
- 256*(parsestate.wave.leftover[18] +
- 256*parsestate.wave.leftover[19]));
- waveremove(20);
- parsestate.wave.state = wvSubchunk;
- break;
- case wvSubchunk:
- if (!waverequire(data,sz,parsestate.wave.chunklength))
- return(0);
- parsestate.wave.align = parsestate.wave.chunklength < 14 ? 1
- : parsestate.wave.leftover[12];
- if (parsestate.wave.align != 1 &&
- parsestate.wave.align != 2 &&
- parsestate.wave.align != 4) {
- warn("Illegal datawidth detected while parsing WAVE file");
- parsestate.wave.state = wvFatal; }
- else
- parsestate.wave.state = wvOutOfBlock;
- waveremove(parsestate.wave.chunklength);
- break;
- case wvOutOfBlock:
- if (!waverequire(data,sz,8))
- return(0);
- /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
- parsestate.wave.chunklength = parsestate.wave.leftover[4] +
- 256*(parsestate.wave.leftover[5] +
- 256*(parsestate.wave.leftover[6] +
- 256*(parsestate.wave.leftover[7] & 0x7F)));
- if (memcmp(parsestate.wave.leftover,"data",4))
- parsestate.wave.state = wvSkipChunk;
- else
- parsestate.wave.state = wvSoundChunk;
- waveremove(8);
- break;
- case wvSkipChunk:
- if (parsestate.wave.chunklength > 0 && *sz > 0 &&
- (signed long)*sz < (signed long)parsestate.wave.chunklength) {
- parsestate.wave.chunklength -= *sz;
- *sz = 0; }
- else {
- if (parsestate.wave.chunklength > 0 && *sz > 0) {
- *sz -= parsestate.wave.chunklength;
- (*(unsigned char **)data) += parsestate.wave.chunklength; }
- parsestate.wave.state = wvOutOfBlock; }
- break;
- case wvSoundChunk: {
- size_t count,rq;
- if (parsestate.wave.left) { /* handle leftover bytes from last
- alignment operation */
- count = parsestate.wave.left;
- rq = HEADERSZ-count;
- if (rq > (size_t) parsestate.wave.chunklength)
- rq = parsestate.wave.chunklength;
- if (!waverequire(data,sz,rq)) {
- parsestate.wave.chunklength -= parsestate.wave.left - count;
- return(0); }
- parsestate.wave.chunklength -= rq;
- *outbuf = parsestate.wave.leftover;
- parsestate.wave.left = 0;
- return(rq); }
- if (*sz >= (size_t) parsestate.wave.chunklength) {
- count = parsestate.wave.chunklength;
- rq = 0; }
- else {
- count = *sz;
- count -= rq = count % parsestate.wave.align; }
- *outbuf = *data;
- (*(unsigned char **)data) += count;
- *sz -= count;
- if ((parsestate.wave.chunklength -= count) < parsestate.wave.align) {
- parsestate.wave.state = wvOutOfBlock;
- /* Some broken software (e.g. SOX) attaches junk to the end of a sound
- chunk; so, let's ignore this... */
- if (parsestate.wave.chunklength)
- parsestate.wave.state = wvSkipChunk; }
- else if (rq)
- /* align data length to a multiple of datasize; keep additional data
- in "leftover" buffer --- this is necessary to ensure proper
- functioning of the sndcnv... routines */
- waverequire(data,sz,rq);
- return(count); }
- case wvFatalNotify:
- warn("Irrecoverable error while parsing WAVE file");
- parsestate.wave.state = wvFatal;
- break;
- case wvFatal:
- default:
- *sz = 0;
- return(0); }
-}
-
-/* Strip the header from files in Sun/DEC audio format; this requires some
- extra processing as the header can be an arbitrary size and it might
- result in alignment errors for subsequent conversions --- thus we do
- some buffering, where needed */
-static size_t parsesundecaudio(void **data,size_t *sz,void **outbuf)
-{
- /* There is data left over from the last invocation of this function; join
- it with the new data and return a sound chunk that is as big as a
- single entry */
- if (parsestate.audio.left) {
- if (parsestate.audio.left + *sz > (size_t) parsestate.audio.align) {
- int count;
- memmove(parsestate.audio.leftover + parsestate.audio.left,
- *data,
- count = parsestate.audio.align - parsestate.audio.left);
- *outbuf = parsestate.audio.leftover;
- *sz -= count;
- *data = (*(char **)data) + count;
- parsestate.audio.left = 0;
- return(parsestate.audio.align); }
- else {
- /* We need even more data in order to get one complete single entry! */
- memmove(parsestate.audio.leftover + parsestate.audio.left,
- *data,
- *sz);
- *data = (*(char **)data) + *sz;
- parsestate.audio.left += *sz;
- *sz = 0;
- return(0); } }
-
- /* This is the main sound chunk, strip of any extra data that does not fit
- the alignment requirements and move these bytes into the leftover buffer*/
- if (parsestate.audio.isdata) {
- int rc = *sz;
- *outbuf = *data;
- if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) {
- memmove(parsestate.audio.leftover,
- (char *)*outbuf + rc - parsestate.audio.left,
- parsestate.audio.left);
- rc -= parsestate.audio.left; }
- *sz = 0;
- return(rc); }
-
- /* This is the first invocation of this function; we need to parse the
- header information and determine how many bytes we need to skip until
- the start of the sound chunk */
- if (!parsestate.audio.skipping) {
- unsigned char *header = (unsigned char *) *data;
- if (*sz < 8) {
- warn("Irrecoverable error while parsing Sun/DEC audio file");
- return(0); }
- /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
- if (header[3]) { /* Sun audio (big endian) */
- parsestate.audio.align = ((header[15] > 2)+1)*header[23];
- parsestate.audio.skipping = header[7]+256*(header[6]+256*
- (header[5]+256*header[4])); }
- else { /* DEC audio (little endian) */
- parsestate.audio.align = ((header[12] > 2)+1)*header[20];
- parsestate.audio.skipping = header[4]+256*(header[5]+256*
- (header[6]+256*header[7])); }}
-
- /* We are skipping extra data that has been attached to header; most usually
- this will be just a comment, such as the original filename and/or the
- creation date. Make sure that we do not return less than one single sound
- sample entry to the caller; if this happens, rather decide to move those
- few bytes into the leftover buffer and deal with it later */
- if (*sz >= (size_t) parsestate.audio.skipping) {
- /* Skip just the header information and return the sound chunk */
- int rc = *sz - parsestate.audio.skipping;
- *outbuf = (char *)*data + parsestate.audio.skipping;
- if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) {
- memmove(parsestate.audio.leftover,
- (char *)*outbuf + rc - parsestate.audio.left,
- parsestate.audio.left);
- rc -= parsestate.audio.left; }
- *sz = 0;
- parsestate.audio.skipping = 0;
- parsestate.audio.isdata++;
- return(rc); }
- else {
- /* Skip everything */
- parsestate.audio.skipping -= *sz;
- return(0); }
-}
-
-/* If the soundcard could not be set to natively support the data format, we
- try to do some limited on-the-fly conversion to a different format; if
- no conversion is needed, though, we can output directly */
-static size_t sndcnvnop(void **data,size_t *sz,void **outbuf)
-{
- int rc = *sz;
-
- *outbuf = *data;
- *sz = 0;
- return(rc);
-}
-
-/* Convert 8 bit unsigned stereo data to 8 bit unsigned mono data */
-static size_t sndcnv8U_2mono(void **data,size_t *sz,void **outbuf)
-{
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc,count;
-
- count = *sz / 2;
- if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- while (count--)
- *dest++ = (unsigned char)(((int)*(src)++ +
- (int)*(src)++) / 2);
- *data = src;
- return(rc);
-}
-
-/* Convert 8 bit signed stereo data to 8 bit signed mono data */
-static size_t sndcnv8S_2mono(void **data,size_t *sz,void **outbuf)
-{
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc, count;
-
- count = *sz / 2;
- if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- while (count--)
- *dest++ = (unsigned char)(((int)*((signed char *)(src++)) +
- (int)*((signed char *)(src++))) / 2);
- *data = src;
- return(rc);
-}
-
-/* Convert 8 bit signed stereo data to 8 bit unsigned mono data */
-static size_t sndcnv2monounsigned(void **data,size_t *sz,void **outbuf)
-{
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc,count;
-
- count = *sz / 2;
- if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- while (count--)
- *dest++ = (unsigned char)(((int)*((signed char *)(src++)) +
- (int)*((signed char *)(src++))) / 2) ^ 0x80;
- *data = src;
- return(rc);
-}
-
-/* Convert 8 bit signed mono data to 8 bit unsigned mono data */
-static size_t sndcnv2unsigned(void **data,size_t *sz,void **outbuf)
-{
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc,count;
-
- count = *sz;
- if (count > SNDBUFSZ) { *sz -= SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- while (count--)
- *dest++ = *(src)++ ^ 0x80;
- *data = src;
- return(rc);
-}
-
-/* Convert a number in the range -32768..32767 to an 8 bit ulaw encoded
- number --- I hope, I got this conversion right :-) */
-static __inline__ signed char int2ulaw(int i)
-{
- /* Lookup table for fast calculation of number of bits that need shifting*/
- static short int t_bits[128] = {
- 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,
- 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,
- 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,
- 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};
- REGISTER int bits,logi;
-
- /* unrolling this condition (hopefully) improves execution speed */
- if (i < 0) {
- if ((i = (132-i)) > 0x7FFF) i = 0x7FFF;
- logi = (i >> ((bits = t_bits[i/256])+4));
- return((bits << 4 | logi) ^ 0x7F); }
- else {
- if ((i = 132+i) > 0x7FFF) i = 0x7FFF;
- logi = (i >> ((bits = t_bits[i/256])+4));
- return(~(bits << 4 | logi)); }
-}
-
-/* Convert 8 bit ulaw stereo data to 8 bit ulaw mono data */
-static size_t sndcnvULaw_2mono(void **data,size_t *sz,void **outbuf)
-{
-
- static short int ulaw2int[256] = {
- /* Precomputed lookup table for conversion from ulaw to 15 bit signed */
- -16062,-15550,-15038,-14526,-14014,-13502,-12990,-12478,
- -11966,-11454,-10942,-10430, -9918, -9406, -8894, -8382,
- -7998, -7742, -7486, -7230, -6974, -6718, -6462, -6206,
- -5950, -5694, -5438, -5182, -4926, -4670, -4414, -4158,
- -3966, -3838, -3710, -3582, -3454, -3326, -3198, -3070,
- -2942, -2814, -2686, -2558, -2430, -2302, -2174, -2046,
- -1950, -1886, -1822, -1758, -1694, -1630, -1566, -1502,
- -1438, -1374, -1310, -1246, -1182, -1118, -1054, -990,
- -942, -910, -878, -846, -814, -782, -750, -718,
- -686, -654, -622, -590, -558, -526, -494, -462,
- -438, -422, -406, -390, -374, -358, -342, -326,
- -310, -294, -278, -262, -246, -230, -214, -198,
- -186, -178, -170, -162, -154, -146, -138, -130,
- -122, -114, -106, -98, -90, -82, -74, -66,
- -60, -56, -52, -48, -44, -40, -36, -32,
- -28, -24, -20, -16, -12, -8, -4, +0,
- +16062,+15550,+15038,+14526,+14014,+13502,+12990,+12478,
- +11966,+11454,+10942,+10430, +9918, +9406, +8894, +8382,
- +7998, +7742, +7486, +7230, +6974, +6718, +6462, +6206,
- +5950, +5694, +5438, +5182, +4926, +4670, +4414, +4158,
- +3966, +3838, +3710, +3582, +3454, +3326, +3198, +3070,
- +2942, +2814, +2686, +2558, +2430, +2302, +2174, +2046,
- +1950, +1886, +1822, +1758, +1694, +1630, +1566, +1502,
- +1438, +1374, +1310, +1246, +1182, +1118, +1054, +990,
- +942, +910, +878, +846, +814, +782, +750, +718,
- +686, +654, +622, +590, +558, +526, +494, +462,
- +438, +422, +406, +390, +374, +358, +342, +326,
- +310, +294, +278, +262, +246, +230, +214, +198,
- +186, +178, +170, +162, +154, +146, +138, +130,
- +122, +114, +106, +98, +90, +82, +74, +66,
- +60, +56, +52, +48, +44, +40, +36, +32,
- +28, +24, +20, +16, +12, +8, +4, +0};
-
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc,count;
-
- count = *sz / 2;
- if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- while (count--)
- /* it is not possible to directly interpolate between two ulaw encoded
- data bytes, thus we need to convert to linear format first and later
- we convert back to ulaw format */
- *dest++ = int2ulaw(ulaw2int[*(src)++] +
- ulaw2int[*(src)++]);
- *data = src;
- return(rc);
-}
-
-/* Convert 16 bit little endian signed stereo data to 16 bit little endian
- signed mono data */
-static size_t sndcnv16_2monoLE(void **data,size_t *sz,void **outbuf)
-{
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc,count;
- signed short i;
-
- count = *sz / 2;
- if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- for (count /= 2; count--; ) {
- i = ((int)(src[0]) +
- 256*(int)(src[1]) +
- (int)(src[2]) +
- 256*(int)(src[3])) / 2;
- src += 4;
- *dest++ = (unsigned char)(i & 0xFF);
- *dest++ = (unsigned char)((i / 256) & 0xFF); }
- *data = src;
- return(rc);
-}
-
-/* Convert 16 bit big endian signed stereo data to 16 bit big endian
- signed mono data */
-static size_t sndcnv16_2monoBE(void **data,size_t *sz,void **outbuf)
-{
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc,count;
- signed short i;
-
- count = *sz / 2;
- if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- for (count /= 2; count--; ) {
- i = ((int)(src[1]) +
- 256*(int)(src[0]) +
- (int)(src[3]) +
- 256*(int)(src[2])) / 2;
- src += 4;
- *dest++ = (unsigned char)((i / 256) & 0xFF);
- *dest++ = (unsigned char)(i & 0xFF); }
- *data = src;
- return(rc);
-}
-
-/* Convert 16 bit little endian signed data to 8 bit unsigned data */
-static size_t sndcnv2byteLE(void **data,size_t *sz,void **outbuf)
-{
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc,count;
-
- count = *sz / 2;
- if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- while (count--) {
- *dest++ = (unsigned char)(((signed char *)src)[1] ^ (signed char)0x80);
- src += 2;
- }
- *data = src;
- return(rc);
-}
-
-/* Convert 16 bit big endian signed data to 8 bit unsigned data */
-static size_t sndcnv2byteBE(void **data,size_t *sz,void **outbuf)
-{
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc,count;
-
- count = *sz / 2;
- if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- while (count--) {
- *dest++ = (unsigned char)(((signed char *)src)[0] ^ (signed char)0x80);
- src += 2;
- }
- *data = src;
- return(rc);
-}
-
-/* Convert 16 bit little endian signed stereo data to 8 bit unsigned
- mono data */
-static size_t sndcnv2monobyteLE(void **data,size_t *sz,void **outbuf)
-{
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc,count;
-
- count = *sz / 4;
- if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- while (count--) {
- *dest++ = (unsigned char)(((int)((signed char *)src)[1] +
- (int)((signed char *)src)[3]) / 2 ^ 0x80);
- src += 4;
- }
- *data = src;
- return(rc);
-}
-
-/* Convert 16 bit big endian signed stereo data to 8 bit unsigned
- mono data */
-static size_t sndcnv2monobyteBE(void **data,size_t *sz,void **outbuf)
-{
- REGISTER unsigned char *src;
- REGISTER unsigned char *dest;
- int rc,count;
-
- count = *sz / 4;
- if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; }
- else *sz = 0;
- rc = count;
- src = (unsigned char *) *data;
- *outbuf =
- dest = linuxplay_sndbuf;
- while (count--) {
- *dest++ = (unsigned char)(((int)((signed char *)src)[0] +
- (int)((signed char *)src)[2]) / 2 ^ 0x80);
- src += 4;
- }
- *data = src;
- return(rc);
-}
-
-/* Look at the header of the sound file and try to determine the format;
- we can recognize files in VOC, WAVE, and, Sun/DEC-audio format--- everything
- else is assumed to be raw 8 bit unsigned data sampled at 8kHz */
-static fmtType analyze_format(unsigned char *format,int *fmt,int *speed,
- int *tracks,
- size_t (**parsesndfile)(void **,size_t *sz,
- void **))
-{
- /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
- if (!memcmp(format,"Creative Voice File\x1A\x1A\x00",22) &&
- (format[22]+256*format[23]) ==
- ((0x1233-format[24]-256*format[25])&0xFFFF)) { /* VOC */
- *fmt = AFMT_U8;
- *speed = 8000;
- *tracks = 2;
- *parsesndfile = parsevoc;
- return(fmtVoc); }
- else if (!memcmp(format,"RIFF",4) &&
- !memcmp(format+8,"WAVEfmt ",8)) { /* WAVE */
- if (memcmp(format+20,"\001\000\001"/* PCM mono */,4) &&
- memcmp(format+20,"\001\000\002"/* PCM stereo */,4))
- return(fmtIllegal);
- *fmt = (format[32]/(*tracks = format[22])) == 1 ?
- AFMT_U8 : AFMT_S16_LE;
- /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
- *speed = format[24]+256*(format[25]+256*
- (format[26]+256*format[27]));
- *parsesndfile = parsewave;
- return(fmtWave); }
- else if (!memcmp(format,".snd",4)) { /* Sun Audio (big endian) */
- if (format[7]+256*(format[6]+256*(format[5]+256*format[4])) < 24) {
- *fmt = AFMT_MU_LAW;
- *speed = 8000;
- *tracks = 1;
- *parsesndfile = parsesundecaudio;
- return(fmtSunAudio); }
- if (!memcmp(format+12,"\000\000\000\001",4)) *fmt = AFMT_MU_LAW;
- else if (!memcmp(format+12,"\000\000\000\002",4)) *fmt = AFMT_S8;
- else if (!memcmp(format+12,"\000\000\000\003",4)) *fmt = AFMT_S16_BE;
- else return(fmtIllegal);
- /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
- *speed = format[19]+256*(format[18]+256*
- (format[17]+256*format[16]));
- *tracks = format[23];
- *parsesndfile = parsesundecaudio;
- return(fmtSunAudio); }
- else if (!memcmp(format,".sd",4)) { /* DEC Audio (little endian) */
- if (format[4]+256*(format[5]+256*(format[6]+256*format[7])) < 24) {
- *fmt = AFMT_MU_LAW;
- *speed = 8000;
- *tracks = 1;
- *parsesndfile = parsesundecaudio;
- return(fmtSunAudio); }
- if (!memcmp(format+12,"\001\000\000",4)) *fmt = AFMT_MU_LAW;
- else if (!memcmp(format+12,"\002\000\000",4)) *fmt = AFMT_S8;
- else if (!memcmp(format+12,"\003\000\000",4)) *fmt = AFMT_S16_LE;
- else return(fmtIllegal);
- /* Keep compatibility with Linux 68k, etc. by not relying on byte-sex */
- *speed = format[16]+256*(format[17]+256*
- (format[18]+256*format[19]));
- *tracks = format[20];
- *parsesndfile = parsesundecaudio;
- return(fmtSunAudio); }
- else {
- *fmt = AFMT_U8;
- *speed = 8000;
- *tracks = 1;
- *parsesndfile = parseraw;
- return(fmtRaw); }
-}
-