Browse Source

Updated VGMStream to r1050-2622-g72b9f540

master
Christopher Snowhill 4 months ago
parent
commit
0a9c7693d4
54 changed files with 2271 additions and 1374 deletions
  1. +12
    -4
      Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj
  2. +17
    -16
      Frameworks/vgmstream/vgmstream/src/coding/asf_decoder.c
  3. +11
    -11
      Frameworks/vgmstream/vgmstream/src/coding/coding.h
  4. +13
    -12
      Frameworks/vgmstream/vgmstream/src/coding/dsa_decoder.c
  5. +35
    -38
      Frameworks/vgmstream/vgmstream/src/coding/fadpcm_decoder.c
  6. +5
    -5
      Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c
  7. +2
    -1
      Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c
  8. +1
    -12
      Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c
  9. +48
    -38
      Frameworks/vgmstream/vgmstream/src/coding/lsf_decoder.c
  10. +82
    -32
      Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils.c
  11. +41
    -27
      Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c
  12. +1
    -1
      Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c
  13. +39
    -35
      Frameworks/vgmstream/vgmstream/src/coding/mta2_decoder.c
  14. +38
    -34
      Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c
  15. +43
    -39
      Frameworks/vgmstream/vgmstream/src/coding/nds_procyon_decoder.c
  16. +53
    -43
      Frameworks/vgmstream/vgmstream/src/coding/ngc_afc_decoder.c
  17. +32
    -34
      Frameworks/vgmstream/vgmstream/src/coding/ngc_dtk_decoder.c
  18. +3
    -7
      Frameworks/vgmstream/vgmstream/src/coding/pcm_decoder.c
  19. +55
    -41
      Frameworks/vgmstream/vgmstream/src/coding/ptadpcm_decoder.c
  20. +15
    -13
      Frameworks/vgmstream/vgmstream/src/coding/xmd_decoder.c
  21. +18
    -9
      Frameworks/vgmstream/vgmstream/src/formats.c
  22. +32
    -39
      Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_1snh.c
  23. +15
    -10
      Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c
  24. +1
    -1
      Frameworks/vgmstream/vgmstream/src/layout/segmented.c
  25. +145
    -122
      Frameworks/vgmstream/vgmstream/src/meta/adx.c
  26. +27
    -41
      Frameworks/vgmstream/vgmstream/src/meta/afc.c
  27. +109
    -87
      Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c
  28. +66
    -52
      Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c
  29. +242
    -0
      Frameworks/vgmstream/vgmstream/src/meta/ea_eaac_opus_streamfile.h
  30. +5
    -3
      Frameworks/vgmstream/vgmstream/src/meta/ea_eaac_streamfile.h
  31. +40
    -10
      Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c
  32. +1
    -1
      Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c
  33. +3
    -0
      Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h
  34. +191
    -0
      Frameworks/vgmstream/vgmstream/src/meta/isb.c
  35. +21
    -33
      Frameworks/vgmstream/vgmstream/src/meta/lsf.c
  36. +5
    -2
      Frameworks/vgmstream/vgmstream/src/meta/meta.h
  37. +3
    -8
      Frameworks/vgmstream/vgmstream/src/meta/mta2.c
  38. +18
    -37
      Frameworks/vgmstream/vgmstream/src/meta/mta2_streamfile.h
  39. +29
    -66
      Frameworks/vgmstream/vgmstream/src/meta/nds_sad.c
  40. +40
    -73
      Frameworks/vgmstream/vgmstream/src/meta/ps2_2pfs.c
  41. +10
    -8
      Frameworks/vgmstream/vgmstream/src/meta/rwsd.c
  42. +1
    -1
      Frameworks/vgmstream/vgmstream/src/meta/sgxd.c
  43. +0
    -70
      Frameworks/vgmstream/vgmstream/src/meta/stx.c
  44. +8
    -2
      Frameworks/vgmstream/vgmstream/src/meta/txth.c
  45. +3
    -10
      Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c
  46. +3
    -6
      Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c
  47. +80
    -15
      Frameworks/vgmstream/vgmstream/src/meta/vag.c
  48. +4
    -13
      Frameworks/vgmstream/vgmstream/src/meta/wave.c
  49. +140
    -0
      Frameworks/vgmstream/vgmstream/src/meta/xssb.c
  50. +318
    -160
      Frameworks/vgmstream/vgmstream/src/meta/xwb_xsb.h
  51. +40
    -11
      Frameworks/vgmstream/vgmstream/src/streamfile.c
  52. +82
    -22
      Frameworks/vgmstream/vgmstream/src/streamfile.h
  53. +20
    -16
      Frameworks/vgmstream/vgmstream/src/vgmstream.c
  54. +5
    -3
      Frameworks/vgmstream/vgmstream/src/vgmstream.h

+ 12
- 4
Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj View File

@@ -401,7 +401,6 @@
836F703018BDC2190095E648 /* sqex_scd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF418BDC2190095E648 /* sqex_scd.c */; };
836F703218BDC2190095E648 /* str_asr.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF618BDC2190095E648 /* str_asr.c */; };
836F703318BDC2190095E648 /* str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF718BDC2190095E648 /* str_snds.c */; };
836F703418BDC2190095E648 /* stx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF818BDC2190095E648 /* stx.c */; };
836F703518BDC2190095E648 /* svs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF918BDC2190095E648 /* svs.c */; };
836F703618BDC2190095E648 /* thp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFA18BDC2190095E648 /* thp.c */; };
836F703718BDC2190095E648 /* tun.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFB18BDC2190095E648 /* tun.c */; };
@@ -522,6 +521,9 @@
83AA5D251F6E2F9C0020821C /* hca_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 83AA5D211F6E2F9C0020821C /* hca_keys.h */; };
83AA5D271F6E2F9C0020821C /* stm.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D231F6E2F9C0020821C /* stm.c */; };
83AB8C761E8072A100086084 /* x360_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C741E8072A100086084 /* x360_ast.c */; };
83AFABBC23795202002F3947 /* xssb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AFABB923795201002F3947 /* xssb.c */; };
83AFABBD23795202002F3947 /* ea_eaac_opus_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83AFABBA23795202002F3947 /* ea_eaac_opus_streamfile.h */; };
83AFABBE23795202002F3947 /* isb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AFABBB23795202002F3947 /* isb.c */; };
83BAFB6C19F45EB3005DAB60 /* bfstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BAFB6B19F45EB3005DAB60 /* bfstm.c */; };
83C7280F22BC893D00678B4A /* xwb_xsb.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C727FB22BC893800678B4A /* xwb_xsb.h */; };
83C7281022BC893D00678B4A /* nps.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C727FC22BC893900678B4A /* nps.c */; };
@@ -1087,7 +1089,6 @@
836F6EF418BDC2190095E648 /* sqex_scd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqex_scd.c; sourceTree = "<group>"; };
836F6EF618BDC2190095E648 /* str_asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_asr.c; sourceTree = "<group>"; };
836F6EF718BDC2190095E648 /* str_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds.c; sourceTree = "<group>"; };
836F6EF818BDC2190095E648 /* stx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stx.c; sourceTree = "<group>"; };
836F6EF918BDC2190095E648 /* svs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = svs.c; sourceTree = "<group>"; };
836F6EFA18BDC2190095E648 /* thp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thp.c; sourceTree = "<group>"; };
836F6EFB18BDC2190095E648 /* tun.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tun.c; sourceTree = "<group>"; };
@@ -1207,6 +1208,9 @@
83AA5D211F6E2F9C0020821C /* hca_keys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hca_keys.h; sourceTree = "<group>"; };
83AA5D231F6E2F9C0020821C /* stm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stm.c; sourceTree = "<group>"; };
83AB8C741E8072A100086084 /* x360_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_ast.c; sourceTree = "<group>"; };
83AFABB923795201002F3947 /* xssb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xssb.c; sourceTree = "<group>"; };
83AFABBA23795202002F3947 /* ea_eaac_opus_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ea_eaac_opus_streamfile.h; sourceTree = "<group>"; };
83AFABBB23795202002F3947 /* isb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = isb.c; sourceTree = "<group>"; };
83BAFB6B19F45EB3005DAB60 /* bfstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfstm.c; sourceTree = "<group>"; };
83C727FB22BC893800678B4A /* xwb_xsb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xwb_xsb.h; sourceTree = "<group>"; };
83C727FC22BC893900678B4A /* nps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nps.c; sourceTree = "<group>"; };
@@ -1600,6 +1604,7 @@
83299FCF1E7660C7003A3242 /* dsp_adx.c */,
836F6E4418BDC2180095E648 /* dsp_bdsp.c */,
8349A8FF1FE6258000E26435 /* ea_1snh.c */,
83AFABBA23795202002F3947 /* ea_eaac_opus_streamfile.h */,
8306B0BD2098458B000302D4 /* ea_eaac_streamfile.h */,
8349A8F71FE6257E00E26435 /* ea_eaac.c */,
830165981F256BD000CA0941 /* ea_schl_fixed.c */,
@@ -1642,6 +1647,7 @@
837CEAE623487F2B00E62A4A /* ima.c */,
832BF81121E05149006F50F1 /* imc.c */,
836F6E5518BDC2180095E648 /* ios_psnd.c */,
83AFABBB23795202002F3947 /* isb.c */,
836F6E5618BDC2180095E648 /* ish_isd.c */,
836F6E5718BDC2180095E648 /* ivaud.c */,
836F6E5818BDC2180095E648 /* ivb.c */,
@@ -1849,7 +1855,6 @@
836F6EF718BDC2190095E648 /* str_snds.c */,
834FE0C2215C79E6000A5D3D /* str_wav.c */,
83C7280722BC893B00678B4A /* strm_abylight.c */,
836F6EF818BDC2190095E648 /* stx.c */,
834FE0D7215C79EA000A5D3D /* svg.c */,
836F6EF918BDC2190095E648 /* svs.c */,
831BA6121EAC61A500CF89B0 /* sxd.c */,
@@ -1923,6 +1928,7 @@
832BF80A21E05148006F50F1 /* xpcm.c */,
832BF80C21E05148006F50F1 /* xps.c */,
836F6F1218BDC2190095E648 /* xss.c */,
83AFABB923795201002F3947 /* xssb.c */,
834FE0C6215C79E7000A5D3D /* xvag_streamfile.h */,
83345A4E1F8AEB2800B2EAA4 /* xvag.c */,
837CEADC23487F2900E62A4A /* xvas.c */,
@@ -2023,6 +2029,7 @@
8306B0D820984590000302D4 /* ea_eaac_streamfile.h in Headers */,
837CEB0523487F2C00E62A4A /* sqex_sead_streamfile.h in Headers */,
8306B0E820984590000302D4 /* opus_interleave_streamfile.h in Headers */,
83AFABBD23795202002F3947 /* ea_eaac_opus_streamfile.h in Headers */,
83C7281822BC893D00678B4A /* sfh_streamfile.h in Headers */,
834FE0EF215C79ED000A5D3D /* xvag_streamfile.h in Headers */,
8349A90C1FE6258200E26435 /* sqex_scd_streamfile.h in Headers */,
@@ -2249,7 +2256,6 @@
836F6FA118BDC2190095E648 /* myspd.c in Sources */,
837CEB0123487F2C00E62A4A /* xmu.c in Sources */,
836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */,
836F703418BDC2190095E648 /* stx.c in Sources */,
83FF0EBC1E93282100C58054 /* wwise.c in Sources */,
836F6F7018BDC2190095E648 /* apple_caff.c in Sources */,
836F700018BDC2190095E648 /* ps2_svag.c in Sources */,
@@ -2295,6 +2301,7 @@
8349A8EA1FE6253900E26435 /* blocked_ea_schl.c in Sources */,
836F705118BDC2190095E648 /* zsd.c in Sources */,
8349A91F1FE6258200E26435 /* naac.c in Sources */,
83AFABBE23795202002F3947 /* isb.c in Sources */,
836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */,
836F703C18BDC2190095E648 /* wii_bns.c in Sources */,
830EBE132004656E0023AA10 /* xnb.c in Sources */,
@@ -2594,6 +2601,7 @@
83C7282922BC8C1500678B4A /* mixing.c in Sources */,
8375737621F950ED00F01AF5 /* gin.c in Sources */,
836F6FC918BDC2190095E648 /* ps2_2pfs.c in Sources */,
83AFABBC23795202002F3947 /* xssb.c in Sources */,
836F704818BDC2190095E648 /* xbox_ims.c in Sources */,
837CEAF623487F2C00E62A4A /* mzrt.c in Sources */,
836F6F7518BDC2190095E648 /* bnsf.c in Sources */,


