aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Lauss <manuel.lauss@gmail.com>2025-08-16 10:44:06 +0200
committerManuel Lauss <manuel.lauss@gmail.com>2025-08-20 11:20:14 +0200
commit9141fe9653dc078d81bff8308ffdd2aaaf35495c (patch)
treeeacbddbc5db560b50bb1e37879b041df4c988000
parent1e95f1b269e25dd8907ac65f2963de54d2b73142 (diff)
downloadffmpeg-9141fe9653dc078d81bff8308ffdd2aaaf35495c.tar.gz
avcodec/vima: IMA4 subtag support
Support decoding of the IMA4 ADPCM QT scheme used in some LucasArts SANM files. Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
-rw-r--r--libavcodec/vima.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/libavcodec/vima.c b/libavcodec/vima.c
index 56cc1b7a85..0423fff091 100644
--- a/libavcodec/vima.c
+++ b/libavcodec/vima.c
@@ -28,6 +28,7 @@
#include "libavutil/channel_layout.h"
#include "libavutil/thread.h"
+#include "adpcm.h"
#include "adpcm_data.h"
#include "avcodec.h"
#include "codec_internal.h"
@@ -159,6 +160,19 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;
+ if (show_bits_long(&gb, 32) == MKBETAG('I','M','A','4')) {
+ int16_t *dest = (int16_t *)frame->data[0];
+ ADPCMChannelStatus cs;
+
+ skip_bits_long(&gb, 32); /* skip the 'IMA4' tag */
+ cs.predictor = (int16_t)get_xbits_le(&gb, 16);
+ cs.step_index = av_clip(get_bits(&gb, 8), 0, 88);
+ for (int i = 0; i < samples; i++) {
+ ff_adpcm_ima_qt_expand_nibble(&cs, get_bits(&gb, 4));
+ for (int j = 0; j < channels; j++)
+ *dest++ = cs.predictor;
+ }
+ } else {
for (chan = 0; chan < channels; chan++) {
uint16_t *dest = (uint16_t *)frame->data[0] + chan;
int step_index = channel_hint[chan];
@@ -200,6 +214,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
step_index += step_index_tables[lookup_size - 2][lookup];
}
+ }
}
*got_frame_ptr = 1;