Extend GENH to support little-endian "Gamecube" DSP ADPCM coefficients, for some 3DS titles.

This involves a reinterpretation of byte 0x30 (coef type). Formerly this byte took on only two values, to indicate how the ADPCM coefficients (aka codebook) were stored:
0 - normal coefs: all 16 coefs interleaved into one array, offset given at 0x24 for left, 0x28 for right
1 - split coefs: 8 coefs in the main array, additional offset to 2nd array given at 0x34 for left, 0x38 for right

Now I am considering this to be indicated only by bit 0 of the coef type. Bit 1 is taking on an additional interpretation, if it is set, we consider the coefficients to be little endian rather than the normal big endian.

This should maintain backwards compatibility with old GENH files, which should have only used the value 0 or 1.

Thus, in effect we have:
0: normal, big endian
1: split, big endian
2: normal, little endian
3: split, little endian

I don't know of any situation in which 3 would be used (yet), but I'm sure devs will continue to surprise me.
This commit is contained in:
halleyscometsw 2014-06-26 20:53:49 -07:00 committed by Chris Moeller
parent a5843ef470
commit 1854d42e97

View File

@ -55,10 +55,10 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
/* 12 = NGC DSP */
/* 13 = 8bit unsingned PCM */
/* 14 = PSX ADPCM (bad flagged) */
/* 15 = Microsoft IMA (MS ADPCM)
/* 16 = 8-bit PCM (unsigned)
/* 17 = Apple Quicktime 4-bit IMA ADPCM;
/* ... others to come */
/* 15 = Microsoft IMA (MS ADPCM) */
/* 16 = 8-bit PCM (unsigned) */
/* 17 = Apple Quicktime 4-bit IMA ADPCM */
switch (read_32bitLE(0x18,streamFile)) {
case 0:
coding = coding_PSX;
@ -142,10 +142,16 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
coef[0] = read_32bitLE(0x24,streamFile);
coef[1] = read_32bitLE(0x28,streamFile);
dsp_interleave_type = read_32bitLE(0x2C,streamFile);
coef_type = read_32bitLE(0x30,streamFile); /* 0 - normal coefs
1 - splitted coefs (16byte rows) */
/* DSP coefficient variants */
/* bit 0 - split coefs (2 arrays) */
/* bit 1 - little endian coefs */
coef_type = read_32bitLE(0x30,streamFile);
/* when using split coefficients, 2nd array is at: */
coef_splitted[0] = read_32bitLE(0x34,streamFile);
coef_splitted[1] = read_32bitLE(0x38,streamFile);
//if (coding == coding_XBOX && channel_count != 2) goto fail;
/* build the VGMSTREAM */
@ -298,14 +304,23 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
chstreamfile =
streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (coef_type == 0) {
for (j=0;j<16;j++) {
vgmstream->ch[i].adpcm_coef[j] = read_16bitBE(coef[i]+j*2,streamFile);
{
int16_t (*read_16bit)(off_t , STREAMFILE*);
if ((coef_type & 2) == 0) {
read_16bit = read_16bitBE;
} else {
read_16bit = read_16bitLE;
}
} else if (coef_type == 1) {
for (j=0;j<8;j++) {
vgmstream->ch[i].adpcm_coef[j*2]=read_16bitBE(coef[i]+j*2,streamFile);
vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bitBE(coef_splitted[i]+j*2,streamFile);
if ((coef_type & 1) == 0) {
for (j=0;j<16;j++) {
vgmstream->ch[i].adpcm_coef[j] = read_16bit(coef[i]+j*2,streamFile);
}
} else {
for (j=0;j<8;j++) {
vgmstream->ch[i].adpcm_coef[j*2]=read_16bit(coef[i]+j*2,streamFile);
vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bit(coef_splitted[i]+j*2,streamFile);
}
}
}
chstart_offset =start_offset+vgmstream->interleave_block_size*i;