mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-17 19:19:16 +01:00
Add NGC DSP subinterleave decoder
Meant to replace layout_interleave_byte
This commit is contained in:
parent
9c3adeba8f
commit
98b4f8c5b1
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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"},
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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) */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user