Mercurial > libavcodec.hg
comparison adx.c @ 1531:a78de892cefd libavcodec
added CRI ADX and XA ADPCM audio modules, courtesy of BERO
<bero -at- geocities.co.jp>
author | melanson |
---|---|
date | Tue, 14 Oct 2003 04:40:53 +0000 |
parents | |
children | 5bdf2017d854 |
comparison
equal
deleted
inserted
replaced
1530:3b31998fe22f | 1531:a78de892cefd |
---|---|
1 /* | |
2 * ADX ADPCM codecs | |
3 * Copyright (c) 2001,2003 BERO | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 #include "avcodec.h" | |
20 | |
21 /** | |
22 * @file adx.c | |
23 * SEGA CRI adx codecs. | |
24 * | |
25 * Reference documents: | |
26 * http://ku-www.ss.titech.ac.jp/~yatsushi/adx.html | |
27 * adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/ | |
28 */ | |
29 | |
30 typedef struct { | |
31 int s1,s2; | |
32 } PREV; | |
33 | |
34 typedef struct { | |
35 PREV prev[2]; | |
36 int header_parsed; | |
37 unsigned char dec_temp[18*2]; | |
38 unsigned short enc_temp[32*2]; | |
39 int in_temp; | |
40 } ADXContext; | |
41 | |
42 //#define BASEVOL 0x11e0 | |
43 #define BASEVOL 0x4000 | |
44 #define SCALE1 0x7298 | |
45 #define SCALE2 0x3350 | |
46 | |
47 #define CLIP(s) if (s>32767) s=32767; else if (s<-32768) s=-32768 | |
48 | |
49 /* 18byte <-> 32 samples */ | |
50 | |
51 #ifdef CONFIG_ENCODERS | |
52 static void adx_encode(unsigned char *adx,const short *wav,PREV *prev) | |
53 { | |
54 int scale; | |
55 int i; | |
56 int s0,s1,s2,d; | |
57 int max=0; | |
58 int min=0; | |
59 int data[32]; | |
60 | |
61 s1 = prev->s1; | |
62 s2 = prev->s2; | |
63 for(i=0;i<32;i++) { | |
64 s0 = wav[i]; | |
65 d = ((s0<<14) - SCALE1*s1 + SCALE2*s2)/BASEVOL; | |
66 data[i]=d; | |
67 if (max<d) max=d; | |
68 if (min>d) min=d; | |
69 s2 = s1; | |
70 s1 = s0; | |
71 } | |
72 prev->s1 = s1; | |
73 prev->s2 = s2; | |
74 | |
75 /* -8..+7 */ | |
76 | |
77 if (max==0 && min==0) { | |
78 memset(adx,0,18); | |
79 return; | |
80 } | |
81 | |
82 if (max/7>-min/8) scale = max/7; | |
83 else scale = -min/8; | |
84 | |
85 if (scale==0) scale=1; | |
86 | |
87 adx[0] = scale>>8; | |
88 adx[1] = scale; | |
89 | |
90 for(i=0;i<16;i++) { | |
91 adx[i+2] = ((data[i*2]/scale)<<4) | ((data[i*2+1]/scale)&0xf); | |
92 } | |
93 } | |
94 #endif //CONFIG_ENCODERS | |
95 | |
96 static void adx_decode(short *out,const unsigned char *in,PREV *prev) | |
97 { | |
98 int scale = ((in[0]<<8)|(in[1])); | |
99 int i; | |
100 int s0,s1,s2,d; | |
101 | |
102 // printf("%x ",scale); | |
103 | |
104 in+=2; | |
105 s1 = prev->s1; | |
106 s2 = prev->s2; | |
107 for(i=0;i<16;i++) { | |
108 d = in[i]; | |
109 // d>>=4; if (d&8) d-=16; | |
110 d = ((signed char)d >> 4); | |
111 s0 = (BASEVOL*d*scale + SCALE1*s1 - SCALE2*s2)>>14; | |
112 CLIP(s0); | |
113 *out++=s0; | |
114 s2 = s1; | |
115 s1 = s0; | |
116 | |
117 d = in[i]; | |
118 //d&=15; if (d&8) d-=16; | |
119 d = ((signed char)(d<<4) >> 4); | |
120 s0 = (BASEVOL*d*scale + SCALE1*s1 - SCALE2*s2)>>14; | |
121 CLIP(s0); | |
122 *out++=s0; | |
123 s2 = s1; | |
124 s1 = s0; | |
125 } | |
126 prev->s1 = s1; | |
127 prev->s2 = s2; | |
128 | |
129 } | |
130 | |
131 static void adx_decode_stereo(short *out,const unsigned char *in,PREV *prev) | |
132 { | |
133 short tmp[32*2]; | |
134 int i; | |
135 | |
136 adx_decode(tmp ,in ,prev); | |
137 adx_decode(tmp+32,in+18,prev+1); | |
138 for(i=0;i<32;i++) { | |
139 out[i*2] = tmp[i]; | |
140 out[i*2+1] = tmp[i+32]; | |
141 } | |
142 } | |
143 | |
144 #ifdef CONFIG_ENCODERS | |
145 | |
146 static void write_long(unsigned char *p,uint32_t v) | |
147 { | |
148 p[0] = v>>24; | |
149 p[1] = v>>16; | |
150 p[2] = v>>8; | |
151 p[3] = v; | |
152 } | |
153 | |
154 static int adx_encode_header(AVCodecContext *avctx,unsigned char *buf,size_t bufsize) | |
155 { | |
156 #if 0 | |
157 struct { | |
158 uint32_t offset; /* 0x80000000 + sample start - 4 */ | |
159 unsigned char unknown1[3]; /* 03 12 04 */ | |
160 unsigned char channel; /* 1 or 2 */ | |
161 uint32_t freq; | |
162 uint32_t size; | |
163 uint32_t unknown2; /* 01 f4 03 00 */ | |
164 uint32_t unknown3; /* 00 00 00 00 */ | |
165 uint32_t unknown4; /* 00 00 00 00 */ | |
166 | |
167 /* if loop | |
168 unknown3 00 15 00 01 | |
169 unknown4 00 00 00 01 | |
170 long loop_start_sample; | |
171 long loop_start_byte; | |
172 long loop_end_sample; | |
173 long loop_end_byte; | |
174 long | |
175 */ | |
176 } adxhdr; /* big endian */ | |
177 /* offset-6 "(c)CRI" */ | |
178 #endif | |
179 write_long(buf+0x00,0x80000000|0x20); | |
180 write_long(buf+0x04,0x03120400|avctx->channels); | |
181 write_long(buf+0x08,avctx->sample_rate); | |
182 write_long(buf+0x0c,0); /* FIXME: set after */ | |
183 write_long(buf+0x10,0x01040300); | |
184 write_long(buf+0x14,0x00000000); | |
185 write_long(buf+0x18,0x00000000); | |
186 memcpy(buf+0x1c,"\0\0(c)CRI",8); | |
187 return 0x20+4; | |
188 } | |
189 | |
190 static int adx_decode_init(AVCodecContext *avctx); | |
191 static int adx_encode_init(AVCodecContext *avctx) | |
192 { | |
193 if (avctx->channels > 2) | |
194 return -1; /* only stereo or mono =) */ | |
195 avctx->frame_size = 32; | |
196 | |
197 avctx->coded_frame= avcodec_alloc_frame(); | |
198 avctx->coded_frame->key_frame= 1; | |
199 | |
200 // avctx->bit_rate = avctx->sample_rate*avctx->channels*18*8/32; | |
201 | |
202 printf("adx encode init\n"); fflush(stdout); | |
203 adx_decode_init(avctx); | |
204 | |
205 return 0; | |
206 } | |
207 | |
208 static int adx_encode_close(AVCodecContext *avctx) | |
209 { | |
210 av_freep(&avctx->coded_frame); | |
211 | |
212 return 0; | |
213 } | |
214 | |
215 static int adx_encode_frame(AVCodecContext *avctx, | |
216 unsigned char *frame, int buf_size, const void *data) | |
217 { | |
218 ADXContext *c = avctx->priv_data; | |
219 const short *samples = data; | |
220 unsigned char *dst = frame; | |
221 int rest = avctx->frame_size; | |
222 | |
223 /* | |
224 input data size = | |
225 ffmpeg.c: do_audio_out() | |
226 frame_bytes = enc->frame_size * 2 * enc->channels; | |
227 */ | |
228 | |
229 // printf("sz=%d ",buf_size); fflush(stdout); | |
230 if (!c->header_parsed) { | |
231 int hdrsize = adx_encode_header(avctx,dst,buf_size); | |
232 dst+=hdrsize; | |
233 c->header_parsed = 1; | |
234 } | |
235 | |
236 if (avctx->channels==1) { | |
237 while(rest>=32) { | |
238 adx_encode(dst,samples,c->prev); | |
239 dst+=18; | |
240 samples+=32; | |
241 rest-=32; | |
242 } | |
243 } else { | |
244 while(rest>=32*2) { | |
245 short tmpbuf[32*2]; | |
246 int i; | |
247 | |
248 for(i=0;i<32;i++) { | |
249 tmpbuf[i] = samples[i*2]; | |
250 tmpbuf[i+32] = samples[i*2+1]; | |
251 } | |
252 | |
253 adx_encode(dst,tmpbuf,c->prev); | |
254 adx_encode(dst+18,tmpbuf+32,c->prev+1); | |
255 dst+=18*2; | |
256 samples+=32*2; | |
257 rest-=32*2; | |
258 } | |
259 } | |
260 return dst-frame; | |
261 } | |
262 | |
263 #endif //CONFIG_ENCODERS | |
264 | |
265 static uint32_t read_long(const unsigned char *p) | |
266 { | |
267 return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; | |
268 } | |
269 | |
270 int is_adx(const unsigned char *buf,size_t bufsize) | |
271 { | |
272 int offset; | |
273 | |
274 if (buf[0]!=0x80) return 0; | |
275 offset = (read_long(buf)^0x80000000)+4; | |
276 if (bufsize<offset || memcmp(buf+offset-6,"(c)CRI",6)) return 0; | |
277 return offset; | |
278 } | |
279 | |
280 /* return data offset or 6 */ | |
281 static int adx_decode_header(AVCodecContext *avctx,const unsigned char *buf,size_t bufsize) | |
282 { | |
283 int offset; | |
284 int channels,freq,size; | |
285 | |
286 offset = is_adx(buf,bufsize); | |
287 if (offset==0) return 0; | |
288 | |
289 channels = buf[7]; | |
290 freq = read_long(buf+8); | |
291 size = read_long(buf+12); | |
292 | |
293 // printf("freq=%d ch=%d\n",freq,channels); | |
294 | |
295 avctx->sample_rate = freq; | |
296 avctx->channels = channels; | |
297 avctx->bit_rate = freq*channels*18*8/32; | |
298 // avctx->frame_size = 18*channels; | |
299 | |
300 return offset; | |
301 } | |
302 | |
303 static int adx_decode_init(AVCodecContext * avctx) | |
304 { | |
305 ADXContext *c = avctx->priv_data; | |
306 | |
307 // printf("adx_decode_init\n"); fflush(stdout); | |
308 c->prev[0].s1 = 0; | |
309 c->prev[0].s2 = 0; | |
310 c->prev[1].s1 = 0; | |
311 c->prev[1].s2 = 0; | |
312 c->header_parsed = 0; | |
313 c->in_temp = 0; | |
314 return 0; | |
315 } | |
316 | |
317 static void dump(unsigned char *buf,size_t len) | |
318 { | |
319 int i; | |
320 for(i=0;i<len;i++) { | |
321 if ((i&15)==0) printf("%04x ",i); | |
322 printf("%02x ",buf[i]); | |
323 if ((i&15)==15) printf("\n"); | |
324 } | |
325 printf("\n"); | |
326 } | |
327 static int adx_decode_frame(AVCodecContext *avctx, | |
328 void *data, int *data_size, | |
329 const uint8_t *buf0, int buf_size) | |
330 { | |
331 ADXContext *c = avctx->priv_data; | |
332 short *samples = data; | |
333 const uint8_t *buf = buf0; | |
334 int rest = buf_size; | |
335 | |
336 if (!c->header_parsed) { | |
337 int hdrsize = adx_decode_header(avctx,buf,rest); | |
338 if (hdrsize==0) return -1; | |
339 c->header_parsed = 1; | |
340 buf += hdrsize; | |
341 rest -= hdrsize; | |
342 } | |
343 | |
344 if (c->in_temp) { | |
345 int copysize = 18*avctx->channels - c->in_temp; | |
346 memcpy(c->dec_temp+c->in_temp,buf,copysize); | |
347 rest -= copysize; | |
348 buf += copysize; | |
349 if (avctx->channels==1) { | |
350 adx_decode(samples,c->dec_temp,c->prev); | |
351 samples += 32; | |
352 } else { | |
353 adx_decode_stereo(samples,c->dec_temp,c->prev); | |
354 samples += 32*2; | |
355 } | |
356 } | |
357 // | |
358 if (avctx->channels==1) { | |
359 while(rest>=18) { | |
360 adx_decode(samples,buf,c->prev); | |
361 rest-=18; | |
362 buf+=18; | |
363 samples+=32; | |
364 } | |
365 } else { | |
366 while(rest>=18*2) { | |
367 adx_decode_stereo(samples,buf,c->prev); | |
368 rest-=18*2; | |
369 buf+=18*2; | |
370 samples+=32*2; | |
371 } | |
372 } | |
373 // | |
374 c->in_temp = rest; | |
375 if (rest) { | |
376 memcpy(c->dec_temp,buf,rest); | |
377 buf+=rest; | |
378 } | |
379 *data_size = (uint8_t*)samples - (uint8_t*)data; | |
380 // printf("%d:%d ",buf-buf0,*data_size); fflush(stdout); | |
381 return buf-buf0; | |
382 } | |
383 | |
384 #define DEFINE_ENCODER(id, name, context) \ | |
385 AVCodec name ## _encoder = { \ | |
386 #name, \ | |
387 CODEC_TYPE_AUDIO, \ | |
388 id, \ | |
389 sizeof(context), \ | |
390 name ## _encode_init, \ | |
391 name ## _encode_frame, \ | |
392 name ## _encode_close, \ | |
393 NULL, \ | |
394 }; | |
395 | |
396 #define DEFINE_DECODER(id, name, context) \ | |
397 AVCodec name ## _decoder = { \ | |
398 #name, \ | |
399 CODEC_TYPE_AUDIO, \ | |
400 id, \ | |
401 sizeof(context), \ | |
402 name ## _decode_init, \ | |
403 NULL, \ | |
404 NULL, \ | |
405 name ## _decode_frame, \ | |
406 }; | |
407 | |
408 #ifdef CONFIG_ENCODERS | |
409 DEFINE_ENCODER(CODEC_ID_ADPCM_ADX,adx,ADXContext) | |
410 #endif //CONFIG_ENCODERS | |
411 | |
412 DEFINE_DECODER(CODEC_ID_ADPCM_ADX,adx,ADXContext) |