diff options
author | Paul B Mahol | 2015-10-13 14:16:24 +0200 |
---|---|---|
committer | Paul B Mahol | 2015-10-16 16:37:40 +0200 |
commit | 8b11e43799260009dead51667bf6ff0157c05ff4 (patch) | |
tree | 7b7d14c5231040d93c5f5194b7e7c82869dbbab9 /libavcodec/adpcm.c | |
parent | 377883c4be7a5b27d57737a79d6a58a6af0ae6cd (diff) |
avcodec: add ADPCM PSX decoder
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavcodec/adpcm.c')
-rw-r--r-- | libavcodec/adpcm.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index ba38041f4a..11eb9745c7 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -152,6 +152,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) case AV_CODEC_ID_ADPCM_THP_LE: case AV_CODEC_ID_ADPCM_AFC: case AV_CODEC_ID_ADPCM_DTK: + case AV_CODEC_ID_ADPCM_PSX: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break; case AV_CODEC_ID_ADPCM_IMA_WS: @@ -665,6 +666,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, nb_samples = (buf_size / 128) * 224 / ch; break; case AV_CODEC_ID_ADPCM_DTK: + case AV_CODEC_ID_ADPCM_PSX: nb_samples = buf_size / (16 * ch) * 28; break; } @@ -1548,6 +1550,43 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, bytestream2_seek(&gb, 0, SEEK_SET); } break; + case AV_CODEC_ID_ADPCM_PSX: + for (channel = 0; channel < avctx->channels; channel++) { + samples = samples_p[channel]; + + /* Read in every sample for this channel. */ + for (i = 0; i < nb_samples / 28; i++) { + int filter, shift, flag, byte; + + filter = bytestream2_get_byteu(&gb); + shift = filter & 0xf; + filter = filter >> 4; + if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) + return AVERROR_INVALIDDATA; + flag = bytestream2_get_byteu(&gb); + + /* Decode 28 samples. */ + for (n = 0; n < 28; n++) { + int sample = 0, scale; + + if (flag < 0x07) { + if (n & 1) { + scale = sign_extend(byte >> 4, 4); + } else { + byte = bytestream2_get_byteu(&gb); + scale = sign_extend(byte, 4); + } + + scale = scale << 12; + sample = (int)((scale >> shift) + (c->status[channel].sample1 * xa_adpcm_table[filter][0] + c->status[channel].sample2 * xa_adpcm_table[filter][1]) / 64); + } + *samples++ = av_clip_int16(sample); + c->status[channel].sample2 = c->status[channel].sample1; + c->status[channel].sample1 = sample; + } + } + } + break; default: return -1; @@ -1622,6 +1661,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_SMJPEG, sample_fmts_s16, adpcm_ima_smjpeg, ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WAV, sample_fmts_s16p, adpcm_ima_wav, "ADPCM IMA WAV"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WS, sample_fmts_both, adpcm_ima_ws, "ADPCM IMA Westwood"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_MS, sample_fmts_s16, adpcm_ms, "ADPCM Microsoft"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_PSX, sample_fmts_s16p, adpcm_psx, "ADPCM PSX"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_2, sample_fmts_s16, adpcm_sbpro_2, "ADPCM Sound Blaster Pro 2-bit"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_3, sample_fmts_s16, adpcm_sbpro_3, "ADPCM Sound Blaster Pro 2.6-bit"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_4, sample_fmts_s16, adpcm_sbpro_4, "ADPCM Sound Blaster Pro 4-bit"); |