mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-28 08:20:54 +01:00
Fix some .str+wav [Zapper Beta (PS2)]
This commit is contained in:
parent
5928c8df0d
commit
28f9781a89
@ -155,6 +155,7 @@
|
||||
<ClInclude Include="meta\sfh_streamfile.h" />
|
||||
<ClInclude Include="meta\sqex_streamfile.h" />
|
||||
<ClInclude Include="meta\sscf_encrypted.h" />
|
||||
<ClInclude Include="meta\str_wav_streamfile.h" />
|
||||
<ClInclude Include="meta\txth_streamfile.h" />
|
||||
<ClInclude Include="meta\ubi_bao_streamfile.h" />
|
||||
<ClInclude Include="meta\ubi_ckd_cwav_streamfile.h" />
|
||||
|
@ -290,6 +290,9 @@
|
||||
<ClInclude Include="meta\sscf_encrypted.h">
|
||||
<Filter>meta\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="meta\str_wav_streamfile.h">
|
||||
<Filter>meta\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="meta\txth_streamfile.h">
|
||||
<Filter>meta\Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1,9 +1,10 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/layout_utils.h"
|
||||
#include "str_wav_streamfile.h"
|
||||
|
||||
|
||||
typedef enum { PSX, DSP, XBOX, WMA, IMA, XMA2, MPEG } strwav_codec;
|
||||
typedef enum { PSX, PSX_chunked, DSP, XBOX, WMA, IMA, XMA2, MPEG } strwav_codec;
|
||||
typedef struct {
|
||||
int tracks;
|
||||
int channels;
|
||||
@ -104,6 +105,29 @@ VGMSTREAM* init_vgmstream_str_wav(STREAMFILE* sf) {
|
||||
vgmstream->interleave_block_size = strwav.interleave;
|
||||
break;
|
||||
|
||||
case PSX_chunked: { /* hack */
|
||||
//tracks are stereo blocks of size 0x20000 * tracks, containing 4 interleaves of 0x8000:
|
||||
// | 1 2 1 2 | 3 4 3 4 | 5 6 5 6 | 1 2 1 2 | 3 4 3 4 | 5 6 5 6 | ...
|
||||
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->interleave_block_size = strwav.interleave;
|
||||
for (int i = 0; i < strwav.tracks; i++) {
|
||||
uint32_t chunk_size = 0x20000;
|
||||
int layer_channels = 2;
|
||||
|
||||
STREAMFILE* temp_sf = setup_str_wav_streamfile(sf, 0x00, strwav.tracks, i, chunk_size);
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
bool res = layered_add_sf(vgmstream, strwav.tracks, layer_channels, temp_sf);
|
||||
close_streamfile(temp_sf);
|
||||
if (!res)
|
||||
goto fail;
|
||||
}
|
||||
if (!layered_add_done(vgmstream))
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
|
||||
case DSP:
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
@ -456,8 +480,8 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa
|
||||
|
||||
strwav->codec = PSX;
|
||||
strwav->interleave = strwav->tracks > 1 ? 0x8000 : 0x8000;
|
||||
//todo: tracks are stereo blocks of size 0x20000*tracks, containing 4 interleaves of 0x8000:
|
||||
// | 1 2 1 2 | 3 4 3 4 | 5 6 5 6 | 1 2 1 2 | 3 4 3 4 | 5 6 5 6 | ...
|
||||
if (strwav->tracks > 1) /* hack */
|
||||
strwav->codec = PSX_chunked;
|
||||
;VGM_LOG("STR+WAV: header ZPb (PS2)\n");
|
||||
return 1;
|
||||
}
|
||||
@ -690,7 +714,7 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa
|
||||
/* 0x4c: ? (some low number) */
|
||||
strwav->tracks = read_u8 (0x4e,sf_h);
|
||||
/* 0x4f: 16 bps */
|
||||
/* 0x54: channels per each track? (ex. 2 stereo track: 0x02,0x02) */
|
||||
/* 0x54: channels per each track (ex. 2 stereo track: 0x02,0x02) */
|
||||
/* 0x64: channels */
|
||||
/* 0x70+: tables */
|
||||
|
||||
@ -772,8 +796,14 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa
|
||||
|
||||
strwav->channels = read_s32be(0x70,sf_h);
|
||||
|
||||
/* possible flags/ch numbers at 0x4A/61 */
|
||||
/* other possibly-useful flags (see Karaoke Wii too):
|
||||
* - 0x4b: number of tracks
|
||||
* - 0x60: channels per track, ex. 020202 = 3 tracks of 2ch (max 0x08 = 8)
|
||||
* - 0xa0: sizes per track (max 0x20 = 8)
|
||||
* - 0xc0: samples per track (max 0x20 = 8)
|
||||
* - rest: info/seek table? */
|
||||
if (read_s32be(0x78,sf_h) != 0) { /* KRev */
|
||||
|
||||
strwav->tracks = strwav->channels / 2;
|
||||
strwav->num_samples = strwav->loop_end; /* num_samples here seems to be data size */
|
||||
strwav->interleave = read_s32be(0xA0,sf_h); /* one size per file, but CBR = same for all */
|
||||
|
21
src/meta/str_wav_streamfile.h
Normal file
21
src/meta/str_wav_streamfile.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef _STR_WAV_STREAMFILE_H_
|
||||
#define _STR_WAV_STREAMFILE_H_
|
||||
#include "deblock_streamfile.h"
|
||||
|
||||
/* Deblocks streams */
|
||||
static STREAMFILE* setup_str_wav_streamfile(STREAMFILE* sf, off_t stream_start, int stream_count, int stream_number, size_t interleave) {
|
||||
STREAMFILE *new_sf = NULL;
|
||||
deblock_config_t cfg = {0};
|
||||
|
||||
cfg.stream_start = stream_start;
|
||||
cfg.chunk_size = interleave;
|
||||
cfg.step_start = stream_number;
|
||||
cfg.step_count = stream_count;
|
||||
|
||||
/* setup sf */
|
||||
new_sf = open_wrap_streamfile(sf);
|
||||
new_sf = open_io_deblock_streamfile_f(new_sf, &cfg);
|
||||
return new_sf;
|
||||
}
|
||||
|
||||
#endif
|
@ -56,11 +56,11 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) {
|
||||
static bool layered_add_internal(VGMSTREAM* vs, int layers, int layer_channels, STREAMFILE* sf) {
|
||||
int i;
|
||||
layered_layout_data* data;
|
||||
|
||||
if (!vs || !vs->codec_data) {
|
||||
if (!vs) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -99,9 +99,12 @@ bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) {
|
||||
data->layers[i]->loop_end_sample = vs->loop_end_sample;
|
||||
|
||||
data->layers[i]->codec_data = vs->codec_data;
|
||||
if (!data->layers[i]->codec_data) goto fail;
|
||||
data->layers[i]->coding_type = vs->coding_type;
|
||||
|
||||
data->layers[i]->layout_type = layout_none;
|
||||
data->layers[i]->interleave_block_size = vs->interleave_block_size;
|
||||
if (vs->interleave_block_size)
|
||||
data->layers[i]->layout_type = layout_interleave;
|
||||
|
||||
vs->codec_data = NULL; /* moved to layer, don't hold it */
|
||||
|
||||
@ -112,6 +115,18 @@ fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool layered_add_sf(VGMSTREAM* vs, int layers, int layer_channels, STREAMFILE* sf) {
|
||||
return layered_add_internal(vs, layers, layer_channels, sf);
|
||||
}
|
||||
|
||||
bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) {
|
||||
if (!vs->codec_data)
|
||||
return false;
|
||||
|
||||
return layered_add_internal(vs, layers, layer_channels, NULL);
|
||||
}
|
||||
|
||||
|
||||
bool layered_add_done(VGMSTREAM* vs) {
|
||||
//TODO: some extra checks/setup?
|
||||
|
||||
|
@ -8,6 +8,10 @@ typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*);
|
||||
/* add a new layer from subfile (setups layout if needed) */
|
||||
bool layered_add_subfile(VGMSTREAM* vs, int layers, int layer_channels, STREAMFILE* sf, uint32_t offset, uint32_t size, const char* ext, init_vgmstream_t init_vgmstream);
|
||||
|
||||
|
||||
/* add a new layer from base vgmstream (setups layout if needed) */
|
||||
bool layered_add_sf(VGMSTREAM* vs, int layers, int layer_channels, STREAMFILE* sf);
|
||||
|
||||
/* add a new layer from codec data (setups layout if needed)
|
||||
* codec is passed in the vs for easier free/etc control */
|
||||
bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels);
|
||||
|
@ -616,12 +616,6 @@ static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) {
|
||||
try_dual_file_stereo(vgmstream, sf, init_vgmstream_function);
|
||||
}
|
||||
|
||||
/* clean as loops are readable metadata but loop fields may contain garbage
|
||||
* (done *after* dual stereo as it needs loop fields to match) */
|
||||
if (!vgmstream->loop_flag) {
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = 0;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
/* check FFmpeg streams here, for lack of a better place */
|
||||
@ -678,6 +672,28 @@ static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) {
|
||||
|
||||
void setup_vgmstream(VGMSTREAM* vgmstream) {
|
||||
|
||||
//TODO improve cleanup (done here to handle manually added layers)
|
||||
|
||||
/* sanify loops and remove bad metadata (some layouts will behave incorrectly) */
|
||||
if (vgmstream->loop_flag) {
|
||||
if (vgmstream->loop_end_sample <= vgmstream->loop_start_sample
|
||||
|| vgmstream->loop_end_sample > vgmstream->num_samples
|
||||
|| vgmstream->loop_start_sample < 0) {
|
||||
VGM_LOG("VGMSTREAM: wrong loops ignored (lss=%i, lse=%i, ns=%i)\n",
|
||||
vgmstream->loop_start_sample, vgmstream->loop_end_sample, vgmstream->num_samples);
|
||||
vgmstream->loop_flag = 0;
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* clean as loops are readable metadata but loop fields may contain garbage
|
||||
* (done *after* dual stereo as it needs loop fields to match) */
|
||||
if (!vgmstream->loop_flag) {
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = 0;
|
||||
}
|
||||
|
||||
/* save start things so we can restart when seeking */
|
||||
memcpy(vgmstream->start_ch, vgmstream->ch, sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
||||
memcpy(vgmstream->start_vgmstream, vgmstream, sizeof(VGMSTREAM));
|
||||
|
Loading…
Reference in New Issue
Block a user