|
|
|
@ -38,70 +38,82 @@ static av_cold int adx_decode_init(AVCodecContext *avctx) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* 18 bytes <-> 32 samples */ |
|
|
|
|
|
|
|
|
|
static void adx_decode(int16_t *out,const unsigned char *in, |
|
|
|
|
ADXChannelState *prev) |
|
|
|
|
/**
|
|
|
|
|
* Decode 32 samples from 18 bytes. |
|
|
|
|
* |
|
|
|
|
* A 16-bit scalar value is applied to 32 residuals, which then have a |
|
|
|
|
* 2nd-order LPC filter applied to it to form the output signal for a single |
|
|
|
|
* channel. |
|
|
|
|
*/ |
|
|
|
|
static void adx_decode(int16_t *out, const uint8_t *in, ADXChannelState *prev) |
|
|
|
|
{ |
|
|
|
|
int scale = AV_RB16(in); |
|
|
|
|
int i; |
|
|
|
|
int s0,s1,s2,d; |
|
|
|
|
int s0, s1, s2, d; |
|
|
|
|
|
|
|
|
|
in+=2; |
|
|
|
|
in += 2; |
|
|
|
|
s1 = prev->s1; |
|
|
|
|
s2 = prev->s2; |
|
|
|
|
for(i=0;i<16;i++) { |
|
|
|
|
for (i = 0; i < 16; i++) { |
|
|
|
|
d = in[i]; |
|
|
|
|
d = ((signed char)d >> 4); |
|
|
|
|
s0 = (BASEVOL*d*scale + SCALE1*s1 - SCALE2*s2)>>14; |
|
|
|
|
d = (signed char)d >> 4; |
|
|
|
|
s0 = (BASEVOL * d * scale + SCALE1 * s1 - SCALE2 * s2) >> 14; |
|
|
|
|
s2 = s1; |
|
|
|
|
s1 = av_clip_int16(s0); |
|
|
|
|
*out++=s1; |
|
|
|
|
*out++ = s1; |
|
|
|
|
|
|
|
|
|
d = in[i]; |
|
|
|
|
d = ((signed char)(d<<4) >> 4); |
|
|
|
|
s0 = (BASEVOL*d*scale + SCALE1*s1 - SCALE2*s2)>>14; |
|
|
|
|
d = (signed char)(d << 4) >> 4; |
|
|
|
|
s0 = (BASEVOL * d * scale + SCALE1 * s1 - SCALE2 * s2) >> 14; |
|
|
|
|
s2 = s1; |
|
|
|
|
s1 = av_clip_int16(s0); |
|
|
|
|
*out++=s1; |
|
|
|
|
*out++ = s1; |
|
|
|
|
} |
|
|
|
|
prev->s1 = s1; |
|
|
|
|
prev->s2 = s2; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void adx_decode_stereo(int16_t *out,const unsigned char *in, |
|
|
|
|
static void adx_decode_stereo(int16_t *out,const uint8_t *in, |
|
|
|
|
ADXChannelState *prev) |
|
|
|
|
{ |
|
|
|
|
short tmp[32*2]; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
adx_decode(tmp ,in ,prev); |
|
|
|
|
adx_decode(tmp+32,in+18,prev+1); |
|
|
|
|
for(i=0;i<32;i++) { |
|
|
|
|
out[i*2] = tmp[i]; |
|
|
|
|
adx_decode(tmp, in, prev); |
|
|
|
|
adx_decode(tmp+32, in+18, prev+1); |
|
|
|
|
for (i = 0; i < 32; i++) { |
|
|
|
|
out[i*2 ] = tmp[i ]; |
|
|
|
|
out[i*2+1] = tmp[i+32]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* return data offset or 0 */ |
|
|
|
|
static int adx_decode_header(AVCodecContext *avctx,const unsigned char *buf,size_t bufsize) |
|
|
|
|
/**
|
|
|
|
|
* Decode stream header. |
|
|
|
|
* |
|
|
|
|
* @param avctx codec context |
|
|
|
|
* @param buf packet data |
|
|
|
|
* @param bufsize packet size |
|
|
|
|
* @return data offset or 0 if header is invalid |
|
|
|
|
*/ |
|
|
|
|
static int adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, |
|
|
|
|
int bufsize) |
|
|
|
|
{ |
|
|
|
|
int offset; |
|
|
|
|
|
|
|
|
|
if (buf[0]!=0x80) return 0; |
|
|
|
|
offset = (AV_RB32(buf)^0x80000000)+4; |
|
|
|
|
if (bufsize<offset || memcmp(buf+offset-6,"(c)CRI",6)) return 0; |
|
|
|
|
if (buf[0] != 0x80) |
|
|
|
|
return 0; |
|
|
|
|
offset = (AV_RB32(buf) ^ 0x80000000) + 4; |
|
|
|
|
if (bufsize < offset || memcmp(buf + offset - 6, "(c)CRI", 6)) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
avctx->channels = buf[7]; |
|
|
|
|
avctx->sample_rate = AV_RB32(buf+8); |
|
|
|
|
avctx->bit_rate = avctx->sample_rate*avctx->channels*18*8/32; |
|
|
|
|
avctx->sample_rate = AV_RB32(buf + 8); |
|
|
|
|
avctx->bit_rate = avctx->sample_rate * avctx->channels * 18 * 8 / 32; |
|
|
|
|
|
|
|
|
|
return offset; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int adx_decode_frame(AVCodecContext *avctx, |
|
|
|
|
void *data, int *data_size, |
|
|
|
|
static int adx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
|
|
|
|
AVPacket *avpkt) |
|
|
|
|
{ |
|
|
|
|
const uint8_t *buf0 = avpkt->data; |
|
|
|
@ -112,8 +124,9 @@ static int adx_decode_frame(AVCodecContext *avctx, |
|
|
|
|
int rest = buf_size; |
|
|
|
|
|
|
|
|
|
if (!c->header_parsed) { |
|
|
|
|
int hdrsize = adx_decode_header(avctx,buf,rest); |
|
|
|
|
if (hdrsize==0) return -1; |
|
|
|
|
int hdrsize = adx_decode_header(avctx, buf, rest); |
|
|
|
|
if (!hdrsize) |
|
|
|
|
return -1; |
|
|
|
|
c->header_parsed = 1; |
|
|
|
|
buf += hdrsize; |
|
|
|
|
rest -= hdrsize; |
|
|
|
@ -121,46 +134,46 @@ static int adx_decode_frame(AVCodecContext *avctx, |
|
|
|
|
|
|
|
|
|
/* 18 bytes of data are expanded into 32*2 bytes of audio,
|
|
|
|
|
so guard against buffer overflows */ |
|
|
|
|
if(rest/18 > *data_size/64) |
|
|
|
|
rest = (*data_size/64) * 18; |
|
|
|
|
if (rest / 18 > *data_size / 64) |
|
|
|
|
rest = (*data_size / 64) * 18; |
|
|
|
|
|
|
|
|
|
if (c->in_temp) { |
|
|
|
|
int copysize = 18*avctx->channels - c->in_temp; |
|
|
|
|
memcpy(c->dec_temp+c->in_temp,buf,copysize); |
|
|
|
|
int copysize = 18 * avctx->channels - c->in_temp; |
|
|
|
|
memcpy(c->dec_temp + c->in_temp, buf, copysize); |
|
|
|
|
rest -= copysize; |
|
|
|
|
buf += copysize; |
|
|
|
|
if (avctx->channels==1) { |
|
|
|
|
adx_decode(samples,c->dec_temp,c->prev); |
|
|
|
|
if (avctx->channels == 1) { |
|
|
|
|
adx_decode(samples, c->dec_temp, c->prev); |
|
|
|
|
samples += 32; |
|
|
|
|
} else { |
|
|
|
|
adx_decode_stereo(samples,c->dec_temp,c->prev); |
|
|
|
|
adx_decode_stereo(samples, c->dec_temp, c->prev); |
|
|
|
|
samples += 32*2; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (avctx->channels==1) { |
|
|
|
|
while(rest>=18) { |
|
|
|
|
adx_decode(samples,buf,c->prev); |
|
|
|
|
rest-=18; |
|
|
|
|
buf+=18; |
|
|
|
|
samples+=32; |
|
|
|
|
if (avctx->channels == 1) { |
|
|
|
|
while (rest >= 18) { |
|
|
|
|
adx_decode(samples, buf, c->prev); |
|
|
|
|
rest -= 18; |
|
|
|
|
buf += 18; |
|
|
|
|
samples += 32; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
while(rest>=18*2) { |
|
|
|
|
adx_decode_stereo(samples,buf,c->prev); |
|
|
|
|
rest-=18*2; |
|
|
|
|
buf+=18*2; |
|
|
|
|
samples+=32*2; |
|
|
|
|
while (rest >= 18 * 2) { |
|
|
|
|
adx_decode_stereo(samples, buf, c->prev); |
|
|
|
|
rest -= 18 * 2; |
|
|
|
|
buf += 18 * 2; |
|
|
|
|
samples += 32 * 2; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
c->in_temp = rest; |
|
|
|
|
if (rest) { |
|
|
|
|
memcpy(c->dec_temp,buf,rest); |
|
|
|
|
buf+=rest; |
|
|
|
|
memcpy(c->dec_temp, buf, rest); |
|
|
|
|
buf += rest; |
|
|
|
|
} |
|
|
|
|
*data_size = (uint8_t*)samples - (uint8_t*)data; |
|
|
|
|
return buf-buf0; |
|
|
|
|
return buf - buf0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
AVCodec ff_adpcm_adx_decoder = { |
|
|
|
@ -172,4 +185,3 @@ AVCodec ff_adpcm_adx_decoder = { |
|
|
|
|
.decode = adx_decode_frame, |
|
|
|
|
.long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|