Fix some .str+wav [Karaoke Revolution (PS3)]

This commit is contained in:
bnnm 2023-10-14 12:55:19 +02:00
parent 5fe75088fe
commit 681384fb64
3 changed files with 107 additions and 7 deletions

View File

@ -1,8 +1,9 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/layout_utils.h"
typedef enum { PSX, DSP, XBOX, WMA, IMA, XMA2 } strwav_codec;
typedef enum { PSX, DSP, XBOX, WMA, IMA, XMA2, MPEG } strwav_codec;
typedef struct {
int tracks;
int channels;
@ -173,6 +174,26 @@ VGMSTREAM* init_vgmstream_str_wav(STREAMFILE* sf) {
}
#endif
#ifdef VGM_USE_MPEG
case MPEG: {
/* regular MP3 starting with ID2, stereo tracks xN (bgm + vocals) but assuming last (or only one) could be mono */
int layers = (strwav.channels + 1) / 2;
for (int i = 0; i < layers; i++) {
uint32_t size = strwav.interleave;
uint32_t offset = i * size;
const char* ext = "mp3";
int layer_channels = ((layers % 2) && i + 1 == layers) ? 1 : 2;
layered_add_subfile(vgmstream, layers, layer_channels, sf, offset, size, ext, init_vgmstream_mpeg);
}
if (!layered_add_done(vgmstream))
goto fail;
break;
}
#endif
default:
goto fail;
}
@ -712,6 +733,7 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa
/* Tak and the Guardians of Gross (Wii)[2008] */
/* The House of the Dead: Overkill (Wii)[2009] (not Blitz but still the same format) */
/* All Star Karate (Wii)[2010] */
/* Karaoke Revolution (Wii)[2010] */
if ((read_u32be(0x04,sf_h) == 0x00000800 ||
read_u32be(0x04,sf_h) == 0x00000700) && /* rare? */
read_u32be(0x08,sf_h) != 0x00000000 &&
@ -730,11 +752,12 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa
strwav->codec = DSP;
strwav->coefs_table = 0x7c;
strwav->interleave = strwav->channels > 4 ? 0x4000 : 0x8000;
;VGM_LOG("STR+WAV: header TKGG/HOTDO/ASK (Wii)\n");
;VGM_LOG("STR+WAV: header TKGG/HOTDO/ASK/KR (Wii)\n");
return 1;
}
/* The House of the Dead: Overkill (PS3)[2009] (not Blitz but still the same format) */
/* Karaoke Revolution (PS3)[2010] */
if ((read_u32be(0x04,sf_h) == 0x00000800 ||
read_u32be(0x04,sf_h) == 0x00000700) && /* rare? */
read_u32be(0x08,sf_h) != 0x00000000 &&
@ -747,10 +770,24 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa
strwav->sample_rate = read_s32be(0x38,sf_h);
strwav->flags = read_u32be(0x3c,sf_h);
strwav->channels = read_s32be(0x70,sf_h); /* tracks of 1ch */
strwav->interleave = strwav->channels > 4 ? 0x4000 : 0x8000;
strwav->channels = read_s32be(0x70,sf_h);
/* possible flags/ch numbers at 0x4A/61 */
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 */
//C0: stream samples (same as num_samples)
strwav->codec = MPEG; /* full CBR MP3 one after other */
}
else { /* HOTD */
strwav->channels = read_s32be(0x70,sf_h); /* tracks of 1ch */
strwav->interleave = strwav->channels > 4 ? 0x4000 : 0x8000;
strwav->codec = PSX;
}
strwav->codec = PSX;
;VGM_LOG("STR+WAV: header HOTDO (PS3)\n");
return 1;
}

View File

@ -2,9 +2,17 @@
#include "../vgmstream.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) {
if (!vs || !vs->codec_data) {
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*);
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) {
int i;
layered_layout_data* data;
STREAMFILE* temp_sf;
if (!vs) {
goto fail;
}
@ -13,9 +21,54 @@ bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) {
if (!layers)
layers = vs->channels / layer_channels;
switch(vs->layout_type) {
case layout_segmented: //to be improved
goto fail;
case layout_layered:
data = vs->layout_data;
i = data->curr_layer;
break;
default:
data = init_layout_layered(layers);
if (!data) goto fail;
vs->layout_data = data;
vs->layout_type = layout_layered;
i = 0;
break;
}
temp_sf = setup_subfile_streamfile(sf, offset, size, ext);
if (!temp_sf) goto fail;
data->layers[i] = init_vgmstream(temp_sf);
close_streamfile(temp_sf);
if (!data->layers[i]) goto fail;
data->curr_layer++;
return true;
fail:
return false;
}
bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) {
int i;
layered_layout_data* data;
if (!vs || !vs->codec_data) {
goto fail;
}
if (!layer_channels)
layer_channels = 1;
if (!layers)
layers = vs->channels / layer_channels;
switch(vs->layout_type) {
case layout_segmented: //to be improved
goto fail;
@ -65,6 +118,11 @@ bool layered_add_done(VGMSTREAM* vs) {
if (!setup_layout_layered(vs->layout_data))
goto fail;
if (!vs->coding_type) {
layered_layout_data* data = vs->layout_data;
vs->coding_type = data->layers[0]->coding_type;
}
return true;
fail:
return false;

View File

@ -3,6 +3,11 @@
#include "../vgmstream.h"
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 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);