blob: cb128affed710d3e7a79888549578db05ffe9288 [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"
Justin Ruggles1de84012011-09-11 16:24:0342#include "bytestream.h"
Mike Melanson3ef8be22003-09-02 04:32:0243
44typedef struct DPCMContext {
45 int channels;
46 short roq_square_array[256];
Justin Ruggles04b24cf2011-09-11 16:04:4647 int sample[2]; ///< previous sample (for SOL_DPCM)
Stefan Huehner62a05b52006-07-06 13:53:0748 const int *sol_table;//for SOL_DPCM
Mike Melanson3ef8be22003-09-02 04:32:0249} DPCMContext;
50
Stefan Gehrercf2baeb2008-06-24 20:01:3151static const int interplay_delta_table[] = {
Mike Melanson3ef8be22003-09-02 04:32:0252 0, 1, 2, 3, 4, 5, 6, 7,
53 8, 9, 10, 11, 12, 13, 14, 15,
54 16, 17, 18, 19, 20, 21, 22, 23,
55 24, 25, 26, 27, 28, 29, 30, 31,
56 32, 33, 34, 35, 36, 37, 38, 39,
57 40, 41, 42, 43, 47, 51, 56, 61,
58 66, 72, 79, 86, 94, 102, 112, 122,
59 133, 145, 158, 173, 189, 206, 225, 245,
60 267, 292, 318, 348, 379, 414, 452, 493,
61 538, 587, 640, 699, 763, 832, 908, 991,
62 1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993,
63 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008,
64 4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059,
65 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206,
66 17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589,
67 -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1,
68 1, 1, 5481, 10503, 15105, 19322, 23186, 26728,
69 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298,
70 -17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597,
71 -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772,
72 -4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373,
73 -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180,
74 -1081, -991, -908, -832, -763, -699, -640, -587,
75 -538, -493, -452, -414, -379, -348, -318, -292,
76 -267, -245, -225, -206, -189, -173, -158, -145,
77 -133, -122, -112, -102, -94, -86, -79, -72,
78 -66, -61, -56, -51, -47, -43, -42, -41,
79 -40, -39, -38, -37, -36, -35, -34, -33,
80 -32, -31, -30, -29, -28, -27, -26, -25,
81 -24, -23, -22, -21, -20, -19, -18, -17,
82 -16, -15, -14, -13, -12, -11, -10, -9,
83 -8, -7, -6, -5, -4, -3, -2, -1
84
85};
86
Justin Ruggles4bad4642011-09-11 16:37:1787static const int sol_table_old[16] = {
88 0x0, 0x1, 0x2, 0x3, 0x6, 0xA, 0xF, 0x15,
89 -0x15, -0xF, -0xA, -0x6, -0x3, -0x2, -0x1, 0x0
90};
Mike Melansond08d7142004-09-28 03:09:4991
Justin Ruggles4bad4642011-09-11 16:37:1792static const int sol_table_new[16] = {
93 0x0, 0x1, 0x2, 0x3, 0x6, 0xA, 0xF, 0x15,
94 0x0, -0x1, -0x2, -0x3, -0x6, -0xA, -0xF, -0x15
95};
Diego Biurrun115329f2005-12-17 18:14:3896
Stefan Huehner62a05b52006-07-06 13:53:0797static const int sol_table_16[128] = {
Mike Melansond08d7142004-09-28 03:09:4998 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
99 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
100 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
101 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
102 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
103 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
104 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
105 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
106 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
107 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
108 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
109 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
110 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
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;
Justin Ruggles4bad4642011-09-11 16:37:17129 s->roq_square_array[i ] = square;
Mike Melanson3ef8be22003-09-02 04:32:02130 s->roq_square_array[i + 128] = -square;
131 }
132 break;
133
Mike Melansond08d7142004-09-28 03:09:49134 case CODEC_ID_SOL_DPCM:
135 switch(avctx->codec_tag){
136 case 1:
Justin Ruggles4bad4642011-09-11 16:37:17137 s->sol_table = sol_table_old;
Mike Melansond08d7142004-09-28 03:09:49138 s->sample[0] = s->sample[1] = 0x80;
139 break;
140 case 2:
Justin Ruggles4bad4642011-09-11 16:37:17141 s->sol_table = sol_table_new;
Mike Melansond08d7142004-09-28 03:09:49142 s->sample[0] = s->sample[1] = 0x80;
143 break;
144 case 3:
Justin Ruggles4bad4642011-09-11 16:37:17145 s->sol_table = sol_table_16;
Mike Melansond08d7142004-09-28 03:09:49146 break;
147 default:
148 av_log(avctx, AV_LOG_ERROR, "Unknown SOL subcodec\n");
149 return -1;
150 }
151 break;
Diego Biurrun115329f2005-12-17 18:14:38152
Mike Melanson3ef8be22003-09-02 04:32:02153 default:
154 break;
155 }
156
Justin Ruggles04b24cf2011-09-11 16:04:46157 if (avctx->codec->id == CODEC_ID_SOL_DPCM && avctx->codec_tag != 3)
158 avctx->sample_fmt = AV_SAMPLE_FMT_U8;
159 else
160 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
161
Mike Melanson3ef8be22003-09-02 04:32:02162 return 0;
163}
164
Justin Ruggles4bad4642011-09-11 16:37:17165
166static int dpcm_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
Thilo Borgmann7a00bba2009-04-07 15:59:50167 AVPacket *avpkt)
Mike Melanson3ef8be22003-09-02 04:32:02168{
Thilo Borgmann7a00bba2009-04-07 15:59:50169 const uint8_t *buf = avpkt->data;
170 int buf_size = avpkt->size;
Justin Ruggles1de84012011-09-11 16:24:03171 const uint8_t *buf_end = buf + buf_size;
Mike Melanson3ef8be22003-09-02 04:32:02172 DPCMContext *s = avctx->priv_data;
Justin Ruggles1de84012011-09-11 16:24:03173 int 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 Ruggles1de84012011-09-11 16:24:03210 buf += 6;
211
Justin Ruggles3db8db42011-09-11 15:19:00212 if (stereo) {
Justin Ruggles1de84012011-09-11 16:24:03213 predictor[1] = (int16_t)(bytestream_get_byte(&buf) << 8);
214 predictor[0] = (int16_t)(bytestream_get_byte(&buf) << 8);
Justin Ruggles3db8db42011-09-11 15:19:00215 } else {
Justin Ruggles1de84012011-09-11 16:24:03216 predictor[0] = (int16_t)bytestream_get_le16(&buf);
Mike Melanson3ef8be22003-09-02 04:32:02217 }
Mike Melanson3ef8be22003-09-02 04:32:02218
219 /* decode the samples */
Justin Ruggles1de84012011-09-11 16:24:03220 while (buf < buf_end) {
221 predictor[ch] += s->roq_square_array[*buf++];
Justin Ruggles4bad4642011-09-11 16:37:17222 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:
Justin Ruggles1de84012011-09-11 16:24:03231 buf += 6; /* skip over the stream mask and stream length */
232
233 for (ch = 0; ch < s->channels; ch++) {
234 predictor[ch] = (int16_t)bytestream_get_le16(&buf);
235 *output_samples++ = predictor[ch];
Mike Melanson3ef8be22003-09-02 04:32:02236 }
237
Justin Ruggles1de84012011-09-11 16:24:03238 ch = 0;
239 while (buf < buf_end) {
240 predictor[ch] += interplay_delta_table[*buf++];
Justin Ruggles4bad4642011-09-11 16:37:17241 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08242 *output_samples++ = predictor[ch];
Mike Melanson3ef8be22003-09-02 04:32:02243
244 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00245 ch ^= stereo;
Mike Melanson3ef8be22003-09-02 04:32:02246 }
Mike Melanson3ef8be22003-09-02 04:32:02247 break;
Mike Melanson9937e682003-09-08 04:10:59248
249 case CODEC_ID_XAN_DPCM:
Justin Rugglesfc6faee2011-09-11 16:13:13250 {
251 int shift[2] = { 4, 4 };
Mike Melanson9937e682003-09-08 04:10:59252
Justin Ruggles1de84012011-09-11 16:24:03253 for (ch = 0; ch < s->channels; ch++)
254 predictor[ch] = (int16_t)bytestream_get_le16(&buf);
255
256 ch = 0;
257 while (buf < buf_end) {
258 uint8_t n = *buf++;
Justin Rugglesfc6faee2011-09-11 16:13:13259 int16_t diff = (n & 0xFC) << 8;
Justin Ruggles989bb7b2011-09-11 16:08:38260 if ((n & 0x03) == 3)
Justin Rugglesb09c7ee2011-09-11 15:13:04261 shift[ch]++;
Mike Melanson9937e682003-09-08 04:10:59262 else
Justin Ruggles989bb7b2011-09-11 16:08:38263 shift[ch] -= (2 * (n & 3));
Mike Melanson9937e682003-09-08 04:10:59264 /* saturate the shifter to a lower limit of 0 */
Justin Rugglesb09c7ee2011-09-11 15:13:04265 if (shift[ch] < 0)
266 shift[ch] = 0;
Mike Melanson9937e682003-09-08 04:10:59267
Justin Rugglesb09c7ee2011-09-11 15:13:04268 diff >>= shift[ch];
269 predictor[ch] += diff;
Mike Melanson9937e682003-09-08 04:10:59270
Justin Rugglesb09c7ee2011-09-11 15:13:04271 predictor[ch] = av_clip_int16(predictor[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08272 *output_samples++ = predictor[ch];
Mike Melanson9937e682003-09-08 04:10:59273
274 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00275 ch ^= stereo;
Mike Melanson9937e682003-09-08 04:10:59276 }
277 break;
Justin Rugglesfc6faee2011-09-11 16:13:13278 }
Mike Melansond08d7142004-09-28 03:09:49279 case CODEC_ID_SOL_DPCM:
Mike Melansond08d7142004-09-28 03:09:49280 if (avctx->codec_tag != 3) {
Justin Ruggles04b24cf2011-09-11 16:04:46281 uint8_t *output_samples_u8 = data;
Justin Ruggles1de84012011-09-11 16:24:03282 while (buf < buf_end) {
283 uint8_t n = *buf++;
Justin Ruggles04b24cf2011-09-11 16:04:46284
285 s->sample[0] += s->sol_table[n >> 4];
286 s->sample[0] = av_clip_uint8(s->sample[0]);
287 *output_samples_u8++ = s->sample[0];
288
289 s->sample[stereo] += s->sol_table[n & 0x0F];
290 s->sample[stereo] = av_clip_uint8(s->sample[stereo]);
291 *output_samples_u8++ = s->sample[stereo];
Mike Melansond08d7142004-09-28 03:09:49292 }
293 } else {
Justin Ruggles1de84012011-09-11 16:24:03294 while (buf < buf_end) {
295 uint8_t n = *buf++;
Justin Rugglesb09c7ee2011-09-11 15:13:04296 if (n & 0x80) s->sample[ch] -= s->sol_table[n & 0x7F];
Justin Ruggles4bad4642011-09-11 16:37:17297 else s->sample[ch] += s->sol_table[n & 0x7F];
Justin Rugglesb09c7ee2011-09-11 15:13:04298 s->sample[ch] = av_clip_int16(s->sample[ch]);
Justin Ruggles76db17d2011-09-11 15:51:08299 *output_samples++ = s->sample[ch];
Mike Melansond08d7142004-09-28 03:09:49300 /* toggle channel */
Justin Ruggles3db8db42011-09-11 15:19:00301 ch ^= stereo;
Mike Melansond08d7142004-09-28 03:09:49302 }
303 }
304 break;
Mike Melanson3ef8be22003-09-02 04:32:02305 }
306
Justin Ruggles76db17d2011-09-11 15:51:08307 *data_size = out;
Mike Melanson3ef8be22003-09-02 04:32:02308 return buf_size;
309}
310
Diego Biurrun86714882011-09-23 19:11:15311#define DPCM_DECODER(id_, name_, long_name_) \
312AVCodec ff_ ## name_ ## _decoder = { \
313 .name = #name_, \
314 .type = AVMEDIA_TYPE_AUDIO, \
315 .id = id_, \
316 .priv_data_size = sizeof(DPCMContext), \
317 .init = dpcm_decode_init, \
318 .decode = dpcm_decode_frame, \
319 .long_name = NULL_IF_CONFIG_SMALL(long_name_), \
Mans Rullgard44adbeb2011-02-10 12:04:25320}
Mike Melanson3ef8be22003-09-02 04:32:02321
Diego Biurrun12dd57f2009-03-02 06:01:32322DPCM_DECODER(CODEC_ID_INTERPLAY_DPCM, interplay_dpcm, "DPCM Interplay");
Justin Ruggles4bad4642011-09-11 16:37:17323DPCM_DECODER(CODEC_ID_ROQ_DPCM, roq_dpcm, "DPCM id RoQ");
324DPCM_DECODER(CODEC_ID_SOL_DPCM, sol_dpcm, "DPCM Sol");
325DPCM_DECODER(CODEC_ID_XAN_DPCM, xan_dpcm, "DPCM Xan");