mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
commit
b37bdeff01
@ -18,23 +18,29 @@ extern "C" {
|
||||
}
|
||||
#include "foo_vgmstream.h"
|
||||
|
||||
/* On EOF reads we can return length 0, or ignore and return the requested length + 0-set the buffer.
|
||||
* Some decoders don't check for EOF and may decode garbage if returned 0, as read_Nbit() funcs return -1.
|
||||
* Only matters for metas that get num_samples wrong (bigger than total data). */
|
||||
#define STREAMFILE_IGNORE_EOF 0
|
||||
|
||||
|
||||
static size_t read_the_rest_foo(uint8_t * dest, off_t offset, size_t length, FOO_STREAMFILE * streamfile) {
|
||||
size_t length_read_total=0;
|
||||
|
||||
/* is the beginning at least there? */
|
||||
if (offset >= streamfile->offset && offset < streamfile->offset+streamfile->validsize) {
|
||||
/* is the part of the requested length in the buffer? */
|
||||
if (offset >= streamfile->offset && offset < streamfile->offset + streamfile->validsize) {
|
||||
size_t length_read;
|
||||
off_t offset_into_buffer = offset-streamfile->offset;
|
||||
length_read = streamfile->validsize-offset_into_buffer;
|
||||
memcpy(dest,streamfile->buffer+offset_into_buffer,length_read);
|
||||
off_t offset_into_buffer = offset - streamfile->offset;
|
||||
length_read = streamfile->validsize - offset_into_buffer;
|
||||
|
||||
memcpy(dest,streamfile->buffer + offset_into_buffer,length_read);
|
||||
length_read_total += length_read;
|
||||
length -= length_read;
|
||||
offset += length_read;
|
||||
dest += length_read;
|
||||
}
|
||||
|
||||
/* TODO: What would make more sense here is to read the whole request
|
||||
/* What would make more sense here is to read the whole request
|
||||
* at once into the dest buffer, as it must be large enough, and then
|
||||
* copy some part of that into our own buffer.
|
||||
* The destination buffer is supposed to be much smaller than the
|
||||
@ -42,17 +48,22 @@ static size_t read_the_rest_foo(uint8_t * dest, off_t offset, size_t length, FOO
|
||||
* to the buffer size to avoid having to deal with things like this
|
||||
* which are outside of my intended use.
|
||||
*/
|
||||
/* read as much of the beginning of the request as possible, proceed */
|
||||
while (length>0) {
|
||||
/* read the rest of the requested length */
|
||||
while (length > 0) {
|
||||
size_t length_to_read;
|
||||
size_t length_read;
|
||||
streamfile->validsize=0;
|
||||
streamfile->validsize = 0; /* buffer is empty now */
|
||||
|
||||
/* request outside file: ignore to avoid seek/read */
|
||||
if (offset > streamfile->filesize) {
|
||||
streamfile->offset = streamfile->filesize;
|
||||
memset(dest,0,length);
|
||||
return length; /* return partially-read buffer and 0-set the rest */
|
||||
|
||||
#if STREAMFILE_IGNORE_EOF
|
||||
memset(dest,0,length); /* dest is already shifted */
|
||||
return length_read_total + length; /* partially-read + 0-set buffer */
|
||||
#else
|
||||
return length_read_total; /* partially-read buffer */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* position to new offset */
|
||||
@ -65,43 +76,49 @@ static size_t read_the_rest_foo(uint8_t * dest, off_t offset, size_t length, FOO
|
||||
#ifdef PROFILE_STREAMFILE
|
||||
streamfile->error_count++;
|
||||
#endif
|
||||
return 0; //fail miserably
|
||||
return 0; /* fail miserably (fseek shouldn't fail and reach this) */
|
||||
}
|
||||
|
||||
streamfile->offset=offset;
|
||||
streamfile->offset = offset;
|
||||
|
||||
/* decide how much must be read this time */
|
||||
if (length>streamfile->buffersize) length_to_read=streamfile->buffersize;
|
||||
else length_to_read=length;
|
||||
if (length > streamfile->buffersize)
|
||||
length_to_read = streamfile->buffersize;
|
||||
else
|
||||
length_to_read = length;
|
||||
|
||||
/* always try to fill the buffer */
|
||||
/* fill the buffer */
|
||||
try {
|
||||
length_read = streamfile->m_file->read(streamfile->buffer,streamfile->buffersize,*streamfile->p_abort);
|
||||
} catch(...) {
|
||||
#ifdef PROFILE_STREAMFILE
|
||||
streamfile->error_count++;
|
||||
#endif
|
||||
return 0; //fail miserably
|
||||
return 0; /* fail miserably */
|
||||
}
|
||||
streamfile->validsize=length_read;
|
||||
streamfile->validsize = length_read;
|
||||
|
||||
#ifdef PROFILE_STREAMFILE
|
||||
streamfile->bytes_read += length_read;
|
||||
#endif
|
||||
|
||||
/* if we can't get enough to satisfy the request we give up */
|
||||
/* if we can't get enough to satisfy the request (EOF) we give up */
|
||||
if (length_read < length_to_read) {
|
||||
memcpy(dest,streamfile->buffer,length_read);
|
||||
length_read_total+=length_read;
|
||||
return length_read_total;
|
||||
|
||||
#if STREAMFILE_IGNORE_EOF
|
||||
memset(dest+length_read,0,length-length_read);
|
||||
return length_read_total + length; /* partially-read + 0-set buffer */
|
||||
#else
|
||||
return length_read_total + length_read; /* partially-read buffer */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* use the new buffer */
|
||||
memcpy(dest,streamfile->buffer,length_to_read);
|
||||
length_read_total+=length_to_read;
|
||||
length-=length_to_read;
|
||||
dest+=length_to_read;
|
||||
offset+=length_to_read;
|
||||
length_read_total += length_to_read;
|
||||
length -= length_to_read;
|
||||
dest += length_to_read;
|
||||
offset += length_to_read;
|
||||
}
|
||||
|
||||
return length_read_total;
|
||||
@ -109,23 +126,32 @@ static size_t read_the_rest_foo(uint8_t * dest, off_t offset, size_t length, FOO
|
||||
|
||||
static size_t read_foo(FOO_STREAMFILE *streamfile, uint8_t * dest, off_t offset, size_t length) {
|
||||
|
||||
if (!streamfile || !dest || length<=0) return 0;
|
||||
|
||||
/* if entire request is within the buffer */
|
||||
if (offset >= streamfile->offset && offset+length <= streamfile->offset+streamfile->validsize) {
|
||||
memcpy(dest,streamfile->buffer+(offset-streamfile->offset),length);
|
||||
return length;
|
||||
}
|
||||
if (!streamfile || !dest || length<=0)
|
||||
return 0;
|
||||
|
||||
/* request outside file: ignore to avoid seek/read in read_the_rest_foo() */
|
||||
if (offset > streamfile->filesize) {
|
||||
streamfile->offset = streamfile->filesize;
|
||||
memset(dest, 0, length);
|
||||
|
||||
#if STREAMFILE_IGNORE_EOF
|
||||
memset(dest,0,length);
|
||||
return length; /* 0-set buffer */
|
||||
#else
|
||||
return 0; /* nothing to read */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* just copy if entire request is within the buffer */
|
||||
if (offset >= streamfile->offset && offset + length <= streamfile->offset + streamfile->validsize) {
|
||||
off_t offset_into_buffer = offset - streamfile->offset;
|
||||
memcpy(dest,streamfile->buffer + offset_into_buffer,length);
|
||||
return length;
|
||||
}
|
||||
|
||||
/* request outside buffer: new fread */
|
||||
return read_the_rest_foo(dest,offset,length,streamfile);
|
||||
{
|
||||
return read_the_rest_foo(dest,offset,length,streamfile);
|
||||
}
|
||||
}
|
||||
|
||||
STREAMFILE * open_foo_streamfile(const char * const filename, abort_callback * p_abort, t_filestats * stats) {
|
||||
|
@ -536,6 +536,7 @@ DECLARE_MULTIPLE_FILE_TYPE("LSF Audio File (*.LSF)", lsf);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("LWAV Audio File (*.LWAV)", lwav);
|
||||
|
||||
DECLARE_MULTIPLE_FILE_TYPE("MATX Audio File (*.MATX)", matx);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("MC3 Audio File (*.MC3)", mc3);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("MCA Audio File (*.MCA)", mca);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("MCG Audio File (*.MCG)", mcg);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("MDS Audio File (*.MDS)", mds);
|
||||
|
340
src/Makefile
340
src/Makefile
@ -1,334 +1,20 @@
|
||||
CODING_OBJS=coding/adx_decoder.o \
|
||||
coding/g721_decoder.o \
|
||||
coding/ima_decoder.o \
|
||||
coding/ngc_afc_decoder.o \
|
||||
coding/ngc_dsp_decoder.o \
|
||||
coding/ngc_dtk_decoder.o \
|
||||
coding/pcm_decoder.o \
|
||||
coding/psx_decoder.o \
|
||||
coding/xa_decoder.o \
|
||||
coding/eaxa_decoder.o \
|
||||
coding/ogg_vorbis_decoder.o \
|
||||
coding/sdx2_decoder.o \
|
||||
coding/ws_decoder.o \
|
||||
coding/mpeg_decoder.o \
|
||||
coding/acm_decoder.o \
|
||||
coding/nwa_decoder.o \
|
||||
coding/msadpcm_decoder.o \
|
||||
coding/aica_decoder.o \
|
||||
coding/nds_procyon_decoder.o \
|
||||
coding/l5_555_decoder.o \
|
||||
coding/SASSC_decoder.o \
|
||||
coding/g7221_decoder.o \
|
||||
coding/lsf_decoder.o \
|
||||
coding/mtaf_decoder.o \
|
||||
coding/at3_decoder.o \
|
||||
coding/g719_decoder.o \
|
||||
coding/hca_decoder.o \
|
||||
coding/ffmpeg_decoder.o \
|
||||
coding/coding_utils.o \
|
||||
coding/fsb_vorbis_decoder.o \
|
||||
coding/wwise_vorbis_decoder.o \
|
||||
coding/wwise_vorbis_utils.o \
|
||||
coding/ogl_vorbis_decoder.o
|
||||
# get all .c to find all possible .o
|
||||
SRC_SRCS = $(wildcard *.c)
|
||||
SRC_OBJS = $(patsubst %.c,%.o,$(SRC_SRCS))
|
||||
|
||||
LAYOUT_OBJS=layout/ast_blocked.o \
|
||||
layout/blocked.o \
|
||||
layout/halpst_blocked.o \
|
||||
layout/interleave.o \
|
||||
layout/nolayout.o \
|
||||
layout/xa_blocked.o \
|
||||
layout/caf_blocked.o \
|
||||
layout/ea_block.o \
|
||||
layout/wsi_blocked.o \
|
||||
layout/str_snds_blocked.o \
|
||||
layout/ws_aud_blocked.o \
|
||||
layout/interleave_byte.o \
|
||||
layout/mus_acm_layout.o \
|
||||
layout/aix_layout.o \
|
||||
layout/ims_block.o \
|
||||
layout/de2_blocked.o \
|
||||
layout/xvas_block.o \
|
||||
layout/vs_blocked.o \
|
||||
layout/emff_blocked.o \
|
||||
layout/thp_blocked.o \
|
||||
layout/gsb_blocked.o \
|
||||
layout/filp_blocked.o \
|
||||
layout/aax_layout.o \
|
||||
layout/ivaud_layout.o \
|
||||
layout/mxch_blocked.o \
|
||||
layout/psx_mgav_blocked.o \
|
||||
layout/ps2_adm_blocked.o \
|
||||
layout/bdsp_blocked.o \
|
||||
layout/tra_blocked.o \
|
||||
layout/ps2_iab_blocked.o \
|
||||
layout/ps2_strlr_blocked.o \
|
||||
layout/scd_int_layout.o
|
||||
CODING_SRCS = $(wildcard coding/*.c)
|
||||
CODING_OBJS = $(patsubst %.c,%.o,$(CODING_SRCS))
|
||||
|
||||
META_OBJS=meta/adx.o \
|
||||
meta/afc_header.o \
|
||||
meta/agsc.o \
|
||||
meta/ast.o \
|
||||
meta/brstm.o \
|
||||
meta/halpst.o \
|
||||
meta/nds_strm.o \
|
||||
meta/ngc_adpdtk.o \
|
||||
meta/rsf.o \
|
||||
meta/rs03.o \
|
||||
meta/ngc_dsp_std.o \
|
||||
meta/Cstr.o \
|
||||
meta/gcsw.o \
|
||||
meta/ps2_ads.o \
|
||||
meta/ps2_npsf.o \
|
||||
meta/rwsd.o \
|
||||
meta/psx_cdxa.o \
|
||||
meta/ps2_rxw.o \
|
||||
meta/ps2_int.o \
|
||||
meta/ps2_exst.o \
|
||||
meta/ps2_svag.o \
|
||||
meta/ps2_mib.o \
|
||||
meta/ps2_mic.o \
|
||||
meta/raw.o \
|
||||
meta/ps2_vag.o \
|
||||
meta/psx_gms.o \
|
||||
meta/ps2_str.o \
|
||||
meta/ps2_ild.o \
|
||||
meta/ps2_pnb.o \
|
||||
meta/xbox_wavm.o \
|
||||
meta/xbox_xwav.o \
|
||||
meta/ea_header.o \
|
||||
meta/ngc_caf.o \
|
||||
meta/ps2_vpk.o \
|
||||
meta/genh.o \
|
||||
meta/ogg_vorbis_file.o \
|
||||
meta/ps2_bmdx.o \
|
||||
meta/aifc.o \
|
||||
meta/str_snds.o \
|
||||
meta/ws_aud.o \
|
||||
meta/ahx.o \
|
||||
meta/ivb.o \
|
||||
meta/svs.o \
|
||||
meta/riff.o \
|
||||
meta/pos.o \
|
||||
meta/nwa.o \
|
||||
meta/ps2_rws.o \
|
||||
meta/ps2_hgc1.o \
|
||||
meta/xss.o \
|
||||
meta/ps2_sl3.o \
|
||||
meta/ps2_aus.o \
|
||||
meta/fsb.o \
|
||||
meta/fsb5.o \
|
||||
meta/rsd.o \
|
||||
meta/rwx.o \
|
||||
meta/xwb.o \
|
||||
meta/ea_old.o \
|
||||
meta/ps2_xa30.o \
|
||||
meta/musc.o \
|
||||
meta/musx.o \
|
||||
meta/ps2_leg.o \
|
||||
meta/ps2_filp.o \
|
||||
meta/ps2_ikm.o \
|
||||
meta/ps2_sfs.o \
|
||||
meta/sat_dvi.o \
|
||||
meta/ps2_bg00.o \
|
||||
meta/dc_kcey.o \
|
||||
meta/ps2_rstm.o \
|
||||
meta/acm.o \
|
||||
meta/mus_acm.o \
|
||||
meta/ps2_kces.o \
|
||||
meta/ps2_dxh.o \
|
||||
meta/ps2_psh.o \
|
||||
meta/sli.o \
|
||||
meta/sfl.o \
|
||||
meta/pcm.o \
|
||||
meta/ps2_psw.o \
|
||||
meta/rkv.o \
|
||||
meta/ps2_vas.o \
|
||||
meta/ps2_tec.o \
|
||||
meta/ps2_enth.o \
|
||||
meta/sdt.o \
|
||||
meta/aix.o \
|
||||
meta/ngc_tydsp.o \
|
||||
meta/wvs.o \
|
||||
meta/xbox_ims.o \
|
||||
meta/xbox_stma.o \
|
||||
meta/de2.o \
|
||||
meta/dc_str.o \
|
||||
meta/xbox_xmu.o \
|
||||
meta/ngc_bh2pcm.o \
|
||||
meta/xbox_xvas.o \
|
||||
meta/sat_sap.o \
|
||||
meta/sat_sap.o \
|
||||
meta/dc_idvi.o \
|
||||
meta/ps2_rnd.o \
|
||||
meta/kraw.o \
|
||||
meta/ps2_xa2.o \
|
||||
meta/idsp.o \
|
||||
meta/ngc_ymf.o \
|
||||
meta/nds_sad.o \
|
||||
meta/ps2_ccc.o \
|
||||
meta/psx_fag.o \
|
||||
meta/ps2_mihb.o \
|
||||
meta/ngc_pdt.o \
|
||||
meta/wii_mus.o \
|
||||
meta/dc_asd.o \
|
||||
meta/naomi_spsd.o \
|
||||
meta/bgw.o \
|
||||
meta/ps2_ass.o \
|
||||
meta/ngc_waa_wac_wad_wam.o \
|
||||
meta/seg.o \
|
||||
meta/str_asr.o \
|
||||
meta/zwdsp.o \
|
||||
meta/gca.o \
|
||||
meta/ish_isd.o \
|
||||
meta/spt_spd.o \
|
||||
meta/ydsp.o \
|
||||
meta/gsp_gsb.o \
|
||||
meta/ngc_ssm.o \
|
||||
meta/msvp.o \
|
||||
meta/ps2_joe.o \
|
||||
meta/vgs.o \
|
||||
meta/vs.o \
|
||||
meta/dc_dcsw_dcs.o \
|
||||
meta/wii_smp.o \
|
||||
meta/ss_stream.o \
|
||||
meta/emff.o \
|
||||
meta/thp.o \
|
||||
meta/wii_sts.o \
|
||||
meta/capdsp.o \
|
||||
meta/wii_sng.o \
|
||||
meta/aax.o \
|
||||
meta/ps2_p2bt.o \
|
||||
meta/ps2_gbts.o \
|
||||
meta/ngc_ffcc_str.o \
|
||||
meta/sat_baka.o \
|
||||
meta/nds_swav.o \
|
||||
meta/vsf.o \
|
||||
meta/nds_rrds.o \
|
||||
meta/ps2_tk5.o \
|
||||
meta/ads.o \
|
||||
meta/wii_str.o \
|
||||
meta/zsd.o \
|
||||
meta/ps2_mcg.o \
|
||||
meta/redspark.o \
|
||||
meta/ps2_vgs.o \
|
||||
meta/ivaud.o \
|
||||
meta/ps2_sps.o \
|
||||
meta/nds_hwas.o \
|
||||
meta/ngc_lps.o \
|
||||
meta/ps2_snd.o \
|
||||
meta/naomi_adpcm.o \
|
||||
meta/sd9.o \
|
||||
meta/2dx9.o \
|
||||
meta/ngc_dsp_ygo.o \
|
||||
meta/ps2_vgv.o \
|
||||
meta/ngc_gcub.o \
|
||||
meta/maxis_xa.o \
|
||||
meta/ngc_sck_dsp.o \
|
||||
meta/apple_caff.o \
|
||||
meta/pc_mxst.o \
|
||||
meta/pc_sob.o \
|
||||
meta/exakt_sc.o \
|
||||
meta/wii_bns.o \
|
||||
meta/pona.o \
|
||||
meta/xbox_hlwav.o \
|
||||
meta/stx.o \
|
||||
meta/ps2_stm.o \
|
||||
meta/myspd.o \
|
||||
meta/his.o \
|
||||
meta/ps2_ast.o \
|
||||
meta/dmsg_segh.o \
|
||||
meta/ngc_dsp_konami.o \
|
||||
meta/ps2_ster.o \
|
||||
meta/ps2_wb.o \
|
||||
meta/bnsf.o \
|
||||
meta/s14_sss.o \
|
||||
meta/ps2_gcm.o \
|
||||
meta/ps2_smpl.o \
|
||||
meta/ps2_msa.o \
|
||||
meta/pc_smp.o \
|
||||
meta/p3d.o \
|
||||
meta/ps2_adsc.o \
|
||||
meta/psx_str_mgav.o \
|
||||
meta/ngc_bo2.o \
|
||||
meta/ngc_dsp_mpds.o \
|
||||
meta/ps2_khv.o \
|
||||
meta/ps2_voi.o \
|
||||
meta/dsp_sth_str.o \
|
||||
meta/ps2_b1s.o \
|
||||
meta/ps2_wad.o \
|
||||
meta/ps2_voi.o \
|
||||
meta/ps2_lpcm.o \
|
||||
meta/ps2_adm.o \
|
||||
meta/dsp_bdsp.o \
|
||||
meta/ps2_vms.o \
|
||||
meta/ps2_xau.o \
|
||||
meta/gh3_bar.o \
|
||||
meta/ffw.o \
|
||||
meta/ps2_jstm.o \
|
||||
meta/ps3_xvag.o \
|
||||
meta/ps3_cps.o \
|
||||
meta/sqex_scd.o \
|
||||
meta/ngc_nst_dsp.o \
|
||||
meta/baf.o \
|
||||
meta/ps3_msf.o \
|
||||
meta/nub_vag.o \
|
||||
meta/ps3_past.o \
|
||||
meta/sgxd.o \
|
||||
meta/ngca.o \
|
||||
meta/wii_ras.o \
|
||||
meta/ps2_spm.o \
|
||||
meta/ps2_mtaf.o \
|
||||
meta/x360_tra.o \
|
||||
meta/ps2_iab.o \
|
||||
meta/ps2_strlr.o \
|
||||
meta/lsf.o \
|
||||
meta/vawx.o \
|
||||
meta/pc_snds.o \
|
||||
meta/ps2_wmus.o \
|
||||
meta/mattel_hyperscan.o \
|
||||
meta/ios_psnd.o \
|
||||
meta/pc_adp.o \
|
||||
meta/excitebots.o \
|
||||
meta/ps3_klbs.o \
|
||||
meta/ps2_mtaf.o \
|
||||
meta/tun.o \
|
||||
meta/wpd.o \
|
||||
meta/mn_str.o \
|
||||
meta/ps2_mss.o \
|
||||
meta/ps2_hsf.o \
|
||||
meta/ps3_ivag.o \
|
||||
meta/ps2_2pfs.o \
|
||||
meta/ubi_ckd.o \
|
||||
meta/ps2_vbk.o \
|
||||
meta/otm.o \
|
||||
meta/bcstm.o \
|
||||
meta/bfstm.o \
|
||||
meta/bfwav.o \
|
||||
meta/g1l.o \
|
||||
meta/mca.o \
|
||||
meta/btsnd.o \
|
||||
meta/hca.o \
|
||||
meta/ps2_svag_snk.o \
|
||||
meta/ffmpeg.o \
|
||||
meta/mp4.o \
|
||||
meta/xma.o \
|
||||
meta/ps2_vds_vdm.o \
|
||||
meta/x360_cxs.o \
|
||||
meta/dsp_adx.o \
|
||||
meta/bik.o \
|
||||
meta/akb.o \
|
||||
meta/x360_ast.o \
|
||||
meta/wwise.o \
|
||||
meta/ubi_raki.o \
|
||||
meta/x360_nub.o \
|
||||
meta/x360_pasx.o \
|
||||
meta/sxd.o \
|
||||
meta/ogl.o
|
||||
LAYOUT_SRCS = $(wildcard layout/*.c)
|
||||
LAYOUT_OBJS = $(patsubst %.c,%.o,$(LAYOUT_SRCS))
|
||||
|
||||
EXT_LIBS = ../ext_libs/clHCA.o
|
||||
META_SRCS = $(wildcard meta/*.c)
|
||||
META_OBJS = $(patsubst %.c,%.o,$(META_SRCS))
|
||||
|
||||
OBJECTS=vgmstream.o streamfile.o util.o formats.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS) $(EXT_LIBS)
|
||||
EXT_LIBS_SRCS = $(wildcard ../ext_libs/*.c)
|
||||
EXT_LIBS_OBJS = $(patsubst %.c,%.o,$(EXT_LIBS_SRCS))
|
||||
|
||||
OBJECTS = $(SRC_OBJS) $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS) $(EXT_LIBS_OBJS)
|
||||
|
||||
libvgmstream.a: $(OBJECTS)
|
||||
$(AR) crs libvgmstream.a $(OBJECTS)
|
||||
|
@ -35,5 +35,6 @@ libcoding_la_SOURCES += fsb_vorbis_decoder.c
|
||||
libcoding_la_SOURCES += wwise_vorbis_decoder.c
|
||||
libcoding_la_SOURCES += wwise_vorbis_utils.c
|
||||
libcoding_la_SOURCES += ogl_vorbis_decoder.c
|
||||
libcoding_la_SOURCES += mc3_decoder.c
|
||||
|
||||
EXTRA_DIST = coding.h g72x_state.h clHCA.h
|
||||
|
@ -1,12 +1,10 @@
|
||||
#include "../vgmstream.h"
|
||||
|
||||
#ifdef VGM_USE_MAIATRAC3PLUS
|
||||
#include "maiatrac3plus.h"
|
||||
#include "coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
void decode_at3plus(VGMSTREAM * vgmstream,
|
||||
sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
|
||||
#ifdef VGM_USE_MAIATRAC3PLUS
|
||||
#include "maiatrac3plus.h"
|
||||
|
||||
void decode_at3plus(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
|
||||
VGMSTREAMCHANNEL *ch = &vgmstream->ch[0];
|
||||
maiatrac3plus_codec_data *data = vgmstream->codec_data;
|
||||
int i;
|
||||
@ -37,4 +35,31 @@ void decode_at3plus(VGMSTREAM * vgmstream,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reset_at3plus(VGMSTREAM *vgmstream) {
|
||||
maiatrac3plus_codec_data *data = vgmstream->codec_data;
|
||||
|
||||
if (data->handle)
|
||||
Atrac3plusDecoder_closeContext(data->handle);
|
||||
data->handle = Atrac3plusDecoder_openContext();
|
||||
data->samples_discard = 0;
|
||||
}
|
||||
|
||||
void seek_at3plus(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||
int blocks_to_skip = num_sample / 2048;
|
||||
int samples_to_discard = num_sample % 2048;
|
||||
maiatrac3plus_codec_data *data = (maiatrac3plus_codec_data *)(vgmstream->codec_data);
|
||||
vgmstream->loop_ch[0].offset =
|
||||
vgmstream->loop_ch[0].channel_start_offset +
|
||||
vgmstream->interleave_block_size * blocks_to_skip;
|
||||
data->samples_discard = samples_to_discard;
|
||||
}
|
||||
|
||||
void free_at3plus(maiatrac3plus_codec_data *data) {
|
||||
if (data) {
|
||||
if (data->handle) Atrac3plusDecoder_closeContext(data->handle);
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -77,7 +77,6 @@ void decode_maxis_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspaci
|
||||
/* sdx2_decoder */
|
||||
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
/* sdx2_decoder */
|
||||
void decode_cbd2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
|
||||
@ -113,79 +112,93 @@ void decode_lsf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
|
||||
/* mtaf_decoder */
|
||||
void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int channels);
|
||||
|
||||
/* mc3_decoder */
|
||||
void decode_mc3(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
|
||||
/* hca_decoder */
|
||||
void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
|
||||
void reset_hca(VGMSTREAM *vgmstream);
|
||||
void loop_hca(VGMSTREAM *vgmstream);
|
||||
void free_hca(hca_codec_data * data);
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
/* ogg_vorbis_decoder */
|
||||
void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
void reset_ogg_vorbis(VGMSTREAM *vgmstream);
|
||||
void seek_ogg_vorbis(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||
void free_ogg_vorbis(ogg_vorbis_codec_data *data);
|
||||
|
||||
/* fsb_vorbis_decoder */
|
||||
vorbis_codec_data * init_fsb_vorbis_codec_data(STREAMFILE *streamfile, off_t start_offset, int channels, int sample_rate, uint32_t setup_id);
|
||||
void decode_fsb_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
|
||||
void free_fsb_vorbis(vorbis_codec_data *data);
|
||||
void reset_fsb_vorbis(VGMSTREAM *vgmstream);
|
||||
void seek_fsb_vorbis(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||
void free_fsb_vorbis(vorbis_codec_data *data);
|
||||
|
||||
/* wwise_vorbis_decoder */
|
||||
vorbis_codec_data * init_wwise_vorbis_codec_data(STREAMFILE *streamfile, off_t start_offset, int channels, int sample_rate, int blocksize_0_exp, int blocksize_1_exp,
|
||||
wwise_setup_type setup_type, wwise_header_type header_type, wwise_packet_type packet_type, int big_endian);
|
||||
void decode_wwise_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
|
||||
void free_wwise_vorbis(vorbis_codec_data *data);
|
||||
void reset_wwise_vorbis(VGMSTREAM *vgmstream);
|
||||
void seek_wwise_vorbis(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||
void free_wwise_vorbis(vorbis_codec_data *data);
|
||||
|
||||
/* ogl_vorbis_decoder */
|
||||
vorbis_codec_data * init_ogl_vorbis_codec_data(STREAMFILE *streamFile, off_t start_offset, off_t * data_start_offset);
|
||||
void decode_ogl_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
|
||||
void free_ogl_vorbis(vorbis_codec_data *data);
|
||||
void reset_ogl_vorbis(VGMSTREAM *vgmstream);
|
||||
void seek_ogl_vorbis(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||
void free_ogl_vorbis(vorbis_codec_data *data);
|
||||
#endif
|
||||
|
||||
/* mpeg_decoder */
|
||||
#ifdef VGM_USE_MPEG
|
||||
/* mpeg_decoder */
|
||||
mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, coding_t *coding_type, int channels);
|
||||
mpeg_codec_data *init_mpeg_codec_data_interleaved(STREAMFILE *streamfile, off_t start_offset, coding_t *coding_type, int channels, int fixed_frame_size, int fsb_padding);
|
||||
mpeg_codec_data *init_mpeg_codec_data_ahx(STREAMFILE *streamFile, off_t start_offset, int channel_count);
|
||||
|
||||
void decode_mpeg(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL * stream, mpeg_codec_data * data, sample * outbuf, int32_t samples_to_do);
|
||||
|
||||
void free_mpeg(mpeg_codec_data *data);
|
||||
void reset_mpeg(VGMSTREAM *vgmstream);
|
||||
void seek_mpeg(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||
void free_mpeg(mpeg_codec_data *data);
|
||||
|
||||
long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data *data);
|
||||
void mpeg_set_error_logging(mpeg_codec_data * data, int enable);
|
||||
#endif
|
||||
|
||||
/* g7221_decoder */
|
||||
#ifdef VGM_USE_G7221
|
||||
/* g7221_decoder */
|
||||
void decode_g7221(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
|
||||
void reset_g7221(VGMSTREAM *vgmstream);
|
||||
void free_g7221(VGMSTREAM *vgmstream);
|
||||
#endif
|
||||
|
||||
/* g719_decoder */
|
||||
#ifdef VGM_USE_G719
|
||||
/* g719_decoder */
|
||||
void decode_g719(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
|
||||
void reset_g719(VGMSTREAM *vgmstream);
|
||||
void free_g719(VGMSTREAM *vgmstream);
|
||||
#endif
|
||||
|
||||
/* mp4_aac_decoder */
|
||||
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
||||
/* mp4_aac_decoder */
|
||||
void decode_mp4_aac(mp4_aac_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
void reset_mp4_aac(VGMSTREAM *vgmstream);
|
||||
void seek_mp4_aac(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||
void free_mp4_aac(mp4_aac_codec_data * data);
|
||||
#endif
|
||||
|
||||
/* at3_decoder */
|
||||
#ifdef VGM_USE_MAIATRAC3PLUS
|
||||
/* at3_decoder */
|
||||
void decode_at3plus(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
|
||||
void reset_at3plus(VGMSTREAM *vgmstream);
|
||||
void seek_at3plus(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||
void free_at3plus(maiatrac3plus_codec_data *data);
|
||||
#endif
|
||||
|
||||
/* ffmpeg_decoder */
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
/* ffmpeg_decoder */
|
||||
void decode_ffmpeg(VGMSTREAM *stream, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
void reset_ffmpeg(VGMSTREAM *vgmstream);
|
||||
void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||
|
@ -1,12 +1,10 @@
|
||||
#include "../vgmstream.h"
|
||||
|
||||
#ifdef VGM_USE_G719
|
||||
#include "coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
#ifdef VGM_USE_G719
|
||||
#include "../stack_alloc.h"
|
||||
|
||||
void decode_g719(VGMSTREAM * vgmstream,
|
||||
sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
|
||||
void decode_g719(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
|
||||
VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel];
|
||||
g719_codec_data *data = vgmstream->codec_data;
|
||||
g719_codec_data *ch_data = &data[channel];
|
||||
@ -26,4 +24,30 @@ void decode_g719(VGMSTREAM * vgmstream,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reset_g719(VGMSTREAM *vgmstream) {
|
||||
g719_codec_data *data = vgmstream->codec_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++)
|
||||
{
|
||||
g719_reset(data[i].handle);
|
||||
}
|
||||
}
|
||||
|
||||
void free_g719(VGMSTREAM *vgmstream) {
|
||||
g719_codec_data *data = (g719_codec_data *) vgmstream->codec_data;
|
||||
|
||||
if (data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++)
|
||||
{
|
||||
g719_free(data[i].handle);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,11 +1,9 @@
|
||||
#include "../vgmstream.h"
|
||||
|
||||
#ifdef VGM_USE_G7221
|
||||
#include "coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
void decode_g7221(VGMSTREAM * vgmstream,
|
||||
sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
|
||||
#ifdef VGM_USE_G7221
|
||||
|
||||
void decode_g7221(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
|
||||
VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel];
|
||||
g7221_codec_data *data = vgmstream->codec_data;
|
||||
g7221_codec_data *ch_data = &data[channel];
|
||||
@ -24,4 +22,30 @@ void decode_g7221(VGMSTREAM * vgmstream,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reset_g7221(VGMSTREAM *vgmstream) {
|
||||
g7221_codec_data *data = vgmstream->codec_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++)
|
||||
{
|
||||
g7221_reset(data[i].handle);
|
||||
}
|
||||
}
|
||||
|
||||
void free_g7221(VGMSTREAM *vgmstream) {
|
||||
g7221_codec_data *data = (g7221_codec_data *) vgmstream->codec_data;
|
||||
|
||||
if (data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++)
|
||||
{
|
||||
g7221_free(data[i].handle);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "../vgmstream.h"
|
||||
#include "coding.h"
|
||||
|
||||
void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels) {
|
||||
int samples_done = 0;
|
||||
@ -80,3 +80,29 @@ void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do, i
|
||||
|
||||
free( hca_data );
|
||||
}
|
||||
|
||||
|
||||
void reset_hca(VGMSTREAM *vgmstream) {
|
||||
hca_codec_data *data = vgmstream->codec_data;
|
||||
/*clHCA *hca = (clHCA *)(data + 1);*/
|
||||
data->curblock = 0;
|
||||
data->sample_ptr = clHCA_samplesPerBlock;
|
||||
data->samples_discard = 0;
|
||||
}
|
||||
|
||||
void loop_hca(VGMSTREAM *vgmstream) {
|
||||
hca_codec_data *data = (hca_codec_data *)(vgmstream->codec_data);
|
||||
data->curblock = data->info.loopStart;
|
||||
data->sample_ptr = clHCA_samplesPerBlock;
|
||||
data->samples_discard = 0;
|
||||
}
|
||||
|
||||
void free_hca(hca_codec_data * data) {
|
||||
if (data) {
|
||||
clHCA *hca = (clHCA *)(data + 1);
|
||||
clHCA_done(hca);
|
||||
if (data->streamfile)
|
||||
close_streamfile(data->streamfile);
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
183
src/coding/mc3_decoder.c
Normal file
183
src/coding/mc3_decoder.c
Normal file
@ -0,0 +1,183 @@
|
||||
#include "coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
|
||||
static const int step_table[4] = {
|
||||
5, 1, -1, -3
|
||||
};
|
||||
|
||||
static const int mc3_table[4][4][64] = {
|
||||
{
|
||||
{
|
||||
2, 2, 3, 7, 15, 27, 45, 70, 104, 148, 202, 268, 347, 441, 551, 677,
|
||||
821, 984, 1168, 1374, 1602, 1854, 2131, 2435, 2767, 3127, 3517, 3938, 4392, 4880, 5402, 5960,
|
||||
6555, 7189, 7862, 8577, 9333, 10132, 10976, 11865, 12802, 13786, 14819, 15903, 17038, 18226, 19469, 20766,
|
||||
22120, 23531, 25001, 26531, 28123, 29776, 31494, 33276, 35124, 37039, 39023, 41076, 43201, 45397, 47666, 50010
|
||||
},
|
||||
{
|
||||
1, 1, 2, 5, 10, 18, 31, 48, 72, 101, 139, 184, 239, 303, 378, 465,
|
||||
564, 677, 803, 944, 1101, 1274, 1465, 1674, 1902, 2150, 2418, 2707, 3019, 3355, 3714, 4097,
|
||||
4507, 4942, 5405, 5896, 6416, 6966, 7546, 8157, 8801, 9477, 10188, 10933, 11714, 12530, 13384, 14276,
|
||||
15207, 16177, 17188, 18240, 19334, 20471, 21652, 22877, 24148, 25464, 26828, 28240, 29700, 31210, 32770, 34382
|
||||
},
|
||||
{
|
||||
0, 0, 1, 2, 4, 8, 14, 22, 32, 46, 63, 83, 108, 138, 172, 211,
|
||||
256, 307, 365, 429, 500, 579, 666, 761, 864, 977, 1099, 1230, 1372, 1525, 1688, 1862,
|
||||
2048, 2246, 2457, 2680, 2916, 3166, 3430, 3708, 4000, 4308, 4631, 4969, 5324, 5695, 6084, 6489,
|
||||
6912, 7353, 7813, 8291, 8788, 9305, 9841, 10398, 10976, 11574, 12194, 12836, 13500, 14186, 14895, 15628
|
||||
},
|
||||
{
|
||||
0, 0, 0, 0, 1, 3, 5, 8, 13, 18, 25, 33, 43, 55, 68, 84,
|
||||
102, 123, 146, 171, 200, 231, 266, 304, 345, 390, 439, 492, 549, 610, 675, 745,
|
||||
819, 898, 982, 1072, 1166, 1266, 1372, 1483, 1600, 1723, 1852, 1987, 2129, 2278, 2433, 2595,
|
||||
2765, 2941, 3125, 3316, 3515, 3722, 3936, 4159, 4390, 4629, 4877, 5134, 5400, 5674, 5958, 6251
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
1, 1, 2, 4, 9, 17, 28, 44, 65, 92, 126, 167, 217, 276, 344, 423,
|
||||
513, 615, 730, 858, 1001, 1159, 1332, 1522, 1729, 1954, 2198, 2461, 2745, 3050, 3376, 3725,
|
||||
4097, 4493, 4914, 5360, 5833, 6332, 6860, 7416, 8001, 8616, 9262, 9939, 10649, 11391, 12168, 12978,
|
||||
13825, 14707, 15626, 16582, 17576, 18610, 19683, 20797, 21952, 23149, 24389, 25673, 27000, 28373, 29791, 31256
|
||||
},
|
||||
{
|
||||
0, 0, 1, 2, 5, 10, 17, 26, 39, 55, 75, 100, 130, 165, 206, 254,
|
||||
308, 369, 438, 515, 600, 695, 799, 913, 1037, 1172, 1319, 1477, 1647, 1830, 2025, 2235,
|
||||
2458, 2696, 2948, 3216, 3499, 3799, 4116, 4449, 4800, 5169, 5557, 5963, 6389, 6835, 7300, 7787,
|
||||
8295, 8824, 9375, 9949, 10546, 11166, 11810, 12478, 13171, 13889, 14633, 15403, 16200, 17023, 17874, 18753
|
||||
},
|
||||
{
|
||||
0, 0, 0, 1, 3, 6, 11, 17, 26, 37, 50, 67, 86, 110, 137, 169,
|
||||
205, 246, 292, 343, 400, 463, 532, 608, 691, 781, 879, 984, 1098, 1220, 1350, 1490,
|
||||
1638, 1797, 1965, 2144, 2333, 2533, 2744, 2966, 3200, 3446, 3704, 3975, 4259, 4556, 4867, 5191,
|
||||
5530, 5882, 6250, 6632, 7030, 7444, 7873, 8319, 8781, 9259, 9755, 10269, 10800, 11349, 11916, 12502
|
||||
},
|
||||
{
|
||||
0, 0, 0, 0, 0, 1, 2, 4, 6, 9, 12, 16, 21, 27, 34, 42,
|
||||
51, 61, 73, 85, 100, 115, 133, 152, 172, 195, 219, 246, 274, 305, 337, 372,
|
||||
409, 449, 491, 536, 583, 633, 686, 741, 800, 861, 926, 993, 1064, 1139, 1216, 1297,
|
||||
1382, 1470, 1562, 1658, 1757, 1861, 1968, 2079, 2195, 2314, 2438, 2567, 2700, 2837, 2979, 3125
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
1, 1, 2, 5, 10, 18, 31, 48, 72, 101, 139, 184, 239, 303, 378, 465,
|
||||
564, 677, 803, 944, 1101, 1274, 1465, 1674, 1902, 2150, 2418, 2707, 3019, 3355, 3714, 4097,
|
||||
4507, 4942, 5405, 5896, 6416, 6966, 7546, 8157, 8801, 9477, 10188, 10933, 11714, 12530, 13384, 14276,
|
||||
15207, 16177, 17188, 18240, 19334, 20471, 21652, 22877, 24148, 25464, 26828, 28240, 29700, 31210, 32770, 34382
|
||||
},
|
||||
{
|
||||
1, 1, 1, 3, 7, 13, 22, 35, 52, 74, 101, 134, 173, 220, 275, 338,
|
||||
410, 492, 584, 687, 801, 927, 1065, 1217, 1383, 1563, 1758, 1969, 2196, 2440, 2701, 2980,
|
||||
3277, 3594, 3931, 4288, 4666, 5066, 5488, 5932, 6401, 6893, 7409, 7951, 8519, 9113, 9734, 10383,
|
||||
11060, 11765, 12500, 13265, 14061, 14888, 15747, 16638, 17562, 18519, 19511, 20538, 21600, 22698, 23833, 25005
|
||||
},
|
||||
{
|
||||
0, 0, 1, 2, 4, 8, 14, 22, 32, 46, 63, 83, 108, 138, 172, 211,
|
||||
256, 307, 365, 429, 500, 579, 666, 761, 864, 977, 1099, 1230, 1372, 1525, 1688, 1862,
|
||||
2048, 2246, 2457, 2680, 2916, 3166, 3430, 3708, 4000, 4308, 4631, 4969, 5324, 5695, 6084, 6489,
|
||||
6912, 7353, 7813, 8291, 8788, 9305, 9841, 10398, 10976, 11574, 12194, 12836, 13500, 14186, 14895, 15628
|
||||
},
|
||||
{
|
||||
0, 0, 0, 1, 2, 5, 8, 13, 19, 27, 37, 50, 65, 82, 103, 127,
|
||||
154, 184, 219, 257, 300, 347, 399, 456, 518, 586, 659, 738, 823, 915, 1012, 1117,
|
||||
1229, 1348, 1474, 1608, 1749, 1899, 2058, 2224, 2400, 2584, 2778, 2981, 3194, 3417, 3650, 3893,
|
||||
4147, 4412, 4687, 4974, 5273, 5583, 5905, 6239, 6585, 6944, 7316, 7701, 8100, 8511, 8937, 9376
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
1, 1, 2, 5, 11, 20, 34, 53, 78, 111, 151, 201, 260, 331, 413, 508,
|
||||
616, 738, 876, 1030, 1201, 1390, 1598, 1826, 2075, 2345, 2638, 2954, 3294, 3660, 4051, 4470,
|
||||
4916, 5392, 5897, 6432, 6999, 7599, 8232, 8899, 9601, 10339, 11114, 11927, 12779, 13670, 14601, 15574,
|
||||
16590, 17648, 18751, 19898, 21092, 22332, 23620, 24957, 26343, 27779, 29267, 30807, 32400, 34047, 35749, 37507
|
||||
},
|
||||
{
|
||||
1, 1, 1, 3, 6, 11, 19, 31, 45, 64, 88, 117, 152, 193, 241, 296,
|
||||
359, 430, 511, 601, 701, 811, 932, 1065, 1210, 1368, 1538, 1723, 1921, 2135, 2363, 2607,
|
||||
2868, 3145, 3440, 3752, 4083, 4433, 4802, 5191, 5600, 6031, 6483, 6957, 7454, 7974, 8517, 9085,
|
||||
9677, 10295, 10938, 11607, 12303, 13027, 13778, 14558, 15366, 16204, 17072, 17971, 18900, 19861, 20854, 21879
|
||||
},
|
||||
{
|
||||
0, 0, 0, 1, 2, 5, 8, 13, 19, 27, 37, 50, 65, 82, 103, 127,
|
||||
154, 184, 219, 257, 300, 347, 399, 456, 518, 586, 659, 738, 823, 915, 1012, 1117,
|
||||
1229, 1348, 1474, 1608, 1749, 1899, 2058, 2224, 2400, 2584, 2778, 2981, 3194, 3417, 3650, 3893,
|
||||
4147, 4412, 4687, 4974, 5273, 5583, 5905, 6239, 6585, 6944, 7316, 7701, 8100, 8511, 8937, 9376
|
||||
},
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* MC3 3-bit ADPCM (Paradigm Entertainment games).
|
||||
*
|
||||
* Layout: blocks with 32b header + 32b ch1, 32b ch2, 32b ch1...
|
||||
* Each 32b is a sub-block with 10 samples (3b x10) sharing a 'mode' of sorts.
|
||||
* More than one block is rarely used though.
|
||||
*
|
||||
* Tables and original algorithm by daemon1
|
||||
*/
|
||||
void decode_mc3(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
int i, sample_count = 0;
|
||||
|
||||
int32_t hist = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
||||
/* internal interleave */
|
||||
int block_samples = (vgmstream->interleave_block_size - 4) / 4 / vgmstream->channels * 10;
|
||||
first_sample = first_sample % block_samples;
|
||||
|
||||
|
||||
/* block header */
|
||||
if (first_sample == 0) {
|
||||
uint32_t header = (uint32_t)read_32bitLE(stream->offset, stream->streamfile);
|
||||
header = (header >> channel*16); /* lower 16=ch1, upper 16b=ch2 */
|
||||
step_index = header & 0x3f; /* 6b */
|
||||
hist = header & 0xffc0; /* 16b sans 6b */
|
||||
if (hist > 0x7fff) hist -= 0x10000; /* sign extend */
|
||||
}
|
||||
|
||||
|
||||
/* block samples */
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
||||
uint32_t subblock, mode, samples, index, sign, diff;
|
||||
|
||||
/* header + ch shift + sub-block number (ex. ch0 i=10: sub-block 1, ch0 i=23: sub-block 2) */
|
||||
off_t subblock_offset = stream->offset + 4 + 4*channel + (i/10)*(4*vgmstream->channels);
|
||||
int sample_shift = (i%10)*3;
|
||||
|
||||
/* expand 3b */
|
||||
subblock = (uint32_t)read_32bitLE(subblock_offset, stream->streamfile);
|
||||
mode = (subblock >> 30) & 0x3; /* upper 2b */
|
||||
samples = (subblock) & 0x3FFFFFFF; /* lower 3b*10 */
|
||||
|
||||
index = (samples >> sample_shift) & 3; /* lower 2b */
|
||||
sign = (samples >> sample_shift) & 4; /* upper 1b */
|
||||
diff = mc3_table[mode][index][step_index];
|
||||
if (sign == 0)
|
||||
hist += (- 1 - diff);
|
||||
else
|
||||
hist += diff;
|
||||
|
||||
/* new step + clamp */
|
||||
step_index += step_table[index];
|
||||
if (step_index < 0) step_index = 0;
|
||||
else if (step_index > 63) step_index = 63;
|
||||
|
||||
/* output */
|
||||
outbuf[sample_count] = hist;
|
||||
sample_count += channelspacing;
|
||||
}
|
||||
|
||||
|
||||
/* internal interleave: increment offset on complete frame */
|
||||
if (i == block_samples) stream->offset += vgmstream->interleave_block_size;
|
||||
|
||||
stream->adpcm_history1_32 = hist;
|
||||
stream->adpcm_step_index = step_index;
|
||||
}
|
@ -82,4 +82,29 @@ void decode_mp4_aac(mp4_aac_codec_data * data, sample * outbuf, int32_t samples_
|
||||
data->sample_ptr = samples_remain;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reset_mp4_aac(VGMSTREAM *vgmstream) {
|
||||
mp4_aac_codec_data *data = vgmstream->codec_data;
|
||||
data->sampleId = 0;
|
||||
data->sample_ptr = data->samples_per_frame;
|
||||
data->samples_discard = 0;
|
||||
}
|
||||
|
||||
void seek_mp4_aac(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||
mp4_aac_codec_data *data = (mp4_aac_codec_data *)(vgmstream->codec_data);
|
||||
data->sampleId = 0;
|
||||
data->sample_ptr = data->samples_per_frame;
|
||||
data->samples_discard = num_sample;
|
||||
}
|
||||
|
||||
void free_mp4_aac(mp4_aac_codec_data * data) {
|
||||
if (data) {
|
||||
if (data->h_aacdecoder) aacDecoder_Close(data->h_aacdecoder);
|
||||
if (data->h_mp4file) MP4Close(data->h_mp4file, 0);
|
||||
if (data->if_file.streamfile) close_streamfile(data->if_file.streamfile);
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,9 +1,8 @@
|
||||
#include "../vgmstream.h"
|
||||
#include "coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
#include <vorbis/vorbisfile.h>
|
||||
#include "coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels) {
|
||||
int samples_done = 0;
|
||||
@ -21,4 +20,30 @@ void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t sa
|
||||
swap_samples_le(outbuf, samples_to_do*channels);
|
||||
}
|
||||
|
||||
|
||||
void reset_ogg_vorbis(VGMSTREAM *vgmstream) {
|
||||
ogg_vorbis_codec_data *data = vgmstream->codec_data;
|
||||
OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file);
|
||||
|
||||
ov_pcm_seek(ogg_vorbis_file, 0);
|
||||
}
|
||||
|
||||
void seek_ogg_vorbis(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||
ogg_vorbis_codec_data *data = (ogg_vorbis_codec_data *)(vgmstream->codec_data);
|
||||
OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file);
|
||||
|
||||
ov_pcm_seek_lap(ogg_vorbis_file, num_sample);
|
||||
}
|
||||
|
||||
void free_ogg_vorbis(ogg_vorbis_codec_data *data) {
|
||||
if (!data) {
|
||||
OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file);
|
||||
|
||||
ov_clear(ogg_vorbis_file);
|
||||
|
||||
close_streamfile(data->ov_streamfile.streamfile);
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -149,6 +149,7 @@ static const char* extension_list[] = {
|
||||
"lwav", //fake extension, for looping
|
||||
|
||||
"matx",
|
||||
"mc3",
|
||||
"mca",
|
||||
"mcg",
|
||||
"mds",
|
||||
@ -403,7 +404,7 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_HEVAG, "Playstation Vita HEVAG 4-bit ADPCM"},
|
||||
{coding_XA, "CD-ROM XA 4-bit ADPCM"},
|
||||
{coding_XBOX, "XBOX 4-bit IMA ADPCM"},
|
||||
{coding_INT_XBOX, "XBOX 4-bit IMA ADPCM (interleaved)"},
|
||||
{coding_XBOX_int, "XBOX 4-bit IMA ADPCM (interleaved)"},
|
||||
{coding_EA_XA, "Electronic Arts 4-bit ADPCM (XA based)"},
|
||||
{coding_EA_ADPCM, "Electronic Arts R1 4-bit ADPCM (XA based)"},
|
||||
{coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"},
|
||||
@ -411,20 +412,20 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"},
|
||||
{coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"},
|
||||
{coding_DVI_IMA, "Intel DVI 4-bit IMA ADPCM"},
|
||||
{coding_INT_DVI_IMA, "Interleaved Intel DVI 4-bit IMA ADPCM"},
|
||||
{coding_DVI_IMA_int, "Intel DVI 4-bit IMA ADPCM (interleaved)"},
|
||||
{coding_EACS_IMA, "EACS 4-bit IMA ADPCM"},
|
||||
{coding_MAXIS_ADPCM, "Maxis XA (EA ADPCM Variant)"},
|
||||
{coding_INT_IMA, "Interleaved 4-bit IMA ADPCM"},
|
||||
{coding_IMA, "4-bit IMA ADPCM"},
|
||||
{coding_IMA_int, "IMA 4-bit ADPCM (interleaved)"},
|
||||
{coding_IMA, "IMA 4-bit ADPCM"},
|
||||
{coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"},
|
||||
{coding_RAD_IMA, "'Radical' 4-bit IMA ADPCM"},
|
||||
{coding_RAD_IMA_mono, "'Radical' 4-bit IMA ADPCM (mono)"},
|
||||
{coding_RAD_IMA, "Radical 4-bit IMA ADPCM"},
|
||||
{coding_RAD_IMA_mono, "Radical 4-bit IMA ADPCM (mono)"},
|
||||
{coding_APPLE_IMA4, "Apple Quicktime 4-bit IMA ADPCM"},
|
||||
{coding_SNDS_IMA, "Heavy Iron .snds 4-bit IMA ADPCM"},
|
||||
{coding_OTNS_IMA, "Omikron: The Nomad Soul 4-bit IMA ADPCM"},
|
||||
{coding_FSB_IMA, "FSB multichannel 4-bit IMA ADPCM"},
|
||||
{coding_WWISE_IMA, "Audiokinetic Wwise 4-bit IMA ADPCM"},
|
||||
{coding_WS, "Westwood Studios ADPCM"},
|
||||
{coding_WS, "Westwood Studios VBR ADPCM"},
|
||||
{coding_ACM, "InterPlay ACM"},
|
||||
{coding_NWA0, "NWA DPCM Level 0"},
|
||||
{coding_NWA1, "NWA DPCM Level 1"},
|
||||
@ -439,6 +440,8 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"},
|
||||
{coding_LSF, "lsf 4-bit ADPCM"},
|
||||
{coding_MTAF, "Konami MTAF 4-bit ADPCM"},
|
||||
{coding_MC3, "Paradigm MC3 3-bit ADPCM"},
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
{coding_ogg_vorbis, "Ogg Vorbis"},
|
||||
{coding_fsb_vorbis, "FSB Vorbis"},
|
||||
@ -847,6 +850,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_UBI_RAKI, "Ubisoft RAKI header"},
|
||||
{meta_SXD, "Sony SXD header"},
|
||||
{meta_OGL, "Shin'en OGL header"},
|
||||
{meta_MC3, "Paradigm MC3 header"},
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
{meta_OGG_VORBIS, "Ogg Vorbis"},
|
||||
|
@ -444,6 +444,10 @@
|
||||
RelativePath=".\meta\maxis_xa.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\mc3.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\mca.c"
|
||||
>
|
||||
@ -1330,6 +1334,10 @@
|
||||
RelativePath=".\coding\lsf_decoder.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\mc3_decoder.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\mpeg_decoder.c"
|
||||
>
|
||||
|
@ -225,6 +225,7 @@
|
||||
<ClCompile Include="meta\ivb.c" />
|
||||
<ClCompile Include="meta\kraw.c" />
|
||||
<ClCompile Include="meta\maxis_xa.c" />
|
||||
<ClCompile Include="meta\mc3.c" />
|
||||
<ClCompile Include="meta\mca.c" />
|
||||
<ClCompile Include="meta\msvp.c" />
|
||||
<ClCompile Include="meta\mus_acm.c">
|
||||
@ -412,6 +413,7 @@
|
||||
<ClCompile Include="coding\hca_decoder.c" />
|
||||
<ClCompile Include="coding\ima_decoder.c" />
|
||||
<ClCompile Include="coding\l5_555_decoder.c" />
|
||||
<ClCompile Include="coding\mc3_decoder.c" />
|
||||
<ClCompile Include="coding\mpeg_decoder.c" />
|
||||
<ClCompile Include="coding\msadpcm_decoder.c" />
|
||||
<ClCompile Include="coding\nds_procyon_decoder.c" />
|
||||
|
@ -247,6 +247,9 @@
|
||||
<ClCompile Include="meta\maxis_xa.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\mc3.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\mca.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -781,6 +784,9 @@
|
||||
<ClCompile Include="coding\l5_555_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\mc3_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\mpeg_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1,69 +0,0 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* 2DX (found in beatmaniaIIDX16 - EMPRESS (Arcade) */
|
||||
VGMSTREAM * init_vgmstream_2dx(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("2dx",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x0,streamFile) != 0x32445839) /* 2DX9 */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x18,streamFile) != 0x52494646) /* RIFF */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x20,streamFile) != 0x57415645) /* WAVE */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x24,streamFile) != 0x666D7420) /* fmt */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x6a,streamFile) != 0x64617461) /* data */
|
||||
goto fail;
|
||||
|
||||
loop_flag = 0;
|
||||
channel_count = read_16bitLE(0x2e,streamFile);
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = 0x72;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(0x30,streamFile);
|
||||
vgmstream->coding_type = coding_MSADPCM;
|
||||
vgmstream->num_samples = read_32bitLE(0x66,streamFile);
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = read_16bitLE(0x38,streamFile);
|
||||
vgmstream->meta_type = meta_2DX9;
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
int i;
|
||||
STREAMFILE * file;
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = file;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=start_offset+
|
||||
vgmstream->interleave_block_size*i;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
/* clean up anything we may have opened */
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -260,5 +260,6 @@ libmeta_la_SOURCES += x360_pasx.c
|
||||
libmeta_la_SOURCES += x360_nub.c
|
||||
libmeta_la_SOURCES += sxd.c
|
||||
libmeta_la_SOURCES += ogl.c
|
||||
libmeta_la_SOURCES += mc3.c
|
||||
|
||||
EXTRA_DIST = meta.h
|
||||
|
@ -59,7 +59,7 @@ VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) {
|
||||
start_offset = 0x28;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitBE(0x0c,streamFile);
|
||||
vgmstream->coding_type = coding_INT_XBOX;
|
||||
vgmstream->coding_type = coding_XBOX_int;
|
||||
vgmstream->num_samples = (read_32bitBE(0x24,streamFile) / 36 *64 / vgmstream->channels)-64; // to avoid the "pop" at the loop point
|
||||
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x24;
|
||||
|
@ -36,11 +36,12 @@ fail:
|
||||
/* AKB - found in SQEX iOS games */
|
||||
VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
size_t filesize;
|
||||
off_t start_offset, extra_data_offset = 0;
|
||||
size_t file_size, header_size, extra_header_size = 0, extra_data_size = 0;
|
||||
int loop_flag = 0, channel_count, codec;
|
||||
|
||||
/* check extensions */
|
||||
/* .akb.bytes is the usual extension in later games */
|
||||
if ( !check_extensions(streamFile, "akb") )
|
||||
goto fail;
|
||||
|
||||
@ -49,41 +50,58 @@ VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
|
||||
channel_count = read_8bit(0x0d,streamFile);
|
||||
loop_flag = read_32bitLE(0x18,streamFile) > 0;
|
||||
loop_flag = read_32bitLE(0x18,streamFile) > 0; /* loop end */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* 0x04: version? (iPad/IPhone?) 0x24: file_id? */
|
||||
filesize = read_32bitLE(0x08,streamFile);
|
||||
/* 0x04 (2): version (iPad/IPhone?) */
|
||||
header_size = read_16bitLE(0x06,streamFile);
|
||||
file_size = read_32bitLE(0x08,streamFile);
|
||||
codec = read_8bit(0x0c,streamFile);
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x0e,streamFile);
|
||||
vgmstream->num_samples = read_32bitLE(0x10,streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(0x18,streamFile);
|
||||
/* 0x0c: some size based on codec 0x10+: unk stuff? 0xc0+: data stuff? */
|
||||
vgmstream->loop_end_sample = read_32bitLE(0x18,streamFile);
|
||||
vgmstream->meta_type = meta_AKB;
|
||||
|
||||
/* should be ok but not exact (probably more complex, see AKB2) */
|
||||
if ( header_size >= 0x44) { /* v2 */
|
||||
/* 0x10+: config? (pan, volume), 0x24: file_id? */
|
||||
extra_data_size = read_16bitLE(0x1c,streamFile);
|
||||
extra_header_size = read_16bitLE(0x28,streamFile);
|
||||
extra_data_offset = header_size + extra_header_size;
|
||||
start_offset = extra_data_offset + extra_data_size;
|
||||
/* ~num_samples at extra_data_offset + 0x04/0x0c? */
|
||||
}
|
||||
else { /* v0 */
|
||||
start_offset = header_size;
|
||||
}
|
||||
|
||||
|
||||
switch (codec) {
|
||||
#if 0
|
||||
case 0x02: { /* some kind of ADPCM or PCM [various SFX] */
|
||||
start_offset = 0xC4;
|
||||
vgmstream->coding_type = coding_APPLE_IMA4;
|
||||
vgmstream->layout_type = channel_count==1 ? layout_none : layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x100;
|
||||
case 0x02: { /* MSAPDCM [various SFX] */
|
||||
vgmstream->coding_type = coding_MSADPCM;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = read_16bitLE(extra_data_offset + 0x02,streamFile);
|
||||
|
||||
/* adjusted samples; bigger or smaller than base samples, but seems more accurate
|
||||
* (base samples may have more than possible and read over file size otherwise, very strange)
|
||||
* loop_end seems to exist even with loop disabled */
|
||||
vgmstream->num_samples = read_32bitLE(extra_data_offset + 0x04, streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(extra_data_offset + 0x08, streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(extra_data_offset + 0x0c, streamFile);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 0x05: { /* ogg vorbis [Final Fantasy VI, Dragon Quest II-VI] */
|
||||
case 0x05: { /* Ogg Vorbis [Final Fantasy VI, Dragon Quest II-VI] */
|
||||
/* Starting from an offset in the current libvorbis code is a bit hard so just use FFmpeg.
|
||||
* Decoding seems to produce the same output with (inaudible) +-1 lower byte differences here and there. */
|
||||
* Decoding seems to produce the same output with (inaudible) +-1 lower byte differences due to rounding. */
|
||||
ffmpeg_codec_data *ffmpeg_data;
|
||||
|
||||
start_offset = 0xCC;
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,filesize-start_offset);
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,file_size-start_offset);
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
@ -98,8 +116,7 @@ VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
|
||||
/* init_vgmstream_akb above has priority, but this works fine too */
|
||||
ffmpeg_codec_data *ffmpeg_data;
|
||||
|
||||
start_offset = 0x20;
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,filesize-start_offset);
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,file_size-start_offset);
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
@ -115,7 +132,6 @@ VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* AAC @20 in some cases? (see above) */
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
@ -141,6 +157,7 @@ VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile) {
|
||||
int akb_header_size, sound_index = 0, sound_offset_data, sound, sound_header_size, material_offset_data, material_index = 0, material, extradata, encryption_flag;
|
||||
|
||||
/* check extensions */
|
||||
/* .akb.bytes is the usual extension in later games */
|
||||
if ( !check_extensions(streamFile, "akb") )
|
||||
goto fail;
|
||||
|
||||
@ -161,7 +178,7 @@ VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile) {
|
||||
header_offset = material;
|
||||
|
||||
channel_count = read_8bit(header_offset+0x02,streamFile);
|
||||
loop_flag = read_32bitLE(header_offset+0x14,streamFile) > 0;
|
||||
loop_flag = read_32bitLE(header_offset+0x14,streamFile) > 0; /* loop end */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
@ -175,17 +192,23 @@ VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile) {
|
||||
* Actual num_samples would be loop_end_sample+1, but more testing is needed */
|
||||
vgmstream->num_samples = read_32bitLE(header_offset+0x0c,streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(header_offset+0x10,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(header_offset+0x14,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(header_offset+0x14,streamFile);
|
||||
|
||||
vgmstream->meta_type = meta_AKB;
|
||||
|
||||
switch (codec) {
|
||||
case 0x02: { /* msadpcm [The Irregular at Magic High School Lost Zero (Android)] */
|
||||
case 0x02: { /* MSAPDCM [The Irregular at Magic High School Lost Zero (Android)] */
|
||||
if (encryption_flag) goto fail;
|
||||
vgmstream->num_samples = read_32bitLE(extradata + 0x04, streamFile);
|
||||
vgmstream->coding_type = coding_MSADPCM;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = read_16bitLE(extradata + 0x02, streamFile);
|
||||
|
||||
/* adjusted samples; bigger or smaller than base samples, but seems more accurate
|
||||
* (base samples may have more than possible and read over file size otherwise, very strange)
|
||||
* loop_end seems to exist even with loop disabled */
|
||||
vgmstream->num_samples = read_32bitLE(extradata + 0x04, streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(extradata + 0x08, streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(extradata + 0x0c, streamFile);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) {
|
||||
if (seek_offset == 0) goto fail;
|
||||
if ((uint32_t)read_32bitBE(seek_offset, streamFile) != 0x5345454B) { /* "SEEK" If this header doesn't exist, assuming that the file is IMA */
|
||||
ima = 1;
|
||||
coding_type = coding_INT_IMA;
|
||||
coding_type = coding_IMA_int;
|
||||
}
|
||||
else
|
||||
coding_type = coding_NGC_DSP;
|
||||
|
@ -29,7 +29,7 @@ VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
|
||||
vgmstream->channels = channel_count;
|
||||
start_offset = 0x800;
|
||||
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
|
||||
vgmstream->coding_type = coding_INT_DVI_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile);
|
||||
|
@ -165,17 +165,27 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
||||
{
|
||||
if (coding == coding_SDX2) {
|
||||
coding = coding_SDX2_int;
|
||||
vgmstream->coding_type = coding_SDX2_int;
|
||||
}
|
||||
//todo if 0 do this too (most codecs seem to enter an infinite loop otherwise)
|
||||
if(vgmstream->interleave_block_size==0xffffffff)
|
||||
vgmstream->layout_type=layout_none;
|
||||
|
||||
if (vgmstream->interleave_block_size==0xffffffff) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
else {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
if(coding==coding_DVI_IMA)
|
||||
coding=coding_INT_DVI_IMA;
|
||||
if(coding==coding_IMA)
|
||||
coding=coding_INT_IMA;
|
||||
if (coding == coding_DVI_IMA)
|
||||
coding = coding_DVI_IMA_int;
|
||||
if (coding == coding_IMA)
|
||||
coding = coding_IMA_int;
|
||||
}
|
||||
|
||||
/* to avoid endless loops */
|
||||
if (!interleave && (
|
||||
coding == coding_PSX ||
|
||||
coding == coding_PSX_badflags ||
|
||||
coding == coding_IMA_int ||
|
||||
coding == coding_DVI_IMA_int ||
|
||||
coding == coding_SDX2_int) ) {
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
vgmstream->layout_type = layout_none;
|
||||
@ -191,11 +201,15 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
||||
|
||||
break;
|
||||
case coding_MS_IMA:
|
||||
if (!interleave) goto fail; /* creates garbage */
|
||||
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
case coding_MSADPCM:
|
||||
if (channel_count != 2) goto fail;
|
||||
if (channel_count > 2) goto fail;
|
||||
if (!interleave) goto fail; /* creates garbage */
|
||||
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
@ -208,9 +222,11 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
||||
break;
|
||||
case coding_NGC_DSP:
|
||||
if (dsp_interleave_type == 0) {
|
||||
if (!interleave) goto fail;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
} else if (dsp_interleave_type == 1) {
|
||||
if (!interleave) goto fail;
|
||||
vgmstream->layout_type = layout_interleave_byte;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
} else if (dsp_interleave_type == 2) {
|
||||
|
@ -36,7 +36,7 @@ VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile) {
|
||||
block_table_offset = read_32bitLE(0,streamFile);
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(block_table_offset + 0x04,streamFile);
|
||||
vgmstream->coding_type = coding_INT_IMA;
|
||||
vgmstream->coding_type = coding_IMA_int;
|
||||
|
||||
vgmstream->layout_type = layout_ivaud_blocked;
|
||||
vgmstream->meta_type = meta_PC_IVAUD;
|
||||
|
46
src/meta/mc3.c
Normal file
46
src/meta/mc3.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "meta.h"
|
||||
|
||||
|
||||
/* MC3 - from Paradigm games [Spy Hunter, MX Rider, Terminator 3] */
|
||||
VGMSTREAM * init_vgmstream_mc3(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
if ( !check_extensions(streamFile,"mc3"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4D504333) /* "MPC3" */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x04,streamFile) != 0x00011400) /* version? */
|
||||
goto fail;
|
||||
|
||||
start_offset = 0x1c;
|
||||
loop_flag = 0;
|
||||
channel_count = read_32bitLE(0x08, streamFile);
|
||||
if (channel_count > 2) goto fail; /* not seen, decoder must be adapted */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
vgmstream->coding_type = coding_MC3;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_MC3;
|
||||
|
||||
vgmstream->sample_rate = read_32bitLE(0x0c, streamFile);
|
||||
vgmstream->num_samples = read_32bitLE(0x10, streamFile) * 10; /* sizes in sub-blocks of 10 samples (without headers) */
|
||||
vgmstream->interleave_block_size = (read_32bitLE(0x14, streamFile) * 4 * channel_count) + 4;
|
||||
if (read_32bitLE(0x18, streamFile) + start_offset != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
|
||||
/* open the file for reading */
|
||||
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -686,4 +686,6 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_mc3(STREAMFILE *streamFile);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
@ -28,7 +28,7 @@ VGMSTREAM * init_vgmstream_nds_hwas(STREAMFILE *streamFile) {
|
||||
start_offset = 0x200;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
|
||||
vgmstream->coding_type = coding_INT_IMA;
|
||||
vgmstream->coding_type = coding_IMA_int;
|
||||
vgmstream->num_samples = read_32bitLE(0x14,streamFile);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x10,streamFile);
|
||||
|
@ -27,7 +27,7 @@ VGMSTREAM * init_vgmstream_sadl(STREAMFILE *streamFile) {
|
||||
switch (read_8bit(0x33,streamFile)&0xf0)
|
||||
{
|
||||
case 0x70:
|
||||
coding_type = coding_INT_IMA;
|
||||
coding_type = coding_IMA_int;
|
||||
break;
|
||||
case 0xb0:
|
||||
coding_type = coding_NDS_PROCYON;
|
||||
@ -61,7 +61,7 @@ VGMSTREAM * init_vgmstream_sadl(STREAMFILE *streamFile) {
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
|
||||
if (coding_type == coding_INT_IMA)
|
||||
if (coding_type == coding_IMA_int)
|
||||
vgmstream->num_samples =
|
||||
(read_32bitLE(0x40,streamFile)-start_offset)/channel_count*2;
|
||||
else if (coding_type == coding_NDS_PROCYON)
|
||||
@ -72,7 +72,7 @@ VGMSTREAM * init_vgmstream_sadl(STREAMFILE *streamFile) {
|
||||
|
||||
if (loop_flag)
|
||||
{
|
||||
if (coding_type == coding_INT_IMA)
|
||||
if (coding_type == coding_IMA_int)
|
||||
vgmstream->loop_start_sample = (read_32bitLE(0x54,streamFile)-start_offset)/channel_count*2;
|
||||
else
|
||||
vgmstream->loop_start_sample = (read_32bitLE(0x54,streamFile)-start_offset)/channel_count/16*30;
|
||||
|
@ -134,7 +134,7 @@ VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE *streamFile) {
|
||||
start_offset = 0x2C;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);
|
||||
vgmstream->coding_type = coding_INT_IMA;
|
||||
vgmstream->coding_type = coding_IMA_int;
|
||||
vgmstream->num_samples = (read_32bitLE(0x04,streamFile)-start_offset);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile);
|
||||
|
@ -49,7 +49,7 @@ VGMSTREAM * init_vgmstream_nds_swav(STREAMFILE *streamFile) {
|
||||
bits_per_sample = 16;
|
||||
break;
|
||||
case 2:
|
||||
coding_type = coding_INT_IMA;
|
||||
coding_type = coding_IMA_int;
|
||||
bits_per_sample = 4;
|
||||
break;
|
||||
default:
|
||||
@ -74,7 +74,7 @@ VGMSTREAM * init_vgmstream_nds_swav(STREAMFILE *streamFile) {
|
||||
vgmstream->loop_start_sample;
|
||||
}
|
||||
|
||||
if (coding_type == coding_INT_IMA) {
|
||||
if (coding_type == coding_IMA_int) {
|
||||
/* handle IMA frame header */
|
||||
vgmstream->loop_start_sample -= 32 / bits_per_sample;
|
||||
vgmstream->loop_end_sample -= 32 / bits_per_sample;
|
||||
|
@ -10,7 +10,7 @@ VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE *streamFile) {
|
||||
|
||||
|
||||
/* check extension, case insensitive */
|
||||
/* .adp: Big Air Freestyle */
|
||||
/* .dsp: Big Air Freestyle */
|
||||
/* .mds: Terminator 3 The Redemption, Mission Impossible: Operation Surma */
|
||||
if (!check_extensions(streamFile, "dsp,mds")) goto fail;
|
||||
|
||||
@ -18,7 +18,7 @@ VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE *streamFile) {
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4D504453) /* "MPDS" */
|
||||
goto fail;
|
||||
|
||||
short_mpds = read_32bitBE(0x04,streamFile) != 0x00010000 && read_32bitBE(0x0c,streamFile) == 0x00000002; /* version byte? */
|
||||
short_mpds = read_32bitBE(0x04,streamFile) != 0x00010000 && check_extensions(streamFile, "mds"); /* version byte? */
|
||||
|
||||
channel_count = short_mpds ?
|
||||
read_16bitBE(0x0a, streamFile) :
|
||||
@ -51,12 +51,13 @@ VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE *streamFile) {
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitBE(0x08,streamFile);
|
||||
vgmstream->interleave_block_size = channel_count==1 ? 0 : 0x200;
|
||||
|
||||
#if 0 //todo unknown coeffs, maybe depends on stuff @ 0x10? (but looks like some kind of size)
|
||||
#if 0 //unknown coeffs/hist, related to data after 0x0c? (only coefs 0..7 seem to be needed)
|
||||
{
|
||||
off_t offset = 0x0c;
|
||||
int i,ch;
|
||||
for (ch=0; ch < vgmstream->channels; ch++) {
|
||||
for (i=0; i < 16; i++)
|
||||
vgmstream->ch[ch].adpcm_coef[i] = mpds_coefs[i];
|
||||
vgmstream->ch[ch].adpcm_coef[i] = read_16bitBE(offset + i*2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -31,7 +31,7 @@ VGMSTREAM * init_vgmstream_ps2_snd(STREAMFILE *streamFile) {
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(0xe,streamFile);
|
||||
|
||||
if(read_8bit(0x08,streamFile)==1) {
|
||||
vgmstream->coding_type = coding_INT_DVI_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
}
|
||||
else
|
||||
vgmstream->coding_type = coding_PCM16LE;
|
||||
|
@ -33,7 +33,7 @@ VGMSTREAM * init_vgmstream_ps2_stm(STREAMFILE *streamFile) {
|
||||
start_offset = 0x800;
|
||||
vgmstream->sample_rate = (uint16_t)read_32bitLE(0xc,streamFile);
|
||||
|
||||
vgmstream->coding_type = coding_INT_DVI_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
|
||||
vgmstream->num_samples = read_32bitLE(0x18,streamFile);
|
||||
|
||||
|
@ -29,7 +29,7 @@ VGMSTREAM * init_vgmstream_dvi(STREAMFILE *streamFile) {
|
||||
vgmstream->channels = channel_count;
|
||||
start_offset = read_32bitBE(0x04,streamFile);
|
||||
vgmstream->sample_rate = 44100;
|
||||
vgmstream->coding_type = coding_INT_DVI_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
|
||||
vgmstream->num_samples = read_32bitBE(0x08,streamFile);
|
||||
|
||||
|
@ -34,7 +34,7 @@ VGMSTREAM * init_vgmstream_xbox_stma(STREAMFILE *streamFile) {
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);
|
||||
vgmstream->coding_type = coding_INT_DVI_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->num_samples = read_32bitLE(0x18,streamFile)*2/vgmstream->channels;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size=0x40;
|
||||
|
@ -117,7 +117,8 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
|
||||
/* for Techland's XWB with no data */
|
||||
if (xwb.base_offset == 0) goto fail;
|
||||
if (xwb.data_offset + xwb.data_size != get_streamfile_size(streamFile)) goto fail;
|
||||
/* some BlazBlue Centralfiction songs have padding after data size */
|
||||
if (xwb.data_offset + xwb.data_size > get_streamfile_size(streamFile)) goto fail;
|
||||
|
||||
/* read base entry (WAVEBANKDATA) */
|
||||
off = xwb.base_offset;
|
||||
|
121
src/streamfile.c
121
src/streamfile.c
@ -5,15 +5,23 @@
|
||||
#include "util.h"
|
||||
#include "vgmstream.h"
|
||||
|
||||
|
||||
/* On EOF reads we can return length 0, or ignore and return the requested length + 0-set the buffer.
|
||||
* Some decoders don't check for EOF and may decode garbage if returned 0, as read_Nbit() funcs return -1.
|
||||
* Only matters for metas that get num_samples wrong (bigger than total data). */
|
||||
#define STREAMFILE_IGNORE_EOF 0
|
||||
|
||||
|
||||
/* buffered file reader */
|
||||
typedef struct {
|
||||
STREAMFILE sf;
|
||||
FILE * infile;
|
||||
STREAMFILE sf; /* callbacks */
|
||||
FILE * infile; /* actual FILE */
|
||||
char name[PATH_LIMIT];
|
||||
off_t offset;
|
||||
size_t validsize;
|
||||
uint8_t * buffer;
|
||||
size_t buffersize;
|
||||
size_t filesize;
|
||||
off_t offset; /* current offset */
|
||||
size_t validsize; /* current buffer size */
|
||||
uint8_t * buffer; /* data buffer */
|
||||
size_t buffersize; /* max buffer size */
|
||||
size_t filesize; /* cached file size (max offset) */
|
||||
#ifdef VGM_DEBUG_OUTPUT
|
||||
int error_notified;
|
||||
#endif
|
||||
@ -28,19 +36,20 @@ static STREAMFILE * open_stdio_streamfile_buffer_by_FILE(FILE *infile,const char
|
||||
static size_t read_the_rest(uint8_t * dest, off_t offset, size_t length, STDIOSTREAMFILE * streamfile) {
|
||||
size_t length_read_total=0;
|
||||
|
||||
/* is the beginning at least there? */
|
||||
if (offset >= streamfile->offset && offset < streamfile->offset+streamfile->validsize) {
|
||||
/* is the part of the requested length in the buffer? */
|
||||
if (offset >= streamfile->offset && offset < streamfile->offset + streamfile->validsize) {
|
||||
size_t length_read;
|
||||
off_t offset_into_buffer = offset-streamfile->offset;
|
||||
length_read = streamfile->validsize-offset_into_buffer;
|
||||
memcpy(dest,streamfile->buffer+offset_into_buffer,length_read);
|
||||
off_t offset_into_buffer = offset - streamfile->offset;
|
||||
length_read = streamfile->validsize - offset_into_buffer;
|
||||
|
||||
memcpy(dest,streamfile->buffer + offset_into_buffer,length_read);
|
||||
length_read_total += length_read;
|
||||
length -= length_read;
|
||||
offset += length_read;
|
||||
dest += length_read;
|
||||
}
|
||||
|
||||
/* TODO: What would make more sense here is to read the whole request
|
||||
/* What would make more sense here is to read the whole request
|
||||
* at once into the dest buffer, as it must be large enough, and then
|
||||
* copy some part of that into our own buffer.
|
||||
* The destination buffer is supposed to be much smaller than the
|
||||
@ -48,23 +57,29 @@ static size_t read_the_rest(uint8_t * dest, off_t offset, size_t length, STDIOST
|
||||
* to the buffer size to avoid having to deal with things like this
|
||||
* which are outside of my intended use.
|
||||
*/
|
||||
/* read as much of the beginning of the request as possible, proceed */
|
||||
while (length>0) {
|
||||
/* read the rest of the requested length */
|
||||
while (length > 0) {
|
||||
size_t length_to_read;
|
||||
size_t length_read;
|
||||
streamfile->validsize=0;
|
||||
streamfile->validsize = 0; /* buffer is empty now */
|
||||
|
||||
/* request outside file: ignore to avoid seek/read */
|
||||
if (offset > streamfile->filesize) {
|
||||
#ifdef VGM_DEBUG_OUTPUT
|
||||
streamfile->offset = streamfile->filesize;
|
||||
|
||||
#ifdef VGM_DEBUG_OUTPUT
|
||||
if (!streamfile->error_notified) {
|
||||
VGM_LOG("ERROR: reading outside filesize, at offset 0x%lx + 0x%x (buggy meta?)\n", offset, length);
|
||||
VGM_LOG("ERROR: reading over filesize 0x%x @ 0x%lx + 0x%x (buggy meta?)\n", streamfile->filesize, offset, length);
|
||||
streamfile->error_notified = 1;
|
||||
}
|
||||
#endif
|
||||
streamfile->offset = streamfile->filesize;
|
||||
memset(dest,0,length);
|
||||
return length; /* return partially-read buffer and 0-set the rest */
|
||||
#endif
|
||||
|
||||
#if STREAMFILE_IGNORE_EOF
|
||||
memset(dest,0,length); /* dest is already shifted */
|
||||
return length_read_total + length; /* partially-read + 0-set buffer */
|
||||
#else
|
||||
return length_read_total; /* partially-read buffer */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* position to new offset */
|
||||
@ -73,18 +88,19 @@ static size_t read_the_rest(uint8_t * dest, off_t offset, size_t length, STDIOST
|
||||
#ifdef PROFILE_STREAMFILE
|
||||
streamfile->error_count++;
|
||||
#endif
|
||||
return 0; //fail miserably
|
||||
return 0; /* fail miserably (fseek shouldn't fail and reach this) */
|
||||
}
|
||||
|
||||
streamfile->offset=offset;
|
||||
streamfile->offset = offset;
|
||||
|
||||
/* decide how much must be read this time */
|
||||
if (length>streamfile->buffersize) length_to_read=streamfile->buffersize;
|
||||
else length_to_read=length;
|
||||
if (length > streamfile->buffersize)
|
||||
length_to_read = streamfile->buffersize;
|
||||
else
|
||||
length_to_read = length;
|
||||
|
||||
/* always try to fill the buffer */
|
||||
length_read = fread(streamfile->buffer,1,streamfile->buffersize,streamfile->infile);
|
||||
streamfile->validsize=length_read;
|
||||
/* fill the buffer */
|
||||
length_read = fread(streamfile->buffer,sizeof(uint8_t),streamfile->buffersize,streamfile->infile);
|
||||
streamfile->validsize = length_read;
|
||||
|
||||
#ifdef PROFILE_STREAMFILE
|
||||
if (ferror(streamfile->infile)) {
|
||||
@ -95,19 +111,24 @@ static size_t read_the_rest(uint8_t * dest, off_t offset, size_t length, STDIOST
|
||||
streamfile->bytes_read += length_read;
|
||||
#endif
|
||||
|
||||
/* if we can't get enough to satisfy the request we give up */
|
||||
/* if we can't get enough to satisfy the request (EOF) we give up */
|
||||
if (length_read < length_to_read) {
|
||||
memcpy(dest,streamfile->buffer,length_read);
|
||||
length_read_total+=length_read;
|
||||
return length_read_total;
|
||||
|
||||
#if STREAMFILE_IGNORE_EOF
|
||||
memset(dest+length_read,0,length-length_read);
|
||||
return length_read_total + length; /* partially-read + 0-set buffer */
|
||||
#else
|
||||
return length_read_total + length_read; /* partially-read buffer */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* use the new buffer */
|
||||
memcpy(dest,streamfile->buffer,length_to_read);
|
||||
length_read_total+=length_to_read;
|
||||
length-=length_to_read;
|
||||
dest+=length_to_read;
|
||||
offset+=length_to_read;
|
||||
length_read_total += length_to_read;
|
||||
length -= length_to_read;
|
||||
dest += length_to_read;
|
||||
offset += length_to_read;
|
||||
}
|
||||
|
||||
return length_read_total;
|
||||
@ -115,25 +136,32 @@ static size_t read_the_rest(uint8_t * dest, off_t offset, size_t length, STDIOST
|
||||
|
||||
static size_t read_stdio(STDIOSTREAMFILE *streamfile,uint8_t * dest, off_t offset, size_t length) {
|
||||
|
||||
if (!streamfile || !dest || length<=0) return 0;
|
||||
|
||||
/* if entire request is within the buffer */
|
||||
if (offset >= streamfile->offset && offset+length <= streamfile->offset+streamfile->validsize) {
|
||||
memcpy(dest,streamfile->buffer+(offset-streamfile->offset),length);
|
||||
return length;
|
||||
}
|
||||
if (!streamfile || !dest || length<=0)
|
||||
return 0;
|
||||
|
||||
/* request outside file: ignore to avoid seek/read in read_the_rest() */
|
||||
if (offset > streamfile->filesize) {
|
||||
streamfile->offset = streamfile->filesize;
|
||||
|
||||
#ifdef VGM_DEBUG_OUTPUT
|
||||
if (!streamfile->error_notified) {
|
||||
VGM_LOG("ERROR: reading outside filesize, at offset over 0x%lx (buggy meta?)\n", offset);
|
||||
VGM_LOG("ERROR: offset over filesize 0x%x @ 0x%lx + 0x%x (buggy meta?)\n", streamfile->filesize, offset, length);
|
||||
streamfile->error_notified = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
streamfile->offset = streamfile->filesize;
|
||||
#if STREAMFILE_IGNORE_EOF
|
||||
memset(dest,0,length);
|
||||
return length; /* 0-set buffer */
|
||||
#else
|
||||
return 0; /* nothing to read */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* just copy if entire request is within the buffer */
|
||||
if (offset >= streamfile->offset && offset + length <= streamfile->offset + streamfile->validsize) {
|
||||
off_t offset_into_buffer = offset - streamfile->offset;
|
||||
memcpy(dest,streamfile->buffer + offset_into_buffer,length);
|
||||
return length;
|
||||
}
|
||||
|
||||
@ -523,4 +551,3 @@ int find_chunk(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, in
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
423
src/vgmstream.c
423
src/vgmstream.c
@ -18,8 +18,7 @@ static void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFi
|
||||
|
||||
|
||||
/*
|
||||
* List of functions that will recognize files. These should correspond pretty
|
||||
* directly to the metadata types
|
||||
* List of functions that will recognize files.
|
||||
*/
|
||||
VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_adx,
|
||||
@ -354,6 +353,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_xma,
|
||||
init_vgmstream_sxd,
|
||||
init_vgmstream_ogl,
|
||||
init_vgmstream_mc3,
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
init_vgmstream_mp4_aac_ffmpeg,
|
||||
@ -373,22 +373,20 @@ VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile, int do_dfs) {
|
||||
|
||||
fcns_size = (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0]));
|
||||
/* try a series of formats, see which works */
|
||||
for (i=0;i<fcns_size;i++) {
|
||||
for (i=0; i < fcns_size; i++) {
|
||||
/* call init function and see if valid VGMSTREAM was returned */
|
||||
VGMSTREAM * vgmstream = (init_vgmstream_fcns[i])(streamFile);
|
||||
if (vgmstream) {
|
||||
/* these are little hacky checks */
|
||||
|
||||
/* fail if there is nothing to play
|
||||
* (without this check vgmstream can generate empty files) */
|
||||
/* fail if there is nothing to play (without this check vgmstream can generate empty files) */
|
||||
if (vgmstream->num_samples <= 0) {
|
||||
VGM_LOG("VGMSTREAM: wrong num_samples (ns=%i)\n", vgmstream->num_samples);
|
||||
VGM_LOG("VGMSTREAM: wrong num_samples (ns=%i / 0x%08x)\n", vgmstream->num_samples, vgmstream->num_samples);
|
||||
close_vgmstream(vgmstream);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* everything should have a reasonable sample rate
|
||||
* (a verification of the metadata) */
|
||||
/* everything should have a reasonable sample rate (a verification of the metadata) */
|
||||
if (!check_sample_rate(vgmstream->sample_rate)) {
|
||||
VGM_LOG("VGMSTREAM: wrong sample rate (sr=%i)\n", vgmstream->sample_rate);
|
||||
close_vgmstream(vgmstream);
|
||||
@ -479,11 +477,7 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
if (vgmstream->coding_type==coding_ogg_vorbis) {
|
||||
ogg_vorbis_codec_data *data = vgmstream->codec_data;
|
||||
|
||||
OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file);
|
||||
|
||||
ov_pcm_seek(ogg_vorbis_file, 0);
|
||||
reset_ogg_vorbis(vgmstream);
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type==coding_fsb_vorbis) {
|
||||
@ -498,59 +492,40 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
|
||||
reset_ogl_vorbis(vgmstream);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vgmstream->coding_type==coding_CRI_HCA) {
|
||||
hca_codec_data *data = vgmstream->codec_data;
|
||||
/*clHCA *hca = (clHCA *)(data + 1);*/
|
||||
data->curblock = 0;
|
||||
data->sample_ptr = clHCA_samplesPerBlock;
|
||||
data->samples_discard = 0;
|
||||
reset_hca(vgmstream);
|
||||
}
|
||||
|
||||
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
||||
if (vgmstream->coding_type==coding_MP4_AAC) {
|
||||
mp4_aac_codec_data *data = vgmstream->codec_data;
|
||||
data->sampleId = 0;
|
||||
data->sample_ptr = data->samples_per_frame;
|
||||
data->samples_discard = 0;
|
||||
reset_mp4_aac(vgmstream);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_MPEG
|
||||
if (vgmstream->layout_type==layout_mpeg ||
|
||||
vgmstream->layout_type==layout_fake_mpeg) {
|
||||
reset_mpeg(vgmstream);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_G7221
|
||||
if (vgmstream->coding_type==coding_G7221 ||
|
||||
vgmstream->coding_type==coding_G7221C) {
|
||||
g7221_codec_data *data = vgmstream->codec_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++)
|
||||
{
|
||||
g7221_reset(data[i].handle);
|
||||
}
|
||||
reset_g7221(vgmstream);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_G719
|
||||
if (vgmstream->coding_type==coding_G719) {
|
||||
g719_codec_data *data = vgmstream->codec_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++)
|
||||
{
|
||||
g719_reset(data[i].handle);
|
||||
}
|
||||
reset_g719(vgmstream);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_MAIATRAC3PLUS
|
||||
if (vgmstream->coding_type==coding_AT3plus) {
|
||||
maiatrac3plus_codec_data *data = vgmstream->codec_data;
|
||||
|
||||
if (data->handle) Atrac3plusDecoder_closeContext(data->handle);
|
||||
data->handle = Atrac3plusDecoder_openContext();
|
||||
data->samples_discard = 0;
|
||||
reset_at3plus(vgmstream);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -680,20 +655,13 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
||||
|
||||
void close_vgmstream(VGMSTREAM * vgmstream) {
|
||||
int i,j;
|
||||
if (!vgmstream) return;
|
||||
if (!vgmstream)
|
||||
return;
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
if (vgmstream->coding_type==coding_ogg_vorbis) {
|
||||
ogg_vorbis_codec_data *data = (ogg_vorbis_codec_data *) vgmstream->codec_data;
|
||||
if (vgmstream->codec_data) {
|
||||
OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file);
|
||||
|
||||
ov_clear(ogg_vorbis_file);
|
||||
|
||||
close_streamfile(data->ov_streamfile.streamfile);
|
||||
free(vgmstream->codec_data);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
free_ogg_vorbis(vgmstream->codec_data);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type==coding_fsb_vorbis) {
|
||||
@ -713,43 +681,28 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
|
||||
#endif
|
||||
|
||||
if (vgmstream->coding_type==coding_CRI_HCA) {
|
||||
hca_codec_data *data = (hca_codec_data *) vgmstream->codec_data;
|
||||
if (vgmstream->codec_data) {
|
||||
clHCA *hca = (clHCA *)(data + 1);
|
||||
clHCA_done(hca);
|
||||
if (data->streamfile) close_streamfile(data->streamfile);
|
||||
free(vgmstream->codec_data);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
free_hca(vgmstream->codec_data);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
if (vgmstream->coding_type==coding_FFmpeg) {
|
||||
ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data;
|
||||
if (vgmstream->codec_data) {
|
||||
free_ffmpeg(data);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
free_ffmpeg(vgmstream->codec_data);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
||||
if (vgmstream->coding_type==coding_MP4_AAC) {
|
||||
mp4_aac_codec_data *data = (mp4_aac_codec_data *) vgmstream->codec_data;
|
||||
if (vgmstream->codec_data) {
|
||||
if (data->h_aacdecoder) aacDecoder_Close(data->h_aacdecoder);
|
||||
if (data->h_mp4file) MP4Close(data->h_mp4file, 0);
|
||||
if (data->if_file.streamfile) close_streamfile(data->if_file.streamfile);
|
||||
free(vgmstream->codec_data);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
free_mp4_aac(vgmstream->codec_data);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_MPEG
|
||||
if (vgmstream->layout_type==layout_fake_mpeg||
|
||||
if (vgmstream->layout_type==layout_fake_mpeg ||
|
||||
vgmstream->layout_type==layout_mpeg) {
|
||||
free_mpeg((mpeg_codec_data *)vgmstream->codec_data);
|
||||
free_mpeg(vgmstream->codec_data);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
#endif
|
||||
@ -757,52 +710,22 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
|
||||
#ifdef VGM_USE_G7221
|
||||
if (vgmstream->coding_type == coding_G7221 ||
|
||||
vgmstream->coding_type == coding_G7221C) {
|
||||
|
||||
g7221_codec_data *data = (g7221_codec_data *) vgmstream->codec_data;
|
||||
|
||||
if (data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++)
|
||||
{
|
||||
g7221_free(data[i].handle);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
free_g7221(vgmstream);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_G719
|
||||
if (vgmstream->coding_type == coding_G719) {
|
||||
g719_codec_data *data = (g719_codec_data *) vgmstream->codec_data;
|
||||
|
||||
if (data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++)
|
||||
{
|
||||
g719_free(data[i].handle);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
free_g719(vgmstream);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_MAIATRAC3PLUS
|
||||
if (vgmstream->coding_type == coding_AT3plus) {
|
||||
maiatrac3plus_codec_data *data = (maiatrac3plus_codec_data *) vgmstream->codec_data;
|
||||
|
||||
if (data)
|
||||
{
|
||||
if (data->handle) Atrac3plusDecoder_closeContext(data->handle);
|
||||
free(data);
|
||||
}
|
||||
free_at3plus(vgmstream->codec_data);
|
||||
vgmstream->codec_data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -884,9 +807,7 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
|
||||
vgmstream->coding_type == coding_NWA5
|
||||
) {
|
||||
nwa_codec_data *data = (nwa_codec_data *) vgmstream->codec_data;
|
||||
|
||||
close_nwa(data->nwa);
|
||||
|
||||
free(data);
|
||||
|
||||
vgmstream->codec_data = NULL;
|
||||
@ -1070,8 +991,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
case coding_IMA:
|
||||
case coding_OTNS_IMA:
|
||||
return 1;
|
||||
case coding_INT_IMA:
|
||||
case coding_INT_DVI_IMA:
|
||||
case coding_IMA_int:
|
||||
case coding_DVI_IMA_int:
|
||||
case coding_AICA:
|
||||
return 2;
|
||||
case coding_NGC_AFC:
|
||||
@ -1085,7 +1006,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
case coding_PSX_cfg:
|
||||
return (vgmstream->interleave_block_size - 1) * 2; /* decodes 1 byte into 2 bytes */
|
||||
case coding_XBOX:
|
||||
case coding_INT_XBOX:
|
||||
case coding_XBOX_int:
|
||||
case coding_FSB_IMA:
|
||||
return 64;
|
||||
case coding_EA_XA:
|
||||
@ -1094,8 +1015,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
case coding_EA_ADPCM:
|
||||
return 14*vgmstream->channels;
|
||||
case coding_WS:
|
||||
/* only works if output sample size is 8 bit, which is always
|
||||
is for WS ADPCM */
|
||||
/* only works if output sample size is 8 bit, which always is for WS ADPCM */
|
||||
return vgmstream->ws_output_size;
|
||||
case coding_MSADPCM:
|
||||
return (vgmstream->interleave_block_size-(7-1)*vgmstream->channels)*2/vgmstream->channels;
|
||||
@ -1135,6 +1055,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
return 54;
|
||||
case coding_MTAF:
|
||||
return 0x80*2;
|
||||
case coding_MC3:
|
||||
return 10;
|
||||
case coding_CRI_HCA:
|
||||
return clHCA_samplesPerBlock;
|
||||
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
||||
@ -1220,7 +1142,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
case coding_XA:
|
||||
return 14*vgmstream->channels;
|
||||
case coding_XBOX:
|
||||
case coding_INT_XBOX:
|
||||
case coding_XBOX_int:
|
||||
case coding_FSB_IMA:
|
||||
return 36;
|
||||
case coding_MAXIS_ADPCM:
|
||||
@ -1231,8 +1153,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
return 1; // the frame is variant in size
|
||||
case coding_WS:
|
||||
return vgmstream->current_block_size;
|
||||
case coding_INT_IMA:
|
||||
case coding_INT_DVI_IMA:
|
||||
case coding_IMA_int:
|
||||
case coding_DVI_IMA_int:
|
||||
case coding_AICA:
|
||||
return 1;
|
||||
case coding_APPLE_IMA4:
|
||||
@ -1255,6 +1177,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
case coding_MSADPCM:
|
||||
case coding_MTAF:
|
||||
return vgmstream->interleave_block_size;
|
||||
case coding_MC3:
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -1395,7 +1319,7 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
samples_to_do,chan);
|
||||
}
|
||||
break;
|
||||
case coding_INT_XBOX:
|
||||
case coding_XBOX_int:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_int_xbox_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
@ -1581,7 +1505,7 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
}
|
||||
break;
|
||||
case coding_DVI_IMA:
|
||||
case coding_INT_DVI_IMA:
|
||||
case coding_DVI_IMA_int:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_dvi_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
@ -1596,7 +1520,7 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
}
|
||||
break;
|
||||
case coding_IMA:
|
||||
case coding_INT_IMA:
|
||||
case coding_IMA_int:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
@ -1777,6 +1701,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
chan, vgmstream->channels);
|
||||
}
|
||||
break;
|
||||
case coding_MC3:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_mc3(vgmstream, &vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels, vgmstream->samples_into_block, samples_to_do,
|
||||
chan);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1805,135 +1736,122 @@ int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMST
|
||||
}
|
||||
|
||||
/* if it's a framed encoding don't do more than one frame */
|
||||
if (samples_per_frame>1 && (vgmstream->samples_into_block%samples_per_frame)+samples_to_do>samples_per_frame) samples_to_do=samples_per_frame-(vgmstream->samples_into_block%samples_per_frame);
|
||||
if (samples_per_frame>1 && (vgmstream->samples_into_block%samples_per_frame)+samples_to_do>samples_per_frame)
|
||||
samples_to_do = samples_per_frame - (vgmstream->samples_into_block%samples_per_frame);
|
||||
|
||||
return samples_to_do;
|
||||
}
|
||||
|
||||
/* return 1 if we just looped */
|
||||
int vgmstream_do_loop(VGMSTREAM * vgmstream) {
|
||||
/* if (vgmstream->loop_flag) {*/
|
||||
/* is this the loop end? */
|
||||
if (vgmstream->current_sample==vgmstream->loop_end_sample) {
|
||||
/* against everything I hold sacred, preserve adpcm
|
||||
* history through loop for certain types */
|
||||
if (vgmstream->meta_type == meta_DSP_STD ||
|
||||
vgmstream->meta_type == meta_DSP_RS03 ||
|
||||
vgmstream->meta_type == meta_DSP_CSTR ||
|
||||
vgmstream->coding_type == coding_PSX ||
|
||||
vgmstream->coding_type == coding_PSX_bmdx ||
|
||||
vgmstream->coding_type == coding_PSX_badflags) {
|
||||
int i;
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->loop_ch[i].adpcm_history1_16 = vgmstream->ch[i].adpcm_history1_16;
|
||||
vgmstream->loop_ch[i].adpcm_history2_16 = vgmstream->ch[i].adpcm_history2_16;
|
||||
vgmstream->loop_ch[i].adpcm_history1_32 = vgmstream->ch[i].adpcm_history1_32;
|
||||
vgmstream->loop_ch[i].adpcm_history2_32 = vgmstream->ch[i].adpcm_history2_32;
|
||||
}
|
||||
}
|
||||
/* todo preserve ADPCM (ex hevag) history? */
|
||||
/*if (vgmstream->loop_flag) return 0;*/
|
||||
|
||||
if (vgmstream->coding_type==coding_CRI_HCA) {
|
||||
hca_codec_data *data = (hca_codec_data *)(vgmstream->codec_data);
|
||||
data->curblock = data->info.loopStart;
|
||||
data->sample_ptr = clHCA_samplesPerBlock;
|
||||
data->samples_discard = 0;
|
||||
/* is this the loop end? */
|
||||
if (vgmstream->current_sample==vgmstream->loop_end_sample) {
|
||||
|
||||
/* against everything I hold sacred, preserve adpcm
|
||||
* history through loop for certain types */
|
||||
if (vgmstream->meta_type == meta_DSP_STD ||
|
||||
vgmstream->meta_type == meta_DSP_RS03 ||
|
||||
vgmstream->meta_type == meta_DSP_CSTR ||
|
||||
vgmstream->coding_type == coding_PSX ||
|
||||
vgmstream->coding_type == coding_PSX_bmdx ||
|
||||
vgmstream->coding_type == coding_PSX_badflags) {
|
||||
int i;
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->loop_ch[i].adpcm_history1_16 = vgmstream->ch[i].adpcm_history1_16;
|
||||
vgmstream->loop_ch[i].adpcm_history2_16 = vgmstream->ch[i].adpcm_history2_16;
|
||||
vgmstream->loop_ch[i].adpcm_history1_32 = vgmstream->ch[i].adpcm_history1_32;
|
||||
vgmstream->loop_ch[i].adpcm_history2_32 = vgmstream->ch[i].adpcm_history2_32;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* prepare certain codecs' internal state for looping */
|
||||
|
||||
if (vgmstream->coding_type==coding_CRI_HCA) {
|
||||
loop_hca(vgmstream);
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
if (vgmstream->coding_type==coding_ogg_vorbis) {
|
||||
ogg_vorbis_codec_data *data =
|
||||
(ogg_vorbis_codec_data *)(vgmstream->codec_data);
|
||||
OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file);
|
||||
|
||||
ov_pcm_seek_lap(ogg_vorbis_file, vgmstream->loop_sample);
|
||||
}
|
||||
if (vgmstream->coding_type==coding_ogg_vorbis) {
|
||||
seek_ogg_vorbis(vgmstream, vgmstream->loop_sample);
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type==coding_fsb_vorbis) {
|
||||
seek_fsb_vorbis(vgmstream, vgmstream->loop_start_sample);
|
||||
}
|
||||
if (vgmstream->coding_type==coding_fsb_vorbis) {
|
||||
seek_fsb_vorbis(vgmstream, vgmstream->loop_start_sample);
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type==coding_wwise_vorbis) {
|
||||
seek_wwise_vorbis(vgmstream, vgmstream->loop_start_sample);
|
||||
}
|
||||
if (vgmstream->coding_type==coding_wwise_vorbis) {
|
||||
seek_wwise_vorbis(vgmstream, vgmstream->loop_start_sample);
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type==coding_ogl_vorbis) {
|
||||
seek_ogl_vorbis(vgmstream, vgmstream->loop_start_sample);
|
||||
}
|
||||
if (vgmstream->coding_type==coding_ogl_vorbis) {
|
||||
seek_ogl_vorbis(vgmstream, vgmstream->loop_start_sample);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
if (vgmstream->coding_type==coding_FFmpeg) {
|
||||
seek_ffmpeg(vgmstream, vgmstream->loop_start_sample);
|
||||
}
|
||||
if (vgmstream->coding_type==coding_FFmpeg) {
|
||||
seek_ffmpeg(vgmstream, vgmstream->loop_start_sample);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
||||
if (vgmstream->coding_type==coding_MP4_AAC) {
|
||||
mp4_aac_codec_data *data = (mp4_aac_codec_data *)(vgmstream->codec_data);
|
||||
data->sampleId = 0;
|
||||
data->sample_ptr = data->samples_per_frame;
|
||||
data->samples_discard = vgmstream->loop_sample;
|
||||
}
|
||||
if (vgmstream->coding_type==coding_MP4_AAC) {
|
||||
seek_mp4_aac(vgmstream, vgmstream->loop_sample);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_MAIATRAC3PLUS
|
||||
if (vgmstream->coding_type==coding_AT3plus) {
|
||||
int blocks_to_skip = vgmstream->loop_sample / 2048;
|
||||
int samples_to_discard = vgmstream->loop_sample % 2048;
|
||||
maiatrac3plus_codec_data *data = (maiatrac3plus_codec_data *)(vgmstream->codec_data);
|
||||
vgmstream->loop_ch[0].offset =
|
||||
vgmstream->loop_ch[0].channel_start_offset +
|
||||
vgmstream->interleave_block_size * blocks_to_skip;
|
||||
data->samples_discard = samples_to_discard;
|
||||
}
|
||||
if (vgmstream->coding_type==coding_AT3plus) {
|
||||
seek_at3plus(vgmstream, vgmstream->loop_sample);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_MPEG
|
||||
/* won't work for fake MPEG */
|
||||
if (vgmstream->layout_type==layout_mpeg) {
|
||||
seek_mpeg(vgmstream, vgmstream->loop_sample);
|
||||
}
|
||||
if (vgmstream->layout_type==layout_mpeg) {
|
||||
seek_mpeg(vgmstream, vgmstream->loop_sample); /* won't work for fake MPEG */
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vgmstream->coding_type == coding_NWA0 ||
|
||||
vgmstream->coding_type == coding_NWA1 ||
|
||||
vgmstream->coding_type == coding_NWA2 ||
|
||||
vgmstream->coding_type == coding_NWA3 ||
|
||||
vgmstream->coding_type == coding_NWA4 ||
|
||||
vgmstream->coding_type == coding_NWA5)
|
||||
{
|
||||
nwa_codec_data *data = vgmstream->codec_data;
|
||||
|
||||
seek_nwa(data->nwa, vgmstream->loop_sample);
|
||||
}
|
||||
|
||||
/* restore! */
|
||||
memcpy(vgmstream->ch,vgmstream->loop_ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
||||
vgmstream->current_sample=vgmstream->loop_sample;
|
||||
vgmstream->samples_into_block=vgmstream->loop_samples_into_block;
|
||||
vgmstream->current_block_size=vgmstream->loop_block_size;
|
||||
vgmstream->current_block_offset=vgmstream->loop_block_offset;
|
||||
vgmstream->next_block_offset=vgmstream->loop_next_block_offset;
|
||||
|
||||
return 1;
|
||||
if (vgmstream->coding_type == coding_NWA0 ||
|
||||
vgmstream->coding_type == coding_NWA1 ||
|
||||
vgmstream->coding_type == coding_NWA2 ||
|
||||
vgmstream->coding_type == coding_NWA3 ||
|
||||
vgmstream->coding_type == coding_NWA4 ||
|
||||
vgmstream->coding_type == coding_NWA5)
|
||||
{
|
||||
nwa_codec_data *data = vgmstream->codec_data;
|
||||
seek_nwa(data->nwa, vgmstream->loop_sample);
|
||||
}
|
||||
|
||||
/* restore! */
|
||||
memcpy(vgmstream->ch,vgmstream->loop_ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
||||
vgmstream->current_sample = vgmstream->loop_sample;
|
||||
vgmstream->samples_into_block = vgmstream->loop_samples_into_block;
|
||||
vgmstream->current_block_size = vgmstream->loop_block_size;
|
||||
vgmstream->current_block_offset = vgmstream->loop_block_offset;
|
||||
vgmstream->next_block_offset = vgmstream->loop_next_block_offset;
|
||||
|
||||
/* is this the loop start? */
|
||||
if (!vgmstream->hit_loop && vgmstream->current_sample==vgmstream->loop_start_sample) {
|
||||
/* save! */
|
||||
memcpy(vgmstream->loop_ch,vgmstream->ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
||||
return 1; /* looped */
|
||||
}
|
||||
|
||||
vgmstream->loop_sample=vgmstream->current_sample;
|
||||
vgmstream->loop_samples_into_block=vgmstream->samples_into_block;
|
||||
vgmstream->loop_block_size=vgmstream->current_block_size;
|
||||
vgmstream->loop_block_offset=vgmstream->current_block_offset;
|
||||
vgmstream->loop_next_block_offset=vgmstream->next_block_offset;
|
||||
vgmstream->hit_loop=1;
|
||||
}
|
||||
/*}*/
|
||||
return 0;
|
||||
|
||||
/* is this the loop start? */
|
||||
if (!vgmstream->hit_loop && vgmstream->current_sample==vgmstream->loop_start_sample) {
|
||||
/* save! */
|
||||
memcpy(vgmstream->loop_ch,vgmstream->ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
||||
|
||||
vgmstream->loop_sample = vgmstream->current_sample;
|
||||
vgmstream->loop_samples_into_block = vgmstream->samples_into_block;
|
||||
vgmstream->loop_block_size = vgmstream->current_block_size;
|
||||
vgmstream->loop_block_offset = vgmstream->current_block_offset;
|
||||
vgmstream->loop_next_block_offset = vgmstream->next_block_offset;
|
||||
vgmstream->hit_loop = 1;
|
||||
}
|
||||
|
||||
return 0; /* not looped */
|
||||
}
|
||||
|
||||
/* build a descriptive string */
|
||||
@ -1943,18 +1861,22 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
||||
const char* description;
|
||||
|
||||
if (!vgmstream) {
|
||||
snprintf(temp,TEMPSIZE,"NULL VGMSTREAM");
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"NULL VGMSTREAM");
|
||||
concatn(length,desc,temp);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(temp,TEMPSIZE,"sample rate: %d Hz\n"
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"sample rate: %d Hz\n"
|
||||
"channels: %d\n",
|
||||
vgmstream->sample_rate,vgmstream->channels);
|
||||
vgmstream->sample_rate,
|
||||
vgmstream->channels);
|
||||
concatn(length,desc,temp);
|
||||
|
||||
if (vgmstream->loop_flag) {
|
||||
snprintf(temp,TEMPSIZE,"loop start: %d samples (%.4f seconds)\n"
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"loop start: %d samples (%.4f seconds)\n"
|
||||
"loop end: %d samples (%.4f seconds)\n",
|
||||
vgmstream->loop_start_sample,
|
||||
(double)vgmstream->loop_start_sample/vgmstream->sample_rate,
|
||||
@ -1963,12 +1885,14 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
||||
concatn(length,desc,temp);
|
||||
}
|
||||
|
||||
snprintf(temp,TEMPSIZE,"stream total samples: %d (%.4f seconds)\n",
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"stream total samples: %d (%.4f seconds)\n",
|
||||
vgmstream->num_samples,
|
||||
(double)vgmstream->num_samples/vgmstream->sample_rate);
|
||||
concatn(length,desc,temp);
|
||||
|
||||
snprintf(temp,TEMPSIZE,"encoding: ");
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"encoding: ");
|
||||
concatn(length,desc,temp);
|
||||
switch (vgmstream->coding_type) {
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
@ -1976,9 +1900,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
||||
ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data;
|
||||
if (vgmstream->codec_data) {
|
||||
if (data->codec && data->codec->long_name) {
|
||||
snprintf(temp,TEMPSIZE,data->codec->long_name);
|
||||
snprintf(temp,TEMPSIZE,"%s",data->codec->long_name);
|
||||
} else if (data->codec && data->codec->name) {
|
||||
snprintf(temp,TEMPSIZE,data->codec->name);
|
||||
snprintf(temp,TEMPSIZE,"%s",data->codec->name);
|
||||
} else {
|
||||
snprintf(temp,TEMPSIZE,"FFmpeg (unknown codec)");
|
||||
}
|
||||
@ -1992,56 +1916,79 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
||||
description = get_vgmstream_coding_description(vgmstream->coding_type);
|
||||
if (!description)
|
||||
description = "CANNOT DECODE";
|
||||
strncpy(temp,description,TEMPSIZE);
|
||||
snprintf(temp,TEMPSIZE,"%s",description);
|
||||
break;
|
||||
}
|
||||
concatn(length,desc,temp);
|
||||
|
||||
snprintf(temp,TEMPSIZE,"\nlayout: ");
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"\nlayout: ");
|
||||
concatn(length,desc,temp);
|
||||
switch (vgmstream->layout_type) {
|
||||
default:
|
||||
description = get_vgmstream_layout_description(vgmstream->layout_type);
|
||||
if (!description)
|
||||
description = "INCONCEIVABLE";
|
||||
strncpy(temp,description,TEMPSIZE);
|
||||
snprintf(temp,TEMPSIZE,"%s",description);
|
||||
break;
|
||||
}
|
||||
concatn(length,desc,temp);
|
||||
|
||||
snprintf(temp,TEMPSIZE,"\n");
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"\n");
|
||||
concatn(length,desc,temp);
|
||||
|
||||
if (vgmstream->layout_type == layout_interleave
|
||||
|| vgmstream->layout_type == layout_interleave_shortblock
|
||||
|| vgmstream->layout_type == layout_interleave_byte) {
|
||||
snprintf(temp,TEMPSIZE,"interleave: %#x bytes\n",
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"interleave: %#x bytes\n",
|
||||
(int32_t)vgmstream->interleave_block_size);
|
||||
concatn(length,desc,temp);
|
||||
|
||||
if (vgmstream->layout_type == layout_interleave_shortblock) {
|
||||
snprintf(temp,TEMPSIZE,"last block interleave: %#x bytes\n",
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"last block interleave: %#x bytes\n",
|
||||
(int32_t)vgmstream->interleave_smallblock_size);
|
||||
concatn(length,desc,temp);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(temp,TEMPSIZE,"metadata from: ");
|
||||
concatn(length,desc,temp);
|
||||
/* codecs with blocks + headers (there are more, this is a start) */
|
||||
if (vgmstream->layout_type == layout_none && vgmstream->interleave_block_size > 0) {
|
||||
switch (vgmstream->coding_type) {
|
||||
case coding_MSADPCM:
|
||||
case coding_MS_IMA:
|
||||
case coding_MC3:
|
||||
case coding_WWISE_IMA:
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"block size: %#x bytes\n",
|
||||
(int32_t)vgmstream->interleave_block_size);
|
||||
concatn(length,desc,temp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"metadata from: ");
|
||||
concatn(length,desc,temp);
|
||||
switch (vgmstream->meta_type) {
|
||||
default:
|
||||
description = get_vgmstream_meta_description(vgmstream->meta_type);
|
||||
if (!description)
|
||||
description = "THEY SHOULD HAVE SENT A POET";
|
||||
strncpy(temp,description,TEMPSIZE);
|
||||
snprintf(temp,TEMPSIZE,"%s",description);
|
||||
break;
|
||||
}
|
||||
concatn(length,desc,temp);
|
||||
|
||||
/* only interesting if more than one */
|
||||
if (vgmstream->num_streams > 1) {
|
||||
snprintf(temp,TEMPSIZE,"\nnumber of streams: %d",vgmstream->num_streams);
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"\nnumber of streams: %d",
|
||||
vgmstream->num_streams);
|
||||
concatn(length,desc,temp);
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,10 @@ enum { PATH_LIMIT = 32768 };
|
||||
* done by external libraries.
|
||||
* If someone wants to do a standalone build, they can do it by simply
|
||||
* removing these defines (and the references to the libraries in the Makefile) */
|
||||
#ifndef VGM_DISABLE_VORBIS
|
||||
#define VGM_USE_VORBIS
|
||||
#endif
|
||||
|
||||
/* can be disabled to decode with FFmpeg instead */
|
||||
#ifndef VGM_DISABLE_MPEG
|
||||
#define VGM_USE_MPEG
|
||||
#endif
|
||||
@ -106,16 +107,16 @@ typedef enum {
|
||||
coding_NDS_PROCYON, /* Procyon Studio ADPCM */
|
||||
|
||||
coding_XBOX, /* XBOX IMA ADPCM */
|
||||
coding_INT_XBOX, /* XBOX IMA ADPCM (interleaved) */
|
||||
coding_XBOX_int, /* XBOX IMA ADPCM (interleaved) */
|
||||
coding_IMA, /* IMA ADPCM (low nibble first) */
|
||||
coding_INT_IMA, /* IMA ADPCM (interleaved) */
|
||||
coding_IMA_int, /* IMA ADPCM (interleaved) */
|
||||
coding_DVI_IMA, /* DVI IMA ADPCM (high nibble first), aka ADP4 */
|
||||
coding_INT_DVI_IMA, /* DVI IMA ADPCM (Interleaved) */
|
||||
coding_DVI_IMA_int, /* DVI IMA ADPCM (Interleaved) */
|
||||
coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */
|
||||
coding_EACS_IMA,
|
||||
coding_MS_IMA, /* Microsoft IMA */
|
||||
coding_RAD_IMA, /* "Radical ADPCM" IMA */
|
||||
coding_RAD_IMA_mono, /* "Radical ADPCM" IMA, mono (for interleave) */
|
||||
coding_RAD_IMA, /* Radical IMA ADPCM */
|
||||
coding_RAD_IMA_mono, /* Radical IMA ADPCM, mono (for interleave) */
|
||||
coding_APPLE_IMA4, /* Apple Quicktime IMA4 */
|
||||
coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */
|
||||
coding_SNDS_IMA, /* Heavy Iron Studios .snds IMA ADPCM */
|
||||
@ -130,6 +131,7 @@ typedef enum {
|
||||
coding_SASSC, /* Activision EXAKT SASSC DPCM */
|
||||
coding_LSF, /* lsf ADPCM (Fastlane Street Racing iPhone)*/
|
||||
coding_MTAF, /* Konami MTAF ADPCM (IMA-derived) */
|
||||
coding_MC3, /* Paradigm MC3 3-bit ADPCM */
|
||||
|
||||
/* others */
|
||||
coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression DPCM */
|
||||
@ -605,6 +607,7 @@ typedef enum {
|
||||
meta_UBI_RAKI, /* Ubisoft RAKI header (Rayman Legends, Just Dance 2017) */
|
||||
meta_SXD, /* Sony SXD (Gravity Rush, Freedom Wars PSV) */
|
||||
meta_OGL, /* Shin'en Wii/WiiU (Jett Rocket (Wii), FAST Racing NEO (WiiU)) */
|
||||
meta_MC3, /* Paradigm games (T3 PS2, MX Rider PS2, MI: Operation Surma PS2) */
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
meta_OGG_VORBIS, /* Ogg Vorbis */
|
||||
|
172
winamp/in2.h
172
winamp/in2.h
@ -1,103 +1,137 @@
|
||||
#ifndef NULLSOFT_WINAMP_IN2H
|
||||
#define NULLSOFT_WINAMP_IN2H
|
||||
#include "out.h"
|
||||
|
||||
// note: exported symbol is now winampGetInModule2.
|
||||
|
||||
#define IN_VER 0x100
|
||||
#define IN_UNICODE 0x0F000000
|
||||
|
||||
#ifdef UNICODE_INPUT_PLUGIN
|
||||
#define in_char wchar_t
|
||||
#define IN_VER (IN_UNICODE | 0x100)
|
||||
#else
|
||||
#define in_char char
|
||||
#define IN_VER 0x100
|
||||
#endif
|
||||
|
||||
#define IN_MODULE_FLAG_USES_OUTPUT_PLUGIN 1
|
||||
// By default, Winamp assumes that your input plugin wants to use Winamp's EQ, and doesn't do replay gain
|
||||
// if you handle any of these yourself (EQ, Replay Gain adjustments), then set these flags accordingly
|
||||
#define IN_MODULE_FLAG_EQ 2 // set this if you do your own EQ
|
||||
#define IN_MODULE_FLAG_REPLAYGAIN 8 // set this if you adjusted volume for replay gain
|
||||
// for tracks with no replay gain metadata, you should clear this flag
|
||||
// UNLESS you handle "non_replaygain" gain adjustment yourself
|
||||
#define IN_MODULE_FLAG_REPLAYGAIN_PREAMP 16 // use this if you queried for the replay gain preamp parameter and used it
|
||||
// this parameter is new to 5.54
|
||||
typedef struct
|
||||
{
|
||||
int version; // module type (IN_VER)
|
||||
char *description; // description of module, with version string
|
||||
int version; // module type (IN_VER)
|
||||
char *description; // description of module, with version string
|
||||
|
||||
HWND hMainWindow; // winamp's main window (filled in by winamp)
|
||||
HINSTANCE hDllInstance; // DLL instance handle (Also filled in by winamp)
|
||||
HWND hMainWindow; // winamp's main window (filled in by winamp)
|
||||
HINSTANCE hDllInstance; // DLL instance handle (Also filled in by winamp)
|
||||
|
||||
char *FileExtensions; // "mp3\0Layer 3 MPEG\0mp2\0Layer 2 MPEG\0mpg\0Layer 1 MPEG\0"
|
||||
// May be altered from Config, so the user can select what they want
|
||||
|
||||
int is_seekable; // is this stream seekable?
|
||||
int UsesOutputPlug; // does this plug-in use the output plug-ins? (musn't ever change, ever :)
|
||||
char *FileExtensions; // "mp3\0Layer 3 MPEG\0mp2\0Layer 2 MPEG\0mpg\0Layer 1 MPEG\0"
|
||||
// May be altered from Config, so the user can select what they want
|
||||
|
||||
void (*Config)(HWND hwndParent); // configuration dialog
|
||||
void (*About)(HWND hwndParent); // about dialog
|
||||
int is_seekable; // is this stream seekable?
|
||||
int UsesOutputPlug; // does this plug-in use the output plug-ins? (musn't ever change, ever :)
|
||||
// note that this has turned into a "flags" field
|
||||
// see IN_MODULE_FLAG_*
|
||||
|
||||
void (*Init)(); // called at program init
|
||||
void (*Quit)(); // called at program quit
|
||||
void (*Config)(HWND hwndParent); // configuration dialog
|
||||
void (*About)(HWND hwndParent); // about dialog
|
||||
|
||||
void (*GetFileInfo)(char *file, char *title, int *length_in_ms); // if file == NULL, current playing is used
|
||||
int (*InfoBox)(char *file, HWND hwndParent);
|
||||
|
||||
int (*IsOurFile)(char *fn); // called before extension checks, to allow detection of mms://, etc
|
||||
// playback stuff
|
||||
int (*Play)(char *fn); // return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error
|
||||
void (*Pause)(); // pause stream
|
||||
void (*UnPause)(); // unpause stream
|
||||
int (*IsPaused)(); // ispaused? return 1 if paused, 0 if not
|
||||
void (*Stop)(); // stop (unload) stream
|
||||
void (*Init)(); // called at program init
|
||||
void (*Quit)(); // called at program quit
|
||||
|
||||
// time stuff
|
||||
int (*GetLength)(); // get length in ms
|
||||
int (*GetOutputTime)(); // returns current output time in ms. (usually returns outMod->GetOutputTime()
|
||||
void (*SetOutputTime)(int time_in_ms); // seeks to point in stream (in ms). Usually you signal yoru thread to seek, which seeks and calls outMod->Flush()..
|
||||
#define GETFILEINFO_TITLE_LENGTH 2048
|
||||
void (*GetFileInfo)(const in_char *file, in_char *title, int *length_in_ms); // if file == NULL, current playing is used
|
||||
|
||||
// volume stuff
|
||||
void (*SetVolume)(int volume); // from 0 to 255.. usually just call outMod->SetVolume
|
||||
void (*SetPan)(int pan); // from -127 to 127.. usually just call outMod->SetPan
|
||||
|
||||
// in-window builtin vis stuff
|
||||
#define INFOBOX_EDITED 0
|
||||
#define INFOBOX_UNCHANGED 1
|
||||
int (*InfoBox)(const in_char *file, HWND hwndParent);
|
||||
|
||||
void (*SAVSAInit)(int maxlatency_in_ms, int srate); // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open()
|
||||
// call after opening audio device with max latency in ms and samplerate
|
||||
void (*SAVSADeInit)(); // call in Stop()
|
||||
int (*IsOurFile)(const in_char *fn); // called before extension checks, to allow detection of mms://, etc
|
||||
// playback stuff
|
||||
int (*Play)(const in_char *fn); // return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error
|
||||
void (*Pause)(); // pause stream
|
||||
void (*UnPause)(); // unpause stream
|
||||
int (*IsPaused)(); // ispaused? return 1 if paused, 0 if not
|
||||
void (*Stop)(); // stop (unload) stream
|
||||
|
||||
// time stuff
|
||||
int (*GetLength)(); // get length in ms
|
||||
int (*GetOutputTime)(); // returns current output time in ms. (usually returns outMod->GetOutputTime()
|
||||
void (*SetOutputTime)(int time_in_ms); // seeks to point in stream (in ms). Usually you signal your thread to seek, which seeks and calls outMod->Flush()..
|
||||
|
||||
// volume stuff
|
||||
void (*SetVolume)(int volume); // from 0 to 255.. usually just call outMod->SetVolume
|
||||
void (*SetPan)(int pan); // from -127 to 127.. usually just call outMod->SetPan
|
||||
|
||||
// in-window builtin vis stuff
|
||||
|
||||
void (*SAVSAInit)(int maxlatency_in_ms, int srate); // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open()
|
||||
// call after opening audio device with max latency in ms and samplerate
|
||||
void (*SAVSADeInit)(); // call in Stop()
|
||||
|
||||
|
||||
// simple vis supplying mode
|
||||
void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp);
|
||||
// sets the spec data directly from PCM data
|
||||
// quick and easy way to get vis working :)
|
||||
// needs at least 576 samples :)
|
||||
// simple vis supplying mode
|
||||
void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp);
|
||||
// sets the spec data directly from PCM data
|
||||
// quick and easy way to get vis working :)
|
||||
// needs at least 576 samples :)
|
||||
|
||||
// advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff.
|
||||
int (*SAGetMode)(); // gets csa (the current type (4=ws,2=osc,1=spec))
|
||||
// use when calling SAAdd()
|
||||
void (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp
|
||||
// advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff.
|
||||
int (*SAGetMode)(); // gets csa (the current type (4=ws,2=osc,1=spec))
|
||||
// use when calling SAAdd()
|
||||
int (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp
|
||||
|
||||
|
||||
// vis stuff (plug-in)
|
||||
// simple vis supplying mode
|
||||
void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data
|
||||
// quick and easy way to get vis working :)
|
||||
// needs at least 576 samples :)
|
||||
// vis stuff (plug-in)
|
||||
// simple vis supplying mode
|
||||
void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data
|
||||
// quick and easy way to get vis working :)
|
||||
// needs at least 576 samples :)
|
||||
|
||||
// advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff.
|
||||
int (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd
|
||||
void (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in
|
||||
// advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff.
|
||||
int (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd
|
||||
int (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in
|
||||
|
||||
|
||||
// call this in Play() to tell the vis plug-ins the current output params.
|
||||
void (*VSASetInfo)(int nch, int srate);
|
||||
// call this in Play() to tell the vis plug-ins the current output params.
|
||||
void (*VSASetInfo)(int srate, int nch); // <-- Correct (benski, dec 2005).. old declaration had the params backwards
|
||||
|
||||
|
||||
// dsp plug-in processing:
|
||||
// (filled in by winamp, called by input plug)
|
||||
// dsp plug-in processing:
|
||||
// (filled in by winamp, calld by input plug)
|
||||
|
||||
// returns 1 if active (which means that the number of samples returned by dsp_dosamples
|
||||
// could be greater than went in.. Use it to estimate if you'll have enough room in the
|
||||
// output buffer
|
||||
int (*dsp_isactive)();
|
||||
// returns 1 if active (which means that the number of samples returned by dsp_dosamples
|
||||
// could be greater than went in.. Use it to estimate if you'll have enough room in the
|
||||
// output buffer
|
||||
int (*dsp_isactive)();
|
||||
|
||||
// returns number of samples to output. This can be as much as twice numsamples.
|
||||
// be sure to allocate enough buffer for samples, then.
|
||||
int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);
|
||||
// returns number of samples to output. This can be as much as twice numsamples.
|
||||
// be sure to allocate enough buffer for samples, then.
|
||||
int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);
|
||||
|
||||
|
||||
// eq stuff
|
||||
void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore.
|
||||
// eq stuff
|
||||
void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore.
|
||||
|
||||
// info setting (filled in by winamp)
|
||||
void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :)
|
||||
// info setting (filled in by winamp)
|
||||
void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :)
|
||||
|
||||
Out_Module *outMod; // filled in by winamp, optionally used :)
|
||||
Out_Module *outMod; // filled in by winamp, optionally used :)
|
||||
} In_Module;
|
||||
|
||||
// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param)
|
||||
// which determine if we can uninstall the plugin immediately or on winamp restart
|
||||
//
|
||||
// uninstall support was added from 5.0+ and uninstall now support from 5.5+
|
||||
// it is down to you to ensure that if uninstall now is returned that it will not cause a crash
|
||||
// (ie don't use if you've been subclassing the main window)
|
||||
#define IN_PLUGIN_UNINSTALL_NOW 0x1
|
||||
#define IN_PLUGIN_UNINSTALL_REBOOT 0x0
|
||||
|
||||
#endif
|
||||
|
@ -5,6 +5,11 @@
|
||||
** Copyright (c) 1998, Justin Frankel/Nullsoft Inc.
|
||||
*/
|
||||
|
||||
/* Winamp uses wchar_t filenames when this is on, so extra steps are needed.
|
||||
* To open unicode filenames it needs to use _wfopen, inside a WA_STREAMFILE to pass around */
|
||||
//#define UNICODE_INPUT_PLUGIN
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
@ -22,6 +27,7 @@
|
||||
#include "wa_ipc.h"
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
#ifndef VERSION
|
||||
#include "../version.h"
|
||||
#endif
|
||||
@ -33,14 +39,13 @@
|
||||
#define PLUGIN_DESCRIPTION "vgmstream plugin " VERSION " " __DATE__
|
||||
#define INI_NAME "plugin.ini"
|
||||
|
||||
|
||||
/* post when playback stops */
|
||||
#define WM_WA_MPEG_EOF WM_USER+2
|
||||
|
||||
In_Module input_module; /* the input module, declared at the bottom of this file */
|
||||
DWORD WINAPI __stdcall decode(void *arg);
|
||||
|
||||
char lastfn[MAX_PATH+1] = {0}; /* name of the currently playing file */
|
||||
short sample_buffer[576*2*2]; /* 576 16-bit samples, stereo, possibly doubled in size for DSP */
|
||||
|
||||
#define DEFAULT_FADE_SECONDS "10.00"
|
||||
#define DEFAULT_FADE_DELAY_SECONDS "0.00"
|
||||
@ -56,6 +61,18 @@ short sample_buffer[576*2*2]; /* 576 16-bit samples, stereo, possibly doubled in
|
||||
#define LOOP_FOREVER_INI_ENTRY "loop_forever"
|
||||
#define IGNORE_LOOP_INI_ENTRY "ignore_loop"
|
||||
|
||||
char *priority_strings[] = {"Idle","Lowest","Below Normal","Normal","Above Normal","Highest (not recommended)","Time Critical (not recommended)"};
|
||||
int priority_values[] = {THREAD_PRIORITY_IDLE,THREAD_PRIORITY_LOWEST,THREAD_PRIORITY_BELOW_NORMAL,THREAD_PRIORITY_NORMAL,THREAD_PRIORITY_ABOVE_NORMAL,THREAD_PRIORITY_HIGHEST,THREAD_PRIORITY_TIME_CRITICAL};
|
||||
|
||||
#define WINAMP_MAX_PATH 32768 /* originally 260+1 */
|
||||
in_char lastfn[WINAMP_MAX_PATH] = {0}; /* name of the currently playing file */
|
||||
|
||||
/* Winamp Play extension list, needed to accept/play and associate extensions in Windows */
|
||||
#define EXTENSION_LIST_SIZE VGM_EXTENSION_LIST_CHAR_SIZE * 6
|
||||
#define EXT_BUFFER_SIZE 200
|
||||
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
|
||||
|
||||
/* plugin config */
|
||||
double fade_seconds;
|
||||
double fade_delay_seconds;
|
||||
double loop_count;
|
||||
@ -63,11 +80,11 @@ int thread_priority;
|
||||
int loop_forever;
|
||||
int ignore_loop;
|
||||
|
||||
char *priority_strings[] = {"Idle","Lowest","Below Normal","Normal","Above Normal","Highest (not recommended)","Time Critical (not recommended)"};
|
||||
int priority_values[] = {THREAD_PRIORITY_IDLE,THREAD_PRIORITY_LOWEST,THREAD_PRIORITY_BELOW_NORMAL,THREAD_PRIORITY_NORMAL,THREAD_PRIORITY_ABOVE_NORMAL,THREAD_PRIORITY_HIGHEST,THREAD_PRIORITY_TIME_CRITICAL};
|
||||
|
||||
/* plugin state */
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
HANDLE decode_thread_handle = INVALID_HANDLE_VALUE;
|
||||
short sample_buffer[576*2*2]; /* 576 16-bit samples, stereo, possibly doubled in size for DSP */
|
||||
|
||||
int paused = 0;
|
||||
int decode_abort = 0;
|
||||
int seek_needed_samples = -1;
|
||||
@ -76,15 +93,110 @@ int decode_pos_samples = 0;
|
||||
int stream_length_samples = 0;
|
||||
int fade_samples = 0;
|
||||
|
||||
/* Winamp Play extension list, needed to accept/play and associate extensions in Windows */
|
||||
#define EXTENSION_LIST_SIZE VGM_EXTENSION_LIST_CHAR_SIZE * 6
|
||||
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
|
||||
#define EXT_BUFFER_SIZE 200
|
||||
/* ***************************************** */
|
||||
|
||||
static void add_extension(int length, char * dst, const char * src);
|
||||
static void build_extension_list();
|
||||
/* Winamp INI reader */
|
||||
static void GetINIFileName(char * iniFile) {
|
||||
/* if we're running on a newer winamp version that better supports
|
||||
* saving of settings to a per-user directory, use that directory - if not
|
||||
* then just revert to the old behaviour */
|
||||
|
||||
if(IsWindow(input_module.hMainWindow) && SendMessage(input_module.hMainWindow, WM_WA_IPC,0,IPC_GETVERSION) >= 0x5000) {
|
||||
char * iniDir = (char *)SendMessage(input_module.hMainWindow, WM_WA_IPC, 0, IPC_GETINIDIRECTORY);
|
||||
strncpy(iniFile, iniDir, WINAMP_MAX_PATH);
|
||||
|
||||
strncat(iniFile, "\\Plugins\\", WINAMP_MAX_PATH);
|
||||
/* can't be certain that \Plugins already exists in the user dir */
|
||||
CreateDirectory(iniFile,NULL);
|
||||
strncat(iniFile, INI_NAME, WINAMP_MAX_PATH);
|
||||
}
|
||||
else {
|
||||
char * lastSlash;
|
||||
|
||||
GetModuleFileName(NULL, iniFile, WINAMP_MAX_PATH);
|
||||
lastSlash = strrchr(iniFile, '\\');
|
||||
|
||||
*(lastSlash + 1) = 0;
|
||||
strncat(iniFile, "Plugins\\" INI_NAME,WINAMP_MAX_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adds ext to Winamp's extension list */
|
||||
static void add_extension(int length, char * dst, const char * ext) {
|
||||
char buf[EXT_BUFFER_SIZE];
|
||||
char ext_upp[EXT_BUFFER_SIZE];
|
||||
int ext_len, written;
|
||||
int i,j;
|
||||
if (length <= 1)
|
||||
return;
|
||||
|
||||
ext_len = strlen(ext);
|
||||
|
||||
/* find end of dst (double \0), saved in i */
|
||||
for (i=0; i<length-2 && (dst[i] || dst[i+1]); i++)
|
||||
;
|
||||
|
||||
/* check if end reached or not enough room to add */
|
||||
if (i == length-2 || i + EXT_BUFFER_SIZE+2 > length-2 || ext_len * 3 + 20+2 > EXT_BUFFER_SIZE) {
|
||||
dst[i]='\0';
|
||||
dst[i+1]='\0';
|
||||
return;
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
i++;
|
||||
|
||||
/* uppercase ext */
|
||||
for (j=0; j < ext_len; j++)
|
||||
ext_upp[j] = toupper(ext[j]);
|
||||
ext_upp[j] = '\0';
|
||||
|
||||
/* copy new extension + double null terminate */
|
||||
written = sprintf(buf, "%s%c%s Audio File (*.%s)%c", ext,'\0',ext_upp,ext_upp,'\0'); /*ex: "vgmstream\0vgmstream Audio File (*.VGMSTREAM)\0" */
|
||||
for (j=0; j < written; i++,j++)
|
||||
dst[i] = buf[j];
|
||||
dst[i]='\0';
|
||||
dst[i+1]='\0';
|
||||
}
|
||||
|
||||
/* Creates Winamp's extension list, a single string that ends with \0\0.
|
||||
* Each extension must be in this format: "extension\0Description\0" */
|
||||
static void build_extension_list() {
|
||||
const char ** ext_list;
|
||||
int ext_list_len;
|
||||
int i;
|
||||
|
||||
working_extension_list[0]='\0';
|
||||
working_extension_list[1]='\0';
|
||||
|
||||
ext_list = vgmstream_get_formats();
|
||||
ext_list_len = vgmstream_get_formats_length();
|
||||
|
||||
for (i=0; i < ext_list_len; i++) {
|
||||
add_extension(EXTENSION_LIST_SIZE, working_extension_list, ext_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* unicode utils */
|
||||
static void copy_title(in_char * dst, int dst_size, const in_char * src) {
|
||||
#ifdef UNICODE_INPUT_PLUGIN
|
||||
in_char *p = (in_char*)src + wcslen(src); /* find end */
|
||||
while (*p != '\\' && p >= src) /* and find last "\" */
|
||||
p--;
|
||||
p++;
|
||||
wcscpy(dst,p); /* copy filename only */
|
||||
#else
|
||||
in_char *p = (in_char*)src + strlen(src); /* find end */
|
||||
while (*p != '\\' && p >= src) /* and find last "\" */
|
||||
p--;
|
||||
p++;
|
||||
strcpy(dst,p); /* copy filename only */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ***************************************** */
|
||||
|
||||
/* about dialog */
|
||||
void about(HWND hwndParent) {
|
||||
MessageBox(hwndParent,
|
||||
PLUGIN_DESCRIPTION "\n"
|
||||
@ -92,36 +204,10 @@ void about(HWND hwndParent) {
|
||||
"http://sourceforge.net/projects/vgmstream"
|
||||
,"about in_vgmstream",MB_OK);
|
||||
}
|
||||
void quit() {}
|
||||
|
||||
void GetINIFileName(char * iniFile) {
|
||||
/* if we're running on a newer winamp version that better supports
|
||||
* saving of settings to a per-user directory, use that directory - if not
|
||||
* then just revert to the old behaviour */
|
||||
|
||||
if(IsWindow(input_module.hMainWindow) && SendMessage(input_module.hMainWindow, WM_WA_IPC,0,IPC_GETVERSION) >= 0x5000) {
|
||||
char * iniDir = (char *)SendMessage(input_module.hMainWindow, WM_WA_IPC, 0, IPC_GETINIDIRECTORY);
|
||||
strncpy(iniFile, iniDir, MAX_PATH);
|
||||
|
||||
strncat(iniFile, "\\Plugins\\", MAX_PATH);
|
||||
/* can't be certain that \Plugins already exists in the user dir */
|
||||
CreateDirectory(iniFile,NULL);
|
||||
strncat(iniFile, INI_NAME, MAX_PATH);
|
||||
|
||||
}
|
||||
else {
|
||||
char * lastSlash;
|
||||
|
||||
GetModuleFileName(NULL, iniFile, MAX_PATH);
|
||||
lastSlash = strrchr(iniFile, '\\');
|
||||
|
||||
*(lastSlash + 1) = 0;
|
||||
strncat(iniFile, "Plugins\\" INI_NAME,MAX_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
/* called at program init */
|
||||
void init() {
|
||||
char iniFile[MAX_PATH+1];
|
||||
char iniFile[WINAMP_MAX_PATH];
|
||||
char buf[256];
|
||||
int consumed;
|
||||
|
||||
@ -167,19 +253,25 @@ void init() {
|
||||
build_extension_list();
|
||||
}
|
||||
|
||||
/* we don't recognize protocols */
|
||||
int isourfile(char *fn) { return 0; }
|
||||
/* called at program quit */
|
||||
void quit() {
|
||||
}
|
||||
|
||||
/* called before extension checks, to allow detection of mms://, etc */
|
||||
int isourfile(const in_char *fn) {
|
||||
return 0; /* we don't recognize protocols */
|
||||
}
|
||||
|
||||
/* request to start playing a file */
|
||||
int play(char *fn)
|
||||
{
|
||||
int play(const in_char *fn) {
|
||||
int max_latency;
|
||||
|
||||
/* don't lose a pointer! */
|
||||
if (vgmstream) {
|
||||
/* TODO: this should either pop up an error box or close the file */
|
||||
return 1;
|
||||
return 1; /* error */
|
||||
}
|
||||
|
||||
/* open the stream, set up */
|
||||
vgmstream = init_vgmstream(fn);
|
||||
/* were we able to open it? */
|
||||
@ -191,11 +283,11 @@ int play(char *fn)
|
||||
if (vgmstream->channels <= 0) {
|
||||
close_vgmstream(vgmstream);
|
||||
vgmstream=NULL;
|
||||
return 1;
|
||||
return 1; /* error */
|
||||
}
|
||||
|
||||
/* Remember that name, friends! */
|
||||
strncpy(lastfn,fn,MAX_PATH);
|
||||
strncpy(lastfn,fn,WINAMP_MAX_PATH);
|
||||
|
||||
/* open the output plugin */
|
||||
max_latency = input_module.outMod->Open(vgmstream->sample_rate,vgmstream->channels,
|
||||
@ -204,7 +296,7 @@ int play(char *fn)
|
||||
if (max_latency < 0) {
|
||||
close_vgmstream(vgmstream);
|
||||
vgmstream=NULL;
|
||||
return 1;
|
||||
return 1; /* error */
|
||||
}
|
||||
|
||||
/* Set info display */
|
||||
@ -234,15 +326,27 @@ int play(char *fn)
|
||||
|
||||
SetThreadPriority(decode_thread_handle,priority_values[thread_priority]);
|
||||
|
||||
return 0;
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
/* pausing... */
|
||||
void pause() { paused=1; input_module.outMod->Pause(1); }
|
||||
void unpause() {paused=0; input_module.outMod->Pause(0); }
|
||||
int ispaused() { return paused; }
|
||||
/* pause stream */
|
||||
void pause() {
|
||||
paused=1;
|
||||
input_module.outMod->Pause(1);
|
||||
}
|
||||
|
||||
/* stop playback */
|
||||
/* unpause stream */
|
||||
void unpause() {
|
||||
paused=0;
|
||||
input_module.outMod->Pause(0);
|
||||
}
|
||||
|
||||
/* ispaused? return 1 if paused, 0 if not */
|
||||
int ispaused() {
|
||||
return paused;
|
||||
}
|
||||
|
||||
/* stop (unload) stream */
|
||||
void stop() {
|
||||
if (decode_thread_handle != INVALID_HANDLE_VALUE) {
|
||||
decode_abort=1;
|
||||
@ -265,31 +369,34 @@ void stop() {
|
||||
input_module.SAVSADeInit();
|
||||
}
|
||||
|
||||
/* get current stream length */
|
||||
/* get length in ms */
|
||||
int getlength() {
|
||||
return stream_length_samples*1000LL/vgmstream->sample_rate;
|
||||
}
|
||||
|
||||
/* get current output time */
|
||||
/* current output time in ms */
|
||||
int getoutputtime() {
|
||||
return decode_pos_ms+(input_module.outMod->GetOutputTime()-input_module.outMod->GetWrittenTime());
|
||||
}
|
||||
|
||||
/* seek */
|
||||
/* seeks to point in stream (in ms) */
|
||||
void setoutputtime(int t) {
|
||||
if (vgmstream)
|
||||
seek_needed_samples = (long long)t * vgmstream->sample_rate / 1000LL;
|
||||
}
|
||||
|
||||
/* pass these commands through */
|
||||
void setvolume(int volume) { input_module.outMod->SetVolume(volume); }
|
||||
void setpan(int pan) { input_module.outMod->SetPan(pan); }
|
||||
void setvolume(int volume) {
|
||||
input_module.outMod->SetVolume(volume);
|
||||
}
|
||||
void setpan(int pan) {
|
||||
input_module.outMod->SetPan(pan);
|
||||
}
|
||||
|
||||
/* display information */
|
||||
int infoDlg(char *fn, HWND hwnd) {
|
||||
int infoDlg(const in_char *fn, HWND hwnd) {
|
||||
VGMSTREAM * infostream = NULL;
|
||||
char description[1024];
|
||||
description[0]='\0';
|
||||
char description[1024] = {0};
|
||||
|
||||
concatn(sizeof(description),description,PLUGIN_DESCRIPTION "\n\n");
|
||||
|
||||
@ -297,7 +404,7 @@ int infoDlg(char *fn, HWND hwnd) {
|
||||
if (!vgmstream) return 0;
|
||||
describe_vgmstream(vgmstream,description,sizeof(description));
|
||||
} else {
|
||||
infostream = init_vgmstream(fn);
|
||||
infostream = init_vgmstream((char*)fn);
|
||||
if (!infostream) return 0;
|
||||
describe_vgmstream(infostream,description,sizeof(description));
|
||||
close_vgmstream(infostream);
|
||||
@ -309,43 +416,44 @@ int infoDlg(char *fn, HWND hwnd) {
|
||||
}
|
||||
|
||||
/* retrieve information on this or possibly another file */
|
||||
void getfileinfo(char *filename, char *title, int *length_in_ms) {
|
||||
if (!filename || !*filename) /* currently playing file*/
|
||||
void getfileinfo(const in_char *filename, in_char *title, int *length_in_ms) {
|
||||
|
||||
if (!filename || !*filename) /* no filename = use currently playing file */
|
||||
{
|
||||
if (!vgmstream) return;
|
||||
if (length_in_ms) *length_in_ms=getlength();
|
||||
if (title)
|
||||
{
|
||||
char *p=lastfn+strlen(lastfn);
|
||||
while (*p != '\\' && p >= lastfn) p--;
|
||||
strcpy(title,++p);
|
||||
if (!vgmstream)
|
||||
return;
|
||||
if (length_in_ms)
|
||||
*length_in_ms = getlength();
|
||||
|
||||
if (title) {
|
||||
copy_title(title,GETFILEINFO_TITLE_LENGTH, lastfn);
|
||||
}
|
||||
}
|
||||
else /* some other file */
|
||||
{
|
||||
VGMSTREAM * infostream;
|
||||
if (length_in_ms)
|
||||
{
|
||||
|
||||
if (length_in_ms) {
|
||||
*length_in_ms=-1000;
|
||||
if ((infostream=init_vgmstream(filename)))
|
||||
{
|
||||
|
||||
if ((infostream=init_vgmstream(filename))) {
|
||||
*length_in_ms = get_vgmstream_play_samples(loop_count,fade_seconds,fade_delay_seconds,infostream)*1000LL/infostream->sample_rate;
|
||||
|
||||
close_vgmstream(infostream);
|
||||
infostream=NULL;
|
||||
}
|
||||
}
|
||||
if (title)
|
||||
{
|
||||
char *p=filename+strlen(filename);
|
||||
while (*p != '\\' && p >= filename) p--;
|
||||
strcpy(title,++p);
|
||||
|
||||
if (title) {
|
||||
copy_title(title,GETFILEINFO_TITLE_LENGTH, filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* nothin' */
|
||||
void eq_set(int on, char data[10], int preamp) {}
|
||||
/* eq stuff */
|
||||
void eq_set(int on, char data[10], int preamp) {
|
||||
/* nothin' */
|
||||
}
|
||||
|
||||
/* the decode thread */
|
||||
DWORD WINAPI __stdcall decode(void *arg) {
|
||||
@ -439,7 +547,7 @@ DWORD WINAPI __stdcall decode(void *arg) {
|
||||
|
||||
INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
char buf[256];
|
||||
char iniFile[MAX_PATH+1];
|
||||
char iniFile[WINAMP_MAX_PATH];
|
||||
static int mypri;
|
||||
HANDLE hSlider;
|
||||
|
||||
@ -587,12 +695,16 @@ INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* configuration dialog */
|
||||
void config(HWND hwndParent) {
|
||||
/* defined in resource.rc */
|
||||
DialogBox(input_module.hDllInstance, (const char *)IDD_CONFIG, hwndParent, configDlgProc);
|
||||
}
|
||||
|
||||
In_Module input_module =
|
||||
{
|
||||
/* *********************************** */
|
||||
|
||||
/* main plugin def */
|
||||
In_Module input_module = {
|
||||
IN_VER,
|
||||
PLUGIN_DESCRIPTION,
|
||||
0, /* hMainWindow */
|
||||
@ -624,68 +736,6 @@ In_Module input_module =
|
||||
0 // out_mod
|
||||
};
|
||||
|
||||
__declspec( dllexport ) In_Module * winampGetInModule2()
|
||||
{
|
||||
__declspec( dllexport ) In_Module * winampGetInModule2() {
|
||||
return &input_module;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates Winamp's extension list, a single string that ends with \0\0.
|
||||
* Each extension must be in this format: "extension\0Description\0"
|
||||
*/
|
||||
static void build_extension_list() {
|
||||
const char ** ext_list;
|
||||
int ext_list_len;
|
||||
int i;
|
||||
|
||||
working_extension_list[0]='\0';
|
||||
working_extension_list[1]='\0';
|
||||
|
||||
ext_list = vgmstream_get_formats();
|
||||
ext_list_len = vgmstream_get_formats_length();
|
||||
|
||||
for (i=0; i < ext_list_len; i++) {
|
||||
add_extension(EXTENSION_LIST_SIZE, working_extension_list, ext_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds ext to Winamp's extension list.
|
||||
*/
|
||||
static void add_extension(int length, char * dst, const char * ext) {
|
||||
char buf[EXT_BUFFER_SIZE];
|
||||
char ext_upp[EXT_BUFFER_SIZE];
|
||||
int ext_len, written;
|
||||
int i,j;
|
||||
if (length <= 1)
|
||||
return;
|
||||
|
||||
ext_len = strlen(ext);
|
||||
|
||||
/* find end of dst (double \0), saved in i */
|
||||
for (i=0; i<length-2 && (dst[i] || dst[i+1]); i++)
|
||||
;
|
||||
|
||||
/* check if end reached or not enough room to add */
|
||||
if (i == length-2 || i + EXT_BUFFER_SIZE+2 > length-2 || ext_len * 3 + 20+2 > EXT_BUFFER_SIZE) {
|
||||
dst[i]='\0';
|
||||
dst[i+1]='\0';
|
||||
return;
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
i++;
|
||||
|
||||
/* uppercase ext */
|
||||
for (j=0; j < ext_len; j++)
|
||||
ext_upp[j] = toupper(ext[j]);
|
||||
ext_upp[j] = '\0';
|
||||
|
||||
/* copy new extension + double null terminate */
|
||||
written = sprintf(buf, "%s%c%s Audio File (*.%s)%c", ext,'\0',ext_upp,ext_upp,'\0'); /*ex: "vgmstream\0vgmstream Audio File (*.VGMSTREAM)\0" */
|
||||
for (j=0; j < written; i++,j++)
|
||||
dst[i] = buf[j];
|
||||
dst[i]='\0';
|
||||
dst[i+1]='\0';
|
||||
}
|
||||
|
85
winamp/out.h
85
winamp/out.h
@ -1,52 +1,73 @@
|
||||
#ifndef NULLSOFT_OUTH
|
||||
#define NULLSOFT_OUTH
|
||||
#include <windows.h>
|
||||
#include <stddef.h>
|
||||
// ids:
|
||||
// waveout: 32
|
||||
// gapless: 64
|
||||
// xfade: 63
|
||||
// disk: 33
|
||||
// dsound: 38
|
||||
// NULL: 65
|
||||
// mm2: 69
|
||||
|
||||
#if (_MSC_VER <= 1200)
|
||||
typedef int intptr_t;
|
||||
#endif
|
||||
|
||||
#define OUT_VER 0x10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int version; // module version (OUT_VER)
|
||||
char *description; // description of module, with version string
|
||||
int id; // module id. each input module gets its own. non-nullsoft modules should
|
||||
// be >= 65536.
|
||||
int version; // module version (OUT_VER)
|
||||
char *description; // description of module, with version string
|
||||
intptr_t id; // module id. each input module gets its own. non-nullsoft modules should
|
||||
// be >= 65536.
|
||||
|
||||
HWND hMainWindow; // winamp's main window (filled in by winamp)
|
||||
HINSTANCE hDllInstance; // DLL instance handle (filled in by winamp)
|
||||
HWND hMainWindow; // winamp's main window (filled in by winamp)
|
||||
HINSTANCE hDllInstance; // DLL instance handle (filled in by winamp)
|
||||
|
||||
void (*Config)(HWND hwndParent); // configuration dialog
|
||||
void (*About)(HWND hwndParent); // about dialog
|
||||
void (*Config)(HWND hwndParent); // configuration dialog
|
||||
void (*About)(HWND hwndParent); // about dialog
|
||||
|
||||
void (*Init)(); // called when loaded
|
||||
void (*Quit)(); // called when unloaded
|
||||
void (*Init)(); // called when loaded
|
||||
void (*Quit)(); // called when unloaded
|
||||
|
||||
int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms);
|
||||
// returns >=0 on success, <0 on failure
|
||||
// NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins.
|
||||
// ... so don't expect the max latency returned to be what you asked for.
|
||||
// returns max latency in ms (0 for diskwriters, etc)
|
||||
// bufferlenms and prebufferms must be in ms. 0 to use defaults.
|
||||
// prebufferms must be <= bufferlenms
|
||||
int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms);
|
||||
// returns >=0 on success, <0 on failure
|
||||
|
||||
void (*Close)(); // close the ol' output device.
|
||||
// NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins.
|
||||
// ... so don't expect the max latency returned to be what you asked for.
|
||||
// returns max latency in ms (0 for diskwriters, etc)
|
||||
// bufferlenms and prebufferms must be in ms. 0 to use defaults.
|
||||
// prebufferms must be <= bufferlenms
|
||||
// pass bufferlenms==-666 to tell the output plugin that it's clock is going to be used to sync video
|
||||
// out_ds turns off silence-eating when -666 is passed
|
||||
|
||||
int (*Write)(char *buf, int len);
|
||||
// 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data.
|
||||
// 1 returns not able to write (yet). Non-blocking, always.
|
||||
void (*Close)(); // close the ol' output device.
|
||||
|
||||
int (*CanWrite)(); // returns number of bytes possible to write at a given time.
|
||||
// Never will decrease unless you call Write (or Close, heh)
|
||||
int (*Write)(char *buf, int len);
|
||||
// 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data.
|
||||
// 1 returns not able to write (yet). Non-blocking, always.
|
||||
|
||||
int (*IsPlaying)(); // non0 if output is still going or if data in buffers waiting to be
|
||||
// written (i.e. closing while IsPlaying() returns 1 would truncate the song
|
||||
int (*CanWrite)(); // returns number of bytes possible to write at a given time.
|
||||
// Never will decrease unless you call Write (or Close, heh)
|
||||
|
||||
int (*Pause)(int pause); // returns previous pause state
|
||||
int (*IsPlaying)(); // non0 if output is still going or if data in buffers waiting to be
|
||||
// written (i.e. closing while IsPlaying() returns 1 would truncate the song
|
||||
|
||||
void (*SetVolume)(int volume); // volume is 0-255
|
||||
void (*SetPan)(int pan); // pan is -128 to 128
|
||||
int (*Pause)(int pause); // returns previous pause state
|
||||
|
||||
void (*Flush)(int t); // flushes buffers and restarts output at time t (in ms)
|
||||
// (used for seeking)
|
||||
void (*SetVolume)(int volume); // volume is 0-255
|
||||
void (*SetPan)(int pan); // pan is -128 to 128
|
||||
|
||||
int (*GetOutputTime)(); // returns played time in MS
|
||||
int (*GetWrittenTime)(); // returns time written in MS (used for synching up vis stuff)
|
||||
void (*Flush)(int t); // flushes buffers and restarts output at time t (in ms)
|
||||
// (used for seeking)
|
||||
|
||||
int (*GetOutputTime)(); // returns played time in MS
|
||||
int (*GetWrittenTime)(); // returns time written in MS (used for synching up vis stuff)
|
||||
|
||||
} Out_Module;
|
||||
|
||||
|
||||
#endif
|
||||
|
1256
winamp/wa_ipc.h
1256
winamp/wa_ipc.h
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user