2008-04-03 15:40:36 +02:00
|
|
|
#ifdef _MSC_VER
|
2008-04-03 15:56:50 +02:00
|
|
|
#define _CRT_SECURE_NO_DEPRECATE
|
2008-04-03 15:40:36 +02:00
|
|
|
#endif
|
|
|
|
|
2008-03-11 02:27:59 +01:00
|
|
|
#include <stdio.h>
|
2008-03-25 08:30:04 +01:00
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
2008-01-31 07:04:26 +01:00
|
|
|
#include "vgmstream.h"
|
2008-05-06 05:35:37 +02:00
|
|
|
#include "meta/meta.h"
|
|
|
|
#include "layout/layout.h"
|
|
|
|
#include "coding/coding.h"
|
2023-05-14 20:17:51 +02:00
|
|
|
#include "base/decode.h"
|
|
|
|
#include "base/render.h"
|
|
|
|
#include "base/mixing.h"
|
2023-06-25 22:02:34 +02:00
|
|
|
#include "util/sf_utils.h"
|
2008-05-04 22:36:40 +02:00
|
|
|
|
2023-05-15 16:14:29 +02:00
|
|
|
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*);
|
2017-04-22 13:31:12 +02:00
|
|
|
|
2023-05-15 16:14:29 +02:00
|
|
|
static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, init_vgmstream_t init_vgmstream_function);
|
2017-04-22 13:31:12 +02:00
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
/* list of metadata parser functions that will recognize files, used on init */
|
2023-05-15 16:14:29 +02:00
|
|
|
init_vgmstream_t init_vgmstream_functions[] = {
|
2008-06-09 02:20:08 +02:00
|
|
|
init_vgmstream_adx,
|
|
|
|
init_vgmstream_brstm,
|
2022-01-30 13:33:21 +01:00
|
|
|
init_vgmstream_brwav,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_bfwav,
|
2022-01-14 17:12:41 +01:00
|
|
|
init_vgmstream_bcwav,
|
2022-01-30 13:33:21 +01:00
|
|
|
init_vgmstream_brwar,
|
2008-06-09 02:20:08 +02:00
|
|
|
init_vgmstream_nds_strm,
|
|
|
|
init_vgmstream_afc,
|
|
|
|
init_vgmstream_ast,
|
|
|
|
init_vgmstream_halpst,
|
|
|
|
init_vgmstream_rs03,
|
|
|
|
init_vgmstream_ngc_dsp_std,
|
2018-03-29 23:28:02 +02:00
|
|
|
init_vgmstream_ngc_dsp_std_le,
|
2017-05-14 02:35:20 +02:00
|
|
|
init_vgmstream_ngc_mdsp_std,
|
2018-08-26 18:55:57 +02:00
|
|
|
init_vgmstream_csmp,
|
2018-08-26 19:16:24 +02:00
|
|
|
init_vgmstream_rfrm,
|
2017-11-25 00:43:18 +01:00
|
|
|
init_vgmstream_cstr,
|
2008-06-09 02:20:08 +02:00
|
|
|
init_vgmstream_gcsw,
|
2021-06-20 11:31:30 +02:00
|
|
|
init_vgmstream_ads,
|
2019-03-11 14:49:29 +01:00
|
|
|
init_vgmstream_nps,
|
2018-12-08 02:50:54 +01:00
|
|
|
init_vgmstream_xa,
|
2021-06-20 10:54:00 +02:00
|
|
|
init_vgmstream_rxws,
|
2017-08-28 17:47:19 +02:00
|
|
|
init_vgmstream_ngc_dsp_stm,
|
2021-04-10 19:44:38 +02:00
|
|
|
init_vgmstream_exst,
|
2020-07-16 21:47:50 +02:00
|
|
|
init_vgmstream_svag_kcet,
|
2008-06-09 02:20:08 +02:00
|
|
|
init_vgmstream_ngc_mpdsp,
|
|
|
|
init_vgmstream_ngc_dsp_std_int,
|
2018-08-21 22:16:56 +02:00
|
|
|
init_vgmstream_vag,
|
2019-11-01 08:29:37 +01:00
|
|
|
init_vgmstream_vag_aaap,
|
2021-12-11 17:35:27 +01:00
|
|
|
init_vgmstream_ild,
|
2008-06-09 02:20:08 +02:00
|
|
|
init_vgmstream_ngc_str,
|
2017-07-01 23:02:24 +02:00
|
|
|
init_vgmstream_ea_schl,
|
2008-06-09 02:20:08 +02:00
|
|
|
init_vgmstream_caf,
|
2020-04-05 13:09:05 +02:00
|
|
|
init_vgmstream_vpk,
|
2008-06-10 03:20:54 +02:00
|
|
|
init_vgmstream_genh,
|
2008-06-15 06:01:03 +02:00
|
|
|
init_vgmstream_ogg_vorbis,
|
2018-08-26 02:26:38 +02:00
|
|
|
init_vgmstream_sfl_ogg,
|
2008-06-15 11:23:34 +02:00
|
|
|
init_vgmstream_sadb,
|
2008-06-25 20:04:39 +02:00
|
|
|
init_vgmstream_ps2_bmdx,
|
2008-06-29 03:30:13 +02:00
|
|
|
init_vgmstream_wsi,
|
2008-07-01 05:23:44 +02:00
|
|
|
init_vgmstream_aifc,
|
2008-07-02 15:39:51 +02:00
|
|
|
init_vgmstream_str_snds,
|
2008-07-03 04:20:52 +02:00
|
|
|
init_vgmstream_ws_aud,
|
2008-07-05 13:49:29 +02:00
|
|
|
init_vgmstream_ahx,
|
2008-07-06 10:59:14 +02:00
|
|
|
init_vgmstream_ivb,
|
2008-07-06 14:23:37 +02:00
|
|
|
init_vgmstream_svs,
|
2008-07-06 20:05:04 +02:00
|
|
|
init_vgmstream_riff,
|
2009-05-25 22:59:50 +02:00
|
|
|
init_vgmstream_rifx,
|
2008-07-11 02:41:21 +02:00
|
|
|
init_vgmstream_nwa,
|
2017-11-18 02:20:52 +01:00
|
|
|
init_vgmstream_ea_1snh,
|
2019-01-02 17:17:14 +01:00
|
|
|
init_vgmstream_ea_eacs,
|
2008-07-12 17:20:39 +02:00
|
|
|
init_vgmstream_xss,
|
|
|
|
init_vgmstream_sl3,
|
|
|
|
init_vgmstream_hgc1,
|
|
|
|
init_vgmstream_aus,
|
|
|
|
init_vgmstream_rws,
|
2016-12-29 14:06:57 +01:00
|
|
|
init_vgmstream_fsb,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_fsb4_wav,
|
2014-04-24 06:31:04 +02:00
|
|
|
init_vgmstream_fsb5,
|
2023-06-24 16:15:39 +02:00
|
|
|
init_vgmstream_rwax,
|
2008-08-22 02:24:15 +02:00
|
|
|
init_vgmstream_xwb,
|
2017-06-24 23:33:49 +02:00
|
|
|
init_vgmstream_ps2_xa30,
|
2008-08-22 02:24:15 +02:00
|
|
|
init_vgmstream_musc,
|
2019-08-03 23:35:10 +02:00
|
|
|
init_vgmstream_musx,
|
2008-08-22 02:24:15 +02:00
|
|
|
init_vgmstream_filp,
|
2021-10-09 12:51:33 +02:00
|
|
|
init_vgmstream_ikm,
|
2021-12-06 13:20:36 +01:00
|
|
|
init_vgmstream_ster,
|
2008-08-22 02:24:15 +02:00
|
|
|
init_vgmstream_bg00,
|
2017-11-15 23:26:38 +01:00
|
|
|
init_vgmstream_sat_dvi,
|
|
|
|
init_vgmstream_dc_kcey,
|
2023-06-25 16:18:02 +02:00
|
|
|
init_vgmstream_rstm_rockstar,
|
2008-07-20 07:41:41 +02:00
|
|
|
init_vgmstream_acm,
|
2008-07-21 01:28:16 +02:00
|
|
|
init_vgmstream_mus_acm,
|
2008-08-22 02:24:15 +02:00
|
|
|
init_vgmstream_ps2_kces,
|
2022-08-14 12:36:58 +02:00
|
|
|
init_vgmstream_hxd,
|
2019-01-05 20:20:08 +01:00
|
|
|
init_vgmstream_vsv,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_ps2_pcm,
|
2008-08-22 02:24:15 +02:00
|
|
|
init_vgmstream_ps2_rkv,
|
|
|
|
init_vgmstream_ps2_vas,
|
2019-08-11 21:56:06 +02:00
|
|
|
init_vgmstream_ps2_vas_container,
|
2023-06-24 15:41:59 +02:00
|
|
|
init_vgmstream_lp_ap_lep,
|
2008-08-22 02:24:15 +02:00
|
|
|
init_vgmstream_sdt,
|
2008-08-02 12:24:28 +02:00
|
|
|
init_vgmstream_aix,
|
2021-06-24 22:38:28 +02:00
|
|
|
init_vgmstream_wvs_xbox,
|
|
|
|
init_vgmstream_wvs_ngc,
|
2023-09-02 12:27:06 +02:00
|
|
|
init_vgmstream_str_sega,
|
|
|
|
init_vgmstream_str_sega_custom,
|
2017-11-23 22:48:11 +01:00
|
|
|
init_vgmstream_dec,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_vs,
|
2019-09-02 22:32:02 +02:00
|
|
|
init_vgmstream_xmu,
|
|
|
|
init_vgmstream_xvas,
|
2008-08-22 02:24:15 +02:00
|
|
|
init_vgmstream_sat_sap,
|
|
|
|
init_vgmstream_dc_idvi,
|
|
|
|
init_vgmstream_ps2_rnd,
|
2018-08-12 18:04:19 +02:00
|
|
|
init_vgmstream_idsp_tt,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_kraw,
|
2023-06-25 16:22:29 +02:00
|
|
|
init_vgmstream_omu,
|
2023-06-25 01:59:21 +02:00
|
|
|
init_vgmstream_xa2_acclaim,
|
2018-08-12 18:04:19 +02:00
|
|
|
init_vgmstream_idsp_nl,
|
|
|
|
init_vgmstream_idsp_ie,
|
2023-06-24 17:56:09 +02:00
|
|
|
init_vgmstream_ymf,
|
2008-09-23 13:07:41 +02:00
|
|
|
init_vgmstream_sadl,
|
2018-12-08 02:45:19 +01:00
|
|
|
init_vgmstream_fag,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_ps2_mihb,
|
2018-03-31 20:42:02 +02:00
|
|
|
init_vgmstream_ngc_pdt_split,
|
2018-04-01 02:15:10 +02:00
|
|
|
init_vgmstream_ngc_pdt,
|
2023-07-23 15:30:36 +02:00
|
|
|
init_vgmstream_mus_krome,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_dc_asd,
|
2023-01-29 22:58:13 +01:00
|
|
|
init_vgmstream_spsd,
|
2019-08-10 17:24:06 +02:00
|
|
|
init_vgmstream_rsd,
|
2008-11-07 00:30:33 +01:00
|
|
|
init_vgmstream_bgw,
|
2008-11-07 02:47:39 +01:00
|
|
|
init_vgmstream_spw,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_ps2_ass,
|
2018-04-06 20:48:24 +02:00
|
|
|
init_vgmstream_ubi_jade,
|
|
|
|
init_vgmstream_ubi_jade_container,
|
2011-01-22 03:31:52 +01:00
|
|
|
init_vgmstream_seg,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_nds_strm_ffta2,
|
2021-11-18 00:21:29 +01:00
|
|
|
init_vgmstream_knon,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_gca,
|
|
|
|
init_vgmstream_spt_spd,
|
|
|
|
init_vgmstream_ish_isd,
|
2023-07-08 11:30:28 +02:00
|
|
|
init_vgmstream_gsnd,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_ydsp,
|
|
|
|
init_vgmstream_ngc_ssm,
|
|
|
|
init_vgmstream_ps2_joe,
|
|
|
|
init_vgmstream_vgs,
|
2019-03-04 20:08:33 +01:00
|
|
|
init_vgmstream_dcs_wav,
|
2018-12-22 19:47:17 +01:00
|
|
|
init_vgmstream_mul,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_thp,
|
2021-08-07 22:25:07 +02:00
|
|
|
init_vgmstream_sts,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_ps2_p2bt,
|
|
|
|
init_vgmstream_ps2_gbts,
|
2008-12-24 01:00:10 +01:00
|
|
|
init_vgmstream_wii_sng,
|
2010-09-16 13:53:36 +02:00
|
|
|
init_vgmstream_ngc_dsp_iadp,
|
2009-01-03 12:08:44 +01:00
|
|
|
init_vgmstream_aax,
|
2011-01-04 15:20:49 +01:00
|
|
|
init_vgmstream_utf_dsp,
|
2009-01-08 15:29:40 +01:00
|
|
|
init_vgmstream_ngc_ffcc_str,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_sat_baka,
|
2020-06-21 01:17:19 +02:00
|
|
|
init_vgmstream_swav,
|
2019-12-15 01:37:56 +01:00
|
|
|
init_vgmstream_vsf,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_nds_rrds,
|
|
|
|
init_vgmstream_ps2_vsf_tta,
|
2021-06-20 11:31:30 +02:00
|
|
|
init_vgmstream_ads_midway,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_ps2_mcg,
|
2009-03-13 00:42:56 +01:00
|
|
|
init_vgmstream_zsd,
|
2021-06-24 22:34:41 +02:00
|
|
|
init_vgmstream_vgs_ps,
|
2018-12-23 13:39:50 +01:00
|
|
|
init_vgmstream_redspark,
|
2009-03-26 00:25:30 +01:00
|
|
|
init_vgmstream_wii_wsd,
|
2020-12-19 16:53:15 +01:00
|
|
|
init_vgmstream_dsp_ndp,
|
2009-04-19 11:49:08 +02:00
|
|
|
init_vgmstream_ps2_sps,
|
|
|
|
init_vgmstream_nds_hwas,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_ngc_lps,
|
2009-05-01 17:03:51 +02:00
|
|
|
init_vgmstream_ps2_snd,
|
2009-05-10 09:14:29 +02:00
|
|
|
init_vgmstream_naomi_adpcm,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_sd9,
|
|
|
|
init_vgmstream_2dx9,
|
|
|
|
init_vgmstream_dsp_ygo,
|
2009-07-11 13:28:36 +02:00
|
|
|
init_vgmstream_ps2_vgv,
|
2021-04-10 23:07:41 +02:00
|
|
|
init_vgmstream_gcub,
|
2009-08-25 19:50:43 +02:00
|
|
|
init_vgmstream_maxis_xa,
|
|
|
|
init_vgmstream_ngc_sck_dsp,
|
2009-08-30 04:16:54 +02:00
|
|
|
init_vgmstream_apple_caff,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_pc_mxst,
|
|
|
|
init_vgmstream_sab,
|
2023-07-08 13:43:29 +02:00
|
|
|
init_vgmstream_bns,
|
2009-09-11 20:40:26 +02:00
|
|
|
init_vgmstream_wii_was,
|
2010-02-19 12:28:29 +01:00
|
|
|
init_vgmstream_pona_3do,
|
|
|
|
init_vgmstream_pona_psx,
|
2009-10-15 11:24:04 +02:00
|
|
|
init_vgmstream_xbox_hlwav,
|
2010-01-10 22:22:20 +01:00
|
|
|
init_vgmstream_myspd,
|
2010-01-19 20:40:41 +01:00
|
|
|
init_vgmstream_his,
|
2021-10-09 12:51:33 +02:00
|
|
|
init_vgmstream_ast_mmv,
|
|
|
|
init_vgmstream_ast_mv,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_dmsg,
|
2010-05-02 21:16:35 +02:00
|
|
|
init_vgmstream_ngc_dsp_aaap,
|
|
|
|
init_vgmstream_ngc_dsp_konami,
|
2023-07-08 10:52:28 +02:00
|
|
|
init_vgmstream_wb,
|
2010-03-23 21:57:12 +01:00
|
|
|
init_vgmstream_bnsf,
|
2010-03-29 22:06:08 +02:00
|
|
|
init_vgmstream_ps2_gcm,
|
2023-06-24 15:35:54 +02:00
|
|
|
init_vgmstream_smpl,
|
2023-06-30 23:09:48 +02:00
|
|
|
init_vgmstream_msa,
|
2023-06-25 00:59:10 +02:00
|
|
|
init_vgmstream_voi,
|
2018-03-25 11:08:36 +02:00
|
|
|
init_vgmstream_ngc_rkv,
|
2010-04-20 22:26:10 +02:00
|
|
|
init_vgmstream_dsp_ddsp,
|
2010-04-10 14:06:25 +02:00
|
|
|
init_vgmstream_p3d,
|
2010-04-20 22:26:10 +02:00
|
|
|
init_vgmstream_ngc_dsp_mpds,
|
|
|
|
init_vgmstream_dsp_str_ig,
|
2018-02-17 21:15:21 +01:00
|
|
|
init_vgmstream_ea_swvr,
|
2010-05-02 21:16:35 +02:00
|
|
|
init_vgmstream_ps2_b1s,
|
|
|
|
init_vgmstream_dsp_xiii,
|
|
|
|
init_vgmstream_dsp_cabelas,
|
2021-10-09 12:51:33 +02:00
|
|
|
init_vgmstream_lpcm_shade,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_ps2_vms,
|
|
|
|
init_vgmstream_xau,
|
2017-12-06 15:32:52 +01:00
|
|
|
init_vgmstream_bar,
|
2010-07-27 21:45:59 +02:00
|
|
|
init_vgmstream_ffw,
|
2010-08-04 11:12:08 +02:00
|
|
|
init_vgmstream_dsp_dspw,
|
2019-07-28 15:11:17 +02:00
|
|
|
init_vgmstream_jstm,
|
2017-09-29 23:37:20 +02:00
|
|
|
init_vgmstream_xvag,
|
2023-01-21 20:36:19 +01:00
|
|
|
init_vgmstream_cps,
|
2011-02-08 13:56:16 +01:00
|
|
|
init_vgmstream_sqex_scd,
|
2010-09-11 19:53:33 +02:00
|
|
|
init_vgmstream_ngc_nst_dsp,
|
2010-09-11 22:57:39 +02:00
|
|
|
init_vgmstream_baf,
|
2019-03-11 14:49:29 +01:00
|
|
|
init_vgmstream_msf,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_ps3_past,
|
2017-03-18 15:07:58 +01:00
|
|
|
init_vgmstream_sgxd,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_wii_ras,
|
2021-06-24 22:32:44 +02:00
|
|
|
init_vgmstream_spm,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_ps2_iab,
|
2018-12-22 20:09:01 +01:00
|
|
|
init_vgmstream_vs_str,
|
2011-01-13 09:11:58 +01:00
|
|
|
init_vgmstream_lsf_n1nj4n,
|
2020-09-25 16:52:12 +02:00
|
|
|
init_vgmstream_xwav_new,
|
|
|
|
init_vgmstream_xwav_old,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_hyperscan_kvag,
|
|
|
|
init_vgmstream_ios_psnd,
|
2023-06-24 17:01:40 +02:00
|
|
|
init_vgmstream_adp_wildfire,
|
2021-08-07 20:56:31 +02:00
|
|
|
init_vgmstream_adp_qd,
|
2011-03-03 10:03:18 +01:00
|
|
|
init_vgmstream_eb_sfx,
|
|
|
|
init_vgmstream_eb_sf0,
|
2019-03-11 11:58:57 +01:00
|
|
|
init_vgmstream_mtaf,
|
2022-05-15 12:23:01 +02:00
|
|
|
init_vgmstream_alp,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_wpd,
|
|
|
|
init_vgmstream_mn_str,
|
|
|
|
init_vgmstream_mss,
|
|
|
|
init_vgmstream_ps2_hsf,
|
2019-11-24 20:38:16 +01:00
|
|
|
init_vgmstream_ivag,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_ps2_2pfs,
|
2017-12-26 18:17:59 +01:00
|
|
|
init_vgmstream_xnb,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_ubi_ckd,
|
|
|
|
init_vgmstream_ps2_vbk,
|
|
|
|
init_vgmstream_otm,
|
|
|
|
init_vgmstream_bcstm,
|
2019-11-24 10:47:54 +01:00
|
|
|
init_vgmstream_idsp_namco,
|
2017-01-18 21:28:14 +01:00
|
|
|
init_vgmstream_kt_g1l,
|
|
|
|
init_vgmstream_kt_wiibgm,
|
2021-09-19 23:54:38 +02:00
|
|
|
init_vgmstream_bfstm,
|
|
|
|
init_vgmstream_mca,
|
|
|
|
#if 0
|
|
|
|
init_vgmstream_mp4_aac,
|
|
|
|
#endif
|
|
|
|
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
|
|
|
init_vgmstream_akb_mp4,
|
|
|
|
#endif
|
2017-12-27 06:14:50 +01:00
|
|
|
init_vgmstream_ktss,
|
2016-06-28 09:20:37 +02:00
|
|
|
init_vgmstream_hca,
|
2020-07-16 22:07:20 +02:00
|
|
|
init_vgmstream_svag_snk,
|
2017-01-08 12:59:04 +01:00
|
|
|
init_vgmstream_ps2_vds_vdm,
|
2023-01-20 16:32:32 +01:00
|
|
|
init_vgmstream_cxs,
|
2023-06-24 17:56:09 +02:00
|
|
|
init_vgmstream_adx_monster,
|
2018-03-24 14:22:37 +01:00
|
|
|
init_vgmstream_akb,
|
|
|
|
init_vgmstream_akb2,
|
2017-07-15 11:49:28 +02:00
|
|
|
#ifdef VGM_USE_FFMPEG
|
|
|
|
init_vgmstream_mp4_aac_ffmpeg,
|
|
|
|
#endif
|
2017-08-18 19:24:19 +02:00
|
|
|
init_vgmstream_bik,
|
2023-01-20 16:32:32 +01:00
|
|
|
init_vgmstream_astb,
|
2017-04-02 12:27:21 +02:00
|
|
|
init_vgmstream_wwise,
|
2017-04-07 18:01:04 +02:00
|
|
|
init_vgmstream_ubi_raki,
|
2023-01-20 16:32:32 +01:00
|
|
|
init_vgmstream_pasx,
|
2017-04-22 13:12:01 +02:00
|
|
|
init_vgmstream_xma,
|
2023-07-23 11:06:14 +02:00
|
|
|
init_vgmstream_sndx,
|
2017-04-22 19:25:54 +02:00
|
|
|
init_vgmstream_ogl,
|
2017-04-28 17:26:25 +02:00
|
|
|
init_vgmstream_mc3,
|
2023-01-23 00:50:19 +01:00
|
|
|
init_vgmstream_ghs,
|
2023-01-21 20:36:19 +01:00
|
|
|
init_vgmstream_aac_triace,
|
2018-10-10 00:48:24 +02:00
|
|
|
init_vgmstream_va3,
|
2019-03-11 11:58:57 +01:00
|
|
|
init_vgmstream_mta2,
|
|
|
|
init_vgmstream_mta2_container,
|
2019-07-28 15:11:17 +02:00
|
|
|
init_vgmstream_xa_xa30,
|
|
|
|
init_vgmstream_xa_04sw,
|
2017-07-23 03:46:55 +02:00
|
|
|
init_vgmstream_ea_bnk,
|
2018-07-17 23:14:28 +02:00
|
|
|
init_vgmstream_ea_abk,
|
2018-07-21 20:57:35 +02:00
|
|
|
init_vgmstream_ea_hdr_dat,
|
2019-08-05 20:45:54 +02:00
|
|
|
init_vgmstream_ea_hdr_dat_v2,
|
2018-12-27 18:27:03 +01:00
|
|
|
init_vgmstream_ea_map_mus,
|
2018-12-27 18:01:36 +01:00
|
|
|
init_vgmstream_ea_mpf_mus,
|
2017-07-23 17:09:55 +02:00
|
|
|
init_vgmstream_ea_schl_fixed,
|
2017-07-29 11:46:53 +02:00
|
|
|
init_vgmstream_sk_aud,
|
2023-06-30 23:22:36 +02:00
|
|
|
init_vgmstream_stma,
|
2017-08-20 02:18:48 +02:00
|
|
|
init_vgmstream_ea_snu,
|
2017-08-28 15:14:24 +02:00
|
|
|
init_vgmstream_awc,
|
2018-04-21 21:52:30 +02:00
|
|
|
init_vgmstream_opus_std,
|
|
|
|
init_vgmstream_opus_n1,
|
|
|
|
init_vgmstream_opus_capcom,
|
|
|
|
init_vgmstream_opus_nop,
|
2018-05-05 23:01:49 +02:00
|
|
|
init_vgmstream_opus_shinen,
|
2018-07-15 08:37:15 +02:00
|
|
|
init_vgmstream_opus_nus3,
|
2018-10-07 23:59:42 +02:00
|
|
|
init_vgmstream_opus_sps_n1,
|
2018-08-01 07:24:26 +02:00
|
|
|
init_vgmstream_opus_nxa,
|
2017-11-05 17:06:40 +01:00
|
|
|
init_vgmstream_pc_ast,
|
2017-11-23 22:32:31 +01:00
|
|
|
init_vgmstream_naac,
|
2017-11-05 17:06:40 +01:00
|
|
|
init_vgmstream_ubi_sb,
|
2018-12-22 22:47:24 +01:00
|
|
|
init_vgmstream_ubi_sm,
|
2019-03-17 19:30:02 +01:00
|
|
|
init_vgmstream_ubi_bnm,
|
2020-05-31 20:33:42 +02:00
|
|
|
init_vgmstream_ubi_bnm_ps2,
|
2020-05-30 17:03:41 +02:00
|
|
|
init_vgmstream_ubi_dat,
|
2020-05-22 18:22:23 +02:00
|
|
|
init_vgmstream_ubi_blk,
|
2017-11-27 20:22:10 +01:00
|
|
|
init_vgmstream_ezw,
|
|
|
|
init_vgmstream_vxn,
|
2017-12-01 17:27:49 +01:00
|
|
|
init_vgmstream_ea_snr_sns,
|
|
|
|
init_vgmstream_ea_sps,
|
2019-01-13 03:15:18 +01:00
|
|
|
init_vgmstream_ea_abk_eaac,
|
2018-07-21 20:58:01 +02:00
|
|
|
init_vgmstream_ea_hdr_sth_dat,
|
2019-01-13 03:15:18 +01:00
|
|
|
init_vgmstream_ea_mpf_mus_eaac,
|
2019-02-11 10:37:11 +01:00
|
|
|
init_vgmstream_ea_tmx,
|
2019-01-13 00:42:54 +01:00
|
|
|
init_vgmstream_ea_sbr,
|
2019-01-13 19:53:57 +01:00
|
|
|
init_vgmstream_ea_sbr_harmony,
|
2023-06-24 15:58:29 +02:00
|
|
|
init_vgmstream_vid1,
|
2017-12-03 01:41:25 +01:00
|
|
|
init_vgmstream_flx,
|
2018-01-04 23:38:22 +01:00
|
|
|
init_vgmstream_mogg,
|
2018-01-13 17:47:40 +01:00
|
|
|
init_vgmstream_kma9,
|
2018-01-27 11:00:21 +01:00
|
|
|
init_vgmstream_xwc,
|
2018-03-03 02:03:53 +01:00
|
|
|
init_vgmstream_atsl,
|
2018-01-27 12:21:25 +01:00
|
|
|
init_vgmstream_sps_n1,
|
2018-01-27 14:00:31 +01:00
|
|
|
init_vgmstream_atx,
|
2018-01-27 22:34:48 +01:00
|
|
|
init_vgmstream_sqex_sead,
|
2018-03-03 18:46:12 +01:00
|
|
|
init_vgmstream_waf,
|
2018-03-11 19:24:06 +01:00
|
|
|
init_vgmstream_wave,
|
|
|
|
init_vgmstream_wave_segmented,
|
2018-03-23 22:41:42 +01:00
|
|
|
init_vgmstream_smv,
|
2018-03-25 19:59:58 +02:00
|
|
|
init_vgmstream_nxap,
|
2018-03-29 15:39:33 +02:00
|
|
|
init_vgmstream_ea_wve_au00,
|
|
|
|
init_vgmstream_ea_wve_ad10,
|
2018-03-29 17:01:46 +02:00
|
|
|
init_vgmstream_sthd,
|
2018-03-31 13:10:57 +02:00
|
|
|
init_vgmstream_pcm_sre,
|
2018-03-31 13:28:30 +02:00
|
|
|
init_vgmstream_dsp_mcadpcm,
|
2018-04-07 11:31:43 +02:00
|
|
|
init_vgmstream_ubi_lyn,
|
|
|
|
init_vgmstream_ubi_lyn_container,
|
2018-04-07 13:35:33 +02:00
|
|
|
init_vgmstream_msb_msh,
|
2018-04-15 00:48:37 +02:00
|
|
|
init_vgmstream_txtp,
|
2018-04-15 01:08:27 +02:00
|
|
|
init_vgmstream_smc_smh,
|
2018-04-20 18:27:08 +02:00
|
|
|
init_vgmstream_ppst,
|
2020-10-01 21:22:34 +02:00
|
|
|
init_vgmstream_sps_n1_segmented,
|
2018-04-29 20:28:27 +02:00
|
|
|
init_vgmstream_ubi_bao_pk,
|
2019-02-03 01:47:59 +01:00
|
|
|
init_vgmstream_ubi_bao_atomic,
|
2018-04-29 21:04:55 +02:00
|
|
|
init_vgmstream_dsp_switch_audio,
|
2018-08-28 18:47:56 +02:00
|
|
|
init_vgmstream_sadf,
|
2018-06-03 13:08:41 +02:00
|
|
|
init_vgmstream_h4m,
|
2021-06-20 11:31:30 +02:00
|
|
|
init_vgmstream_ads_container,
|
2018-07-18 00:52:24 +02:00
|
|
|
init_vgmstream_asf,
|
2018-07-27 17:11:11 +02:00
|
|
|
init_vgmstream_xmd,
|
2018-08-02 17:15:09 +02:00
|
|
|
init_vgmstream_cks,
|
|
|
|
init_vgmstream_ckb,
|
2018-08-02 18:22:01 +02:00
|
|
|
init_vgmstream_wv6,
|
2018-08-04 21:02:10 +02:00
|
|
|
init_vgmstream_str_wav,
|
2018-08-13 23:03:39 +02:00
|
|
|
init_vgmstream_wavebatch,
|
2018-08-14 00:28:15 +02:00
|
|
|
init_vgmstream_hd3_bd3,
|
2018-08-15 17:34:17 +02:00
|
|
|
init_vgmstream_bnk_sony,
|
2018-08-15 19:59:10 +02:00
|
|
|
init_vgmstream_nus3bank,
|
2022-10-29 17:59:29 +02:00
|
|
|
init_vgmstream_sscf,
|
2018-10-07 23:59:42 +02:00
|
|
|
init_vgmstream_dsp_sps_n1,
|
2018-08-28 18:47:56 +02:00
|
|
|
init_vgmstream_dsp_itl_ch,
|
|
|
|
init_vgmstream_a2m,
|
|
|
|
init_vgmstream_ahv,
|
|
|
|
init_vgmstream_msv,
|
2019-01-26 17:04:43 +01:00
|
|
|
init_vgmstream_sdf,
|
2018-08-28 18:47:56 +02:00
|
|
|
init_vgmstream_svg,
|
|
|
|
init_vgmstream_vis,
|
|
|
|
init_vgmstream_vai,
|
|
|
|
init_vgmstream_aif_asobo,
|
|
|
|
init_vgmstream_ao,
|
|
|
|
init_vgmstream_apc,
|
|
|
|
init_vgmstream_wv2,
|
|
|
|
init_vgmstream_xau_konami,
|
2018-09-06 17:45:34 +02:00
|
|
|
init_vgmstream_derf,
|
2018-09-09 15:29:34 +02:00
|
|
|
init_vgmstream_utk,
|
2018-09-22 17:45:02 +02:00
|
|
|
init_vgmstream_adpcm_capcom,
|
2018-09-23 04:26:11 +02:00
|
|
|
init_vgmstream_ue4opus,
|
2018-10-07 23:27:31 +02:00
|
|
|
init_vgmstream_xwma,
|
2018-10-13 21:01:58 +02:00
|
|
|
init_vgmstream_xopus,
|
2018-12-22 20:09:01 +01:00
|
|
|
init_vgmstream_vs_square,
|
2018-10-27 23:10:03 +02:00
|
|
|
init_vgmstream_msf_banpresto_wmsf,
|
|
|
|
init_vgmstream_msf_banpresto_2msf,
|
2018-11-09 21:23:31 +01:00
|
|
|
init_vgmstream_nwav,
|
2018-11-09 22:57:35 +01:00
|
|
|
init_vgmstream_xpcm,
|
2018-11-17 17:52:07 +01:00
|
|
|
init_vgmstream_msf_tamasoft,
|
2018-12-01 14:01:52 +01:00
|
|
|
init_vgmstream_xps_dat,
|
|
|
|
init_vgmstream_xps,
|
2018-12-08 00:10:44 +01:00
|
|
|
init_vgmstream_zsnd,
|
2018-12-09 01:23:40 +01:00
|
|
|
init_vgmstream_opus_opusx,
|
2019-08-03 12:22:09 +02:00
|
|
|
init_vgmstream_dsp_adpy,
|
|
|
|
init_vgmstream_dsp_adpx,
|
2018-12-09 02:00:47 +01:00
|
|
|
init_vgmstream_ogg_opus,
|
2018-12-15 12:37:01 +01:00
|
|
|
init_vgmstream_nus3audio,
|
2018-12-23 13:38:18 +01:00
|
|
|
init_vgmstream_imc,
|
|
|
|
init_vgmstream_imc_container,
|
2019-01-05 04:36:20 +01:00
|
|
|
init_vgmstream_smp,
|
2019-01-12 02:26:38 +01:00
|
|
|
init_vgmstream_gin,
|
2019-02-10 01:36:05 +01:00
|
|
|
init_vgmstream_dsf,
|
|
|
|
init_vgmstream_208,
|
2019-02-17 23:17:14 +01:00
|
|
|
init_vgmstream_dsp_ds2,
|
2019-02-23 23:10:58 +01:00
|
|
|
init_vgmstream_ffdl,
|
2019-02-24 11:34:09 +01:00
|
|
|
init_vgmstream_mus_vc,
|
2019-03-09 23:27:28 +01:00
|
|
|
init_vgmstream_strm_abylight,
|
2019-03-10 00:59:59 +01:00
|
|
|
init_vgmstream_sfh,
|
2019-03-10 11:11:27 +01:00
|
|
|
init_vgmstream_ea_schl_video,
|
2019-03-12 00:41:20 +01:00
|
|
|
init_vgmstream_msf_konami,
|
|
|
|
init_vgmstream_xwma_konami,
|
2019-03-16 00:10:28 +01:00
|
|
|
init_vgmstream_9tav,
|
2019-05-26 22:55:37 +02:00
|
|
|
init_vgmstream_fsb5_fev_bank,
|
2019-06-26 08:26:44 +02:00
|
|
|
init_vgmstream_bwav,
|
2019-07-07 04:30:11 +02:00
|
|
|
init_vgmstream_opus_prototype,
|
2019-07-07 20:46:14 +02:00
|
|
|
init_vgmstream_awb,
|
2019-07-14 21:24:28 +02:00
|
|
|
init_vgmstream_acb,
|
2019-07-12 12:14:39 +02:00
|
|
|
init_vgmstream_rad,
|
2019-07-21 15:08:39 +02:00
|
|
|
init_vgmstream_smk,
|
2021-01-25 21:12:27 +01:00
|
|
|
init_vgmstream_mzrt_v0,
|
2019-08-04 11:57:48 +02:00
|
|
|
init_vgmstream_xavs,
|
2019-08-11 19:38:40 +02:00
|
|
|
init_vgmstream_psf_single,
|
|
|
|
init_vgmstream_psf_segmented,
|
2019-08-12 20:05:58 +02:00
|
|
|
init_vgmstream_dsp_itl,
|
2019-08-15 15:12:13 +02:00
|
|
|
init_vgmstream_sch,
|
2019-08-15 16:25:52 +02:00
|
|
|
init_vgmstream_ima,
|
2019-08-28 23:11:46 +02:00
|
|
|
init_vgmstream_nub,
|
|
|
|
init_vgmstream_nub_wav,
|
|
|
|
init_vgmstream_nub_vag,
|
|
|
|
init_vgmstream_nub_at3,
|
|
|
|
init_vgmstream_nub_xma,
|
|
|
|
init_vgmstream_nub_idsp,
|
|
|
|
init_vgmstream_nub_is14,
|
2023-01-21 20:36:19 +01:00
|
|
|
init_vgmstream_xwv_valve,
|
2019-09-08 20:24:47 +02:00
|
|
|
init_vgmstream_ubi_hx,
|
2019-09-08 21:12:13 +02:00
|
|
|
init_vgmstream_bmp_konami,
|
2019-09-24 00:53:52 +02:00
|
|
|
init_vgmstream_opus_opusnx,
|
2019-10-03 17:46:37 +02:00
|
|
|
init_vgmstream_opus_sqex,
|
2019-11-03 22:56:37 +01:00
|
|
|
init_vgmstream_isb,
|
2019-11-10 22:17:21 +01:00
|
|
|
init_vgmstream_xssb,
|
2019-12-15 18:21:31 +01:00
|
|
|
init_vgmstream_xma_ue3,
|
2019-12-15 22:24:54 +01:00
|
|
|
init_vgmstream_csb,
|
2020-01-07 18:44:17 +01:00
|
|
|
init_vgmstream_fwse,
|
2019-12-27 01:33:37 +01:00
|
|
|
init_vgmstream_fda,
|
2020-01-24 20:10:29 +01:00
|
|
|
init_vgmstream_kwb,
|
2020-02-03 00:23:07 +01:00
|
|
|
init_vgmstream_lrmd,
|
2020-03-07 14:40:13 +01:00
|
|
|
init_vgmstream_bkhd,
|
2020-04-04 18:37:53 +02:00
|
|
|
init_vgmstream_bkhd_fx,
|
2020-04-15 05:42:55 +02:00
|
|
|
init_vgmstream_diva,
|
2020-05-01 09:15:01 +02:00
|
|
|
init_vgmstream_imuse,
|
2020-05-23 23:12:45 +02:00
|
|
|
init_vgmstream_ktsr,
|
2020-05-24 15:50:41 +02:00
|
|
|
init_vgmstream_mups,
|
2020-05-29 18:28:32 +02:00
|
|
|
init_vgmstream_kat,
|
2020-06-06 16:15:06 +02:00
|
|
|
init_vgmstream_pcm_success,
|
2020-07-11 21:25:12 +02:00
|
|
|
init_vgmstream_ktsc,
|
2020-07-16 22:51:58 +02:00
|
|
|
init_vgmstream_adp_konami,
|
2020-08-01 15:28:12 +02:00
|
|
|
init_vgmstream_zwv,
|
2020-08-01 16:04:41 +02:00
|
|
|
init_vgmstream_dsb,
|
2020-08-01 17:04:55 +02:00
|
|
|
init_vgmstream_bsf,
|
2023-01-21 20:36:19 +01:00
|
|
|
init_vgmstream_sdrh_new,
|
|
|
|
init_vgmstream_sdrh_old,
|
2020-10-11 00:01:11 +02:00
|
|
|
init_vgmstream_wady,
|
2020-10-11 01:10:02 +02:00
|
|
|
init_vgmstream_dsp_sqex,
|
2020-11-09 20:40:24 +01:00
|
|
|
init_vgmstream_dsp_wiivoice,
|
2020-11-09 22:22:00 +01:00
|
|
|
init_vgmstream_xws,
|
2020-11-15 00:11:48 +01:00
|
|
|
init_vgmstream_cpk,
|
2020-11-15 00:20:44 +01:00
|
|
|
init_vgmstream_opus_nsopus,
|
2020-12-09 17:29:09 +01:00
|
|
|
init_vgmstream_sbk,
|
2020-12-19 14:52:04 +01:00
|
|
|
init_vgmstream_dsp_wiiadpcm,
|
2020-12-19 16:53:15 +01:00
|
|
|
init_vgmstream_dsp_cwac,
|
2020-12-20 15:07:23 +01:00
|
|
|
init_vgmstream_ifs,
|
2021-01-03 19:22:32 +01:00
|
|
|
init_vgmstream_acx,
|
2021-01-23 15:50:32 +01:00
|
|
|
init_vgmstream_compresswave,
|
2021-01-24 20:17:07 +01:00
|
|
|
init_vgmstream_ktac,
|
2021-01-25 21:12:27 +01:00
|
|
|
init_vgmstream_mzrt_v1,
|
|
|
|
init_vgmstream_bsnf,
|
2021-02-16 23:14:07 +01:00
|
|
|
init_vgmstream_tac,
|
2021-04-03 16:53:27 +02:00
|
|
|
init_vgmstream_idsp_tose,
|
2021-04-03 17:43:37 +02:00
|
|
|
init_vgmstream_dsp_kwa,
|
2021-04-10 22:47:11 +02:00
|
|
|
init_vgmstream_ogv_3rdeye,
|
2021-07-09 00:06:27 +02:00
|
|
|
init_vgmstream_sspr,
|
2021-07-23 22:30:57 +02:00
|
|
|
init_vgmstream_piff_tpcm,
|
2021-08-07 12:32:42 +02:00
|
|
|
init_vgmstream_wxd_wxh,
|
|
|
|
init_vgmstream_bnk_relic,
|
2021-08-22 13:13:38 +02:00
|
|
|
init_vgmstream_xsh_xsd_xss,
|
2021-09-11 16:12:35 +02:00
|
|
|
init_vgmstream_psb,
|
2021-10-03 13:48:22 +02:00
|
|
|
init_vgmstream_lopu_fb,
|
|
|
|
init_vgmstream_lpcm_fb,
|
2021-11-18 12:08:40 +01:00
|
|
|
init_vgmstream_wbk,
|
2021-12-07 05:34:03 +01:00
|
|
|
init_vgmstream_wbk_nslb,
|
2021-11-28 14:01:22 +01:00
|
|
|
init_vgmstream_dsp_apex,
|
2021-12-31 16:20:52 +01:00
|
|
|
init_vgmstream_ubi_ckd_cwav,
|
2022-04-09 14:57:49 +02:00
|
|
|
init_vgmstream_sspf,
|
2022-04-09 15:15:43 +02:00
|
|
|
init_vgmstream_opus_rsnd,
|
2022-04-21 05:05:37 +02:00
|
|
|
init_vgmstream_s3v,
|
2022-04-29 21:33:43 +02:00
|
|
|
init_vgmstream_esf,
|
2022-05-01 12:17:57 +02:00
|
|
|
init_vgmstream_adm3,
|
2022-05-01 18:10:22 +02:00
|
|
|
init_vgmstream_tt_ad,
|
2022-05-13 19:04:26 +02:00
|
|
|
init_vgmstream_bw_mp3_riff,
|
|
|
|
init_vgmstream_bw_riff_mp3,
|
2022-06-26 17:05:31 +02:00
|
|
|
init_vgmstream_sndz,
|
2022-08-04 10:02:38 +02:00
|
|
|
init_vgmstream_vab,
|
2022-09-23 22:53:45 +02:00
|
|
|
init_vgmstream_bigrp,
|
2022-10-29 17:52:41 +02:00
|
|
|
init_vgmstream_sscf_encrypted,
|
2023-01-23 00:50:19 +01:00
|
|
|
init_vgmstream_s_p_sth,
|
2023-03-12 14:53:29 +01:00
|
|
|
init_vgmstream_utf_ahx,
|
2023-06-11 19:41:06 +02:00
|
|
|
init_vgmstream_ego_dic,
|
2023-06-24 15:06:01 +02:00
|
|
|
init_vgmstream_awd,
|
2023-06-28 13:20:47 +02:00
|
|
|
init_vgmstream_rws_809,
|
2023-06-25 16:07:16 +02:00
|
|
|
init_vgmstream_pwb,
|
2023-07-09 23:22:36 +02:00
|
|
|
init_vgmstream_squeakstream,
|
|
|
|
init_vgmstream_squeaksample,
|
2023-07-23 13:43:10 +02:00
|
|
|
init_vgmstream_snds,
|
2023-08-19 23:28:05 +02:00
|
|
|
init_vgmstream_adm2,
|
2023-09-28 20:25:03 +02:00
|
|
|
init_vgmstream_nxof,
|
2018-08-28 18:47:56 +02:00
|
|
|
|
2021-12-11 17:35:27 +01:00
|
|
|
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
|
2022-10-22 15:14:57 +02:00
|
|
|
init_vgmstream_scd_pcm,
|
2021-12-11 17:35:27 +01:00
|
|
|
init_vgmstream_agsc,
|
|
|
|
init_vgmstream_ps2_wmus,
|
|
|
|
init_vgmstream_mib_mih,
|
2022-01-22 22:56:35 +01:00
|
|
|
init_vgmstream_mjb_mjh,
|
2021-12-11 17:35:27 +01:00
|
|
|
init_vgmstream_mic_koei,
|
|
|
|
init_vgmstream_seb,
|
2022-05-01 18:57:22 +02:00
|
|
|
init_vgmstream_tgc,
|
2023-07-23 11:03:29 +02:00
|
|
|
init_vgmstream_ivaud,
|
2023-06-25 23:33:00 +02:00
|
|
|
/* need companion files */
|
|
|
|
init_vgmstream_pos,
|
|
|
|
init_vgmstream_sli_loops,
|
2021-12-11 17:35:27 +01:00
|
|
|
|
2018-08-28 18:47:56 +02:00
|
|
|
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
|
2018-08-22 20:39:31 +02:00
|
|
|
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
|
2022-12-31 17:05:43 +01:00
|
|
|
init_vgmstream_dtk, /* semi-raw GC streamed files */
|
2022-06-19 19:36:57 +02:00
|
|
|
init_vgmstream_mpeg, /* semi-raw MP3 */
|
2021-08-26 18:48:19 +02:00
|
|
|
init_vgmstream_btsnd, /* semi-headerless */
|
2023-06-25 23:33:00 +02:00
|
|
|
init_vgmstream_fsb_encrypted,
|
|
|
|
init_vgmstream_nus3bank_encrypted,
|
2022-12-31 17:05:43 +01:00
|
|
|
init_vgmstream_encrypted, /* encrypted stuff */
|
2023-06-24 16:40:17 +02:00
|
|
|
init_vgmstream_raw_rsf, /* raw GC streamed files */
|
2019-09-02 22:32:02 +02:00
|
|
|
init_vgmstream_raw_int, /* .int raw PCM */
|
2018-08-22 20:39:31 +02:00
|
|
|
init_vgmstream_ps_headerless, /* tries to detect a bunch of PS-ADPCM formats */
|
2021-12-11 17:37:38 +01:00
|
|
|
init_vgmstream_raw_snds, /* .snds raw SNDS IMA */
|
2019-09-02 22:32:02 +02:00
|
|
|
init_vgmstream_raw_wavm, /* .wavm raw xbox */
|
|
|
|
init_vgmstream_raw_pcm, /* .raw raw PCM */
|
2023-06-24 16:36:54 +02:00
|
|
|
init_vgmstream_raw_s14_sss, /* .s14/sss raw siren14 */
|
2021-11-18 00:17:40 +01:00
|
|
|
init_vgmstream_exakt_sc, /* .sc raw PCM */
|
2020-10-12 23:31:07 +02:00
|
|
|
init_vgmstream_zwdsp, /* fake format */
|
2021-11-18 00:17:40 +01:00
|
|
|
init_vgmstream_ps2_adm, /* weird non-constant PSX blocks */
|
2022-12-31 17:05:43 +01:00
|
|
|
init_vgmstream_rwsd, /* crap, to be removed */
|
2016-07-17 08:02:27 +02:00
|
|
|
#ifdef VGM_USE_FFMPEG
|
2018-08-22 20:39:31 +02:00
|
|
|
init_vgmstream_ffmpeg, /* may play anything incorrectly, since FFmpeg doesn't check extensions */
|
2016-07-17 08:02:27 +02:00
|
|
|
#endif
|
2008-01-31 07:04:26 +01:00
|
|
|
};
|
|
|
|
|
2023-05-15 16:14:29 +02:00
|
|
|
#define LOCAL_ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
|
|
|
|
static const int init_vgmstream_count = LOCAL_ARRAY_LENGTH(init_vgmstream_functions);
|
2008-06-09 02:20:08 +02:00
|
|
|
|
2020-07-18 00:12:44 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* INIT/META */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
2008-03-25 08:30:04 +01:00
|
|
|
/* internal version with all parameters */
|
2020-07-17 22:35:32 +02:00
|
|
|
static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) {
|
|
|
|
if (!sf)
|
2008-05-20 17:18:38 +02:00
|
|
|
return NULL;
|
2008-01-31 07:04:26 +01:00
|
|
|
|
|
|
|
/* try a series of formats, see which works */
|
2023-05-15 16:14:29 +02:00
|
|
|
for (int i = 0; i < init_vgmstream_count; i++) {
|
|
|
|
init_vgmstream_t init_vgmstream_function = init_vgmstream_functions[i];
|
|
|
|
|
|
|
|
|
2017-01-08 01:09:20 +01:00
|
|
|
/* call init function and see if valid VGMSTREAM was returned */
|
2023-05-15 16:14:29 +02:00
|
|
|
VGMSTREAM* vgmstream = init_vgmstream_function(sf);
|
2017-11-24 20:15:23 +01:00
|
|
|
if (!vgmstream)
|
|
|
|
continue;
|
|
|
|
|
2019-12-05 23:20:16 +01:00
|
|
|
/* fail if there is nothing/too much to play (<=0 generates empty files, >N writes GBs of garbage) */
|
|
|
|
if (vgmstream->num_samples <= 0 || vgmstream->num_samples > VGMSTREAM_MAX_NUM_SAMPLES) {
|
2019-03-02 19:23:37 +01:00
|
|
|
VGM_LOG("VGMSTREAM: wrong num_samples %i\n", vgmstream->num_samples);
|
2017-11-25 00:43:18 +01:00
|
|
|
close_vgmstream(vgmstream);
|
|
|
|
continue;
|
|
|
|
}
|
2016-11-11 23:36:12 +01:00
|
|
|
|
2019-03-02 19:23:37 +01:00
|
|
|
/* everything should have a reasonable sample rate */
|
|
|
|
if (vgmstream->sample_rate < VGMSTREAM_MIN_SAMPLE_RATE || vgmstream->sample_rate > VGMSTREAM_MAX_SAMPLE_RATE) {
|
|
|
|
VGM_LOG("VGMSTREAM: wrong sample_rate %i\n", vgmstream->sample_rate);
|
2017-11-25 00:43:18 +01:00
|
|
|
close_vgmstream(vgmstream);
|
|
|
|
continue;
|
|
|
|
}
|
2019-02-15 23:46:21 +01:00
|
|
|
|
|
|
|
/* sanify loops and remove bad metadata */
|
2017-11-25 00:43:18 +01:00
|
|
|
if (vgmstream->loop_flag) {
|
2019-02-15 22:28:20 +01:00
|
|
|
if (vgmstream->loop_end_sample <= vgmstream->loop_start_sample
|
|
|
|
|| vgmstream->loop_end_sample > vgmstream->num_samples
|
|
|
|
|| vgmstream->loop_start_sample < 0) {
|
|
|
|
VGM_LOG("VGMSTREAM: wrong loops ignored (lss=%i, lse=%i, ns=%i)\n",
|
|
|
|
vgmstream->loop_start_sample, vgmstream->loop_end_sample, vgmstream->num_samples);
|
2019-02-15 23:46:21 +01:00
|
|
|
vgmstream->loop_flag = 0;
|
|
|
|
vgmstream->loop_start_sample = 0;
|
|
|
|
vgmstream->loop_end_sample = 0;
|
2016-07-17 08:02:27 +02:00
|
|
|
}
|
2017-11-25 00:43:18 +01:00
|
|
|
}
|
2008-03-25 08:30:04 +01:00
|
|
|
|
2017-11-25 00:43:18 +01:00
|
|
|
/* test if candidate for dual stereo */
|
2018-08-23 18:00:34 +02:00
|
|
|
if (vgmstream->channels == 1 && vgmstream->allow_dual_stereo == 1) {
|
2023-05-15 16:14:29 +02:00
|
|
|
try_dual_file_stereo(vgmstream, sf, init_vgmstream_function);
|
2017-11-25 00:43:18 +01:00
|
|
|
}
|
2008-03-25 08:30:04 +01:00
|
|
|
|
2019-02-17 23:53:37 +01:00
|
|
|
/* clean as loops are readable metadata but loop fields may contain garbage
|
|
|
|
* (done *after* dual stereo as it needs loop fields to match) */
|
|
|
|
if (!vgmstream->loop_flag) {
|
|
|
|
vgmstream->loop_start_sample = 0;
|
|
|
|
vgmstream->loop_end_sample = 0;
|
|
|
|
}
|
|
|
|
|
2017-03-04 02:05:07 +01:00
|
|
|
#ifdef VGM_USE_FFMPEG
|
2017-11-25 00:43:18 +01:00
|
|
|
/* check FFmpeg streams here, for lack of a better place */
|
|
|
|
if (vgmstream->coding_type == coding_FFmpeg) {
|
2021-07-23 18:55:03 +02:00
|
|
|
int ffmpeg_subsongs = ffmpeg_get_subsong_count(vgmstream->codec_data);
|
|
|
|
if (ffmpeg_subsongs && !vgmstream->num_streams) {
|
|
|
|
vgmstream->num_streams = ffmpeg_subsongs;
|
2017-03-04 02:05:07 +01:00
|
|
|
}
|
2017-11-25 00:43:18 +01:00
|
|
|
}
|
2017-03-04 02:05:07 +01:00
|
|
|
#endif
|
|
|
|
|
2019-03-09 21:31:15 +01:00
|
|
|
/* some players are picky with incorrect channel layouts */
|
|
|
|
if (vgmstream->channel_layout > 0) {
|
|
|
|
int output_channels = vgmstream->channels;
|
|
|
|
int ch, count = 0, max_ch = 32;
|
|
|
|
for (ch = 0; ch < max_ch; ch++) {
|
|
|
|
int bit = (vgmstream->channel_layout >> ch) & 1;
|
|
|
|
if (ch > 17 && bit) {
|
|
|
|
VGM_LOG("VGMSTREAM: wrong bit %i in channel_layout %x\n", ch, vgmstream->channel_layout);
|
|
|
|
vgmstream->channel_layout = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
count += bit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count > output_channels) {
|
|
|
|
VGM_LOG("VGMSTREAM: wrong totals %i in channel_layout %x\n", count, vgmstream->channel_layout);
|
|
|
|
vgmstream->channel_layout = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-16 20:05:53 +02:00
|
|
|
/* files can have thousands subsongs, but let's put a limit */
|
2019-03-09 23:27:28 +01:00
|
|
|
if (vgmstream->num_streams < 0 || vgmstream->num_streams > VGMSTREAM_MAX_SUBSONGS) {
|
2018-08-16 20:05:53 +02:00
|
|
|
VGM_LOG("VGMSTREAM: wrong num_streams (ns=%i)\n", vgmstream->num_streams);
|
|
|
|
close_vgmstream(vgmstream);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-11-25 00:43:18 +01:00
|
|
|
/* save info */
|
2018-04-15 00:48:37 +02:00
|
|
|
/* stream_index 0 may be used by plugins to signal "vgmstream default" (IOW don't force to 1) */
|
2019-02-15 23:46:21 +01:00
|
|
|
if (vgmstream->stream_index == 0) {
|
2020-07-17 22:35:32 +02:00
|
|
|
vgmstream->stream_index = sf->stream_index;
|
2019-02-15 23:46:21 +01:00
|
|
|
}
|
2017-08-12 11:27:10 +02:00
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
|
|
|
|
setup_vgmstream(vgmstream); /* final setup */
|
2008-05-19 05:58:15 +02:00
|
|
|
|
2017-11-25 00:43:18 +01:00
|
|
|
return vgmstream;
|
2008-01-31 07:04:26 +01:00
|
|
|
}
|
|
|
|
|
2017-11-25 00:43:18 +01:00
|
|
|
/* not supported */
|
2008-01-31 07:04:26 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-07-17 22:35:32 +02:00
|
|
|
void setup_vgmstream(VGMSTREAM* vgmstream) {
|
2019-02-25 00:38:35 +01:00
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
/* save start things so we can restart when seeking */
|
|
|
|
memcpy(vgmstream->start_ch, vgmstream->ch, sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
|
|
|
memcpy(vgmstream->start_vgmstream, vgmstream, sizeof(VGMSTREAM));
|
|
|
|
|
|
|
|
/* layout's sub-VGMSTREAM are expected to setup externally and maybe call this,
|
|
|
|
* as they can be created using init_vgmstream or manually */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-20 17:18:38 +02:00
|
|
|
/* format detection and VGMSTREAM setup, uses default parameters */
|
2020-07-17 22:35:32 +02:00
|
|
|
VGMSTREAM* init_vgmstream(const char* const filename) {
|
|
|
|
VGMSTREAM* vgmstream = NULL;
|
|
|
|
STREAMFILE* sf = open_stdio_streamfile(filename);
|
|
|
|
if (sf) {
|
|
|
|
vgmstream = init_vgmstream_from_STREAMFILE(sf);
|
|
|
|
close_streamfile(sf);
|
2008-05-20 17:18:38 +02:00
|
|
|
}
|
|
|
|
return vgmstream;
|
|
|
|
}
|
|
|
|
|
2020-07-17 22:35:32 +02:00
|
|
|
VGMSTREAM* init_vgmstream_from_STREAMFILE(STREAMFILE* sf) {
|
|
|
|
return init_vgmstream_internal(sf);
|
2008-05-20 17:18:38 +02:00
|
|
|
}
|
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
/* Reset a VGMSTREAM to its state at the start of playback (when a plugin seeks back to zero). */
|
2020-07-17 22:35:32 +02:00
|
|
|
void reset_vgmstream(VGMSTREAM* vgmstream) {
|
2008-05-19 05:58:15 +02:00
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
/* reset the VGMSTREAM and channels back to their original state */
|
|
|
|
memcpy(vgmstream, vgmstream->start_vgmstream, sizeof(VGMSTREAM));
|
|
|
|
memcpy(vgmstream->ch, vgmstream->start_ch, sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
|
|
|
/* loop_ch is not reset here because there is a possibility of the
|
2008-05-19 05:58:15 +02:00
|
|
|
* init_vgmstream_* function doing something tricky and precomputing it.
|
|
|
|
* Otherwise hit_loop will be 0 and it will be copied over anyway when we
|
|
|
|
* really hit the loop start. */
|
2008-06-15 06:01:03 +02:00
|
|
|
|
2023-05-15 16:14:29 +02:00
|
|
|
decode_reset(vgmstream);
|
2018-08-12 00:58:20 +02:00
|
|
|
|
2023-05-15 16:14:29 +02:00
|
|
|
render_reset(vgmstream);
|
2019-02-15 22:28:20 +01:00
|
|
|
|
|
|
|
/* note that this does not reset the constituent STREAMFILES
|
2020-07-17 22:35:32 +02:00
|
|
|
* (vgmstream->ch[N].streamfiles' internal state, like internal offset, though shouldn't matter) */
|
2008-05-19 05:58:15 +02:00
|
|
|
}
|
|
|
|
|
2017-12-06 15:32:52 +01:00
|
|
|
/* Allocate memory and setup a VGMSTREAM */
|
2020-07-17 22:35:32 +02:00
|
|
|
VGMSTREAM* allocate_vgmstream(int channel_count, int loop_flag) {
|
|
|
|
VGMSTREAM* vgmstream;
|
2008-01-31 07:04:26 +01:00
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
/* up to ~16-24 aren't too rare for multilayered files, more is probably a bug */
|
2019-02-23 23:38:53 +01:00
|
|
|
if (channel_count <= 0 || channel_count > VGMSTREAM_MAX_CHANNELS) {
|
2018-08-15 17:36:20 +02:00
|
|
|
VGM_LOG("VGMSTREAM: error allocating %i channels\n", channel_count);
|
2018-02-25 12:17:51 +01:00
|
|
|
return NULL;
|
2018-08-15 17:36:20 +02:00
|
|
|
}
|
2008-04-02 19:50:50 +02:00
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
/* VGMSTREAM's alloc'ed internals work as follows:
|
|
|
|
* - vgmstream: main struct (config+state) modified by metas, layouts and codings as needed
|
|
|
|
* - ch: config+state per channel, also modified by those
|
|
|
|
* - start_vgmstream: vgmstream clone copied on init_vgmstream and restored on reset_vgmstream
|
|
|
|
* - start_ch: ch clone copied on init_vgmstream and restored on reset_vgmstream
|
2023-05-15 16:14:29 +02:00
|
|
|
* - loop_ch: ch clone copied on loop start and restored on loop end (decode_do_loop)
|
2019-02-15 22:28:20 +01:00
|
|
|
* - codec/layout_data: custom state for complex codecs or layouts, handled externally
|
|
|
|
*
|
|
|
|
* Here we only create the basic structs to be filled, and only after init_vgmstream it
|
|
|
|
* can be considered ready. Clones are shallow copies, in that they share alloc'ed struts
|
|
|
|
* (like, vgmstream->ch and start_vgmstream->ch will be the same after init_vgmstream, or
|
|
|
|
* start_vgmstream->start_vgmstream will end up pointing to itself)
|
|
|
|
*
|
|
|
|
* This is all a bit too brittle, so code alloc'ing or changing anything sensitive should
|
|
|
|
* take care clones are properly synced.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* create vgmstream + main structs (other data is 0'ed) */
|
2008-01-31 07:04:26 +01:00
|
|
|
vgmstream = calloc(1,sizeof(VGMSTREAM));
|
|
|
|
if (!vgmstream) return NULL;
|
2020-07-29 19:34:55 +02:00
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
vgmstream->start_vgmstream = calloc(1,sizeof(VGMSTREAM));
|
|
|
|
if (!vgmstream->start_vgmstream) goto fail;
|
2008-05-19 05:58:15 +02:00
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
vgmstream->ch = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
|
|
|
if (!vgmstream->ch) goto fail;
|
2008-01-31 07:04:26 +01:00
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
vgmstream->start_ch = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
|
|
|
if (!vgmstream->start_ch) goto fail;
|
2008-01-31 07:04:26 +01:00
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
if (loop_flag) {
|
|
|
|
vgmstream->loop_ch = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
|
|
|
if (!vgmstream->loop_ch) goto fail;
|
2008-01-31 07:04:26 +01:00
|
|
|
}
|
|
|
|
|
2020-08-03 23:15:59 +02:00
|
|
|
/* garbage buffer for decode discarding (local bufs may cause stack overflows with segments/layers)
|
|
|
|
* in theory the bigger the better but in practice there isn't much difference */
|
|
|
|
vgmstream->tmpbuf_size = 0x10000; /* for all channels */
|
|
|
|
vgmstream->tmpbuf = malloc(sizeof(sample_t) * vgmstream->tmpbuf_size);
|
|
|
|
|
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
vgmstream->channels = channel_count;
|
|
|
|
vgmstream->loop_flag = loop_flag;
|
2008-01-31 07:04:26 +01:00
|
|
|
|
2019-03-09 20:50:58 +01:00
|
|
|
mixing_init(vgmstream); /* pre-init */
|
2019-03-24 01:21:09 +01:00
|
|
|
|
2020-08-12 17:41:03 +02:00
|
|
|
/* BEWARE: try_dual_file_stereo does some free'ing too */
|
|
|
|
|
2019-02-25 00:38:35 +01:00
|
|
|
//vgmstream->stream_name_size = STREAM_NAME_SIZE;
|
2008-01-31 07:04:26 +01:00
|
|
|
return vgmstream;
|
2019-02-15 22:28:20 +01:00
|
|
|
fail:
|
|
|
|
if (vgmstream) {
|
2019-03-24 01:21:09 +01:00
|
|
|
mixing_close(vgmstream);
|
2020-08-03 23:15:59 +02:00
|
|
|
free(vgmstream->tmpbuf);
|
2019-02-15 22:28:20 +01:00
|
|
|
free(vgmstream->ch);
|
|
|
|
free(vgmstream->start_ch);
|
|
|
|
free(vgmstream->loop_ch);
|
|
|
|
free(vgmstream->start_vgmstream);
|
|
|
|
}
|
|
|
|
free(vgmstream);
|
|
|
|
return NULL;
|
2008-01-31 07:04:26 +01:00
|
|
|
}
|
|
|
|
|
2020-07-17 22:35:32 +02:00
|
|
|
void close_vgmstream(VGMSTREAM* vgmstream) {
|
2017-04-29 22:37:15 +02:00
|
|
|
if (!vgmstream)
|
|
|
|
return;
|
2008-01-31 07:04:26 +01:00
|
|
|
|
2023-05-15 16:14:29 +02:00
|
|
|
decode_free(vgmstream);
|
2020-07-17 22:35:32 +02:00
|
|
|
vgmstream->codec_data = NULL;
|
|
|
|
|
2023-05-15 16:14:29 +02:00
|
|
|
render_free(vgmstream);
|
2020-07-17 22:35:32 +02:00
|
|
|
vgmstream->layout_data = NULL;
|
|
|
|
|
2017-12-06 15:32:52 +01:00
|
|
|
|
2008-08-02 12:24:28 +02:00
|
|
|
/* now that the special cases have had their chance, clean up the standard items */
|
2017-10-28 01:34:32 +02:00
|
|
|
{
|
|
|
|
int i,j;
|
|
|
|
|
2019-02-15 22:28:20 +01:00
|
|
|
for (i = 0; i < vgmstream->channels; i++) {
|
2017-10-28 01:34:32 +02:00
|
|
|
if (vgmstream->ch[i].streamfile) {
|
|
|
|
close_streamfile(vgmstream->ch[i].streamfile);
|
|
|
|
/* Multiple channels might have the same streamfile. Find the others
|
2019-02-15 22:28:20 +01:00
|
|
|
* that are the same as this and clear them so they won't be closed again. */
|
|
|
|
for (j = 0; j < vgmstream->channels; j++) {
|
|
|
|
if (i != j && vgmstream->ch[j].streamfile == vgmstream->ch[i].streamfile) {
|
2017-10-28 01:34:32 +02:00
|
|
|
vgmstream->ch[j].streamfile = NULL;
|
|
|
|
}
|
2008-08-02 12:24:28 +02:00
|
|
|
}
|
2017-10-28 01:34:32 +02:00
|
|
|
vgmstream->ch[i].streamfile = NULL;
|
2008-08-02 12:24:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-24 01:21:09 +01:00
|
|
|
|
2019-03-09 20:50:58 +01:00
|
|
|
mixing_close(vgmstream);
|
2020-08-03 23:15:59 +02:00
|
|
|
free(vgmstream->tmpbuf);
|
2019-02-15 22:28:20 +01:00
|
|
|
free(vgmstream->ch);
|
|
|
|
free(vgmstream->start_ch);
|
|
|
|
free(vgmstream->loop_ch);
|
|
|
|
free(vgmstream->start_vgmstream);
|
2008-01-31 07:04:26 +01:00
|
|
|
free(vgmstream);
|
|
|
|
}
|
|
|
|
|
2017-12-06 16:55:41 +01:00
|
|
|
void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sample, int loop_end_sample) {
|
|
|
|
if (!vgmstream) return;
|
|
|
|
|
2021-08-22 13:13:38 +02:00
|
|
|
/* ignore bad values (may happen with layers + TXTP loop install) */
|
2020-09-06 19:24:56 +02:00
|
|
|
if (loop_flag && (loop_start_sample < 0 ||
|
|
|
|
loop_start_sample > loop_end_sample ||
|
|
|
|
loop_end_sample > vgmstream->num_samples))
|
|
|
|
return;
|
|
|
|
|
2017-12-06 16:55:41 +01:00
|
|
|
/* this requires a bit more messing with the VGMSTREAM than I'm comfortable with... */
|
|
|
|
if (loop_flag && !vgmstream->loop_flag && !vgmstream->loop_ch) {
|
2020-07-26 11:19:52 +02:00
|
|
|
vgmstream->loop_ch = calloc(vgmstream->channels, sizeof(VGMSTREAMCHANNEL));
|
2019-02-15 22:28:20 +01:00
|
|
|
if (!vgmstream->loop_ch) loop_flag = 0; /* ??? */
|
2017-12-06 16:55:41 +01:00
|
|
|
}
|
2020-07-26 11:19:52 +02:00
|
|
|
#if 0
|
|
|
|
/* allow in case loop_flag is re-enabled later */
|
2018-09-06 16:44:42 +02:00
|
|
|
else if (!loop_flag && vgmstream->loop_flag) {
|
2020-07-26 11:19:52 +02:00
|
|
|
free(vgmstream->loop_ch);
|
2018-08-19 00:43:06 +02:00
|
|
|
vgmstream->loop_ch = NULL;
|
|
|
|
}
|
2020-07-26 11:19:52 +02:00
|
|
|
#endif
|
2018-08-19 00:43:06 +02:00
|
|
|
|
2017-12-06 16:55:41 +01:00
|
|
|
vgmstream->loop_flag = loop_flag;
|
2020-07-26 11:19:52 +02:00
|
|
|
|
2017-12-06 16:55:41 +01:00
|
|
|
if (loop_flag) {
|
|
|
|
vgmstream->loop_start_sample = loop_start_sample;
|
|
|
|
vgmstream->loop_end_sample = loop_end_sample;
|
2019-02-15 23:46:21 +01:00
|
|
|
}
|
|
|
|
#if 0 /* keep metadata as it's may be shown (with 'loop disabled' info) */
|
|
|
|
else {
|
2018-08-19 00:43:06 +02:00
|
|
|
vgmstream->loop_start_sample = 0;
|
|
|
|
vgmstream->loop_end_sample = 0;
|
|
|
|
}
|
2019-02-15 23:46:21 +01:00
|
|
|
#endif
|
2019-02-15 22:28:20 +01:00
|
|
|
|
2018-08-19 00:43:06 +02:00
|
|
|
/* propagate changes to layouts that need them */
|
|
|
|
if (vgmstream->layout_type == layout_layered) {
|
|
|
|
int i;
|
2020-07-26 11:19:52 +02:00
|
|
|
layered_layout_data* data = vgmstream->layout_data;
|
|
|
|
|
|
|
|
/* layered loops using the internal VGMSTREAMs */
|
2018-08-19 00:43:06 +02:00
|
|
|
for (i = 0; i < data->layer_count; i++) {
|
2020-07-26 11:19:52 +02:00
|
|
|
if (!data->layers[i]->config_enabled) /* only in simple mode */
|
|
|
|
vgmstream_force_loop(data->layers[i], loop_flag, loop_start_sample, loop_end_sample);
|
2019-02-15 22:28:20 +01:00
|
|
|
/* layer's force_loop also calls setup_vgmstream, no need to do it here */
|
2018-08-19 00:43:06 +02:00
|
|
|
}
|
2017-12-06 16:55:41 +01:00
|
|
|
}
|
2019-02-15 22:28:20 +01:00
|
|
|
|
|
|
|
/* segmented layout loops with standard loop start/end values and works ok */
|
|
|
|
|
|
|
|
/* notify of new initial state */
|
|
|
|
setup_vgmstream(vgmstream);
|
2017-12-06 16:55:41 +01:00
|
|
|
}
|
|
|
|
|
2018-09-07 19:34:31 +02:00
|
|
|
void vgmstream_set_loop_target(VGMSTREAM* vgmstream, int loop_target) {
|
|
|
|
if (!vgmstream) return;
|
2020-07-29 19:34:55 +02:00
|
|
|
if (!vgmstream->loop_flag) return;
|
|
|
|
|
2018-09-07 19:34:31 +02:00
|
|
|
|
|
|
|
vgmstream->loop_target = loop_target; /* loop count must be rounded (int) as otherwise target is meaningless */
|
|
|
|
|
|
|
|
/* propagate changes to layouts that need them */
|
|
|
|
if (vgmstream->layout_type == layout_layered) {
|
|
|
|
int i;
|
|
|
|
layered_layout_data *data = vgmstream->layout_data;
|
|
|
|
for (i = 0; i < data->layer_count; i++) {
|
|
|
|
vgmstream_set_loop_target(data->layers[i], loop_target);
|
|
|
|
}
|
|
|
|
}
|
2019-02-25 00:38:35 +01:00
|
|
|
|
|
|
|
/* notify of new initial state */
|
|
|
|
setup_vgmstream(vgmstream);
|
2018-09-07 19:34:31 +02:00
|
|
|
}
|
2008-02-05 07:44:44 +01:00
|
|
|
|
2020-07-18 00:12:44 +02:00
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
/* MISC */
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
2017-11-24 20:15:23 +01:00
|
|
|
/* See if there is a second file which may be the second channel, given an already opened mono vgmstream.
|
|
|
|
* If a suitable file is found, open it and change opened_vgmstream to a stereo vgmstream. */
|
2023-05-15 16:14:29 +02:00
|
|
|
static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, init_vgmstream_t init_vgmstream_function) {
|
2017-11-24 20:15:23 +01:00
|
|
|
/* filename search pairs for dual file stereo */
|
2020-07-17 22:35:32 +02:00
|
|
|
static const char* const dfs_pairs[][2] = {
|
2019-11-03 18:37:20 +01:00
|
|
|
{"L","R"}, /* most common in .dsp and .vag */
|
|
|
|
{"l","r"}, /* same */
|
|
|
|
{"left","right"}, /* Freaky Flyers (GC) .adp, Velocity (PSP) .vag, Hyper Fighters (Wii) .dsp */
|
|
|
|
{"Left","Right"}, /* Geometry Wars: Galaxies (Wii) .dsp */
|
2018-03-24 19:43:17 +01:00
|
|
|
{".V0",".V1"}, /* Homura (PS2) */
|
2018-08-21 22:16:56 +02:00
|
|
|
{".L",".R"}, /* Crash Nitro Racing (PS2), Gradius V (PS2) */
|
2019-11-03 18:37:20 +01:00
|
|
|
{"_0.dsp","_1.dsp"}, /* Wario World (GC) */
|
2020-02-22 10:08:57 +01:00
|
|
|
{".adpcm","_NxEncoderOut_.adpcm"}, /* Kill la Kill: IF (Switch) */
|
|
|
|
{".adpcm","_2.adpcm"}, /* Desire: Remaster Version (Switch) */
|
2017-11-24 20:15:23 +01:00
|
|
|
};
|
|
|
|
char new_filename[PATH_LIMIT];
|
2020-07-17 22:35:32 +02:00
|
|
|
char* extension;
|
2017-11-24 20:15:23 +01:00
|
|
|
int dfs_pair = -1; /* -1=no stereo, 0=opened_vgmstream is left, 1=opened_vgmstream is right */
|
2020-07-17 22:35:32 +02:00
|
|
|
VGMSTREAM* new_vgmstream = NULL;
|
|
|
|
STREAMFILE* dual_sf = NULL;
|
2019-07-28 14:47:33 +02:00
|
|
|
int i,j, dfs_pair_count, extension_len, filename_len;
|
2008-03-25 08:30:04 +01:00
|
|
|
|
2017-11-24 20:15:23 +01:00
|
|
|
if (opened_vgmstream->channels != 1)
|
|
|
|
return;
|
2008-05-20 17:18:38 +02:00
|
|
|
|
2019-03-10 00:28:16 +01:00
|
|
|
/* custom codec/layouts aren't designed for this (should never get here anyway) */
|
|
|
|
if (opened_vgmstream->codec_data || opened_vgmstream->layout_data)
|
|
|
|
return;
|
|
|
|
|
2019-07-28 14:47:33 +02:00
|
|
|
//todo other layouts work but some stereo codecs do weird things
|
2017-11-24 20:15:23 +01:00
|
|
|
//if (opened_vgmstream->layout != layout_none) return;
|
2008-03-25 08:30:04 +01:00
|
|
|
|
2020-07-17 22:35:32 +02:00
|
|
|
get_streamfile_name(sf, new_filename, sizeof(new_filename));
|
2019-07-28 14:47:33 +02:00
|
|
|
filename_len = strlen(new_filename);
|
|
|
|
if (filename_len < 2)
|
|
|
|
return;
|
|
|
|
|
|
|
|
extension = (char *)filename_extension(new_filename);
|
2019-09-29 18:25:24 +02:00
|
|
|
if (extension - new_filename >= 1 && extension[-1] == '.') /* [-1] is ok, yeah */
|
2019-07-28 14:47:33 +02:00
|
|
|
extension--; /* must include "." */
|
|
|
|
extension_len = strlen(extension);
|
2019-03-10 00:28:16 +01:00
|
|
|
|
2008-03-25 08:30:04 +01:00
|
|
|
|
2019-07-28 14:47:33 +02:00
|
|
|
/* find pair from base name and modify new_filename with the opposite (tries L>R then R>L) */
|
2017-11-24 20:15:23 +01:00
|
|
|
dfs_pair_count = (sizeof(dfs_pairs)/sizeof(dfs_pairs[0]));
|
2019-02-15 22:28:20 +01:00
|
|
|
for (i = 0; dfs_pair == -1 && i < dfs_pair_count; i++) {
|
|
|
|
for (j = 0; dfs_pair == -1 && j < 2; j++) {
|
2020-07-17 22:35:32 +02:00
|
|
|
const char* this_suffix = dfs_pairs[i][j];
|
|
|
|
const char* that_suffix = dfs_pairs[i][j^1];
|
2017-11-24 20:15:23 +01:00
|
|
|
size_t this_suffix_len = strlen(dfs_pairs[i][j]);
|
2019-07-28 14:47:33 +02:00
|
|
|
size_t that_suffix_len = strlen(dfs_pairs[i][j^1]);
|
|
|
|
|
|
|
|
//;VGM_LOG("DFS: l=%s, r=%s\n", this_suffix,that_suffix);
|
2008-03-25 08:30:04 +01:00
|
|
|
|
2019-09-29 18:25:24 +02:00
|
|
|
/* if suffix matches paste opposite suffix (+ terminator) to extension pointer, thus to new_filename */
|
2019-11-03 18:37:20 +01:00
|
|
|
if (filename_len > this_suffix_len && strchr(this_suffix, '.') != NULL) { /* same suffix with extension */
|
|
|
|
//;VGM_LOG("DFS: suf+ext %s vs %s len %i\n", new_filename, this_suffix, this_suffix_len);
|
|
|
|
if (memcmp(new_filename + (filename_len - this_suffix_len), this_suffix, this_suffix_len) == 0) {
|
|
|
|
memcpy (new_filename + (filename_len - this_suffix_len), that_suffix,that_suffix_len+1);
|
2020-02-22 10:08:57 +01:00
|
|
|
dfs_pair = j;
|
2017-11-26 01:54:33 +01:00
|
|
|
}
|
|
|
|
}
|
2019-11-03 18:37:20 +01:00
|
|
|
else if (filename_len - extension_len > this_suffix_len) { /* same suffix without extension */
|
|
|
|
//;VGM_LOG("DFS: suf-ext %s vs %s len %i\n", extension - this_suffix_len, this_suffix, this_suffix_len);
|
2019-07-28 14:47:33 +02:00
|
|
|
if (memcmp(extension - this_suffix_len, this_suffix,this_suffix_len) == 0) {
|
|
|
|
memmove(extension + that_suffix_len - this_suffix_len, extension,extension_len+1); /* move old extension to end */
|
|
|
|
memcpy (extension - this_suffix_len, that_suffix,that_suffix_len); /* overwrite with new suffix */
|
2020-02-22 10:08:57 +01:00
|
|
|
dfs_pair = j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dfs_pair != -1) {
|
|
|
|
//VGM_LOG("DFS: try %i: %s\n", dfs_pair, new_filename);
|
|
|
|
/* try to init other channel (new_filename now has the opposite name) */
|
2020-07-17 22:35:32 +02:00
|
|
|
dual_sf = open_streamfile(sf, new_filename);
|
|
|
|
if (!dual_sf) {
|
2020-02-22 10:08:57 +01:00
|
|
|
/* restore filename and keep trying (if found it'll break and init) */
|
|
|
|
dfs_pair = -1;
|
2020-07-17 22:35:32 +02:00
|
|
|
get_streamfile_name(sf, new_filename, sizeof(new_filename));
|
2017-11-26 01:54:33 +01:00
|
|
|
}
|
2008-03-25 08:30:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-22 10:08:57 +01:00
|
|
|
/* filename didn't have a suitable L/R-pair name */
|
2017-11-24 20:15:23 +01:00
|
|
|
if (dfs_pair == -1)
|
|
|
|
goto fail;
|
2019-07-28 14:47:33 +02:00
|
|
|
//;VGM_LOG("DFS: match %i filename=%s\n", dfs_pair, new_filename);
|
2008-03-25 08:30:04 +01:00
|
|
|
|
2020-07-17 22:35:32 +02:00
|
|
|
new_vgmstream = init_vgmstream_function(dual_sf); /* use the init function that just worked */
|
|
|
|
close_streamfile(dual_sf);
|
2008-03-25 08:30:04 +01:00
|
|
|
|
|
|
|
/* see if we were able to open the file, and if everything matched nicely */
|
2017-11-26 01:54:33 +01:00
|
|
|
if (!(new_vgmstream &&
|
2017-11-24 20:15:23 +01:00
|
|
|
new_vgmstream->channels == 1 &&
|
|
|
|
/* we have seen legitimate pairs where these are off by one...
|
|
|
|
* but leaving it commented out until I can find those and recheck */
|
|
|
|
/* abs(new_vgmstream->num_samples-opened_vgmstream->num_samples <= 1) && */
|
|
|
|
new_vgmstream->num_samples == opened_vgmstream->num_samples &&
|
|
|
|
new_vgmstream->sample_rate == opened_vgmstream->sample_rate &&
|
|
|
|
new_vgmstream->meta_type == opened_vgmstream->meta_type &&
|
|
|
|
new_vgmstream->coding_type == opened_vgmstream->coding_type &&
|
|
|
|
new_vgmstream->layout_type == opened_vgmstream->layout_type &&
|
2008-03-25 08:30:04 +01:00
|
|
|
/* check even if the layout doesn't use them, because it is
|
2017-11-24 20:15:23 +01:00
|
|
|
* difficult to determine when it does, and they should be zero otherwise, anyway */
|
|
|
|
new_vgmstream->interleave_block_size == opened_vgmstream->interleave_block_size &&
|
2018-03-24 19:27:24 +01:00
|
|
|
new_vgmstream->interleave_last_block_size == opened_vgmstream->interleave_last_block_size)) {
|
2017-11-26 01:54:33 +01:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check these even if there is no loop, because they should then be zero in both
|
2019-02-25 00:38:35 +01:00
|
|
|
* (Homura PS2 right channel doesn't have loop points so this check is ignored) */
|
2023-06-24 15:35:54 +02:00
|
|
|
if (new_vgmstream->meta_type != meta_SMPL &&
|
2017-11-26 01:54:33 +01:00
|
|
|
!(new_vgmstream->loop_flag == opened_vgmstream->loop_flag &&
|
|
|
|
new_vgmstream->loop_start_sample== opened_vgmstream->loop_start_sample &&
|
|
|
|
new_vgmstream->loop_end_sample == opened_vgmstream->loop_end_sample)) {
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We seem to have a usable, matching file. Merge in the second channel. */
|
|
|
|
{
|
2020-07-17 22:35:32 +02:00
|
|
|
VGMSTREAMCHANNEL* new_chans;
|
|
|
|
VGMSTREAMCHANNEL* new_loop_chans = NULL;
|
|
|
|
VGMSTREAMCHANNEL* new_start_chans = NULL;
|
2008-03-25 08:30:04 +01:00
|
|
|
|
|
|
|
/* build the channels */
|
|
|
|
new_chans = calloc(2,sizeof(VGMSTREAMCHANNEL));
|
|
|
|
if (!new_chans) goto fail;
|
|
|
|
|
2017-11-24 20:15:23 +01:00
|
|
|
memcpy(&new_chans[dfs_pair],&opened_vgmstream->ch[0],sizeof(VGMSTREAMCHANNEL));
|
|
|
|
memcpy(&new_chans[dfs_pair^1],&new_vgmstream->ch[0],sizeof(VGMSTREAMCHANNEL));
|
2008-03-25 08:30:04 +01:00
|
|
|
|
2017-11-24 20:15:23 +01:00
|
|
|
/* loop and start will be initialized later, we just need to allocate them here */
|
2008-03-25 08:30:04 +01:00
|
|
|
new_start_chans = calloc(2,sizeof(VGMSTREAMCHANNEL));
|
|
|
|
if (!new_start_chans) {
|
|
|
|
free(new_chans);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2017-11-24 20:15:23 +01:00
|
|
|
if (opened_vgmstream->loop_ch) {
|
2008-03-25 08:30:04 +01:00
|
|
|
new_loop_chans = calloc(2,sizeof(VGMSTREAMCHANNEL));
|
|
|
|
if (!new_loop_chans) {
|
|
|
|
free(new_chans);
|
|
|
|
free(new_start_chans);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remove the existing structures */
|
|
|
|
/* not using close_vgmstream as that would close the file */
|
2017-11-24 20:15:23 +01:00
|
|
|
free(opened_vgmstream->ch);
|
|
|
|
free(new_vgmstream->ch);
|
2008-03-25 08:30:04 +01:00
|
|
|
|
2017-11-24 20:15:23 +01:00
|
|
|
free(opened_vgmstream->start_ch);
|
|
|
|
free(new_vgmstream->start_ch);
|
2008-03-25 08:30:04 +01:00
|
|
|
|
2017-11-24 20:15:23 +01:00
|
|
|
if (opened_vgmstream->loop_ch) {
|
|
|
|
free(opened_vgmstream->loop_ch);
|
|
|
|
free(new_vgmstream->loop_ch);
|
2008-03-25 08:30:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* fill in the new structures */
|
2017-11-24 20:15:23 +01:00
|
|
|
opened_vgmstream->ch = new_chans;
|
|
|
|
opened_vgmstream->start_ch = new_start_chans;
|
|
|
|
opened_vgmstream->loop_ch = new_loop_chans;
|
2008-03-25 08:30:04 +01:00
|
|
|
|
|
|
|
/* stereo! */
|
2017-11-24 20:15:23 +01:00
|
|
|
opened_vgmstream->channels = 2;
|
2022-01-14 17:22:31 +01:00
|
|
|
if (opened_vgmstream->layout_type == layout_interleave)
|
|
|
|
opened_vgmstream->layout_type = layout_none; /* fixes some odd cases */
|
2008-03-25 08:30:04 +01:00
|
|
|
|
|
|
|
/* discard the second VGMSTREAM */
|
2019-09-29 18:25:24 +02:00
|
|
|
mixing_close(new_vgmstream);
|
2020-08-12 17:41:03 +02:00
|
|
|
free(new_vgmstream->tmpbuf);
|
2019-09-29 18:25:24 +02:00
|
|
|
free(new_vgmstream->start_vgmstream);
|
2017-11-24 20:15:23 +01:00
|
|
|
free(new_vgmstream);
|
2019-03-10 00:28:16 +01:00
|
|
|
|
|
|
|
mixing_update_channel(opened_vgmstream); /* notify of new channel hacked-in */
|
2008-03-25 08:30:04 +01:00
|
|
|
}
|
2017-11-26 01:54:33 +01:00
|
|
|
|
2019-04-07 02:10:44 +02:00
|
|
|
return;
|
2008-03-25 08:30:04 +01:00
|
|
|
fail:
|
2019-04-07 02:10:44 +02:00
|
|
|
close_vgmstream(new_vgmstream);
|
2008-05-20 17:18:38 +02:00
|
|
|
return;
|
2009-07-30 06:10:16 +02:00
|
|
|
}
|
2015-02-09 04:01:26 +01:00
|
|
|
|
2017-01-14 00:59:54 +01:00
|
|
|
|
2017-03-09 20:38:52 +01:00
|
|
|
/**
|
2018-04-19 22:44:05 +02:00
|
|
|
* Inits vgmstream, doing two things:
|
2017-03-09 20:38:52 +01:00
|
|
|
* - sets the starting offset per channel (depending on the layout)
|
|
|
|
* - opens its own streamfile from on a base one. One streamfile per channel may be open (to improve read/seeks).
|
2018-02-24 22:30:17 +01:00
|
|
|
* Should be called in metas before returning the VGMSTREAM.
|
2017-03-09 20:38:52 +01:00
|
|
|
*/
|
2020-05-01 16:32:33 +02:00
|
|
|
int vgmstream_open_stream(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_offset) {
|
|
|
|
return vgmstream_open_stream_bf(vgmstream, sf, start_offset, 0);
|
|
|
|
}
|
|
|
|
int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_offset, int force_multibuffer) {
|
|
|
|
STREAMFILE* file = NULL;
|
2017-01-14 00:59:54 +01:00
|
|
|
char filename[PATH_LIMIT];
|
|
|
|
int ch;
|
2017-01-15 21:02:01 +01:00
|
|
|
int use_streamfile_per_channel = 0;
|
|
|
|
int use_same_offset_per_channel = 0;
|
2018-09-04 17:10:41 +02:00
|
|
|
int is_stereo_codec = 0;
|
2017-01-14 00:59:54 +01:00
|
|
|
|
2017-03-09 20:38:52 +01:00
|
|
|
|
2019-03-24 01:21:09 +01:00
|
|
|
if (vgmstream == NULL) {
|
|
|
|
VGM_LOG("VGMSTREAM: buggy code (null vgmstream)\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2023-06-24 15:06:01 +02:00
|
|
|
/* no need to open anything */
|
|
|
|
if (vgmstream->coding_type == coding_SILENCE)
|
|
|
|
return 1;
|
2019-03-24 01:21:09 +01:00
|
|
|
|
2018-04-19 22:44:05 +02:00
|
|
|
/* stream/offsets not needed, managed by layout */
|
2019-02-23 16:17:29 +01:00
|
|
|
if (vgmstream->layout_type == layout_segmented ||
|
2018-03-30 21:28:32 +02:00
|
|
|
vgmstream->layout_type == layout_layered)
|
2017-03-09 20:38:52 +01:00
|
|
|
return 1;
|
|
|
|
|
2018-04-19 22:44:05 +02:00
|
|
|
/* stream/offsets not needed, managed by decoder */
|
2018-09-04 17:51:34 +02:00
|
|
|
if (vgmstream->coding_type == coding_NWA ||
|
|
|
|
vgmstream->coding_type == coding_ACM ||
|
|
|
|
vgmstream->coding_type == coding_CRI_HCA)
|
2018-04-19 22:44:05 +02:00
|
|
|
return 1;
|
|
|
|
|
2019-08-11 19:46:16 +02:00
|
|
|
#ifdef VGM_USE_VORBIS
|
|
|
|
/* stream/offsets not needed, managed by decoder */
|
|
|
|
if (vgmstream->coding_type == coding_OGG_VORBIS)
|
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
|
2017-01-14 00:59:54 +01:00
|
|
|
#ifdef VGM_USE_FFMPEG
|
2018-04-19 22:44:05 +02:00
|
|
|
/* stream/offsets not needed, managed by decoder */
|
2017-03-09 20:38:52 +01:00
|
|
|
if (vgmstream->coding_type == coding_FFmpeg)
|
2017-01-14 00:59:54 +01:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
|
2019-10-05 15:10:40 +02:00
|
|
|
if ((vgmstream->coding_type == coding_CRI_ADX ||
|
|
|
|
vgmstream->coding_type == coding_CRI_ADX_enc_8 ||
|
|
|
|
vgmstream->coding_type == coding_CRI_ADX_enc_9 ||
|
|
|
|
vgmstream->coding_type == coding_CRI_ADX_exp ||
|
|
|
|
vgmstream->coding_type == coding_CRI_ADX_fixed) &&
|
|
|
|
(vgmstream->interleave_block_size == 0 || vgmstream->interleave_block_size > 0x12)) {
|
|
|
|
VGM_LOG("VGMSTREAM: ADX decoder with wrong frame size %x\n", vgmstream->interleave_block_size);
|
2019-10-20 01:24:59 +02:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2022-05-01 18:10:22 +02:00
|
|
|
if ((vgmstream->coding_type == coding_MSADPCM || vgmstream->coding_type == coding_MSADPCM_ck ||
|
|
|
|
vgmstream->coding_type == coding_MSADPCM_int ||
|
2023-06-30 22:59:22 +02:00
|
|
|
vgmstream->coding_type == coding_MS_IMA || vgmstream->coding_type == coding_MS_IMA_mono ||
|
|
|
|
vgmstream->coding_type == coding_PSX_cfg || vgmstream->coding_type == coding_PSX_pivotal
|
2022-05-01 18:10:22 +02:00
|
|
|
) &&
|
2019-10-20 01:24:59 +02:00
|
|
|
vgmstream->frame_size == 0) {
|
|
|
|
vgmstream->frame_size = vgmstream->interleave_block_size;
|
2019-10-05 15:10:40 +02:00
|
|
|
}
|
|
|
|
|
2023-06-30 22:59:22 +02:00
|
|
|
if ((vgmstream->coding_type == coding_PSX_cfg ||
|
|
|
|
vgmstream->coding_type == coding_PSX_pivotal) &&
|
|
|
|
(vgmstream->frame_size == 0 || vgmstream->frame_size > 0x50)) {
|
|
|
|
VGM_LOG("VGMSTREAM: PSX-cfg decoder with wrong frame size %x\n", vgmstream->frame_size);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2021-03-27 18:15:43 +01:00
|
|
|
if ((vgmstream->coding_type == coding_MSADPCM ||
|
|
|
|
vgmstream->coding_type == coding_MSADPCM_ck ||
|
|
|
|
vgmstream->coding_type == coding_MSADPCM_int) &&
|
2023-06-30 22:59:22 +02:00
|
|
|
(vgmstream->frame_size == 0 || vgmstream->frame_size > MSADPCM_MAX_BLOCK_SIZE)) {
|
2021-03-27 18:15:43 +01:00
|
|
|
VGM_LOG("VGMSTREAM: MSADPCM decoder with wrong frame size %x\n", vgmstream->frame_size);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2020-04-23 17:42:57 +02:00
|
|
|
/* big interleaved values for non-interleaved data may result in incorrect behavior,
|
|
|
|
* quick fix for now since layouts are finicky, with 'interleave' left for meta info
|
|
|
|
* (certain layouts+codecs combos results in funny output too, should rework the whole thing) */
|
|
|
|
if (vgmstream->layout_type == layout_interleave
|
|
|
|
&& vgmstream->channels == 1
|
|
|
|
&& vgmstream->interleave_block_size > 0) {
|
|
|
|
/* main codecs that use arbitrary interleaves but could happen for others too */
|
|
|
|
switch(vgmstream->coding_type) {
|
|
|
|
case coding_NGC_DSP:
|
|
|
|
case coding_NGC_DSP_subint:
|
|
|
|
case coding_PSX:
|
|
|
|
case coding_PSX_badflags:
|
|
|
|
vgmstream->interleave_block_size = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-15 21:02:01 +01:00
|
|
|
/* if interleave is big enough keep a buffer per channel */
|
2017-06-24 22:53:17 +02:00
|
|
|
if (vgmstream->interleave_block_size * vgmstream->channels >= STREAMFILE_DEFAULT_BUFFER_SIZE) {
|
2017-01-15 21:02:01 +01:00
|
|
|
use_streamfile_per_channel = 1;
|
2017-01-14 00:59:54 +01:00
|
|
|
}
|
|
|
|
|
2018-08-15 20:21:55 +02:00
|
|
|
/* if blocked layout (implicit) use multiple streamfiles; using only one leads to
|
2019-11-03 17:57:07 +01:00
|
|
|
* lots of buffer-trashing, with all the jumping around in the block layout
|
|
|
|
* (this increases total of data read but still seems faster) */
|
2018-08-15 20:21:55 +02:00
|
|
|
if (vgmstream->layout_type != layout_none && vgmstream->layout_type != layout_interleave) {
|
|
|
|
use_streamfile_per_channel = 1;
|
|
|
|
}
|
|
|
|
|
2020-05-01 16:32:33 +02:00
|
|
|
/* for hard-to-detect fixed offsets or full interleave */
|
|
|
|
if (force_multibuffer) {
|
|
|
|
use_streamfile_per_channel = 1;
|
|
|
|
}
|
|
|
|
|
2017-03-09 20:38:52 +01:00
|
|
|
/* for mono or codecs like IMA (XBOX, MS IMA, MS ADPCM) where channels work with the same bytes */
|
2017-02-18 18:27:21 +01:00
|
|
|
if (vgmstream->layout_type == layout_none) {
|
2017-01-15 21:02:01 +01:00
|
|
|
use_same_offset_per_channel = 1;
|
2017-01-14 00:59:54 +01:00
|
|
|
}
|
|
|
|
|
2018-09-04 17:10:41 +02:00
|
|
|
/* stereo codecs interleave in 2ch pairs (interleave size should still be: full_block_size / channels) */
|
2019-03-11 11:58:57 +01:00
|
|
|
if (vgmstream->layout_type == layout_interleave &&
|
|
|
|
(vgmstream->coding_type == coding_XBOX_IMA || vgmstream->coding_type == coding_MTAF)) {
|
2018-09-04 17:10:41 +02:00
|
|
|
is_stereo_codec = 1;
|
|
|
|
}
|
2017-01-14 00:59:54 +01:00
|
|
|
|
2020-05-01 16:32:33 +02:00
|
|
|
if (sf == NULL || start_offset < 0) {
|
2019-03-24 01:21:09 +01:00
|
|
|
VGM_LOG("VGMSTREAM: buggy code (null streamfile / wrong start_offset)\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2020-05-01 16:32:33 +02:00
|
|
|
get_streamfile_name(sf, filename, sizeof(filename));
|
2017-01-14 00:59:54 +01:00
|
|
|
/* open the file for reading by each channel */
|
|
|
|
{
|
2017-01-15 21:02:01 +01:00
|
|
|
if (!use_streamfile_per_channel) {
|
2020-05-01 16:32:33 +02:00
|
|
|
file = open_streamfile(sf, filename);
|
2017-01-15 21:02:01 +01:00
|
|
|
if (!file) goto fail;
|
|
|
|
}
|
2017-01-14 00:59:54 +01:00
|
|
|
|
2019-01-19 23:08:26 +01:00
|
|
|
for (ch = 0; ch < vgmstream->channels; ch++) {
|
2017-01-15 21:02:01 +01:00
|
|
|
off_t offset;
|
|
|
|
if (use_same_offset_per_channel) {
|
|
|
|
offset = start_offset;
|
2018-09-04 17:10:41 +02:00
|
|
|
} else if (is_stereo_codec) {
|
|
|
|
int ch_mod = (ch & 1) ? ch - 1 : ch; /* adjust odd channels (ch 0,1,2,3,4,5 > ch 0,0,2,2,4,4) */
|
2021-07-17 19:01:50 +02:00
|
|
|
offset = start_offset + vgmstream->interleave_block_size * ch_mod;
|
|
|
|
} else if (vgmstream->interleave_first_block_size) {
|
|
|
|
/* start_offset assumes + vgmstream->interleave_first_block_size, maybe should do it here */
|
|
|
|
offset = start_offset + (vgmstream->interleave_first_block_size + vgmstream->interleave_first_skip) * ch;
|
2017-01-15 21:02:01 +01:00
|
|
|
} else {
|
2021-07-17 19:01:50 +02:00
|
|
|
offset = start_offset + vgmstream->interleave_block_size * ch;
|
2017-01-14 00:59:54 +01:00
|
|
|
}
|
2017-01-15 21:02:01 +01:00
|
|
|
|
2019-11-03 17:57:07 +01:00
|
|
|
/* open new one if needed, useful to avoid jumping around when each channel data is too apart
|
|
|
|
* (don't use when data is close as it'd make buffers read the full file multiple times) */
|
2017-01-15 21:02:01 +01:00
|
|
|
if (use_streamfile_per_channel) {
|
2020-05-01 16:32:33 +02:00
|
|
|
file = open_streamfile(sf,filename);
|
2017-01-15 21:02:01 +01:00
|
|
|
if (!file) goto fail;
|
2017-01-14 00:59:54 +01:00
|
|
|
}
|
2017-01-15 21:02:01 +01:00
|
|
|
|
|
|
|
vgmstream->ch[ch].streamfile = file;
|
2020-05-01 16:32:33 +02:00
|
|
|
vgmstream->ch[ch].channel_start_offset = offset;
|
|
|
|
vgmstream->ch[ch].offset = offset;
|
2017-01-14 00:59:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-26 13:46:07 +02:00
|
|
|
/* init first block for blocked layout (if not blocked this will do nothing) */
|
|
|
|
block_update(start_offset, vgmstream);
|
|
|
|
|
2017-12-03 13:44:55 +01:00
|
|
|
/* EA-MT decoder is a bit finicky and needs this when channel offsets change */
|
|
|
|
if (vgmstream->coding_type == coding_EA_MT) {
|
|
|
|
flush_ea_mt(vgmstream);
|
|
|
|
}
|
|
|
|
|
2017-01-14 00:59:54 +01:00
|
|
|
return 1;
|
2017-01-15 21:02:01 +01:00
|
|
|
|
|
|
|
fail:
|
2017-01-25 22:31:28 +01:00
|
|
|
/* open streams will be closed in close_vgmstream(), hopefully called by the meta */
|
2017-01-15 21:02:01 +01:00
|
|
|
return 0;
|
2017-01-14 00:59:54 +01:00
|
|
|
}
|
2019-09-15 15:47:41 +02:00
|
|
|
|
|
|
|
int vgmstream_is_virtual_filename(const char* filename) {
|
|
|
|
int len = strlen(filename);
|
|
|
|
if (len < 6)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* vgmstream can play .txtp files that have size 0 but point to another file with config
|
|
|
|
* based only in the filename (ex. "file.fsb #2.txtp" plays 2nd subsong of file.fsb).
|
|
|
|
*
|
|
|
|
* Also, .m3u playlist can include files that don't exist, and players often allow filenames
|
|
|
|
* pointing to nothing (since could be some protocol/url).
|
|
|
|
*
|
|
|
|
* Plugins can use both quirks to allow "virtual files" (.txtp) in .m3u that don't need
|
|
|
|
* to exist but allow config. Plugins with this function if the filename is virtual,
|
|
|
|
* and their STREAMFILEs should be modified as to ignore null FILEs and report size 0. */
|
|
|
|
return strcmp(&filename[len-5], ".txtp") == 0;
|
|
|
|
}
|