mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 09:40:51 +01:00
b462417ddf
git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@206 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
254 lines
9.9 KiB
C
254 lines
9.9 KiB
C
/*
|
|
* vgmstream.h - definitions for VGMSTREAM, encapsulating a multi-channel, looped audio stream
|
|
*/
|
|
|
|
#ifndef _VGMSTREAM_H
|
|
#define _VGMSTREAM_H
|
|
|
|
#include "streamfile.h"
|
|
#include "coding/g72x_state.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 */
|
|
/* 8-bit PCM */
|
|
coding_PCM8, /* 8-bit PCM */
|
|
/* 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_XA, /* PSX CD-XA */
|
|
coding_XBOX, /* XBOX IMA */
|
|
coding_EAXA, /* EA/XA 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 */
|
|
#if 0
|
|
layout_interleave_byte, /* full byte interleave */
|
|
#endif
|
|
/* headered blocks */
|
|
layout_ast_blocked, /* .ast STRM with BLCK blocks*/
|
|
layout_halpst_blocked, /* blocks with HALPST-format header */
|
|
layout_xa_blocked,
|
|
layout_xbox_blocked,
|
|
layout_ea_blocked,
|
|
layout_caf_blocked,
|
|
#if 0
|
|
layout_strm_blocked, /* */
|
|
#endif
|
|
/* otherwise odd */
|
|
layout_dtk_interleave, /* dtk interleaves channels by nibble */
|
|
} 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 */
|
|
|
|
/* 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 */
|
|
/* CRI ADX */
|
|
meta_ADX_03, /* ADX "type 03" */
|
|
meta_ADX_04, /* ADX "type 04" */
|
|
meta_ADX_05, /* ADX "type 05" */
|
|
|
|
/* 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_XBOX_WAVM, /* XBOX WAVM File */
|
|
meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */
|
|
|
|
meta_EAXA_R2, /* EA XA Release 2 */
|
|
meta_EAXA_R3, /* EA XA Release 3 */
|
|
meta_EAXA_PSX, /* EA with PSX ADPCM */
|
|
|
|
meta_RAW, /* RAW PCM 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 */
|
|
|
|
/* 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 */
|
|
|
|
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 */
|
|
|
|
uint8_t ea_big_endian; /* Big Endian ? */
|
|
uint8_t ea_compression_type;
|
|
uint8_t ea_compression_version;
|
|
uint8_t ea_platform;
|
|
|
|
void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream */
|
|
} VGMSTREAM;
|
|
|
|
/* 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);
|
|
|
|
/* 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
|