summaryrefslogtreecommitdiff
path: root/libavcodec/adpcm.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2015-10-13 14:16:24 +0200
committerPaul B Mahol <onemda@gmail.com>2015-10-16 16:37:40 +0200
commit8b11e43799260009dead51667bf6ff0157c05ff4 (patch)
tree7b7d14c5231040d93c5f5194b7e7c82869dbbab9 /libavcodec/adpcm.c
parent377883c4be7a5b27d57737a79d6a58a6af0ae6cd (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.c40
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");