blob: a024671fa268df623cb20ad0ecb08936a0fe9127 [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 Melanson9937e682003-09-08 04:10:59178 int shift[2];
Mike Melanson9937e682003-09-08 04:10:59179 short diff;
Mike Melanson3ef8be22003-09-02 04:32:02180
Mike Melansonc89c1d22004-01-31 17:30:28181 if (!buf_size)
182 return 0;
183
Justin Ruggles76db17d2011-09-11 15:51:08184 /* calculate output size */
185 switch(avctx->codec->id) {
186 case CODEC_ID_ROQ_DPCM:
187 out = buf_size - 8;
188 break;
189 case CODEC_ID_INTERPLAY_DPCM:
190 out = buf_size - 6 - s->channels;
191 break;
192 case CODEC_ID_XAN_DPCM:
193 out = buf_size - 2 * s->channels;
194 break;
195 case CODEC_ID_SOL_DPCM:
196 if (avctx->codec_tag != 3)
197 out = buf_size * 2;
198 else
199 out = buf_size;
200 break;
201 }
202 out *= av_get_bytes_per_sample(avctx->sample_fmt);
203
204 if (*data_size < out) {
205 av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
206 return AVERROR(EINVAL);
207 }
Kostya Shishkova2085a72007-09-22 09:21:43208
Mike Melanson3ef8be22003-09-02 04:32:02209 switch(avctx->codec->id) {
210
211 case CODEC_ID_ROQ_DPCM:
Justin Ruggles3db8db42011-09-11 15:19:00212 if (stereo) {
Mike Melanson3ef8be22003-09-02 04:32:02213 predictor[0] = buf[7] << 8;
214 predictor[1] = buf[6] << 8;
Justin Ruggles3db8db42011-09-11 15:19:00215 } else {
216 predictor[0] = AV_RL16(&buf[6]);
Mike Melanson3ef8be22003-09-02 04:32:02217 }
218 SE_16BIT(predictor[0]);
219 SE_16BIT(predictor[1]);
220
221 /* decode the samples */
Justin Ruggles76db17d2011-09-11 15:51:08222 for (in = 8; in < buf_size; in++) {
Justin Rugglesb09c7ee2011-09-11 15:13:04223 predictor[ch] += s->roq_square_array[buf[in]];
224 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08225 *output_samples++ = predictor[ch];
Mike Melanson3ef8be22003-09-02 04:32:02226
227 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00228 ch ^= stereo;
Mike Melanson3ef8be22003-09-02 04:32:02229 }
230 break;
231
232 case CODEC_ID_INTERPLAY_DPCM:
Mike Melansonb10529b2003-09-19 04:41:02233 in = 6; /* skip over the stream mask and stream length */
Alex Beregszaszifead30d2007-01-19 22:12:59234 predictor[0] = AV_RL16(&buf[in]);
Mike Melansonb10529b2003-09-19 04:41:02235 in += 2;
236 SE_16BIT(predictor[0])
Justin Ruggles76db17d2011-09-11 15:51:08237 *output_samples++ = predictor[0];
Justin Ruggles3db8db42011-09-11 15:19:00238 if (stereo) {
Alex Beregszaszifead30d2007-01-19 22:12:59239 predictor[1] = AV_RL16(&buf[in]);
Mike Melanson3ef8be22003-09-02 04:32:02240 in += 2;
Mike Melansonb10529b2003-09-19 04:41:02241 SE_16BIT(predictor[1])
Justin Ruggles76db17d2011-09-11 15:51:08242 *output_samples++ = predictor[1];
Mike Melanson3ef8be22003-09-02 04:32:02243 }
244
245 while (in < buf_size) {
Justin Rugglesb09c7ee2011-09-11 15:13:04246 predictor[ch] += interplay_delta_table[buf[in++]];
247 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08248 *output_samples++ = predictor[ch];
Mike Melanson3ef8be22003-09-02 04:32:02249
250 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00251 ch ^= stereo;
Mike Melanson3ef8be22003-09-02 04:32:02252 }
Mike Melanson3ef8be22003-09-02 04:32:02253 break;
Mike Melanson9937e682003-09-08 04:10:59254
255 case CODEC_ID_XAN_DPCM:
256 in = 0;
257 shift[0] = shift[1] = 4;
Alex Beregszaszifead30d2007-01-19 22:12:59258 predictor[0] = AV_RL16(&buf[in]);
Mike Melanson9937e682003-09-08 04:10:59259 in += 2;
260 SE_16BIT(predictor[0]);
Justin Ruggles3db8db42011-09-11 15:19:00261 if (stereo) {
Alex Beregszaszifead30d2007-01-19 22:12:59262 predictor[1] = AV_RL16(&buf[in]);
Mike Melanson9937e682003-09-08 04:10:59263 in += 2;
264 SE_16BIT(predictor[1]);
265 }
266
267 while (in < buf_size) {
Justin Ruggles989bb7b2011-09-11 16:08:38268 uint8_t n = buf[in++];
269 diff = (n & 0xFC) << 8;
270 if ((n & 0x03) == 3)
Justin Rugglesb09c7ee2011-09-11 15:13:04271 shift[ch]++;
Mike Melanson9937e682003-09-08 04:10:59272 else
Justin Ruggles989bb7b2011-09-11 16:08:38273 shift[ch] -= (2 * (n & 3));
Mike Melanson9937e682003-09-08 04:10:59274 /* saturate the shifter to a lower limit of 0 */
Justin Rugglesb09c7ee2011-09-11 15:13:04275 if (shift[ch] < 0)
276 shift[ch] = 0;
Mike Melanson9937e682003-09-08 04:10:59277
Justin Rugglesb09c7ee2011-09-11 15:13:04278 diff >>= shift[ch];
279 predictor[ch] += diff;
Mike Melanson9937e682003-09-08 04:10:59280
Justin Rugglesb09c7ee2011-09-11 15:13:04281 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08282 *output_samples++ = predictor[ch];
Mike Melanson9937e682003-09-08 04:10:59283
284 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00285 ch ^= stereo;
Mike Melanson9937e682003-09-08 04:10:59286 }
287 break;
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");