Add .wav DSP/OPUS [Dragon Quest (Switch)]

This commit is contained in:
bnnm 2020-10-11 01:10:02 +02:00
parent 27fd84ca8c
commit 347507a775
6 changed files with 366 additions and 330 deletions

View File

@ -1314,6 +1314,7 @@ static const meta_info meta_info_list[] = {
{meta_ADP_KONAMI, "Konami ADP header"}, {meta_ADP_KONAMI, "Konami ADP header"},
{meta_SDRH, "feelplus SDRH header"}, {meta_SDRH, "feelplus SDRH header"},
{meta_WADY, "Marble WADY header"}, {meta_WADY, "Marble WADY header"},
{meta_DSP_SQEX, "Square Enix DSP header"},
}; };
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {

View File

@ -26,34 +26,35 @@ VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ngc_adpdtk(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ngc_adpdtk(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_std(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ngc_mdsp_std(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_ngc_mdsp_std(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ngc_dsp_stm(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_ngc_dsp_stm(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ngc_mpdsp(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_ngc_mpdsp(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_ngc_dsp_std_int(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_idsp_namco(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_idsp_namco(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_sadb(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_sadb(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_sadf(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_sadf(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_idsp_tt(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_idsp_tt(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_idsp_nl(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_idsp_nl(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_wii_wsd(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_wii_wsd(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_ddsp(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_dsp_ddsp(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_wii_was(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_wii_was(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_str_ig(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_dsp_str_ig(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_xiii(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_dsp_xiii(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_cabelas(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_dsp_cabelas(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_wii_ndp(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_wii_ndp(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ngc_dsp_aaap(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_ngc_dsp_aaap(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_dspw(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_dsp_dspw(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ngc_dsp_iadp(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_ngc_dsp_iadp(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_mcadpcm(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_dsp_mcadpcm(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_switch_audio(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_dsp_switch_audio(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_sps_n1(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_dsp_sps_n1(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_itl_ch(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_dsp_itl_ch(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_adpy(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_dsp_adpy(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_adpx(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_dsp_adpx(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_ds2(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_dsp_ds2(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dsp_itl(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_dsp_itl(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_sqex(STREAMFILE *sf);
VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile);
@ -636,18 +637,18 @@ VGMSTREAM * init_vgmstream_stm(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_opus_std(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_std(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_n1(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_n1(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_capcom(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_capcom(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_nop(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_nop(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_shinen(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_shinen(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_nus3(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_nus3(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_sps_n1(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_sps_n1(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_nxa(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_nxa(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_opusx(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_opusx(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_prototype(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_prototype(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_opusnx(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_opus_opusnx(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_opus_sqex(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_opus_sqex(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_raw_al(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_raw_al(STREAMFILE * streamFile);

File diff suppressed because it is too large Load Diff

View File

@ -5,32 +5,32 @@
/* Nintendo OPUS - from Switch games, including header variations (not the same as Ogg Opus) */ /* Nintendo OPUS - from Switch games, including header variations (not the same as Ogg Opus) */
static VGMSTREAM * init_vgmstream_opus(STREAMFILE *streamFile, meta_t meta_type, off_t offset, int32_t num_samples, int32_t loop_start, int32_t loop_end) { static VGMSTREAM* init_vgmstream_opus(STREAMFILE* sf, meta_t meta_type, off_t offset, int32_t num_samples, int32_t loop_start, int32_t loop_end) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag = 0, channel_count; int loop_flag = 0, channel_count;
off_t data_offset, multichannel_offset = 0; off_t data_offset, multichannel_offset = 0;
size_t data_size, skip = 0; size_t data_size, skip = 0;
if ((uint32_t)read_32bitLE(offset + 0x00,streamFile) != 0x80000001) if ((uint32_t)read_32bitLE(offset + 0x00,sf) != 0x80000001)
goto fail; goto fail;
channel_count = read_8bit(offset + 0x09, streamFile); channel_count = read_8bit(offset + 0x09, sf);
/* 0x0a: packet size if CBR, 0 if VBR */ /* 0x0a: packet size if CBR, 0 if VBR */
data_offset = offset + read_32bitLE(offset + 0x10, streamFile); data_offset = offset + read_32bitLE(offset + 0x10, sf);
skip = read_16bitLE(offset + 0x1c, streamFile); skip = read_16bitLE(offset + 0x1c, sf);
/* 0x1e: ? (seen in Lego Movie 2 (Switch)) */ /* 0x1e: ? (seen in Lego Movie 2 (Switch)) */
/* recent >2ch info [Clannad (Switch)] */ /* recent >2ch info [Clannad (Switch)] */
if ((uint32_t)read_32bitLE(offset + 0x20, streamFile) == 0x80000005) { if ((uint32_t)read_32bitLE(offset + 0x20, sf) == 0x80000005) {
multichannel_offset = offset + 0x20; multichannel_offset = offset + 0x20;
} }
if ((uint32_t)read_32bitLE(data_offset, streamFile) != 0x80000004) if ((uint32_t)read_32bitLE(data_offset, sf) != 0x80000004)
goto fail; goto fail;
data_size = read_32bitLE(data_offset + 0x04, streamFile); data_size = read_32bitLE(data_offset + 0x04, sf);
start_offset = data_offset + 0x08; start_offset = data_offset + 0x08;
loop_flag = (loop_end > 0); /* -1 when not set */ loop_flag = (loop_end > 0); /* -1 when not set */
@ -41,7 +41,7 @@ static VGMSTREAM * init_vgmstream_opus(STREAMFILE *streamFile, meta_t meta_type,
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_type; vgmstream->meta_type = meta_type;
vgmstream->sample_rate = read_32bitLE(offset + 0x0c,streamFile); vgmstream->sample_rate = read_32bitLE(offset + 0x0c,sf);
if (vgmstream->sample_rate == 16000) if (vgmstream->sample_rate == 16000)
vgmstream->sample_rate = 48000; // Grandia HD Collection contains a false sample_rate in header vgmstream->sample_rate = 48000; // Grandia HD Collection contains a false sample_rate in header
vgmstream->num_samples = num_samples; vgmstream->num_samples = num_samples;
@ -59,28 +59,28 @@ static VGMSTREAM * init_vgmstream_opus(STREAMFILE *streamFile, meta_t meta_type,
if (multichannel_offset && vgmstream->channels <= 8) { if (multichannel_offset && vgmstream->channels <= 8) {
int i; int i;
cfg.stream_count = read_8bit(multichannel_offset + 0x08,streamFile); cfg.stream_count = read_8bit(multichannel_offset + 0x08,sf);
cfg.coupled_count = read_8bit(multichannel_offset + 0x09,streamFile); cfg.coupled_count = read_8bit(multichannel_offset + 0x09,sf);
for (i = 0; i < vgmstream->channels; i++) { for (i = 0; i < vgmstream->channels; i++) {
cfg.channel_mapping[i] = read_8bit(multichannel_offset + 0x0a + i,streamFile); cfg.channel_mapping[i] = read_8bit(multichannel_offset + 0x0a + i,sf);
} }
} }
vgmstream->codec_data = init_ffmpeg_switch_opus_config(streamFile, start_offset,data_size, &cfg); vgmstream->codec_data = init_ffmpeg_switch_opus_config(sf, start_offset,data_size, &cfg);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->channel_layout = ffmpeg_get_channel_layout(vgmstream->codec_data); vgmstream->channel_layout = ffmpeg_get_channel_layout(vgmstream->codec_data);
if (vgmstream->num_samples == 0) { if (vgmstream->num_samples == 0) {
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, streamFile) - skip; vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, sf) - skip;
} }
} }
#else #else
goto fail; goto fail;
#endif #endif
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) if ( !vgmstream_open_stream(vgmstream, sf, start_offset) )
goto fail; goto fail;
return vgmstream; return vgmstream;
@ -91,20 +91,20 @@ fail:
/* standard Switch Opus, Nintendo header + raw data (generated by opus_test.c?) [Lego City Undercover (Switch)] */ /* standard Switch Opus, Nintendo header + raw data (generated by opus_test.c?) [Lego City Undercover (Switch)] */
VGMSTREAM * init_vgmstream_opus_std(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_std(STREAMFILE* sf) {
STREAMFILE * PSIFile = NULL; STREAMFILE * PSIFile = NULL;
off_t offset; off_t offset;
int num_samples, loop_start, loop_end; int num_samples, loop_start, loop_end;
/* checks */ /* checks */
if (!check_extensions(streamFile,"opus,lopus")) if (!check_extensions(sf,"opus,lopus"))
goto fail; goto fail;
offset = 0x00; offset = 0x00;
/* BlazBlue: Cross Tag Battle (Switch) PSI Metadata for corresponding Opus */ /* BlazBlue: Cross Tag Battle (Switch) PSI Metadata for corresponding Opus */
/* Maybe future Arc System Works games will use this too? */ /* Maybe future Arc System Works games will use this too? */
PSIFile = open_streamfile_by_ext(streamFile, "psi"); PSIFile = open_streamfile_by_ext(sf, "psi");
if (PSIFile) { if (PSIFile) {
num_samples = read_32bitLE(0x8C, PSIFile); num_samples = read_32bitLE(0x8C, PSIFile);
loop_start = read_32bitLE(0x84, PSIFile); loop_start = read_32bitLE(0x84, PSIFile);
@ -117,56 +117,56 @@ VGMSTREAM * init_vgmstream_opus_std(STREAMFILE *streamFile) {
loop_end = 0; loop_end = 0;
} }
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples,loop_start,loop_end);
fail: fail:
return NULL; return NULL;
} }
/* Nippon1 variation [Disgaea 5 (Switch)] */ /* Nippon1 variation [Disgaea 5 (Switch)] */
VGMSTREAM * init_vgmstream_opus_n1(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_n1(STREAMFILE* sf) {
off_t offset; off_t offset;
int num_samples, loop_start, loop_end; int num_samples, loop_start, loop_end;
/* checks */ /* checks */
if ( !check_extensions(streamFile,"opus,lopus")) if ( !check_extensions(sf,"opus,lopus"))
goto fail; goto fail;
if (!((read_32bitBE(0x04,streamFile) == 0x00000000 && read_32bitBE(0x0c,streamFile) == 0x00000000) || if (!((read_32bitBE(0x04,sf) == 0x00000000 && read_32bitBE(0x0c,sf) == 0x00000000) ||
(read_32bitBE(0x04,streamFile) == 0xFFFFFFFF && read_32bitBE(0x0c,streamFile) == 0xFFFFFFFF))) (read_32bitBE(0x04,sf) == 0xFFFFFFFF && read_32bitBE(0x0c,sf) == 0xFFFFFFFF)))
goto fail; goto fail;
offset = 0x10; offset = 0x10;
num_samples = 0; num_samples = 0;
loop_start = read_32bitLE(0x00,streamFile); loop_start = read_32bitLE(0x00,sf);
loop_end = read_32bitLE(0x08,streamFile); loop_end = read_32bitLE(0x08,sf);
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples,loop_start,loop_end);
fail: fail:
return NULL; return NULL;
} }
/* Capcom variation [Ultra Street Fighter II (Switch), Resident Evil: Revelations (Switch)] */ /* Capcom variation [Ultra Street Fighter II (Switch), Resident Evil: Revelations (Switch)] */
VGMSTREAM * init_vgmstream_opus_capcom(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_capcom(STREAMFILE* sf) {
VGMSTREAM *vgmstream = NULL; VGMSTREAM *vgmstream = NULL;
off_t offset; off_t offset;
int num_samples, loop_start, loop_end; int num_samples, loop_start, loop_end;
int channel_count; int channel_count;
/* checks */ /* checks */
if ( !check_extensions(streamFile,"opus,lopus")) if ( !check_extensions(sf,"opus,lopus"))
goto fail; goto fail;
channel_count = read_32bitLE(0x04,streamFile); channel_count = read_32bitLE(0x04,sf);
if (channel_count != 1 && channel_count != 2 && channel_count != 6) if (channel_count != 1 && channel_count != 2 && channel_count != 6)
goto fail; /* unknown stream layout */ goto fail; /* unknown stream layout */
num_samples = read_32bitLE(0x00,streamFile); num_samples = read_32bitLE(0x00,sf);
/* 0x04: channels, >2 uses interleaved streams (2ch+2ch+2ch) */ /* 0x04: channels, >2 uses interleaved streams (2ch+2ch+2ch) */
loop_start = read_32bitLE(0x08,streamFile); loop_start = read_32bitLE(0x08,sf);
loop_end = read_32bitLE(0x0c,streamFile); loop_end = read_32bitLE(0x0c,sf);
/* 0x10: frame size (with extra data) */ /* 0x10: frame size (with extra data) */
/* 0x14: extra chunk count */ /* 0x14: extra chunk count */
/* 0x18: null */ /* 0x18: null */
offset = read_32bitLE(0x1c,streamFile); offset = read_32bitLE(0x1c,sf);
/* 0x20-8: config? (0x0077C102 04000000 E107070C) */ /* 0x20-8: config? (0x0077C102 04000000 E107070C) */
/* 0x2c: some size? */ /* 0x2c: some size? */
/* 0x30+: extra chunks (0x00: 0x7f, 0x04: num_sample), alt loop starts/regions? */ /* 0x30+: extra chunks (0x00: 0x7f, 0x04: num_sample), alt loop starts/regions? */
@ -193,7 +193,7 @@ VGMSTREAM * init_vgmstream_opus_capcom(STREAMFILE *streamFile) {
/* open each layer subfile */ /* open each layer subfile */
for (i = 0; i < layers; i++) { for (i = 0; i < layers; i++) {
STREAMFILE* temp_sf = setup_opus_interleave_streamfile(streamFile, offset, i, layers); STREAMFILE* temp_sf = setup_opus_interleave_streamfile(sf, offset, i, layers);
if (!temp_sf) goto fail; if (!temp_sf) goto fail;
data->layers[i] = init_vgmstream_opus(temp_sf, meta_OPUS, 0x00, num_samples,loop_start,loop_end); data->layers[i] = init_vgmstream_opus(temp_sf, meta_OPUS, 0x00, num_samples,loop_start,loop_end);
@ -215,7 +215,7 @@ VGMSTREAM * init_vgmstream_opus_capcom(STREAMFILE *streamFile) {
return vgmstream; return vgmstream;
} }
else { else {
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples,loop_start,loop_end);
} }
@ -225,85 +225,85 @@ fail:
} }
/* Procyon Studio variation [Xenoblade Chronicles 2 (Switch)] */ /* Procyon Studio variation [Xenoblade Chronicles 2 (Switch)] */
VGMSTREAM * init_vgmstream_opus_nop(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_nop(STREAMFILE* sf) {
off_t offset; off_t offset;
int num_samples, loop_start = 0, loop_end = 0, loop_flag; int num_samples, loop_start = 0, loop_end = 0, loop_flag;
/* checks */ /* checks */
if (!check_extensions(streamFile,"nop")) if (!check_extensions(sf,"nop"))
goto fail; goto fail;
if (read_32bitBE(0x00, streamFile) != 0x73616466 || /* "sadf" */ if (read_32bitBE(0x00, sf) != 0x73616466 || /* "sadf" */
read_32bitBE(0x08, streamFile) != 0x6f707573) /* "opus" */ read_32bitBE(0x08, sf) != 0x6f707573) /* "opus" */
goto fail; goto fail;
offset = read_32bitLE(0x1c, streamFile); offset = read_32bitLE(0x1c, sf);
num_samples = read_32bitLE(0x28, streamFile); num_samples = read_32bitLE(0x28, sf);
loop_flag = read_8bit(0x19, streamFile); loop_flag = read_8bit(0x19, sf);
if (loop_flag) { if (loop_flag) {
loop_start = read_32bitLE(0x2c, streamFile); loop_start = read_32bitLE(0x2c, sf);
loop_end = read_32bitLE(0x30, streamFile); loop_end = read_32bitLE(0x30, sf);
} }
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples,loop_start,loop_end);
fail: fail:
return NULL; return NULL;
} }
/* Shin'en variation [Fast RMX (Switch)] */ /* Shin'en variation [Fast RMX (Switch)] */
VGMSTREAM * init_vgmstream_opus_shinen(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_shinen(STREAMFILE* sf) {
off_t offset = 0; off_t offset = 0;
int num_samples, loop_start, loop_end; int num_samples, loop_start, loop_end;
/* checks */ /* checks */
if ( !check_extensions(streamFile,"opus,lopus")) if ( !check_extensions(sf,"opus,lopus"))
goto fail; goto fail;
if (read_32bitBE(0x08,streamFile) != 0x01000080) if (read_32bitBE(0x08,sf) != 0x01000080)
goto fail; goto fail;
offset = 0x08; offset = 0x08;
num_samples = 0; num_samples = 0;
loop_start = read_32bitLE(0x00,streamFile); loop_start = read_32bitLE(0x00,sf);
loop_end = read_32bitLE(0x04,streamFile); /* 0 if no loop */ loop_end = read_32bitLE(0x04,sf); /* 0 if no loop */
if (loop_start > loop_end) if (loop_start > loop_end)
goto fail; /* just in case */ goto fail; /* just in case */
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples,loop_start,loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples,loop_start,loop_end);
fail: fail:
return NULL; return NULL;
} }
/* Bandai Namco Opus (found in NUS3Banks) [Taiko no Tatsujin: Nintendo Switch Version!] */ /* Bandai Namco Opus (found in NUS3Banks) [Taiko no Tatsujin: Nintendo Switch Version!] */
VGMSTREAM * init_vgmstream_opus_nus3(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_nus3(STREAMFILE* sf) {
off_t offset = 0; off_t offset = 0;
int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag;
/* checks */ /* checks */
/* .opus: header ID (they only exist inside .nus3bank) */ /* .opus: header ID (they only exist inside .nus3bank) */
if (!check_extensions(streamFile, "opus,lopus")) if (!check_extensions(sf, "opus,lopus"))
goto fail; goto fail;
if (read_32bitBE(0x00, streamFile) != 0x4F505553) /* "OPUS" */ if (read_32bitBE(0x00, sf) != 0x4F505553) /* "OPUS" */
goto fail; goto fail;
/* Here's an interesting quirk, OPUS header contains big endian values /* Here's an interesting quirk, OPUS header contains big endian values
while the Nintendo Opus header and data that follows remain little endian as usual */ while the Nintendo Opus header and data that follows remain little endian as usual */
offset = read_32bitBE(0x20, streamFile); offset = read_32bitBE(0x20, sf);
num_samples = read_32bitBE(0x08, streamFile); num_samples = read_32bitBE(0x08, sf);
/* Check if there's a loop end value to determine loop_flag*/ /* Check if there's a loop end value to determine loop_flag*/
loop_flag = read_32bitBE(0x18, streamFile); loop_flag = read_32bitBE(0x18, sf);
if (loop_flag) { if (loop_flag) {
loop_start = read_32bitBE(0x14, streamFile); loop_start = read_32bitBE(0x14, sf);
loop_end = read_32bitBE(0x18, streamFile); loop_end = read_32bitBE(0x18, sf);
} }
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples, loop_start, loop_end);
fail: fail:
return NULL; return NULL;
} }
/* Nippon Ichi SPS wrapper (non-segmented) [Ys VIII: Lacrimosa of Dana (Switch)] */ /* Nippon Ichi SPS wrapper (non-segmented) [Ys VIII: Lacrimosa of Dana (Switch)] */
VGMSTREAM * init_vgmstream_opus_sps_n1(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_sps_n1(STREAMFILE* sf) {
off_t offset; off_t offset;
int num_samples, loop_start = 0, loop_end = 0, loop_flag; int num_samples, loop_start = 0, loop_end = 0, loop_flag;
@ -311,28 +311,28 @@ VGMSTREAM * init_vgmstream_opus_sps_n1(STREAMFILE *streamFile) {
/* .sps: Labyrinth of Refrain: Coven of Dusk (Switch) /* .sps: Labyrinth of Refrain: Coven of Dusk (Switch)
* .nlsd: Disgaea Refine (Switch), Ys VIII (Switch) * .nlsd: Disgaea Refine (Switch), Ys VIII (Switch)
* .at9: void tRrLM(); //Void Terrarium (Switch) */ * .at9: void tRrLM(); //Void Terrarium (Switch) */
if (!check_extensions(streamFile, "sps,nlsd,at9")) if (!check_extensions(sf, "sps,nlsd,at9"))
goto fail; goto fail;
if (read_32bitBE(0x00, streamFile) != 0x09000000) /* file type (see other N1 SPS) */ if (read_32bitBE(0x00, sf) != 0x09000000) /* file type (see other N1 SPS) */
goto fail; goto fail;
num_samples = read_32bitLE(0x0C, streamFile); num_samples = read_32bitLE(0x0C, sf);
if (read_32bitBE(0x1c, streamFile) == 0x01000080) { if (read_32bitBE(0x1c, sf) == 0x01000080) {
offset = 0x1C; offset = 0x1C;
/* older games loop section (remnant of segmented opus_sps_n1): */ /* older games loop section (remnant of segmented opus_sps_n1): */
loop_start = read_32bitLE(0x10, streamFile); /* intro samples */ loop_start = read_32bitLE(0x10, sf); /* intro samples */
loop_end = loop_start + read_32bitLE(0x14, streamFile); /* loop samples */ loop_end = loop_start + read_32bitLE(0x14, sf); /* loop samples */
/* 0x18: end samples (all must add up to num_samples) */ /* 0x18: end samples (all must add up to num_samples) */
loop_flag = read_32bitLE(0x18, streamFile); /* with loop disabled only loop_end has a value */ loop_flag = read_32bitLE(0x18, sf); /* with loop disabled only loop_end has a value */
} }
else { else {
offset = 0x18; offset = 0x18;
/* newer games loop section: */ /* newer games loop section: */
loop_start = read_32bitLE(0x10, streamFile); loop_start = read_32bitLE(0x10, sf);
loop_end = read_32bitLE(0x14, streamFile); loop_end = read_32bitLE(0x14, sf);
loop_flag = loop_start != loop_end; /* with loop disabled start and end are the same as num samples */ loop_flag = loop_start != loop_end; /* with loop disabled start and end are the same as num samples */
} }
@ -341,29 +341,29 @@ VGMSTREAM * init_vgmstream_opus_sps_n1(STREAMFILE *streamFile) {
loop_end = 0; loop_end = 0;
} }
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples, loop_start, loop_end);
fail: fail:
return NULL; return NULL;
} }
/* AQUASTYLE wrapper [Touhou Genso Wanderer -Reloaded- (Switch)] */ /* AQUASTYLE wrapper [Touhou Genso Wanderer -Reloaded- (Switch)] */
VGMSTREAM * init_vgmstream_opus_opusx(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_opusx(STREAMFILE* sf) {
off_t offset; off_t offset;
int num_samples, loop_start = 0, loop_end = 0; int num_samples, loop_start = 0, loop_end = 0;
float modifier; float modifier;
/* checks */ /* checks */
if (!check_extensions(streamFile, "opusx")) if (!check_extensions(sf, "opusx"))
goto fail; goto fail;
if (read_32bitBE(0x00, streamFile) != 0x4F505553) /* "OPUS" */ if (read_32bitBE(0x00, sf) != 0x4F505553) /* "OPUS" */
goto fail; goto fail;
offset = 0x10; offset = 0x10;
/* values are for the original 44100 files, but Opus resamples to 48000 */ /* values are for the original 44100 files, but Opus resamples to 48000 */
modifier = 48000.0f / 44100.0f; modifier = 48000.0f / 44100.0f;
num_samples = 0;//read_32bitLE(0x04, streamFile) * modifier; /* better use calc'd num_samples */ num_samples = 0;//read_32bitLE(0x04, sf) * modifier; /* better use calc'd num_samples */
loop_start = read_32bitLE(0x08, streamFile) * modifier; loop_start = read_32bitLE(0x08, sf) * modifier;
loop_end = read_32bitLE(0x0c, streamFile) * modifier; loop_end = read_32bitLE(0x0c, sf) * modifier;
/* resampling calcs are slighly off and may to over num_samples, but by removing delay seems ok */ /* resampling calcs are slighly off and may to over num_samples, but by removing delay seems ok */
if (loop_start >= 120) { if (loop_start >= 120) {
@ -374,81 +374,83 @@ VGMSTREAM * init_vgmstream_opus_opusx(STREAMFILE *streamFile) {
loop_end = 0; loop_end = 0;
} }
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples, loop_start, loop_end);
fail: fail:
return NULL; return NULL;
} }
/* Prototype variation [Clannad (Switch)] */ /* Prototype variation [Clannad (Switch)] */
VGMSTREAM * init_vgmstream_opus_prototype(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_prototype(STREAMFILE* sf) {
off_t offset = 0; off_t offset = 0;
int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag;
/* checks */ /* checks */
if (!check_extensions(streamFile, "opus,lopus")) if (!check_extensions(sf, "opus,lopus"))
goto fail; goto fail;
if (read_32bitBE(0x00, streamFile) != 0x4F505553 || /* "OPUS" */ if (read_32bitBE(0x00, sf) != 0x4F505553 || /* "OPUS" */
read_32bitBE(0x18, streamFile) != 0x01000080) read_32bitBE(0x18, sf) != 0x01000080)
goto fail; goto fail;
offset = 0x18; offset = 0x18;
num_samples = read_32bitLE(0x08, streamFile); num_samples = read_32bitLE(0x08, sf);
/* Check if there's a loop end value to determine loop_flag*/ /* Check if there's a loop end value to determine loop_flag*/
loop_flag = read_32bitLE(0x10, streamFile); loop_flag = read_32bitLE(0x10, sf);
if (loop_flag) { if (loop_flag) {
loop_start = read_32bitLE(0x0C, streamFile); loop_start = read_32bitLE(0x0C, sf);
loop_end = read_32bitLE(0x10, streamFile); loop_end = read_32bitLE(0x10, sf);
} }
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples, loop_start, loop_end);
fail: fail:
return NULL; return NULL;
} }
/* Edelweiss variation [Astebreed (Switch)] */ /* Edelweiss variation [Astebreed (Switch)] */
VGMSTREAM * init_vgmstream_opus_opusnx(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_opusnx(STREAMFILE* sf) {
off_t offset = 0; off_t offset = 0;
int num_samples = 0, loop_start = 0, loop_end = 0; int num_samples = 0, loop_start = 0, loop_end = 0;
/* checks */ /* checks */
if (!check_extensions(streamFile, "opus,lopus")) if (!check_extensions(sf, "opus,lopus"))
goto fail; goto fail;
if (read_64bitBE(0x00, streamFile) != 0x4F5055534E580000) /* "OPUSNX\0\0" */ if (read_64bitBE(0x00, sf) != 0x4F5055534E580000) /* "OPUSNX\0\0" */
goto fail; goto fail;
offset = 0x10; offset = 0x10;
num_samples = 0; //read_32bitLE(0x08, streamFile); /* samples with encoder delay */ num_samples = 0; //read_32bitLE(0x08, sf); /* samples with encoder delay */
if (read_32bitLE(0x0c, streamFile) != 0) if (read_32bitLE(0x0c, sf) != 0)
goto fail; goto fail;
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples, loop_start, loop_end);
fail: fail:
return NULL; return NULL;
} }
/* Square Enix variation [Dragon Quest I-III (Switch)] */ /* Square Enix variation [Dragon Quest I-III (Switch)] */
VGMSTREAM * init_vgmstream_opus_sqex(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_opus_sqex(STREAMFILE* sf) {
off_t offset = 0; off_t offset = 0;
int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag; int num_samples = 0, loop_start = 0, loop_end = 0, loop_flag;
/* checks */ /* checks */
if (!check_extensions(streamFile, "opus,lopus")) /* .wav: default
* .opus: fake? */
if (!check_extensions(sf, "wav,lwav,opus,lopus"))
goto fail; goto fail;
if (read_64bitBE(0x00, streamFile) != 0x0100000002000000) if (read_u32be(0x00, sf) != 0x01000000)
goto fail; goto fail;
/* 0x04: channels */
offset = read_32bitLE(0x0C, streamFile); /* 0x08: data_size */
num_samples = read_32bitLE(0x1C, streamFile); offset = read_32bitLE(0x0C, sf);
num_samples = read_32bitLE(0x1C, sf);
/* Check if there's a loop end value to determine loop_flag*/
loop_flag = read_32bitLE(0x18, streamFile); loop_flag = read_32bitLE(0x18, sf);
if (loop_flag) { if (loop_flag) {
loop_start = read_32bitLE(0x14, streamFile); loop_start = read_32bitLE(0x14, sf);
loop_end = read_32bitLE(0x18, streamFile); loop_end = read_32bitLE(0x18, sf);
} }
return init_vgmstream_opus(streamFile, meta_OPUS, offset, num_samples, loop_start, loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples, loop_start, loop_end);
fail: fail:
return NULL; return NULL;
} }

View File

@ -512,6 +512,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_xse_new, init_vgmstream_xse_new,
init_vgmstream_xse_old, init_vgmstream_xse_old,
init_vgmstream_wady, init_vgmstream_wady,
init_vgmstream_dsp_sqex,
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */ /* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */ init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */

View File

@ -741,6 +741,7 @@ typedef enum {
meta_ADP_KONAMI, meta_ADP_KONAMI,
meta_SDRH, meta_SDRH,
meta_WADY, meta_WADY,
meta_DSP_SQEX,
} meta_t; } meta_t;
/* standard WAVEFORMATEXTENSIBLE speaker positions */ /* standard WAVEFORMATEXTENSIBLE speaker positions */