1 /* libSoX xa.c Support for Maxis .XA file format
3 * Copyright (C) 2006 Dwayne C. Litzenberger <dlitz@dlitz.net>
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.
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.
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
20 /* Thanks to Valery V. Anisimovsky <samael@avn.mccme.ru> for the
21 * "Maxis XA Audio File Format Description", dated 5-01-2002. */
29 #define HNIBBLE(byte) (((byte) >> 4) & 0xf)
30 #define LNIBBLE(byte) ((byte) & 0xf)
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) */
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 */
47 int32_t curSample
; /* current sample */
48 int32_t prevSample
; /* previous sample */
54 /* Private data for .xa file */
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 */
64 /* coefficients for EA ADPCM */
65 static const int32_t EA_ADPCM_Table
[]= {
73 /* Clip sample to 16 bits */
74 static inline int32_t clip16(int32_t sample
)
78 } else if (sample
< -32768) {
85 static int startread(sox_format_t
* ft
)
87 priv_t
* xa
= (priv_t
*) ft
->priv
;
88 char *magic
= xa
->header
.magic
;
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))
96 lsx_fail_errno(ft
, SOX_EHDR
, "XA: Header not found");
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
;
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
);
125 /* Populate the sox_soundstream structure */
126 ft
->encoding
.encoding
= SOX_ENCODING_SIGN2
;
128 if (!ft
->encoding
.bits_per_sample
|| ft
->encoding
.bits_per_sample
== xa
->header
.bits
) {
129 ft
->encoding
.bits_per_sample
= xa
->header
.bits
;
131 lsx_report("User options overriding size read in .xa header");
134 if (ft
->signal
.channels
== 0 || ft
->signal
.channels
== xa
->header
.channels
) {
135 ft
->signal
.channels
= xa
->header
.channels
;
137 lsx_report("User options overriding channels read in .xa header");
140 if (ft
->signal
.rate
== 0 || ft
->signal
.rate
== xa
->header
.sampleRate
) {
141 ft
->signal
.rate
= xa
->header
.sampleRate
;
143 lsx_report("User options overriding rate read in .xa header");
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
);
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
);
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
;
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
;
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
;
176 /* Set up the block buffer */
177 xa
->blockSize
= ft
->signal
.channels
* 0xf;
178 xa
->bufPos
= xa
->blockSize
;
180 /* Allocate memory for the block buffer */
181 xa
->buf
= lsx_calloc(1, (size_t)xa
->blockSize
);
183 /* Allocate memory for the state */
184 xa
->state
= lsx_calloc(sizeof(xa_state_t
), ft
->signal
.channels
);
186 /* Final initialization */
187 xa
->bytesDecoded
= 0;
193 * Read up to len samples from a file, converted to signed longs.
194 * Return the number of samples read.
196 static size_t read_samples(sox_format_t
* ft
, sox_sample_t
*buf
, size_t len
)
198 priv_t
* xa
= (priv_t
*) ft
->priv
;
200 unsigned char inByte
;
201 size_t i
, done
, bytes
;
203 ft
->sox_errno
= SOX_SUCCESS
;
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
) {
214 lsx_fail_errno(ft
,SOX_EOF
,"Premature EOF on .xa input file");
218 lsx_fail_errno(ft
,SOX_EOF
,"read error on input stream");
224 for (i
= 0; i
< ft
->signal
.channels
; 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;
230 xa
->bufPos
+= ft
->signal
.channels
;
232 /* Process the block */
233 for (i
= 0; i
< ft
->signal
.channels
&& done
< len
; i
++) {
235 sample
= HNIBBLE(xa
->buf
[xa
->bufPos
+i
]);
236 sample
= (sample
<< 28) >> xa
->state
[i
].shift
;
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
;
244 buf
[done
++] = SOX_SIGNED_16BIT_TO_SAMPLE(sample
,);
245 xa
->bytesDecoded
+= (ft
->encoding
.bits_per_sample
>> 3);
247 for (i
= 0; i
< ft
->signal
.channels
&& done
< len
; i
++) {
249 sample
= LNIBBLE(xa
->buf
[xa
->bufPos
+i
]);
250 sample
= (sample
<< 28) >> xa
->state
[i
].shift
;
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
;
258 buf
[done
++] = SOX_SIGNED_16BIT_TO_SAMPLE(sample
,);
259 xa
->bytesDecoded
+= (ft
->encoding
.bits_per_sample
>> 3);
262 xa
->bufPos
+= ft
->signal
.channels
;
271 static int stopread(sox_format_t
* ft
)
273 priv_t
* xa
= (priv_t
*) ft
->priv
;
275 ft
->sox_errno
= SOX_SUCCESS
;
286 LSX_FORMAT_HANDLER(xa
)
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
,
294 NULL
, NULL
, NULL
, sizeof(priv_t
)