Mercurial > SDL_sound_CoreAudio
diff decoders/shn.c @ 101:c08794028df4
Fully implemented. Needs testing, but it works on the Grateful Dead show I
leeched through etree.org. :)
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Wed, 03 Oct 2001 17:59:14 +0000 |
parents | 6d9fdec2f708 |
children | 103cfcb3c014 |
line wrap: on
line diff
--- a/decoders/shn.c Wed Oct 03 12:25:34 2001 +0000 +++ b/decoders/shn.c Wed Oct 03 17:59:14 2001 +0000 @@ -21,7 +21,7 @@ * Shorten decoder for SDL_sound. * * This driver handles Shorten-compressed waveforms. Despite the fact that - * SHNs are generally used in online trading communities, they tend to be + * SHNs are popular in online music trading communities, they tend to be * much bigger than MP3s. If an MP3 crunches the waveform to 10-20 percent * of its original size, SHNs only go to about 50-60%. Why do the Phish fans * of the world use this format then? Rabid music traders appreciate the @@ -34,7 +34,7 @@ * Shorten homepage: http://www.softsound.com/Shorten.html * * The Shorten format was gleaned from the shorten codebase, by Tony - * Robinson and SoftSound Limited, but none of their code was used here. + * Robinson and SoftSound Limited. * * Please see the file LICENSE in the source's root directory. * @@ -76,6 +76,252 @@ }; +#define SHN_BUFSIZ 512 + +typedef struct +{ + Sint32 version; + Sint32 datatype; + Sint32 nchan; + Sint32 blocksize; + Sint32 maxnlpc; + Sint32 nmean; + Sint32 nwrap; + Sint32 **buffer; + Sint32 **offset; + Sint32 *qlpc; + Sint32 lpcqoffset; + Sint32 bitshift; + int nbitget; + int nbyteget; + Uint8 *getbuf; + Uint8 *getbufp; + Uint32 gbuffer; + Uint8 *backBuffer; + Uint32 backBufferSize; + Uint32 backBufLeft; +} shn_t; + + +static const Uint32 mask_table[] = +{ + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, + 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, + 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF, + 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, + 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, + 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF +}; + + +static const Uint8 ulaw_outward[13][256] = { +{127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128}, +{112,114,116,118,120,122,124,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,113,115,117,119,121,123,125,255,253,251,249,247,245,243,241,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,252,250,248,246,244,242,240}, +{96,98,100,102,104,106,108,110,112,113,114,116,117,118,120,121,122,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,97,99,101,103,105,107,109,111,115,119,123,255,251,247,243,239,237,235,233,231,229,227,225,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,250,249,248,246,245,244,242,241,240,238,236,234,232,230,228,226,224}, +{80,82,84,86,88,90,92,94,96,97,98,100,101,102,104,105,106,108,109,110,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,81,83,85,87,89,91,93,95,99,103,107,111,119,255,247,239,235,231,227,223,221,219,217,215,213,211,209,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,246,245,244,243,242,241,240,238,237,236,234,233,232,230,229,228,226,225,224,222,220,218,216,214,212,210,208}, +{64,66,68,70,72,74,76,78,80,81,82,84,85,86,88,89,90,92,93,94,96,97,98,99,100,101,102,104,105,106,107,108,109,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,65,67,69,71,73,75,77,79,83,87,91,95,103,111,255,239,231,223,219,215,211,207,205,203,201,199,197,195,193,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,238,237,236,235,234,233,232,230,229,228,227,226,225,224,222,221,220,218,217,216,214,213,212,210,209,208,206,204,202,200,198,196,194,192}, +{49,51,53,55,57,59,61,63,64,66,67,68,70,71,72,74,75,76,78,79,80,81,82,84,85,86,87,88,89,90,92,93,94,95,96,97,98,99,100,101,102,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,50,52,54,56,58,60,62,65,69,73,77,83,91,103,255,231,219,211,205,201,197,193,190,188,186,184,182,180,178,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,230,229,228,227,226,225,224,223,222,221,220,218,217,216,215,214,213,212,210,209,208,207,206,204,203,202,200,199,198,196,195,194,192,191,189,187,185,183,181,179,177}, +{32,34,36,38,40,42,44,46,48,49,51,52,53,55,56,57,59,60,61,63,64,65,66,67,68,70,71,72,73,74,75,76,78,79,80,81,82,83,84,85,86,87,88,89,90,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,33,35,37,39,41,43,45,47,50,54,58,62,69,77,91,255,219,205,197,190,186,182,178,175,173,171,169,167,165,163,161,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,218,217,216,215,214,213,212,211,210,209,208,207,206,204,203,202,201,200,199,198,196,195,194,193,192,191,189,188,187,185,184,183,181,180,179,177,176,174,172,170,168,166,164,162,160}, +{16,18,20,22,24,26,28,30,32,33,34,36,37,38,40,41,42,44,45,46,48,49,50,51,52,53,55,56,57,58,59,60,61,63,64,65,66,67,68,69,70,71,72,73,74,75,76,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,19,21,23,25,27,29,31,35,39,43,47,54,62,77,255,205,190,182,175,171,167,163,159,157,155,153,151,149,147,145,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,204,203,202,201,200,199,198,197,196,195,194,193,192,191,189,188,187,186,185,184,183,181,180,179,178,177,176,174,173,172,170,169,168,166,165,164,162,161,160,158,156,154,152,150,148,146,144}, +{2,4,6,8,10,12,14,16,17,18,20,21,22,24,25,26,28,29,30,32,33,34,35,36,37,38,40,41,42,43,44,45,46,48,49,50,51,52,53,54,55,56,57,58,59,60,61,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,1,3,5,7,9,11,13,15,19,23,27,31,39,47,62,255,190,175,167,159,155,151,147,143,141,139,137,135,133,131,129,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,189,188,187,186,185,184,183,182,181,180,179,178,177,176,174,173,172,171,170,169,168,166,165,164,163,162,161,160,158,157,156,154,153,152,150,149,148,146,145,144,142,140,138,136,134,132,130,128}, +{1,2,4,5,6,8,9,10,12,13,14,16,17,18,19,20,21,22,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,3,7,11,15,23,31,47,255,175,159,151,143,139,135,131,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,158,157,156,155,154,153,152,150,149,148,147,146,145,144,142,141,140,138,137,136,134,133,132,130,129,128}, +{1,2,3,4,5,6,8,9,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,7,15,31,255,159,143,135,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,142,141,140,139,138,137,136,134,133,132,131,130,129,128}, +{1,2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,15,255,143,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128}, +{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,0,255,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128} +}; + + +#ifndef MIN_MACRO +#define MIN_MACRO(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef MAX_MACRO +#define MAX_MACRO(a,b) (((a)>(b))?(a):(b)) +#endif + +#define POSITIVE_ULAW_ZERO 0xff +#define NEGATIVE_ULAW_ZERO 0x7f + +#define CAPMAXSCHAR(x) ((x > 127) ? 127 : x) +#define CAPMAXUCHAR(x) ((x > 255) ? 255 : x) +#define CAPMAXSHORT(x) ((x > 32767) ? 32767 : x) +#define CAPMAXUSHORT(x) ((x > 65535) ? 65535 : x) + +#define UNDEFINED_UINT -1 +#define DEFAULT_BLOCK_SIZE 256 +#define DEFAULT_V0NMEAN 0 +#define DEFAULT_V2NMEAN 4 +#define DEFAULT_MAXNLPC 0 +#define DEFAULT_NCHAN 1 +#define DEFAULT_NSKIP 0 +#define DEFAULT_NDISCARD 0 +#define NBITPERLONG 32 +#define DEFAULT_MINSNR 256 +#define DEFAULT_QUANTERROR 0 +#define MINBITRATE 2.5 + +#define MEAN_VERSION0 0 +#define MEAN_VERSION2 4 + +#define SHN_FN_DIFF0 0 +#define SHN_FN_DIFF1 1 +#define SHN_FN_DIFF2 2 +#define SHN_FN_DIFF3 3 +#define SHN_FN_QUIT 4 +#define SHN_FN_BLOCKSIZE 5 +#define SHN_FN_BITSHIFT 6 +#define SHN_FN_QLPC 7 +#define SHN_FN_ZERO 8 +#define SHN_FN_VERBATIM 9 + +#define SHN_TYPE_AU1 0 +#define SHN_TYPE_S8 1 +#define SHN_TYPE_U8 2 +#define SHN_TYPE_S16HL 3 +#define SHN_TYPE_U16HL 4 +#define SHN_TYPE_S16LH 5 +#define SHN_TYPE_U16LH 6 +#define SHN_TYPE_ULAW 7 +#define SHN_TYPE_AU2 8 +#define SHN_TYPE_AU3 9 +#define SHN_TYPE_ALAW 10 +#define SHN_TYPE_RIFF_WAVE 11 +#define SHN_TYPE_EOF 12 +#define SHN_TYPE_GENERIC_ULAW 128 +#define SHN_TYPE_GENERIC_ALAW 129 + +#define SHN_FNSIZE 2 +#define SHN_CHANNELSIZE 0 +#define SHN_TYPESIZE 4 +#define SHN_ULONGSIZE 2 +#define SHN_NSKIPSIZE 1 +#define SHN_LPCQSIZE 2 +#define SHN_LPCQUANT 5 +#define SHN_XBYTESIZE 7 +#define SHN_VERBATIM_CKSIZE_SIZE 5 +#define SHN_VERBATIM_BYTE_SIZE 8 +#define SHN_ENERGYSIZE 3 +#define SHN_BITSHIFTSIZE 2 + +#define SHN_LPCQOFFSET_VER2 (1 << SHN_LPCQUANT) + + +#define MAGIC_NUM 0x676B6A61 /* looks like "ajkg" as chars. */ + +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + + +static int word_get(shn_t *shn, SDL_RWops *rw, Uint32 *word) +{ + if (shn->nbyteget < 4) + { + shn->nbyteget += SDL_RWread(rw, shn->getbuf, 1, SHN_BUFSIZ); + BAIL_IF_MACRO(shn->nbyteget < 4, NULL, 0); + shn->getbufp = shn->getbuf; + } /* if */ + + if (word != NULL) + { + *word = (((Sint32) shn->getbufp[0]) << 24) | + (((Sint32) shn->getbufp[1]) << 16) | + (((Sint32) shn->getbufp[2]) << 8) | + (((Sint32) shn->getbufp[3]) ); + } /* if */ + + shn->getbufp += 4; + shn->nbyteget -= 4; + + return(1); +} /* word_get */ + + +static int uvar_get(int nbin, shn_t *shn, SDL_RWops *rw, Sint32 *word) +{ + Sint32 result; + + if (shn->nbitget == 0) + { + BAIL_IF_MACRO(!word_get(shn, rw, &shn->gbuffer), NULL, 0); + shn->nbitget = 32; + } /* if */ + + for (result = 0; !(shn->gbuffer & (1L << --shn->nbitget)); result++) + { + if (shn->nbitget == 0) + { + BAIL_IF_MACRO(!word_get(shn, rw, &shn->gbuffer), NULL, 0); + shn->nbitget = 32; + } /* if */ + } /* for */ + + while (nbin != 0) + { + if (shn->nbitget >= nbin) + { + result = ( (result << nbin) | + ((shn->gbuffer >> (shn->nbitget - nbin)) & + mask_table[nbin]) ); + shn->nbitget -= nbin; + break; + } /* if */ + else + { + result = (result << shn->nbitget) | + (shn->gbuffer & mask_table[shn->nbitget]); + BAIL_IF_MACRO(!word_get(shn, rw, &shn->gbuffer), NULL, 0); + nbin -= shn->nbitget; + shn->nbitget = 32; + } /* else */ + } /* while */ + + if (word != NULL) + *word = result; + + return(1); +} /* uvar_get */ + + +static int var_get(int nbin, shn_t *shn, SDL_RWops *rw, Sint32 *word) +{ + BAIL_IF_MACRO(!uvar_get(nbin + 1, shn, rw, word), NULL, 0); + + if ((*word) & 1) + *word = (Sint32) ~((*word) >> 1); + else + *word = (Sint32) ((*word) >> 1); + + return(1); +} /* var_get */ + + +static int ulong_get(shn_t *shn, SDL_RWops *rw, Sint32 *word) +{ + Sint32 nbit; + Sint32 retval; + BAIL_IF_MACRO(!uvar_get(SHN_ULONGSIZE, shn, rw, &nbit), NULL, 0); + BAIL_IF_MACRO(!uvar_get(nbit, shn, rw, &retval), NULL, 0); + + if (word != NULL) + *word = retval; + + return(1); +} /* ulong_get */ + + +static inline int uint_get(int nbit, shn_t *shn, SDL_RWops *rw, Sint32 *word) +{ + return((shn->version == 0) ? + uvar_get(nbit, shn, rw, word) : + ulong_get(shn, rw, word)); +} /* uint_get */ + + static int SHN_init(void) { return(1); /* initialization always successful. */ @@ -88,19 +334,6 @@ } /* SHN_quit */ -static Uint32 mask_table[] = -{ - 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, - 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, - 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF, - 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, - 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, - 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF -}; - - -#define MAGIC_NUM 0x676B6A61 /* looks like "ajkg" as chars. */ - /* * Look through the whole file for a SHN magic number. This is costly, so * it should only be done if the user SWEARS they have a Shorten stream... @@ -115,7 +348,7 @@ { BAIL_IF_MACRO(SDL_RWread(rw, &ch, sizeof (ch), 1) != 1, NULL, -1); word = ((word << 8) & 0xFFFFFF00) | ch; - if (SDL_SwapLE32(word) == MAGIC_NUM) + if (SDL_SwapBE32(word) == MAGIC_NUM) { BAIL_IF_MACRO(SDL_RWread(rw, &ch, sizeof (ch), 1) != 1, NULL, -1); return((int) ch); @@ -127,7 +360,7 @@ /* look for the magic number in the RWops and see what kind of file this is. */ -static inline int determine_shn_version(Sound_Sample *sample) +static inline int determine_shn_version(Sound_Sample *sample, const char *ext) { SDL_RWops *rw = ((Sound_SampleInternal *) sample->opaque)->rw; Uint32 magic; @@ -142,7 +375,7 @@ */ if (__Sound_strcasecmp(ext, "shn") == 0) - return(extended_shn_magic_search(sample); + return(extended_shn_magic_search(sample)); BAIL_IF_MACRO(SDL_RWread(rw, &magic, sizeof (magic), 1) != 1, NULL, -1); BAIL_IF_MACRO(SDL_SwapLE32(magic) != MAGIC_NUM, "SHN: Not a SHN file", -1); @@ -153,59 +386,903 @@ } /* determine_shn_version */ +static int init_shn_offset(Sint32 **offset, int nchan, int nblock, int ftype) +{ + Sint32 mean = 0; + int chan; + + switch (ftype) + { + case SHN_TYPE_AU1: + case SHN_TYPE_S8: + case SHN_TYPE_S16HL: + case SHN_TYPE_S16LH: + case SHN_TYPE_ULAW: + case SHN_TYPE_AU2: + case SHN_TYPE_AU3: + case SHN_TYPE_ALAW: + mean = 0; + break; + case SHN_TYPE_U8: + mean = 0x80; + break; + case SHN_TYPE_U16HL: + case SHN_TYPE_U16LH: + mean = 0x8000; + break; + default: + BAIL_MACRO("SHN: unknown file type", 0); + } /* switch */ + + for(chan = 0; chan < nchan; chan++) + { + int i; + for(i = 0; i < nblock; i++) + offset[chan][i] = mean; + } /* for */ +} /* init_shn_offset */ + + +static inline Uint16 cvt_shnftype_to_sdlfmt(Sint16 shntype) +{ + switch (shntype) + { + case SHN_TYPE_S8: + return(AUDIO_S8); + + case SHN_TYPE_ALAW: + case SHN_TYPE_ULAW: + case SHN_TYPE_AU1: + case SHN_TYPE_AU2: + case SHN_TYPE_AU3: + case SHN_TYPE_U8: + return(AUDIO_U8); + + case SHN_TYPE_S16HL: + return(AUDIO_S16MSB); + + case SHN_TYPE_S16LH: + return(AUDIO_S16LSB); + + case SHN_TYPE_U16HL: + return(AUDIO_U16MSB); + + case SHN_TYPE_U16LH: + return(AUDIO_U16LSB); + } /* switch */ + + return(0); +} /* cvt_shnftype_to_sdlfmt */ + + +static inline int skip_bits(shn_t *shn, SDL_RWops *rw) +{ + int i; + Sint32 skip; + Sint32 trash; + + BAIL_IF_MACRO(!uint_get(SHN_NSKIPSIZE, shn, rw, &skip), NULL, 0); + for(i = 0; i < skip; i++) + { + BAIL_IF_MACRO(!uint_get(SHN_XBYTESIZE, shn, rw, &trash), NULL, 0); + } /* for */ + + return(1); +} /* skip_bits */ + + +static Sint32 **shn_long2d(Uint32 n0, Uint32 n1) +{ + Sint32 **array0; + Uint32 size = (n0 * sizeof (Sint32 *)) + (n0 * n1 * sizeof (Sint32)); + + array0 = (Sint32 **) malloc(size); + if (array0 != NULL) + { + int i; + Sint32 *array1 = (Sint32 *) (array0 + n0); + for(i = 0; i < n0; i++) + array0[i] = array1 + (i * n1); + } /* if */ + + return(array0); +} /* shn_long2d */ + +#define riffID 0x46464952 /* "RIFF", in ascii. */ +#define waveID 0x45564157 /* "WAVE", in ascii. */ +#define fmtID 0x20746D66 /* "fmt ", in ascii. */ +#define dataID 0x61746164 /* "data", in ascii. */ + +static int verb_ReadLE32(shn_t *shn, SDL_RWops *rw, Uint32 *word) +{ + int i; + Uint8 chars[4]; + Sint32 byte; + + for (i = 0; i < 4; i++) + { + if (!uvar_get(SHN_VERBATIM_BYTE_SIZE, shn, rw, &byte)) + return(0); + chars[i] = (Uint8) byte; + } /* for */ + + memcpy(word, chars, sizeof (*word)); + *word = SDL_SwapLE32(*word); + + return(1); +} /* verb_ReadLE32 */ + + +static int verb_ReadLE16(shn_t *shn, SDL_RWops *rw, Uint16 *word) +{ + int i; + Uint8 chars[2]; + Sint32 byte; + + for (i = 0; i < 2; i++) + { + if (!uvar_get(SHN_VERBATIM_BYTE_SIZE, shn, rw, &byte)) + return(0); + chars[i] = (Uint8) byte; + } /* for */ + + memcpy(word, chars, sizeof (*word)); + *word = SDL_SwapLE16(*word); + + return(1); +} /* verb_ReadLE16 */ + + +static inline int parse_riff_header(shn_t *shn, Sound_Sample *sample) +{ + Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; + SDL_RWops *rw = internal->rw; + Uint16 u16; + Uint32 u32; + Sint32 cklen; + + BAIL_IF_MACRO(!uvar_get(SHN_VERBATIM_CKSIZE_SIZE, shn, rw, &cklen), NULL, 0); + + BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* RIFF header */ + BAIL_IF_MACRO(u32 != riffID, "SHN: No RIFF header.", 0); + BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* length */ + + BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* WAVE header */ + BAIL_IF_MACRO(u32 != waveID, "SHN: No WAVE header.", 0); + + BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* 'fmt ' header */ + BAIL_IF_MACRO(u32 != fmtID, "SHN: No 'fmt ' header.", 0); + + BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* chunksize */ + BAIL_IF_MACRO(!verb_ReadLE16(shn, rw, &u16), NULL, 0); /* format */ + BAIL_IF_MACRO(!verb_ReadLE16(shn, rw, &u16), NULL, 0); /* channels */ + sample->actual.channels = u16; + BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* sample rate */ + sample->actual.rate = u32; + + BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* bytespersec */ + BAIL_IF_MACRO(!verb_ReadLE16(shn, rw, &u16), NULL, 0); /* blockalign */ + BAIL_IF_MACRO(!verb_ReadLE16(shn, rw, &u16), NULL, 0); /* bitspersample */ + + BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* 'data' header */ + BAIL_IF_MACRO(u32 != dataID, "SHN: No 'data' header.", 0); + BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* chunksize */ + + return(1); +} /* parse_riff_header */ + + static int SHN_open(Sound_Sample *sample, const char *ext) { Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; SDL_RWops *rw = internal->rw; - int shn_version = determine_shn_version(sample, ext); - int mean = MEAN_VERSION2; + shn_t _shn; + shn_t *shn = &_shn; /* malloc and copy later. */ + Sint32 cmd; + Sint32 chan; + + memset(shn, '\0', sizeof (shn_t)); + shn->getbufp = shn->getbuf = (Uint8 *) malloc(SHN_BUFSIZ); + shn->datatype = SHN_TYPE_EOF; + shn->nchan = DEFAULT_NCHAN; + shn->blocksize = DEFAULT_BLOCK_SIZE; + shn->maxnlpc = DEFAULT_MAXNLPC; + shn->nmean = UNDEFINED_UINT; + shn->version = determine_shn_version(sample, ext); + + if (shn->version == -1) goto shn_open_puke; + if (!uint_get(SHN_TYPESIZE, shn, rw, &shn->datatype)) goto shn_open_puke; + if (!uint_get(SHN_CHANNELSIZE, shn, rw, &shn->nchan)) goto shn_open_puke; + + sample->actual.format = cvt_shnftype_to_sdlfmt(shn->datatype); + if (sample->actual.format == 0) + { + SDL_SetError(ERR_UNSUPPORTED_FORMAT); + goto shn_open_puke; + } /* if */ + + if (shn->version > 0) + { + int rc = uint_get((int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2), + shn, rw, &shn->blocksize); + if (!rc) goto shn_open_puke;; + if (!uint_get(SHN_LPCQSIZE, shn, rw, &shn->maxnlpc)) goto shn_open_puke; + if (!uint_get(0, shn, rw, &shn->nmean)) goto shn_open_puke; + if (!skip_bits(shn, rw)) goto shn_open_puke; + } /* else */ + + shn->nwrap = (shn->maxnlpc > 3) ? shn->maxnlpc : 3; + + /* grab some space for the input buffer */ + shn->buffer = shn_long2d((Uint32) shn->nchan, shn->blocksize + shn->nwrap); + shn->offset = shn_long2d((Uint32) shn->nchan, MAX_MACRO(1, shn->nmean)); + + for (chan = 0; chan < shn->nchan; chan++) + { + int i; + for(i = 0; i < shn->nwrap; i++) + shn->buffer[chan][i] = 0; + shn->buffer[chan] += shn->nwrap; + } /* for */ - BAIL_IF_MACRO(shn_version == -1, NULL, 0); - if (shn_version < 2) /* downgrade? */ - mean = MEAN_VERSION0; + if (shn->maxnlpc > 0) + { + shn->qlpc = (int *) malloc((Uint32) (shn->maxnlpc * sizeof (Sint32))); + if (shn->qlpc == NULL) + { + Sound_SetError(ERR_OUT_OF_MEMORY); + goto shn_open_puke; + } /* if */ + } /* if */ + + if (shn->version > 1) + shn->lpcqoffset = SHN_LPCQOFFSET_VER2; + + init_shn_offset(shn->offset, shn->nchan, + MAX_MACRO(1, shn->nmean), shn->datatype); + + if ( (!uvar_get(SHN_FNSIZE, shn, rw, &cmd)) || + (cmd != SHN_FN_VERBATIM) || + (!parse_riff_header(shn, sample)) ) + { + if (cmd != SHN_FN_VERBATIM) + Sound_SetError("SHN: Expected VERBATIM function"); + + goto shn_open_puke; + return(0); + } /* if */ + + shn = (shn_t *) malloc(sizeof (shn_t)); + if (shn == NULL) + { + Sound_SetError(ERR_OUT_OF_MEMORY); + goto shn_open_puke; + } /* if */ + + memcpy(shn, &_shn, sizeof (shn_t)); + internal->decoder_private = shn; + + SNDDBG(("SHN: Accepting data stream.\n")); + sample->flags = SOUND_SAMPLEFLAG_NONE; + return(1); /* we'll handle this data. */ + +shn_open_puke: + if (_shn.getbuf) + free(_shn.getbuf); + if (_shn.buffer != NULL) + free(_shn.buffer); + if (_shn.offset != NULL) + free(_shn.offset); + if (_shn.qlpc != NULL) + free(_shn.qlpc); + + return(0); +} /* SHN_open */ +void fix_bitshift(Sint32 *buffer, int nitem, int bitshift, int ftype) +{ + int i; - SNDDBG(("SHN: Accepting data stream.\n")); - set up sample->actual; - sample->flags = SOUND_SAMPLEFLAG_NONE; - return(1); /* we'll handle this data. */ -} /* SHN_open */ + if (ftype == SHN_TYPE_AU1) + { + for (i = 0; i < nitem; i++) + buffer[i] = ulaw_outward[bitshift][buffer[i] + 128]; + } /* if */ + else if (ftype == SHN_TYPE_AU2) + { + for(i = 0; i < nitem; i++) + { + if (buffer[i] >= 0) + buffer[i] = ulaw_outward[bitshift][buffer[i] + 128]; + else if (buffer[i] == -1) + buffer[i] = NEGATIVE_ULAW_ZERO; + else + buffer[i] = ulaw_outward[bitshift][buffer[i] + 129]; + } /* for */ + } /* else if */ + else + { + if (bitshift != 0) + { + for(i = 0; i < nitem; i++) + buffer[i] <<= bitshift; + } /* if */ + } /* else */ +} /* fix_bitshift */ static void SHN_close(Sound_Sample *sample) { Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; - clean up anything you put into internal->decoder_private; + shn_t *shn = (shn_t *) internal->decoder_private; + + if (shn->qlpc != NULL) + free(shn->qlpc); + + if (shn->backBuffer != NULL) + free(shn->backBuffer); + + if (shn->offset != NULL) + free(shn->offset); + + if (shn->buffer != NULL) + free(shn->buffer); + + if (shn->getbuf != NULL) + free(shn->getbuf); + + free(shn); } /* SHN_close */ +/* xLaw conversions... */ + +/* adapted by ajr for int input */ +static Uint8 Slinear2ulaw(int sample) +{ +/* +** This routine converts from linear to ulaw. +** +** Craig Reese: IDA/Supercomputing Research Center +** Joe Campbell: Department of Defense +** 29 September 1989 +** +** References: +** 1) CCITT Recommendation G.711 (very difficult to follow) +** 2) "A New Digital Technique for Implementation of Any +** Continuous PCM Companding Law," Villeret, Michel, +** et al. 1973 IEEE Int. Conf. on Communications, Vol 1, +** 1973, pg. 11.12-11.17 +** 3) MIL-STD-188-113,"Interoperability and Performance Standards +** for Analog-to_Digital Conversion Techniques," +** 17 February 1987 +** +** Input: Signed 16 bit linear sample +** Output: 8 bit ulaw sample +*/ + +#define BIAS 0x84 /* define the add-in bias for 16 bit samples */ +#define CLIP 32635 + + int sign, exponent, mantissa; + Uint8 ulawbyte; + static const int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 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, + 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, + 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}; + + /* Get the sample into sign-magnitude. */ + if (sample >= 0) + sign = 0; + else + { + sign = 0x80; + sample = -sample; + } /* else */ + + /* clip the magnitude */ + if (sample > CLIP) + sample = CLIP; + + /* Convert from 16 bit linear to ulaw. */ + sample = sample + BIAS; + exponent = exp_lut[( sample >> 7 ) & 0xFF]; + mantissa = (sample >> (exponent + 3)) & 0x0F; + ulawbyte = ~(sign | (exponent << 4) | mantissa); + + return(ulawbyte); +} /* Slinear2ulaw */ + + +/* this is derived from the Sun code - it is a bit simpler and has int input */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ + + +static Uint8 Slinear2alaw(Sint32 linear) +{ + int seg; + Uint8 aval, mask; + static const Sint32 seg_aend[NSEGS] = + { + 0x1f,0x3f,0x7f,0xff,0x1ff,0x3ff,0x7ff,0xfff + }; + + linear >>= 3; + if(linear >= 0) + mask = 0xd5; /* sign (7th) bit = 1 */ + else + { + mask = 0x55; /* sign bit = 0 */ + linear = -linear - 1; + } /* else */ + + /* Convert the scaled magnitude to segment number. */ + for (seg = 0; (seg < NSEGS) && (linear > seg_aend[seg]); seg++); + + /* Combine the sign, segment, and quantization bits. */ + if (seg >= NSEGS) /* out of range, return maximum value. */ + return((Uint8) (0x7F ^ mask)); + + aval = (Uint8) seg << SEG_SHIFT; + if (seg < 2) + aval |= (linear >> 1) & QUANT_MASK; + else + aval |= (linear >> seg) & QUANT_MASK; + + return (aval ^ mask); +} /* Slinear2alaw */ + + +/* convert from signed ints to a given type and write */ +static Uint32 put_to_buffers(Sound_Sample *sample, Uint32 bw) +{ + Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; + shn_t *shn = (shn_t *) internal->decoder_private; + int i, chan; + Sint32 *data0 = shn->buffer[0]; + Sint32 nitem = shn->blocksize; + int datasize = ((sample->actual.format & 0xFF) / 8); + Uint32 bsiz = shn->nchan * nitem * datasize; + + assert(shn->backBufLeft == 0); + + if (shn->backBufferSize < bsiz) + { + void *rc = realloc(shn->backBuffer, bsiz); + if (rc == NULL) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + BAIL_MACRO(ERR_OUT_OF_MEMORY, 0); + } /* if */ + shn->backBuffer = (Uint8 *) rc; + shn->backBufferSize = bsiz; + } /* if */ + + switch (shn->datatype) + { + case SHN_TYPE_AU1: /* leave the conversion to fix_bitshift() */ + case SHN_TYPE_AU2: + { + Uint8 *writebufp = shn->backBuffer; + if (shn->nchan == 1) + { + for (i = 0; i < nitem; i++) + *writebufp++ = data0[i]; + } /* if */ + else + { + for (i = 0; i < nitem; i++) + { + for (chan = 0; chan < shn->nchan; chan++) + *writebufp++ = shn->buffer[chan][i]; + } /* for */ + } /* else */ + } /* case */ + break; + + case SHN_TYPE_U8: + { + Uint8 *writebufp = shn->backBuffer; + if (shn->nchan == 1) + { + for (i = 0; i < nitem; i++) + *writebufp++ = CAPMAXUCHAR(data0[i]); + } /* if */ + else + { + for (i = 0; i < nitem; i++) + { + for (chan = 0; chan < shn->nchan; chan++) + *writebufp++ = CAPMAXUCHAR(shn->buffer[chan][i]); + } /* for */ + } /* else */ + } /* case */ + break; + + case SHN_TYPE_S8: + { + Sint8 *writebufp = (Sint8 *) shn->backBuffer; + if (shn->nchan == 1) + { + for(i = 0; i < nitem; i++) + *writebufp++ = CAPMAXSCHAR(data0[i]); + } /* if */ + else + { + for(i = 0; i < nitem; i++) + { + for(chan = 0; chan < shn->nchan; chan++) + *writebufp++ = CAPMAXSCHAR(shn->buffer[chan][i]); + } /* for */ + } /* else */ + } /* case */ + break; + + case SHN_TYPE_S16HL: + case SHN_TYPE_S16LH: + { + Sint16 *writebufp = (Sint16 *) shn->backBuffer; + if (shn->nchan == 1) + { + for (i = 0; i < nitem; i++) + *writebufp++ = CAPMAXSHORT(data0[i]); + } /* if */ + else + { + for (i = 0; i < nitem; i++) + { + for (chan = 0; chan < shn->nchan; chan++) + *writebufp++ = CAPMAXSHORT(shn->buffer[chan][i]); + } /* for */ + } /* else */ + } /* case */ + break; + + case SHN_TYPE_U16HL: + case SHN_TYPE_U16LH: + { + Uint16 *writebufp = (Uint16 *) shn->backBuffer; + if (shn->nchan == 1) + { + for (i = 0; i < nitem; i++) + *writebufp++ = CAPMAXUSHORT(data0[i]); + } /* if */ + else + { + for (i = 0; i < nitem; i++) + { + for (chan = 0; chan < shn->nchan; chan++) + *writebufp++ = CAPMAXUSHORT(shn->buffer[chan][i]); + } /* for */ + } /* else */ + } /* case */ + break; + + case SHN_TYPE_ULAW: + { + Uint8 *writebufp = shn->backBuffer; + if (shn->nchan == 1) + { + for(i = 0; i < nitem; i++) + *writebufp++ = Slinear2ulaw(CAPMAXSHORT((data0[i] << 3))); + } /* if */ + else + { + for(i = 0; i < nitem; i++) + { + for(chan = 0; chan < shn->nchan; chan++) + *writebufp++ = Slinear2ulaw(CAPMAXSHORT((shn->buffer[chan][i] << 3))); + } /* for */ + } /* else */ + } /* case */ + break; + + case SHN_TYPE_AU3: + { + Uint8 *writebufp = shn->backBuffer; + if (shn->nchan == 1) + { + for (i = 0; i < nitem; i++) + if(data0[i] < 0) + *writebufp++ = (127 - data0[i]) ^ 0xd5; + else + *writebufp++ = (data0[i] + 128) ^ 0x55; + } /* if */ + else + { + for (i = 0; i < nitem; i++) + { + for (chan = 0; chan < shn->nchan; chan++) + { + if (shn->buffer[chan][i] < 0) + *writebufp++ = (127 - shn->buffer[chan][i]) ^ 0xd5; + else + *writebufp++ = (shn->buffer[chan][i] + 128) ^ 0x55; + } /* for */ + } /* for */ + } /* else */ + } /* case */ + break; + + case SHN_TYPE_ALAW: + { + Uint8 *writebufp = shn->backBuffer; + if (shn->nchan == 1) + { + for (i = 0; i < nitem; i++) + *writebufp++ = Slinear2alaw(CAPMAXSHORT((data0[i] << 3))); + } /* if */ + else + { + for (i = 0; i < nitem; i++) + { + for(chan = 0; chan < shn->nchan; chan++) + *writebufp++ = Slinear2alaw(CAPMAXSHORT((shn->buffer[chan][i] << 3))); + } /* for */ + }/* else */ + } /* case */ + break; + } /* switch */ + + i = MIN_MACRO(internal->buffer_size - bw, bsiz); + memcpy(internal->buffer + bw, shn->backBuffer, i); + shn->backBufLeft = bsiz - i; + memcpy(shn->backBuffer, shn->backBuffer + i, shn->backBufLeft); + return(i); +} /* put_to_buffers */ + + +#define ROUNDEDSHIFTDOWN(x, n) (((n) == 0) ? (x) : ((x) >> ((n) - 1)) >> 1) + static Uint32 SHN_read(Sound_Sample *sample) { - Uint32 retval; + Uint32 retval = 0; + Sint32 chan = 0; + Uint32 cpyBytes = 0; Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; + SDL_RWops *rw = internal->rw; + shn_t *shn = (shn_t *) internal->decoder_private; + Sint32 cmd; + + assert(shn->backBufLeft >= 0); + + /* see if there are leftovers to copy... */ + if (shn->backBufLeft > 0) + { + retval = MIN_MACRO(shn->backBufLeft, internal->buffer_size); + memcpy(internal->buffer, shn->backBuffer, retval); + shn->backBufLeft -= retval; + memcpy(shn->backBuffer, shn->backBuffer + retval, shn->backBufLeft); + } /* if */ + + assert((shn->backBufLeft == 0) || (retval == internal->buffer_size)); + + /* get commands from file and execute them */ + while (retval < internal->buffer_size) + { + if (!uvar_get(SHN_FNSIZE, shn, rw, &cmd)) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + + if (cmd == SHN_FN_QUIT) + { + sample->flags |= SOUND_SAMPLEFLAG_EOF; + return(retval); + } /* if */ + + switch(cmd) + { + case SHN_FN_ZERO: + case SHN_FN_DIFF0: + case SHN_FN_DIFF1: + case SHN_FN_DIFF2: + case SHN_FN_DIFF3: + case SHN_FN_QLPC: + { + Sint32 i; + Sint32 coffset, *cbuffer = shn->buffer[chan]; + Sint32 resn = 0, nlpc, j; - /* - * We don't actually do any decoding, so we read the fmt data - * directly into the internal buffer... - */ - retval = SDL_RWread(internal->rw, internal->buffer, - 1, internal->buffer_size); + if (cmd != SHN_FN_ZERO) + { + if (!uvar_get(SHN_ENERGYSIZE, shn, rw, &resn)) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + + /* version 0 differed in definition of var_get */ + if (shn->version == 0) + resn--; + } /* if */ + + /* find mean offset : N.B. this code duplicated */ + if (shn->nmean == 0) + coffset = shn->offset[chan][0]; + else + { + Sint32 sum = (shn->version < 2) ? 0 : shn->nmean / 2; + for (i = 0; i < shn->nmean; i++) + sum += shn->offset[chan][i]; + + if (shn->version < 2) + coffset = sum / shn->nmean; + else + coffset = ROUNDEDSHIFTDOWN(sum / shn->nmean, shn->bitshift); + } /* else */ - (or whatever. Do some decoding here...) + switch (cmd) + { + case SHN_FN_ZERO: + for (i = 0; i < shn->blocksize; i++) + cbuffer[i] = 0; + break; + + case SHN_FN_DIFF0: + for(i = 0; i < shn->blocksize; i++) + { + if (!var_get(resn, shn, rw, &cbuffer[i])) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + cbuffer[i] += coffset; + } /* for */ + break; + + case SHN_FN_DIFF1: + for(i = 0; i < shn->blocksize; i++) + { + if (!var_get(resn, shn, rw, &cbuffer[i])) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + cbuffer[i] += cbuffer[i - 1]; + } /* for */ + break; - /* Make sure the read went smoothly... */ - if (retval == 0) - sample->flags |= SOUND_SAMPLEFLAG_EOF; + case SHN_FN_DIFF2: + for (i = 0; i < shn->blocksize; i++) + { + if (!var_get(resn, shn, rw, &cbuffer[i])) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + cbuffer[i] += (2 * cbuffer[i-1] - cbuffer[i-2]); + } /* for */ + break; + + case SHN_FN_DIFF3: + for (i = 0; i < shn->blocksize; i++) + { + if (!var_get(resn, shn, rw, &cbuffer[i])) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + cbuffer[i] += 3 * (cbuffer[i - 1] - cbuffer[i - 2]) + cbuffer[i - 3]; + } /* for */ + break; + + case SHN_FN_QLPC: + if (!uvar_get(SHN_LPCQSIZE, shn, rw, &nlpc)) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + + for(i = 0; i < nlpc; i++) + { + if (!var_get(SHN_LPCQUANT, shn, rw, &shn->qlpc[i])) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + } /* for */ + + for(i = 0; i < nlpc; i++) + cbuffer[i - nlpc] -= coffset; + + for(i = 0; i < shn->blocksize; i++) + { + Sint32 sum = shn->lpcqoffset; + + for(j = 0; j < nlpc; j++) + sum += shn->qlpc[j] * cbuffer[i - j - 1]; + + if (!var_get(resn, shn, rw, &cbuffer[i])) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + cbuffer[i] += (sum >> SHN_LPCQUANT); + } /* for */ - else if (retval == -1) - sample->flags |= SOUND_SAMPLEFLAG_ERROR; + if (coffset != 0) + { + for(i = 0; i < shn->blocksize; i++) + cbuffer[i] += coffset; + } /* if */ + + break; + } /* switch */ + + /* store mean value if appropriate : N.B. Duplicated code */ + if (shn->nmean > 0) + { + Sint32 sum = (shn->version < 2) ? 0 : shn->blocksize / 2; + for (i = 0; i < shn->blocksize; i++) + sum += cbuffer[i]; + + for(i = 1; i < shn->nmean; i++) + shn->offset[chan][i - 1] = shn->offset[chan][i]; + + if (shn->version < 2) + shn->offset[chan][shn->nmean - 1] = sum / shn->blocksize; + else + shn->offset[chan][shn->nmean - 1] = (sum / shn->blocksize) << shn->bitshift; + } /* if */ + + /* do the wrap */ + for(i = -shn->nwrap; i < 0; i++) + cbuffer[i] = cbuffer[i + shn->blocksize]; + + fix_bitshift(cbuffer, shn->blocksize, shn->bitshift, shn->datatype); - /* (next call this EAGAIN may turn into an EOF or error.) */ - else if (retval < internal->buffer_size) - sample->flags |= SOUND_SAMPLEFLAG_EAGAIN; + if (chan == shn->nchan - 1) + { + retval += put_to_buffers(sample, retval); + if (sample->flags & SOUND_SAMPLEFLAG_ERROR) + return(retval); + } /* if */ + + chan = (chan + 1) % shn->nchan; + break; + } /* case */ - (or whatever. retval == number of bytes you put in internal->buffer). + case SHN_FN_BLOCKSIZE: + if (!uint_get((int) (log((double) shn->blocksize) / M_LN2), + shn, rw, &shn->blocksize)) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + break; + + case SHN_FN_BITSHIFT: + if (!uvar_get(SHN_BITSHIFTSIZE, shn, rw, &shn->bitshift)) + { + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* if */ + break; + + case SHN_FN_VERBATIM: + default: + Sound_SetError("SHN: Unhandled function."); + sample->flags |= SOUND_SAMPLEFLAG_ERROR; + return(retval); + } /* switch */ + } /* while */ return(retval); } /* SHN_read */