summaryrefslogtreecommitdiff
path: root/libavcodec/adpcm.c
diff options
context:
space:
mode:
authorMike Melanson <mike@multimedia.cx>2003-10-15 03:20:40 +0000
committerMike Melanson <mike@multimedia.cx>2003-10-15 03:20:40 +0000
commitfc3847771595fb52e01363d64b0b6b996ef0dfdc (patch)
treecd460d7005a53b11615beaf894bf8ecf4cdf10b8 /libavcodec/adpcm.c
parentf19af812a32c1398d48c3550d11dbc6aafbb2bfc (diff)
activate the XA and ADX ADPCM codecs
Originally committed as revision 2385 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/adpcm.c')
-rw-r--r--libavcodec/adpcm.c100
1 files changed, 98 insertions, 2 deletions
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 68a5c6f22f..9e5312663c 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -21,9 +21,10 @@
/**
* @file adpcm.c
* ADPCM codecs.
- * First version by Francois Revol revol@free.fr
+ * First version by Francois Revol (revol@free.fr)
* Fringe ADPCM codecs (e.g., DK3, DK4, Westwood)
* by Mike Melanson (melanson@pcisys.net)
+ * CD-ROM XA ADPCM codec by BERO
*
* Features and limitations:
*
@@ -34,6 +35,11 @@
* XAnim sources (xa_codec.c) http://www.rasnaimaging.com/people/lapus/download.html
* http://www.cs.ucla.edu/~leec/mediabench/applications.html
* SoX source code http://home.sprynet.com/~cbagwell/sox.html
+ *
+ * CD-ROM XA:
+ * http://ku-www.ss.titech.ac.jp/~yatsushi/xaadpcm.html
+ * vagpack & depack http://homepages.compuserve.de/bITmASTER32/psx-index.html
+ * readstr http://www.geocities.co.jp/Playtown/2004/
*/
#define BLKSIZE 1024
@@ -67,7 +73,7 @@ static const int step_table[89] = {
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};
-/* Those are for MS-ADPCM */
+/* These are for MS-ADPCM */
/* AdaptationTable[], AdaptCoeff1[], and AdaptCoeff2[] are from libsndfile */
static const int AdaptationTable[] = {
230, 230, 230, 230, 307, 409, 512, 614,
@@ -82,6 +88,15 @@ static const int AdaptCoeff2[] = {
0, -256, 0, 64, 0, -208, -232
};
+/* These are for CD-ROM XA ADPCM */
+const static int xa_adpcm_table[5][2] = {
+ { 0, 0 },
+ { 60, 0 },
+ { 115, -52 },
+ { 98, -55 },
+ { 122, -60 }
+};
+
/* end of tables */
typedef struct ADPCMChannelStatus {
@@ -355,6 +370,74 @@ static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, char nibble)
return (short)predictor;
}
+static void xa_decode(short *out, const unsigned char *in,
+ ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc)
+{
+ int i, j;
+ int shift,filter,f0,f1;
+ int s_1,s_2;
+ int d,s,t;
+
+ for(i=0;i<4;i++) {
+
+ shift = 12 - (in[4+i*2] & 15);
+ filter = in[4+i*2] >> 4;
+ f0 = xa_adpcm_table[filter][0];
+ f1 = xa_adpcm_table[filter][1];
+
+ s_1 = left->sample1;
+ s_2 = left->sample2;
+
+ for(j=0;j<28;j++) {
+ d = in[16+i+j*4];
+
+ t = (signed char)(d<<4)>>4;
+ s = ( t<<shift ) + ((s_1*f0 + s_2*f1+32)>>6);
+ CLAMP_TO_SHORT(s);
+ *out = s;
+ out += inc;
+ s_2 = s_1;
+ s_1 = s;
+ }
+
+ if (inc==2) { /* stereo */
+ left->sample1 = s_1;
+ left->sample2 = s_2;
+ s_1 = right->sample1;
+ s_2 = right->sample2;
+ out = out + 1 - 28*2;
+ }
+
+ shift = 12 - (in[5+i*2] & 15);
+ filter = in[5+i*2] >> 4;
+
+ f0 = xa_adpcm_table[filter][0];
+ f1 = xa_adpcm_table[filter][1];
+
+ for(j=0;j<28;j++) {
+ d = in[16+i+j*4];
+
+ t = (signed char)d >> 4;
+ s = ( t<<shift ) + ((s_1*f0 + s_2*f1+32)>>6);
+ CLAMP_TO_SHORT(s);
+ *out = s;
+ out += inc;
+ s_2 = s_1;
+ s_1 = s;
+ }
+
+ if (inc==2) { /* stereo */
+ right->sample1 = s_1;
+ right->sample2 = s_2;
+ out -= 1;
+ } else {
+ left->sample1 = s_1;
+ left->sample2 = s_2;
+ }
+ }
+}
+
+
/* DK3 ADPCM support macro */
#define DK3_GET_NEXT_NIBBLE() \
if (decode_top_nibble_next) \
@@ -679,6 +762,17 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
src++;
}
break;
+ case CODEC_ID_ADPCM_XA:
+ c->status[0].sample1 = c->status[0].sample2 =
+ c->status[1].sample1 = c->status[1].sample2 = 0;
+ while (buf_size >= 128) {
+ xa_decode(samples, src, &c->status[0], &c->status[1],
+ avctx->channels);
+ src += 128;
+ samples += 28 * 8;
+ buf_size -= 128;
+ }
+ break;
default:
*data_size = 0;
return -1;
@@ -731,5 +825,7 @@ ADPCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4);
ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws);
ADPCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms);
ADPCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm);
+ADPCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
+ADPCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
#undef ADPCM_CODEC