mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 06:50:20 +01:00
Add interleave_first to fix some .vag/seg clicks
This commit is contained in:
parent
01ac9377d4
commit
b3a8f2b280
@ -8,19 +8,48 @@
|
||||
* Incompatible with decoders that move offsets. */
|
||||
void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
|
||||
int samples_written = 0;
|
||||
int frame_size, samples_per_frame, samples_this_block;
|
||||
int samples_per_frame, samples_this_block; /* used */
|
||||
int samples_per_frame_d = 0, samples_this_block_d = 0; /* default */
|
||||
int samples_per_frame_f = 0, samples_this_block_f = 0; /* first */
|
||||
int samples_per_frame_l = 0, samples_this_block_l = 0; /* last */
|
||||
int has_interleave_first = vgmstream->interleave_first_block_size && vgmstream->channels > 1;
|
||||
int has_interleave_last = vgmstream->interleave_last_block_size && vgmstream->channels > 1;
|
||||
|
||||
frame_size = get_vgmstream_frame_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
|
||||
samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame;
|
||||
|
||||
if (has_interleave_last &&
|
||||
vgmstream->current_sample - vgmstream->samples_into_block + samples_this_block > vgmstream->num_samples) {
|
||||
/* adjust values again if inside last interleave */
|
||||
frame_size = get_vgmstream_shortframe_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream);
|
||||
samples_this_block = vgmstream->interleave_last_block_size / frame_size * samples_per_frame;
|
||||
/* setup */
|
||||
{
|
||||
int frame_size_d = get_vgmstream_frame_size(vgmstream);
|
||||
samples_per_frame_d = get_vgmstream_samples_per_frame(vgmstream);
|
||||
if (frame_size_d == 0 || samples_per_frame_d == 0) goto fail;
|
||||
samples_this_block_d = vgmstream->interleave_block_size / frame_size_d * samples_per_frame_d;
|
||||
}
|
||||
if (has_interleave_first) {
|
||||
int frame_size_f = get_vgmstream_frame_size(vgmstream);
|
||||
samples_per_frame_f = get_vgmstream_samples_per_frame(vgmstream); //todo samples per shortframe
|
||||
if (frame_size_f == 0 || samples_per_frame_f == 0) goto fail;
|
||||
samples_this_block_f = vgmstream->interleave_first_block_size / frame_size_f * samples_per_frame_f;
|
||||
}
|
||||
else if (has_interleave_last) {
|
||||
int frame_size_l = get_vgmstream_shortframe_size(vgmstream);
|
||||
samples_per_frame_l = get_vgmstream_samples_per_shortframe(vgmstream);
|
||||
if (frame_size_l == 0 || samples_per_frame_l == 0) goto fail;
|
||||
samples_this_block_l = vgmstream->interleave_last_block_size / frame_size_l * samples_per_frame_l;
|
||||
}
|
||||
|
||||
/* set current values */
|
||||
if (has_interleave_first &&
|
||||
vgmstream->current_sample < samples_this_block_f) {
|
||||
samples_per_frame = samples_per_frame_f;
|
||||
samples_this_block = samples_this_block_f;
|
||||
}
|
||||
else if (has_interleave_last &&
|
||||
vgmstream->current_sample - vgmstream->samples_into_block + samples_this_block_d > vgmstream->num_samples) {
|
||||
samples_per_frame = samples_per_frame_l;
|
||||
samples_this_block = samples_this_block_l;
|
||||
}
|
||||
else {
|
||||
samples_per_frame = samples_per_frame_d;
|
||||
samples_this_block = samples_this_block_d;
|
||||
}
|
||||
|
||||
/* mono interleaved stream with no layout set, just behave like flat layout */
|
||||
@ -28,18 +57,28 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
|
||||
samples_this_block = vgmstream->num_samples;
|
||||
|
||||
|
||||
/* write samples */
|
||||
while (samples_written < sample_count) {
|
||||
int samples_to_do;
|
||||
|
||||
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
|
||||
/* handle looping, restore standard interleave sizes */
|
||||
if (has_interleave_last) { /* assumes that won't loop back into a interleave_last */
|
||||
frame_size = get_vgmstream_frame_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
|
||||
samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame;
|
||||
|
||||
if (has_interleave_first &&
|
||||
vgmstream->current_sample < samples_this_block_f) {
|
||||
/* use first interleave*/
|
||||
samples_per_frame = samples_per_frame_f;
|
||||
samples_this_block = samples_this_block_f;
|
||||
if (samples_this_block == 0 && vgmstream->channels == 1)
|
||||
samples_this_block = vgmstream->num_samples;
|
||||
}
|
||||
else if (has_interleave_last) { /* assumes that won't loop back into a interleave_last */
|
||||
samples_per_frame = samples_per_frame_d;
|
||||
samples_this_block = samples_this_block_d;
|
||||
if (samples_this_block == 0 && vgmstream->channels == 1)
|
||||
samples_this_block = vgmstream->num_samples;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -48,9 +87,7 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
|
||||
samples_to_do = sample_count - samples_written;
|
||||
|
||||
if (samples_to_do == 0) { /* happens when interleave is not set */
|
||||
VGM_LOG("layout_interleave: wrong samples_to_do found\n");
|
||||
memset(buffer + samples_written*vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample_t));
|
||||
break;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer);
|
||||
@ -64,18 +101,34 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
|
||||
if (vgmstream->samples_into_block == samples_this_block) {
|
||||
int ch;
|
||||
|
||||
if (has_interleave_last &&
|
||||
vgmstream->current_sample + samples_this_block > vgmstream->num_samples) {
|
||||
/* adjust values again if inside last interleave */
|
||||
frame_size = get_vgmstream_shortframe_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream);
|
||||
samples_this_block = vgmstream->interleave_last_block_size / frame_size * samples_per_frame;
|
||||
if (has_interleave_first &&
|
||||
vgmstream->current_sample == samples_this_block_f) {
|
||||
/* restore standard frame size after going past first interleave */
|
||||
samples_per_frame = samples_per_frame_d;
|
||||
samples_this_block = samples_this_block_d;
|
||||
if (samples_this_block == 0 && vgmstream->channels == 1)
|
||||
samples_this_block = vgmstream->num_samples;
|
||||
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
off_t skip = vgmstream->interleave_block_size*(vgmstream->channels-ch) +
|
||||
vgmstream->interleave_last_block_size*ch;;
|
||||
off_t skip =
|
||||
vgmstream->interleave_first_skip*(vgmstream->channels-1-ch) +
|
||||
vgmstream->interleave_first_block_size*(vgmstream->channels-ch) +
|
||||
vgmstream->interleave_block_size*ch;
|
||||
vgmstream->ch[ch].offset += skip;
|
||||
}
|
||||
}
|
||||
else if (has_interleave_last &&
|
||||
vgmstream->current_sample + samples_this_block > vgmstream->num_samples) {
|
||||
/* adjust values again if inside last interleave */
|
||||
samples_per_frame = samples_per_frame_l;
|
||||
samples_this_block = samples_this_block_l;
|
||||
if (samples_this_block == 0 && vgmstream->channels == 1)
|
||||
samples_this_block = vgmstream->num_samples;
|
||||
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
off_t skip =
|
||||
vgmstream->interleave_block_size*(vgmstream->channels-ch) +
|
||||
vgmstream->interleave_last_block_size*ch;
|
||||
vgmstream->ch[ch].offset += skip;
|
||||
}
|
||||
}
|
||||
@ -88,6 +141,9 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
|
||||
|
||||
vgmstream->samples_into_block = 0;
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
fail:
|
||||
VGM_LOG("layout_interleave: wrong values found\n");
|
||||
memset(buffer + samples_written*vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample_t));
|
||||
}
|
||||
|
@ -67,11 +67,14 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x2000;
|
||||
vgmstream->interleave_first_skip = 0x60;
|
||||
vgmstream->interleave_first_block_size = vgmstream->interleave_block_size - vgmstream->interleave_first_skip;
|
||||
|
||||
/* standard dsp header at start_offset */
|
||||
dsp_read_coefs_be(vgmstream, streamFile, start_offset+0x1c, vgmstream->interleave_block_size);
|
||||
dsp_read_hist_be(vgmstream, streamFile, start_offset+0x40, vgmstream->interleave_block_size);
|
||||
//todo first_interleave: 0x2000 - 60
|
||||
|
||||
start_offset += vgmstream->interleave_first_skip;
|
||||
break;
|
||||
|
||||
case 0x70635F00: /* "pc_\0" */
|
||||
|
@ -6,7 +6,7 @@
|
||||
VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
size_t file_size, channel_size, interleave;
|
||||
size_t file_size, channel_size, interleave, interleave_first = 0, interleave_first_skip = 0;
|
||||
meta_t meta_type;
|
||||
int channel_count = 0, loop_flag, sample_rate;
|
||||
uint32_t vag_id, version;
|
||||
@ -80,7 +80,7 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
|
||||
|
||||
case 0x70474156: /* pGAV (little endian / stereo) [Jak 3 (PS2), Jak X (PS2)] */
|
||||
meta_type = meta_PS2_pGAV;
|
||||
start_offset = 0x00; //todo 0x30, requires interleave_first
|
||||
start_offset = 0x30;
|
||||
|
||||
if (read_32bitBE(0x20,streamFile) == 0x53746572) { /* "Ster" */
|
||||
channel_count = 2;
|
||||
@ -91,7 +91,8 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
|
||||
interleave = 0x1000; /* Jak X interleave, includes header */
|
||||
else
|
||||
interleave = 0x2000; /* Jak 3 interleave in rare files, no header */
|
||||
//todo interleave_first = interleave - start_offset; /* interleave includes header */
|
||||
interleave_first = interleave - start_offset; /* interleave includes header */
|
||||
interleave_first_skip = start_offset;
|
||||
}
|
||||
else {
|
||||
channel_count = 1;
|
||||
@ -127,21 +128,21 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
|
||||
}
|
||||
else if (read_32bitBE(0x6000,streamFile) == 0x56414770) { /* "VAGp" */
|
||||
/* The Simpsons Wrestling (PS1) */
|
||||
start_offset = 0x00; //todo 0x30, requires interleave_first
|
||||
start_offset = 0x30;
|
||||
channel_count = 2;
|
||||
interleave = 0x6000;
|
||||
//todo interleave_first = interleave - start_offset; /* includes header */
|
||||
channel_size += 0x30;
|
||||
interleave_first = interleave - start_offset; /* includes header */
|
||||
interleave_first_skip = start_offset;
|
||||
|
||||
loop_flag = 0;
|
||||
}
|
||||
else if (read_32bitBE(0x1000,streamFile) == 0x56414770) { /* "VAGp" */
|
||||
/* Shikigami no Shiro (PS2) */
|
||||
start_offset = 0x00; //todo 0x30, requires interleave_first
|
||||
start_offset = 0x30;
|
||||
channel_count = 2;
|
||||
interleave = 0x1000;
|
||||
//todo interleave_first = interleave - start_offset; /* includes header */
|
||||
channel_size += 0x30;
|
||||
interleave_first = interleave - start_offset; /* includes header */
|
||||
interleave_first_skip = start_offset;
|
||||
|
||||
loop_flag = ps_find_loop_offsets(streamFile, start_offset, channel_size*channel_count, channel_count, interleave, &loop_start_sample, &loop_end_sample);
|
||||
}
|
||||
@ -244,6 +245,9 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
|
||||
vgmstream->coding_type = coding_HEVAG;
|
||||
vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->interleave_first_block_size = interleave_first;
|
||||
vgmstream->interleave_first_skip = interleave_first_skip;
|
||||
|
||||
|
||||
read_string(vgmstream->stream_name,0x10+1, 0x20,streamFile); /* always, can be null */
|
||||
|
||||
|
@ -2422,6 +2422,11 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
||||
snprintf(temp,TEMPSIZE, "interleave: %#x bytes\n", (int32_t)vgmstream->interleave_block_size);
|
||||
concatn(length,desc,temp);
|
||||
|
||||
if (vgmstream->interleave_first) {
|
||||
snprintf(temp,TEMPSIZE, "interleave first block: %#x bytes\n", (int32_t)vgmstream->interleave_first);
|
||||
concatn(length,desc,temp);
|
||||
}
|
||||
|
||||
if (vgmstream->interleave_last_block_size) {
|
||||
snprintf(temp,TEMPSIZE, "interleave last block: %#x bytes\n", (int32_t)vgmstream->interleave_last_block_size);
|
||||
concatn(length,desc,temp);
|
||||
|
@ -824,6 +824,8 @@ typedef struct {
|
||||
|
||||
/* layouts/block config */
|
||||
size_t interleave_block_size; /* interleave, or block/frame size (depending on the codec) */
|
||||
size_t interleave_first_block_size; /* different interleave for first block */
|
||||
size_t interleave_first_skip; /* data skipped before interleave first (needed to skip other channels) */
|
||||
size_t interleave_last_block_size; /* smaller interleave for last block */
|
||||
|
||||
/* subsong config */
|
||||
|
Loading…
Reference in New Issue
Block a user