Updated VGMStream to r1951-100-g73ef7c6c
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
de43b1b226
commit
aa491fe0bb
12 changed files with 1578 additions and 1374 deletions
|
@ -458,6 +458,7 @@
|
|||
835C883722CC17BE001B4B3F /* ogg_vorbis_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 835C883522CC17BE001B4B3F /* ogg_vorbis_streamfile.h */; };
|
||||
835DF7032C79ABB50008814A /* sbuf.c in Sources */ = {isa = PBXBuildFile; fileRef = 835DF7022C79ABB50008814A /* sbuf.c */; };
|
||||
835DF7052C79AED70008814A /* play_state.c in Sources */ = {isa = PBXBuildFile; fileRef = 835DF7042C79AED70008814A /* play_state.c */; };
|
||||
836581A62CF3E53600E26C58 /* sdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836581A52CF3E53600E26C58 /* sdd.c */; };
|
||||
836C052B23F62F1A00FA07C7 /* libatrac9.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 835FC6C623F62AEF006960FA /* libatrac9.framework */; };
|
||||
836C052C23F62F3100FA07C7 /* libatrac9.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 835FC6C623F62AEF006960FA /* libatrac9.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
836DF622298F83F400CD0580 /* cri_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 836DF61F298F83F400CD0580 /* cri_keys.h */; };
|
||||
|
@ -1370,6 +1371,7 @@
|
|||
835DF7022C79ABB50008814A /* sbuf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sbuf.c; sourceTree = "<group>"; };
|
||||
835DF7042C79AED70008814A /* play_state.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = play_state.c; sourceTree = "<group>"; };
|
||||
835FC6C123F62AEE006960FA /* libatrac9.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libatrac9.xcodeproj; path = ../libatrac9/libatrac9.xcodeproj; sourceTree = "<group>"; };
|
||||
836581A52CF3E53600E26C58 /* sdd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sdd.c; sourceTree = "<group>"; };
|
||||
836DF61F298F83F400CD0580 /* cri_keys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cri_keys.h; sourceTree = "<group>"; };
|
||||
836DF620298F83F400CD0580 /* bitstream_msb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitstream_msb.h; sourceTree = "<group>"; };
|
||||
836DF621298F83F400CD0580 /* cri_keys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cri_keys.c; sourceTree = "<group>"; };
|
||||
|
@ -2520,6 +2522,7 @@
|
|||
8399335E2591E8C0001855AF /* sbk.c */,
|
||||
8349A8F51FE6257D00E26435 /* scd_pcm.c */,
|
||||
836F6EEE18BDC2190095E648 /* sd9.c */,
|
||||
836581A52CF3E53600E26C58 /* sdd.c */,
|
||||
834FE0E6215C79EC000A5D3D /* sdf.c */,
|
||||
83A8BAE225667AA7000F5F3F /* sdrh.c */,
|
||||
836F6EEF18BDC2190095E648 /* sdt.c */,
|
||||
|
@ -3209,6 +3212,7 @@
|
|||
83FBB17D2A4FF87200CD0580 /* sf_utils.c in Sources */,
|
||||
8349A91F1FE6258200E26435 /* naac.c in Sources */,
|
||||
834F7DD22C7093EA003AC386 /* ice_decoder.c in Sources */,
|
||||
836581A62CF3E53600E26C58 /* sdd.c in Sources */,
|
||||
83AFABBE23795202002F3947 /* isb.c in Sources */,
|
||||
836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */,
|
||||
836F703C18BDC2190095E648 /* bns.c in Sources */,
|
||||
|
|
|
@ -499,6 +499,7 @@ static const char* extension_list[] = {
|
|||
"scd",
|
||||
"sch",
|
||||
"sd9",
|
||||
"sdd",
|
||||
"sdl",
|
||||
"sdp", //txth/reserved [Metal Gear Arcade (AC)]
|
||||
"sdf",
|
||||
|
@ -1446,6 +1447,7 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_EA_SBK, "Electronic Arts SBK header"},
|
||||
{meta_DSP_ASURA, "Rebellion DSP header"},
|
||||
{meta_ONGAKUKAN_RIFF_ADP, "Ongakukan RIFF WAVE header"},
|
||||
{meta_SDD, "Doki Denki DSBH header"},
|
||||
};
|
||||
|
||||
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
|
||||
|
|
|
@ -156,7 +156,7 @@ VGMSTREAM* init_vgmstream_awc(STREAMFILE* sf) {
|
|||
#endif
|
||||
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
case 0x0F: { /* ATRAC9 (PC) [Red Dead Redemption (PS4)] */
|
||||
case 0x0F: { /* ATRAC9 (PS4) [Red Dead Redemption (PS4)] */
|
||||
if (awc.is_streamed) {
|
||||
vgmstream->layout_data = build_layered_awc(sf_body, &awc);
|
||||
if (!vgmstream->layout_data) goto fail;
|
||||
|
@ -205,6 +205,50 @@ VGMSTREAM* init_vgmstream_awc(STREAMFILE* sf) {
|
|||
}
|
||||
break;
|
||||
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
case 0x0D: { /* OPUS (PC) [Red Dead Redemption (PC)] */
|
||||
if (awc.is_streamed) {
|
||||
vgmstream->layout_data = build_layered_awc(sf_body, &awc);
|
||||
if (!vgmstream->layout_data) goto fail;
|
||||
vgmstream->layout_type = layout_layered;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
}
|
||||
else {
|
||||
VGM_LOG("AWC: unknown non-streamed Opus mode\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case 0x11: { /* RIFF-MSADPCM (PC) [Red Dead Redemption (PC)] */
|
||||
if (awc.is_streamed) {
|
||||
VGM_LOG("AWC: unknown streamed mode for codec 0x%02x\n", awc.codec);
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
VGMSTREAM* temp_vs = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
|
||||
temp_sf = setup_subfile_streamfile(sf_body, awc.stream_offset, awc.stream_size, "wav");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
temp_vs = init_vgmstream_riff(temp_sf);
|
||||
close_streamfile(temp_sf);
|
||||
if (!temp_vs) goto fail;
|
||||
|
||||
temp_vs->num_streams = vgmstream->num_streams;
|
||||
temp_vs->stream_size = vgmstream->stream_size;
|
||||
temp_vs->meta_type = vgmstream->meta_type;
|
||||
strcpy(temp_vs->stream_name, vgmstream->stream_name);
|
||||
|
||||
close_vgmstream(vgmstream);
|
||||
//vgmstream = temp_vs;
|
||||
return temp_vs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xFF:
|
||||
vgmstream->coding_type = coding_SILENCE;
|
||||
snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "[%s]", "midi");
|
||||
|
@ -617,6 +661,24 @@ static VGMSTREAM* build_blocks_vgmstream(STREAMFILE* sf, awc_header* awc, int ch
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 0x0D: {
|
||||
opus_config cfg = {0};
|
||||
|
||||
/* read from first block (all blocks have it but same thing), see awc_streamfile.h */
|
||||
uint32_t frame_size_offset = awc->stream_offset + 0x10 * awc->channels + 0x70 * channel + 0x04;
|
||||
|
||||
cfg.frame_size = read_u16le(frame_size_offset, sf); // always 0x50?
|
||||
cfg.channels = 1;
|
||||
|
||||
vgmstream->codec_data = init_ffmpeg_fixed_opus(temp_sf, substream_offset, substream_size, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
case 0x0F: {
|
||||
atrac9_config cfg = {0};
|
||||
|
@ -669,9 +731,8 @@ fail:
|
|||
// independently.
|
||||
//
|
||||
// This can be simulated by making one decoder per block (segmented, but opens too many SFs and can't skip
|
||||
// samples correctly), or with a custom STREAMFILE that skips repeated block (works ok-ish but not all codecs).
|
||||
// samples correctly), or with a custom STREAMFILE that skips repeated block (works ok-ish).
|
||||
static layered_layout_data* build_layered_awc(STREAMFILE* sf, awc_header* awc) {
|
||||
int i;
|
||||
layered_layout_data* data = NULL;
|
||||
|
||||
|
||||
|
@ -680,7 +741,7 @@ static layered_layout_data* build_layered_awc(STREAMFILE* sf, awc_header* awc) {
|
|||
if (!data) goto fail;
|
||||
|
||||
/* open each layer subfile */
|
||||
for (i = 0; i < awc->channels; i++) {
|
||||
for (int i = 0; i < awc->channels; i++) {
|
||||
data->layers[i] = build_blocks_vgmstream(sf, awc, i);
|
||||
if (!data->layers[i]) goto fail;
|
||||
}
|
||||
|
|
|
@ -61,9 +61,9 @@ typedef struct {
|
|||
* 0x00: "D11A"
|
||||
* 0x04: frame size
|
||||
* 0x06: frame samples
|
||||
* 0x08: flags? (0x0103=AT9, 0x0104=DSP)
|
||||
* 0x08: flags? (0x0101=OPUS, 0x0103=AT9, 0x0104=DSP)
|
||||
* 0x0a: sample rate
|
||||
* 0x0c: ATRAC9 config (repeated but same for all blocks) or "D11E" (DSP)
|
||||
* 0x0c: ATRAC9 config (repeated but same for all blocks) or "D11E" (OPUS/DSP)
|
||||
* 0x10-0x70: padding with 0x77 (ATRAC3) or standard DSP header for original full file (DSP)
|
||||
* - padding up to data start, depending on codec (DSP/ATRAC9: none, others: aligned to 0x800)
|
||||
*/
|
||||
|
@ -91,6 +91,7 @@ static bool read_awc_block(STREAMFILE* sf, awc_block_info_t* bi) {
|
|||
extra_entry_size = 0x00;
|
||||
header_padding = 0x800;
|
||||
break;
|
||||
case 0x0D: /* OPUS */
|
||||
case 0x0F: /* ATRAC9 */
|
||||
channel_entry_size = 0x10;
|
||||
seek_entry_size = 0x00;
|
||||
|
@ -136,6 +137,7 @@ static bool read_awc_block(STREAMFILE* sf, awc_block_info_t* bi) {
|
|||
bi->blk[ch].chunk_size = align_size_to_block(bi->blk[ch].channel_size, 0x10);
|
||||
//bi->blk[ch].channel_size = (pre-loaded);
|
||||
break;
|
||||
case 0x0D: /* OPUS */
|
||||
case 0x0F: /* ATRAC9 */
|
||||
bi->blk[ch].frame_size = read_u16(offset + 0x04, sf);
|
||||
bi->blk[ch].chunk_size = bi->blk[ch].entries * bi->blk[ch].frame_size;
|
||||
|
@ -217,6 +219,7 @@ static uint32_t get_block_repeated_size(STREAMFILE* sf, awc_block_info_t* bi, in
|
|||
return skip_size; /* skip_size fills frame size */
|
||||
}
|
||||
|
||||
case 0x0D: /* OPUS */
|
||||
case 0x0F: /* ATRAC9 */
|
||||
default:
|
||||
VGM_LOG("AWC: found channel skip in codec %x\n", bi->codec); /* not seen */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1011,4 +1011,6 @@ VGMSTREAM* init_vgmstream_dsp_asura_sfx(STREAMFILE* sf);
|
|||
|
||||
VGMSTREAM* init_vgmstream_adp_ongakukan(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM* init_vgmstream_sdd(STREAMFILE* sf);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
|
122
Frameworks/vgmstream/vgmstream/src/meta/sdd.c
Normal file
122
Frameworks/vgmstream/vgmstream/src/meta/sdd.c
Normal file
|
@ -0,0 +1,122 @@
|
|||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
/* .SDD - from Piglet's Big Game (PS2/GC) */
|
||||
VGMSTREAM* init_vgmstream_sdd(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
uint32_t header_size, data_size, sample_rate, sound_offset, sound_size;
|
||||
uint8_t codec, channels;
|
||||
off_t table_offset, data_offset, entry_offset, name_offset;
|
||||
size_t name_size;
|
||||
int target_subsong = sf->stream_index, total_subsongs, loop_flag;
|
||||
|
||||
if (!is_id32be(0x00, sf, "DSBH"))
|
||||
goto fail;
|
||||
|
||||
if (!check_extensions(sf, "sdd"))
|
||||
goto fail;
|
||||
|
||||
/* always little endian, even on GC */
|
||||
header_size = read_u32le(0x04, sf);
|
||||
table_offset = 0x20;
|
||||
|
||||
/* haven't seen any filenames larger than 16 bytes so should be safe */
|
||||
total_subsongs = (header_size - table_offset) / 0x20;
|
||||
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1)
|
||||
goto fail;
|
||||
|
||||
/* get name buffer size */
|
||||
name_offset = table_offset + (target_subsong - 1) * 0x20;
|
||||
name_size = read_string(NULL, STREAM_NAME_SIZE, name_offset, sf) + 1;
|
||||
|
||||
entry_offset = name_offset + name_size;
|
||||
codec = read_u8(entry_offset + 0x00, sf);
|
||||
//bps = read_u8(entry_offset + 0x01, sf);
|
||||
channels = read_u8(entry_offset + 0x02, sf);
|
||||
sample_rate = read_u32le(entry_offset + 0x03, sf);
|
||||
sound_offset = read_u32le(entry_offset + 0x07, sf);
|
||||
sound_size = read_u32le(entry_offset + 0x0b, sf);
|
||||
|
||||
/* no stereo samples seen */
|
||||
if (channels > 1)
|
||||
goto fail;
|
||||
|
||||
data_offset = header_size;
|
||||
if (!is_id32be(data_offset, sf, "DSBD"))
|
||||
goto fail;
|
||||
|
||||
data_size = read_u32le(data_offset + 0x04, sf);
|
||||
if (data_offset + data_size > get_streamfile_size(sf))
|
||||
goto fail;
|
||||
|
||||
sound_offset += data_offset + 0x20;
|
||||
loop_flag = 0;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_SDD;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->stream_size = sound_size;
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
read_string(vgmstream->stream_name, STREAM_NAME_SIZE, name_offset, sf);
|
||||
|
||||
switch (codec) {
|
||||
case 0x01: /* DSP */
|
||||
/* starts with incomplete DSP header (nibble count not set) */
|
||||
if (sound_size < 0x60)
|
||||
goto fail;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->num_samples = read_u32be(sound_offset + 0x00, sf);
|
||||
|
||||
/* set coefs and initial history */
|
||||
dsp_read_coefs_be(vgmstream, sf, sound_offset + 0x1c, 0x00);
|
||||
vgmstream->ch[0].adpcm_history1_16 = read_u16be(sound_offset + 0x40, sf);
|
||||
vgmstream->ch[0].adpcm_history2_16 = read_u16be(sound_offset + 0x42, sf);
|
||||
|
||||
sound_offset += 0x60;
|
||||
vgmstream->stream_size -= 0x60;
|
||||
break;
|
||||
case 0x02: { /* PCM */
|
||||
off_t chunk_offset;
|
||||
size_t chunk_size;
|
||||
|
||||
/* stored as RIFF */
|
||||
sound_offset += 0x0c;
|
||||
sound_size -= 0x0c;
|
||||
|
||||
/* find "data" chunk */
|
||||
if (!find_chunk_riff_le(sf, 0x64617461, sound_offset, sound_size, &chunk_offset, &chunk_size))
|
||||
goto fail;
|
||||
|
||||
vgmstream->coding_type = coding_PCM16LE;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->num_samples = pcm16_bytes_to_samples(chunk_size, channels);
|
||||
|
||||
sound_offset = chunk_offset;
|
||||
vgmstream->stream_size = chunk_size;
|
||||
break;
|
||||
}
|
||||
case 0x03: /* PSX */
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->num_samples = ps_bytes_to_samples(sound_size, channels);
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, sound_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
|
@ -109,7 +109,7 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
|
|||
uint32_t stream_offset;
|
||||
chunk_offset += 0x08 + 0x38 * (target_subsong-1); /* position in target header*/
|
||||
|
||||
/* 0x00: ? (00/01/02) */
|
||||
/* 0x00: flags? (00/01/02) */
|
||||
name_offset = read_u32le(chunk_offset+0x04,sf_head);
|
||||
codec = read_u8(chunk_offset+0x08,sf_head);
|
||||
channels = read_u8(chunk_offset+0x09,sf_head);
|
||||
|
@ -119,16 +119,14 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
|
|||
/* 0x10: info_type, meaning of the next value
|
||||
* (00=null, 30/40=data size without padding (ADPCM, ATRAC3plus), 80/A0=block size (AC3) */
|
||||
/* 0x14: info_value (see above) */
|
||||
/* 0x18: unknown (ex. 0x0008/0010/3307/CC02/etc, RGND related?) x2 */
|
||||
/* 0x18: vol L + vol R? */
|
||||
/* 0x1c: null */
|
||||
|
||||
num_samples = read_s32le(chunk_offset+0x20,sf_head);
|
||||
loop_start_sample = read_s32le(chunk_offset+0x24,sf_head);
|
||||
loop_end_sample = read_s32le(chunk_offset+0x28,sf_head);
|
||||
stream_size = read_u32le(chunk_offset+0x2c,sf_head); /* stream size (without padding) / interleave (for type3) */
|
||||
|
||||
stream_offset = read_u32le(chunk_offset+0x30,sf_head);
|
||||
|
||||
/* 0x34: SGD/SGH = stream size (with padding) / interleave */
|
||||
|
||||
loop_flag = loop_start_sample != -1 && loop_end_sample != -1;
|
||||
|
@ -216,6 +214,8 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
|
|||
}
|
||||
#endif
|
||||
|
||||
// 0x00: PCM16LE?
|
||||
// https://github.com/Nenkai/010GameTemplates/blob/main/Sony/SGXD.bt
|
||||
default:
|
||||
VGM_LOG("SGDX: unknown codec %i\n", codec);
|
||||
goto fail;
|
||||
|
|
|
@ -3,83 +3,83 @@
|
|||
|
||||
/* .APM - seen in old Ubisoft games [Rayman 2: The Great Escape (PC), Donald Duck: Goin' Quackers (PC)] */
|
||||
VGMSTREAM* init_vgmstream_ubi_apm(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
uint32_t channels, sample_rate, file_size, nibble_size;
|
||||
off_t start_offset;
|
||||
int loop_flag;
|
||||
uint32_t i;
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
uint32_t channels, sample_rate, file_size, nibble_size;
|
||||
off_t start_offset;
|
||||
int loop_flag;
|
||||
uint32_t i;
|
||||
|
||||
if (read_u16le(0x00, sf) != 0x2000 || !is_id32be(0x14, sf, "vs12"))
|
||||
goto fail;
|
||||
if (read_u16le(0x00, sf) != 0x2000 || !is_id32be(0x14, sf, "vs12"))
|
||||
goto fail;
|
||||
|
||||
if (!check_extensions(sf, "apm"))
|
||||
goto fail;
|
||||
if (!check_extensions(sf, "apm"))
|
||||
goto fail;
|
||||
|
||||
/* (info from https://github.com/Synthesis/ray2get)
|
||||
* 0x00(2): format tag (0x2000 for Ubisoft ADPCM)
|
||||
* 0x02(2): channels
|
||||
* 0x04(4): sample rate
|
||||
* 0x08(4): byte rate? PCM samples?
|
||||
* 0x0C(2): block align
|
||||
* 0x0E(2): bits per sample
|
||||
* 0x10(4): header size
|
||||
* 0x14(4): "vs12"
|
||||
* 0x18(4): file size
|
||||
* 0x1C(4): nibble size
|
||||
* 0x20(4): -1?
|
||||
* 0x24(4): 0?
|
||||
* 0x28(4): high/low nibble flag (when loaded in memory)
|
||||
* 0x2C(N): ADPCM info per channel, last to first
|
||||
* - 0x00(4): ADPCM hist
|
||||
* - 0x04(4): ADPCM step index
|
||||
* - 0x08(4): copy of ADPCM data (after interleave, ex. R from data + 0x01)
|
||||
* 0x60(4): "DATA"
|
||||
* 0x64(N): ADPCM data
|
||||
*/
|
||||
/* (info from https://github.com/Synthesis/ray2get)
|
||||
* 0x00(2): format tag (0x2000 for Ubisoft ADPCM)
|
||||
* 0x02(2): channels
|
||||
* 0x04(4): sample rate
|
||||
* 0x08(4): byte rate? PCM samples?
|
||||
* 0x0C(2): block align
|
||||
* 0x0E(2): bits per sample
|
||||
* 0x10(4): header size
|
||||
* 0x14(4): "vs12"
|
||||
* 0x18(4): file size
|
||||
* 0x1C(4): nibble size
|
||||
* 0x20(4): -1?
|
||||
* 0x24(4): 0?
|
||||
* 0x28(4): high/low nibble flag (when loaded in memory)
|
||||
* 0x2C(N): ADPCM info per channel, last to first
|
||||
* - 0x00(4): ADPCM hist
|
||||
* - 0x04(4): ADPCM step index
|
||||
* - 0x08(4): copy of ADPCM data (after interleave, ex. R from data + 0x01)
|
||||
* 0x60(4): "DATA"
|
||||
* 0x64(N): ADPCM data
|
||||
*/
|
||||
|
||||
channels = read_u16le(0x02, sf);
|
||||
sample_rate = read_u32le(0x04, sf);
|
||||
file_size = read_u32le(0x18, sf);
|
||||
nibble_size = read_u32le(0x1c, sf);
|
||||
channels = read_u16le(0x02, sf);
|
||||
sample_rate = read_u32le(0x04, sf);
|
||||
file_size = read_u32le(0x18, sf);
|
||||
nibble_size = read_u32le(0x1c, sf);
|
||||
|
||||
start_offset = 0x64;
|
||||
start_offset = 0x64;
|
||||
|
||||
if (file_size != get_streamfile_size(sf))
|
||||
goto fail;
|
||||
if (file_size != get_streamfile_size(sf))
|
||||
goto fail;
|
||||
|
||||
if (nibble_size > (file_size - start_offset))
|
||||
goto fail;
|
||||
if (nibble_size > (file_size - start_offset))
|
||||
goto fail;
|
||||
|
||||
if (!is_id32be(0x60, sf, "DATA"))
|
||||
goto fail;
|
||||
if (!is_id32be(0x60, sf, "DATA"))
|
||||
goto fail;
|
||||
|
||||
loop_flag = 0;
|
||||
loop_flag = 0;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_UBI_APM;
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x01;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = ima_bytes_to_samples(file_size - start_offset, channels);
|
||||
vgmstream->meta_type = meta_UBI_APM;
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x01;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = ima_bytes_to_samples(file_size - start_offset, channels);
|
||||
|
||||
/* read initial hist (last to first) */
|
||||
for (i = 0; i < channels; i++) {
|
||||
vgmstream->ch[i].adpcm_history1_32 = read_s32le(0x2c + 0x0c * (channels - 1 - i) + 0x00, sf);
|
||||
vgmstream->ch[i].adpcm_step_index = read_s32le(0x2c + 0x0c * (channels - 1 - i) + 0x04, sf);
|
||||
}
|
||||
//todo supposedly APM IMA removes lower 3b after assigning step, but wave looks a bit off (Rayman 2 only?):
|
||||
// ...; step = adpcm_table[step_index]; delta = (step >> 3); step &= (~7); ...
|
||||
/* read initial hist (last to first) */
|
||||
for (i = 0; i < channels; i++) {
|
||||
vgmstream->ch[i].adpcm_history1_32 = read_s32le(0x2c + 0x0c * (channels - 1 - i) + 0x00, sf);
|
||||
vgmstream->ch[i].adpcm_step_index = read_s32le(0x2c + 0x0c * (channels - 1 - i) + 0x04, sf);
|
||||
}
|
||||
//todo supposedly APM IMA removes lower 3b after assigning step, but wave looks a bit off (Rayman 2 only?):
|
||||
// ...; step = adpcm_table[step_index]; delta = (step >> 3); step &= (~7); ...
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
|
||||
return vgmstream;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -509,6 +509,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
|
|||
init_vgmstream_dsp_asura_ttss,
|
||||
init_vgmstream_dsp_asura_sfx,
|
||||
init_vgmstream_adp_ongakukan,
|
||||
init_vgmstream_sdd,
|
||||
|
||||
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
|
||||
init_vgmstream_agsc,
|
||||
|
|
|
@ -708,6 +708,7 @@ typedef enum {
|
|||
meta_EA_SBK,
|
||||
meta_DSP_ASURA,
|
||||
meta_ONGAKUKAN_RIFF_ADP,
|
||||
meta_SDD,
|
||||
|
||||
} meta_t;
|
||||
|
||||
|
|
|
@ -795,6 +795,7 @@
|
|||
<string>scd</string>
|
||||
<string>sch</string>
|
||||
<string>sd9</string>
|
||||
<string>sdd</string>
|
||||
<string>sdl</string>
|
||||
<string>sdp</string>
|
||||
<string>sdf</string>
|
||||
|
|
Loading…
Reference in a new issue