diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index 77c24ec17..4a429400c 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj @@ -75,6 +75,8 @@ 830EBE1A200465C00023AA10 /* libatrac9.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 830EBD9720045F1B0023AA10 /* libatrac9.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 8313E3E61902020400B4B6F1 /* mpg123.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313E3431901FBDD00B4B6F1 /* mpg123.framework */; }; 8313E3E71902021800B4B6F1 /* mpg123.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8313E3431901FBDD00B4B6F1 /* mpg123.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + 8315958720FEC832007002F0 /* asf_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8315958320FEC831007002F0 /* asf_decoder.c */; }; + 8315958920FEC83F007002F0 /* asf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8315958820FEC83F007002F0 /* asf.c */; }; 831BA6181EAC61A500CF89B0 /* adx.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA60E1EAC61A500CF89B0 /* adx.c */; }; 831BA6191EAC61A500CF89B0 /* ogl.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA60F1EAC61A500CF89B0 /* ogl.c */; }; 831BA61A1EAC61A500CF89B0 /* ps2_vds_vdm.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6101EAC61A500CF89B0 /* ps2_vds_vdm.c */; }; @@ -657,6 +659,8 @@ 830EBE112004656E0023AA10 /* xnb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xnb.c; sourceTree = ""; }; 830EBE122004656E0023AA10 /* ktss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ktss.c; sourceTree = ""; }; 8313E33D1901FBDC00B4B6F1 /* mpg123.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = mpg123.xcodeproj; path = ../mpg123/mpg123.xcodeproj; sourceTree = ""; }; + 8315958320FEC831007002F0 /* asf_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = asf_decoder.c; sourceTree = ""; }; + 8315958820FEC83F007002F0 /* asf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = asf.c; sourceTree = ""; }; 831BA60E1EAC61A500CF89B0 /* adx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adx.c; sourceTree = ""; }; 831BA60F1EAC61A500CF89B0 /* ogl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ogl.c; sourceTree = ""; }; 831BA6101EAC61A500CF89B0 /* ps2_vds_vdm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vds_vdm.c; sourceTree = ""; }; @@ -1199,6 +1203,7 @@ 836F6DE018BDC2180095E648 /* acm_decoder.c */, 836F6DE118BDC2180095E648 /* acm_decoder.h */, 836F6DE218BDC2180095E648 /* adx_decoder.c */, + 8315958320FEC831007002F0 /* asf_decoder.c */, 8306B08120984517000302D4 /* at3plus_decoder.c */, 830EBE0F2004655D0023AA10 /* atrac9_decoder.c */, 831BA6221EAC61CB00CF89B0 /* coding_utils.c */, @@ -1327,6 +1332,7 @@ 836F6E3218BDC2180095E648 /* aix.c */, 836F6E3318BDC2180095E648 /* akb.c */, 836F6E3418BDC2180095E648 /* apple_caff.c */, + 8315958820FEC83F007002F0 /* asf.c */, 836F6E3518BDC2180095E648 /* ast.c */, 8306B0D520984590000302D4 /* atsl.c */, 83A21F7C201D897F000F04B9 /* atx.c */, @@ -2052,6 +2058,7 @@ 836F6FD518BDC2190095E648 /* ps2_enth.c in Sources */, 8306B0DC20984590000302D4 /* sthd.c in Sources */, 836F6FAE18BDC2190095E648 /* ngc_dsp_mpds.c in Sources */, + 8315958720FEC832007002F0 /* asf_decoder.c in Sources */, 836F705218BDC2190095E648 /* zwdsp.c in Sources */, 836F6FFB18BDC2190095E648 /* ps2_sps.c in Sources */, 836F6FFF18BDC2190095E648 /* ps2_strlr.c in Sources */, @@ -2221,6 +2228,7 @@ 836F6FE918BDC2190095E648 /* ps2_mihb.c in Sources */, 836F6FA918BDC2190095E648 /* ngc_adpdtk.c in Sources */, 836F6FDC18BDC2190095E648 /* ps2_iab.c in Sources */, + 8315958920FEC83F007002F0 /* asf.c in Sources */, 836F6F3818BDC2190095E648 /* psx_decoder.c in Sources */, 836F6F2D18BDC2190095E648 /* mpeg_decoder.c in Sources */, 836F6F2618BDC2190095E648 /* g7221_decoder.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/src/coding/asf_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/asf_decoder.c new file mode 100644 index 000000000..c97d7434e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/asf_decoder.c @@ -0,0 +1,64 @@ +#include "coding.h" + + +/* Decodec Argonaut's ASF ADPCM codec. Algorithm follows Croc2_asf2raw.exe, and the waveform + * looks almost correct, but should reverse engineer asfcodec.adl (DLL) for accuracy. */ +void decode_asf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + off_t frame_offset; + int i, frames_in, sample_count = 0; + size_t bytes_per_frame, samples_per_frame; + uint32_t shift, mode; + int32_t hist1 = stream->adpcm_history1_32; + int32_t hist2 = stream->adpcm_history2_32; + + /* external interleave (fixed size), mono */ + bytes_per_frame = 0x11; + samples_per_frame = (bytes_per_frame - 0x01) * 2; + frames_in = first_sample / samples_per_frame; + first_sample = first_sample % samples_per_frame; + + /* parse header */ + frame_offset = stream->offset + bytes_per_frame*frames_in; + shift = (read_8bit(frame_offset+0x00,stream->streamfile) >> 4) & 0xf; + mode = (read_8bit(frame_offset+0x00,stream->streamfile) >> 0) & 0xf; + + /* decoder nibbles */ + for (i = first_sample; i < first_sample + samples_to_do; i++) { + int32_t new_sample; + uint8_t nibbles = (uint8_t)read_8bit(frame_offset+0x01 + i/2,stream->streamfile); + + new_sample = i&1 ? /* high nibble first */ + get_low_nibble_signed(nibbles): + get_high_nibble_signed(nibbles); + new_sample = new_sample << shift; + + switch(mode) { + case 0x00: + new_sample = new_sample + hist1; + //new_sample = (new_sample + (hist1 << 6)) >> 6; /* maybe? */ + break; + + case 0x04: + new_sample = new_sample + hist1*2 - hist2; + //new_sample = (new_sample + (hist1 << 7) - (hist2 << 6)) >> 6; /* maybe? */ + break; + + default: /* other modes (ex 0x02/09) seem only at last frame as 0 */ + //VGM_LOG("ASF: unknown mode %x at %lx\n", mode,frame_offset); + //new_sample = 0; /* maybe? */ + break; + } + + //new_sample = clamp16(new_sample); /* must not */ + new_sample = new_sample & 0xFFFF; /* probably unnecessary */ + + outbuf[sample_count] = new_sample; + sample_count += channelspacing; + + hist2 = hist1; + hist1 = new_sample; + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_history2_32 = hist2; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding.h b/Frameworks/vgmstream/vgmstream/src/coding/coding.h index b9de6322a..b9fb13d1e 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding.h @@ -147,6 +147,9 @@ void decode_mc3(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbu /* fadpcm_decoder */ void decode_fadpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +/* asf_decoder */ +void decode_asf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + /* ea_mt_decoder*/ ea_mt_codec_data *init_ea_mt(int channel_count, int type); void decode_ea_mt(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); diff --git a/Frameworks/vgmstream/vgmstream/src/coding/fadpcm_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/fadpcm_decoder.c index 331e94c47..e70f6adc9 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/fadpcm_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/fadpcm_decoder.c @@ -15,21 +15,21 @@ static const int8_t fadpcm_coefs[8][2] = { /* FMOD's FADPCM, basically XA/PSX ADPCM with a fancy header layout. * Code/layout could be simplified but tries to emulate FMOD's code. - * Algorithm and tables debugged from their PC DLLs. */ + * Algorithm and tables debugged from their PC DLLs (byte-accurate). */ void decode_fadpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { off_t frame_offset; int i, j, k; - int block_samples, num_frame, samples_done = 0, sample_count = 0; + int block_samples, frames_in, samples_done = 0, sample_count = 0; uint32_t coefs, shifts; int32_t hist1; //= stream->adpcm_history1_32; int32_t hist2; //= stream->adpcm_history2_32; /* external interleave (fixed size), mono */ block_samples = (0x8c - 0xc) * 2; - num_frame = first_sample / block_samples; + frames_in = first_sample / block_samples; first_sample = first_sample % block_samples; - frame_offset = stream->offset + 0x8c*num_frame; + frame_offset = stream->offset + 0x8c*frames_in; /* parse 0xc header (header samples are not written to outbuf) */ @@ -50,7 +50,7 @@ void decode_fadpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacin coef1 = fadpcm_coefs[coef_index][0]; coef2 = fadpcm_coefs[coef_index][1]; - shift = 0x16 - shift_factor; + shift = 0x16 - shift_factor; /* pre-adjust for 32b sign extend */ for (j = 0; j < 4; j++) { uint32_t nibbles = read_32bitLE(group_offset + 0x04*j, stream->streamfile); @@ -59,9 +59,9 @@ void decode_fadpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacin int32_t new_sample; new_sample = (nibbles >> k*4) & 0x0f; - new_sample = (new_sample << 28) >> shift; /* sign extend + scale */ + new_sample = (new_sample << 28) >> shift; /* 32b sign extend + scale */ new_sample = (new_sample - hist2*coef2 + hist1*coef1); - new_sample = new_sample >> 6; /* (new_sample / 64) has minor rounding differences */ + new_sample = new_sample >> 6; new_sample = clamp16(new_sample); if (sample_count >= first_sample && samples_done < samples_to_do) { diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_ea_xma.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_ea_xma.c index c4dc0b625..559c6fe63 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_ea_xma.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_ea_xma.c @@ -39,10 +39,16 @@ int ffmpeg_custom_read_eaxma(ffmpeg_codec_data *data, uint8_t *buf, int buf_size /* read and transform SNS/EA-XMA blocks into XMA packets */ while (buf_done < buf_size) { int s, p, bytes_to_copy, max_packets; - size_t data_size = 0, gap_size = 0; - size_t block_size = read_32bitBE(real_offset, data->streamfile); - /* 0x04(4): decoded samples */ - off_t packets_offset = real_offset + 0x08; + size_t block_size, data_size = 0, gap_size = 0; + uint32_t block_flag; + off_t packets_offset; + + block_flag = (uint8_t)read_8bit(real_offset+0x00,data->streamfile); + block_size = read_32bitBE(real_offset+0x00,data->streamfile) & 0x00FFFFFF; + packets_offset = real_offset + 0x08; /* 0x04(4): decoded samples */ + + if (block_flag == 0x45) /* exit on last block just in case, though should reach real_size */ + break; max_packets = get_block_max_packets(num_streams, packets_offset, data->streamfile); if (max_packets == 0) goto fail; @@ -115,12 +121,11 @@ int ffmpeg_custom_read_eaxma(ffmpeg_codec_data *data, uint8_t *buf, int buf_size /* move when block is fully done */ if (data_size == bytes_to_copy + gap_size) { - real_offset += (block_size & 0x00FFFFFF); + real_offset += block_size; virtual_base += data_size; } - /* exit on last block just in case, though should reach real_size */ - if ((block_size & 0x80000000) || (block_size & 0x45000000)) + if (block_flag == 0x80) /* exit on last block just in case, though should reach real_size */ break; } @@ -153,10 +158,16 @@ int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset /* find target block */ while (virtual_base < seek_virtual_offset) { - size_t data_size, extra_size = 0; - size_t block_size = read_32bitBE(real_offset, data->streamfile); + size_t block_size, data_size, extra_size = 0; + uint32_t block_flag; - data_size = (block_size & 0x00FFFFFF) - 0x0c; + block_flag = (uint8_t)read_8bit(real_offset+0x00,data->streamfile); + block_size = read_32bitBE(real_offset+0x00,data->streamfile) & 0x00FFFFFF; + + if (block_flag == 0x45) /* exit on last block just in case (v1/SPS, empty) */ + break; + + data_size = block_size - 0x0c; if (data_size % EAXMA_XMA_PACKET_SIZE) extra_size = EAXMA_XMA_PACKET_SIZE - (data_size % EAXMA_XMA_PACKET_SIZE); @@ -164,8 +175,11 @@ int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset if (data_size + extra_size > seek_virtual_offset) break; - real_offset += (block_size & 0x00FFFFFF); + real_offset += block_size; virtual_base += data_size + extra_size; + + if (block_flag == 0x80) /* exit on last block just in case (v0/SNS, full) */ + break; } /* closest we can use for reads */ @@ -195,13 +209,16 @@ size_t ffmpeg_get_eaxma_virtual_size(int channels, off_t real_offset, size_t rea /* count all SNS/EAXMA blocks size + padding size */ while (real_offset < real_end_offset) { int max_packets; - size_t block_size = read_32bitBE(real_offset + 0x00, streamFile); - /* 0x04(4): decoded samples */ - off_t packets_offset = real_offset + 0x08; + uint32_t block_flag, block_size; + off_t packets_offset; + + block_flag = (uint8_t)read_8bit(real_offset+0x00,streamFile); + block_size = read_32bitBE(real_offset+0x00,streamFile) & 0x00FFFFFF; + packets_offset = real_offset + 0x08; /* 0x04(4): decoded samples */ + + if (block_flag == 0x45) /* exit on last block just in case (v1/SPS, empty) */ + break; - /* At 0x00(1): block flag - * - in SNS: 0x00=normal block, 0x80=last block (not mandatory) - * - in SPS: 0x48=header, 0x44=normal block, 0x45=last block (empty) */ max_packets = get_block_max_packets(num_streams, packets_offset, streamFile); if (max_packets == 0) goto fail; @@ -209,10 +226,9 @@ size_t ffmpeg_get_eaxma_virtual_size(int channels, off_t real_offset, size_t rea /* fixed data_size per block for multichannel, see reads */ virtual_size += max_packets * num_streams * EAXMA_XMA_PACKET_SIZE; - real_offset += (block_size & 0x00FFFFFF); + real_offset += block_size; - /* exit on last block just in case, though should reach real_size */ - if ((block_size & 0x80000000) || (block_size & 0x45000000)) + if (block_flag == 0x80) /* exit on last block just in case (v0/SNS, full) */ break; } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c index 7931247c7..088c24bf5 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c @@ -2,13 +2,13 @@ #include "../util.h" // todo this is based on Kazzuya's old code; different emus (PCSX, Mame, Mednafen, etc) do -// XA coefs int math in different ways (see comments below), so may not be 100% accurate. -// May be implemented like the SNES/SPC700 BRR (per-filter code?). +// XA coefs int math in different ways (see comments below), not be 100% accurate. +// May be implemented like the SNES/SPC700 BRR (see BSNES' brr.cpp, hardware-tested). /* XA ADPCM gain values */ static const double K0[4] = { 0.0, 0.9375, 1.796875, 1.53125 }; static const double K1[4] = { 0.0, 0.0, -0.8125,-0.859375}; -static int IK0(int fid) { return ((int)((-K0[fid]) * (1 << 10))); } /* K0/1 floats to int, K*2^10 = K*1024 */ +static int IK0(int fid) { return ((int)((-K0[fid]) * (1 << 10))); } /* K0/1 floats to int, K*2^10 = K*(1<<10) = K*1024 */ static int IK1(int fid) { return ((int)((-K1[fid]) * (1 << 10))); } /* Sony XA ADPCM, defined for CD-DA/CD-i in the "Red Book" (private) or "Green Book" (public) specs. @@ -21,15 +21,16 @@ static int IK1(int fid) { return ((int)((-K1[fid]) * (1 << 10))); } * short sample = ((nibble << 12) & 0xf000) >> shift * or: int sample = ((nibble << 28) & 0xf0000000) >> (shift + N) * - K0/K1 are float coefs are typically redefined with int math in various ways, with non-equivalent rounding: - * (sample + K0*2^N*hist1 + K1*2^N*hist1 + [(2^N)/2]) / 2^N - * (sample + K0*2^N*hist1 + K1*2^N*hist1 + [(2^N)/2]) >> N - * sample + (K0<>N - * sample + (K0*2^N*hist1)>>N + (K1*2^N*hist1)>>N + * (sample + K0*2^N*hist1 + K1*2^N*hist2 + [(2^N)/2]) / 2^N + * (sample + K0*2^N*hist1 + K1*2^N*hist2 + [(2^N)/2]) >> N + * sample + (K0*2^N*hist1 + K1*2^N*hist2)>>N + * sample + (K0*2^N*hist1)>>N + (K1*2^N*hist2)>>N * etc * (rounding differences should be inaudible, so public implementations may be approximations) * * Various XA descendants (PS-ADPCM, EA-XA, NGC DTK, FADPCM, etc) do filters/rounding slightly - * differently, using one of the above methods. + * differently, using one of the above methods in software/CPU, but in XA's case may be done like + * the SNES/SPC700 BRR, with specific per-filter ops. * int coef tables commonly use N = 6 or 8, so K0 0.9375*64 = 60 or 0.9375*256 = 240 * PS1 XA is apparently upsampled and interpolated to 44100, vgmstream doesn't simulate this. * diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index 2f58b387b..31aa49ed9 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -547,6 +547,7 @@ static const coding_info coding_info_list[] = { {coding_MTA2, "Konami MTA2 4-bit ADPCM"}, {coding_MC3, "Paradigm MC3 3-bit ADPCM"}, {coding_FADPCM, "FMOD FADPCM 4-bit ADPCM"}, + {coding_ASF, "Argonaut ASF 4-bit ADPCM"}, {coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"}, {coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"}, @@ -1031,6 +1032,7 @@ static const meta_info meta_info_list[] = { {meta_DSP_SADF, "Procyon Studio SADF header"}, {meta_H4M, "Hudson HVQM4 header"}, {meta_OGG_MUS, "Ogg Vorbis (MUS header)"}, + {meta_ASF, "Argonaut ASF header"}, #ifdef VGM_USE_FFMPEG {meta_FFmpeg, "FFmpeg supported file format"}, diff --git a/Frameworks/vgmstream/vgmstream/src/meta/asf.c b/Frameworks/vgmstream/vgmstream/src/meta/asf.c new file mode 100644 index 000000000..fc094d36f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/asf.c @@ -0,0 +1,56 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* ASF - Argonaut PC games [Croc 2 (PC), Aladdin: Nasira's Revenge (PC)] */ +VGMSTREAM * init_vgmstream_asf(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count, version; + + + /* checks */ + if (!check_extensions(streamFile, "asf")) + goto fail; + + if (read_32bitBE(0x00,streamFile) != 0x41534600) /* "ASF\0" */ + goto fail; + if (read_32bitBE(0x04,streamFile) != 0x02000100) + goto fail; + if (read_32bitLE(0x08,streamFile) != 0x01 && + read_32bitLE(0x0c,streamFile) != 0x18 && + read_32bitLE(0x1c,streamFile) != 0x20) + goto fail; + + version = read_32bitLE(0x28,streamFile); /* assumed? */ + switch(version){ + case 0x0d: channel_count = 1; break; /* Aladdin: Nasira's Revenge (PC) */ + case 0x0f: channel_count = 2; break; /* Croc 2 (PC), The Emperor's New Groove (PC) */ + default: goto fail; + } + + loop_flag = 0; + start_offset = 0x2c; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = (uint16_t)read_16bitLE(0x24, streamFile); + vgmstream->meta_type = meta_ASF; + vgmstream->coding_type = coding_ASF; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x11; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/(0x11*channel_count)*32; /* bytes_to_samples */ + //vgmstream->num_samples = read_32bitLE(0x18,streamFile) * (0x20<stream_name,0x10, 0x08+1,streamFile); + + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index c4545d642..d14629f32 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -758,4 +758,6 @@ VGMSTREAM * init_vgmstream_dsp_sadf(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_h4m(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_asf(STREAMFILE *streamFile); + #endif /*_META_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 91c0594d3..19a277438 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -413,6 +413,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_dsp_sadf, init_vgmstream_h4m, init_vgmstream_ps2_ads_container, + init_vgmstream_asf, init_vgmstream_txth, /* should go at the end (lower priority) */ #ifdef VGM_USE_FFMPEG @@ -1117,6 +1118,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { return 10; case coding_FADPCM: return 256; /* (0x8c - 0xc) * 2 */ + case coding_ASF: + return 32; /* (0x11 - 0x1) * 2 */ case coding_EA_MT: return 432; case coding_CRI_HCA: @@ -1273,6 +1276,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { return 0x04; case coding_FADPCM: return 0x8c; + case coding_ASF: + return 0x11; case coding_EA_MT: return 0; /* variable (frames of bit counts or PCM frames) */ #ifdef VGM_USE_ATRAC9 @@ -1904,6 +1909,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do); } break; + case coding_ASF: + for (chan=0;chanchannels;chan++) { + decode_asf(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; case coding_EA_MT: for (chan=0;chanchannels;chan++) { decode_ea_mt(vgmstream, buffer+samples_written*vgmstream->channels+chan, diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 0803cf455..59065ce1e 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -162,6 +162,7 @@ typedef enum { coding_MTA2, /* Konami MTA2 ADPCM */ coding_MC3, /* Paradigm MC3 3-bit ADPCM */ coding_FADPCM, /* FMOD FADPCM 4-bit ADPCM */ + coding_ASF, /* Argonaut ASF 4-bit ADPCM */ /* others */ coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression DPCM */ @@ -687,6 +688,7 @@ typedef enum { meta_OGG_GWM, /* Ogg Vorbis with encryption [Metronomicon (PC)] */ meta_H4M, /* Hudson HVQM4 video [Resident Evil 0 (GC), Tales of Symphonia (GC)] */ meta_OGG_MUS, /* Ogg Vorbis with encryption [Redux - Dark Matters (PC)] */ + meta_ASF, /* Argonaut ASF [Croc 2 (PC)] */ #ifdef VGM_USE_FFMPEG meta_FFmpeg,