Added short VAG variation (SGXD type 5 found in PS3 Afrika)

This commit is contained in:
bnnm 2016-12-21 23:00:34 +01:00
parent 08d3e7c62f
commit ea7b8d2570
5 changed files with 78 additions and 16 deletions

View File

@ -62,6 +62,8 @@ void decode_baf_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspa
void decode_hevag_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_short_vag_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_xa(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void init_get_high_nibble(VGMSTREAM * vgmstream);

View File

@ -14,7 +14,6 @@ static const double VAG_f[5][2] = {
{ 98.0 / 64.0 , -55.0 / 64.0 },
{ 122.0 / 64.0 , -60.0 / 64.0 }
};
#if VAG_USE_INTEGER_TABLE
/* PS ADPCM table */
static const int8_t VAG_coefs[5][2] = {
{ 0 , 0 },
@ -23,7 +22,6 @@ static const int8_t VAG_coefs[5][2] = {
{ 98 , -55 },
{ 122 , -60 }
};
#endif
/* PSVita ADPCM table */
@ -418,7 +416,7 @@ void decode_hevag_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels
byte = read_8bit(stream->offset+(framesin*16)+2+i/2,stream->streamfile);
scale = byte & 0x0f;
}
if (scale > 7) { /* sign fix */
if (scale > 7) { /* sign extend */
scale = scale - 16;
}
@ -441,3 +439,59 @@ void decode_hevag_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels
stream->adpcm_history3_32 = hist3;
stream->adpcm_history4_32 = hist4;
}
/**
* Short VAG ADPCM, found in PS3 Afrika (SGDX type 5).
* Uses 8 byte blocks and no flag.
*/
void decode_short_vag_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t predict_nr, shift, byte;
int16_t scale = 0;
int32_t sample;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
int i, sample_count;
int framesin = first_sample / 6;
/* 2 byte header: predictor = 1st, shift = 2nd */
byte = (uint8_t)read_8bit(stream->offset+framesin*8+0,stream->streamfile);
predict_nr = byte >> 4;
shift = byte & 0x0f;
first_sample = first_sample % 6;
for (i = first_sample, sample_count = 0; i < first_sample + samples_to_do; i++, sample_count += channelspacing) {
sample = 0;
if (predict_nr < 5) {
if (i & 1) {/* odd/even nibble */
scale = byte >> 4;
} else {
byte = (uint8_t)read_8bit(stream->offset+(framesin*8)+1+i/2,stream->streamfile);
scale = (byte & 0x0f);
}
/*if (scale > 7) {
scale = scale - 16;
}*/
scale = scale << 12; /* shift + sign extend only if scale is int16_t */
sample = (hist1 * VAG_coefs[predict_nr][0] +
hist2 * VAG_coefs[predict_nr][1] ) / 64;
sample = sample + (scale >> shift);
}
outbuf[sample_count] = clamp16(sample);
hist2 = hist1;
hist1 = sample;
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_history2_32 = hist2;
}

View File

@ -194,21 +194,12 @@ VGMSTREAM * init_vgmstream_ps3_sgdx(STREAMFILE *streamFile) {
break;
}
#endif
case 0x05: /* todo PCM? */
goto fail;
/*
vgmstream->coding_type = coding_PCM16LE;
if (vgmstream->channels > 1) {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x1;
} else {
vgmstream->layout_type = layout_none;
}
case 0x05: /* Short VAG ADPCM */
vgmstream->coding_type = coding_SHORT_VAG_ADPCM;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x4;
break;
*/
#ifdef VGM_USE_FFMPEG
case 0x06: /* AC3 */

View File

@ -1035,6 +1035,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_HEVAG_ADPCM:
case coding_XA:
return 28;
case coding_SHORT_VAG_ADPCM:
return 6;
case coding_XBOX:
case coding_INT_XBOX:
case coding_BAF_ADPCM:
@ -1164,6 +1166,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_invert_PSX:
case coding_NDS_PROCYON:
return 16;
case coding_SHORT_VAG_ADPCM:
return 4;
case coding_XA:
return 14*vgmstream->channels;
case coding_XBOX:
@ -1444,6 +1448,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do);
}
break;
case coding_SHORT_VAG_ADPCM:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_short_vag_adpcm(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do);
}
break;
case coding_XA:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_xa(vgmstream,buffer+samples_written*vgmstream->channels+chan,
@ -1974,6 +1985,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case coding_HEVAG_ADPCM:
snprintf(temp,TEMPSIZE,"PSVita HEVAG ADPCM");
break;
case coding_SHORT_VAG_ADPCM:
snprintf(temp,TEMPSIZE,"Short VAG (SGXD type 5) ADPCM");
break;
case coding_XA:
snprintf(temp,TEMPSIZE,"CD-ROM XA 4-bit ADPCM");
break;

View File

@ -94,6 +94,7 @@ typedef enum {
coding_FFXI, /* FF XI PSX-ish ADPCM */
coding_BAF_ADPCM, /* Bizarre Creations PSX-ish ADPCM */
coding_HEVAG_ADPCM, /* PSVita games */
coding_SHORT_VAG_ADPCM, /* SGXD type 5 (PS3 Afrika) */
coding_XA, /* PSX CD-XA */
coding_XBOX, /* XBOX IMA */
coding_INT_XBOX, /* XBOX 'real interleaved' IMA */