mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-17 20:07:08 +01:00
3a6c65c2b9
git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@521 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
569 lines
21 KiB
C
569 lines
21 KiB
C
/*
|
|
* vgmstream.h - definitions for VGMSTREAM, encapsulating a multi-channel, looped audio stream
|
|
*/
|
|
|
|
#ifndef _VGMSTREAM_H
|
|
#define _VGMSTREAM_H
|
|
|
|
/* Vorbis and MPEG decoding are 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) */
|
|
#define VGM_USE_VORBIS
|
|
#define VGM_USE_MPEG
|
|
|
|
#include "streamfile.h"
|
|
#include "coding/g72x_state.h"
|
|
#ifdef VGM_USE_VORBIS
|
|
#include <vorbis/vorbisfile.h>
|
|
#endif
|
|
#ifdef VGM_USE_MPEG
|
|
#include <mpg123.h>
|
|
#endif
|
|
#include "coding/acm_decoder.h"
|
|
#include "coding/nwa_decoder.h"
|
|
|
|
/* The encoding type specifies the format the sound data itself takes */
|
|
typedef enum {
|
|
/* 16-bit PCM */
|
|
coding_PCM16BE, /* big endian 16-bit PCM */
|
|
coding_PCM16LE, /* little endian 16-bit PCM */
|
|
coding_PCM16LE_int, /* little endian 16-bit PCM with sample-level
|
|
interleave handled by the decoder */
|
|
|
|
/* 8-bit PCM */
|
|
coding_PCM8, /* 8-bit PCM */
|
|
coding_PCM8_int, /* 8-Bit PCM with sample-level interleave handled
|
|
by the decoder */
|
|
coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement),
|
|
sample-level interleave */
|
|
coding_PCM8_U_int, /* 8-bit PCM, unsigned (0x80 = 0), sample-level
|
|
interleave */
|
|
|
|
/* 4-bit ADPCM */
|
|
coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */
|
|
coding_CRI_ADX, /* CRI ADX */
|
|
coding_NGC_DSP, /* NGC ADPCM, called DSP */
|
|
coding_NGC_DTK, /* NGC hardware disc ADPCM, called DTK, TRK or ADP */
|
|
coding_G721, /* CCITT G.721 ADPCM */
|
|
coding_NGC_AFC, /* NGC ADPCM, called AFC */
|
|
coding_PSX, /* PSX & PS2 ADPCM */
|
|
coding_invert_PSX, /* PSX ADPCM with first byte of frame inverted */
|
|
coding_PSX_badflags, /* with garbage in the flags byte */
|
|
coding_FFXI, /* FF XI PSX-ish ADPCM */
|
|
coding_XA, /* PSX CD-XA */
|
|
coding_XBOX, /* XBOX IMA */
|
|
coding_EAXA, /* EA/XA ADPCM */
|
|
coding_EA_ADPCM, /* EA ADPCM */
|
|
|
|
#ifdef VGM_USE_VORBIS
|
|
coding_ogg_vorbis, /* vorbis */
|
|
#endif
|
|
coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression */
|
|
coding_SDX2_int, /* SDX2 2:1 Squareroot-Delta-Exact compression,
|
|
with smaple-level interleave handled by the
|
|
decoder */
|
|
coding_DVI_IMA, /* DVI (bare IMA, high nibble first), aka ADP4 */
|
|
coding_INT_DVI_IMA, /* Interleaved DVI */
|
|
coding_EACS_IMA,
|
|
coding_IMA, /* bare IMA, low nibble first */
|
|
coding_INT_IMA, /* */
|
|
coding_WS, /* Westwood Studios' custom VBR ADPCM */
|
|
#ifdef VGM_USE_MPEG
|
|
coding_fake_MPEG2_L2, /* MPEG-2 Layer 2 (AHX), with lying headers */
|
|
/* I don't even know offhand if all these combinations exist... */
|
|
coding_MPEG1_L1,
|
|
coding_MPEG1_L2,
|
|
coding_MPEG1_L3, /* good ol' MPEG-1 Layer 3 (MP3) */
|
|
coding_MPEG2_L1,
|
|
coding_MPEG2_L2,
|
|
coding_MPEG2_L3,
|
|
coding_MPEG25_L1,
|
|
coding_MPEG25_L2,
|
|
coding_MPEG25_L3,
|
|
#endif
|
|
|
|
coding_ACM, /* InterPlay ACM */
|
|
/* compressed NWA at various levels */
|
|
coding_NWA0,
|
|
coding_NWA1,
|
|
coding_NWA2,
|
|
coding_NWA3,
|
|
coding_NWA4,
|
|
coding_NWA5,
|
|
|
|
coding_MSADPCM, /* Microsoft ADPCM */
|
|
coding_AICA, /* Yamaha AICA ADPCM */
|
|
} coding_t;
|
|
|
|
/* The layout type specifies how the sound data is laid out in the file */
|
|
typedef enum {
|
|
/* generic */
|
|
layout_none, /* straight data */
|
|
/* interleave */
|
|
layout_interleave, /* equal interleave throughout the stream */
|
|
layout_interleave_shortblock, /* interleave with a short last block */
|
|
|
|
layout_interleave_byte, /* full byte interleave */
|
|
|
|
/* headered blocks */
|
|
layout_ast_blocked, /* .ast STRM with BLCK blocks*/
|
|
layout_halpst_blocked, /* blocks with HALPST-format header */
|
|
layout_xa_blocked,
|
|
layout_ea_blocked,
|
|
layout_eacs_blocked,
|
|
layout_caf_blocked,
|
|
layout_wsi_blocked,
|
|
layout_str_snds_blocked,
|
|
layout_ws_aud_blocked,
|
|
layout_matx_blocked,
|
|
layout_de2_blocked,
|
|
layout_xvas_blocked,
|
|
layout_vs_blocked,
|
|
layout_emff_ps2_blocked,
|
|
layout_emff_ngc_blocked,
|
|
layout_gsb_blocked,
|
|
layout_thp_blocked,
|
|
layout_filp_blocked,
|
|
|
|
#if 0
|
|
layout_strm_blocked, /* */
|
|
#endif
|
|
/* otherwise odd */
|
|
layout_dtk_interleave, /* dtk interleaves channels by nibble */
|
|
#ifdef VGM_USE_VORBIS
|
|
layout_ogg_vorbis, /* ogg vorbis file */
|
|
#endif
|
|
#ifdef VGM_USE_MPEG
|
|
layout_fake_mpeg, /* MPEG audio stream with bad frame headers (AHX) */
|
|
layout_mpeg, /* proper MPEG audio stream */
|
|
#endif
|
|
layout_acm, /* dummy, let libacm handle layout */
|
|
layout_mus_acm, /* mus has multi-files to deal with */
|
|
layout_aix, /* CRI AIX's wheels within wheels */
|
|
} layout_t;
|
|
|
|
/* The meta type specifies how we know what we know about the file. We may know because of a header we read, some of it may have been guessed from filenames, etc. */
|
|
typedef enum {
|
|
/* DSP-specific */
|
|
meta_DSP_STD, /* standard GC ADPCM (DSP) header */
|
|
meta_DSP_CSTR, /* Star Fox Assault "Cstr" */
|
|
meta_DSP_RS03, /* Metroid Prime 2 "RS03" */
|
|
meta_DSP_STM, /* Paper Mario 2 STM */
|
|
meta_DSP_HALP, /* SSB:M "HALPST" */
|
|
meta_DSP_AGSC, /* Metroid Prime 2 title */
|
|
meta_DSP_MPDSP, /* Monopoly Party single header stereo */
|
|
meta_DSP_JETTERS, /* Bomberman Jetters .dsp */
|
|
meta_DSP_MSS,
|
|
meta_DSP_GCM,
|
|
meta_DSP_STR, /* Conan .str files */
|
|
meta_DSP_SADB, /* .sad */
|
|
meta_DSP_WSI, /* .wsi */
|
|
meta_DSP_AMTS, /* .amts */
|
|
meta_DSP_WII_IDSP, /* .gcm with IDSP header */
|
|
meta_DSP_WII_MUS, /* .mus */
|
|
|
|
/* Nintendo */
|
|
meta_STRM, /* STRM */
|
|
meta_RSTM, /* RSTM (similar to STRM) */
|
|
meta_AFC, /* AFC */
|
|
meta_AST, /* AST */
|
|
meta_RWSD, /* single-stream RWSD */
|
|
meta_RSTM_SPM, /* RSTM with 44->22khz hack */
|
|
meta_THP,
|
|
|
|
/* CRI ADX */
|
|
meta_ADX_03, /* ADX "type 03" */
|
|
meta_ADX_04, /* ADX "type 04" */
|
|
meta_ADX_05, /* ADX "type 05" */
|
|
meta_AIX, /* CRI AIX */
|
|
|
|
/* etc */
|
|
meta_NGC_ADPDTK, /* NGC DTK/ADP, no header (.adp) */
|
|
meta_kRAW, /* almost headerless PCM */
|
|
meta_RSF, /* Retro Studios RSF, no header (.rsf) */
|
|
meta_HALPST, /* HAL Labs HALPST */
|
|
meta_GCSW, /* GCSW (PCM) */
|
|
meta_CFN, /* Namco CAF Audio File */
|
|
|
|
meta_PS2_SShd, /* .ADS with SShd header */
|
|
meta_PS2_NPSF, /* Namco Production Sound File */
|
|
meta_PS2_RXW, /* Sony Arc The Lad Sound File */
|
|
meta_PS2_RAW, /* RAW Interleaved Format */
|
|
meta_PS2_EXST, /* Shadow of Colossus EXST */
|
|
meta_PS2_SVAG, /* Konami SVAG */
|
|
meta_PS2_MIB, /* MIB File */
|
|
meta_PS2_MIB_MIH, /* MIB File + MIH Header*/
|
|
meta_PS2_MIC, /* KOEI MIC File */
|
|
meta_PS2_VAGi, /* VAGi Interleaved File */
|
|
meta_PS2_VAGp, /* VAGp Mono File */
|
|
meta_PS2_VAGm, /* VAGp Mono File */
|
|
meta_PS2_pGAV, /* VAGp with Little Endian Header */
|
|
meta_PSX_GMS, /* GMS File (used in PS1 & PS2) */
|
|
meta_PS2_STR, /* Pacman STR+STH files */
|
|
meta_PS2_ILD, /* ILD File */
|
|
meta_PS2_PNB, /* PsychoNauts Bgm File */
|
|
meta_PSX_XA, /* CD-XA with RIFF header */
|
|
meta_PS2_VAGs, /* VAG Stereo from Kingdom Hearts */
|
|
meta_PS2_VPK, /* VPK Audio File */
|
|
meta_PS2_BMDX, /* Beatmania thing */
|
|
meta_PS2_IVB, /* Langrisser 3 IVB */
|
|
meta_PS2_SVS, /* Square SVS */
|
|
meta_XSS, /* Dino Crisis 3 */
|
|
meta_SL3, /* Test Drive Unlimited */
|
|
meta_HGC1, /* Knights of the Temple 2 */
|
|
meta_AUS, /* Variuos Capcom Games */
|
|
meta_RWS, /* Variuos Konami Games */
|
|
meta_FSB1, /* FMOD Sample Bank, version 1 */
|
|
meta_FSB3, /* FMOD Sample Bank, version 3 */
|
|
meta_FSB4, /* FMOD Sample Bank, version 4 */
|
|
meta_RWX, /* Air Force Delta Storm (XBOX) */
|
|
meta_XWB, /* King of Fighters (XBOX) */
|
|
meta_XA30, /* Driver - Parallel Lines (PS2) */
|
|
meta_MUSC, /* Spyro Games, possibly more */
|
|
meta_MUSX_V004, /* Spyro Games, possibly more */
|
|
meta_MUSX_V006, /* Spyro Games, possibly more */
|
|
meta_MUSX_V010, /* Spyro Games, possibly more */
|
|
meta_MUSX_V201, /* Sphinx and the cursed Mummy */
|
|
meta_LEG, /* Legaia 2 */
|
|
meta_FILP, /* Resident Evil - Dead Aim */
|
|
meta_IKM, /* Zwei! */
|
|
meta_SFS, /* Baroque */
|
|
meta_BG00, /* Ibara, Mushihimesama */
|
|
meta_PS2_RSTM, /* Midnight Club 3 */
|
|
meta_PS2_KCES, /* Dance Dance Revolution */
|
|
meta_PS2_DXH, /* Tokobot Plus - Myteries of the Karakuri */
|
|
meta_PS2_PSH, /* Dawn of Mana - Seiken Densetsu 4 */
|
|
meta_PCM, /* Ephemeral Fantasia, Lunar - Eternal Blue */
|
|
meta_PS2_RKV, /* Legacy of Kain - Blood Omen 2 */
|
|
meta_PS2_PSW, /* Rayman Raving Rabbids */
|
|
meta_PS2_VAS, /* Pro Baseball Spirits 5 */
|
|
meta_PS2_TEC, /* TECMO badflagged stream */
|
|
meta_PS2_ENTH, /* Enthusia */
|
|
meta_SDT, /* Baldur's Gate - Dark Alliance */
|
|
meta_NGC_TYDSP, /* Ty - The Tasmanian Tiger */
|
|
meta_NGC_SWD, /* Conflict - Desert Storm 1 & 2 */
|
|
meta_NGC_VJDSP, /* Viewtiful Joe */
|
|
meta_DC_STR, /* Evil Dead */
|
|
meta_NGC_BH2PCM, /* Bio Hazard 2 */
|
|
meta_SAT_SAP, /* Bubble Symphony */
|
|
meta_DC_IDVI, /* Eldorado Gate */
|
|
meta_KRAW, /* Geometry Wars - Galaxies */
|
|
meta_PS2_OMU, /* PS2 Int file with Header */
|
|
meta_PS2_XA2, /* XA2 XG3 file */
|
|
meta_IDSP, /* Chronicles of Narnia */
|
|
meta_SPT_SPD, /* Variouis */
|
|
meta_ISH_ISD, /* Various */
|
|
meta_GSP_GSB, /* Various */
|
|
meta_YDSP, /* WWE Day of Reckoning */
|
|
|
|
meta_IDSP2, /* Chronicles of Narnia */
|
|
meta_WAA_WAC_WAD_WAM, /* Beyond Good & Evil */
|
|
meta_GCA, /* Metal Slug Anthology */
|
|
meta_MSVP, /* Popcap Hits */
|
|
meta_NGC_SSM, /* Golden Gashbell Full Power */
|
|
meta_PS2_JOE, /* Wall-E / Pixar games */
|
|
|
|
meta_NGC_YMF, /* WWE WrestleMania X8 */
|
|
meta_SADL, /* .sad */
|
|
meta_PS2_CCC, /* Tokyo Xtreme Racer DRIFT 2 */
|
|
meta_PSX_FAG, /* Jackie Chan - Stuntmaster */
|
|
meta_PS2_MIHB, /* Merged MIH+MIB */
|
|
meta_NGC_PDT, /* Mario Party 6 */
|
|
meta_DC_ASD, /* Miss Moonligh */
|
|
meta_NAOMI_SPSD, /* Guilty Gear X */
|
|
|
|
meta_RSD2VAG, /* RSD2VAG */
|
|
meta_RSD2PCMB, /* RSD2PCMB */
|
|
meta_RSD2XADP, /* RSD2XADP */
|
|
meta_RSD3PCM, /* RSD3PCM */
|
|
meta_RSD4PCMB, /* RSD4PCMB */
|
|
meta_RSD4PCM, /* RSD4PCM */
|
|
meta_RSD4VAG, /* RSD4VAG */
|
|
meta_RSD6VAG, /* RSD6VAG */
|
|
meta_RSD6WADP, /* RSD6WADP */
|
|
meta_RSD6XADP, /* RSD6XADP */
|
|
|
|
meta_PS2_ASS, /* ASS */
|
|
meta_PS2_SEG, /* Eragon */
|
|
meta_NDS_STRM_FFTA2, /* Final Fantasy Tactics A2 */
|
|
meta_STR_ASR, /* Donkey Kong Jet Race */
|
|
meta_ZWDSP, /* Zack and Wiki */
|
|
meta_VGS, /* Guitar Hero Encore - Rocks the 80s */
|
|
meta_DC_WAV_DCS, /* Evil Twin - Cypriens Chronicles (DC) */
|
|
meta_WII_SMP, /* Mushroom Men - The Spore Wars */
|
|
meta_EMFF_PS2, /* Eidos Music File Format for PS2*/
|
|
meta_EMFF_NGC, /* Eidos Music File Format for NGC/WII */
|
|
|
|
meta_XBOX_WAVM, /* XBOX WAVM File */
|
|
meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */
|
|
meta_XBOX_WVS, /* XBOX WVS */
|
|
meta_XBOX_STMA, /* XBOX STMA */
|
|
meta_XBOX_MATX, /* XBOX MATX */
|
|
meta_XBOX_XMU, /* XBOX XMU */
|
|
meta_XBOX_XVAS, /* XBOX VAS */
|
|
|
|
meta_EAXA_R2, /* EA XA Release 2 */
|
|
meta_EAXA_R3, /* EA XA Release 3 */
|
|
meta_EAXA_PSX, /* EA with PSX ADPCM */
|
|
meta_EACS_PC, /* EACS PC */
|
|
meta_EACS_PSX, /* EACS PSX */
|
|
meta_EACS_SAT, /* EACS SATURN */
|
|
meta_EA_ADPCM, /* EA XA ADPCM */
|
|
meta_EA_IMA, /* EA IMA */
|
|
meta_EA_PCM, /* EA PCM */
|
|
|
|
meta_RAW, /* RAW PCM file */
|
|
|
|
meta_GENH, /* generic header */
|
|
|
|
#ifdef VGM_USE_VORBIS
|
|
meta_ogg_vorbis, /* ogg vorbis */
|
|
meta_OGG_SLI, /* Ogg Vorbis file w/ companion .sli for looping */
|
|
meta_OGG_SLI2, /* Ogg Vorbis file w/ different styled .sli for looping */
|
|
meta_OGG_SFL, /* Ogg Vorbis file w/ .sfl (RIFF SFPL) for looping */
|
|
meta_um3_ogg, /* Ogg Vorbis with first 0x800 bytes XOR 0xFF */
|
|
#endif
|
|
|
|
meta_AIFC, /* Audio Interchange File Format AIFF-C */
|
|
meta_AIFF, /* Audio Interchange File Format */
|
|
meta_STR_SNDS, /* .str with SNDS blocks and SHDR header */
|
|
meta_WS_AUD, /* Westwood Studios .aud */
|
|
meta_WS_AUD_old, /* Westwood Studios .aud, old style */
|
|
#ifdef VGM_USE_MPEG
|
|
meta_AHX, /* CRI AHX header (same structure as ADX) */
|
|
#endif
|
|
meta_RIFF_WAVE, /* RIFF, for WAVs */
|
|
meta_RIFF_WAVE_POS, /* .wav + .pos for looping */
|
|
meta_RIFF_WAVE_labl_Marker, /* RIFF w/ loop Markers in LIST-adtl-labl */
|
|
meta_RIFF_WAVE_smpl, /* RIFF w/ loop data in smpl chunk */
|
|
meta_NWA, /* Visual Art's NWA */
|
|
meta_NWA_NWAINFOINI, /* NWA w/ NWAINFO.INI for looping */
|
|
meta_NWA_GAMEEXEINI, /* NWA w/ Gameexe.ini for looping */
|
|
meta_DVI, /* DVI Interleaved */
|
|
meta_KCEY, /* KCEYCOMP */
|
|
meta_ACM, /* InterPlay ACM header */
|
|
meta_MUS_ACM, /* MUS playlist of InterPlay ACM files */
|
|
meta_DE2, /* Falcom (Gurumin) .de2 */
|
|
meta_VS, /* Men in Black .vs */
|
|
meta_FFXI_BGW, /* FFXI BGW */
|
|
meta_FFXI_SPW, /* FFXI SPW */
|
|
meta_STS_WII, /* Shikigami No Shiro 3 STS Audio File */
|
|
} meta_t;
|
|
|
|
typedef struct {
|
|
STREAMFILE * streamfile; /* file used by this channel */
|
|
off_t channel_start_offset; /* where data for this channel begins */
|
|
off_t offset; /* current location in the file */
|
|
|
|
off_t frame_header_offset; /* offset of the current frame header (for WS) */
|
|
int samples_left_in_frame; /* for WS */
|
|
|
|
/* format specific */
|
|
|
|
/* adpcm */
|
|
int16_t adpcm_coef[16]; /* for formats with decode coefficients built in */
|
|
union {
|
|
int16_t adpcm_history1_16; /* previous sample */
|
|
int32_t adpcm_history1_32;
|
|
};
|
|
union {
|
|
int16_t adpcm_history2_16; /* previous previous sample */
|
|
int32_t adpcm_history2_32;
|
|
};
|
|
|
|
int adpcm_step_index; /* for IMA */
|
|
int adpcm_scale; /* for MS ADPCM */
|
|
|
|
struct g72x_state g72x_state; /* state for G.721 decoder, sort of big but we
|
|
might as well keep it around */
|
|
|
|
#ifdef DEBUG
|
|
int samples_done;
|
|
int16_t loop_history1,loop_history2;
|
|
#endif
|
|
} VGMSTREAMCHANNEL;
|
|
|
|
typedef struct {
|
|
/* basics */
|
|
int32_t num_samples; /* the actual number of samples in this stream */
|
|
int32_t sample_rate; /* sample rate in Hz */
|
|
int channels; /* number of channels */
|
|
coding_t coding_type; /* type of encoding */
|
|
layout_t layout_type; /* type of layout for data */
|
|
meta_t meta_type; /* how we know the metadata */
|
|
|
|
/* looping */
|
|
int loop_flag; /* is this stream looped? */
|
|
int32_t loop_start_sample; /* first sample of the loop (included in the loop) */
|
|
int32_t loop_end_sample; /* last sample of the loop (not included in the loop) */
|
|
|
|
/* channels */
|
|
VGMSTREAMCHANNEL * ch; /* pointer to array of channels */
|
|
|
|
/* channel copies */
|
|
VGMSTREAMCHANNEL * start_ch; /* copies of channel status as they were at the beginning of the stream */
|
|
VGMSTREAMCHANNEL * loop_ch; /* copies of channel status as they were at the loop point */
|
|
|
|
/* layout-specific */
|
|
int32_t current_sample; /* number of samples we've passed */
|
|
int32_t samples_into_block; /* number of samples into the current block */
|
|
/* interleave */
|
|
size_t interleave_block_size; /* interleave for this file */
|
|
size_t interleave_smallblock_size; /* smaller interleave for last block */
|
|
/* headered blocks */
|
|
off_t current_block_offset; /* start of this block (offset of block header) */
|
|
size_t current_block_size; /* size of the block we're in now */
|
|
off_t next_block_offset; /* offset of header of the next block */
|
|
|
|
int hit_loop; /* have we seen the loop yet? */
|
|
|
|
/* loop layout (saved values) */
|
|
int32_t loop_sample; /* saved from current_sample, should be loop_start_sample... */
|
|
int32_t loop_samples_into_block; /* saved from samples_into_block */
|
|
off_t loop_block_offset; /* saved from current_block_offset */
|
|
size_t loop_block_size; /* saved from current_block_size */
|
|
off_t loop_next_block_offset; /* saved from next_block_offset */
|
|
|
|
uint8_t xa_channel; /* Selected XA Channel */
|
|
int32_t xa_sector_length; /* XA block */
|
|
int8_t get_high_nibble;
|
|
|
|
uint8_t ea_big_endian; /* Big Endian ? */
|
|
uint8_t ea_compression_type;
|
|
uint8_t ea_compression_version;
|
|
uint8_t ea_platform;
|
|
|
|
int32_t ws_output_size; /* output bytes for this block */
|
|
|
|
void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream */
|
|
|
|
int32_t thpNextFrameSize;
|
|
|
|
/* Data the codec needs for the whole stream. This is for codecs too
|
|
* different from vgmstream's structure to be reasonably shoehorned into
|
|
* using the ch structures.
|
|
* Note also that support must be added for resetting, looping and
|
|
* closing for every codec that uses this, as it will not be handled. */
|
|
void * codec_data;
|
|
} VGMSTREAM;
|
|
|
|
#ifdef VGM_USE_VORBIS
|
|
typedef struct {
|
|
STREAMFILE *streamfile;
|
|
ogg_int64_t offset;
|
|
ogg_int64_t size;
|
|
} ogg_vorbis_streamfile;
|
|
|
|
typedef struct {
|
|
OggVorbis_File ogg_vorbis_file;
|
|
int bitstream;
|
|
|
|
ogg_vorbis_streamfile ov_streamfile;
|
|
} ogg_vorbis_codec_data;
|
|
#endif
|
|
|
|
#ifdef VGM_USE_MPEG
|
|
#define AHX_EXPECTED_FRAME_SIZE 0x414
|
|
/* MPEG_BUFFER_SIZE should be >= AHX_EXPECTED_FRAME_SIZE */
|
|
#define MPEG_BUFFER_SIZE 0x1000
|
|
typedef struct {
|
|
uint8_t buffer[MPEG_BUFFER_SIZE];
|
|
int buffer_used;
|
|
int buffer_full;
|
|
size_t bytes_in_buffer;
|
|
mpg123_handle *m;
|
|
} mpeg_codec_data;
|
|
#endif
|
|
|
|
/* with one file this is also used for just
|
|
ACM */
|
|
typedef struct {
|
|
int file_count;
|
|
int current_file;
|
|
/* the index we return to upon loop completion */
|
|
int loop_start_file;
|
|
/* one after the index of the last file, typically
|
|
* will be equal to file_count */
|
|
int loop_end_file;
|
|
/* Upon exit from a loop, which file to play. */
|
|
/* -1 if there is no such file */
|
|
/*int end_file;*/
|
|
ACMStream **files;
|
|
} mus_acm_codec_data;
|
|
|
|
#define AIX_BUFFER_SIZE 0x1000
|
|
/* AIXery */
|
|
typedef struct {
|
|
sample buffer[AIX_BUFFER_SIZE];
|
|
int segment_count;
|
|
int stream_count;
|
|
int current_segment;
|
|
/* one per segment */
|
|
int32_t *sample_counts;
|
|
/* organized like:
|
|
* segment1_stream1, segment1_stream2, segment2_stream1, segment2_stream2*/
|
|
VGMSTREAM **adxs;
|
|
} aix_codec_data;
|
|
|
|
/* for compressed NWA */
|
|
typedef struct {
|
|
NWAData *nwa;
|
|
} nwa_codec_data;
|
|
|
|
/* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */
|
|
VGMSTREAM * init_vgmstream(const char * const filename);
|
|
|
|
VGMSTREAM * init_vgmstream_from_STREAMFILE(STREAMFILE *streamFile);
|
|
|
|
/* reset a VGMSTREAM to start of stream */
|
|
void reset_vgmstream(VGMSTREAM * vgmstream);
|
|
|
|
/* allocate a VGMSTREAM and channel stuff */
|
|
VGMSTREAM * allocate_vgmstream(int channel_count, int looped);
|
|
|
|
/* deallocate, close, etc. */
|
|
void close_vgmstream(VGMSTREAM * vgmstream);
|
|
|
|
/* calculate the number of samples to be played based on looping parameters */
|
|
int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM * vgmstream);
|
|
|
|
/* render! */
|
|
void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
|
|
|
/* smallest self-contained group of samples is a frame */
|
|
int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream);
|
|
/* number of bytes per frame */
|
|
int get_vgmstream_frame_size(VGMSTREAM * vgmstream);
|
|
/* in NDS IMA the frame size is the block size, so the last one is short */
|
|
int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream);
|
|
int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream);
|
|
|
|
/* Assume that we have written samples_written into the buffer already, and we have samples_to_do consecutive
|
|
* samples ahead of us. Decode those samples into the buffer. */
|
|
void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer);
|
|
|
|
/* Assume additionally that we have samples_to_do consecutive samples in "data",
|
|
* and this this is for channel number "channel" */
|
|
void decode_vgmstream_mem(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer, uint8_t * data, int channel);
|
|
|
|
/* calculate number of consecutive samples to do (taking into account stopping for loop start and end) */
|
|
int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM * vgmstream);
|
|
|
|
/* Detect start and save values, also detect end and restore values. Only works on exact sample values.
|
|
* Returns 1 if loop was done. */
|
|
int vgmstream_do_loop(VGMSTREAM * vgmstream);
|
|
|
|
/* Write a description of the stream into array pointed by desc,
|
|
* which must be length bytes long. Will always be null-terminated if length > 0
|
|
*/
|
|
void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length);
|
|
|
|
/* See if there is a second file which may be the second channel, given
|
|
* already opened mono opened_stream which was opened from filename.
|
|
* If a suitable file is found, open it and change opened_stream to a
|
|
* stereo stream. */
|
|
void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFile);
|
|
|
|
#endif
|