summaryrefslogtreecommitdiff
path: root/libavcodec/dpcm.c
diff options
context:
space:
mode:
authorMike Melanson <mike@multimedia.cx>2003-09-08 04:10:59 +0000
committerMike Melanson <mike@multimedia.cx>2003-09-08 04:10:59 +0000
commit9937e686fe86cc463577208d67431dabe74ad2ae (patch)
tree3ca4b5537f199c8f6c62a0e722793eaaf7cea286 /libavcodec/dpcm.c
parent0a5f92a120118286961a28486cb2a1d96ca47627 (diff)
New fringe codecs: WC3/Xan video, Xan DPCM, DK3 & DK4 ADPCM
Originally committed as revision 2217 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/dpcm.c')
-rw-r--r--libavcodec/dpcm.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c
index bd3ad7fd0f..958e46467d 100644
--- a/libavcodec/dpcm.c
+++ b/libavcodec/dpcm.c
@@ -21,8 +21,17 @@
* @file: dpcm.c
* Assorted DPCM (differential pulse code modulation) audio codecs
* by Mike Melanson (melanson@pcisys.net)
+ * Xan DPCM decoder by Mario Brito (mbrito@student.dei.uc.pt)
* for more information on the specific data formats, visit:
* http://www.pcisys.net/~melanson/codecs/simpleaudio.html
+ *
+ * Note about using the Xan DPCM decoder: Xan DPCM is used in AVI files
+ * found in the Wing Commander IV computer game. These AVI files contain
+ * WAVEFORMAT headers which report the audio format as 0x01: raw PCM.
+ * Clearly incorrect. To detect Xan DPCM, you will probably have to
+ * special-case your AVI demuxer to use Xan DPCM if the file uses 'Xxan'
+ * (Xan video) for its video codec. Alternately, such AVI files also contain
+ * the fourcc 'Axan' in the 'auds' chunk of the AVI header.
*/
#include "avcodec.h"
@@ -115,6 +124,9 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
int channel_number = 0;
short *output_samples = data;
int sequence_number;
+ int shift[2];
+ unsigned char byte;
+ short diff;
switch(avctx->codec->id) {
@@ -171,6 +183,40 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
s->last_delta[i] = predictor[i];
break;
+
+ case CODEC_ID_XAN_DPCM:
+ in = 0;
+ shift[0] = shift[1] = 4;
+ predictor[0] = LE_16(&buf[in]);
+ in += 2;
+ SE_16BIT(predictor[0]);
+ if (s->channels == 2) {
+ predictor[1] = LE_16(&buf[in]);
+ in += 2;
+ SE_16BIT(predictor[1]);
+ }
+
+ while (in < buf_size) {
+ byte = buf[in++];
+ diff = (byte & 0xFC) << 8;
+ if ((byte & 0x03) == 3)
+ shift[channel_number]++;
+ else
+ shift[channel_number] -= (2 * (byte & 3));
+ /* saturate the shifter to a lower limit of 0 */
+ if (shift[channel_number] < 0)
+ shift[channel_number] = 0;
+
+ diff >>= shift[channel_number];
+ predictor[channel_number] += diff;
+
+ SATURATE_S16(predictor[channel_number]);
+ output_samples[out++] = predictor[channel_number];
+
+ /* toggle channel */
+ channel_number ^= s->channels - 1;
+ }
+ break;
}
*data_size = out * sizeof(short);
@@ -198,3 +244,14 @@ AVCodec interplay_dpcm_decoder = {
NULL,
dpcm_decode_frame,
};
+
+AVCodec xan_dpcm_decoder = {
+ "xan_dpcm",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_XAN_DPCM,
+ sizeof(DPCMContext),
+ dpcm_decode_init,
+ NULL,
+ NULL,
+ dpcm_decode_frame,
+};