blob: 86cb9134f8f4e895a46d828f2bb2eb6d04b699a9 [file] [log] [blame]
Mike Melanson3ef8be22003-09-02 04:32:021/*
2 * Assorted DPCM codecs
Vittorio Giovara41ed7ab2016-04-27 17:45:233 * Copyright (c) 2003 The FFmpeg project
Mike Melanson3ef8be22003-09-02 04:32:024 *
Diego Biurrunb78e7192006-10-07 15:30:465 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
Mike Melanson3ef8be22003-09-02 04:32:028 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
Diego Biurrunb78e7192006-10-07 15:30:4610 * version 2.1 of the License, or (at your option) any later version.
Mike Melanson3ef8be22003-09-02 04:32:0211 *
Diego Biurrunb78e7192006-10-07 15:30:4612 * FFmpeg is distributed in the hope that it will be useful,
Mike Melanson3ef8be22003-09-02 04:32:0213 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
Diego Biurrunb78e7192006-10-07 15:30:4618 * License along with FFmpeg; if not, write to the Free Software
Diego Biurrun5509bff2006-01-12 22:43:2619 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Mike Melanson3ef8be22003-09-02 04:32:0220 */
21
22/**
Diego Biurrun33edd312010-07-02 10:59:3523 * @file
Mike Melanson3ef8be22003-09-02 04:32:0224 * Assorted DPCM (differential pulse code modulation) audio codecs
25 * by Mike Melanson ([email protected])
Mike Melanson9937e682003-09-08 04:10:5926 * Xan DPCM decoder by Mario Brito ([email protected])
Mike Melanson3ef8be22003-09-02 04:32:0227 * for more information on the specific data formats, visit:
28 * http://www.pcisys.net/~melanson/codecs/simpleaudio.html
Mike Melansond08d7142004-09-28 03:09:4929 * SOL DPCMs implemented by Konstantin Shishkov
Mike Melanson9937e682003-09-08 04:10:5930 *
31 * Note about using the Xan DPCM decoder: Xan DPCM is used in AVI files
32 * found in the Wing Commander IV computer game. These AVI files contain
33 * WAVEFORMAT headers which report the audio format as 0x01: raw PCM.
34 * Clearly incorrect. To detect Xan DPCM, you will probably have to
35 * special-case your AVI demuxer to use Xan DPCM if the file uses 'Xxan'
36 * (Xan video) for its video codec. Alternately, such AVI files also contain
37 * the fourcc 'Axan' in the 'auds' chunk of the AVI header.
Mike Melanson3ef8be22003-09-02 04:32:0238 */
39
Mike Melanson3ef8be22003-09-02 04:32:0240#include "avcodec.h"
Justin Ruggles1de84012011-09-11 16:24:0341#include "bytestream.h"
Andreas Rheinhardta688f3c2022-03-16 17:18:2842#include "codec_internal.h"
Andreas Rheinhardt66b691f2022-08-24 19:28:1643#include "decode.h"
Ronald S. Bultje3a3f06b2012-03-19 02:33:0444#include "mathops.h"
Mike Melanson3ef8be22003-09-02 04:32:0245
46typedef struct DPCMContext {
Paul B Mahol29bdcf52017-06-02 10:43:0247 int16_t array[256];
Paul B Maholc5a545c2023-01-21 11:21:4448 int sample[2]; ///< previous sample (for SOL_DPCM and WADY_DPCM)
49 int scale; ///< scale for WADY_DPCM
Justin Ruggles0354fb72011-09-11 16:46:0650 const int8_t *sol_table; ///< delta table for SOL_DPCM
Mike Melanson3ef8be22003-09-02 04:32:0251} DPCMContext;
52
Paul B Maholc6bbdba2020-03-15 10:03:2753static const int32_t derf_steps[96] = {
54 0, 1, 2, 3, 4, 5, 6, 7,
55 8, 9, 10, 11, 12, 13, 14, 16,
56 17, 19, 21, 23, 25, 28, 31, 34,
57 37, 41, 45, 50, 55, 60, 66, 73,
58 80, 88, 97, 107, 118, 130, 143, 157,
59 173, 190, 209, 230, 253, 279, 307, 337,
60 371, 408, 449, 494, 544, 598, 658, 724,
61 796, 876, 963, 1060, 1166, 1282, 1411, 1552,
62 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
63 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132,
64 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289,
65 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767,
66};
67
Justin Ruggles0354fb72011-09-11 16:46:0668static const int16_t interplay_delta_table[] = {
Mike Melanson3ef8be22003-09-02 04:32:0269 0, 1, 2, 3, 4, 5, 6, 7,
70 8, 9, 10, 11, 12, 13, 14, 15,
71 16, 17, 18, 19, 20, 21, 22, 23,
72 24, 25, 26, 27, 28, 29, 30, 31,
73 32, 33, 34, 35, 36, 37, 38, 39,
74 40, 41, 42, 43, 47, 51, 56, 61,
75 66, 72, 79, 86, 94, 102, 112, 122,
76 133, 145, 158, 173, 189, 206, 225, 245,
77 267, 292, 318, 348, 379, 414, 452, 493,
78 538, 587, 640, 699, 763, 832, 908, 991,
79 1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993,
80 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008,
81 4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059,
82 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206,
83 17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589,
84 -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1,
85 1, 1, 5481, 10503, 15105, 19322, 23186, 26728,
86 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298,
87 -17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597,
88 -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772,
89 -4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373,
90 -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180,
91 -1081, -991, -908, -832, -763, -699, -640, -587,
92 -538, -493, -452, -414, -379, -348, -318, -292,
93 -267, -245, -225, -206, -189, -173, -158, -145,
94 -133, -122, -112, -102, -94, -86, -79, -72,
95 -66, -61, -56, -51, -47, -43, -42, -41,
96 -40, -39, -38, -37, -36, -35, -34, -33,
97 -32, -31, -30, -29, -28, -27, -26, -25,
98 -24, -23, -22, -21, -20, -19, -18, -17,
99 -16, -15, -14, -13, -12, -11, -10, -9,
100 -8, -7, -6, -5, -4, -3, -2, -1
101
102};
103
Justin Ruggles0354fb72011-09-11 16:46:06104static const int8_t sol_table_old[16] = {
Justin Ruggles4bad4642011-09-11 16:37:17105 0x0, 0x1, 0x2, 0x3, 0x6, 0xA, 0xF, 0x15,
106 -0x15, -0xF, -0xA, -0x6, -0x3, -0x2, -0x1, 0x0
107};
Mike Melansond08d7142004-09-28 03:09:49108
Justin Ruggles0354fb72011-09-11 16:46:06109static const int8_t sol_table_new[16] = {
Justin Ruggles4bad4642011-09-11 16:37:17110 0x0, 0x1, 0x2, 0x3, 0x6, 0xA, 0xF, 0x15,
111 0x0, -0x1, -0x2, -0x3, -0x6, -0xA, -0xF, -0x15
112};
Diego Biurrun115329f2005-12-17 18:14:38113
Justin Ruggles0354fb72011-09-11 16:46:06114static const int16_t sol_table_16[128] = {
Mike Melansond08d7142004-09-28 03:09:49115 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
116 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
117 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
118 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
119 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
120 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
121 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
122 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
123 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
124 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
125 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
126 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
127 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
128};
129
Paul B Maholc5a545c2023-01-21 11:21:44130static const int16_t wady_table[128] = {
131 0, 2, 4, 6, 8, 10, 12, 15,
132 18, 21, 24, 28, 32, 36, 40, 44,
133 49, 54, 59, 64, 70, 76, 82, 88,
134 95, 102, 109, 116, 124, 132, 140, 148,
135 160, 170, 180, 190, 200, 210, 220, 230,
136 240, 255, 270, 285, 300, 320, 340, 360,
137 380, 400, 425, 450, 475, 500, 525, 550,
138 580, 610, 650, 700, 750, 800, 900, 1000,
139 -0, -2, -4, -6, -8, -10, -12, -15,
140 -18, -21, -24, -28, -32, -36, -40, -44,
141 -49, -54, -59, -64, -70, -76, -82, -88,
142 -95, -102,-109,-116,-124,-132,-140,-148,
143 -160,-170,-180,-190,-200,-210,-220,-230,
144 -240,-255,-270,-285,-300,-320,-340,-360,
145 -380,-400,-425,-450,-475,-500,-525,-550,
146 -580,-610,-650,-700,-750,-800,-900,-1000,
147};
Mike Melansond08d7142004-09-28 03:09:49148
Zuxy Meng98a6fff2008-03-21 03:11:20149static av_cold int dpcm_decode_init(AVCodecContext *avctx)
Mike Melanson3ef8be22003-09-02 04:32:02150{
151 DPCMContext *s = avctx->priv_data;
152 int i;
Mike Melanson3ef8be22003-09-02 04:32:02153
Vittorio Giovarac5022f52017-03-29 16:21:29154 if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 2) {
Piotr Bandurski8d889202012-11-05 16:44:24155 av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
Justin Ruggles8d77d122011-09-11 16:40:40156 return AVERROR(EINVAL);
157 }
Mike Melanson3ef8be22003-09-02 04:32:02158
Mike Melansond08d7142004-09-28 03:09:49159 s->sample[0] = s->sample[1] = 0;
Mike Melanson3ef8be22003-09-02 04:32:02160
Paul B Maholc5a545c2023-01-21 11:21:44161 switch (avctx->codec->id) {
Mike Melanson3ef8be22003-09-02 04:32:02162
Anton Khirnov36ef5362012-08-05 09:11:04163 case AV_CODEC_ID_ROQ_DPCM:
Mike Melanson3ef8be22003-09-02 04:32:02164 /* initialize square table */
165 for (i = 0; i < 128; i++) {
Justin Rugglesf47f7ef2011-09-11 16:41:48166 int16_t square = i * i;
Paul B Mahol29bdcf52017-06-02 10:43:02167 s->array[i ] = square;
168 s->array[i + 128] = -square;
Mike Melanson3ef8be22003-09-02 04:32:02169 }
170 break;
171
Anton Khirnov36ef5362012-08-05 09:11:04172 case AV_CODEC_ID_SOL_DPCM:
Mike Melansond08d7142004-09-28 03:09:49173 switch(avctx->codec_tag){
174 case 1:
Justin Ruggles4bad4642011-09-11 16:37:17175 s->sol_table = sol_table_old;
Mike Melansond08d7142004-09-28 03:09:49176 s->sample[0] = s->sample[1] = 0x80;
177 break;
178 case 2:
Justin Ruggles4bad4642011-09-11 16:37:17179 s->sol_table = sol_table_new;
Mike Melansond08d7142004-09-28 03:09:49180 s->sample[0] = s->sample[1] = 0x80;
181 break;
182 case 3:
Mike Melansond08d7142004-09-28 03:09:49183 break;
184 default:
185 av_log(avctx, AV_LOG_ERROR, "Unknown SOL subcodec\n");
186 return -1;
187 }
188 break;
Diego Biurrun115329f2005-12-17 18:14:38189
Paul B Mahol035ae3c2015-10-24 18:41:32190 case AV_CODEC_ID_SDX2_DPCM:
191 for (i = -128; i < 128; i++) {
192 int16_t square = i * i * 2;
Paul B Mahol29bdcf52017-06-02 10:43:02193 s->array[i+128] = i < 0 ? -square: square;
194 }
195 break;
196
197 case AV_CODEC_ID_GREMLIN_DPCM: {
198 int delta = 0;
199 int code = 64;
200 int step = 45;
201
202 s->array[0] = 0;
203 for (i = 0; i < 127; i++) {
204 delta += (code >> 5);
205 code += step;
206 step += 2;
207
208 s->array[i*2 + 1] = delta;
209 s->array[i*2 + 2] = -delta;
210 }
211 s->array[255] = delta + (code >> 5);
Paul B Mahol035ae3c2015-10-24 18:41:32212 }
213 break;
214
Paul B Maholc5a545c2023-01-21 11:21:44215 case AV_CODEC_ID_WADY_DPCM:
216 s->scale = (avctx->extradata && avctx->extradata_size > 0) ? avctx->extradata[0] : 1;
217 break;
218
Mike Melanson3ef8be22003-09-02 04:32:02219 default:
220 break;
221 }
222
Anton Khirnov36ef5362012-08-05 09:11:04223 if (avctx->codec->id == AV_CODEC_ID_SOL_DPCM && avctx->codec_tag != 3)
Justin Ruggles04b24cf2011-09-11 16:04:46224 avctx->sample_fmt = AV_SAMPLE_FMT_U8;
225 else
226 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
227
Mike Melanson3ef8be22003-09-02 04:32:02228 return 0;
229}
230
Justin Ruggles4bad4642011-09-11 16:37:17231
Andreas Rheinhardtce7dbd02022-03-30 19:33:24232static int dpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
Justin Ruggles0eea2122011-09-06 16:17:45233 int *got_frame_ptr, AVPacket *avpkt)
Mike Melanson3ef8be22003-09-02 04:32:02234{
Thilo Borgmann7a00bba2009-04-07 15:59:50235 int buf_size = avpkt->size;
Mike Melanson3ef8be22003-09-02 04:32:02236 DPCMContext *s = avctx->priv_data;
Justin Ruggles0eea2122011-09-06 16:17:45237 int out = 0, ret;
Mike Melanson3ef8be22003-09-02 04:32:02238 int predictor[2];
Justin Rugglesb09c7ee2011-09-11 15:13:04239 int ch = 0;
Vittorio Giovarac5022f52017-03-29 16:21:29240 int stereo = avctx->ch_layout.nb_channels - 1;
Ronald S. Bultje3a3f06b2012-03-19 02:33:04241 int16_t *output_samples, *samples_end;
242 GetByteContext gb;
Mike Melanson3ef8be22003-09-02 04:32:02243
Ronald S. Bultje3a3f06b2012-03-19 02:33:04244 if (stereo && (buf_size & 1))
Alex Conversece7aee92012-02-17 22:13:40245 buf_size--;
Ronald S. Bultje3a3f06b2012-03-19 02:33:04246 bytestream2_init(&gb, avpkt->data, buf_size);
Alex Conversece7aee92012-02-17 22:13:40247
Justin Ruggles76db17d2011-09-11 15:51:08248 /* calculate output size */
249 switch(avctx->codec->id) {
Anton Khirnov36ef5362012-08-05 09:11:04250 case AV_CODEC_ID_ROQ_DPCM:
Justin Ruggles76db17d2011-09-11 15:51:08251 out = buf_size - 8;
252 break;
Anton Khirnov36ef5362012-08-05 09:11:04253 case AV_CODEC_ID_INTERPLAY_DPCM:
Vittorio Giovarac5022f52017-03-29 16:21:29254 out = buf_size - 6 - avctx->ch_layout.nb_channels;
Justin Ruggles76db17d2011-09-11 15:51:08255 break;
Anton Khirnov36ef5362012-08-05 09:11:04256 case AV_CODEC_ID_XAN_DPCM:
Vittorio Giovarac5022f52017-03-29 16:21:29257 out = buf_size - 2 * avctx->ch_layout.nb_channels;
Justin Ruggles76db17d2011-09-11 15:51:08258 break;
Anton Khirnov36ef5362012-08-05 09:11:04259 case AV_CODEC_ID_SOL_DPCM:
Justin Ruggles76db17d2011-09-11 15:51:08260 if (avctx->codec_tag != 3)
261 out = buf_size * 2;
262 else
263 out = buf_size;
264 break;
Paul B Maholc5a545c2023-01-21 11:21:44265 case AV_CODEC_ID_WADY_DPCM:
Paul B Maholc6bbdba2020-03-15 10:03:27266 case AV_CODEC_ID_DERF_DPCM:
Paul B Mahol29bdcf52017-06-02 10:43:02267 case AV_CODEC_ID_GREMLIN_DPCM:
Paul B Mahol035ae3c2015-10-24 18:41:32268 case AV_CODEC_ID_SDX2_DPCM:
269 out = buf_size;
270 break;
Justin Ruggles76db17d2011-09-11 15:51:08271 }
Justin Ruggles8dbc6d02011-11-02 20:49:38272 if (out <= 0) {
Justin Ruggles08bd22a2011-09-11 17:18:51273 av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
274 return AVERROR(EINVAL);
275 }
Vittorio Giovarac5022f52017-03-29 16:21:29276 if (out % avctx->ch_layout.nb_channels) {
Michael Niedermayer92115bb2012-01-26 16:04:51277 av_log(avctx, AV_LOG_WARNING, "channels have differing number of samples\n");
278 }
Justin Ruggles0eea2122011-09-06 16:17:45279
280 /* get output buffer */
Vittorio Giovarac5022f52017-03-29 16:21:29281 frame->nb_samples = (out + avctx->ch_layout.nb_channels - 1) / avctx->ch_layout.nb_channels;
Clément Bœsch1ec94b02013-03-12 07:41:53282 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
Justin Ruggles0eea2122011-09-06 16:17:45283 return ret;
Justin Rugglesb8788672012-12-23 23:03:43284 output_samples = (int16_t *)frame->data[0];
Ronald S. Bultje3a3f06b2012-03-19 02:33:04285 samples_end = output_samples + out;
Kostya Shishkova2085a72007-09-22 09:21:43286
Mike Melanson3ef8be22003-09-02 04:32:02287 switch(avctx->codec->id) {
288
Anton Khirnov36ef5362012-08-05 09:11:04289 case AV_CODEC_ID_ROQ_DPCM:
Ronald S. Bultje3a3f06b2012-03-19 02:33:04290 bytestream2_skipu(&gb, 6);
Justin Ruggles1de84012011-09-11 16:24:03291
Justin Ruggles3db8db42011-09-11 15:19:00292 if (stereo) {
Ronald S. Bultje3a3f06b2012-03-19 02:33:04293 predictor[1] = sign_extend(bytestream2_get_byteu(&gb) << 8, 16);
294 predictor[0] = sign_extend(bytestream2_get_byteu(&gb) << 8, 16);
Justin Ruggles3db8db42011-09-11 15:19:00295 } else {
Ronald S. Bultje3a3f06b2012-03-19 02:33:04296 predictor[0] = sign_extend(bytestream2_get_le16u(&gb), 16);
Mike Melanson3ef8be22003-09-02 04:32:02297 }
Mike Melanson3ef8be22003-09-02 04:32:02298
299 /* decode the samples */
Ronald S. Bultje3a3f06b2012-03-19 02:33:04300 while (output_samples < samples_end) {
Paul B Mahol29bdcf52017-06-02 10:43:02301 predictor[ch] += s->array[bytestream2_get_byteu(&gb)];
Justin Ruggles4bad4642011-09-11 16:37:17302 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08303 *output_samples++ = predictor[ch];
Mike Melanson3ef8be22003-09-02 04:32:02304
305 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00306 ch ^= stereo;
Mike Melanson3ef8be22003-09-02 04:32:02307 }
308 break;
309
Anton Khirnov36ef5362012-08-05 09:11:04310 case AV_CODEC_ID_INTERPLAY_DPCM:
Ronald S. Bultje3a3f06b2012-03-19 02:33:04311 bytestream2_skipu(&gb, 6); /* skip over the stream mask and stream length */
Justin Ruggles1de84012011-09-11 16:24:03312
Vittorio Giovarac5022f52017-03-29 16:21:29313 for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
Ronald S. Bultje3a3f06b2012-03-19 02:33:04314 predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16);
Justin Ruggles1de84012011-09-11 16:24:03315 *output_samples++ = predictor[ch];
Mike Melanson3ef8be22003-09-02 04:32:02316 }
317
Justin Ruggles1de84012011-09-11 16:24:03318 ch = 0;
Ronald S. Bultje3a3f06b2012-03-19 02:33:04319 while (output_samples < samples_end) {
320 predictor[ch] += interplay_delta_table[bytestream2_get_byteu(&gb)];
Justin Ruggles4bad4642011-09-11 16:37:17321 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08322 *output_samples++ = predictor[ch];
Mike Melanson3ef8be22003-09-02 04:32:02323
324 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00325 ch ^= stereo;
Mike Melanson3ef8be22003-09-02 04:32:02326 }
Mike Melanson3ef8be22003-09-02 04:32:02327 break;
Mike Melanson9937e682003-09-08 04:10:59328
Anton Khirnov36ef5362012-08-05 09:11:04329 case AV_CODEC_ID_XAN_DPCM:
Justin Rugglesfc6faee2011-09-11 16:13:13330 {
331 int shift[2] = { 4, 4 };
Mike Melanson9937e682003-09-08 04:10:59332
Vittorio Giovarac5022f52017-03-29 16:21:29333 for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++)
Ronald S. Bultje3a3f06b2012-03-19 02:33:04334 predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16);
Justin Ruggles1de84012011-09-11 16:24:03335
336 ch = 0;
Ronald S. Bultje3a3f06b2012-03-19 02:33:04337 while (output_samples < samples_end) {
338 int diff = bytestream2_get_byteu(&gb);
339 int n = diff & 3;
340
341 if (n == 3)
Justin Rugglesb09c7ee2011-09-11 15:13:04342 shift[ch]++;
Mike Melanson9937e682003-09-08 04:10:59343 else
Ronald S. Bultje3a3f06b2012-03-19 02:33:04344 shift[ch] -= (2 * n);
345 diff = sign_extend((diff &~ 3) << 8, 16);
346
Michael Niedermayer20ade592020-04-09 13:37:55347 /* saturate the shifter to 0..31 */
348 shift[ch] = av_clip_uintp2(shift[ch], 5);
Mike Melanson9937e682003-09-08 04:10:59349
Justin Rugglesb09c7ee2011-09-11 15:13:04350 diff >>= shift[ch];
351 predictor[ch] += diff;
Mike Melanson9937e682003-09-08 04:10:59352
Justin Rugglesb09c7ee2011-09-11 15:13:04353 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08354 *output_samples++ = predictor[ch];
Mike Melanson9937e682003-09-08 04:10:59355
356 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00357 ch ^= stereo;
Mike Melanson9937e682003-09-08 04:10:59358 }
359 break;
Justin Rugglesfc6faee2011-09-11 16:13:13360 }
Anton Khirnov36ef5362012-08-05 09:11:04361 case AV_CODEC_ID_SOL_DPCM:
Mike Melansond08d7142004-09-28 03:09:49362 if (avctx->codec_tag != 3) {
Justin Rugglesb8788672012-12-23 23:03:43363 uint8_t *output_samples_u8 = frame->data[0],
Ronald S. Bultje3a3f06b2012-03-19 02:33:04364 *samples_end_u8 = output_samples_u8 + out;
365 while (output_samples_u8 < samples_end_u8) {
366 int n = bytestream2_get_byteu(&gb);
Justin Ruggles04b24cf2011-09-11 16:04:46367
368 s->sample[0] += s->sol_table[n >> 4];
369 s->sample[0] = av_clip_uint8(s->sample[0]);
370 *output_samples_u8++ = s->sample[0];
371
372 s->sample[stereo] += s->sol_table[n & 0x0F];
373 s->sample[stereo] = av_clip_uint8(s->sample[stereo]);
374 *output_samples_u8++ = s->sample[stereo];
Mike Melansond08d7142004-09-28 03:09:49375 }
376 } else {
Ronald S. Bultje3a3f06b2012-03-19 02:33:04377 while (output_samples < samples_end) {
378 int n = bytestream2_get_byteu(&gb);
Justin Ruggles5a54d512011-09-11 16:43:03379 if (n & 0x80) s->sample[ch] -= sol_table_16[n & 0x7F];
380 else s->sample[ch] += sol_table_16[n & 0x7F];
Justin Rugglesb09c7ee2011-09-11 15:13:04381 s->sample[ch] = av_clip_int16(s->sample[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08382 *output_samples++ = s->sample[ch];
Mike Melansond08d7142004-09-28 03:09:49383 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00384 ch ^= stereo;
Mike Melansond08d7142004-09-28 03:09:49385 }
386 }
387 break;
Paul B Mahol035ae3c2015-10-24 18:41:32388
389 case AV_CODEC_ID_SDX2_DPCM:
390 while (output_samples < samples_end) {
391 int8_t n = bytestream2_get_byteu(&gb);
392
393 if (!(n & 1))
394 s->sample[ch] = 0;
Paul B Mahol29bdcf52017-06-02 10:43:02395 s->sample[ch] += s->array[n + 128];
Paul B Mahol035ae3c2015-10-24 18:41:32396 s->sample[ch] = av_clip_int16(s->sample[ch]);
397 *output_samples++ = s->sample[ch];
398 ch ^= stereo;
399 }
400 break;
Paul B Mahol29bdcf52017-06-02 10:43:02401
402 case AV_CODEC_ID_GREMLIN_DPCM: {
403 int idx = 0;
404
405 while (output_samples < samples_end) {
406 uint8_t n = bytestream2_get_byteu(&gb);
407
Michael Niedermayerb1aecad2020-01-22 22:11:47408 *output_samples++ = s->sample[idx] += (unsigned)s->array[n];
Paul B Mahol29bdcf52017-06-02 10:43:02409 idx ^= 1;
410 }
411 }
412 break;
Paul B Maholc6bbdba2020-03-15 10:03:27413
414 case AV_CODEC_ID_DERF_DPCM: {
415 int idx = 0;
416
417 while (output_samples < samples_end) {
418 uint8_t n = bytestream2_get_byteu(&gb);
419 int index = FFMIN(n & 0x7f, 95);
420
421 s->sample[idx] += (n & 0x80 ? -1: 1) * derf_steps[index];
422 s->sample[idx] = av_clip_int16(s->sample[idx]);
423 *output_samples++ = s->sample[idx];
424 idx ^= stereo;
425 }
426 }
427 break;
Paul B Maholc5a545c2023-01-21 11:21:44428
429 case AV_CODEC_ID_WADY_DPCM: {
430 int idx = 0;
431
432 while (output_samples < samples_end) {
433 const uint8_t n = bytestream2_get_byteu(&gb);
434
435 if (n & 0x80)
436 s->sample[idx] = sign_extend((n & 0x7f) << 9, 16);
437 else
438 s->sample[idx] += s->scale * wady_table[n & 0x7f];
439 *output_samples++ = av_clip_int16(s->sample[idx]);
440 idx ^= stereo;
441 }
442 }
443 break;
Mike Melanson3ef8be22003-09-02 04:32:02444 }
445
Justin Rugglesb8788672012-12-23 23:03:43446 *got_frame_ptr = 1;
Justin Ruggles0eea2122011-09-06 16:17:45447
Alex Conversece7aee92012-02-17 22:13:40448 return avpkt->size;
Mike Melanson3ef8be22003-09-02 04:32:02449}
450
Paul B Mahol3110e282023-01-21 13:07:48451static void dpcm_flush(AVCodecContext *avctx)
452{
453 DPCMContext *s = avctx->priv_data;
454
455 s->sample[0] = s->sample[1] = 0;
456}
457
Diego Biurrun86714882011-09-23 19:11:15458#define DPCM_DECODER(id_, name_, long_name_) \
Andreas Rheinhardt20f97272022-03-16 20:09:54459const FFCodec ff_ ## name_ ## _decoder = { \
460 .p.name = #name_, \
Andreas Rheinhardt48286d42022-08-29 11:38:02461 CODEC_LONG_NAME(long_name_), \
Andreas Rheinhardt20f97272022-03-16 20:09:54462 .p.type = AVMEDIA_TYPE_AUDIO, \
463 .p.id = id_, \
464 .p.capabilities = AV_CODEC_CAP_DR1, \
Diego Biurrun86714882011-09-23 19:11:15465 .priv_data_size = sizeof(DPCMContext), \
466 .init = dpcm_decode_init, \
Paul B Mahol3110e282023-01-21 13:07:48467 .flush = dpcm_flush, \
Andreas Rheinhardt4243da42022-03-30 21:28:24468 FF_CODEC_DECODE_CB(dpcm_decode_frame), \
Mans Rullgard98ec8282011-02-10 12:04:25469}
Mike Melanson3ef8be22003-09-02 04:32:02470
Paul B Maholc6bbdba2020-03-15 10:03:27471DPCM_DECODER(AV_CODEC_ID_DERF_DPCM, derf_dpcm, "DPCM Xilam DERF");
Paul B Mahol29bdcf52017-06-02 10:43:02472DPCM_DECODER(AV_CODEC_ID_GREMLIN_DPCM, gremlin_dpcm, "DPCM Gremlin");
Anton Khirnov36ef5362012-08-05 09:11:04473DPCM_DECODER(AV_CODEC_ID_INTERPLAY_DPCM, interplay_dpcm, "DPCM Interplay");
474DPCM_DECODER(AV_CODEC_ID_ROQ_DPCM, roq_dpcm, "DPCM id RoQ");
Paul B Mahol035ae3c2015-10-24 18:41:32475DPCM_DECODER(AV_CODEC_ID_SDX2_DPCM, sdx2_dpcm, "DPCM Squareroot-Delta-Exact");
Anton Khirnov36ef5362012-08-05 09:11:04476DPCM_DECODER(AV_CODEC_ID_SOL_DPCM, sol_dpcm, "DPCM Sol");
477DPCM_DECODER(AV_CODEC_ID_XAN_DPCM, xan_dpcm, "DPCM Xan");
Paul B Maholc5a545c2023-01-21 11:21:44478DPCM_DECODER(AV_CODEC_ID_WADY_DPCM, wady_dpcm, "DPCM Marble WADY");