ffmpeg / libavcodec / adx.c @ 5509bffa
History | View | Annotate | Download (9.49 KB)
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 |
/* 18 bytes <-> 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 |
av_log(avctx, AV_LOG_DEBUG, "adx encode init\n");
|
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 |
uint8_t *frame, int buf_size, 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 |
#if 0
|
318 |
static void dump(unsigned char *buf,size_t len)
|
319 |
{
|
320 |
int i;
|
321 |
for(i=0;i<len;i++) {
|
322 |
if ((i&15)==0) av_log(NULL, AV_LOG_DEBUG, "%04x ",i);
|
323 |
av_log(NULL, AV_LOG_DEBUG, "%02x ",buf[i]);
|
324 |
if ((i&15)==15) av_log(NULL, AV_LOG_DEBUG, "\n");
|
325 |
}
|
326 |
av_log(NULL, AV_LOG_ERROR, "\n");
|
327 |
}
|
328 |
#endif
|
329 |
|
330 |
static int adx_decode_frame(AVCodecContext *avctx, |
331 |
void *data, int *data_size, |
332 |
uint8_t *buf0, int buf_size)
|
333 |
{ |
334 |
ADXContext *c = avctx->priv_data; |
335 |
short *samples = data;
|
336 |
const uint8_t *buf = buf0;
|
337 |
int rest = buf_size;
|
338 |
|
339 |
if (!c->header_parsed) {
|
340 |
int hdrsize = adx_decode_header(avctx,buf,rest);
|
341 |
if (hdrsize==0) return -1; |
342 |
c->header_parsed = 1;
|
343 |
buf += hdrsize; |
344 |
rest -= hdrsize; |
345 |
} |
346 |
|
347 |
if (c->in_temp) {
|
348 |
int copysize = 18*avctx->channels - c->in_temp; |
349 |
memcpy(c->dec_temp+c->in_temp,buf,copysize); |
350 |
rest -= copysize; |
351 |
buf += copysize; |
352 |
if (avctx->channels==1) { |
353 |
adx_decode(samples,c->dec_temp,c->prev); |
354 |
samples += 32;
|
355 |
} else {
|
356 |
adx_decode_stereo(samples,c->dec_temp,c->prev); |
357 |
samples += 32*2; |
358 |
} |
359 |
} |
360 |
//
|
361 |
if (avctx->channels==1) { |
362 |
while(rest>=18) { |
363 |
adx_decode(samples,buf,c->prev); |
364 |
rest-=18;
|
365 |
buf+=18;
|
366 |
samples+=32;
|
367 |
} |
368 |
} else {
|
369 |
while(rest>=18*2) { |
370 |
adx_decode_stereo(samples,buf,c->prev); |
371 |
rest-=18*2; |
372 |
buf+=18*2; |
373 |
samples+=32*2; |
374 |
} |
375 |
} |
376 |
//
|
377 |
c->in_temp = rest; |
378 |
if (rest) {
|
379 |
memcpy(c->dec_temp,buf,rest); |
380 |
buf+=rest; |
381 |
} |
382 |
*data_size = (uint8_t*)samples - (uint8_t*)data; |
383 |
// printf("%d:%d ",buf-buf0,*data_size); fflush(stdout);
|
384 |
return buf-buf0;
|
385 |
} |
386 |
|
387 |
#ifdef CONFIG_ENCODERS
|
388 |
AVCodec adx_adpcm_encoder = { |
389 |
"adx_adpcm",
|
390 |
CODEC_TYPE_AUDIO, |
391 |
CODEC_ID_ADPCM_ADX, |
392 |
sizeof(ADXContext),
|
393 |
adx_encode_init, |
394 |
adx_encode_frame, |
395 |
adx_encode_close, |
396 |
NULL,
|
397 |
}; |
398 |
#endif //CONFIG_ENCODERS |
399 |
|
400 |
AVCodec adx_adpcm_decoder = { |
401 |
"adx_adpcm",
|
402 |
CODEC_TYPE_AUDIO, |
403 |
CODEC_ID_ADPCM_ADX, |
404 |
sizeof(ADXContext),
|
405 |
adx_decode_init, |
406 |
NULL,
|
407 |
NULL,
|
408 |
adx_decode_frame, |
409 |
}; |
410 |
|