Add NGC DSP subinterleave decoder

Meant to replace layout_interleave_byte
This commit is contained in:
bnnm 2017-12-06 21:04:04 +01:00
parent 9c3adeba8f
commit 98b4f8c5b1
5 changed files with 71 additions and 2 deletions

View File

@ -38,6 +38,7 @@ size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFi
/* ngc_dsp_decoder */
void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ngc_dsp_subint(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int interleave);
void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem);
size_t dsp_bytes_to_samples(size_t bytes, int channels);
int32_t dsp_nibbles_to_samples(int32_t nibbles);

View File

@ -72,6 +72,61 @@ void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels
stream->adpcm_history2_16 = hist2;
}
/* read from memory rather than a file */
static void decode_ngc_dsp_subint_internal(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem) {
int i=first_sample;
int32_t sample_count;
int8_t header = mem[0];
int32_t scale = 1 << (header & 0xf);
int coef_index = (header >> 4) & 0xf;
int32_t hist1 = stream->adpcm_history1_16;
int32_t hist2 = stream->adpcm_history2_16;
int coef1 = stream->adpcm_coef[coef_index*2];
int coef2 = stream->adpcm_coef[coef_index*2+1];
first_sample = first_sample%14;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = mem[1 + i/2];
outbuf[sample_count] = clamp16((
(((i&1?
get_low_nibble_signed(sample_byte):
get_high_nibble_signed(sample_byte)
) * scale)<<11) + 1024 +
(coef1 * hist1 + coef2 * hist2))>>11
);
hist2 = hist1;
hist1 = outbuf[sample_count];
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_history2_16 = hist2;
}
/* decode DSP with byte-interleaved frames (ex. 0x08: 1122112211221122) */
void decode_ngc_dsp_subint(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int interleave) {
uint8_t sample_data[0x08];
int i;
int framesin = first_sample/14;
for (i=0; i < 0x08; i++) {
/* base + current frame + subint section + subint byte + channel adjust */
sample_data[i] = read_8bit(
stream->offset
+ framesin*(0x08*channelspacing)
+ i/interleave * interleave * channelspacing
+ i%interleave
+ interleave * channel, stream->streamfile);
}
decode_ngc_dsp_subint_internal(stream, outbuf, channelspacing, first_sample, samples_to_do, sample_data);
}
/*
* The original DSP spec uses nibble counts for loop points, and some
* variants don't have a proper sample count, so we (who are interested

View File

@ -429,6 +429,7 @@ static const coding_info coding_info_list[] = {
{coding_CRI_ADX_enc_9, "CRI ADX 4-bit ADPCM (type 9 encryption)"},
{coding_NGC_DSP, "Nintendo DSP 4-bit ADPCM"},
{coding_NGC_DSP_subint, "Nintendo DSP 4-bit ADPCM (subinterleave)"},
{coding_NGC_DTK, "Nintendo DTK 4-bit ADPCM"},
{coding_NGC_AFC, "Nintendo AFC 4-bit ADPCM"},

View File

@ -994,6 +994,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_L5_555:
return 32;
case coding_NGC_DSP:
case coding_NGC_DSP_subint:
return 14;
case coding_PCM16LE:
case coding_PCM16LE_XOR_int:
@ -1146,7 +1147,9 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_L5_555:
return 18;
case coding_NGC_DSP:
return 8;
return 0x08;
case coding_NGC_DSP_subint:
return 0x08 * vgmstream->channels;
case coding_PCM16LE:
case coding_PCM16LE_XOR_int:
case coding_PCM16BE:
@ -1342,6 +1345,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do);
}
break;
case coding_NGC_DSP_subint:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_ngc_dsp_subint(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do,
chan, vgmstream->interleave_block_size);
}
break;
case coding_PCM16LE:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_pcm16LE(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,

View File

@ -98,6 +98,7 @@ typedef enum {
coding_CRI_ADX_enc_9, /* CRI ADX, type 9 encryption (PSO2) */
coding_NGC_DSP, /* Nintendo DSP ADPCM */
coding_NGC_DSP_subint, /* Nintendo DSP ADPCM with frame subinterframe */
coding_NGC_DTK, /* Nintendo DTK ADPCM (hardware disc), also called TRK or ADP */
coding_NGC_AFC, /* Nintendo AFC ADPCM */
@ -730,7 +731,7 @@ typedef struct {
int32_t loop_end_sample; /* last sample of the loop (not included in the loop) */
/* layouts/block */
size_t interleave_block_size; /* interleave for this file */
size_t interleave_block_size; /* interleave, or block/frame size (depending on the codec) */
size_t interleave_smallblock_size; /* smaller interleave for last block */
size_t full_block_size; /* fixed data size, from header (may include padding and other unusable data) */