mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
Creative ADPCM decoder, format 0x200, courtesy of Konstantin Shishkov
Originally committed as revision 3589 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
8bcb147f54
commit
b3bfb29980
@ -3,6 +3,7 @@ version <next>
|
|||||||
- IBM Ultimotion (ULTI) video decoder
|
- IBM Ultimotion (ULTI) video decoder
|
||||||
- Sierra Online audio file demuxer and decoder
|
- Sierra Online audio file demuxer and decoder
|
||||||
- Apple QuickDraw (qdrw) video decoder
|
- Apple QuickDraw (qdrw) video decoder
|
||||||
|
- Creative ADPCM audio decoder
|
||||||
|
|
||||||
version 0.4.9-pre1:
|
version 0.4.9-pre1:
|
||||||
|
|
||||||
|
@ -805,6 +805,7 @@ solutions.
|
|||||||
@tab used in Sega Dreamcast games
|
@tab used in Sega Dreamcast games
|
||||||
@item Electronic Arts ADPCM @tab @tab X
|
@item Electronic Arts ADPCM @tab @tab X
|
||||||
@tab used in various EA titles
|
@tab used in various EA titles
|
||||||
|
@item Creative ADPCM @tab @tab X
|
||||||
@item RA144 @tab @tab X
|
@item RA144 @tab @tab X
|
||||||
@tab Real 14400 bit/s codec
|
@tab Real 14400 bit/s codec
|
||||||
@item RA288 @tab @tab X
|
@item RA288 @tab @tab X
|
||||||
|
@ -103,6 +103,11 @@ static int ea_adpcm_table[] = {
|
|||||||
3, 4, 7, 8, 10, 11, 0, -1, -3, -4
|
3, 4, 7, 8, 10, 11, 0, -1, -3, -4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int ct_adpcm_table[8] = {
|
||||||
|
0x00E6, 0x00E6, 0x00E6, 0x00E6,
|
||||||
|
0x0133, 0x0199, 0x0200, 0x0266
|
||||||
|
};
|
||||||
|
|
||||||
/* end of tables */
|
/* end of tables */
|
||||||
|
|
||||||
typedef struct ADPCMChannelStatus {
|
typedef struct ADPCMChannelStatus {
|
||||||
@ -361,6 +366,9 @@ static int adpcm_decode_init(AVCodecContext * avctx)
|
|||||||
c->status[0].step = c->status[1].step = 0;
|
c->status[0].step = c->status[1].step = 0;
|
||||||
|
|
||||||
switch(avctx->codec->id) {
|
switch(avctx->codec->id) {
|
||||||
|
case CODEC_ID_ADPCM_CT:
|
||||||
|
c->status[0].step = c->status[1].step = 511;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -411,6 +419,37 @@ static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, char nibble)
|
|||||||
return (short)predictor;
|
return (short)predictor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline short adpcm_ct_expand_nibble(ADPCMChannelStatus *c, char nibble)
|
||||||
|
{
|
||||||
|
int predictor;
|
||||||
|
int sign, delta, diff;
|
||||||
|
int new_step;
|
||||||
|
|
||||||
|
sign = nibble & 8;
|
||||||
|
delta = nibble & 7;
|
||||||
|
/* perform direct multiplication instead of series of jumps proposed by
|
||||||
|
* the reference ADPCM implementation since modern CPUs can do the mults
|
||||||
|
* quickly enough */
|
||||||
|
diff = ((2 * delta + 1) * c->step) >> 3;
|
||||||
|
predictor = c->predictor;
|
||||||
|
/* predictor update is not so trivial: predictor is multiplied on 254/256 before updating */
|
||||||
|
if(sign)
|
||||||
|
predictor = ((predictor * 254) >> 8) - diff;
|
||||||
|
else
|
||||||
|
predictor = ((predictor * 254) >> 8) + diff;
|
||||||
|
/* calculate new step and clamp it to range 511..32767 */
|
||||||
|
new_step = (ct_adpcm_table[nibble & 7] * c->step) >> 8;
|
||||||
|
c->step = new_step;
|
||||||
|
if(c->step < 511)
|
||||||
|
c->step = 511;
|
||||||
|
if(c->step > 32767)
|
||||||
|
c->step = 32767;
|
||||||
|
|
||||||
|
CLAMP_TO_SHORT(predictor);
|
||||||
|
c->predictor = predictor;
|
||||||
|
return (short)predictor;
|
||||||
|
}
|
||||||
|
|
||||||
static void xa_decode(short *out, const unsigned char *in,
|
static void xa_decode(short *out, const unsigned char *in,
|
||||||
ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc)
|
ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc)
|
||||||
{
|
{
|
||||||
@ -840,6 +879,22 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
|
|||||||
src++;
|
src++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CODEC_ID_ADPCM_CT:
|
||||||
|
while (src < buf + buf_size) {
|
||||||
|
if (st) {
|
||||||
|
*samples++ = adpcm_ct_expand_nibble(&c->status[0],
|
||||||
|
(src[0] >> 4) & 0x0F);
|
||||||
|
*samples++ = adpcm_ct_expand_nibble(&c->status[1],
|
||||||
|
src[0] & 0x0F);
|
||||||
|
} else {
|
||||||
|
*samples++ = adpcm_ct_expand_nibble(&c->status[0],
|
||||||
|
(src[0] >> 4) & 0x0F);
|
||||||
|
*samples++ = adpcm_ct_expand_nibble(&c->status[0],
|
||||||
|
src[0] & 0x0F);
|
||||||
|
}
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -895,5 +950,6 @@ ADPCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm);
|
|||||||
ADPCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
|
ADPCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
|
||||||
ADPCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
|
ADPCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
|
||||||
ADPCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
|
ADPCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
|
||||||
|
ADPCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct);
|
||||||
|
|
||||||
#undef ADPCM_CODEC
|
#undef ADPCM_CODEC
|
||||||
|
@ -223,6 +223,7 @@ PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
|
|||||||
PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
|
PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
|
||||||
PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
|
PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
|
||||||
PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726);
|
PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726);
|
||||||
|
PCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct);
|
||||||
|
|
||||||
#undef PCM_CODEC
|
#undef PCM_CODEC
|
||||||
|
|
||||||
|
@ -128,6 +128,7 @@ enum CodecID {
|
|||||||
CODEC_ID_ADPCM_ADX,
|
CODEC_ID_ADPCM_ADX,
|
||||||
CODEC_ID_ADPCM_EA,
|
CODEC_ID_ADPCM_EA,
|
||||||
CODEC_ID_ADPCM_G726,
|
CODEC_ID_ADPCM_G726,
|
||||||
|
CODEC_ID_ADPCM_CT,
|
||||||
|
|
||||||
/* AMR */
|
/* AMR */
|
||||||
CODEC_ID_AMR_NB,
|
CODEC_ID_AMR_NB,
|
||||||
@ -1916,6 +1917,7 @@ PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa);
|
|||||||
PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
|
PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx);
|
||||||
PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
|
PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea);
|
||||||
PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726);
|
PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726);
|
||||||
|
PCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct);
|
||||||
|
|
||||||
#undef PCM_CODEC
|
#undef PCM_CODEC
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ const CodecTag codec_wav_tags[] = {
|
|||||||
{ CODEC_ID_VORBIS, ('V'<<8)+'o' }, //HACK/FIXME, does vorbis in WAV/AVI have an (in)official id?
|
{ CODEC_ID_VORBIS, ('V'<<8)+'o' }, //HACK/FIXME, does vorbis in WAV/AVI have an (in)official id?
|
||||||
{ CODEC_ID_SONIC, 0x2048 },
|
{ CODEC_ID_SONIC, 0x2048 },
|
||||||
{ CODEC_ID_SONIC_LS, 0x2048 },
|
{ CODEC_ID_SONIC_LS, 0x2048 },
|
||||||
|
{ CODEC_ID_ADPCM_CT, 0x200 },
|
||||||
{ 0, 0 },
|
{ 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user