blob: 02267d76416bb17c8fed53459d667163e3ed2e56 [file] [log] [blame]
Mike Melanson3ef8be22003-09-02 04:32:021/*
2 * Assorted DPCM codecs
Diego Biurrun406792e2009-01-19 15:46:403 * Copyright (c) 2003 The ffmpeg Project
Mike Melanson3ef8be22003-09-02 04:32:024 *
Mans Rullgard2912e872011-03-18 17:35:105 * This file is part of Libav.
Diego Biurrunb78e7192006-10-07 15:30:466 *
Mans Rullgard2912e872011-03-18 17:35:107 * Libav 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 *
Mans Rullgard2912e872011-03-18 17:35:1012 * Libav 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
Mans Rullgard2912e872011-03-18 17:35:1018 * License along with Libav; 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
Diego Biurrun6a5d31a2009-01-11 22:19:4840#include "libavutil/intreadwrite.h"
Mike Melanson3ef8be22003-09-02 04:32:0241#include "avcodec.h"
42
43typedef struct DPCMContext {
44 int channels;
45 short roq_square_array[256];
Justin Ruggles04b24cf2011-09-11 16:04:4646 int sample[2]; ///< previous sample (for SOL_DPCM)
Stefan Huehner62a05b52006-07-06 13:53:0747 const int *sol_table;//for SOL_DPCM
Mike Melanson3ef8be22003-09-02 04:32:0248} DPCMContext;
49
Mike Melanson3ef8be22003-09-02 04:32:0250#define SE_16BIT(x) if (x & 0x8000) x -= 0x10000;
Mike Melanson3ef8be22003-09-02 04:32:0251
Stefan Gehrercf2baeb2008-06-24 20:01:3152static const int interplay_delta_table[] = {
Mike Melanson3ef8be22003-09-02 04:32:0253 0, 1, 2, 3, 4, 5, 6, 7,
54 8, 9, 10, 11, 12, 13, 14, 15,
55 16, 17, 18, 19, 20, 21, 22, 23,
56 24, 25, 26, 27, 28, 29, 30, 31,
57 32, 33, 34, 35, 36, 37, 38, 39,
58 40, 41, 42, 43, 47, 51, 56, 61,
59 66, 72, 79, 86, 94, 102, 112, 122,
60 133, 145, 158, 173, 189, 206, 225, 245,
61 267, 292, 318, 348, 379, 414, 452, 493,
62 538, 587, 640, 699, 763, 832, 908, 991,
63 1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993,
64 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008,
65 4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059,
66 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206,
67 17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589,
68 -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1,
69 1, 1, 5481, 10503, 15105, 19322, 23186, 26728,
70 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298,
71 -17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597,
72 -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772,
73 -4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373,
74 -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180,
75 -1081, -991, -908, -832, -763, -699, -640, -587,
76 -538, -493, -452, -414, -379, -348, -318, -292,
77 -267, -245, -225, -206, -189, -173, -158, -145,
78 -133, -122, -112, -102, -94, -86, -79, -72,
79 -66, -61, -56, -51, -47, -43, -42, -41,
80 -40, -39, -38, -37, -36, -35, -34, -33,
81 -32, -31, -30, -29, -28, -27, -26, -25,
82 -24, -23, -22, -21, -20, -19, -18, -17,
83 -16, -15, -14, -13, -12, -11, -10, -9,
84 -8, -7, -6, -5, -4, -3, -2, -1
85
86};
87
Stefan Huehner62a05b52006-07-06 13:53:0788static const int sol_table_old[16] =
Mike Melansond08d7142004-09-28 03:09:4989 { 0x0, 0x1, 0x2 , 0x3, 0x6, 0xA, 0xF, 0x15,
90 -0x15, -0xF, -0xA, -0x6, -0x3, -0x2, -0x1, 0x0};
91
Stefan Huehner62a05b52006-07-06 13:53:0792static const int sol_table_new[16] =
Mike Melansond08d7142004-09-28 03:09:4993 { 0x0, 0x1, 0x2, 0x3, 0x6, 0xA, 0xF, 0x15,
94 0x0, -0x1, -0x2, -0x3, -0x6, -0xA, -0xF, -0x15};
Diego Biurrun115329f2005-12-17 18:14:3895
Stefan Huehner62a05b52006-07-06 13:53:0796static const int sol_table_16[128] = {
Mike Melansond08d7142004-09-28 03:09:4997 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
98 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
99 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
100 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
101 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
102 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
103 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
104 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
105 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
106 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
107 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
108 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
109 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
110};
111
112
113
Zuxy Meng98a6fff2008-03-21 03:11:20114static av_cold int dpcm_decode_init(AVCodecContext *avctx)
Mike Melanson3ef8be22003-09-02 04:32:02115{
116 DPCMContext *s = avctx->priv_data;
117 int i;
118 short square;
119
120 s->channels = avctx->channels;
Mike Melansond08d7142004-09-28 03:09:49121 s->sample[0] = s->sample[1] = 0;
Mike Melanson3ef8be22003-09-02 04:32:02122
123 switch(avctx->codec->id) {
124
125 case CODEC_ID_ROQ_DPCM:
126 /* initialize square table */
127 for (i = 0; i < 128; i++) {
128 square = i * i;
129 s->roq_square_array[i] = square;
130 s->roq_square_array[i + 128] = -square;
131 }
132 break;
133
Diego Biurrun115329f2005-12-17 18:14:38134
Mike Melansond08d7142004-09-28 03:09:49135 case CODEC_ID_SOL_DPCM:
136 switch(avctx->codec_tag){
137 case 1:
138 s->sol_table=sol_table_old;
139 s->sample[0] = s->sample[1] = 0x80;
140 break;
141 case 2:
142 s->sol_table=sol_table_new;
143 s->sample[0] = s->sample[1] = 0x80;
144 break;
145 case 3:
146 s->sol_table=sol_table_16;
147 break;
148 default:
149 av_log(avctx, AV_LOG_ERROR, "Unknown SOL subcodec\n");
150 return -1;
151 }
152 break;
Diego Biurrun115329f2005-12-17 18:14:38153
Mike Melanson3ef8be22003-09-02 04:32:02154 default:
155 break;
156 }
157
Justin Ruggles04b24cf2011-09-11 16:04:46158 if (avctx->codec->id == CODEC_ID_SOL_DPCM && avctx->codec_tag != 3)
159 avctx->sample_fmt = AV_SAMPLE_FMT_U8;
160 else
161 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
162
Mike Melanson3ef8be22003-09-02 04:32:02163 return 0;
164}
165
166static int dpcm_decode_frame(AVCodecContext *avctx,
167 void *data, int *data_size,
Thilo Borgmann7a00bba2009-04-07 15:59:50168 AVPacket *avpkt)
Mike Melanson3ef8be22003-09-02 04:32:02169{
Thilo Borgmann7a00bba2009-04-07 15:59:50170 const uint8_t *buf = avpkt->data;
171 int buf_size = avpkt->size;
Mike Melanson3ef8be22003-09-02 04:32:02172 DPCMContext *s = avctx->priv_data;
173 int in, out = 0;
Mike Melanson3ef8be22003-09-02 04:32:02174 int predictor[2];
Justin Rugglesb09c7ee2011-09-11 15:13:04175 int ch = 0;
Justin Ruggles3db8db42011-09-11 15:19:00176 int stereo = s->channels - 1;
Mike Melanson3ef8be22003-09-02 04:32:02177 short *output_samples = data;
Mike Melanson3ef8be22003-09-02 04:32:02178
Mike Melansonc89c1d22004-01-31 17:30:28179 if (!buf_size)
180 return 0;
181
Justin Ruggles76db17d2011-09-11 15:51:08182 /* calculate output size */
183 switch(avctx->codec->id) {
184 case CODEC_ID_ROQ_DPCM:
185 out = buf_size - 8;
186 break;
187 case CODEC_ID_INTERPLAY_DPCM:
188 out = buf_size - 6 - s->channels;
189 break;
190 case CODEC_ID_XAN_DPCM:
191 out = buf_size - 2 * s->channels;
192 break;
193 case CODEC_ID_SOL_DPCM:
194 if (avctx->codec_tag != 3)
195 out = buf_size * 2;
196 else
197 out = buf_size;
198 break;
199 }
200 out *= av_get_bytes_per_sample(avctx->sample_fmt);
201
202 if (*data_size < out) {
203 av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
204 return AVERROR(EINVAL);
205 }
Kostya Shishkova2085a72007-09-22 09:21:43206
Mike Melanson3ef8be22003-09-02 04:32:02207 switch(avctx->codec->id) {
208
209 case CODEC_ID_ROQ_DPCM:
Justin Ruggles3db8db42011-09-11 15:19:00210 if (stereo) {
Mike Melanson3ef8be22003-09-02 04:32:02211 predictor[0] = buf[7] << 8;
212 predictor[1] = buf[6] << 8;
Justin Ruggles3db8db42011-09-11 15:19:00213 } else {
214 predictor[0] = AV_RL16(&buf[6]);
Mike Melanson3ef8be22003-09-02 04:32:02215 }
216 SE_16BIT(predictor[0]);
217 SE_16BIT(predictor[1]);
218
219 /* decode the samples */
Justin Ruggles76db17d2011-09-11 15:51:08220 for (in = 8; in < buf_size; in++) {
Justin Rugglesb09c7ee2011-09-11 15:13:04221 predictor[ch] += s->roq_square_array[buf[in]];
222 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08223 *output_samples++ = predictor[ch];
Mike Melanson3ef8be22003-09-02 04:32:02224
225 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00226 ch ^= stereo;
Mike Melanson3ef8be22003-09-02 04:32:02227 }
228 break;
229
230 case CODEC_ID_INTERPLAY_DPCM:
Mike Melansonb10529b2003-09-19 04:41:02231 in = 6; /* skip over the stream mask and stream length */
Alex Beregszaszifead30d2007-01-19 22:12:59232 predictor[0] = AV_RL16(&buf[in]);
Mike Melansonb10529b2003-09-19 04:41:02233 in += 2;
234 SE_16BIT(predictor[0])
Justin Ruggles76db17d2011-09-11 15:51:08235 *output_samples++ = predictor[0];
Justin Ruggles3db8db42011-09-11 15:19:00236 if (stereo) {
Alex Beregszaszifead30d2007-01-19 22:12:59237 predictor[1] = AV_RL16(&buf[in]);
Mike Melanson3ef8be22003-09-02 04:32:02238 in += 2;
Mike Melansonb10529b2003-09-19 04:41:02239 SE_16BIT(predictor[1])
Justin Ruggles76db17d2011-09-11 15:51:08240 *output_samples++ = predictor[1];
Mike Melanson3ef8be22003-09-02 04:32:02241 }
242
243 while (in < buf_size) {
Justin Rugglesb09c7ee2011-09-11 15:13:04244 predictor[ch] += interplay_delta_table[buf[in++]];
245 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08246 *output_samples++ = predictor[ch];
Mike Melanson3ef8be22003-09-02 04:32:02247
248 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00249 ch ^= stereo;
Mike Melanson3ef8be22003-09-02 04:32:02250 }
Mike Melanson3ef8be22003-09-02 04:32:02251 break;
Mike Melanson9937e682003-09-08 04:10:59252
253 case CODEC_ID_XAN_DPCM:
Justin Rugglesfc6faee2011-09-11 16:13:13254 {
255 int shift[2] = { 4, 4 };
Mike Melanson9937e682003-09-08 04:10:59256 in = 0;
Alex Beregszaszifead30d2007-01-19 22:12:59257 predictor[0] = AV_RL16(&buf[in]);
Mike Melanson9937e682003-09-08 04:10:59258 in += 2;
259 SE_16BIT(predictor[0]);
Justin Ruggles3db8db42011-09-11 15:19:00260 if (stereo) {
Alex Beregszaszifead30d2007-01-19 22:12:59261 predictor[1] = AV_RL16(&buf[in]);
Mike Melanson9937e682003-09-08 04:10:59262 in += 2;
263 SE_16BIT(predictor[1]);
264 }
265
266 while (in < buf_size) {
Justin Ruggles989bb7b2011-09-11 16:08:38267 uint8_t n = buf[in++];
Justin Rugglesfc6faee2011-09-11 16:13:13268 int16_t diff = (n & 0xFC) << 8;
Justin Ruggles989bb7b2011-09-11 16:08:38269 if ((n & 0x03) == 3)
Justin Rugglesb09c7ee2011-09-11 15:13:04270 shift[ch]++;
Mike Melanson9937e682003-09-08 04:10:59271 else
Justin Ruggles989bb7b2011-09-11 16:08:38272 shift[ch] -= (2 * (n & 3));
Mike Melanson9937e682003-09-08 04:10:59273 /* saturate the shifter to a lower limit of 0 */
Justin Rugglesb09c7ee2011-09-11 15:13:04274 if (shift[ch] < 0)
275 shift[ch] = 0;
Mike Melanson9937e682003-09-08 04:10:59276
Justin Rugglesb09c7ee2011-09-11 15:13:04277 diff >>= shift[ch];
278 predictor[ch] += diff;
Mike Melanson9937e682003-09-08 04:10:59279
Justin Rugglesb09c7ee2011-09-11 15:13:04280 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08281 *output_samples++ = predictor[ch];
Mike Melanson9937e682003-09-08 04:10:59282
283 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00284 ch ^= stereo;
Mike Melanson9937e682003-09-08 04:10:59285 }
286 break;
Justin Rugglesfc6faee2011-09-11 16:13:13287 }
Mike Melansond08d7142004-09-28 03:09:49288 case CODEC_ID_SOL_DPCM:
289 in = 0;
290 if (avctx->codec_tag != 3) {
Justin Ruggles04b24cf2011-09-11 16:04:46291 uint8_t *output_samples_u8 = data;
Mike Melansond08d7142004-09-28 03:09:49292 while (in < buf_size) {
Justin Ruggles04b24cf2011-09-11 16:04:46293 uint8_t n = buf[in++];
294
295 s->sample[0] += s->sol_table[n >> 4];
296 s->sample[0] = av_clip_uint8(s->sample[0]);
297 *output_samples_u8++ = s->sample[0];
298
299 s->sample[stereo] += s->sol_table[n & 0x0F];
300 s->sample[stereo] = av_clip_uint8(s->sample[stereo]);
301 *output_samples_u8++ = s->sample[stereo];
Mike Melansond08d7142004-09-28 03:09:49302 }
303 } else {
304 while (in < buf_size) {
Justin Ruggles989bb7b2011-09-11 16:08:38305 uint8_t n = buf[in++];
Justin Rugglesb09c7ee2011-09-11 15:13:04306 if (n & 0x80) s->sample[ch] -= s->sol_table[n & 0x7F];
307 else s->sample[ch] += s->sol_table[n & 0x7F];
308 s->sample[ch] = av_clip_int16(s->sample[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08309 *output_samples++ = s->sample[ch];
Mike Melansond08d7142004-09-28 03:09:49310 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00311 ch ^= stereo;
Mike Melansond08d7142004-09-28 03:09:49312 }
313 }
314 break;
Mike Melanson3ef8be22003-09-02 04:32:02315 }
316
Justin Ruggles76db17d2011-09-11 15:51:08317 *data_size = out;
Mike Melanson3ef8be22003-09-02 04:32:02318 return buf_size;
319}
320
Diego Biurrun86714882011-09-23 19:11:15321#define DPCM_DECODER(id_, name_, long_name_) \
322AVCodec ff_ ## name_ ## _decoder = { \
323 .name = #name_, \
324 .type = AVMEDIA_TYPE_AUDIO, \
325 .id = id_, \
326 .priv_data_size = sizeof(DPCMContext), \
327 .init = dpcm_decode_init, \
328 .decode = dpcm_decode_frame, \
329 .long_name = NULL_IF_CONFIG_SMALL(long_name_), \
Mans Rullgard44adbeb2011-02-10 12:04:25330}
Mike Melanson3ef8be22003-09-02 04:32:02331
Diego Biurrun12dd57f2009-03-02 06:01:32332DPCM_DECODER(CODEC_ID_INTERPLAY_DPCM, interplay_dpcm, "DPCM Interplay");
333DPCM_DECODER(CODEC_ID_ROQ_DPCM, roq_dpcm, "DPCM id RoQ");
334DPCM_DECODER(CODEC_ID_SOL_DPCM, sol_dpcm, "DPCM Sol");
335DPCM_DECODER(CODEC_ID_XAN_DPCM, xan_dpcm, "DPCM Xan");