+ 17
- 16
Frameworks/vgmstream/vgmstream/src/coding/asf_decoder.c View File

@@ -2,52 +2,53 @@
/* Decodes Argonaut's ASF ADPCM codec, used in some of their PC games.
* Algorithm should be accurate (reverse engineered from asfcodec.adl DLL). */
void decode_asf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
* Reverse engineered from asfcodec.adl DLL. */
void decode_asf(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame[0x11] = {0};
off_t frame_offset;
int i, frames_in, sample_count = 0;
size_t bytes_per_frame, samples_per_frame;
uint8_t shift, mode;
int 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;
//first_sample = first_sample % samples_per_frame; /* for flat layout */
/* parse frame header */
frame_offset = stream->offset + bytes_per_frame*frames_in;
shift = ((uint8_t)read_8bit(frame_offset+0x00,stream->streamfile) >> 4) & 0xf;
mode = ((uint8_t)read_8bit(frame_offset+0x00,stream->streamfile) >> 0) & 0xf;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
shift = (frame[0x00] >> 4) & 0xf;
mode = (frame[0x00] >> 0) & 0xf;
/* decode 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);
uint8_t nibbles = frame[0x01 + i/2];
int32_t sample;
new_sample = i&1 ? /* high nibble first */
sample = i&1 ? /* high nibble first */
get_low_nibble_signed(nibbles):
get_high_nibble_signed(nibbles);
/* move sample to upper nibble, then shift + 2 (IOW: shift + 6) */
new_sample = (new_sample << 4) << (shift + 2);
sample = (sample << 4) << (shift + 2); /* move sample to upper nibble, then shift + 2 (IOW: shift + 6) */
/* mode is checked as a flag, so there are 2 modes only, but lower nibble
* may have other values at last frame (ex 0x02/09), could be control flags (loop related?) */
if (mode & 0x4) { /* ~filters: 2, -1 */
new_sample = (new_sample + (hist1 << 7) - (hist2 << 6)) >> 6;
sample = (sample + (hist1 << 7) - (hist2 << 6)) >> 6;
}
else { /* ~filters: 1, 0 */
new_sample = (new_sample + (hist1 << 6)) >> 6;
sample = (sample + (hist1 << 6)) >> 6;
}
//new_sample = clamp16(new_sample); /* must not */
outbuf[sample_count] = (int16_t)new_sample;
outbuf[sample_count] = (int16_t)sample; /* must not clamp */
sample_count += channelspacing;
hist2 = hist1;
hist1 = new_sample;
hist1 = sample;
}
stream->adpcm_history1_32 = hist1;


+ 11
- 11
Frameworks/vgmstream/vgmstream/src/coding/coding.h View File

