mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-25 07:20:10 +01:00
Fix interleaved 2ch XBOX-IMA [Fairly OddParents: Breakin' da Rules]
This commit is contained in:
parent
3a64f8b0d2
commit
fa472d4f70
@ -24,9 +24,8 @@ void decode_wv6_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
|
||||
void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
|
||||
void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
|
||||
void decode_xbox_ima_mch(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
|
@ -430,22 +430,26 @@ void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o
|
||||
/* ************************************ */
|
||||
|
||||
/* MS-IMA with fixed frame size, and outputs an even number of samples per frame (skips last nibble).
|
||||
* Defined in Xbox's SDK. Multichannel interleaves 2ch*N/2, or 1ch*N with odd num_channels
|
||||
* (seen in some Koei .wav, could be simplified as interleaved stereo) --unsure if official. */
|
||||
void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
int i, sample_count = 0;
|
||||
* Defined in Xbox's SDK. Usable in mono or stereo modes (both suitable for interleaved multichannel). */
|
||||
void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo) {
|
||||
int i, frames_in, sample_pos = 0, block_samples, frame_size;
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
off_t frame_offset;
|
||||
|
||||
/* internal interleave (fixed size), mixed channels */
|
||||
int block_samples = (0x24-0x4) * 2;
|
||||
/* external interleave (fixed size), stereo/mono */
|
||||
block_samples = (0x24 - 0x4) * 2;
|
||||
frames_in = first_sample / block_samples;
|
||||
first_sample = first_sample % block_samples;
|
||||
frame_size = is_stereo ? 0x24*2 : 0x24;
|
||||
|
||||
/* normal header (hist+step+reserved), per stereo/mono channel in blocks */
|
||||
frame_offset = stream->offset + frame_size*frames_in;
|
||||
|
||||
/* normal header (hist+step+reserved), stereo/mono */
|
||||
if (first_sample == 0) {
|
||||
off_t header_offset = (channelspacing & 1) ?
|
||||
stream->offset + 0x24*(channel) + 0x00:
|
||||
stream->offset + 0x48*(channel/2) + 0x04*(channel%2);
|
||||
off_t header_offset = is_stereo ?
|
||||
frame_offset + 0x04*(channel % 2) :
|
||||
frame_offset + 0x00;
|
||||
|
||||
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
|
||||
step_index = read_8bit(header_offset+0x02,stream->streamfile);
|
||||
@ -453,32 +457,27 @@ void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac
|
||||
if (step_index > 88) step_index=88;
|
||||
|
||||
/* write header sample (even samples per block, skips last nibble) */
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
sample_count += channelspacing;
|
||||
outbuf[sample_pos] = (short)(hist1);
|
||||
sample_pos += channelspacing;
|
||||
first_sample += 1;
|
||||
samples_to_do -= 1;
|
||||
}
|
||||
|
||||
/* decode nibbles (layout: alternates 4 bytes/4*2 nibbles per channel, in stereo blocks) */
|
||||
/* decode nibbles (layout: straight in mono or 4 bytes per channel in stereo) */
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
||||
off_t byte_offset = (channelspacing & 1) ?
|
||||
(stream->offset + 0x24*(channel) + 0x04) + (i-1)/2:
|
||||
(stream->offset + 0x48*(channel/2) + 0x04*2) + 0x04*(channel%2) + 0x04*2*((i-1)/8) + ((i-1)%8)/2;
|
||||
int nibble_shift = ((i-1)&1?4:0); /* low nibble first */
|
||||
off_t byte_offset = is_stereo ?
|
||||
frame_offset + 0x04*2 + 0x04*(channel % 2) + 0x04*2*((i-1)/8) + ((i-1)%8)/2 :
|
||||
frame_offset + 0x04 + (i-1)/2;
|
||||
int nibble_shift = (!((i-1)&1) ? 0:4); /* low first */
|
||||
|
||||
/* must skip last nibble per official decoder, probably not needed though */
|
||||
/* must skip last nibble per spec, rarely needed though (ex. Gauntlet Dark Legacy) */
|
||||
if (i < block_samples) {
|
||||
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
sample_count += channelspacing;
|
||||
outbuf[sample_pos] = (short)(hist1);
|
||||
sample_pos += channelspacing;
|
||||
}
|
||||
}
|
||||
|
||||
/* internal interleave: increment offset on complete frame */
|
||||
if (i == block_samples) {
|
||||
stream->offset += 0x24*channelspacing;
|
||||
}
|
||||
|
||||
stream->adpcm_history1_32 = hist1;
|
||||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
@ -527,50 +526,6 @@ void decode_xbox_ima_mch(VGMSTREAMCHANNEL * stream, sample * outbuf, int channel
|
||||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
|
||||
/* Mono XBOX-IMA ADPCM, used for interleave. Also defined in Xbox's SDK. */
|
||||
void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
int i, sample_count = 0, num_frame;
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
||||
/* external interleave (fixed size), mono */
|
||||
int block_samples = (0x24 - 0x4) * 2;
|
||||
num_frame = first_sample / block_samples;
|
||||
first_sample = first_sample % block_samples;
|
||||
|
||||
/* normal header (hist+step+reserved), single channel */
|
||||
if (first_sample == 0) {
|
||||
off_t header_offset = stream->offset + 0x24*num_frame;
|
||||
|
||||
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
|
||||
step_index = read_8bit(header_offset+0x02,stream->streamfile);
|
||||
if (step_index < 0) step_index=0;
|
||||
if (step_index > 88) step_index=88;
|
||||
|
||||
/* write header sample (even samples per block, skips last nibble) */
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
sample_count += channelspacing;
|
||||
first_sample += 1;
|
||||
samples_to_do -= 1;
|
||||
}
|
||||
|
||||
/* decode nibbles (layout: all nibbles from one channel) */
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
||||
off_t byte_offset = (stream->offset + 0x24*num_frame + 0x4) + (i-1)/2;
|
||||
int nibble_shift = ((i-1)&1?4:0); /* low nibble first */
|
||||
|
||||
/* must skip last nibble per spec, rarely needed though (ex. Gauntlet Dark Legacy) */
|
||||
if (i < block_samples) {
|
||||
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
sample_count += channelspacing;
|
||||
}
|
||||
}
|
||||
|
||||
stream->adpcm_history1_32 = hist1;
|
||||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
|
||||
/* Similar to MS-IMA with even number of samples, header sample is not written (setup only).
|
||||
* Apparently clamps to -32767 unlike standard's -32768 (probably not noticeable).
|
||||
* Info here: http://problemkaputt.de/gbatek.htm#dssoundnotes */
|
||||
|
@ -9,46 +9,48 @@ VGMSTREAM * init_vgmstream_mss(STREAMFILE *streamFile) {
|
||||
size_t data_size;
|
||||
int loop_flag = 0, channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
if (!check_extensions(streamFile, "mss")) goto fail;
|
||||
|
||||
/* check header */
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "mss"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4D435353) /* "MCSS" */
|
||||
goto fail;
|
||||
|
||||
loop_flag = 0;
|
||||
channel_count = read_16bitLE(0x16,streamFile);
|
||||
if (read_32bitLE(0x18,streamFile) == 0x4800 && channel_count > 2)
|
||||
channel_count = 2; //todo add support for interleave stereo streams
|
||||
|
||||
/* 0x04: version? (always 0x00000100 LE) */
|
||||
start_offset = read_32bitLE(0x08,streamFile);
|
||||
data_size = read_32bitLE(0x0c,streamFile);
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
/* 0x04: version? (always 0x00000100 LE) */
|
||||
start_offset = read_32bitLE(0x08,streamFile);
|
||||
data_size = read_32bitLE(0x0c,streamFile);
|
||||
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
|
||||
/* 0x14(1): 1/2/3/4 if 2/4/6/8ch, 0x15(1): 0/1?, 0x16: ch */
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile);
|
||||
vgmstream->num_samples = read_32bitLE(0x1C,streamFile);
|
||||
vgmstream->meta_type = meta_MSS;
|
||||
|
||||
/* no other way to know */
|
||||
if (vgmstream->interleave_block_size == 0x4800) {
|
||||
/* interleaved stereo streams (2ch 0x4800 + 2ch 0x4800 = 4ch) */
|
||||
vgmstream->coding_type = coding_XBOX_IMA;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
|
||||
/* in stereo multichannel this value is distance between 2ch pair, but we need
|
||||
* interleave*ch = full block (2ch 0x4800 + 2ch 0x4800 = 4ch, 0x4800+4800 / 4 = 0x2400) */
|
||||
vgmstream->interleave_block_size = vgmstream->interleave_block_size / 2;
|
||||
if (vgmstream->channels > 2 && vgmstream->channels % 2 != 0)
|
||||
goto fail; /* only 2ch+..+2ch layout is known */
|
||||
|
||||
/* header values are somehow off? */
|
||||
data_size = get_streamfile_size(streamFile);
|
||||
data_size = get_streamfile_size(streamFile) - start_offset;
|
||||
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
|
||||
}
|
||||
else {
|
||||
/* 0x800 interleave */
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
|
||||
|
||||
if (vgmstream->num_samples * vgmstream->channels <= data_size)
|
||||
vgmstream->num_samples = vgmstream->num_samples / 16 * 28;
|
||||
|
@ -612,6 +612,15 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Dynasty Warriors 5 (Xbox) 6ch interleaves stereo frames, probably not official */
|
||||
if (vgmstream->coding_type == coding_XBOX_IMA && vgmstream->channels > 2) {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x24; /* block_size / channels */
|
||||
if (vgmstream->channels > 2 && vgmstream->channels % 2 != 0)
|
||||
goto fail; /* only 2ch+..+2ch layout is known */
|
||||
}
|
||||
|
||||
|
||||
/* meta, loops */
|
||||
vgmstream->meta_type = meta_RIFF_WAVE;
|
||||
if (loop_flag) {
|
||||
|
@ -120,8 +120,10 @@ VGMSTREAM * init_vgmstream_str_wav(STREAMFILE *streamFile) {
|
||||
|
||||
case XBOX:
|
||||
vgmstream->coding_type = coding_XBOX_IMA;
|
||||
vgmstream->layout_type = layout_none;
|
||||
if (strwav.channels > 2) goto fail; //todo multistreams are 2ch*N interleaved using ~0xD000
|
||||
vgmstream->layout_type = layout_interleave; /* interleaved stereo for >2ch*/
|
||||
vgmstream->interleave_block_size = strwav.interleave;
|
||||
if (vgmstream->channels > 2 && vgmstream->channels % 2 != 0)
|
||||
goto fail; /* only 2ch+..+2ch layout is known */
|
||||
break;
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
@ -190,7 +192,7 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
strwav->interleave = 0;
|
||||
|
||||
strwav->codec = WMA;
|
||||
;VGM_LOG("STR+WAV: header Fuzion Frenzy (Xbox)\n");
|
||||
//;VGM_LOG("STR+WAV: header Fuzion Frenzy (Xbox)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -213,7 +215,7 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
|
||||
strwav->coefs_offset = 0xdc;
|
||||
strwav->codec = DSP;
|
||||
;VGM_LOG("STR+WAV: header Taz: Wanted (GC)\n");
|
||||
//;VGM_LOG("STR+WAV: header Taz: Wanted (GC)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -231,10 +233,10 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
|
||||
strwav->channels = read_32bitLE(0x70,streamHeader) * (strwav->flags & 0x02 ? 2 : 1); /* tracks of 2/1ch */
|
||||
strwav->loop_flag = strwav->flags & 0x01;
|
||||
strwav->interleave = strwav->channels > 2 ? 0xD000 : 0x0;
|
||||
strwav->interleave = 0xD800/2;
|
||||
|
||||
strwav->codec = XBOX;
|
||||
;VGM_LOG("STR+WAV: header The Fairly OddParents (Xbox)\n");
|
||||
//;VGM_LOG("STR+WAV: header The Fairly OddParents (Xbox)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -257,32 +259,10 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
|
||||
strwav->dsps_table = 0xe0;
|
||||
strwav->codec = DSP;
|
||||
;VGM_LOG("STR+WAV: header Bad Boys II (GC)\n");
|
||||
//;VGM_LOG("STR+WAV: header Bad Boys II (GC)\n");
|
||||
return 1;
|
||||
}
|
||||
#if 0
|
||||
if ( read_32bitBE(0x04,streamHeader) == 0x00000800 &&
|
||||
read_32bitBE(0x24,streamHeader) == read_32bitBE(0xb0,streamHeader) && /* sample rate repeat */
|
||||
read_32bitBE(0x24,streamHeader) == read_32bitBE(read_32bitBE(0xf0,streamHeader)+0x08,streamHeader) && /* sample rate vs 1st DSP header */
|
||||
read_32bitBE(0x28,streamHeader) == 0x10 &&
|
||||
read_32bitBE(0xc0,streamHeader)*0x04 + read_32bitBE(0xc4,streamHeader) == header_size /* variable + variable */
|
||||
) {
|
||||
strwav->num_samples = read_32bitBE(0x20,streamHeader);
|
||||
strwav->sample_rate = read_32bitBE(0x24,streamHeader);
|
||||
strwav->flags = read_32bitBE(0x2c,streamHeader);
|
||||
strwav->loop_start = read_32bitBE(0xd8,streamHeader);
|
||||
strwav->loop_end = read_32bitBE(0xdc,streamHeader);
|
||||
|
||||
strwav->channels = read_32bitBE(0x70,streamHeader) * read_32bitBE(0x88,streamHeader); /* tracks of Nch */
|
||||
strwav->loop_flag = strwav->flags & 0x01;
|
||||
strwav->interleave = strwav->channels > 2 ? 0x8000 : 0x10000;
|
||||
|
||||
strwav->dsps_table = 0xf0;
|
||||
strwav->codec = DSP;
|
||||
;VGM_LOG("STR+WAV: header Pac-Man World 3 (GC)\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
/* Bad Boys II (PS2)[2004] */
|
||||
/* Pac-Man World 3 (PS2)[2005] */
|
||||
if ((read_32bitBE(0x04,streamHeader) == 0x00000800 ||
|
||||
@ -303,7 +283,7 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
strwav->interleave = strwav->channels > 2 ? 0x4000 : 0x8000;
|
||||
|
||||
strwav->codec = PSX;
|
||||
;VGM_LOG("STR+WAV: header Bad Boys II (PS2)\n");
|
||||
//;VGM_LOG("STR+WAV: header Bad Boys II (PS2)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -324,7 +304,7 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
strwav->interleave = strwav->channels > 2 ? 0x4000 : 0x8000;
|
||||
|
||||
strwav->codec = PSX;
|
||||
;VGM_LOG("STR+WAV: header Zapper (PS2)\n");
|
||||
//;VGM_LOG("STR+WAV: header Zapper (PS2)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -346,7 +326,7 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
|
||||
strwav->dsps_table = 0xe0;
|
||||
strwav->codec = DSP;
|
||||
;VGM_LOG("STR+WAV: header Zapper (GC)\n");
|
||||
//;VGM_LOG("STR+WAV: header Zapper (GC)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -372,7 +352,7 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
|
||||
strwav->dsps_table = 0xf0;
|
||||
strwav->codec = DSP;
|
||||
;VGM_LOG("STR+WAV: header SpongeBob SquarePants (GC)\n");
|
||||
//;VGM_LOG("STR+WAV: header SpongeBob SquarePants (GC)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -394,7 +374,7 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
strwav->interleave = strwav->channels > 4 ? 0x4000 : 0x8000;
|
||||
|
||||
strwav->codec = PSX;
|
||||
;VGM_LOG("STR+WAV: header SpongeBob SquarePants (PS2)\n");
|
||||
//;VGM_LOG("STR+WAV: header SpongeBob SquarePants (PS2)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -415,7 +395,7 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
strwav->interleave = strwav->channels > 4 ? 0x4000 : 0x8000;
|
||||
|
||||
strwav->codec = PSX;
|
||||
;VGM_LOG("STR+WAV: header Tak (PS2)\n");
|
||||
//;VGM_LOG("STR+WAV: header Tak (PS2)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -439,7 +419,7 @@ static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) {
|
||||
|
||||
strwav->coefs_table = 0x7c;
|
||||
strwav->codec = DSP;
|
||||
;VGM_LOG("STR+WAV: header Tak (Wii)\n");
|
||||
//;VGM_LOG("STR+WAV: header Tak (Wii)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1547,9 +1547,12 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
}
|
||||
break;
|
||||
case coding_XBOX_IMA:
|
||||
case coding_XBOX_IMA_int:
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
int is_stereo = (vgmstream->channels > 1 && vgmstream->coding_type == coding_XBOX_IMA);
|
||||
decode_xbox_ima(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
|
||||
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, ch);
|
||||
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, ch,
|
||||
is_stereo);
|
||||
}
|
||||
break;
|
||||
case coding_XBOX_IMA_mch:
|
||||
@ -1558,12 +1561,6 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, ch);
|
||||
}
|
||||
break;
|
||||
case coding_XBOX_IMA_int:
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
decode_xbox_ima_int(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
|
||||
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, ch);
|
||||
}
|
||||
break;
|
||||
case coding_MS_IMA:
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
decode_ms_ima(vgmstream,&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
|
||||
@ -2611,6 +2608,7 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s
|
||||
int ch;
|
||||
int use_streamfile_per_channel = 0;
|
||||
int use_same_offset_per_channel = 0;
|
||||
int is_stereo_codec = 0;
|
||||
|
||||
|
||||
/* stream/offsets not needed, managed by layout */
|
||||
@ -2640,12 +2638,15 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s
|
||||
use_streamfile_per_channel = 1;
|
||||
}
|
||||
|
||||
|
||||
/* for mono or codecs like IMA (XBOX, MS IMA, MS ADPCM) where channels work with the same bytes */
|
||||
if (vgmstream->layout_type == layout_none) {
|
||||
use_same_offset_per_channel = 1;
|
||||
}
|
||||
|
||||
/* stereo codecs interleave in 2ch pairs (interleave size should still be: full_block_size / channels) */
|
||||
if (vgmstream->layout_type == layout_interleave && vgmstream->coding_type == coding_XBOX_IMA) {
|
||||
is_stereo_codec = 1;
|
||||
}
|
||||
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
/* open the file for reading by each channel */
|
||||
@ -2659,6 +2660,10 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s
|
||||
off_t offset;
|
||||
if (use_same_offset_per_channel) {
|
||||
offset = start_offset;
|
||||
} else if (is_stereo_codec) {
|
||||
int ch_mod = (ch & 1) ? ch - 1 : ch; /* adjust odd channels (ch 0,1,2,3,4,5 > ch 0,0,2,2,4,4) */
|
||||
offset = start_offset + vgmstream->interleave_block_size*ch_mod;
|
||||
//VGM_LOG("ch%i offset=%lx\n", ch,offset);
|
||||
} else {
|
||||
offset = start_offset + vgmstream->interleave_block_size*ch;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user