1 /* libSoX xa.c  Support for Maxis .XA file format
2  *
3  *      Copyright (C) 2006 Dwayne C. Litzenberger <dlitz@dlitz.net>
4  *
5  * This library is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation; either version 2.1 of the License, or (at
8  * your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 /* Thanks to Valery V. Anisimovsky <samael@avn.mccme.ru> for the
21  * "Maxis XA Audio File Format Description", dated 5-01-2002. */
22 
23 #include "sox_i.h"
24 
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 
29 #define HNIBBLE(byte) (((byte) >> 4) & 0xf)
30 #define LNIBBLE(byte) ((byte) & 0xf)
31 
32 /* .xa file header */
33 typedef struct {
34     char magic[4];  /* "XA\0\0", "XAI\0" (sound/speech), or "XAJ\0" (music) */
35     uint32_t outSize;       /* decompressed size of the stream (in bytes) */
36 
37     /* WAVEFORMATEX structure for the decompressed data */
38     uint16_t tag;           /* 0x0001 - PCM data */
39     uint16_t channels;      /* number of channels */
40     uint32_t sampleRate;    /* sample rate (samples/sec) */
41     uint32_t avgByteRate;   /* sampleRate * align */
42     uint16_t align;         /* bits / 8 * channels */
43     uint16_t bits;          /* 8 or 16 */
44 } xa_header_t;
45 
46 typedef struct {
47     int32_t curSample;      /* current sample */
48     int32_t prevSample;     /* previous sample */
49     int32_t c1;
50     int32_t c2;
51     unsigned int shift;
52 } xa_state_t;
53 
54 /* Private data for .xa file */
55 typedef struct {
56     xa_header_t header;
57     xa_state_t *state;
58     unsigned int blockSize;
59     unsigned int bufPos;    /* position within the current block */
60     unsigned char *buf;     /* buffer for the current block */
61     unsigned int bytesDecoded;  /* number of decompressed bytes read */
62 } priv_t;
63 
64 /* coefficients for EA ADPCM */
65 static const int32_t EA_ADPCM_Table[]= {
66     0, 240,  460,  392,
67     0,   0, -208, -220,
68     0,   1,    3,    4,
69     7,   8,   10,   11,
70     0,  -1,   -3,   -4
71 };
72 
73 /* Clip sample to 16 bits */
clip16(int32_t sample)74 static inline int32_t clip16(int32_t sample)
75 {
76     if (sample > 32767) {
77         return 32767;
78     } else if (sample < -32768) {
79         return -32768;
80     } else {
81         return sample;
82     }
83 }
84 
startread(sox_format_t * ft)85 static int startread(sox_format_t * ft)
86 {
87     priv_t * xa = (priv_t *) ft->priv;
88     char *magic = xa->header.magic;
89 
90     /* Check for the magic value */
91     if (lsx_readbuf(ft, xa->header.magic, (size_t)4) != 4 ||
92         (memcmp("XA\0\0", xa->header.magic, (size_t)4) != 0 &&
93          memcmp("XAI\0", xa->header.magic, (size_t)4) != 0 &&
94          memcmp("XAJ\0", xa->header.magic, (size_t)4) != 0))
95     {
96         lsx_fail_errno(ft, SOX_EHDR, "XA: Header not found");
97         return SOX_EOF;
98     }
99 
100     /* Read the rest of the header */
101     if (lsx_readdw(ft, &xa->header.outSize) != SOX_SUCCESS) return SOX_EOF;
102     if (lsx_readw(ft, &xa->header.tag) != SOX_SUCCESS) return SOX_EOF;
103     if (lsx_readw(ft, &xa->header.channels) != SOX_SUCCESS) return SOX_EOF;
104     if (lsx_readdw(ft, &xa->header.sampleRate) != SOX_SUCCESS) return SOX_EOF;
105     if (lsx_readdw(ft, &xa->header.avgByteRate) != SOX_SUCCESS) return SOX_EOF;
106     if (lsx_readw(ft, &xa->header.align) != SOX_SUCCESS) return SOX_EOF;
107     if (lsx_readw(ft, &xa->header.bits) != SOX_SUCCESS) return SOX_EOF;
108 
109     /* Output the data from the header */
110     lsx_debug("XA Header:");
111     lsx_debug(" szID:          %02x %02x %02x %02x  |%c%c%c%c|",
112         magic[0], magic[1], magic[2], magic[3],
113         (magic[0] >= 0x20 && magic[0] <= 0x7e) ? magic[0] : '.',
114         (magic[1] >= 0x20 && magic[1] <= 0x7e) ? magic[1] : '.',
115         (magic[2] >= 0x20 && magic[2] <= 0x7e) ? magic[2] : '.',
116         (magic[3] >= 0x20 && magic[3] <= 0x7e) ? magic[3] : '.');
117     lsx_debug(" dwOutSize:     %u", xa->header.outSize);
118     lsx_debug(" wTag:          0x%04x", xa->header.tag);
119     lsx_debug(" wChannels:     %u", xa->header.channels);
120     lsx_debug(" dwSampleRate:  %u", xa->header.sampleRate);
121     lsx_debug(" dwAvgByteRate: %u", xa->header.avgByteRate);
122     lsx_debug(" wAlign:        %u", xa->header.align);
123     lsx_debug(" wBits:         %u", xa->header.bits);
124 
125     /* Populate the sox_soundstream structure */
126     ft->encoding.encoding = SOX_ENCODING_SIGN2;
127 
128     if (!ft->encoding.bits_per_sample || ft->encoding.bits_per_sample == xa->header.bits) {
129         ft->encoding.bits_per_sample = xa->header.bits;
130     } else {
131         lsx_report("User options overriding size read in .xa header");
132     }
133 
134     if (ft->signal.channels == 0 || ft->signal.channels == xa->header.channels) {
135         ft->signal.channels = xa->header.channels;
136     } else {
137         lsx_report("User options overriding channels read in .xa header");
138     }
139 
140     if (ft->signal.rate == 0 || ft->signal.rate == xa->header.sampleRate) {
141         ft->signal.rate = xa->header.sampleRate;
142     } else {
143         lsx_report("User options overriding rate read in .xa header");
144     }
145 
146     if (ft->signal.channels == 0 || ft->signal.channels > UINT16_MAX) {
147         lsx_fail_errno(ft, SOX_EFMT, "invalid channel count %d",
148                        ft->signal.channels);
149         return SOX_EOF;
150     }
151 
152     /* Check for supported formats */
153     if (ft->encoding.bits_per_sample != 16) {
154         lsx_fail_errno(ft, SOX_EFMT, "%d-bit sample resolution not supported.",
155             ft->encoding.bits_per_sample);
156         return SOX_EOF;
157     }
158 
159     /* Validate the header */
160     if (xa->header.bits != ft->encoding.bits_per_sample) {
161         lsx_report("Invalid sample resolution %d bits.  Assuming %d bits.",
162             xa->header.bits, ft->encoding.bits_per_sample);
163         xa->header.bits = ft->encoding.bits_per_sample;
164     }
165     if (xa->header.align != (ft->encoding.bits_per_sample >> 3) * xa->header.channels) {
166         lsx_report("Invalid sample alignment value %d.  Assuming %d.",
167             xa->header.align, (ft->encoding.bits_per_sample >> 3) * xa->header.channels);
168         xa->header.align = (ft->encoding.bits_per_sample >> 3) * xa->header.channels;
169     }
170     if (xa->header.avgByteRate != (xa->header.align * xa->header.sampleRate)) {
171         lsx_report("Invalid dwAvgByteRate value %d.  Assuming %d.",
172             xa->header.avgByteRate, xa->header.align * xa->header.sampleRate);
173         xa->header.avgByteRate = xa->header.align * xa->header.sampleRate;
174     }
175 
176     /* Set up the block buffer */
177     xa->blockSize = ft->signal.channels * 0xf;
178     xa->bufPos = xa->blockSize;
179 
180     /* Allocate memory for the block buffer */
181     xa->buf = lsx_calloc(1, (size_t)xa->blockSize);
182 
183     /* Allocate memory for the state */
184     xa->state = lsx_calloc(sizeof(xa_state_t), ft->signal.channels);
185 
186     /* Final initialization */
187     xa->bytesDecoded = 0;
188 
189     return SOX_SUCCESS;
190 }
191 
192 /*
193  * Read up to len samples from a file, converted to signed longs.
194  * Return the number of samples read.
195  */
read_samples(sox_format_t * ft,sox_sample_t * buf,size_t len)196 static size_t read_samples(sox_format_t * ft, sox_sample_t *buf, size_t len)
197 {
198     priv_t * xa = (priv_t *) ft->priv;
199     int32_t sample;
200     unsigned char inByte;
201     size_t i, done, bytes;
202 
203     ft->sox_errno = SOX_SUCCESS;
204     done = 0;
205     while (done < len) {
206         if (xa->bufPos >= xa->blockSize) {
207             /* Read the next block */
208             bytes = lsx_readbuf(ft, xa->buf, (size_t) xa->blockSize);
209             if (bytes < xa->blockSize) {
210                 if (lsx_eof(ft)) {
211                     if (done > 0) {
212                         return done;
213                     }
214                     lsx_fail_errno(ft,SOX_EOF,"Premature EOF on .xa input file");
215                     return 0;
216                 } else {
217                     /* error */
218                     lsx_fail_errno(ft,SOX_EOF,"read error on input stream");
219                     return 0;
220                 }
221             }
222             xa->bufPos = 0;
223 
224             for (i = 0; i < ft->signal.channels; i++) {
225                 inByte = xa->buf[i];
226                 xa->state[i].c1 = EA_ADPCM_Table[HNIBBLE(inByte)];
227                 xa->state[i].c2 = EA_ADPCM_Table[HNIBBLE(inByte) + 4];
228                 xa->state[i].shift = LNIBBLE(inByte) + 8;
229             }
230             xa->bufPos += ft->signal.channels;
231         } else {
232             /* Process the block */
233             for (i = 0; i < ft->signal.channels && done < len; i++) {
234                 /* high nibble */
235                 sample = HNIBBLE(xa->buf[xa->bufPos+i]);
236                 sample = (sample << 28) >> xa->state[i].shift;
237                 sample = (sample +
238                           xa->state[i].curSample * xa->state[i].c1 +
239                           xa->state[i].prevSample * xa->state[i].c2 + 0x80) >> 8;
240                 sample = clip16(sample);
241                 xa->state[i].prevSample = xa->state[i].curSample;
242                 xa->state[i].curSample = sample;
243 
244                 buf[done++] = SOX_SIGNED_16BIT_TO_SAMPLE(sample,);
245                 xa->bytesDecoded += (ft->encoding.bits_per_sample >> 3);
246             }
247             for (i = 0; i < ft->signal.channels && done < len; i++) {
248                 /* low nibble */
249                 sample = LNIBBLE(xa->buf[xa->bufPos+i]);
250                 sample = (sample << 28) >> xa->state[i].shift;
251                 sample = (sample +
252                           xa->state[i].curSample * xa->state[i].c1 +
253                           xa->state[i].prevSample * xa->state[i].c2 + 0x80) >> 8;
254                 sample = clip16(sample);
255                 xa->state[i].prevSample = xa->state[i].curSample;
256                 xa->state[i].curSample = sample;
257 
258                 buf[done++] = SOX_SIGNED_16BIT_TO_SAMPLE(sample,);
259                 xa->bytesDecoded += (ft->encoding.bits_per_sample >> 3);
260             }
261 
262             xa->bufPos += ft->signal.channels;
263         }
264     }
265     if (done == 0) {
266         return 0;
267     }
268     return done;
269 }
270 
stopread(sox_format_t * ft)271 static int stopread(sox_format_t * ft)
272 {
273     priv_t * xa = (priv_t *) ft->priv;
274 
275     ft->sox_errno = SOX_SUCCESS;
276 
277     /* Free memory */
278     free(xa->buf);
279     xa->buf = NULL;
280     free(xa->state);
281     xa->state = NULL;
282 
283     return SOX_SUCCESS;
284 }
285 
LSX_FORMAT_HANDLER(xa)286 LSX_FORMAT_HANDLER(xa)
287 {
288   static char const * const names[] = {"xa", NULL };
289   static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
290     "16-bit ADPCM audio files used by Maxis games",
291     names, SOX_FILE_LIT_END,
292     startread, read_samples, stopread,
293     NULL, NULL, NULL,
294     NULL, NULL, NULL, sizeof(priv_t)
295   };
296   return &handler;
297 }
298