@@ -55,10 +55,10 @@ void dsp_read_hist_le(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offse
void dsp_read_hist(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing, int be);

/* ngc_dtk_decoder */
void decode_ngc_dtk(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ngc_dtk(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);

/* ngc_afc_decoder */
void decode_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ngc_afc(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);

/* pcm_decoder */
void decode_pcm16le(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
@@ -138,7 +138,7 @@ size_t yamaha_bytes_to_samples(size_t bytes, int channels);
size_t aska_bytes_to_samples(size_t bytes, int channels);

/* nds_procyon_decoder */
void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_nds_procyon(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);

/* l5_555_decoder */
void decode_l5_555(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
@@ -147,28 +147,28 @@ void decode_l5_555(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacin
void decode_sassc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);

/* lsf_decode */
void decode_lsf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_lsf(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);

/* mtaf_decoder */
void decode_mtaf(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_mtaf(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);

/* mta2_decoder */
void decode_mta2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_mta2(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);

/* mc3_decoder */
void decode_mc3(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);

/* fadpcm_decoder */
void decode_fadpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_fadpcm(VGMSTREAMCHANNEL *stream, sample_t *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);
void decode_asf(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);

/* dsa_decoder */
void decode_dsa(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_dsa(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);

/* xmd_decoder */
void decode_xmd(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
void decode_xmd(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);

/* derf_decoder */
void decode_derf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
@@ -183,7 +183,7 @@ void decode_oki4s(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspaci
size_t oki_bytes_to_samples(size_t bytes, int channels);

/* ptadpcm_decoder */
void decode_ptadpcm(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
void decode_ptadpcm(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
size_t ptadpcm_bytes_to_samples(size_t bytes, int channels, size_t frame_size);

/* ubi_adpcm_decoder */


+ 13
- 12
Frameworks/vgmstream/vgmstream/src/coding/dsa_decoder.c View File

@@ -10,37 +10,38 @@ static const int dsa_coefs[16] = {
/* Decodes Ocean DSA ADPCM codec from Last Rites (PC).
* Reverse engineered from daemon1's reverse engineering. */
void decode_dsa(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
void decode_dsa(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame[0x08] = {0};
off_t frame_offset;
int i, frames_in, sample_count = 0;
size_t bytes_per_frame, samples_per_frame;
uint8_t header;
int shift, filter;
int index, shift, coef;
int32_t hist1 = stream->adpcm_history1_32;
/* external interleave (fixed size), mono */
bytes_per_frame = 0x08;
samples_per_frame = (bytes_per_frame - 0x01) * 2;
frames_in = first_sample / samples_per_frame;
first_sample = first_sample % samples_per_frame;
first_sample = first_sample % samples_per_frame; /* for flat layout */
/* parse frame header */
frame_offset = stream->offset + bytes_per_frame*frames_in;
header = (uint8_t)read_8bit(frame_offset+0x00,stream->streamfile);
shift = 0x0c - ((header >> 4) & 0xf);
filter = dsa_coefs[header & 0xf];
frame_offset = stream->offset + bytes_per_frame * frames_in;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
index = ((frame[0] >> 0) & 0xf);
shift = 12 - ((frame[0] >> 4) & 0xf);
coef = dsa_coefs[index];
/* decode nibbles */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
uint8_t nibbles = frame[0x01 + i/2];
int32_t sample;
uint8_t nibbles = (uint8_t)read_8bit(frame_offset+0x01 + i/2,stream->streamfile);
sample = i&1 ? /* high nibble first */
(nibbles >> 0) & 0xf :
(nibbles >> 4) & 0xf;
sample = ((int16_t)(sample << 0xC) >> shift); /* 16b sign extend + scale */
sample = sample + ((hist1 * filter) >> 0x10);
sample = ((int16_t)(sample << 12) >> shift); /* 16b sign extend + scale */
sample = sample + ((hist1 * coef) >> 16);
outbuf[sample_count] = (sample_t)(sample << 2);
sample_count += channelspacing;


+ 35
- 38
Frameworks/vgmstream/vgmstream/src/coding/fadpcm_decoder.c View File

@@ -1,77 +1,74 @@
#include "coding.h"
/* FADPCM table */
/* tweaked XA/PSX coefs << 6 */
static const int8_t fadpcm_coefs[8][2] = {
{ 0 , 0 },
{ 60 , 0 },
{ 122 , 60 },
{ 115 , 52 },
{ 98 , 55 },
{ 0 , 0 },
{ 0 , 0 },
{ 0 , 0 },
{ 0, 0 },
{ 60, 0 },
{ 122, 60 },
{ 115, 52 },
{ 98, 55 },
/* rest is 0s */
};
/* 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 (byte-accurate). */
void decode_fadpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
void decode_fadpcm(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame[0x8c] = {0};
off_t frame_offset;
int i, j, k;
int block_samples, frames_in, samples_done = 0, sample_count = 0;
int i, j, k, frames_in, sample_count = 0, samples_done = 0;
size_t bytes_per_frame, samples_per_frame;
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;
frames_in = first_sample / block_samples;
first_sample = first_sample % block_samples;
frame_offset = stream->offset + 0x8c*frames_in;
bytes_per_frame = 0x8c;
samples_per_frame = (bytes_per_frame - 0xc) * 2;
frames_in = first_sample / samples_per_frame;
first_sample = first_sample % samples_per_frame;
/* parse 0xc header (header samples are not written to outbuf) */
coefs = read_32bitLE(frame_offset + 0x00, stream->streamfile);
shifts = read_32bitLE(frame_offset + 0x04, stream->streamfile);
hist1 = read_16bitLE(frame_offset + 0x08, stream->streamfile);
hist2 = read_16bitLE(frame_offset + 0x0a, stream->streamfile);
frame_offset = stream->offset + bytes_per_frame * frames_in;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
coefs = get_u32le(frame + 0x00);
shifts = get_u32le(frame + 0x04);
hist1 = get_s16le(frame + 0x08);
hist2 = get_s16le(frame + 0x0a);
/* decode nibbles, grouped in 8 sets of 0x10 * 0x04 * 2 */
for (i = 0; i < 8; i++) {
int32_t coef1, coef2, shift, coef_index, shift_factor;
off_t group_offset = frame_offset + 0x0c + 0x10*i;
int index, shift, coef1, coef2;
/* each set has its own coefs/shifts (indexes > 7 are repeat, ex. 0x9 is 0x2) */
coef_index = ((coefs >> i*4) & 0x0f) % 0x07;
shift_factor = (shifts >> i*4) & 0x0f;
index = ((coefs >> i*4) & 0x0f) % 0x07;
shift = (shifts >> i*4) & 0x0f;
coef1 = fadpcm_coefs[coef_index][0];
coef2 = fadpcm_coefs[coef_index][1];
shift = 0x16 - shift_factor; /* pre-adjust for 32b sign extend */
coef1 = fadpcm_coefs[index][0];
coef2 = fadpcm_coefs[index][1];
shift = 22 - shift; /* pre-adjust for 32b sign extend */
for (j = 0; j < 4; j++) {
uint32_t nibbles = read_32bitLE(group_offset + 0x04*j, stream->streamfile);
uint32_t nibbles = get_u32le(frame + 0x0c + 0x10*i + 0x04*j);
for (k = 0; k < 8; k++) {
int32_t new_sample;
int32_t sample;
new_sample = (nibbles >> k*4) & 0x0f;
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 = clamp16(new_sample);
sample = (nibbles >> k*4) & 0x0f;
sample = (sample << 28) >> shift; /* 32b sign extend + scale */
sample = (sample - hist2*coef2 + hist1*coef1) >> 6;
sample = clamp16(sample);
if (sample_count >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = new_sample;
outbuf[samples_done * channelspacing] = sample;
samples_done++;
}
sample_count++;
hist2 = hist1;
hist1 = new_sample;
hist1 = sample;
}
}
}


+ 5
- 5
Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c View File

@@ -557,16 +557,17 @@ fail:
* float requirements, but C99 adds some faster-but-less-precise casting functions
* we try to use (returning "long", though). They work ok without "fast float math" compiler
* flags, but probably should be enabled anyway to ensure no extra IEEE checks are needed.
* MSVC added this in VS2015 (_MSC_VER 1900) but don't seem correctly optimized and is very slow.
*/
static inline int float_to_int(float val) {
#if defined(_MSC_VER) && (_MSC_VER < 1900) /* VS2015 */
#if defined(_MSC_VER)
return (int)val;
#else
return lrintf(val);
#endif
}
static inline int double_to_int(double val) {
#if defined(_MSC_VER) && (_MSC_VER < 1900) /* VS2015 */
#if defined(_MSC_VER)
return (int)val;
#else
return lrint(val); /* returns long tho */
@@ -580,9 +581,9 @@ static inline int double_to_int(double val) {
* keep it simple for now until more tests are done.
*
* in normal (interleaved) formats samples are laid out straight
* (ibuf[s*chs+ch], ex. 4ch with 8s: 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3)
* (ibuf[s*chs+ch], ex. 4ch with 4s: 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3)
* in "p" (planar) formats samples are in planes per channel
* (ibuf[ch][s], ex. 4ch with 8s: 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3)
* (ibuf[ch][s], ex. 4ch with 4s: 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3)
*
* alt float clamping:
* clamp_float(f32)
@@ -731,7 +732,6 @@ void decode_ffmpeg(VGMSTREAM *vgmstream, sample_t * outbuf, int32_t samples_to_d

copy_samples(data, outbuf, samples_to_get);

//samples_done += samples_to_get;
samples_to_do -= samples_to_get;
outbuf += samples_to_get * channels;
}


+ 2
- 1
Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c View File

@@ -133,7 +133,8 @@ ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* o
/* implicit skip: official tools skip this even with encoder delay forced to 0. Maybe FFmpeg decodes late,
* but when forcing tools to decode all frame samples it always ends a bit before last frame, so maybe it's
* really an internal skip, since encoder adds extra frames so fact num_samples + encoder delay + implicit skip
* never goes past file. Same for all bitrate/channels, not added to loops. */
* never goes past file. Same for all bitrate/channels, not added to loops. This is probably "decoder delay"
* also seen in codecs like MP3 */
if (is_at3) {
implicit_skip = 69;
}


+ 1
- 12
Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c View File

@@ -878,7 +878,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t *
stream->adpcm_step_index = step_index;
}

/* mono XBOX-IMA with header endianness and alt nibble expand (per hcs's decompilation) */
/* mono XBOX-IMA with header endianness and alt nibble expand (verified vs AK test demos) */
void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0, num_frame;
int32_t hist1 = stream->adpcm_history1_32;
@@ -922,17 +922,6 @@ void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
/* from hcs's analysis Wwise IMA expands nibbles slightly different, reducing dbs. Just "MUL" expand?
<_ZN13CAkADPCMCodec12DecodeSampleEiii>: //From Wwise_v2015.1.6_Build5553_SDK.Linux
10: 83 e0 07 and $0x7,%eax ; sample
13: 01 c0 add %eax,%eax ; sample*2
15: 83 c0 01 add $0x1,%eax ; sample*2+1
18: 0f af 45 e4 imul -0x1c(%rbp),%eax ; (sample*2+1)*scale
1c: 8d 50 07 lea 0x7(%rax),%edx ; result+7
1f: 85 c0 test %eax,%eax ; result negative?
21: 0f 48 c2 cmovs %edx,%eax ; adjust if negative to fix rounding for below division
24: c1 f8 03 sar $0x3,%eax ; (sample*2+1)*scale/8
*/

/* MS-IMA with possibly the XBOX-IMA model of even number of samples per block (more tests are needed) */
void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {


+ 48
- 38
Frameworks/vgmstream/vgmstream/src/coding/lsf_decoder.c View File

@@ -1,50 +1,60 @@
#include "coding.h"
#include "../util.h"

/* lsf ADPCM, as seen in Fastlane Street Racing */

static const short lsf_coefs[5][2] = {
{0x73, -0x34},
{0, 0},
{0x62, -0x37},
{0x3C, 0},
{0x7A, -0x3c}
};

void decode_lsf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int32_t sample_count;
const int bytes_per_frame = 0x1c;
const int samples_per_frame = (bytes_per_frame-1)*2;

int framesin = first_sample/samples_per_frame;
/* tweaked XA/PSX coefs << 6 */
static const short lsf_coefs[16][2] = {
{ 115, -52 },
{ 0, 0 },
{ 98, -55 },
{ 60, 0 },
{ 122, -60 },
/* rest assumed to be 0s */
};

uint8_t q = 0xFF - read_8bit(framesin*bytes_per_frame + stream->offset,stream->streamfile);
int scale = (q&0xF0)>>4;
int coef_idx = q&0x0F;
void decode_lsf(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame[0x1c] = {0};
off_t frame_offset;
int i, frames_in, sample_count = 0;
int index, shift, coef1, coef2;
size_t bytes_per_frame, samples_per_frame;
int32_t hist1 = stream->adpcm_history1_16;
int32_t hist2 = stream->adpcm_history2_16;

first_sample = first_sample%samples_per_frame;

for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(framesin*bytes_per_frame+stream->offset+1+i/2,stream->streamfile);

int32_t prediction =
(hist1 * lsf_coefs[coef_idx][0] +
hist2 * lsf_coefs[coef_idx][1]) / 0x40;

prediction += (i&1?
get_high_nibble_signed(sample_byte):
get_low_nibble_signed(sample_byte)
) * (1 << (12-scale));

prediction = clamp16(prediction);
uint8_t header;


/* external interleave (fixed size), mono */
bytes_per_frame = 0x1c;
samples_per_frame = (bytes_per_frame - 1) * 2;
frames_in = first_sample / samples_per_frame;
//first_sample = first_sample % samples_per_frame; /* for flat layout */

/* external interleave (fixed size), mono */
frame_offset = stream->offset + bytes_per_frame * frames_in;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
header = 0xFF - frame[0x00];
shift = (header >> 4) & 0xf;
index = (header >> 0) & 0xf;
coef1 = lsf_coefs[index][0];
coef2 = lsf_coefs[index][1];

/* decode nibbles */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
uint8_t nibbles = frame[0x01 + i/2];
int32_t sample;

sample = i&1 ? /* low nibble first */
get_high_nibble_signed(nibbles) :
get_low_nibble_signed(nibbles);
sample = sample * (1 << (12 - shift));
sample = sample + (hist1 * coef1 + hist2 * coef2) / 64; /* >> 6 */
sample = clamp16(sample);

outbuf[sample_count] = sample;
sample_count += channelspacing;

hist2 = hist1;
hist1 = prediction;

outbuf[sample_count] = prediction;
hist1 = sample;
}

stream->adpcm_history1_16 = hist1;


+ 82
- 32
Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils.c View File

@@ -92,6 +92,14 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m
data->skip_samples = data->config.skip_samples; break;
case MPEG_STANDARD:
data->skip_samples = data->config.skip_samples; break;
case MPEG_EA:
/* typical MP2 decoder delay, verified vs sx.exe, also SCHl blocks header takes discard
* samples into account (so block_samples+240*2+1 = total frame samples) */
if (info.layer == 2) {
data->skip_samples = 240*2 + 1;
}
/* MP3 probably uses 576 + 528+1 but no known games use it */
break;
default:
break;
}
@@ -234,7 +242,7 @@ fail:
* Gets info from a MPEG frame header at offset. Normally you would use mpg123_info but somehow
* it's wrong at times (maybe because we use an ancient version) so here we do our thing.
*/
int mpeg_get_frame_info(STREAMFILE *streamfile, off_t offset, mpeg_frame_info * info) {
static int mpeg_get_frame_info_h(uint32_t header, mpeg_frame_info *info) {
/* index tables */
static const int versions[4] = { /* MPEG 2.5 */ 3, /* reserved */ -1, /* MPEG 2 */ 2, /* MPEG 1 */ 1 };
static const int layers[4] = { -1,3,2,1 };
@@ -257,14 +265,11 @@ int mpeg_get_frame_info(STREAMFILE *streamfile, off_t offset, mpeg_frame_info *
{ 384, 1152, 576 } /* MPEG2.5 */
};
uint32_t header;
int idx, padding;
memset(info, 0, sizeof(*info));
header = read_32bitBE(offset, streamfile);
if ((header >> 21) != 0x7FF) /* 31-21: sync */
goto fail;
@@ -308,34 +313,36 @@ int mpeg_get_frame_info(STREAMFILE *streamfile, off_t offset, mpeg_frame_info *
fail:
return 0;
}
int mpeg_get_frame_info(STREAMFILE *sf, off_t offset, mpeg_frame_info *info) {
uint32_t header = read_u32be(offset, sf);
return mpeg_get_frame_info_h(header, info);
}
size_t mpeg_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes) {
size_t mpeg_get_samples(STREAMFILE *sf, off_t start_offset, size_t bytes) {
off_t offset = start_offset;
off_t max_offset = start_offset + bytes;
int samples = 0;
int frames = 0, samples = 0, encoder_delay = 0, encoder_padding = 0;
mpeg_frame_info info;
size_t prev_size = 0;
int cbr_count = 0;
int is_vbr = 0;
if (!streamFile)
if (!sf)
return 0;
if (max_offset > get_streamfile_size(streamFile))
max_offset = get_streamfile_size(streamFile);
if (max_offset > get_streamfile_size(sf))
max_offset = get_streamfile_size(sf);
/* MPEG may use VBR so must read all frames */
while (offset < max_offset) {
uint32_t header = read_u32be(offset+0x00, sf);
/* skip ID3v2 */
if ((read_32bitBE(offset+0x00, streamFile) & 0xFFFFFF00) == 0x49443300) { /* "ID3\0" */
if ((header & 0xFFFFFF00) == 0x49443300) { /* "ID3\0" */
size_t frame_size = 0;
uint8_t flags = read_8bit(offset+0x05, streamFile);
uint8_t flags = read_u8(offset+0x05, sf);
/* this is how it's officially read :/ */
frame_size += read_8bit(offset+0x06, streamFile) << 21;
frame_size += read_8bit(offset+0x07, streamFile) << 14;
frame_size += read_8bit(offset+0x08, streamFile) << 7;
frame_size += read_8bit(offset+0x09, streamFile) << 0;
frame_size += read_u8(offset+0x06, sf) << 21;
frame_size += read_u8(offset+0x07, sf) << 14;
frame_size += read_u8(offset+0x08, sf) << 7;
frame_size += read_u8(offset+0x09, sf) << 0;
frame_size += 0x0a;
if (flags & 0x10) /* footer? */
frame_size += 0x0a;
@@ -344,28 +351,71 @@ size_t mpeg_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes
continue;
}
/* this may fail with unknown ID3 tags */
if (!mpeg_get_frame_info(streamFile, offset, &info))
break;
if (prev_size && prev_size != info.frame_size) {
is_vbr = 1;
}
else if (!is_vbr) {
cbr_count++;
/* skip ID3v1 */
if ((header & 0xFFFFFF00) == 0x54414700) { /* "TAG\0" */
;VGM_LOG("MPEG: ID3v1 at %lx\n", offset);
offset += 0x80;
continue;
}
if (cbr_count >= 10) {
/* must be CBR, don't bother counting */
samples = (bytes / info.frame_size) * info.frame_samples;
/* regular frame */
if (!mpeg_get_frame_info_h(header, &info)) {
VGM_LOG("MPEG: unknown frame at %lx\n", offset);
break;
}
/* detect Xing header (disguised as a normal frame) */
if (frames < 3 && /* should be first after tags */
info.frame_size >= 0x24 + 0x78 &&
read_u32be(offset + 0x04, sf) == 0 &&
(read_u32be(offset + 0x24, sf) == 0x58696E67 || /* "Xing" (mainly for VBR) */
read_u32be(offset + 0x24, sf) == 0x496E666F)) { /* "Info" (mainly for CBR) */
uint32_t flags = read_u32be(offset + 0x28, sf);
if (flags & 1) { /* other flags indicate seek table and stuff */
uint32_t frame_count = read_u32be(offset + 0x2c, sf);
samples = frame_count * info.frame_samples;
}
/* vendor specific */
if (info.frame_size > 0x24 + 0x78 + 0x24 &&
read_u32be(offset + 0x9c, sf) == 0x4C414D45) { /* "LAME" */
if (info.layer == 3) {
uint32_t delays = read_u32be(offset + 0xb0, sf);
encoder_delay = ((delays >> 12) & 0xFFF);
encoder_padding = ((delays >> 0) & 0xFFF);
encoder_delay += (528 + 1); /* implicit MDCT decoder delay (seen in LAME source) */
if (encoder_padding > 528 + 1)
encoder_padding -= (528 + 1);
}
else {
encoder_delay = 240 + 1;
}
/* replay gain and stuff */
}
/* there is also "iTunes" vendor with no apparent extra info, iTunes delays are in "iTunSMPB" ID3 tag */
;VGM_LOG("MPEG: found Xing header\n");
break; /* we got samples */
}
//TODO: detect "VBRI" header (Fraunhofer encoder)
// https://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header#VBRIHeader
/* could detect VBR/CBR but read frames to remove ID3 end tags */
frames++;
offset += info.frame_size;
prev_size = info.frame_size;
samples += info.frame_samples; /* header frames may be 0? */
samples += info.frame_samples;
}
;VGM_LOG("MPEG: samples=%i, ed=%i, ep=%i, end=%i\n", samples,encoder_delay,encoder_padding, samples - encoder_delay - encoder_padding);
//todo return encoder delay
samples = samples - encoder_delay - encoder_padding;
return samples;
}


+ 41
- 27
Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c View File

@@ -112,12 +112,16 @@ int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamfile, off_t start_offset,
ok = ealayer3_parse_frame(data, -1, &ib, &eaf);
if (!ok) goto fail;
}
//;VGM_ASSERT(!eaf.mpeg1, "EAL3: mpeg2 found at 0x%lx\n", start_offset); /* rare [FIFA 08 (PS3) abk] */
;VGM_ASSERT(!eaf.mpeg1, "EAL3: mpeg2 found at 0x%lx\n", start_offset); /* rare [FIFA 08 (PS3) abk] */
*coding_type = coding_MPEG_ealayer3;
data->channels_per_frame = eaf.channels;
data->samples_per_frame = eaf.mpeg1 ? 1152 : 576;
/* handled at frame start */
//data->skip_samples = 576 + 529;
//data->samples_to_discard = data->skip_samples;
/* encoder delay: EALayer3 handles this while decoding (skips samples as writes PCM blocks) */
return 1;
@@ -133,6 +137,16 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
ealayer3_frame_t eaf_0, eaf_1;
/* the first frame samples must be discarded (verified vs sx.exe with a file without PCM blocks),
* but we can't set samples_to_discard since PCM blocks would be discarded
* SCHl block samples field takes into account this discard (its value already substracts this) */
if ((data->type == MPEG_EAL31 || data->type == MPEG_EAL31b) && ms->current_size_count == 0) {
/* seems true for MP2/576 frame samples too, though they are rare so it's hard to test */
ms->decode_to_discard += 529 + 576; /* standard MP3 decoder delay + 1 granule samples */
ms->current_size_count++;
}
/* read first frame/granule, or PCM-only frame (found alone at the end of SCHl streams) */
{
//;VGM_LOG("s%i: get granule0 at %lx\n", num_stream,stream->offset);
@@ -317,7 +331,7 @@ static int ealayer3_parse_frame_v1(ealayer3_buffer_t *ib, ealayer3_frame_t *eaf,
/* check PCM block */
if (eaf->v1_pcm_flag == 0xEE) {
fill_buf(ib, 32);
r_bits(is, 16,&eaf->v1_offset_samples); /* samples to discard of the next decoded (not PCM block) samples */
r_bits(is, 16,&eaf->v1_offset_samples); /* PCM block offset in the buffer */
r_bits(is, 16,&eaf->v1_pcm_samples); /* number of PCM samples, can be 0 */
eaf->pre_size += 2+2; /* 16b+16b */
@@ -672,8 +686,7 @@ static void ealayer3_copy_pcm_block(uint8_t* outbuf, off_t pcm_offset, int pcm_n
}
/* write PCM block directly to sample buffer and setup decode discard (EALayer3 seems to use this as a prefetch of sorts).
* Meant to be written inmediatedly, as those PCM are parts that can be found after 1 decoded frame.
* (ex. EA-frame_gr0, PCM-frame_0, EA-frame_gr1, PCM-frame_1 actually writes PCM-frame_0+1, decode of EA-frame_gr0+1 + discard part */
* Seems to alter decoded sample buffer to handle encoder delay/padding in a twisted way. */
static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_t *eaf) {
mpeg_custom_stream *ms = data->streams[num_stream];
int channels_per_frame = ms->channels_per_frame;
@@ -694,38 +707,34 @@ static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
if (eaf->v1_pcm_samples || eaf->v1_offset_samples) {
uint8_t* outbuf = ms->output_buffer + bytes_filled;
off_t pcm_offset = stream->offset + eaf->pre_size + eaf->common_size;
size_t decode_to_discard;
VGM_ASSERT(eaf->v1_offset_samples > 576, "EAL3: big discard %i at 0x%x\n", eaf->v1_offset_samples, (uint32_t)stream->offset);
VGM_ASSERT(eaf->v1_pcm_samples > 0x100, "EAL3: big samples %i at 0x%x\n", eaf->v1_pcm_samples, (uint32_t)stream->offset);
VGM_ASSERT(eaf->v1_offset_samples > 0 && eaf->v1_pcm_samples == 0, "EAL3: offset_samples without pcm_samples\n"); /* not seen but could work */
//;VGM_LOG("EA EAL3 v1: off=%lx, discard=%x, pcm=%i, pcm_o=%lx\n",
// stream->offset, eaf->v1_offset_samples, eaf->v1_pcm_samples, pcm_offset);
//;VGM_LOG("EA EAL3 v1: offset=%lx + %x, offset_samples=%x, pcm_samples=%i, spf=%i\n",
// stream->offset, eaf->pre_size + eaf->common_size, eaf->v1_offset_samples, eaf->v1_pcm_samples, data->samples_per_frame);
/* V1 usually discards + copies samples at the same time
* V1b PCM block is in 'planar' format (ex. NFS:U PS3) */
/* V1b PCM block is in 'planar' format (ex. NFS:U PS3) */
ealayer3_copy_pcm_block(outbuf, pcm_offset, eaf->v1_pcm_samples, channels_per_frame, (data->type == MPEG_EAL31), stream->streamfile);
ms->samples_filled += eaf->v1_pcm_samples;
/* skip decoded samples as PCM block 'overwrites' them w/ special meanings */
{
size_t decode_to_discard = eaf->v1_offset_samples;
if (data->type == MPEG_EAL31) {
//todo should also discard v1_pcm_samples, but block layout samples may be exhausted
// and won't move (maybe new block if offset = new offset detected)
if (decode_to_discard == 576)
decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_samples;
}
else {
VGM_ASSERT(decode_to_discard > 0, "EAL3: found offset_samples in V1b\n");
/* probably (576 or samples_per_frame - eaf->v1_offset_samples) but V1b seems to always use 0 and ~47 samples */
if (decode_to_discard == 0) /* seems ok (ex. comparing NFS:UC PS3 vs PC gets correct waveform this way) */
decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_samples; /* musn't discard pcm_number */
}
ms->decode_to_discard += decode_to_discard;
}
//TODO: we should put samples at offset but most EAL3 use it at first frame, which decodes ok, and rarely
// in the last frame [ex. Celebrity Sports Showdown], which is ~60-80 samples off (could click on segments?)
/* v1_offset_samples in V1a controls how the PCM block goes in the sample buffer. Value seems to start
* from frame samples end, taking into account that 1st frame discards 576+529 samples.
* ex. with 47 samples:
* - offset 47 puts block at sample 0 (at 576*2-47 w/o 576+529 discard),
* - offset 63 puts block at sample -16 (only 31 samples visible, so 576*2-63 w/o discard),
* - offset 0 seems to cause sample buffer overrun (at 576*2-0 = outside single frame buffer?)
* In V1b seems to works similarly but offset looks adjusted after initial discard (so offset 0 for first frame)
*
* This behaviour matters most in looping sfx (ex. Burnout Paradise), or tracks that start
* without silence (ex. NFS:UG2), and NFS:UC PS3 (EAL3v1b) vs PC (EAXAS) gets correct waveform this way */
decode_to_discard = eaf->v1_pcm_samples;
ms->decode_to_discard += decode_to_discard;
}
if (eaf->v2_extended_flag) {
@@ -789,6 +798,11 @@ fail:
}
//TODO: this causes lots of rebuffering/slowness in multichannel since each stream has to read back
// (frames are interleaved like s0_g0, s1_g0, s2_g0, s0_g1, s1_g1, s2_g1, ...,
// stream0 advances buffers to s0_g1, but stream1 needs to read back to s1_g0, often trashing custom IO)
// would need to store granule0 after reading but not decoding until next?
/* Skip EA-frames from other streams for .sns/sps multichannel (interleaved 1 EA-frame per stream).
* Due to EALayer3 being in blocks and other complexities (we can't go past a block) all
* streams's offsets should start in the first stream's EA-frame.


+ 1
- 1
Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c View File

@@ -204,7 +204,7 @@ static mpg123_handle * init_mpg123_handle() {
}

mpg123_param(m,MPG123_REMOVE_FLAGS,MPG123_GAPLESS,0.0); /* wonky support */
mpg123_param(m,MPG123_RESYNC_LIMIT, -1, 0x10000); /* should be enough */
mpg123_param(m,MPG123_RESYNC_LIMIT, -1, 0x2000); /* just in case, games shouldn't ever need this */

if (mpg123_open_feed(m) != MPG123_OK) {
goto fail;


+ 39
- 35
Frameworks/vgmstream/vgmstream/src/coding/mta2_decoder.c View File

@@ -4,6 +4,7 @@
/* MTA2 decoder based on:
* - MGS Developer Wiki: https://www.mgsdevwiki.com/wiki/index.php/MTA2_(Codec) [codec by daemon1]
* - Solid4 tools: https://github.com/GHzGangster/Drebin
* (PS3 probably uses floats, so this may not be 100% accurate)
*
* MTA2 layout:
* - data is divided into N tracks of 0x10 header + 0x90 frame per track channel, forming N streams
@@ -17,34 +18,28 @@
* expects samples_to_do to be block_samples at most (could be simplified, I guess).
*/
/* coefs table (extended XA filters) */
static const int mta2_coefs1[8] = {
0, 240, 460, 392, 488, 460, 460, 240
/* tweaked XA/PSX coefs << 8 */
static const int16_t mta2_coefs[8][2] = {
{ 0, 0 },
{ 240, 0 },
{ 460, -208 },
{ 392, -220 },
{ 488, -240 },
{ 460, -240 },
{ 460, -220 },
{ 240, -104 }
};
static const int mta2_coefs2[8] = {
0, 0, -208, -220, -240, -240, -220, -104
};
/* shift table */
static const int mta2_shifts[32] = {
static const int mta2_scales[32] = {
256, 335, 438, 573, 749, 979, 1281, 1675,
2190, 2864, 3746, 4898, 6406, 8377, 10955, 14327,
18736, 24503, 32043, 41905, 54802, 71668, 93724, 122568,
160290, 209620, 274133, 358500, 468831, 613119, 801811, 1048576
};
/* expands nibble */
static short mta2_expand_nibble(int nibble, short hist1, short hist2, int coef_index, int shift_index) {
int output;
if (nibble > 7) /* sign extend */
nibble = nibble - 16;
output = (hist1 * mta2_coefs1[coef_index] + hist2 * mta2_coefs2[coef_index] + (nibble * mta2_shifts[shift_index]) + 128) >> 8;
output = clamp16(output);
return (short)output;
}
/* decodes a block for a channel */
void decode_mta2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
void decode_mta2(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
uint8_t frame[0x10 + 0x90*8] = {0};
int samples_done = 0, sample_count = 0, channel_block_samples, channel_first_sample, frame_size = 0;
int i, group, row, col;
int track_channels = 0, track_channel;
@@ -55,14 +50,14 @@ void decode_mta2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacin
int num_track = 0, channel_layout;
/* parse track header (0x10) and skip tracks that our current channel doesn't belong to */
num_track = read_8bit(stream->offset+0x00,stream->streamfile); /* 0=first */
read_streamfile(frame, stream->offset, 0x10, stream->streamfile); /* ignore EOF errors */
num_track = get_u8 (frame + 0x00); /* 0=first */
/* 0x01(3): num_frame (0=first) */
/* 0x04(1): 0? */
channel_layout = read_8bit(stream->offset+0x05,stream->streamfile); /* bitmask, see mta2.c */
frame_size = read_16bitBE(stream->offset+0x06,stream->streamfile); /* not including this header */
channel_layout = get_u8 (frame + 0x05); /* bitmask, see mta2.c */
frame_size = get_u16be(frame + 0x06); /* not including this header */
/* 0x08(8): null */
VGM_ASSERT(frame_size == 0, "MTA2: empty frame at %x\n", (uint32_t)stream->offset);
/* frame_size 0 means silent/empty frame (rarely found near EOF for one track but not others)
* negative track only happens for truncated files (EOF) */
@@ -74,13 +69,13 @@ void decode_mta2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacin
}
track_channels = 0;
for (i = 0; i < 8; i++) {
for (i = 0; i < 8; i++) { /* max 8ch */
if ((channel_layout >> i) & 0x01)
track_channels++;
}
if (track_channels == 0) { /* bad data, avoid div by 0 */
VGM_LOG("track_channels 0 at %x\n", (uint32_t)stream->offset);
VGM_LOG("MTA2: track_channels 0 at %x\n", (uint32_t)stream->offset);
return;
}
@@ -93,19 +88,20 @@ void decode_mta2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacin
}
while (1);
/* parse stuff */
read_streamfile(frame + 0x10, stream->offset + 0x10, frame_size, stream->streamfile); /* ignore EOF errors */
track_channel = channel % track_channels;
channel_block_samples = (0x80*2);
channel_first_sample = first_sample % (0x80*2);
/* parse channel frame (header 0x04*4 + data 0x20*4) */
for (group = 0; group < 4; group++) {
short hist2, hist1, coefs, shift, output;
int group_header = read_32bitBE(stream->offset + 0x10 + track_channel*0x90 + group*0x4, stream->streamfile);
short hist2, hist1, coefs, scale;
uint32_t group_header = get_u32be(frame + 0x10 + track_channel*0x90 + group*0x4);
hist2 = (short) ((group_header >> 16) & 0xfff0); /* upper 16b discarding 4b */
hist1 = (short) ((group_header >> 4) & 0xfff0); /* lower 16b discarding 4b */
coefs = (group_header >> 5) & 0x7; /* mid 3b */
shift = group_header & 0x1f; /* lower 5b */
scale = group_header & 0x1f; /* lower 5b */
/* write header samples (skips the last 2 group nibbles), like Drebin's decoder
* last 2 nibbles and next 2 header hist should match though */
@@ -120,23 +116,31 @@ void decode_mta2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacin
}
sample_count++;
/* decode nibbles */
for (row = 0; row < 8; row++) {
int pos = 0x10 + track_channel*0x90 + 0x10 + group*0x4 + row*0x10;
for (col = 0; col < 4*2; col++) {
uint8_t nibbles = read_8bit(stream->offset + 0x10 + 0x10 + track_channel*0x90 + group*0x4 + row*0x10 + col/2, stream->streamfile);
int nibble_shift = (!(col&1) ? 4 : 0); /* upper first */
output = mta2_expand_nibble((nibbles >> nibble_shift) & 0xf, hist1, hist2, coefs, shift);
uint8_t nibbles = frame[pos + col/2];
int32_t sample;
sample = col&1 ? /* high nibble first */
get_low_nibble_signed(nibbles) :
get_high_nibble_signed(nibbles);
sample = sample * mta2_scales[scale];
sample = (sample + hist1 * mta2_coefs[coefs][0] + hist2 * mta2_coefs[coefs][1] + 128) >> 8;
sample = clamp16(sample);
/* ignore last 2 nibbles (uses first 2 header samples) */
if (row < 7 || col < 3*2) {
if (sample_count >= channel_first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = output;
outbuf[samples_done * channelspacing] = sample;
samples_done++;
}
sample_count++;
}
hist2 = hist1;
hist1 = output;
hist1 = sample;
}
}
}


+ 38
- 34
Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c View File

@@ -8,12 +8,12 @@
* Layout: N tracks of 0x10 header + 0x80*2 (always 2ch; multichannels uses 4ch = 2ch track0 + 2ch track1 xN).
*/

static const int index_table[16] = {
static const int mtaf_step_indexes[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};

static const int16_t step_size[32][16] = {
static const int16_t mtaf_step_sizes[32][16] = {
{ 1, 5, 9, 13, 16, 20, 24, 28,
-1, -5, -9, -13, -16, -20, -24, -28, },
{ 2, 6, 11, 15, 20, 24, 29, 33,
@@ -81,52 +81,56 @@ static const int16_t step_size[32][16] = {
};


void decode_mtaf(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int32_t sample_count;
int i;
int c = channel%2; /* global channel to track channel */
void decode_mtaf(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
uint8_t frame[0x110] = {0};
off_t frame_offset;
int i, ch, sample_count = 0;
size_t bytes_per_frame /*, samples_per_frame*/;
int32_t hist = stream->adpcm_history1_16;
int32_t step_idx = stream->adpcm_step_index;
int32_t step_index = stream->adpcm_step_index;


/* read header when we hit a new track every 0x100 samples */
first_sample = first_sample % 0x100;
/* special stereo interleave, stereo */
bytes_per_frame = 0x10 + 0x80*2;
//samples_per_frame = (bytes_per_frame - 0x10) / 2 * 2; /* 256 */
ch = channel % 2; /* global channel to track channel */
//first_sample = first_sample % samples_per_frame; /* for flat layout */

/* read frame */
frame_offset = stream->offset;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */

/* parse frame header when we hit a new track every frame samples */
if (first_sample == 0) {
/* 0x10 header: track (8b, 0=first), track count (24b, 1=first), step-L, step-R, hist-L, hist-R */
int32_t init_idx = read_16bitLE(stream->offset+4+0+c*2, stream->streamfile); /* step-L/R */
int32_t init_hist = read_16bitLE(stream->offset+4+4+c*4, stream->streamfile); /* hist-L/R: hist 16bit + empty 16bit */

VGM_ASSERT(init_idx < 0 || init_idx > 31, "MTAF: bad header idx @ 0x%x\n", (uint32_t)stream->offset);
/* avoid index out of range in corrupt files */
if (init_idx < 0) {
init_idx = 0;
} else if (init_idx > 31) {
init_idx = 31;
step_index = get_s16le(frame + 0x04 + 0x00 + ch*0x02); /* step-L/R */
hist = get_s16le(frame + 0x04 + 0x04 + ch*0x04); /* hist-L/R: hist 16bit + empty 16bit */

VGM_ASSERT(step_index < 0 || step_index > 31, "MTAF: bad header idx at 0x%x\n", (uint32_t)stream->offset);
if (step_index < 0) {
step_index = 0;
} else if (step_index > 31) {
step_index = 31;
}

step_idx = init_idx;
hist = init_hist;
}

/* decode nibbles */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
uint8_t nibbles = frame[0x10 + 0x80*ch + i/2];
uint8_t nibble = (nibbles >> (!(i&1)?0:4)) & 0xf; /* lower first */

/* skip to nibble */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t byte = read_8bit(stream->offset + 0x10 + 0x80*c + i/2, stream->streamfile);
uint8_t nibble = (byte >> (!(i&1)?0:4)) & 0xf; /* lower first */

hist = clamp16(hist+step_size[step_idx][nibble]);
hist = clamp16(hist + mtaf_step_sizes[step_index][nibble]);
outbuf[sample_count] = hist;
sample_count += channelspacing;

step_idx += index_table[nibble];
if (step_idx < 0) { /* clip step */
step_idx = 0;
} else if (step_idx > 31) {
step_idx = 31;
step_index += mtaf_step_indexes[nibble];
if (step_index < 0) {
step_index = 0;
} else if (step_index > 31) {
step_index = 31;
}
}

/* update state */
stream->adpcm_step_index = step_idx;
stream->adpcm_step_index = step_index;
stream->adpcm_history1_16 = hist;
}

+ 43
- 39
Frameworks/vgmstream/vgmstream/src/coding/nds_procyon_decoder.c View File

@@ -1,58 +1,62 @@
#include "coding.h"
#include "../util.h"

/* standard XA/PSX coefs << 6 */
static const int8_t proc_coefs[16][2] = {
{ 0, 0 },
{ 60, 0 },
{ 115, -52 },
{ 98, -55 },
{ 122, -60 },
/* rest is 0s */
};

/* ADPCM found in NDS games using Procyon Studio Digital Sound Elements */
void decode_nds_procyon(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame[0x10] = {0};
off_t frame_offset;
int i, frames_in, sample_count = 0;
size_t bytes_per_frame, samples_per_frame;
int index, scale, coef1, coef2;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
uint8_t header;

static const int8_t proc_coef[5][2] =
{
{0x00,0x00},
{0x3C,0x00},
{0x73,0xCC},
{0x62,0xC9},
{0x7A,0xC4},
};

void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int32_t sample_count;
/* external interleave (fixed size), mono */
bytes_per_frame = 0x10;
samples_per_frame = (bytes_per_frame - 0x01) * 2; /* 30 */
frames_in = first_sample / samples_per_frame;

int framesin = first_sample/30;
/* parse frame header */
frame_offset = stream->offset + bytes_per_frame * frames_in;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
header = frame[0x0F] ^ 0x80;
scale = 12 - (header & 0xf);
index = (header >> 4) & 0xf;
coef1 = proc_coefs[index][0];
coef2 = proc_coefs[index][1];

uint8_t header = read_8bit(framesin*16+15+stream->offset,stream->streamfile) ^ 0x80;
int scale = 12 - (header & 0xf);
int coef_index = (header >> 4) & 0xf;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
int32_t coef1;
int32_t coef2;

if (coef_index > 4) coef_index = 0;
coef1 = proc_coef[coef_index][0];
coef2 = proc_coef[coef_index][1];
first_sample = first_sample%30;

for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(framesin*16+stream->offset+i/2,stream->streamfile) ^ 0x80;

int32_t sample =
(int32_t)
(i&1?
get_high_nibble_signed(sample_byte):
get_low_nibble_signed(sample_byte)
) * 64 * 64;
/* decode nibbles */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
uint8_t nibbles = frame[i/2] ^ 0x80;
int32_t sample = 0;

sample = i&1 ? /* low nibble first */
get_high_nibble_signed(nibbles) :
get_low_nibble_signed(nibbles);
sample = sample * 64 * 64; /* << 12 */
if (scale < 0)
{
sample <<= -scale;
}
else
sample >>= scale;

sample = (hist1 * coef1 + hist2 * coef2 + 32) / 64 + (sample * 64);

hist2 = hist1;
hist1 = sample;
hist1 = sample; /* clamp *after* this */

outbuf[sample_count] = clamp16((sample + 32) / 64) / 64 * 64;
outbuf[sample_count] = clamp16((sample + 32) / 64) / 64 * 64;
sample_count += channelspacing;
}

stream->adpcm_history1_32 = hist1;


+ 53
- 43
Frameworks/vgmstream/vgmstream/src/coding/ngc_afc_decoder.c View File

@@ -1,56 +1,66 @@
#include "coding.h"
#include "../util.h"

const short afc_coef[16][2] =
{{0,0},
{0x0800,0},
{0,0x0800},
{0x0400,0x0400},
{0x1000,0xf800},
{0x0e00,0xfa00},
{0x0c00,0xfc00},
{0x1200,0xf600},
{0x1068,0xf738},
{0x12c0,0xf704},
{0x1400,0xf400},
{0x0800,0xf800},
{0x0400,0xfc00},
{0xfc00,0x0400},
{0xfc00,0},
{0xf800,0}};

void decode_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int32_t sample_count;

int framesin = first_sample/16;

int8_t header = read_8bit(framesin*9+stream->offset,stream->streamfile);
int32_t scale = 1 << ((header>>4) & 0xf);
int coef_index = (header & 0xf);
static const int16_t afc_coefs[16][2] = {
{ 0, 0 },
{ 2048, 0 },
{ 0, 2048 },
{ 1024, 1024 },
{ 4096,-2048 },
{ 3584,-1536 },
{ 3072,-1024 },
{ 4608,-2560 },
{ 4200,-2248 },
{ 4800,-2300 },
{ 5120,-3072 },
{ 2048,-2048 },
{ 1024,-1024 },
{-1024, 1024 },
{-1024, 0 },
{-2048, 0 }
};

void decode_ngc_afc(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame[0x09] = {0};
off_t frame_offset;
int i, frames_in, sample_count = 0;
size_t bytes_per_frame, samples_per_frame;
int index, scale, coef1, coef2;
int32_t hist1 = stream->adpcm_history1_16;
int32_t hist2 = stream->adpcm_history2_16;
int coef1 = afc_coef[coef_index][0];
int coef2 = afc_coef[coef_index][1];
/*printf("offset: %x\nscale: %d\nindex: %d (%lf,%lf)\nhist: %d %d\n",
(unsigned)stream->offset,scale,coef_index,coef1/2048.0,coef2/2048.0,hist1,hist2);*/

first_sample = first_sample%16;

for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(framesin*9+stream->offset+1+i/2,stream->streamfile);
/* external interleave, mono */
bytes_per_frame = 0x09;
samples_per_frame = (bytes_per_frame - 0x01) * 2; /* always 16 */
frames_in = first_sample / samples_per_frame;

/* parse frame header */
frame_offset = stream->offset + bytes_per_frame * frames_in;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
scale = 1 << ((frame[0] >> 4) & 0xf);
index = (frame[0] & 0xf);
coef1 = afc_coefs[index][0];
coef2 = afc_coefs[index][1];

/* decode nibbles */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
uint8_t nibbles = frame[0x01 + i/2];
int32_t sample;

sample = i&1 ? /* high nibble first */
get_low_nibble_signed(nibbles) :
get_high_nibble_signed(nibbles);
sample = ((sample * scale) << 11);
sample = (sample + coef1*hist1 + coef2*hist2) >> 11;

sample = clamp16(sample);

outbuf[sample_count] = clamp16((
(((i&1?
get_low_nibble_signed(sample_byte):
get_high_nibble_signed(sample_byte)
) * scale)<<11) +
(coef1 * hist1 + coef2 * hist2))>>11
);
/*printf("%hd\n",outbuf[sample_count]);*/
outbuf[sample_count] = sample;
sample_count += channelspacing;

hist2 = hist1;
hist1 = outbuf[sample_count];
hist1 = sample;
}

stream->adpcm_history1_16 = hist1;


+ 32
- 34
Frameworks/vgmstream/vgmstream/src/coding/ngc_dtk_decoder.c View File

@@ -2,63 +2,61 @@
#include "../util.h"


/* Nintendo GC Disc TracK streaming ADPCM (similar to CD-XA) */
void decode_ngc_dtk(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
/* standard XA coefs << 6 */
static const int8_t dtk_coefs[16][2] = {
{ 0, 0 },
{ 60, 0 },
{ 115, 52 },
{ 98, 55 },
/* rest assumed to be 0s */
};

/* Nintendo GC Disc TracK streaming ADPCM (similar to XA) */
void decode_ngc_dtk(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
uint8_t frame[0x20] = {0};
off_t frame_offset;
int i, frames_in, sample_count = 0;
size_t bytes_per_frame, samples_per_frame;
uint8_t coef_index, shift_factor;
int index, shift, coef1, coef2;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;


/* external interleave (fixed size), stereo */
bytes_per_frame = 0x20;
samples_per_frame = 28;
samples_per_frame = (0x20 - 0x04); /* 28 for each channel */
frames_in = first_sample / samples_per_frame;
first_sample = first_sample % samples_per_frame;

/* parse frame L/R header (repeated at 0x03/04) */
frame_offset = stream->offset + bytes_per_frame*frames_in;
coef_index = ((uint8_t)read_8bit(frame_offset+channel,stream->streamfile) >> 4) & 0xf;
shift_factor = ((uint8_t)read_8bit(frame_offset+channel,stream->streamfile) >> 0) & 0xf;
frame_offset = stream->offset + bytes_per_frame * frames_in;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
index = (frame[channel] >> 4) & 0xf;
shift = (frame[channel] >> 0) & 0xf;
coef1 = dtk_coefs[index][0];
coef2 = dtk_coefs[index][1];
/* rare but happens, also repeated headers don't match (ex. Ikaruga (GC) SONG02.adp) */
VGM_ASSERT_ONCE(coef_index > 4 || shift_factor > 12, "DTK: incorrect coefs/shift at %x\n", (uint32_t)frame_offset);
VGM_ASSERT_ONCE(index > 4 || shift > 12, "DTK: incorrect coefs/shift at %x\n", (uint32_t)frame_offset);

/* decode nibbles */
for (i = first_sample; i < first_sample+samples_to_do; i++) {
int32_t hist = 0, new_sample;
uint8_t nibbles = (uint8_t)read_8bit(frame_offset+0x04+i,stream->streamfile);
for (i = first_sample; i < first_sample + samples_to_do; i++) {
int sample, hist;
uint8_t nibbles = frame[0x04 + i];

/* apply XA filters << 6 */
switch(coef_index) {
case 0:
hist = 0; // (hist1 * 0) - (hist2 * 0);
break;
case 1:
hist = (hist1 * 60); // - (hist2 * 0);
break;
case 2:
hist = (hist1 * 115) - (hist2 * 52);
break;
case 3:
hist = (hist1 * 98) - (hist2 * 55);
break;
}
hist = (hist + 32) >> 6;
if (hist > 0x1fffff) hist = 0x1fffff;
if (hist < -0x200000) hist = -0x200000;
hist = (hist1*coef1 - hist2*coef2 + 32) >> 6;
if (hist > 2097151) hist = 2097151;
else if (hist < -2097152) hist = -2097152;

new_sample = (channel==0) ? /* L=low nibble first */
sample = (channel==0) ? /* L=low nibble first */
get_low_nibble_signed(nibbles) :
get_high_nibble_signed(nibbles);
new_sample = (new_sample << 12) >> shift_factor;
new_sample = (new_sample << 6) + hist;
sample = (sample << 12) >> shift;
sample = (sample << 6) + hist;

hist2 = hist1;
hist1 = new_sample;
hist1 = sample; /* clamp *after* this so hist goes pretty high */

outbuf[sample_count] = clamp16(new_sample >> 6);
outbuf[sample_count] = clamp16(sample >> 6);
sample_count += channelspacing;
}



+ 3
- 7
Frameworks/vgmstream/vgmstream/src/coding/pcm_decoder.c View File

@@ -206,15 +206,11 @@ void decode_alaw(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacin

void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian) {
int i, sample_count;
int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE;
float (*read_f32)(off_t,STREAMFILE*) = big_endian ? read_f32be : read_f32le;

for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint32_t sample_int = read_32bit(stream->offset+i*4,stream->streamfile);
float* sample_float;
int sample_pcm;

sample_float = (float*)&sample_int;
sample_pcm = (int)floor((*sample_float) * 32767.f + .5f);
float sample_float = read_f32(stream->offset+i*4,stream->streamfile);
int sample_pcm = (int)floor(sample_float * 32767.f + .5f);

outbuf[sample_count] = clamp16(sample_pcm);
}


+ 55
- 41
Frameworks/vgmstream/vgmstream/src/coding/ptadpcm_decoder.c View File

@@ -1,54 +1,69 @@
#include "coding.h"
/* a somewhat IMA-like mix of step+next index all in one (maybe an array[][] originally?) */
static const int32_t ptadpcm_table[(16+16)*16] = { /* 16 of (step+index) + 16 values in a nibble */
-14, 2, -10, 2, -7, 1, -5, 1, -3, 0, -2, 0, -1, 0, 0, 0,
0, 0, 1, 0, 2, 0, 3, 0, 5, 1, 7, 1, 10, 2, 14, 2,
-28, 3, -20, 3, -14, 2, -10, 2, -7, 1, -5, 1, -3, 1, -1, 0,
1, 0, 3, 1, 5, 1, 7, 1, 10, 2, 14, 2, 20, 3, 28, 3,
-56, 4, -40, 4, -28, 3, -20, 3, -14, 2, -10, 2, -6, 2, -2, 1,
2, 1, 6, 2, 10, 2, 14, 2, 20, 3, 28, 3, 40, 4, 56, 4,
-112, 5, -80, 5, -56, 4, -40, 4, -28, 3, -20, 3, -12, 3, -4, 2,
4, 2, 12, 3, 20, 3, 28, 3, 40, 4, 56, 4, 80, 5, 112, 5,
-224, 6, -160, 6, -112, 5, -80, 5, -56, 4, -40, 4, -24, 4, -8, 3,
8, 3, 24, 4, 40, 4, 56, 4, 80, 5, 112, 5, 160, 6, 224, 6,
-448, 7, -320, 7, -224, 6, -160, 6, -112, 5, -80, 5, -48, 5, -16, 4,
16, 4, 48, 5, 80, 5, 112, 5, 160, 6, 224, 6, 320, 7, 448, 7,
-896, 8, -640, 8, -448, 7, -320, 7, -224, 6, -160, 6, -96, 6, -32, 5,
32, 5, 96, 6, 160, 6, 224, 6, 320, 7, 448, 7, 640, 8, 896, 8,
-1792, 9, -1280, 9, -896, 8, -640, 8, -448, 7, -320, 7, -192, 7, -64, 6,
64, 6, 192, 7, 320, 7, 448, 7, 640, 8, 896, 8, 1280, 9, 1792, 9,
-3584, 10, -2560, 10, -1792, 9, -1280, 9, -896, 8, -640, 8, -384, 8, -128, 7,
128, 7, 384, 8, 640, 8, 896, 8, 1280, 9, 1792, 9, 2560, 10, 3584, 10,
-7168, 11, -5120, 11, -3584, 10, -2560, 10, -1792, 9, -1280, 9, -768, 9, -256, 8,
256, 8, 768, 9, 1280, 9, 1792, 9, 2560, 10, 3584, 10, 5120, 11, 7168, 11,
-14336, 11, -10240, 11, -7168, 11, -5120, 11, -3584, 10, -2560, 10, -1536, 10, -512, 9,
512, 9, 1536, 10, 2560, 10, 3584, 10, 5120, 11, 7168, 11, 10240, 11, 14336, 11,
-28672, 11, -20480, 11, -14336, 11, -10240, 11, -7168, 11, -5120, 11, -3072, 11, -1024, 10,
1024, 10, 3072, 11, 5120, 11, 7168, 11, 10240, 11, 14336, 11, 20480, 11, 28672, 11,
/* rest is 0s */
/* a somewhat IMA-like mix of pre-calculated [index][nibble][step,index] all in one */
static const int32_t ptadpcm_table[16][16][2] = {
{
{ -14, 2}, { -10, 2}, { -7, 1}, { -5, 1}, { -3, 0}, { -2, 0}, { -1, 0}, { 0, 0},
{ 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 5, 1}, { 7, 1}, { 10, 2}, { 14, 2},
}, {
{ -28, 3}, { -20, 3}, { -14, 2}, { -10, 2}, { -7, 1}, { -5, 1}, { -3, 1}, { -1, 0},
{ 1, 0}, { 3, 1}, { 5, 1}, { 7, 1}, { 10, 2}, { 14, 2}, { 20, 3}, { 28, 3},
}, {
{ -56, 4}, { -40, 4}, { -28, 3}, { -20, 3}, { -14, 2}, { -10, 2}, { -6, 2}, { -2, 1},
{ 2, 1}, { 6, 2}, { 10, 2}, { 14, 2}, { 20, 3}, { 28, 3}, { 40, 4}, { 56, 4},
}, {
{ -112, 5}, { -80, 5}, { -56, 4}, { -40, 4}, { -28, 3}, { -20, 3}, { -12, 3}, { -4, 2},
{ 4, 2}, { 12, 3}, { 20, 3}, { 28, 3}, { 40, 4}, { 56, 4}, { 80, 5}, { 112, 5},
}, {
{ -224, 6}, { -160, 6}, { -112, 5}, { -80, 5}, { -56, 4}, { -40, 4}, { -24, 4}, { -8, 3},
{ 8, 3}, { 24, 4}, { 40, 4}, { 56, 4}, { 80, 5}, { 112, 5}, { 160, 6}, { 224, 6},
}, {
{ -448, 7}, { -320, 7}, { -224, 6}, { -160, 6}, { -112, 5}, { -80, 5}, { -48, 5}, { -16, 4},
{ 16, 4}, { 48, 5}, { 80, 5}, { 112, 5}, { 160, 6}, { 224, 6}, { 320, 7}, { 448, 7},
}, {
{ -896, 8}, { -640, 8}, { -448, 7}, { -320, 7}, { -224, 6}, { -160, 6}, { -96, 6}, { -32, 5},
{ 32, 5}, { 96, 6}, { 160, 6}, { 224, 6}, { 320, 7}, { 448, 7}, { 640, 8}, { 896, 8},
}, {
{ -1792, 9}, { -1280, 9}, { -896, 8}, { -640, 8}, { -448, 7}, { -320, 7}, { -192, 7}, { -64, 6},
{ 64, 6}, { 192, 7}, { 320, 7}, { 448, 7}, { 640, 8}, { 896, 8}, { 1280, 9}, { 1792, 9},
}, {
{ -3584, 10}, { -2560, 10}, { -1792, 9}, { -1280, 9}, { -896, 8}, { -640, 8}, { -384, 8}, { -128, 7},
{ 128, 7}, { 384, 8}, { 640, 8}, { 896, 8}, { 1280, 9}, { 1792, 9}, { 2560, 10}, { 3584, 10},
}, {
{ -7168, 11}, { -5120, 11}, { -3584, 10}, { -2560, 10}, {-1792, 9}, {-1280, 9}, { -768, 9}, { -256, 8},
{ 256, 8}, { 768, 9}, { 1280, 9}, { 1792, 9}, { 2560, 10}, { 3584, 10}, { 5120, 11}, { 7168, 11},
}, {
{-14336, 11}, {-10240, 11}, { -7168, 11}, { -5120, 11}, {-3584, 10}, {-2560, 10}, {-1536, 10}, { -512, 9},
{ 512, 9}, { 1536, 10}, { 2560, 10}, { 3584, 10}, { 5120, 11}, { 7168, 11}, {10240, 11}, {14336, 11},
}, {
{-28672, 11}, {-20480, 11}, {-14336, 11}, {-10240, 11}, {-7168, 11}, {-5120, 11}, {-3072, 11}, {-1024, 10},
{ 1024, 10}, { 3072, 11}, { 5120, 11}, { 7168, 11}, {10240, 11}, {14336, 11}, {20480, 11}, {28672, 11},
},
/* rest is 0s (uses up to index 12) */
};
/* Platinum "PtADPCM" custom ADPCM for Wwise (reverse engineered from .exes). */
void decode_ptadpcm(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size) {
void decode_ptadpcm(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size) {
uint8_t frame[0x104] = {0};
off_t frame_offset;
int i, frames_in, sample_count = 0, samples_done = 0;
size_t bytes_per_frame, samples_per_frame;
int16_t hist1, hist2;
int index, step;
int index, nibble, step;
/* external interleave (variable size), mono */
bytes_per_frame = frame_size;
samples_per_frame = 2 + (frame_size - 0x05) * 2;
frames_in = first_sample / samples_per_frame;
first_sample = first_sample % samples_per_frame;
//first_sample = first_sample % samples_per_frame;
/* parse frame header */
frame_offset = stream->offset + bytes_per_frame*frames_in;
hist2 = read_16bitLE(frame_offset+0x00,stream->streamfile);
hist1 = read_16bitLE(frame_offset+0x02,stream->streamfile);
index = (uint8_t)read_8bit(frame_offset+0x04,stream->streamfile);
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
hist2 = get_s16le(frame + 0x00);
hist1 = get_s16le(frame + 0x02);
index = frame[0x04];
VGM_ASSERT_ONCE(index > 12, "PTADPCM: incorrect index at %x\n", (uint32_t)frame_offset);
@@ -66,26 +81,25 @@ void decode_ptadpcm(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspa
/* decode 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+0x05 + i/2,stream->streamfile);
uint8_t nibble;
uint8_t nibbles = frame[0x05 + i/2];
int32_t sample;
nibble = !(i&1) ? /* low nibble first */
(nibbles >> 0) & 0xF :
(nibbles >> 4) & 0xF;
step = ptadpcm_table[2*(nibble + 16*index) + 0];
index = ptadpcm_table[2*(nibble + 16*index) + 1];
new_sample = clamp16(step + 2*hist1 - hist2);
step = ptadpcm_table[index][nibble][0];
index = ptadpcm_table[index][nibble][1];
sample = clamp16(step + 2*hist1 - hist2);
if (sample_count >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = new_sample;
outbuf[samples_done * channelspacing] = sample;
samples_done++;
}
sample_count++;
hist2 = hist1;
hist1 = new_sample;
hist1 = sample;
}
//stream->adpcm_history1_32 = hist1;


+ 15
- 13
Frameworks/vgmstream/vgmstream/src/coding/xmd_decoder.c View File

@@ -3,25 +3,27 @@
/* Decodes Konami XMD from Xbox games.
* Algorithm reverse engineered from SH4/CV:CoD's xbe (byte-accurate). */
void decode_xmd(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size) {
void decode_xmd(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size) {
uint8_t frame[0x15] = {0};
off_t frame_offset;
int i, frames_in, sample_count = 0, samples_done = 0;
size_t bytes_per_frame, samples_per_frame;
int16_t hist1, hist2;
uint16_t scale;
/* external interleave (variable size), mono */
bytes_per_frame = frame_size;
samples_per_frame = 2 + (frame_size - 0x06) * 2;
frames_in = first_sample / samples_per_frame;
first_sample = first_sample % samples_per_frame;
//first_sample = first_sample % samples_per_frame; /* for flat layout */
/* parse frame header */
frame_offset = stream->offset + bytes_per_frame*frames_in;
hist2 = read_16bitLE(frame_offset+0x00,stream->streamfile);
hist1 = read_16bitLE(frame_offset+0x02,stream->streamfile);
scale = (uint16_t)read_16bitLE(frame_offset+0x04,stream->streamfile); /* scale doesn't go too high though */
frame_offset = stream->offset + bytes_per_frame * frames_in;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
hist2 = get_s16le(frame + 0x00);
hist1 = get_s16le(frame + 0x02);
scale = get_u16le(frame + 0x04); /* scale doesn't go too high though */
/* write header samples (needed) */
if (sample_count >= first_sample && samples_done < samples_to_do) {
@@ -37,25 +39,25 @@ void decode_xmd(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
/* decode 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+0x06 + i/2,stream->streamfile);
uint8_t nibbles = frame[0x06 + i/2];
int32_t sample;
new_sample = i&1 ? /* low nibble first */
sample = i&1 ? /* low nibble first */
get_high_nibble_signed(nibbles):
get_low_nibble_signed(nibbles);
/* Coefs are based on XA's filter 2 (using those creates hissing in some songs though)
* ex. 1.796875 * (1 << 14) = 0x7300, -0.8125 * (1 << 14) = -0x3400 */
new_sample = (new_sample*(scale<<14) + (hist1*0x7298) - (hist2*0x3350)) >> 14;
sample = (sample*(scale<<14) + (hist1*0x7298) - (hist2*0x3350)) >> 14;
//new_sample = clamp16(new_sample); /* not needed */
if (sample_count >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (int16_t)new_sample;
outbuf[samples_done * channelspacing] = (int16_t)sample;
samples_done++;
}
sample_count++;
hist2 = hist1;
hist1 = new_sample;
hist1 = sample;
}
//stream->adpcm_history1_32 = hist1;


+ 18
- 9
Frameworks/vgmstream/vgmstream/src/formats.c View File

@@ -6,10 +6,16 @@
* to inform plugins that need it. Common extensions are commented out to avoid stealing them
* and possibly adding an unwanted association to the player. */
/* Common extensions (like .wav or .ogg) should go in the common_extension_list. It should only
* contain common formats that vgmstream can also parse, to avoid hijacking them (since their
* plugins typically are faster and have desirable features vgmstream won't handle). Extensions of
* formats not parsed don't need to go there (for example .stm is a Scream Tracker Module elsewhere,
* but our .stm is very different so there is no conflict). */
/* Some extensions require external libraries and could be #ifdef, not worth. */
/* Formats marked as "not parsed" mean they'll go through FFmpeg, the header/extension isn't
* parsed by vgmstream and typically won't not be fully accurate. May have a .ext.pos pair for fun. */
* parsed by vgmstream and typically won't not be fully accurate. */
static const char* extension_list[] = {
@@ -25,7 +31,6 @@ static const char* extension_list[] = {
//"aac", //common
"aa3", //FFmpeg/not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
"aaap",
"aax",
"abk",
//"ac3", //common, FFmpeg/not parsed (AC3)
@@ -131,6 +136,7 @@ static const char* extension_list[] = {
"data",
"dax",
"dbm",
"dct",
"dcs",
"ddsp",
"de2",
@@ -175,7 +181,7 @@ static const char* extension_list[] = {
"gin",
"gms",
"gsb",
//"gsf", //conflicts with GBA gsf plugins?
"gsf",
"gtd",
"gwm",
@@ -211,6 +217,7 @@ static const char* extension_list[] = {
"imc",
"int",
"is14",
"isb",
"isd",
"isws",
"itl",
@@ -268,6 +275,7 @@ static const char* extension_list[] = {
"lwma", //fake extension for .wma, FFmpeg/not parsed
"mab",
"mad",
"map",
"matx",
"mc3",
@@ -444,7 +452,7 @@ static const char* extension_list[] = {
"sss",
"ster",
"sth",
//"stm", //common
"stm",
"stma", //fake extension/header id for .stm
"str",
"stream",
@@ -568,6 +576,7 @@ static const char* extension_list[] = {
"ydsp",
"ymf",
"zic",
"zsd",
"zsm",
"zss",
@@ -585,7 +594,6 @@ static const char* common_extension_list[] = {
"aiff", //common
"bin", //common
"flac", //common
"gsf", //conflicts with GBA gsf plugins?
"mp+", //common [Moonshine Runners (PC)]
"mp2", //common
"mp3", //common
@@ -593,7 +601,6 @@ static const char* common_extension_list[] = {
"mpc", //common
"ogg", //common
"opus", //common
"stm", //common
"wav", //common
};
@@ -830,7 +837,7 @@ static const meta_info meta_info_list[] = {
{meta_RFRM, "Retro Studios RFRM header"},
{meta_NGC_ADPDTK, "Nintendo ADP raw header"},
{meta_RSF, "Retro Studios RSF raw header"},
{meta_AFC, "Nintendo AFC header"},
{meta_AFC, "Nintendo .AFC header"},
{meta_AST, "Nintendo AST header"},
{meta_HALPST, "HAL Laboratory HALPST header"},
{meta_DSP_RS03, "Retro Studios RS03 header"},
@@ -864,6 +871,7 @@ static const meta_info meta_info_list[] = {
{meta_PS2_VAGi, "Sony VAGi header"},
{meta_PS2_VAGp, "Sony VAGp header"},
{meta_PS2_pGAV, "Sony pGAV header"},
{meta_PS2_VAGp_AAAP, "Acclaim Austin AAAp VAG header"},
{meta_SEB, "Game Arts .SEB header"},
{meta_STR_WAV, "Blitz Games .STR+WAV header"},
{meta_PS2_ILD, "ILD header"},
@@ -1021,7 +1029,6 @@ static const meta_info meta_info_list[] = {
{meta_WII_BNS, "Nintendo BNS header"},
{meta_WII_WAS, "Sumo Digital iSWS header"},
{meta_XBOX_HLWAV, "Half Life 2 bgm header"},
{meta_STX, "Nintendo .stx header"},
{meta_MYSPD, "U-Sing .MYSPD header"},
{meta_HIS, "Her Interactive HIS header"},
{meta_PS2_AST, "KOEI AST header"},
@@ -1029,7 +1036,7 @@ static const meta_info meta_info_list[] = {
{meta_DMSG, "RIFF/DMSGsegh header"},
{meta_PONA_3DO, "Policenauts BGM header"},
{meta_PONA_PSX, "Policenauts BGM header"},
{meta_NGC_DSP_AAAP, "Acclaim Austin AAAp header"},
{meta_NGC_DSP_AAAP, "Acclaim Austin AAAp DSP header"},
{meta_NGC_DSP_KONAMI, "Konami DSP header"},
{meta_PS2_STER, "STER Header"},
{meta_BNSF, "Namco Bandai BNSF header"},
@@ -1240,6 +1247,8 @@ static const meta_info meta_info_list[] = {
{meta_XMV_VALVE, "Valve XMV header"},
{meta_UBI_HX, "Ubisoft HXx header"},
{meta_BMP_KONAMI, "Konami BMP header"},
{meta_ISB, "Creative ISACT header"},
{meta_XSSB, "Artoon XSSB header"},
};


+ 32
- 39
Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_1snh.c View File

@@ -6,89 +6,81 @@
void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
int i;
size_t block_size = 0, block_header = 0;
uint32_t block_id;
size_t block_size = 0, block_header = 0, audio_size = 0;
int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE;
size_t file_size = get_streamfile_size(streamFile);
/* EOF reads: signal we have nothing and let the layout fail */
if (block_offset >= file_size) {
if (block_offset >= get_streamfile_size(streamFile)) {
vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset;
vgmstream->current_block_samples = -1;
return;
}
block_id = read_32bitBE(block_offset + 0x00, streamFile);
while (block_offset < file_size) {
uint32_t id = read_32bitBE(block_offset+0x00,streamFile);
/* BE in SAT, but one file may have both BE and LE chunks [FIFA 98 (SAT): movie LE, audio BE] */
if (guess_endianness32bit(block_offset + 0x04, streamFile))
block_size = read_32bitBE(block_offset + 0x04, streamFile);
else
block_size = read_32bitLE(block_offset + 0x04, streamFile);