diff options
author | Vidar Madsen <vidarino@gmail.com> | 2005-07-15 06:51:36 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2005-07-15 06:51:36 +0000 |
commit | 2ff4524e7243a628e26d34bf353beeba4f217f61 (patch) | |
tree | b53c85f0ee60afd00f31f355b29b95cafd89d0ff | |
parent | e0111b3243a759229656aebe45a5288b84fa6288 (diff) | |
download | ffmpeg-2ff4524e7243a628e26d34bf353beeba4f217f61.tar.gz |
Add Yamaha ADPCM encoding/decoding patch by (Vidar Madsen: vidarino, gmail com)
Originally committed as revision 4442 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavcodec/adpcm.c | 82 | ||||
-rw-r--r-- | libavcodec/allcodecs.c | 1 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 2 |
3 files changed, 85 insertions, 0 deletions
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 0c44121d59..67a98769db 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -117,6 +117,16 @@ static const int swf_index_tables[4][16] = { /*5*/ { -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16 } }; +static const int yamaha_indexscale[] = { + 230, 230, 230, 230, 307, 409, 512, 614, + 230, 230, 230, 230, 307, 409, 512, 614 +}; + +static const int yamaha_difflookup[] = { + 1, 3, 5, 7, 9, 11, 13, 15, + -1, -3, -5, -7, -9, -11, -13, -15 +}; + /* end of tables */ typedef struct ADPCMChannelStatus { @@ -168,6 +178,10 @@ static int adpcm_encode_init(AVCodecContext *avctx) /* and we have 7 bytes per channel overhead */ avctx->block_align = BLKSIZE; break; + case CODEC_ID_ADPCM_YAMAHA: + avctx->frame_size = BLKSIZE * avctx->channels; + avctx->block_align = BLKSIZE; + break; default: return -1; break; @@ -260,6 +274,31 @@ static inline unsigned char adpcm_ms_compress_sample(ADPCMChannelStatus *c, shor return nibble; } +static inline unsigned char adpcm_yamaha_compress_sample(ADPCMChannelStatus *c, short sample) +{ + int i1 = 0, j1; + + if(!c->step) { + c->predictor = 0; + c->step = 127; + } + j1 = sample - c->predictor; + + j1 = (j1 * 8) / c->step; + i1 = abs(j1) / 2; + if (i1 > 7) + i1 = 7; + if (j1 < 0) + i1 += 8; + + c->predictor = c->predictor + ((c->step * yamaha_difflookup[i1]) / 8); + CLAMP_TO_SHORT(c->predictor); + c->step = (c->step * yamaha_indexscale[i1]) >> 8; + c->step = clip(c->step, 127, 24567); + + return i1; +} + static int adpcm_encode_frame(AVCodecContext *avctx, unsigned char *frame, int buf_size, void *data) { @@ -362,6 +401,18 @@ static int adpcm_encode_frame(AVCodecContext *avctx, *dst++ = nibble; } break; + case CODEC_ID_ADPCM_YAMAHA: + n = avctx->frame_size / 2; + for (; n>0; n--) { + for(i = 0; i < avctx->channels; i++) { + int nibble; + nibble = adpcm_yamaha_compress_sample(&c->status[i], samples[i]) << 4; + nibble |= adpcm_yamaha_compress_sample(&c->status[i], samples[i+avctx->channels]); + *dst++ = nibble; + } + samples += 2 * avctx->channels; + } + break; default: return -1; } @@ -463,6 +514,20 @@ static inline short adpcm_ct_expand_nibble(ADPCMChannelStatus *c, char nibble) return (short)predictor; } +static inline short adpcm_yamaha_expand_nibble(ADPCMChannelStatus *c, unsigned char nibble) +{ + if(!c->step) { + c->predictor = 0; + c->step = 127; + } + + c->predictor += (c->step * yamaha_difflookup[nibble]) / 8; + CLAMP_TO_SHORT(c->predictor); + c->step = (c->step * yamaha_indexscale[nibble]) >> 8; + c->step = clip(c->step, 127, 24567); + return c->predictor; +} + static void xa_decode(short *out, const unsigned char *in, ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc) { @@ -978,6 +1043,22 @@ static int adpcm_decode_frame(AVCodecContext *avctx, break; } + case CODEC_ID_ADPCM_YAMAHA: + while (src < buf + buf_size) { + if (st) { + *samples++ = adpcm_yamaha_expand_nibble(&c->status[0], + (src[0] >> 4) & 0x0F); + *samples++ = adpcm_yamaha_expand_nibble(&c->status[1], + src[0] & 0x0F); + } else { + *samples++ = adpcm_yamaha_expand_nibble(&c->status[0], + (src[0] >> 4) & 0x0F); + *samples++ = adpcm_yamaha_expand_nibble(&c->status[0], + src[0] & 0x0F); + } + src++; + } + break; default: return -1; } @@ -1035,5 +1116,6 @@ ADPCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx); ADPCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea); ADPCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct); ADPCM_CODEC(CODEC_ID_ADPCM_SWF, adpcm_swf); +ADPCM_CODEC(CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha); #undef ADPCM_CODEC diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index a0a7d7fc4e..eb00ac432b 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -548,6 +548,7 @@ PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea); PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726); PCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct); PCM_CODEC(CODEC_ID_ADPCM_SWF, adpcm_swf); +PCM_CODEC(CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha); #undef PCM_CODEC diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 8b113cd4d0..178e65f0f6 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -137,6 +137,7 @@ enum CodecID { CODEC_ID_ADPCM_G726, CODEC_ID_ADPCM_CT, CODEC_ID_ADPCM_SWF, + CODEC_ID_ADPCM_YAMAHA, /* AMR */ CODEC_ID_AMR_NB= 0x12000, @@ -2119,6 +2120,7 @@ PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea); PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726); PCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct); PCM_CODEC(CODEC_ID_ADPCM_SWF, adpcm_swf); +PCM_CODEC(CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha); #undef PCM_CODEC |