Commit | Line | Data |
---|---|---|
ef79bbde P |
1 | /*************************************************************************** |
2 | * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team * | |
3 | * * | |
4 | * This program is free software; you can redistribute it and/or modify * | |
5 | * it under the terms of the GNU General Public License as published by * | |
6 | * the Free Software Foundation; either version 2 of the License, or * | |
7 | * (at your option) any later version. * | |
8 | * * | |
9 | * This program is distributed in the hope that it will be useful, * | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
12 | * GNU General Public License for more details. * | |
13 | * * | |
14 | * You should have received a copy of the GNU General Public License * | |
15 | * along with this program; if not, write to the * | |
16 | * Free Software Foundation, Inc., * | |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * | |
18 | ***************************************************************************/ | |
19 | ||
20 | /* | |
21 | * XA audio decoding functions (Kazzuya). | |
22 | */ | |
23 | ||
24 | #include "decode_xa.h" | |
25 | ||
26 | #define FIXED | |
27 | ||
28 | #define NOT(_X_) (!(_X_)) | |
29 | #define XACLAMP(_X_,_MI_,_MA_) {if(_X_<_MI_)_X_=_MI_;if(_X_>_MA_)_X_=_MA_;} | |
30 | ||
31 | #define SH 4 | |
32 | #define SHC 10 | |
33 | ||
34 | //============================================ | |
35 | //=== ADPCM DECODING ROUTINES | |
36 | //============================================ | |
37 | ||
38 | #ifndef FIXED | |
39 | static double K0[4] = { | |
40 | 0.0, | |
41 | 0.9375, | |
42 | 1.796875, | |
43 | 1.53125 | |
44 | }; | |
45 | ||
46 | static double K1[4] = { | |
47 | 0.0, | |
48 | 0.0, | |
49 | -0.8125, | |
50 | -0.859375 | |
51 | }; | |
52 | #else | |
53 | static int K0[4] = { | |
54 | 0.0 * (1<<SHC), | |
55 | 0.9375 * (1<<SHC), | |
56 | 1.796875 * (1<<SHC), | |
57 | 1.53125 * (1<<SHC) | |
58 | }; | |
59 | ||
60 | static int K1[4] = { | |
61 | 0.0 * (1<<SHC), | |
62 | 0.0 * (1<<SHC), | |
63 | -0.8125 * (1<<SHC), | |
64 | -0.859375 * (1<<SHC) | |
65 | }; | |
66 | #endif | |
67 | ||
68 | #define BLKSIZ 28 /* block size (32 - 4 nibbles) */ | |
69 | ||
70 | //=========================================== | |
71 | void ADPCM_InitDecode(ADPCM_Decode_t *decp) { | |
72 | decp->y0 = 0; | |
73 | decp->y1 = 0; | |
74 | } | |
75 | ||
76 | //=========================================== | |
77 | #ifndef FIXED | |
78 | #define IK0(fid) ((int)((-K0[fid]) * (1<<SHC))) | |
79 | #define IK1(fid) ((int)((-K1[fid]) * (1<<SHC))) | |
80 | #else | |
81 | #define IK0(fid) (-K0[fid]) | |
82 | #define IK1(fid) (-K1[fid]) | |
83 | #endif | |
84 | ||
85 | static __inline void ADPCM_DecodeBlock16( ADPCM_Decode_t *decp, u8 filter_range, const void *vblockp, short *destp, int inc ) { | |
86 | int i; | |
87 | int range, filterid; | |
88 | s32 fy0, fy1; | |
89 | const u16 *blockp; | |
90 | ||
91 | blockp = (const unsigned short *)vblockp; | |
92 | filterid = (filter_range >> 4) & 0x0f; | |
93 | range = (filter_range >> 0) & 0x0f; | |
94 | ||
95 | fy0 = decp->y0; | |
96 | fy1 = decp->y1; | |
97 | ||
98 | for (i = BLKSIZ/4; i; --i) { | |
99 | s32 y; | |
100 | s32 x0, x1, x2, x3; | |
101 | ||
102 | y = *blockp++; | |
103 | x3 = (short)( y & 0xf000) >> range; x3 <<= SH; | |
104 | x2 = (short)((y << 4) & 0xf000) >> range; x2 <<= SH; | |
105 | x1 = (short)((y << 8) & 0xf000) >> range; x1 <<= SH; | |
106 | x0 = (short)((y << 12) & 0xf000) >> range; x0 <<= SH; | |
107 | ||
108 | x0 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x0; | |
109 | x1 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x1; | |
110 | x2 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x2; | |
111 | x3 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x3; | |
112 | ||
113 | XACLAMP( x0, -32768<<SH, 32767<<SH ); *destp = x0 >> SH; destp += inc; | |
114 | XACLAMP( x1, -32768<<SH, 32767<<SH ); *destp = x1 >> SH; destp += inc; | |
115 | XACLAMP( x2, -32768<<SH, 32767<<SH ); *destp = x2 >> SH; destp += inc; | |
116 | XACLAMP( x3, -32768<<SH, 32767<<SH ); *destp = x3 >> SH; destp += inc; | |
117 | } | |
118 | decp->y0 = fy0; | |
119 | decp->y1 = fy1; | |
120 | } | |
121 | ||
122 | static int headtable[4] = {0,2,8,10}; | |
123 | ||
124 | //=========================================== | |
125 | static void xa_decode_data( xa_decode_t *xdp, unsigned char *srcp ) { | |
126 | const u8 *sound_groupsp; | |
127 | const u8 *sound_datap, *sound_datap2; | |
128 | int i, j, k, nbits; | |
129 | u16 data[4096], *datap; | |
130 | short *destp; | |
131 | ||
132 | destp = xdp->pcm; | |
133 | nbits = xdp->nbits == 4 ? 4 : 2; | |
134 | ||
135 | if (xdp->stereo) { // stereo | |
136 | if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A | |
137 | for (j=0; j < 18; j++) { | |
138 | sound_groupsp = srcp + j * 128; // sound groups header | |
139 | sound_datap = sound_groupsp + 16; // sound data just after the header | |
140 | ||
141 | for (i=0; i < nbits; i++) { | |
142 | datap = data; | |
143 | sound_datap2 = sound_datap + i; | |
144 | ||
145 | for (k=0; k < 14; k++, sound_datap2 += 8) { | |
146 | *(datap++) = (u16)sound_datap2[0] | | |
147 | (u16)(sound_datap2[4] << 8); | |
148 | } | |
149 | ||
150 | ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, | |
151 | destp+0, 2 ); | |
152 | ||
153 | datap = data; | |
154 | sound_datap2 = sound_datap + i; | |
155 | for (k=0; k < 14; k++, sound_datap2 += 8) { | |
156 | *(datap++) = (u16)sound_datap2[0] | | |
157 | (u16)(sound_datap2[4] << 8); | |
158 | } | |
159 | ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, | |
160 | destp+1, 2 ); | |
161 | ||
162 | destp += 28*2; | |
163 | } | |
164 | } | |
165 | } else { // level B/C | |
166 | for (j=0; j < 18; j++) { | |
167 | sound_groupsp = srcp + j * 128; // sound groups header | |
168 | sound_datap = sound_groupsp + 16; // sound data just after the header | |
169 | ||
170 | for (i=0; i < nbits; i++) { | |
171 | datap = data; | |
172 | sound_datap2 = sound_datap + i; | |
173 | ||
174 | for (k=0; k < 7; k++, sound_datap2 += 16) { | |
175 | *(datap++) = (u16)(sound_datap2[ 0] & 0x0f) | | |
176 | ((u16)(sound_datap2[ 4] & 0x0f) << 4) | | |
177 | ((u16)(sound_datap2[ 8] & 0x0f) << 8) | | |
178 | ((u16)(sound_datap2[12] & 0x0f) << 12); | |
179 | } | |
180 | ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, | |
181 | destp+0, 2 ); | |
182 | ||
183 | datap = data; | |
184 | sound_datap2 = sound_datap + i; | |
185 | for (k=0; k < 7; k++, sound_datap2 += 16) { | |
186 | *(datap++) = (u16)(sound_datap2[ 0] >> 4) | | |
187 | ((u16)(sound_datap2[ 4] >> 4) << 4) | | |
188 | ((u16)(sound_datap2[ 8] >> 4) << 8) | | |
189 | ((u16)(sound_datap2[12] >> 4) << 12); | |
190 | } | |
191 | ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, | |
192 | destp+1, 2 ); | |
193 | ||
194 | destp += 28*2; | |
195 | } | |
196 | } | |
197 | } | |
198 | } else { // mono | |
199 | if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A | |
200 | for (j=0; j < 18; j++) { | |
201 | sound_groupsp = srcp + j * 128; // sound groups header | |
202 | sound_datap = sound_groupsp + 16; // sound data just after the header | |
203 | ||
204 | for (i=0; i < nbits; i++) { | |
205 | datap = data; | |
206 | sound_datap2 = sound_datap + i; | |
207 | for (k=0; k < 14; k++, sound_datap2 += 8) { | |
208 | *(datap++) = (u16)sound_datap2[0] | | |
209 | (u16)(sound_datap2[4] << 8); | |
210 | } | |
211 | ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, | |
212 | destp, 1 ); | |
213 | ||
214 | destp += 28; | |
215 | ||
216 | datap = data; | |
217 | sound_datap2 = sound_datap + i; | |
218 | for (k=0; k < 14; k++, sound_datap2 += 8) { | |
219 | *(datap++) = (u16)sound_datap2[0] | | |
220 | (u16)(sound_datap2[4] << 8); | |
221 | } | |
222 | ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, | |
223 | destp, 1 ); | |
224 | ||
225 | destp += 28; | |
226 | } | |
227 | } | |
228 | } else { // level B/C | |
229 | for (j=0; j < 18; j++) { | |
230 | sound_groupsp = srcp + j * 128; // sound groups header | |
231 | sound_datap = sound_groupsp + 16; // sound data just after the header | |
232 | ||
233 | for (i=0; i < nbits; i++) { | |
234 | datap = data; | |
235 | sound_datap2 = sound_datap + i; | |
236 | for (k=0; k < 7; k++, sound_datap2 += 16) { | |
237 | *(datap++) = (u16)(sound_datap2[ 0] & 0x0f) | | |
238 | ((u16)(sound_datap2[ 4] & 0x0f) << 4) | | |
239 | ((u16)(sound_datap2[ 8] & 0x0f) << 8) | | |
240 | ((u16)(sound_datap2[12] & 0x0f) << 12); | |
241 | } | |
242 | ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, | |
243 | destp, 1 ); | |
244 | ||
245 | destp += 28; | |
246 | ||
247 | datap = data; | |
248 | sound_datap2 = sound_datap + i; | |
249 | for (k=0; k < 7; k++, sound_datap2 += 16) { | |
250 | *(datap++) = (u16)(sound_datap2[ 0] >> 4) | | |
251 | ((u16)(sound_datap2[ 4] >> 4) << 4) | | |
252 | ((u16)(sound_datap2[ 8] >> 4) << 8) | | |
253 | ((u16)(sound_datap2[12] >> 4) << 12); | |
254 | } | |
255 | ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, | |
256 | destp, 1 ); | |
257 | ||
258 | destp += 28; | |
259 | } | |
260 | } | |
261 | } | |
262 | } | |
263 | } | |
264 | ||
265 | //============================================ | |
266 | //=== XA SPECIFIC ROUTINES | |
267 | //============================================ | |
268 | typedef struct { | |
269 | u8 filenum; | |
270 | u8 channum; | |
271 | u8 submode; | |
272 | u8 coding; | |
273 | ||
274 | u8 filenum2; | |
275 | u8 channum2; | |
276 | u8 submode2; | |
277 | u8 coding2; | |
278 | } xa_subheader_t; | |
279 | ||
280 | #define SUB_SUB_EOF (1<<7) // end of file | |
281 | #define SUB_SUB_RT (1<<6) // real-time sector | |
282 | #define SUB_SUB_FORM (1<<5) // 0 form1 1 form2 | |
283 | #define SUB_SUB_TRIGGER (1<<4) // used for interrupt | |
284 | #define SUB_SUB_DATA (1<<3) // contains data | |
285 | #define SUB_SUB_AUDIO (1<<2) // contains audio | |
286 | #define SUB_SUB_VIDEO (1<<1) // contains video | |
287 | #define SUB_SUB_EOR (1<<0) // end of record | |
288 | ||
289 | #define AUDIO_CODING_GET_STEREO(_X_) ( (_X_) & 3) | |
290 | #define AUDIO_CODING_GET_FREQ(_X_) (((_X_) >> 2) & 3) | |
291 | #define AUDIO_CODING_GET_BPS(_X_) (((_X_) >> 4) & 3) | |
292 | #define AUDIO_CODING_GET_EMPHASIS(_X_) (((_X_) >> 6) & 1) | |
293 | ||
294 | #define SUB_UNKNOWN 0 | |
295 | #define SUB_VIDEO 1 | |
296 | #define SUB_AUDIO 2 | |
297 | ||
298 | //============================================ | |
299 | static int parse_xa_audio_sector( xa_decode_t *xdp, | |
300 | xa_subheader_t *subheadp, | |
301 | unsigned char *sectorp, | |
302 | int is_first_sector ) { | |
303 | if ( is_first_sector ) { | |
304 | switch ( AUDIO_CODING_GET_FREQ(subheadp->coding) ) { | |
305 | case 0: xdp->freq = 37800; break; | |
306 | case 1: xdp->freq = 18900; break; | |
307 | default: xdp->freq = 0; break; | |
308 | } | |
309 | switch ( AUDIO_CODING_GET_BPS(subheadp->coding) ) { | |
310 | case 0: xdp->nbits = 4; break; | |
311 | case 1: xdp->nbits = 8; break; | |
312 | default: xdp->nbits = 0; break; | |
313 | } | |
314 | switch ( AUDIO_CODING_GET_STEREO(subheadp->coding) ) { | |
315 | case 0: xdp->stereo = 0; break; | |
316 | case 1: xdp->stereo = 1; break; | |
317 | default: xdp->stereo = 0; break; | |
318 | } | |
319 | ||
320 | if ( xdp->freq == 0 ) | |
321 | return -1; | |
322 | ||
323 | ADPCM_InitDecode( &xdp->left ); | |
324 | ADPCM_InitDecode( &xdp->right ); | |
325 | ||
326 | xdp->nsamples = 18 * 28 * 8; | |
327 | if (xdp->stereo == 1) xdp->nsamples /= 2; | |
328 | } | |
329 | xa_decode_data( xdp, sectorp ); | |
330 | ||
331 | return 0; | |
332 | } | |
333 | ||
334 | //================================================================ | |
335 | //=== THIS IS WHAT YOU HAVE TO CALL | |
336 | //=== xdp - structure were all important data are returned | |
337 | //=== sectorp - data in input | |
338 | //=== pcmp - data in output | |
339 | //=== is_first_sector - 1 if it's the 1st sector of the stream | |
340 | //=== - 0 for any other successive sector | |
341 | //=== return -1 if error | |
342 | //================================================================ | |
343 | s32 xa_decode_sector( xa_decode_t *xdp, | |
344 | unsigned char *sectorp, int is_first_sector ) { | |
345 | if (parse_xa_audio_sector(xdp, (xa_subheader_t *)sectorp, sectorp + sizeof(xa_subheader_t), is_first_sector)) | |
346 | return -1; | |
347 | ||
348 | return 0; | |
349 | } | |
350 | ||
351 | /* EXAMPLE: | |
352 | "nsamples" is the number of 16 bit samples | |
353 | every sample is 2 bytes in mono and 4 bytes in stereo | |
354 | ||
355 | xa_decode_t xa; | |
356 | ||
357 | sectorp = read_first_sector(); | |
358 | xa_decode_sector( &xa, sectorp, 1 ); | |
359 | play_wave( xa.pcm, xa.freq, xa.nsamples ); | |
360 | ||
361 | while ( --n_sectors ) | |
362 | { | |
363 | sectorp = read_next_sector(); | |
364 | xa_decode_sector( &xa, sectorp, 0 ); | |
365 | play_wave( xa.pcm, xa.freq, xa.nsamples ); | |
366 | } | |
367 | */ |