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