Merge pull request #667 from bnnm/svag-cleanup

svag cleanup
This commit is contained in:
bnnm 2020-07-18 10:43:48 +02:00 committed by GitHub
commit 41914bc09c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 2818 additions and 2734 deletions

View File

@ -135,6 +135,12 @@ standard, whose docs discuss extending M3U with arbitrary tags.
vgmstream aims to support most audio formats as-is, but some files require extra
handling.
### Subsongs
Certain container formats have multiple audio files, usually called "subsongs", often
not meant to be extracted (no simple separation). Some plugins are able to "unpack"
those files automatically into the playlist. For others without support, you can create
multiple .txtp (explained below) to select one of the subsongs (like `bgm.sxd#10.txtp`).
### Renamed files
A few extensions that vgmstream supports clash with common ones. Since players
like foobar or Winamp don't react well to that, they may be renamed to make
@ -264,7 +270,6 @@ loops, remove unneeded channels, and many other features.
Creation of those files is meant for advanced users, docs can be found in
vgmstream source.
### Plugin conflicts
Since vgmstream supports a huge amount of formats it's possibly that some of
them are also supported in other plugins, and this sometimes causes conflicts.
@ -283,7 +288,6 @@ need to disable some plugins (requires restart) or set priority on compile
time. Particularly, mpg123 plugin may steal formats that aren't even MP3,
making impossible for vgmstream to play it properly.
### Channel issues
Some games layer a huge number of channels, that are disabled or downmixed
during gameplay. The player may be unable to play those files (for example
@ -296,6 +300,7 @@ formats.
You can also choose which channels to play using *TXTP*. For example, create
a file named `song.adx#C1,2.txtp` to play only channels 1 and 2 from `song.adx`.
## Tagging
Some of vgmstream's plugins support simple read-only tagging via external files.
@ -320,7 +325,7 @@ separated by one or multiple spaces. Repeated tags overwrite previous
(ex.- may define *@COMPOSER* for multiple tracks). It only reads up to current
*filename* though, so any *@TAG* below would be ignored.
Playlist formatting should follow player's config. ASCII or UTF-8 tags work.
Playlist title formatting should follow player's config. ASCII or UTF-8 tags work.
*GLOBAL_COMMAND*s currently can be:
- *AUTOTRACK*: sets *%TRACK* tag automatically (1..N as files are encountered
@ -364,11 +369,15 @@ tags change (for reasons outside vgmstream's control):
Currently there is no tool to aid in the creation of there m3u, but you can create
a base m3u and edit as a text file.
vgmstream's "m3u tagging" is meant to be simple to make and share (just a text
file), easier to support in multiple players (rather than needed a custom plugin),
having OST-like ordering in the M3U, and be flexible enough to have commands.
If you are not satisfied with vgmstream's tagging format, foobar2000 has other
plugins (with write support) that may be of use:
- m-TAGS: http://www.m-tags.org/
- foo_external_tags: https://foobar.hyv.fi/?view=foo_external_tags
## Virtual TXTP files
Some of vgmstream's plugins allow you to use virtual .txtp files, that combined
with playlists let you make quick song configs.
@ -444,6 +453,7 @@ are used in few games.
- Argonaut ASF 4-bit ADPCM
- Ocean DSA 4-bit ADPCM
- Circus XPCM ADPCM
- Circus XPCM VQ
- OKI 4-bit ADPCM (16-bit output, 4-shift, PC-FX)
- Ubisoft 4/6-bit ADPCM
- Tiger Game.com ADPCM

View File

@ -5,17 +5,17 @@
/* libacm 1.2 (despite what libacm.h says) from: https://github.com/markokr/libacm */
typedef struct {
STREAMFILE *streamfile;
STREAMFILE* streamfile; /* reference */
int offset;
} acm_io_config;
static int acm_read_streamfile(void *ptr, int size, int n, void *arg);
static int acm_seek_streamfile(void *arg, int offset, int whence);
static int acm_get_length_streamfile(void *arg);
acm_codec_data *init_acm(STREAMFILE *streamFile, int force_channel_number) {
static int acm_read_streamfile(void* ptr, int size, int n, void* arg);
static int acm_seek_streamfile(void* arg, int offset, int whence);
static int acm_get_length_streamfile(void* arg);
acm_codec_data* init_acm(STREAMFILE* sf, int force_channel_number) {
acm_codec_data* data = NULL;
char filename[PATH_LIMIT];
data = calloc(1,sizeof(acm_codec_data));
@ -24,15 +24,14 @@ acm_codec_data *init_acm(STREAMFILE *streamFile, int force_channel_number) {
data->io_config = calloc(1,sizeof(acm_io_config));
if (!data->io_config) goto fail;
streamFile->get_name(streamFile,filename,sizeof(filename));
data->streamfile = open_streamfile(streamFile,filename);
data->streamfile = reopen_streamfile(sf, 0);
if (!data->streamfile) goto fail;
/* Setup libacm decoder, needs read callbacks and a parameter for said callbacks */
{
ACMStream *handle = NULL;
ACMStream* handle = NULL;
int res;
acm_io_config *io_config = data->io_config;
acm_io_config* io_config = data->io_config;
acm_io_callbacks io_callbacks = {0};
io_config->offset = 0;
@ -60,8 +59,8 @@ fail:
return NULL;
}
void decode_acm(acm_codec_data *data, sample * outbuf, int32_t samples_to_do, int channelspacing) {
ACMStream * acm = data->handle;
void decode_acm(acm_codec_data* data, sample_t* outbuf, int32_t samples_to_do, int channelspacing) {
ACMStream* acm = data->handle;
int32_t samples_read = 0;
while (samples_read < samples_to_do) {
@ -79,14 +78,14 @@ void decode_acm(acm_codec_data *data, sample * outbuf, int32_t samples_to_do, in
}
}
void reset_acm(acm_codec_data *data) {
void reset_acm(acm_codec_data* data) {
if (!data || !data->handle)
return;
acm_seek_pcm(data->handle, 0);
}
void free_acm(acm_codec_data *data) {
void free_acm(acm_codec_data* data) {
if (!data)
return;
@ -96,6 +95,11 @@ void free_acm(acm_codec_data *data) {
free(data);
}
STREAMFILE* acm_get_streamfile(acm_codec_data* data) {
if (!data) return NULL;
return data->streamfile;
}
/* ******************************* */
static int acm_read_streamfile(void *ptr, int size, int n, void *arg) {

View File

@ -4,6 +4,14 @@
#ifdef VGM_USE_MAIATRAC3PLUS
#include "maiatrac3plus.h"
struct maiatrac3plus_codec_data {
sample_t* buffer;
int channels;
int samples_discard;
void* handle;
};
maiatrac3plus_codec_data *init_at3plus() {
maiatrac3plus_codec_data *data = malloc(sizeof(maiatrac3plus_codec_data));

View File

@ -6,10 +6,10 @@
/* opaque struct */
struct atrac9_codec_data {
uint8_t *data_buffer;
uint8_t* data_buffer;
size_t data_buffer_size;
sample_t *sample_buffer;
sample_t* sample_buffer;
size_t samples_filled; /* number of samples in the buffer */
size_t samples_used; /* number of samples extracted from the buffer */
@ -17,15 +17,15 @@ struct atrac9_codec_data {
atrac9_config config;
void *handle; /* decoder handle */
void* handle; /* decoder handle */
Atrac9CodecInfo info; /* decoder info */
};
atrac9_codec_data *init_atrac9(atrac9_config *cfg) {
atrac9_codec_data* init_atrac9(atrac9_config* cfg) {
int status;
uint8_t config_data[4];
atrac9_codec_data *data = NULL;
atrac9_codec_data* data = NULL;
data = calloc(1, sizeof(atrac9_codec_data));
if (!data) goto fail;
@ -65,9 +65,9 @@ fail:
return NULL;
}
void decode_atrac9(VGMSTREAM *vgmstream, sample_t * outbuf, int32_t samples_to_do, int channels) {
VGMSTREAMCHANNEL *stream = &vgmstream->ch[0];
atrac9_codec_data * data = vgmstream->codec_data;
void decode_atrac9(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do, int channels) {
VGMSTREAMCHANNEL* stream = &vgmstream->ch[0];
atrac9_codec_data* data = vgmstream->codec_data;
int samples_done = 0;
@ -134,8 +134,7 @@ decode_fail:
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample) * channels);
}
void reset_atrac9(VGMSTREAM *vgmstream) {
atrac9_codec_data *data = vgmstream->codec_data;
void reset_atrac9(atrac9_codec_data* data) {
if (!data) return;
if (!data->handle)
@ -167,11 +166,11 @@ fail:
return; /* decode calls should fail... */
}
void seek_atrac9(VGMSTREAM *vgmstream, int32_t num_sample) {
atrac9_codec_data *data = vgmstream->codec_data;
void seek_atrac9(VGMSTREAM* vgmstream, int32_t num_sample) {
atrac9_codec_data* data = vgmstream->codec_data;
if (!data) return;
reset_atrac9(vgmstream);
reset_atrac9(data);
/* find closest offset to desired sample, and samples to discard after that offset to reach loop */
{
@ -212,7 +211,7 @@ void seek_atrac9(VGMSTREAM *vgmstream, int32_t num_sample) {
}
void free_atrac9(atrac9_codec_data *data) {
void free_atrac9(atrac9_codec_data* data) {
if (!data) return;
if (data->handle) Atrac9ReleaseHandle(data->handle);
@ -265,7 +264,7 @@ fail:
return 0;
}
size_t atrac9_bytes_to_samples(size_t bytes, atrac9_codec_data *data) {
size_t atrac9_bytes_to_samples(size_t bytes, atrac9_codec_data* data) {
return bytes / data->info.superframeSize * (data->info.frameSamples * data->info.framesInSuperframe);
}

View File

@ -4,16 +4,16 @@
#include "celt/celt_fsb.h"
#define FSB_CELT_0_06_1_VERSION 0x80000009 /* libcelt-0.6.1 */
#define FSB_CELT_0_11_0_VERSION 0x80000010 /* libcelt-0.6.1 */
#define FSB_CELT_0_11_0_VERSION 0x80000010 /* libcelt-0.11.0 */
#define FSB_CELT_SAMPLES_PER_FRAME 512
#define FSB_CELT_INTERNAL_SAMPLE_RATE 44100
#define FSB_CELT_MAX_DATA_SIZE 0x200 /* from 0x2e~0x172/1d0, all files are CBR though */
/* opaque struct */
struct celt_codec_data {
sample *buffer;
sample_t* buffer;
sample *sample_buffer;
sample_t* sample_buffer;
size_t samples_filled; /* number of samples in the buffer */
size_t samples_used; /* number of samples extracted from the buffer */
@ -31,7 +31,7 @@ struct celt_codec_data {
celt_codec_data *init_celt_fsb(int channels, celt_lib_t version) {
int error = 0, lib_version = 0;
celt_codec_data *data = NULL;
celt_codec_data* data = NULL;
data = calloc(1, sizeof(celt_codec_data));
@ -79,9 +79,9 @@ fail:
}
void decode_celt_fsb(VGMSTREAM *vgmstream, sample * outbuf, int32_t samples_to_do, int channels) {
VGMSTREAMCHANNEL *stream = &vgmstream->ch[0];
celt_codec_data * data = vgmstream->codec_data;
void decode_celt_fsb(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do, int channels) {
VGMSTREAMCHANNEL* stream = &vgmstream->ch[0];
celt_codec_data* data = vgmstream->codec_data;
int samples_done = 0;
@ -161,8 +161,7 @@ decode_fail:
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample) * channels);
}
void reset_celt_fsb(VGMSTREAM *vgmstream) {
celt_codec_data *data = vgmstream->codec_data;
void reset_celt_fsb(celt_codec_data* data) {
if (!data) return;
/* recreate decoder (mode should not change) */
@ -195,10 +194,10 @@ fail:
}
void seek_celt_fsb(VGMSTREAM *vgmstream, int32_t num_sample) {
celt_codec_data *data = vgmstream->codec_data;
celt_codec_data* data = vgmstream->codec_data;
if (!data) return;
reset_celt_fsb(vgmstream);
reset_celt_fsb(data);
data->samples_to_discard = num_sample;
@ -207,7 +206,7 @@ void seek_celt_fsb(VGMSTREAM *vgmstream, int32_t num_sample) {
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset;
}
void free_celt_fsb(celt_codec_data *data) {
void free_celt_fsb(celt_codec_data* data) {
if (!data) return;
switch(data->version) {

View File

@ -4,39 +4,41 @@
#include "../vgmstream.h"
/* adx_decoder */
void decode_adx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int32_t frame_bytes, coding_t coding_type);
void adx_next_key(VGMSTREAMCHANNEL * stream);
void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int32_t frame_bytes, coding_t coding_type);
void adx_next_key(VGMSTREAMCHANNEL* stream);
/* g721_decoder */
void decode_g721(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void g72x_init_state(struct g72x_state *state_ptr);
void decode_g721(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void g72x_init_state(struct g72x_state* state_ptr);
/* ima_decoder */
void decode_standard_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first);
void decode_3ds_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_otns_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_wv6_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_alp_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ffta2_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_blitz_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_mtf_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
void decode_standard_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first);
void decode_3ds_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_snds_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_otns_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_wv6_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_alp_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ffta2_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_blitz_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_mtf_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_ms_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_ref_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
void decode_xbox_ima_mch(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int codec_config);
void decode_h4m_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, uint16_t frame_format);
void decode_xbox_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
void decode_xbox_ima_mch(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_nds_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_dat4_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_rad_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_rad_ima_mono(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_apple_ima4(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_fsb_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_wwise_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_awc_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ubi_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int codec_config);
void decode_h4m_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, uint16_t frame_format);
void decode_cd_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
size_t ima_bytes_to_samples(size_t bytes, int channels);
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels);
@ -44,149 +46,187 @@ size_t xbox_ima_bytes_to_samples(size_t bytes, int channels);
size_t dat4_ima_bytes_to_samples(size_t bytes, int channels);
size_t apple_ima4_bytes_to_samples(size_t bytes, int channels);
/* ngc_dsp_decoder */
void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ngc_dsp_subint(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int interleave);
void decode_ngc_dsp(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ngc_dsp_subint(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int interleave);
size_t dsp_bytes_to_samples(size_t bytes, int channels);
int32_t dsp_nibbles_to_samples(int32_t nibbles);
void dsp_read_coefs_be(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing);
void dsp_read_coefs_le(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing);
void dsp_read_coefs(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing, int be);
void dsp_read_hist_be(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing);
void dsp_read_hist_le(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing);
void dsp_read_hist(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing, int be);
void dsp_read_coefs_be(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t offset, off_t spacing);
void dsp_read_coefs_le(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t offset, off_t spacing);
void dsp_read_coefs(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t offset, off_t spacing, int be);
void dsp_read_hist_be(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t offset, off_t spacing);
void dsp_read_hist_le(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t offset, off_t spacing);
void dsp_read_hist(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t offset, off_t spacing, int be);
/* ngc_dtk_decoder */
void decode_ngc_dtk(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ngc_dtk(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
/* ngc_afc_decoder */
void decode_ngc_afc(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ngc_afc(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* vadpcm_decoder */
void decode_vadpcm(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int order);
void decode_vadpcm(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int order);
//int32_t vadpcm_bytes_to_samples(size_t bytes, int channels);
void vadpcm_read_coefs_be(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t offset, int order, int entries, int ch);
/* pcm_decoder */
void decode_pcm16le(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16be(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
void decode_pcm8(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_unsigned(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_sb(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm4(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_pcm4_unsigned(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ulaw(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ulaw_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_alaw(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
void decode_pcm16le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16be(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16_int(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
void decode_pcm8(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_int(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_unsigned(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_sb(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm4(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_pcm4_unsigned(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ulaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ulaw_int(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_alaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcmfloat(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
/* psx_decoder */
void decode_psx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int is_badflags, int config);
void decode_psx_configurable(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size, int config);
void decode_psx_pivotal(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size);
int ps_find_loop_offsets(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t * out_loop_start, int32_t * out_loop_end);
int ps_find_loop_offsets_full(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t * out_loop_start, int32_t * out_loop_end);
size_t ps_find_padding(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int discard_empty);
void decode_psx_pivotal(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size);
int ps_find_loop_offsets(STREAMFILE* sf, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t* out_loop_start, int32_t* out_loop_end);
int ps_find_loop_offsets_full(STREAMFILE* sf, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t* out_loop_start, int32_t* out_loop_end);
size_t ps_find_padding(STREAMFILE* sf, off_t start_offset, size_t data_size, int channels, size_t interleave, int discard_empty);
size_t ps_bytes_to_samples(size_t bytes, int channels);
size_t ps_cfg_bytes_to_samples(size_t bytes, size_t frame_size, int channels);
int ps_check_format(STREAMFILE *streamFile, off_t offset, size_t max);
int ps_check_format(STREAMFILE* sf, off_t offset, size_t max);
/* psv_decoder */
void decode_hevag(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_hevag(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* xa_decoder */
void decode_xa(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_xa(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
size_t xa_bytes_to_samples(size_t bytes, int channels, int is_blocked, int is_form2);
/* ea_xa_decoder */
void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ea_xa_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ea_xa_v2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_maxis_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ea_xa(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ea_xa_int(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ea_xa_v2(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_maxis_xa(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
int32_t ea_xa_bytes_to_samples(size_t bytes, int channels);
/* ea_xas_decoder */
void decode_ea_xas_v0(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ea_xas_v1(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ea_xas_v0(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ea_xas_v1(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
/* sdx2_decoder */
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_cbd2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_sdx2(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_sdx2_int(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_cbd2(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_cbd2_int(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* ws_decoder */
void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ws(VGMSTREAM* vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* acm_decoder */
acm_codec_data *init_acm(STREAMFILE *streamFile, int force_channel_number);
void decode_acm(acm_codec_data *data, sample * outbuf, int32_t samples_to_do, int channelspacing);
void reset_acm(acm_codec_data *data);
void free_acm(acm_codec_data *data);
acm_codec_data* init_acm(STREAMFILE* sf, int force_channel_number);
void decode_acm(acm_codec_data* data, sample_t* outbuf, int32_t samples_to_do, int channelspacing);
void reset_acm(acm_codec_data* data);
void free_acm(acm_codec_data* data);
STREAMFILE* acm_get_streamfile(acm_codec_data* data);
/* nwa_decoder */
void decode_nwa(NWAData *nwa, sample *outbuf, int32_t samples_to_do);
typedef struct nwa_codec_data nwa_codec_data;
nwa_codec_data* init_nwa(STREAMFILE* sf);
void decode_nwa(nwa_codec_data* data, sample_t* outbuf, int32_t samples_to_do);
void seek_nwa(nwa_codec_data *data, int32_t sample);
void reset_nwa(nwa_codec_data *data);
void free_nwa(nwa_codec_data* data);
STREAMFILE* nwa_get_streamfile(nwa_codec_data* data);
/* msadpcm_decoder */
void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample_t * outbuf, int32_t first_sample, int32_t samples_to_do);
void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_msadpcm_ck(VGMSTREAM * vgmstream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first_sample, int32_t samples_to_do);
void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_msadpcm_ck(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels);
int msadpcm_check_coefs(STREAMFILE *sf, off_t offset);
int msadpcm_check_coefs(STREAMFILE* sf, off_t offset);
/* yamaha_decoder */
void decode_aica(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
void decode_aska(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_nxap(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_aica(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
void decode_aska(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_nxap(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
size_t yamaha_bytes_to_samples(size_t bytes, int channels);
size_t aska_bytes_to_samples(size_t bytes, int channels);
/* tgcadpcm_decoder */
void decode_tgc(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int32_t first_sample, int32_t samples_to_do);
void decode_tgc(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int32_t first_sample, int32_t samples_to_do);
/* nds_procyon_decoder */
void decode_nds_procyon(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_nds_procyon(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* l5_555_decoder */
void decode_l5_555(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_l5_555(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* sassc_decoder */
void decode_sassc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_sassc(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* lsf_decode */
void decode_lsf(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_lsf(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* mtaf_decoder */
void decode_mtaf(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_mtaf(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
/* mta2_decoder */
void decode_mta2(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_mta2(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
/* mc3_decoder */
void decode_mc3(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_mc3(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
/* fadpcm_decoder */
void decode_fadpcm(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_fadpcm(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* asf_decoder */
void decode_asf(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_asf(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
int32_t asf_bytes_to_samples(size_t bytes, int channels);
/* dsa_decoder */
void decode_dsa(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_dsa(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* xmd_decoder */
void decode_xmd(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
void decode_xmd(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
/* derf_decoder */
void decode_derf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_derf(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* circus_decoder */
typedef struct circus_codec_data circus_codec_data;
circus_codec_data* init_circus_vq(STREAMFILE* sf, off_t start, uint8_t codec, uint8_t flags);
void decode_circus_vq(circus_codec_data* data, sample_t* outbuf, int32_t samples_to_do, int channels);
void reset_circus_vq(circus_codec_data* data);
@ -194,93 +234,205 @@ void seek_circus_vq(circus_codec_data* data, int32_t num_sample);
void free_circus_vq(circus_codec_data* data);
void decode_circus_adpcm(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* oki_decoder */
void decode_pcfx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int mode);
void decode_oki16(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_oki4s(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_pcfx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int mode);
void decode_oki16(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_oki4s(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
size_t oki_bytes_to_samples(size_t bytes, int channels);
/* ptadpcm_decoder */
void decode_ptadpcm(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
void decode_ptadpcm(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
size_t ptadpcm_bytes_to_samples(size_t bytes, int channels, size_t frame_size);
/* ubi_adpcm_decoder */
ubi_adpcm_codec_data *init_ubi_adpcm(STREAMFILE *streamFile, off_t offset, int channels);
void decode_ubi_adpcm(VGMSTREAM * vgmstream, sample_t * outbuf, int32_t samples_to_do);
void reset_ubi_adpcm(ubi_adpcm_codec_data *data);
void seek_ubi_adpcm(ubi_adpcm_codec_data *data, int32_t num_sample);
void free_ubi_adpcm(ubi_adpcm_codec_data *data);
int ubi_adpcm_get_samples(ubi_adpcm_codec_data *data);
typedef struct ubi_adpcm_codec_data ubi_adpcm_codec_data;
ubi_adpcm_codec_data* init_ubi_adpcm(STREAMFILE* sf, off_t offset, int channels);
void decode_ubi_adpcm(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do);
void reset_ubi_adpcm(ubi_adpcm_codec_data* data);
void seek_ubi_adpcm(ubi_adpcm_codec_data* data, int32_t num_sample);
void free_ubi_adpcm(ubi_adpcm_codec_data* data);
int ubi_adpcm_get_samples(ubi_adpcm_codec_data* data);
/* imuse_decoder */
typedef struct imuse_codec_data imuse_codec_data;
imuse_codec_data *init_imuse(STREAMFILE* sf, int channels);
imuse_codec_data* init_imuse(STREAMFILE* sf, int channels);
void decode_imuse(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do);
void reset_imuse(imuse_codec_data* data);
void seek_imuse(imuse_codec_data* data, int32_t num_sample);
void free_imuse(imuse_codec_data* data);
/* ea_mt_decoder*/
ea_mt_codec_data *init_ea_mt(int channels, int type);
ea_mt_codec_data *init_ea_mt_loops(int channels, int pcm_blocks, int loop_sample, off_t *loop_offsets);
void decode_ea_mt(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
void reset_ea_mt(VGMSTREAM * vgmstream);
void flush_ea_mt(VGMSTREAM *vgmstream);
void seek_ea_mt(VGMSTREAM * vgmstream, int32_t num_sample);
void free_ea_mt(ea_mt_codec_data *data, int channels);
typedef struct ea_mt_codec_data ea_mt_codec_data;
ea_mt_codec_data* init_ea_mt(int channels, int type);
ea_mt_codec_data* init_ea_mt_loops(int channels, int pcm_blocks, int loop_sample, off_t* loop_offsets);
void decode_ea_mt(VGMSTREAM* vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
void reset_ea_mt(VGMSTREAM* vgmstream);
void flush_ea_mt(VGMSTREAM* vgmstream);
void seek_ea_mt(VGMSTREAM* vgmstream, int32_t num_sample);
void free_ea_mt(ea_mt_codec_data* data, int channels);
/* relic_decoder */
typedef struct relic_codec_data relic_codec_data;
relic_codec_data* init_relic(int channels, int bitrate, int codec_rate);
void decode_relic(VGMSTREAMCHANNEL* stream, relic_codec_data* data, sample_t* outbuf, int32_t samples_to_do);
void reset_relic(relic_codec_data* data);
void seek_relic(relic_codec_data* data, int32_t num_sample);
void free_relic(relic_codec_data* data);
/* hca_decoder */
hca_codec_data *init_hca(STREAMFILE *streamFile);
void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do);
void reset_hca(hca_codec_data * data);
void loop_hca(hca_codec_data * data, int32_t num_sample);
void free_hca(hca_codec_data * data);
int test_hca_key(hca_codec_data * data, unsigned long long keycode);
typedef struct hca_codec_data hca_codec_data;
hca_codec_data* init_hca(STREAMFILE* sf);
void decode_hca(hca_codec_data* data, sample_t* outbuf, int32_t samples_to_do);
void reset_hca(hca_codec_data* data);
void loop_hca(hca_codec_data* data, int32_t num_sample);
void free_hca(hca_codec_data* data);
int test_hca_key(hca_codec_data* data, unsigned long long keycode);
void hca_set_encryption_key(hca_codec_data* data, uint64_t keycode);
clHCA_stInfo* hca_get_info(hca_codec_data* data);
STREAMFILE* hca_get_streamfile(hca_codec_data* data);
#ifdef VGM_USE_VORBIS
/* ogg_vorbis_decoder */
ogg_vorbis_codec_data* init_ogg_vorbis(STREAMFILE *sf, off_t start, off_t size, ogg_vorbis_io *io);
void decode_ogg_vorbis(ogg_vorbis_codec_data *data, sample_t *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);
typedef struct ogg_vorbis_codec_data ogg_vorbis_codec_data;
typedef struct { //todo simplify
STREAMFILE *streamfile;
ogg_int64_t start; /* file offset where the Ogg starts */
ogg_int64_t offset; /* virtual offset, from 0 to size */
ogg_int64_t size; /* virtual size of the Ogg */
/* decryption setup */
void (*decryption_callback)(void *ptr, size_t size, size_t nmemb, void *datasource);
uint8_t scd_xor;
off_t scd_xor_length;
uint32_t xor_value;
} ogg_vorbis_io;
ogg_vorbis_codec_data* init_ogg_vorbis(STREAMFILE* sf, off_t start, off_t size, ogg_vorbis_io* io);
void decode_ogg_vorbis(ogg_vorbis_codec_data* data, sample_t* outbuf, int32_t samples_to_do, int channels);
void reset_ogg_vorbis(VGMSTREAM* vgmstream);
void seek_ogg_vorbis(ogg_vorbis_codec_data* data, int32_t num_sample);
void free_ogg_vorbis(ogg_vorbis_codec_data* data);
int ogg_vorbis_get_comment(ogg_vorbis_codec_data* data, const char** comment);
void ogg_vorbis_get_info(ogg_vorbis_codec_data* data, int* p_channels, int* p_sample_rate);
void ogg_vorbis_get_samples(ogg_vorbis_codec_data* data, int* p_samples);
void ogg_vorbis_set_disable_reordering(ogg_vorbis_codec_data* data, int set);
STREAMFILE* ogg_vorbis_get_streamfile(ogg_vorbis_codec_data* data);
int ogg_vorbis_get_comment(ogg_vorbis_codec_data *data, const char **comment);
void ogg_vorbis_get_info(ogg_vorbis_codec_data *data, int *p_channels, int *p_sample_rate);
void ogg_vorbis_get_samples(ogg_vorbis_codec_data *data, int *p_samples);
void ogg_vorbis_set_disable_reordering(ogg_vorbis_codec_data *data, int set);
STREAMFILE* ogg_vorbis_get_streamfile(ogg_vorbis_codec_data *data);
/* vorbis_custom_decoder */
vorbis_custom_codec_data *init_vorbis_custom(STREAMFILE *streamfile, off_t start_offset, vorbis_custom_t type, vorbis_custom_config * config);
void decode_vorbis_custom(VGMSTREAM * vgmstream, sample_t * outbuf, int32_t samples_to_do, int channels);
void reset_vorbis_custom(VGMSTREAM *vgmstream);
void seek_vorbis_custom(VGMSTREAM *vgmstream, int32_t num_sample);
void free_vorbis_custom(vorbis_custom_codec_data *data);
typedef struct vorbis_custom_codec_data vorbis_custom_codec_data;
typedef enum {
VORBIS_FSB, /* FMOD FSB: simplified/external setup packets, custom packet headers */
VORBIS_WWISE, /* Wwise WEM: many variations (custom setup, headers and data) */
VORBIS_OGL, /* Shin'en OGL: custom packet headers */
VORBIS_SK, /* Silicon Knights AUD: "OggS" replaced by "SK" */
VORBIS_VID1, /* Neversoft VID1: custom packet blocks/headers */
} vorbis_custom_t;
/* config for Wwise Vorbis (3 types for flexibility though not all combinations exist) */
typedef enum { WWV_HEADER_TRIAD, WWV_FULL_SETUP, WWV_INLINE_CODEBOOKS, WWV_EXTERNAL_CODEBOOKS, WWV_AOTUV603_CODEBOOKS } wwise_setup_t;
typedef enum { WWV_TYPE_8, WWV_TYPE_6, WWV_TYPE_2 } wwise_header_t;
typedef enum { WWV_STANDARD, WWV_MODIFIED } wwise_packet_t;
typedef struct {
/* to reconstruct init packets */
int channels;
int sample_rate;
int blocksize_0_exp;
int blocksize_1_exp;
uint32_t setup_id; /* external setup */
int big_endian; /* flag */
/* Wwise Vorbis config */
wwise_setup_t setup_type;
wwise_header_t header_type;
wwise_packet_t packet_type;
/* output (kinda ugly here but to simplify) */
off_t data_start_offset;
} vorbis_custom_config;
vorbis_custom_codec_data* init_vorbis_custom(STREAMFILE* sf, off_t start_offset, vorbis_custom_t type, vorbis_custom_config* config);
void decode_vorbis_custom(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do, int channels);
void reset_vorbis_custom(VGMSTREAM* vgmstream);
void seek_vorbis_custom(VGMSTREAM* vgmstream, int32_t num_sample);
void free_vorbis_custom(vorbis_custom_codec_data* data);
#endif
#ifdef VGM_USE_MPEG
/* mpeg_decoder */
mpeg_codec_data *init_mpeg(STREAMFILE *streamfile, off_t start_offset, coding_t *coding_type, int channels);
mpeg_codec_data *init_mpeg_custom(STREAMFILE *streamFile, off_t start_offset, coding_t *coding_type, int channels, mpeg_custom_t custom_type, mpeg_custom_config *config);
void decode_mpeg(VGMSTREAM * vgmstream, sample_t * outbuf, int32_t samples_to_do, int channels);
void reset_mpeg(VGMSTREAM *vgmstream);
void seek_mpeg(VGMSTREAM *vgmstream, int32_t num_sample);
void free_mpeg(mpeg_codec_data *data);
void flush_mpeg(mpeg_codec_data * data);
typedef struct mpeg_codec_data mpeg_codec_data;
long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data *data);
/* Custom MPEG modes, mostly differing in the data layout */
typedef enum {
MPEG_STANDARD, /* 1 stream */
MPEG_AHX, /* 1 stream with false frame headers */
MPEG_XVAG, /* N streams of fixed interleave (frame-aligned, several data-frames of fixed size) */
MPEG_FSB, /* N streams of 1 data-frame+padding (=interleave) */
MPEG_P3D, /* N streams of fixed interleave (not frame-aligned) */
MPEG_SCD, /* N streams of fixed interleave (not frame-aligned) */
MPEG_EA, /* 1 stream (maybe N streams in absolute offsets?) */
MPEG_EAL31, /* EALayer3 v1 (SCHl), custom frames with v1 header */
MPEG_EAL31b, /* EALayer3 v1 (SNS), custom frames with v1 header + minor changes */
MPEG_EAL32P, /* EALayer3 v2 "PCM", custom frames with v2 header + bigger PCM blocks? */
MPEG_EAL32S, /* EALayer3 v2 "Spike", custom frames with v2 header + smaller PCM blocks? */
MPEG_LYN, /* N streams of fixed interleave */
MPEG_AWC, /* N streams in block layout (music) or absolute offsets (sfx) */
MPEG_EAMP3 /* custom frame header + MPEG frame + PCM blocks */
} mpeg_custom_t;
/* config for the above modes */
typedef struct {
int channels; /* max channels */
int fsb_padding; /* fsb padding mode */
int chunk_size; /* size of a data portion */
int data_size; /* playable size */
int interleave; /* size of stream interleave */
int encryption; /* encryption mode */
int big_endian;
int skip_samples;
/* for AHX */
int cri_type;
uint16_t cri_key1;
uint16_t cri_key2;
uint16_t cri_key3;
} mpeg_custom_config;
mpeg_codec_data* init_mpeg(STREAMFILE* sf, off_t start_offset, coding_t *coding_type, int channels);
mpeg_codec_data* init_mpeg_custom(STREAMFILE* sf, off_t start_offset, coding_t* coding_type, int channels, mpeg_custom_t custom_type, mpeg_custom_config* config);
void decode_mpeg(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do, int channels);
void reset_mpeg(mpeg_codec_data* data);
void seek_mpeg(VGMSTREAM* vgmstream, int32_t num_sample);
void free_mpeg(mpeg_codec_data* data);
void flush_mpeg(mpeg_codec_data* data);
int mpeg_get_sample_rate(mpeg_codec_data* data);
long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data* data);
#endif
#ifdef VGM_USE_G7221
/* g7221_decoder */
typedef struct g7221_codec_data g7221_codec_data;
g7221_codec_data* init_g7221(int channel_count, int frame_size);
void decode_g7221(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t samples_to_do, int channel);
void reset_g7221(g7221_codec_data* data);
@ -289,73 +441,93 @@ void set_key_g7221(g7221_codec_data* data, const uint8_t* key);
int test_key_g7221(g7221_codec_data* data, off_t start, STREAMFILE* sf);
#endif
#ifdef VGM_USE_G719
/* g719_decoder */
g719_codec_data *init_g719(int channel_count, int frame_size);
void decode_g719(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
void reset_g719(g719_codec_data * data, int channels);
void free_g719(g719_codec_data * data, int channels);
typedef struct g719_codec_data g719_codec_data;
g719_codec_data* init_g719(int channel_count, int frame_size);
void decode_g719(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t samples_to_do, int channel);
void reset_g719(g719_codec_data* data, int channels);
void free_g719(g719_codec_data* data, int channels);
#endif
#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);
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
#ifdef VGM_USE_MAIATRAC3PLUS
/* at3plus_decoder */
maiatrac3plus_codec_data *init_at3plus();
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);
typedef struct maiatrac3plus_codec_data maiatrac3plus_codec_data;
maiatrac3plus_codec_data* init_at3plus();
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
#ifdef VGM_USE_ATRAC9
/* atrac9_decoder */
atrac9_codec_data *init_atrac9(atrac9_config *cfg);
void decode_atrac9(VGMSTREAM *vgmstream, sample_t * outbuf, int32_t samples_to_do, int channels);
void reset_atrac9(VGMSTREAM *vgmstream);
void seek_atrac9(VGMSTREAM *vgmstream, int32_t num_sample);
void free_atrac9(atrac9_codec_data *data);
size_t atrac9_bytes_to_samples(size_t bytes, atrac9_codec_data *data);
typedef struct {
int channels; /* to detect weird multichannel */
uint32_t config_data; /* ATRAC9 config header */
int encoder_delay; /* initial samples to discard */
} atrac9_config;
typedef struct atrac9_codec_data atrac9_codec_data;
atrac9_codec_data* init_atrac9(atrac9_config* cfg);
void decode_atrac9(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do, int channels);
void reset_atrac9(atrac9_codec_data* data);
void seek_atrac9(VGMSTREAM* vgmstream, int32_t num_sample);
void free_atrac9(atrac9_codec_data* data);
size_t atrac9_bytes_to_samples(size_t bytes, atrac9_codec_data* data);
size_t atrac9_bytes_to_samples_cfg(size_t bytes, uint32_t atrac9_config);
#endif
#ifdef VGM_USE_CELT
/* celt_fsb_decoder */
celt_codec_data *init_celt_fsb(int channels, celt_lib_t version);
void decode_celt_fsb(VGMSTREAM *vgmstream, sample * outbuf, int32_t samples_to_do, int channels);
void reset_celt_fsb(VGMSTREAM *vgmstream);
void seek_celt_fsb(VGMSTREAM *vgmstream, int32_t num_sample);
void free_celt_fsb(celt_codec_data *data);
typedef enum { CELT_0_06_1,CELT_0_11_0} celt_lib_t;
typedef struct celt_codec_data celt_codec_data;
celt_codec_data* init_celt_fsb(int channels, celt_lib_t version);
void decode_celt_fsb(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do, int channels);
void reset_celt_fsb(celt_codec_data* data);
void seek_celt_fsb(VGMSTREAM* vgmstream, int32_t num_sample);
void free_celt_fsb(celt_codec_data* data);
#endif
#ifdef VGM_USE_FFMPEG
/* ffmpeg_decoder */
ffmpeg_codec_data *init_ffmpeg_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size);
ffmpeg_codec_data *init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size);
ffmpeg_codec_data *init_ffmpeg_header_offset_subsong(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size, int target_subsong);
ffmpeg_codec_data* init_ffmpeg_offset(STREAMFILE* sf, uint64_t start, uint64_t size);
ffmpeg_codec_data* init_ffmpeg_header_offset(STREAMFILE* sf, uint8_t* header, uint64_t header_size, uint64_t start, uint64_t size);
ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* header, uint64_t header_size, uint64_t start, uint64_t size, int target_subsong);
void decode_ffmpeg(VGMSTREAM *stream, sample_t * outbuf, int32_t samples_to_do, int channels);
void reset_ffmpeg(VGMSTREAM *vgmstream);
void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample);
void free_ffmpeg(ffmpeg_codec_data *data);
void decode_ffmpeg(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do, int channels);
void reset_ffmpeg(ffmpeg_codec_data* data);
void seek_ffmpeg(ffmpeg_codec_data* data, int32_t num_sample);
void free_ffmpeg(ffmpeg_codec_data* data);
void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples);
uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data * data);
void ffmpeg_set_channel_remapping(ffmpeg_codec_data * data, int *channels_remap);
const char* ffmpeg_get_codec_name(ffmpeg_codec_data * data);
void ffmpeg_set_force_seek(ffmpeg_codec_data * data);
void ffmpeg_set_skip_samples(ffmpeg_codec_data* data, int skip_samples);
uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data* data);
void ffmpeg_set_channel_remapping(ffmpeg_codec_data* data, int* channels_remap);
const char* ffmpeg_get_codec_name(ffmpeg_codec_data* data);
void ffmpeg_set_force_seek(ffmpeg_codec_data* data);
const char* ffmpeg_get_metadata_value(ffmpeg_codec_data* data, const char* key);
STREAMFILE* ffmpeg_get_streamfile(ffmpeg_codec_data* data);
/* ffmpeg_decoder_utils.c (helper-things) */
ffmpeg_codec_data * init_ffmpeg_atrac3_raw(STREAMFILE *sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay);
ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* out_samples);
ffmpeg_codec_data* init_ffmpeg_atrac3_raw(STREAMFILE* sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay);
ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* out_samples);
/* ffmpeg_decoder_custom_opus.c (helper-things) */
@ -369,28 +541,28 @@ typedef struct {
int channel_mapping[8];
} opus_config;
ffmpeg_codec_data * init_ffmpeg_switch_opus_config(STREAMFILE *streamFile, off_t start_offset, size_t data_size, opus_config* cfg);
ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
ffmpeg_codec_data * init_ffmpeg_ue4_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
ffmpeg_codec_data * init_ffmpeg_ea_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
ffmpeg_codec_data * init_ffmpeg_x_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
ffmpeg_codec_data* init_ffmpeg_switch_opus_config(STREAMFILE* sf, off_t start_offset, size_t data_size, opus_config* cfg);
ffmpeg_codec_data* init_ffmpeg_switch_opus(STREAMFILE* sf, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
ffmpeg_codec_data* init_ffmpeg_ue4_opus(STREAMFILE* sf, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
ffmpeg_codec_data* init_ffmpeg_ea_opus(STREAMFILE* sf, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
ffmpeg_codec_data* init_ffmpeg_x_opus(STREAMFILE* sf, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
size_t switch_opus_get_samples(off_t offset, size_t stream_size, STREAMFILE *streamFile);
size_t switch_opus_get_samples(off_t offset, size_t stream_size, STREAMFILE* sf);
size_t switch_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile);
size_t ue4_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile);
size_t ea_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile);
size_t switch_opus_get_encoder_delay(off_t offset, STREAMFILE* sf);
size_t ue4_opus_get_encoder_delay(off_t offset, STREAMFILE* sf);
size_t ea_opus_get_encoder_delay(off_t offset, STREAMFILE* sf);
#endif
/* coding_utils */
int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, size_t chunk_size, uint16_t codec);
int ffmpeg_make_riff_atrac3plus(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay);
int ffmpeg_make_riff_xma1(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int stream_mode);
int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size);
int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t * buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE *streamFile, int big_endian);
int ffmpeg_make_riff_xma2_from_xma2_chunk(uint8_t * buf, size_t buf_size, off_t xma2_offset, size_t xma2_size, size_t data_size, STREAMFILE *streamFile);
int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align);
int ffmpeg_fmt_chunk_swap_endian(uint8_t* chunk, size_t chunk_size, uint16_t codec);
int ffmpeg_make_riff_atrac3plus(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay);
int ffmpeg_make_riff_xma1(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int stream_mode);
int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size);
int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t* buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE* sf, int big_endian);
int ffmpeg_make_riff_xma2_from_xma2_chunk(uint8_t* buf, size_t buf_size, off_t xma2_offset, size_t xma2_size, size_t data_size, STREAMFILE* sf);
int ffmpeg_make_riff_xwma(uint8_t* buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align);
/* MS audio format's sample info (struct to avoid passing so much stuff, separate for reusing) */
typedef struct {
@ -414,39 +586,39 @@ typedef struct {
int32_t loop_start_sample;
int32_t loop_end_sample;
} ms_sample_data;
void xma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile);
void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags);
void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags);
void xma_get_samples(ms_sample_data* msd, STREAMFILE* sf);
void wmapro_get_samples(ms_sample_data* msd, STREAMFILE* sf, int block_align, int sample_rate, uint32_t decode_flags);
void wma_get_samples(ms_sample_data* msd, STREAMFILE* sf, int block_align, int sample_rate, uint32_t decode_flags);
void xma1_parse_fmt_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * loop_start_b, int32_t * loop_end_b, int32_t * loop_subframe, int be);
void xma2_parse_fmt_chunk_extra(STREAMFILE *streamFile, off_t chunk_offset, int * loop_flag, int32_t * out_num_samples, int32_t * out_loop_start_sample, int32_t * out_loop_end_sample, int be);
void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * num_samples, int32_t * loop_start_sample, int32_t * loop_end_sample);
void xma1_parse_fmt_chunk(STREAMFILE* sf, off_t chunk_offset, int* channels, int* sample_rate, int* loop_flag, int32_t* loop_start_b, int32_t* loop_end_b, int32_t* loop_subframe, int be);
void xma2_parse_fmt_chunk_extra(STREAMFILE* sf, off_t chunk_offset, int* loop_flag, int32_t* out_num_samples, int32_t* out_loop_start_sample, int32_t* out_loop_end_sample, int be);
void xma2_parse_xma2_chunk(STREAMFILE* sf, off_t chunk_offset, int* channels, int* sample_rate, int* loop_flag, int32_t* num_samples, int32_t* loop_start_sample, int32_t* loop_end_sample);
void xma_fix_raw_samples(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples);
void xma_fix_raw_samples_hb(VGMSTREAM *vgmstream, STREAMFILE *headerFile, STREAMFILE *bodyFile, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples);
void xma_fix_raw_samples_ch(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, int channel_per_stream, int fix_num_samples, int fix_loop_samples);
void xma_fix_raw_samples(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples);
void xma_fix_raw_samples_hb(VGMSTREAM* vgmstream, STREAMFILE* sf_head, STREAMFILE* sf_body, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples);
void xma_fix_raw_samples_ch(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t stream_offset, size_t stream_size, int channel_per_stream, int fix_num_samples, int fix_loop_samples);
size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align);
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align);
size_t ac3_bytes_to_samples(size_t bytes, int full_block_align, int channels);
size_t aac_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes);
size_t mpeg_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes);
size_t aac_get_samples(STREAMFILE* sf, off_t start_offset, size_t bytes);
size_t mpeg_get_samples(STREAMFILE* sf, off_t start_offset, size_t bytes);
/* An internal struct to pass around and simulate a bitstream. */
typedef enum { BITSTREAM_MSF, BITSTREAM_VORBIS } vgm_bitstream_t;
typedef struct {
uint8_t * buf; /* buffer to read/write*/
uint8_t* buf; /* buffer to read/write*/
size_t bufsize; /* max size of the buffer */
off_t b_off; /* current offset in bits inside the buffer */
vgm_bitstream_t mode; /* read/write modes */
} vgm_bitstream;
int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value);
int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value);
int r_bits(vgm_bitstream* ib, int num_bits, uint32_t* value);
int w_bits(vgm_bitstream* ob, int num_bits, uint32_t value);
/* helper to pass a wrapped, clamped, fake extension-ed, SF to another meta */
STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* extension);
STREAMFILE* setup_subfile_streamfile(STREAMFILE* sf, off_t subfile_offset, size_t subfile_size, const char* extension);
#endif /*_CODING_H*/

View File

@ -8,11 +8,8 @@
static volatile int g_ffmpeg_initialized = 0;
static void free_ffmpeg_config(ffmpeg_codec_data *data);
static int init_ffmpeg_config(ffmpeg_codec_data * data, int target_subsong, int reset);
static void reset_ffmpeg_internal(ffmpeg_codec_data *data);
static void seek_ffmpeg_internal(ffmpeg_codec_data *data, int32_t num_sample);
static void free_ffmpeg_config(ffmpeg_codec_data* data);
static int init_ffmpeg_config(ffmpeg_codec_data* data, int target_subsong, int reset);
/* ******************************************** */
/* INTERNAL UTILS */
@ -34,7 +31,7 @@ static void g_init_ffmpeg() {
}
}
static void remap_audio(sample_t *outbuf, int sample_count, int channels, int *channel_mappings) {
static void remap_audio(sample_t* outbuf, int sample_count, int channels, int* channel_mappings) {
int ch_from,ch_to,s;
sample_t temp;
for (s = 0; s < sample_count; s++) {
@ -65,7 +62,7 @@ static void remap_audio(sample_t *outbuf, int sample_count, int channels, int *c
* first frame/packet and sets up index to timestamp 0. This ensures faulty demuxers will seek to 0 correctly.
* Some formats may not seek to 0 even with this, though.
*/
static int init_seek(ffmpeg_codec_data * data) {
static int init_seek(ffmpeg_codec_data* data) {
int ret, ts_index, packet_count = 0;
int64_t ts = 0; /* seek timestamp */
int64_t pos = 0; /* data offset */
@ -161,8 +158,8 @@ fail:
/* ******************************************** */
/* AVIO callback: read stream, handling custom data */
static int ffmpeg_read(void *opaque, uint8_t *buf, int read_size) {
ffmpeg_codec_data *data = (ffmpeg_codec_data *) opaque;
static int ffmpeg_read(void* opaque, uint8_t* buf, int read_size) {
ffmpeg_codec_data* data = opaque;
int bytes = 0;
int max_to_copy = 0;
@ -196,8 +193,8 @@ static int ffmpeg_read(void *opaque, uint8_t *buf, int read_size) {
}
/* AVIO callback: seek stream, handling custom data */
static int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence) {
ffmpeg_codec_data *data = (ffmpeg_codec_data *) opaque;
static int64_t ffmpeg_seek(void* opaque, int64_t offset, int whence) {
ffmpeg_codec_data* data = opaque;
int ret = 0;
/* get cache'd size */
@ -243,12 +240,12 @@ static int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence) {
/* MAIN INIT/DECODER */
/* ******************************************** */
ffmpeg_codec_data * init_ffmpeg_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size) {
return init_ffmpeg_header_offset(streamFile, NULL,0, start,size);
ffmpeg_codec_data* init_ffmpeg_offset(STREAMFILE* sf, uint64_t start, uint64_t size) {
return init_ffmpeg_header_offset(sf, NULL,0, start,size);
}
ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size) {
return init_ffmpeg_header_offset_subsong(streamFile, header, header_size, start, size, 0);
ffmpeg_codec_data* init_ffmpeg_header_offset(STREAMFILE* sf, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size) {
return init_ffmpeg_header_offset_subsong(sf, header, header_size, start, size, 0);
}
@ -261,8 +258,8 @@ ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t *
* NULL header can used given if the stream has internal data recognized by FFmpeg at offset.
* Stream index can be passed if the file has multiple audio streams that FFmpeg can demux (1=first).
*/
ffmpeg_codec_data * init_ffmpeg_header_offset_subsong(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size, int target_subsong) {
ffmpeg_codec_data * data = NULL;
ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* header, uint64_t header_size, uint64_t start, uint64_t size, int target_subsong) {
ffmpeg_codec_data* data = NULL;
int errcode;
@ -270,9 +267,9 @@ ffmpeg_codec_data * init_ffmpeg_header_offset_subsong(STREAMFILE *streamFile, ui
if ((header && !header_size) || (!header && header_size))
goto fail;
if (size == 0 || start + size > get_streamfile_size(streamFile)) {
VGM_LOG("FFMPEG: wrong start+size found: %x + %x > %x \n", (uint32_t)start, (uint32_t)size, get_streamfile_size(streamFile));
size = get_streamfile_size(streamFile) - start;
if (size == 0 || start + size > get_streamfile_size(sf)) {
VGM_LOG("FFMPEG: wrong start+size found: %x + %x > %x \n", (uint32_t)start, (uint32_t)size, get_streamfile_size(sf));
size = get_streamfile_size(sf) - start;
}
@ -284,7 +281,7 @@ ffmpeg_codec_data * init_ffmpeg_header_offset_subsong(STREAMFILE *streamFile, ui
data = calloc(1, sizeof(ffmpeg_codec_data));
if (!data) return NULL;
data->streamfile = reopen_streamfile(streamFile, 0);
data->streamfile = reopen_streamfile(sf, 0);
if (!data->streamfile) goto fail;
/* fake header to trick FFmpeg into demuxing/decoding the stream */
@ -366,7 +363,7 @@ fail:
return NULL;
}
static int init_ffmpeg_config(ffmpeg_codec_data * data, int target_subsong, int reset) {
static int init_ffmpeg_config(ffmpeg_codec_data* data, int target_subsong, int reset) {
int errcode = 0;
/* basic IO/format setup */
@ -455,7 +452,7 @@ fail:
}
/* decodes a new frame to internal data */
static int decode_ffmpeg_frame(ffmpeg_codec_data *data) {
static int decode_ffmpeg_frame(ffmpeg_codec_data* data) {
int errcode;
int frame_error = 0;
@ -672,7 +669,7 @@ static void samples_dblp_to_s16(sample_t* obuf, double** inbuf, int ichs, int sa
}
}
static void copy_samples(ffmpeg_codec_data *data, sample_t *outbuf, int samples_to_do) {
static void copy_samples(ffmpeg_codec_data* data, sample_t* outbuf, int samples_to_do) {
int channels = data->codecCtx->channels;
int is_planar = av_sample_fmt_is_planar(data->codecCtx->sample_fmt) && (channels > 1);
void* ibuf;
@ -709,8 +706,8 @@ static void copy_samples(ffmpeg_codec_data *data, sample_t *outbuf, int samples_
}
/* decode samples of any kind of FFmpeg format */
void decode_ffmpeg(VGMSTREAM *vgmstream, sample_t * outbuf, int32_t samples_to_do, int channels) {
ffmpeg_codec_data *data = vgmstream->codec_data;
void decode_ffmpeg(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do, int channels) {
ffmpeg_codec_data* data = vgmstream->codec_data;
while (samples_to_do > 0) {
@ -757,14 +754,11 @@ decode_fail:
/* UTILS */
/* ******************************************** */
void reset_ffmpeg_internal(ffmpeg_codec_data *data) {
seek_ffmpeg_internal(data, 0);
}
void reset_ffmpeg(VGMSTREAM *vgmstream) {
reset_ffmpeg_internal(vgmstream->codec_data);
void reset_ffmpeg(ffmpeg_codec_data* data) {
seek_ffmpeg(data, 0);
}
void seek_ffmpeg_internal(ffmpeg_codec_data *data, int32_t num_sample) {
void seek_ffmpeg(ffmpeg_codec_data* data, int32_t num_sample) {
if (!data) return;
/* Start from 0 and discard samples until sample (slower but not too noticeable).
@ -813,12 +807,8 @@ fail:
data->bad_init = 1; /* internals were probably free'd */
}
void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample) {
seek_ffmpeg_internal(vgmstream->codec_data, num_sample);
}
static void free_ffmpeg_config(ffmpeg_codec_data *data) {
static void free_ffmpeg_config(ffmpeg_codec_data* data) {
if (data == NULL)
return;
@ -858,7 +848,7 @@ static void free_ffmpeg_config(ffmpeg_codec_data *data) {
//todo avformat_find_stream_info may cause some Win Handle leaks? related to certain option
}
void free_ffmpeg(ffmpeg_codec_data *data) {
void free_ffmpeg(ffmpeg_codec_data* data) {
if (data == NULL)
return;
@ -883,7 +873,7 @@ void free_ffmpeg(ffmpeg_codec_data *data) {
* This could be added per format in FFmpeg directly, but it's here for flexibility and due to bugs
* (FFmpeg's stream->(start_)skip_samples causes glitches in XMA).
*/
void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples) {
void ffmpeg_set_skip_samples(ffmpeg_codec_data* data, int skip_samples) {
AVStream *stream = NULL;
if (!data || !data->formatCtx)
return;
@ -902,7 +892,7 @@ void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples) {
}
/* returns channel layout if set */
uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data * data) {
uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data* data) {
if (!data || !data->codecCtx) return 0;
return (uint32_t)data->codecCtx->channel_layout; /* uint64 but there ain't so many speaker mappings */
}
@ -910,7 +900,7 @@ uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data * data) {
/* yet another hack to fix codecs that encode channels in different order and reorder on decoder
* but FFmpeg doesn't do it automatically
* (maybe should be done via mixing, but could clash with other stuff?) */
void ffmpeg_set_channel_remapping(ffmpeg_codec_data * data, int *channel_remap) {
void ffmpeg_set_channel_remapping(ffmpeg_codec_data* data, int *channel_remap) {
int i;
if (data->channels > 32)
@ -922,7 +912,7 @@ void ffmpeg_set_channel_remapping(ffmpeg_codec_data * data, int *channel_remap)
data->channel_remap_set = 1;
}
const char* ffmpeg_get_codec_name(ffmpeg_codec_data * data) {
const char* ffmpeg_get_codec_name(ffmpeg_codec_data* data) {
if (!data || !data->codec)
return NULL;
if (data->codec->long_name)
@ -932,12 +922,12 @@ const char* ffmpeg_get_codec_name(ffmpeg_codec_data * data) {
return NULL;
}
void ffmpeg_set_force_seek(ffmpeg_codec_data * data) {
void ffmpeg_set_force_seek(ffmpeg_codec_data* data) {
/* some formats like Smacker are so buggy that any seeking is impossible (even on video players),
* or MPC with an incorrectly parsed seek table (using as 0 some non-0 seek offset).
* whatever, we'll just kill and reconstruct FFmpeg's config every time */
data->force_seek = 1;
reset_ffmpeg_internal(data); /* reset state from trying to seek */
reset_ffmpeg(data); /* reset state from trying to seek */
//stream = data->formatCtx->streams[data->streamIndex];
}
@ -959,4 +949,8 @@ const char* ffmpeg_get_metadata_value(ffmpeg_codec_data* data, const char* key)
return avde->value;
}
STREAMFILE* ffmpeg_get_streamfile(ffmpeg_codec_data* data) {
if (!data) return NULL;
return data->streamfile;
}
#endif

View File

@ -4,10 +4,14 @@
#ifdef VGM_USE_G719
#define G719_MAX_CODES ((1280/8)) /* in int16, so max frame size is (value/8)*2 (0xF0=common, 0x140=decoder max 2560b, rare) */
struct g719_codec_data {
sample_t buffer[960];
void *handle;
};
g719_codec_data *init_g719(int channel_count, int frame_size) {
g719_codec_data* init_g719(int channel_count, int frame_size) {
int i;
g719_codec_data *data = NULL;
g719_codec_data* data = NULL;
if (frame_size / sizeof(int16_t) > G719_MAX_CODES)
goto fail;
@ -34,10 +38,10 @@ fail:
}
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];
void decode_g719(VGMSTREAM* vgmstream, sample_t* 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];
int i;
if (0 == vgmstream->samples_into_block) {
@ -53,7 +57,7 @@ void decode_g719(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int
}
void reset_g719(g719_codec_data * data, int channels) {
void reset_g719(g719_codec_data* data, int channels) {
int i;
if (!data) return;
@ -62,7 +66,7 @@ void reset_g719(g719_codec_data * data, int channels) {
}
}
void free_g719(g719_codec_data * data, int channels) {
void free_g719(g719_codec_data* data, int channels) {
int i;
if (!data) return;

View File

@ -1,21 +1,36 @@
#include "coding.h"
struct hca_codec_data {
STREAMFILE* streamfile;
clHCA_stInfo info;
signed short* sample_buffer;
size_t samples_filled;
size_t samples_consumed;
size_t samples_to_discard;
void* data_buffer;
unsigned int current_block;
void* handle;
};
/* init a HCA stream; STREAMFILE will be duplicated for internal use. */
hca_codec_data * init_hca(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
hca_codec_data* init_hca(STREAMFILE* sf) {
uint8_t header_buffer[0x2000]; /* hca header buffer data (probable max ~0x400) */
hca_codec_data * data = NULL; /* vgmstream HCA context */
hca_codec_data* data = NULL; /* vgmstream HCA context */
int header_size;
int status;
/* test header */
if (read_streamfile(header_buffer, 0x00, 0x08, streamFile) != 0x08)
if (read_streamfile(header_buffer, 0x00, 0x08, sf) != 0x08)
goto fail;
header_size = clHCA_isOurFile(header_buffer, 0x08);
if (header_size < 0 || header_size > 0x1000)
goto fail;
if (read_streamfile(header_buffer, 0x00, header_size, streamFile) != header_size)
if (read_streamfile(header_buffer, 0x00, header_size, sf) != header_size)
goto fail;
/* init vgmstream context */
@ -39,8 +54,7 @@ hca_codec_data * init_hca(STREAMFILE *streamFile) {
if (!data->sample_buffer) goto fail;
/* load streamfile for reads */
get_streamfile_name(streamFile,filename, sizeof(filename));
data->streamfile = open_streamfile(streamFile,filename);
data->streamfile = reopen_streamfile(sf, 0);
if (!data->streamfile) goto fail;
/* set initial values */
@ -53,7 +67,7 @@ fail:
return NULL;
}
void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do) {
void decode_hca(hca_codec_data* data, sample_t* outbuf, int32_t samples_to_do) {
int samples_done = 0;
const unsigned int channels = data->info.channelCount;
const unsigned int blockSize = data->info.blockSize;
@ -120,7 +134,7 @@ void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do) {
}
}
void reset_hca(hca_codec_data * data) {
void reset_hca(hca_codec_data* data) {
if (!data) return;
clHCA_DecodeReset(data->handle);
@ -130,7 +144,7 @@ void reset_hca(hca_codec_data * data) {
data->samples_to_discard = data->info.encoderDelay;
}
void loop_hca(hca_codec_data * data, int32_t num_sample) {
void loop_hca(hca_codec_data* data, int32_t num_sample) {
if (!data) return;
/* manually calc loop values if not set (should only happen with installed/forced looping,
@ -149,7 +163,7 @@ void loop_hca(hca_codec_data * data, int32_t num_sample) {
data->samples_to_discard = data->info.loopStartDelay;
}
void free_hca(hca_codec_data * data) {
void free_hca(hca_codec_data* data) {
if (!data) return;
close_streamfile(data->streamfile);
@ -175,7 +189,7 @@ void free_hca(hca_codec_data * data) {
/* Test a number of frames if key decrypts correctly.
* Returns score: <0: error/wrong, 0: unknown/silent file, >0: good (the closest to 1 the better). */
int test_hca_key(hca_codec_data * data, unsigned long long keycode) {
int test_hca_key(hca_codec_data* data, unsigned long long keycode) {
size_t test_frames = 0, current_frame = 0, blank_frames = 0;
int total_score = 0, found_regular_frame = 0;
const unsigned int blockSize = data->info.blockSize;
@ -242,3 +256,17 @@ int test_hca_key(hca_codec_data * data, unsigned long long keycode) {
clHCA_DecodeReset(data->handle);
return total_score;
}
void hca_set_encryption_key(hca_codec_data* data, uint64_t keycode) {
VGM_LOG("k=%x%x", (uint32_t)((keycode >> 32) & 0xFFFFFFFF), (uint32_t)(keycode & 0xFFFFFFFF));
clHCA_SetKey(data->handle, (unsigned long long)keycode);
}
clHCA_stInfo* hca_get_info(hca_codec_data* data) {
return &data->info;
}
STREAMFILE* hca_get_streamfile(hca_codec_data* data) {
if (!data) return NULL;
return data->streamfile;
}

View File

@ -505,8 +505,7 @@ void free_mpeg(mpeg_codec_data *data) {
}
/* seeks stream to 0 */
void reset_mpeg(VGMSTREAM *vgmstream) {
mpeg_codec_data *data = vgmstream->codec_data;
void reset_mpeg(mpeg_codec_data* data) {
if (!data) return;
flush_mpeg(data);
@ -593,6 +592,10 @@ void flush_mpeg(mpeg_codec_data * data) {
data->buffer_used = 0;
}
int mpeg_get_sample_rate(mpeg_codec_data* data) {
return data->sample_rate_per_frame;
}
long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data *data) {
/* if not found just return 0 and expect to fail (if used for num_samples) */
if (!data->custom) {

View File

@ -16,6 +16,59 @@ typedef struct {
int channels;
} mpeg_frame_info;
/* represents a single MPEG stream */
typedef struct {
/* per stream as sometimes mpg123 must be fed in passes if data is big enough (ex. EALayer3 multichannel) */
uint8_t *buffer; /* raw data buffer */
size_t buffer_size;
size_t bytes_in_buffer;
int buffer_full; /* raw buffer has been filled */
int buffer_used; /* raw buffer has been fed to the decoder */
mpg123_handle *m; /* MPEG decoder */
uint8_t *output_buffer; /* decoded samples from this stream (in bytes for mpg123) */
size_t output_buffer_size;
size_t samples_filled; /* data in the buffer (in samples) */
size_t samples_used; /* data extracted from the buffer */
size_t current_size_count; /* data read (if the parser needs to know) */
size_t current_size_target; /* max data, until something happens */
size_t decode_to_discard; /* discard from this stream only (for EALayer3 or AWC) */
int channels_per_frame; /* for rare cases that streams don't share this */
} mpeg_custom_stream;
struct mpeg_codec_data {
/* regular/single MPEG internals */
uint8_t *buffer; /* raw data buffer */
size_t buffer_size;
size_t bytes_in_buffer;
int buffer_full; /* raw buffer has been filled */
int buffer_used; /* raw buffer has been fed to the decoder */
mpg123_handle *m; /* MPEG decoder */
struct mpg123_frameinfo mi; /* start info, so it's available even when resetting */
/* for internal use */
int channels_per_frame;
int samples_per_frame;
/* for some calcs */
int bitrate_per_frame;
int sample_rate_per_frame;
/* custom MPEG internals */
int custom; /* flag */
mpeg_custom_t type; /* mpeg subtype */
mpeg_custom_config config; /* config depending on the mode */
size_t default_buffer_size;
mpeg_custom_stream **streams; /* array of MPEG streams (ex. 2ch+2ch) */
size_t streams_size;
size_t skip_samples; /* base encoder delay */
size_t samples_to_discard; /* for custom mpeg looping */
};
int mpeg_get_frame_info(STREAMFILE *streamfile, off_t offset, mpeg_frame_info * info);
int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type);

View File

@ -1,4 +1,33 @@
/* originally from nwatowav.cc 2007.7.28 version, which read: */
/* Originally from nwatowav.cc (2007.7.28 version) by jagarl.
* - http://www.creator.club.ne.jp/~jagarl/
*
* Converted to .c by hcs (redone as a lib without RIFF/main handling), some cleanup by bnnm.
*
* nwa format (abridged from the original)
* NWA Header
* data offset index
* data block<0>
* data block<1>
* ...
* data block<N>
*
* - NWA header: 0x2c with nwa info (channels, compression level, etc), no magic number
* - data offset index: pointers to data blocks
* - data block: variable sized DPCM blocks to fixed size PCM (a,b,c compresses to (a),b-a,c-b),
* DPCM codes use variable bits. Usually for 16-bit PCM ends ups using 6-8 bits.
* - Block format:
* - mono: initial PCM (8 or 16-bit) then bitstream
* - stereo: initial PCM for left + right channel then bitstream
* Differential accuracy isn't high so initial PCM is used to correct data in each block (?)
* - bitstream: Roughly each code has an 'exponent' (2 bits) + 'mantissa' (variable bits).
* Depending on compression level + type it configures final shift value and matissa bits.
* There is a run length encoding mode in some cases (Tomoyo After voice files).
* Bitstream bytes follow little endian.
* (some examples here in the original, see decoder).
*
* Original copyright:
*/
/*
* Copyright 2001-2007 jagarl / Kazunori Ueno <jagarl@creator.club.ne.jp>
* All Rights Reserved.
@ -33,319 +62,380 @@
#include <stdlib.h>
#include "nwa_decoder.h"
/* can serve up 8 bits at a time */
static int
getbits (STREAMFILE *file, off_t *offset, int *shift, int bits)
{
int ret;
if (*shift > 8)
{
++*offset;
*shift -= 8;
//NWAInfo::UseRunLength
static int is_use_runlength(NWAData* nwa) {
if (nwa->channels == 2 && nwa->bps == 16 && nwa->complevel == 2) {
return 0; /* sw2 */
}
ret = read_16bitLE(*offset,file) >> *shift;
*shift += bits;
return ret & ((1 << bits) - 1); /* mask */
if (nwa->complevel == 5) {
if (nwa->channels == 2)
return 0; // BGM*.nwa in Little Busters!
return 1; // Tomoyo After (.nwk koe file)
}
return 0;
}
NWAData *
open_nwa (STREAMFILE * streamFile, const char *filename)
{
NWAData* nwalib_open(STREAMFILE* sf) {
uint8_t header[0x2c] = {0};
int i;
NWAData * const nwa = malloc(sizeof(NWAData));
NWAData* const nwa = malloc(sizeof(NWAData));
if (!nwa) goto fail;
nwa->channels = read_16bitLE(0x00,streamFile);
nwa->bps = read_16bitLE(0x02,streamFile);
nwa->freq = read_32bitLE(0x04,streamFile);
nwa->complevel = read_32bitLE(0x08,streamFile);
nwa->blocks = read_32bitLE(0x10,streamFile);
nwa->datasize = read_32bitLE(0x14,streamFile);
nwa->compdatasize = read_32bitLE(0x18,streamFile);
nwa->samplecount = read_32bitLE(0x1c,streamFile);
nwa->blocksize = read_32bitLE(0x20,streamFile);
nwa->restsize = read_32bitLE(0x24,streamFile);
//NWAData::ReadHeader
read_streamfile(header, 0x00, sizeof(header), sf);
nwa->channels = get_s16le(header+0x00);
nwa->bps = get_s16le(header+0x02);
nwa->freq = get_s32le(header+0x04);
nwa->complevel = get_s32le(header+0x08);
nwa->dummy = get_s32le(header+0x0c);
nwa->blocks = get_s32le(header+0x10);
nwa->datasize = get_s32le(header+0x14);
nwa->compdatasize = get_s32le(header+0x18);
nwa->samplecount = get_s32le(header+0x1c);
nwa->blocksize = get_s32le(header+0x20);
nwa->restsize = get_s32le(header+0x24);
nwa->dummy2 = get_s32le(header+0x28);
nwa->offsets = NULL;
nwa->buffer = NULL;
nwa->buffer_readpos = NULL;
nwa->file = NULL;
nwa->outdata = NULL;
nwa->outdata_readpos = NULL;
nwa->tmpdata = NULL;
nwa->filesize = get_streamfile_size(sf);
/* PCM not handled here */
if (nwa->complevel < 0 || nwa->complevel > 5) goto fail;
if (nwa->channels != 1 && nwa->channels != 2) goto fail;
if (nwa->blocks <= 0 || nwa->blocks > 1000000)
/* 1時間を超える曲ってのはないでしょ*/ //surely there won't be songs over 1 hour
goto fail;
if (nwa->bps != 8 && nwa->bps != 16) goto fail;
// NWAData::CheckHeader:
if (nwa->blocks <= 0) goto fail;
if (nwa->channels != 1 && nwa->channels != 2)
goto fail;
if (nwa->compdatasize == 0
|| get_streamfile_size(streamFile) != nwa->compdatasize) goto fail;
if (nwa->bps != 8 && nwa->bps != 16)
goto fail;
if (nwa->datasize != nwa->samplecount * (nwa->bps/8)) goto fail;
// (PCM not handled)
if (nwa->samplecount !=
(nwa->blocks-1) * nwa->blocksize + nwa->restsize) goto fail;
if (nwa->complevel < 0 || nwa->complevel > 5)
goto fail;
nwa->offsets = malloc(sizeof(off_t)*nwa->blocks);
if (nwa->filesize != nwa->compdatasize)
goto fail;
if (nwa->datasize != nwa->samplecount * (nwa->bps / 8))
goto fail;
if (nwa->samplecount != (nwa->blocks - 1) * nwa->blocksize + nwa->restsize)
goto fail;
/* offset index 読み込み */ //read offset index
nwa->offsets = malloc(sizeof(off_t) * nwa->blocks);
if (!nwa->offsets) goto fail;
for (i = 0; i < nwa->blocks; i++)
{
int32_t o = read_32bitLE(0x2c+i*4,streamFile);
for (i = 0; i < nwa->blocks; i++) {
int32_t o = read_s32le(0x2c + i*4, sf);
if (o < 0) goto fail;
nwa->offsets[i] = o;
}
if (nwa->offsets[nwa->blocks-1] >= nwa->compdatasize) goto fail;
if (nwa->restsize > nwa->blocksize) nwa->buffer =
malloc(sizeof(sample)*nwa->restsize);
else nwa->buffer =
malloc(sizeof(sample)*nwa->blocksize);
if (nwa->buffer == NULL) goto fail;
nwa->buffer_readpos = nwa->buffer;
nwa->samples_in_buffer = 0;
if (nwa->offsets[nwa->blocks-1] >= nwa->compdatasize)
goto fail;
nwa->use_runlength = is_use_runlength(nwa);
nwa->curblock = 0;
/* if we got this far, it's probably safe */
nwa->file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!nwa->file) goto fail;
//extra
if (nwa->restsize > nwa->blocksize) {
nwa->outdata = malloc(sizeof(int16_t) * nwa->restsize);
}
else {
nwa->outdata = malloc(sizeof(int16_t) * nwa->blocksize);
}
if (!nwa->outdata)
goto fail;
/* これ以上の大きさはないだろう、、、 */ //probably not over this size
nwa->tmpdata = malloc(sizeof(uint8_t) * nwa->blocksize * (nwa->bps / 8) * 2);
if (!nwa->tmpdata)
goto fail;
nwa->outdata_readpos = nwa->outdata;
nwa->samples_in_buffer = 0;
return nwa;
fail:
if (nwa)
{
close_nwa(nwa);
}
nwalib_close(nwa);
return NULL;
}
void
close_nwa(NWAData * nwa)
{
void nwalib_close(NWAData * nwa) {
if (!nwa) return;
if (nwa->offsets)
free (nwa->offsets);
nwa->offsets = NULL;
if (nwa->buffer)
free (nwa->buffer);
nwa->buffer = NULL;
if (nwa->file)
close_streamfile (nwa->file);
nwa->file = NULL;
free(nwa->offsets);
free(nwa->outdata);
free(nwa->tmpdata);
free(nwa);
}
void
reset_nwa(NWAData *nwa)
{
//NWAData::Rewind
void nwalib_reset(NWAData* nwa) {
nwa->curblock = 0;
nwa->buffer_readpos = nwa->buffer;
nwa->outdata_readpos = nwa->outdata;
nwa->samples_in_buffer = 0;
}
static int use_runlength(NWAData *nwa)
{
if (nwa->channels == 2 && nwa->bps == 16 && nwa->complevel == 2)
{
/* sw2 */
return 0;
// can serve up 8 bits at a time
static int getbits(const uint8_t** p_data, int* shift, int bits) {
int ret;
if (*shift > 8) {
(*p_data)++;
*shift -= 8;
}
if (nwa->complevel == 5)
{
if (nwa->channels == 2) return 0; /* BGM*.nwa in Little Busters! */
return 1; /* Tomoyo After (.nwk koe file) */
ret = get_s16le(*p_data) >> *shift;
*shift += bits;
return ret & ((1 << bits) - 1); /* mask */
}
// NWADecode
static void decode_block(NWAData* nwa, const uint8_t* data, int outdatasize) {
sample d[2];
int i;
int shift = 0;
int dsize = outdatasize / (nwa->bps / 8);
int flip_flag = 0; /* stereo 用 */ //for stereo
int runlength = 0;
/* 最初のデータを読み込む */ //read initial data
for (i = 0; i < nwa->channels; i++) {
if (nwa->bps == 8) {
d[i] = get_s8(data);
data += 1;
}
else { /* nwa->bps == 16 */
d[i] = get_s16le(data);
data += 2;
}
}
for (i = 0; i < dsize; i++) {
if (runlength == 0) { /* コピーループ中でないならデータ読み込み */ //read data if not in the copy loop
int type = getbits(&data, &shift, 3);
/* type により分岐0, 1-6, 7 */ //fork depending on type
if (type == 7) {
/* 7 : 大きな差分 */ //big diff
/* RunLength() 有効時CompLevel==5, 音声ファイル) では無効 */ //invalid when using RLE (comp=5, voice file)
if (getbits(&data, &shift, 1) == 1) {
d[flip_flag] = 0; /* 未使用 */ //unused
}
else {
int BITS, SHIFT;
if (nwa->complevel >= 3) {
BITS = 8;
SHIFT = 9;
}
else {
BITS = 8 - nwa->complevel;
SHIFT = 2 + 7 + nwa->complevel;
}
{
const int MASK1 = (1 << (BITS - 1));
const int MASK2 = (1 << (BITS - 1)) - 1;
int b = getbits(&data, &shift, BITS);
if (b & MASK1)
d[flip_flag] -= (b & MASK2) << SHIFT;
else
d[flip_flag] += (b & MASK2) << SHIFT;
}
}
}
else if (type != 0) {
/* 1-6 : 通常の差分 */ //normal diff
int BITS, SHIFT;
if (nwa->complevel >= 3) {
BITS = nwa->complevel + 3;
SHIFT = 1 + type;
}
else {
BITS = 5 - nwa->complevel;
SHIFT = 2 + type + nwa->complevel;
}
{
const int MASK1 = (1 << (BITS - 1));
const int MASK2 = (1 << (BITS - 1)) - 1;
int b = getbits(&data, &shift, BITS);
if (b & MASK1)
d[flip_flag] -= (b & MASK2) << SHIFT;
else
d[flip_flag] += (b & MASK2) << SHIFT;
}
}
else { /* type == 0 */
/* ランレングス圧縮なしの場合はなにもしない */ //does nothing in case of no RLE compression
if (nwa->use_runlength) {
/* ランレングス圧縮ありの場合 */ //in case of RLE compression
runlength = getbits(&data, &shift, 1);
if (runlength == 1) {
runlength = getbits(&data, &shift, 2);
if (runlength == 3) {
runlength = getbits(&data, &shift, 8);
}
}
}
}
}
else {
runlength--;
}
if (nwa->bps == 8) {
nwa->outdata[i] = d[flip_flag] * 256; //extra (original outputs 8-bit)
}
else {
nwa->outdata[i] = d[flip_flag];
}
if (nwa->channels == 2)
flip_flag ^= 1; /* channel 切り替え */ //channel swap
}
nwa->samples_in_buffer = dsize;
}
//NWAData::Decode
int nwalib_decode(STREAMFILE* sf, NWAData* nwa) {
/* some wav/pcm handling skipped here */
/* 今回読み込む/デコードするデータの大きさを得る */ //get current read/decode data size
int curblocksize, curcompsize;
if (nwa->curblock != nwa->blocks - 1) {
curblocksize = nwa->blocksize * (nwa->bps / 8);
curcompsize = nwa->offsets[nwa->curblock + 1] - nwa->offsets[nwa->curblock];
if (curblocksize >= nwa->blocksize * (nwa->bps / 8) * 2) {
return -1; // Fatal error
}
}
else { //last block
curblocksize = nwa->restsize * (nwa->bps / 8);
curcompsize = nwa->blocksize * (nwa->bps / 8) * 2;
}
// (in practice compsize is ~200-400 and blocksize ~0x800, but last block can be different)
/* データ読み込み */ //data read (may read less on last block?)
read_streamfile(nwa->tmpdata, nwa->offsets[nwa->curblock], curcompsize, sf);
nwa->samples_in_buffer = 0;
nwa->outdata_readpos = nwa->outdata;
decode_block(nwa, nwa->tmpdata, curblocksize);
nwa->curblock++; //todo check not over max blocks?
return 0;
}
static void
nwa_decode_block(NWAData *nwa)
{
/* 今回読み込む/デコードするデータの大きさを得る */
int curblocksize;
if (nwa->curblock != nwa->blocks - 1)
{
curblocksize = nwa->blocksize * (nwa->bps / 8);
//curcompsize = nwa->offsets[nwa->curblock + 1] - nwa->offsets[nwa->curblock];
}
else
{
curblocksize = nwa->restsize * (nwa->bps / 8);
//curcompsize = nwa->blocksize * (nwa->bps / 8) * 2;
}
nwa->samples_in_buffer = 0;
nwa->buffer_readpos = nwa->buffer;
{
sample d[2];
int i;
int shift = 0;
off_t offset = nwa->offsets[nwa->curblock];
int dsize = curblocksize / (nwa->bps / 8);
int flip_flag = 0; /* stereo 用 */
int runlength = 0;
/* read initial sample value */
for (i=0;i<nwa->channels;i++)
{
if (nwa->bps == 8) { d[i] = read_8bit(offset,nwa->file); }
else /* bps == 16 */
{
d[i] = read_16bitLE(offset,nwa->file);
offset += 2;
}
}
for (i = 0; i < dsize; i++)
{
if (runlength == 0)
{ /* コピーループ中でないならデータ読み込み */
int type = getbits(nwa->file, &offset, &shift, 3);
/* type により分岐0, 1-6, 7 */
if (type == 7)
{
/* 7 : 大きな差分 */
/* RunLength() 有効時CompLevel==5, 音声ファイル) では無効 */
if (getbits(nwa->file, &offset, &shift, 1) == 1)
{
d[flip_flag] = 0; /* 未使用 */
}
else
{
int BITS, SHIFT;
if (nwa->complevel >= 3)
{
BITS = 8;
SHIFT = 9;
}
else
{
BITS = 8 - nwa->complevel;
SHIFT = 2 + 7 + nwa->complevel;
}
{
const int MASK1 = (1 << (BITS - 1));
const int MASK2 = (1 << (BITS - 1)) - 1;
int b = getbits(nwa->file, &offset, &shift, BITS);
if (b & MASK1)
d[flip_flag] -= (b & MASK2) << SHIFT;
else
d[flip_flag] += (b & MASK2) << SHIFT;
}
}
}
else if (type != 0)
{
/* 1-6 : 通常の差分 */
int BITS, SHIFT;
if (nwa->complevel >= 3)
{
BITS = nwa->complevel + 3;
SHIFT = 1 + type;
}
else
{
BITS = 5 - nwa->complevel;
SHIFT = 2 + type + nwa->complevel;
}
{
const int MASK1 = (1 << (BITS - 1));
const int MASK2 = (1 << (BITS - 1)) - 1;
int b = getbits(nwa->file, &offset, &shift, BITS);
if (b & MASK1)
d[flip_flag] -= (b & MASK2) << SHIFT;
else
d[flip_flag] += (b & MASK2) << SHIFT;
}
}
else
{ /* type == 0 */
/* ランレングス圧縮なしの場合はなにもしない */
if (use_runlength(nwa))
{
/* ランレングス圧縮ありの場合 */
runlength = getbits(nwa->file, &offset, &shift, 1);
if (runlength == 1)
{
runlength = getbits(nwa->file, &offset, &shift, 2);
if (runlength == 3)
{
runlength = getbits(nwa->file, &offset, &shift, 8);
}
}
}
}
}
else
{
runlength--;
}
if (nwa->bps == 8)
{
nwa->buffer[i] = d[flip_flag]*0x100;
}
else
{
nwa->buffer[i] = d[flip_flag];
}
nwa->samples_in_buffer++;
if (nwa->channels == 2)
flip_flag ^= 1; /* channel 切り替え */
}
}
nwa->curblock++;
return;
}
void
seek_nwa(NWAData *nwa, int32_t seekpos)
{
int dest_block = seekpos/(nwa->blocksize/nwa->channels);
int32_t remainder = seekpos%(nwa->blocksize/nwa->channels);
//NWAFILE::Seek (not too similar)
void nwalib_seek(STREAMFILE* sf, NWAData* nwa, int32_t seekpos) {
int dest_block = seekpos / (nwa->blocksize / nwa->channels);
int32_t remainder = seekpos % (nwa->blocksize / nwa->channels);
nwa->curblock = dest_block;
nwa_decode_block(nwa);
nwalib_decode(sf, nwa);
nwa->buffer_readpos = nwa->buffer + remainder*nwa->channels;
nwa->outdata_readpos = nwa->outdata + remainder * nwa->channels;
nwa->samples_in_buffer -= remainder*nwa->channels;
}
/* interface to vgmstream */
void
decode_nwa(NWAData *nwa, sample *outbuf,
int32_t samples_to_do)
{
while (samples_to_do > 0)
{
int32_t samples_to_read;
/* ****************************************************************** */
if (nwa->samples_in_buffer > 0)
{
samples_to_read = nwa->samples_in_buffer/nwa->channels;
#include "coding.h"
struct nwa_codec_data {
STREAMFILE* sf;
NWAData* nwa;
};
/* interface to vgmstream */
void decode_nwa(nwa_codec_data* data, sample_t* outbuf, int32_t samples_to_do) {
NWAData* nwa = data->nwa;
while (samples_to_do > 0) {
if (nwa->samples_in_buffer > 0) {
int32_t samples_to_read = nwa->samples_in_buffer / nwa->channels;
if (samples_to_read > samples_to_do)
samples_to_read = samples_to_do;
memcpy(outbuf,nwa->buffer_readpos,
sizeof(sample)*samples_to_read*nwa->channels);
memcpy(outbuf, nwa->outdata_readpos, sizeof(sample_t) * samples_to_read * nwa->channels);
nwa->buffer_readpos += samples_to_read*nwa->channels;
nwa->samples_in_buffer -= samples_to_read*nwa->channels;
outbuf += samples_to_read*nwa->channels;
nwa->outdata_readpos += samples_to_read * nwa->channels;
nwa->samples_in_buffer -= samples_to_read * nwa->channels;
outbuf += samples_to_read * nwa->channels;
samples_to_do -= samples_to_read;
}
else
{
nwa_decode_block(nwa);
else {
int err = nwalib_decode(data->sf, nwa);
if (err < 0) {
VGM_LOG("NWA: decoding error\n");
return;
}
}
}
}
nwa_codec_data* init_nwa(STREAMFILE* sf) {
nwa_codec_data* data = NULL;
data = malloc(sizeof(nwa_codec_data));
if (!data) goto fail;
data->nwa = nwalib_open(sf);
if (!data->nwa) goto fail;
data->sf = reopen_streamfile(sf, 0);
if (!data->sf) goto fail;
return data;
fail:
free_nwa(data);
return NULL;
}
void seek_nwa(nwa_codec_data* data, int32_t sample) {
if (!data) return;
nwalib_seek(data->sf, data->nwa, sample);
}
void reset_nwa(nwa_codec_data* data) {
if (!data) return;
nwalib_reset(data->nwa);
}
void free_nwa(nwa_codec_data* data) {
if (!data) return;
close_streamfile(data->sf);
nwalib_close(data->nwa);
free(data);
}
STREAMFILE* nwa_get_streamfile(nwa_codec_data* data) {
if (!data) return NULL;
return data->sf;
}

View File

@ -1,4 +1,4 @@
/* originally from nwatowav.cc 2007.7.28 version, which read: */
/* derived from nwatowav.cc 2007.7.28 version, which read: */
/*
* Copyright 2001-2007 jagarl / Kazunori Ueno <jagarl@creator.club.ne.jp>
* All Rights Reserved.
@ -35,33 +35,39 @@
#include "../streamfile.h"
typedef struct NWAData_s
{
typedef struct NWAData_s {
int channels;
int bps; /* bits per sample */
int freq; /* samples per second */
int complevel; /* compression level */
int blocks; /* block count */
int datasize; /* all data size */
int compdatasize; /* compressed data size */
int samplecount; /* all samples */
int blocksize; /* samples per block */
int restsize; /* samples of the last block */
int bps; /* bits per sample */
int freq; /* samples per second */
int complevel; /* compression level */
int dummy; /* ? : 0x00 */
int blocks; /* block count */
int datasize; /* all data size */
int compdatasize; /* compressed data size */
int samplecount; /* all samples */
int blocksize; /* samples per block */
int restsize; /* samples of the last block */
int dummy2; /* ? : 0x89 */
int curblock;
off_t *offsets;
off_t* offsets;
int filesize;
STREAMFILE *file;
int use_runlength; //extra
/* temporarily store samples */
sample *buffer;
sample *buffer_readpos;
uint8_t *tmpdata;
int16_t *outdata;
int16_t *outdata_readpos;
int samples_in_buffer;
} NWAData;
NWAData *open_nwa(STREAMFILE *streamFile, const char *filename);
void close_nwa(NWAData *nwa);
void reset_nwa(NWAData *nwa);
void seek_nwa(NWAData *nwa, int32_t seekpos);
NWAData* nwalib_open(STREAMFILE* sf);
void nwalib_close(NWAData* nwa);
int nwalib_decode(STREAMFILE* sf, NWAData* nwa);
void nwalib_seek(STREAMFILE* sf, NWAData* nwa, int32_t seekpos);
void nwalib_reset(NWAData* nwa);
#endif

View File

@ -265,8 +265,7 @@ void reset_ogg_vorbis(VGMSTREAM *vgmstream) {
ov_pcm_seek(&data->ogg_vorbis_file, 0);
}
void seek_ogg_vorbis(VGMSTREAM *vgmstream, int32_t num_sample) {
ogg_vorbis_codec_data *data = vgmstream->codec_data;
void seek_ogg_vorbis(ogg_vorbis_codec_data *data, int32_t num_sample) {
if (!data) return;
/* this seek crosslaps to avoid possible clicks, so seeking to 0 will

View File

@ -17,7 +17,7 @@ static const int stex_indexes[16] = { /* OKI table (also from IMA) */
};
static void pcfx_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index, int16_t *out_sample, int mode) {
static void pcfx_expand_nibble(VGMSTREAMCHANNEL* stream, off_t byte_offset, int nibble_shift, int32_t* hist1, int32_t* step_index, int16_t* out_sample, int mode) {
int code, step, delta;
code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf;
@ -57,7 +57,7 @@ static void pcfx_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int
}
}
static void oki16_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index, int16_t *out_sample) {
static void oki16_expand_nibble(VGMSTREAMCHANNEL* stream, off_t byte_offset, int nibble_shift, int32_t* hist1, int32_t* step_index, int16_t* out_sample) {
int code, step, delta;
code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf;
@ -79,7 +79,15 @@ static void oki16_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, in
*out_sample = *hist1;
}
static void oki4s_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index, int16_t *out_sample) {
/* Possible variation for adp_konami (Viper hardware):
* delta = ((n&7) + 0.5) * stepsize / 4; clamps 2047,-2048; nigh nibble first
*
* Results are very similar, but can't verify actual decoding, and oki4s is used in
* Jubeat (also Konami) so it makes sense they would have reused it.
* Viper sound chip may be a YMZ280B though.
*/
static void oki4s_expand_nibble(VGMSTREAMCHANNEL* stream, off_t byte_offset, int nibble_shift, int32_t* hist1, int32_t* step_index, int16_t* out_sample) {
int code, step, delta;
code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf;
@ -116,7 +124,7 @@ static void oki4s_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, in
* so it's needs GENH/TXTH. Sample rate can only be base_value divided by 1/2/3/4, where
* base_value is approximately ~31468.5 (follows hardware clocks), mono or interleaved for stereo.
*/
void decode_pcfx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int mode) {
void decode_pcfx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int mode) {
int i, sample_count = 0;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
@ -137,7 +145,7 @@ void decode_pcfx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacin
/* OKI variation with 16-bit output (vs standard's 12-bit), found in FrontWing's PS2 games (Sweet Legacy, Hooligan).
* Reverse engineered from the ELF with help from the folks at hcs. */
void decode_oki16(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
void decode_oki16(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
@ -169,7 +177,7 @@ void decode_oki16(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspaci
/* OKI variation with 16-bit output (vs standard's 12-bit) and pre-adjusted tables (shifted by 4), found in Jubeat Clan (AC).
* Reverse engineered from the DLLs. */
void decode_oki4s(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
void decode_oki4s(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;

View File

@ -6,17 +6,49 @@
/* used by vorbis_custom_decoder.c, but scattered in other .c files */
#ifdef VGM_USE_VORBIS
int vorbis_custom_setup_init_fsb(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data);
int vorbis_custom_setup_init_wwise(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data);
int vorbis_custom_setup_init_ogl(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data);
int vorbis_custom_setup_init_sk(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data);
int vorbis_custom_setup_init_vid1(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data);
int vorbis_custom_parse_packet_fsb(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data);
int vorbis_custom_parse_packet_wwise(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data);
int vorbis_custom_parse_packet_ogl(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data);
int vorbis_custom_parse_packet_sk(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data);
int vorbis_custom_parse_packet_vid1(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data);
/* custom Vorbis without Ogg layer */
struct vorbis_custom_codec_data {
vorbis_info vi; /* stream settings */
vorbis_comment vc; /* stream comments */
vorbis_dsp_state vd; /* decoder global state */
vorbis_block vb; /* decoder local state */
ogg_packet op; /* fake packet for internal use */
uint8_t * buffer; /* internal raw data buffer */
size_t buffer_size;
size_t samples_to_discard; /* for looping purposes */
int samples_full; /* flag, samples available in vorbis buffers */
vorbis_custom_t type; /* Vorbis subtype */
vorbis_custom_config config; /* config depending on the mode */
/* Wwise Vorbis: saved data to reconstruct modified packets */
uint8_t mode_blockflag[64+1]; /* max 6b+1; flags 'n stuff */
int mode_bits; /* bits to store mode_number */
uint8_t prev_blockflag; /* blockflag in the last decoded packet */
/* Ogg-style Vorbis: packet within a page */
int current_packet;
/* reference for page/blocks */
off_t block_offset;
size_t block_size;
int prev_block_samples; /* count for optimization */
};
int vorbis_custom_setup_init_fsb(STREAMFILE* sf, off_t start_offset, vorbis_custom_codec_data* data);
int vorbis_custom_setup_init_wwise(STREAMFILE* sf, off_t start_offset, vorbis_custom_codec_data* data);
int vorbis_custom_setup_init_ogl(STREAMFILE* sf, off_t start_offset, vorbis_custom_codec_data* data);
int vorbis_custom_setup_init_sk(STREAMFILE* sf, off_t start_offset, vorbis_custom_codec_data* data);
int vorbis_custom_setup_init_vid1(STREAMFILE* sf, off_t start_offset, vorbis_custom_codec_data* data);
int vorbis_custom_parse_packet_fsb(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data* data);
int vorbis_custom_parse_packet_wwise(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data* data);
int vorbis_custom_parse_packet_ogl(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data* data);
int vorbis_custom_parse_packet_sk(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data* data);
int vorbis_custom_parse_packet_vid1(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data* data);
#endif/* VGM_USE_VORBIS */
#endif/*_VORBIS_CUSTOM_DECODER_H_ */

View File

@ -898,7 +898,7 @@ static const meta_info meta_info_list[] = {
{meta_PS2_OMU, "Alter Echo OMU Header"},
{meta_DSP_STM, "Intelligent Systems STM header"},
{meta_PS2_EXST, "Sony EXST header"},
{meta_PS2_SVAG, "Konami SVAG header"},
{meta_SVAG_KCET, "Konami SVAG header"},
{meta_PS_HEADERLESS, "Headerless PS-ADPCM raw header"},
{meta_PS2_MIB_MIH, "Sony MultiStream MIH+MIB header"},
{meta_DSP_MPDSP, "Single DSP header stereo by .mpdsp extension"},
@ -1154,7 +1154,7 @@ static const meta_info meta_info_list[] = {
{meta_MCA, "Capcom MCA header"},
{meta_XB3D_ADX, "Xenoblade 3D ADX header"},
{meta_HCA, "CRI HCA header"},
{meta_PS2_SVAG_SNK, "SNK SVAG header"},
{meta_SVAG_SNK, "SNK SVAG header"},
{meta_PS2_VDS_VDM, "Procyon Studio VDS/VDM header"},
{meta_FFMPEG, "FFmpeg supported file format"},
{meta_X360_CXS, "tri-Crescendo CXS header"},
@ -1302,6 +1302,7 @@ static const meta_info meta_info_list[] = {
{meta_KTSR, "Koei Tecmo KTSR header"},
{meta_KAT, "Sega KAT header"},
{meta_PCM_SUCCESS, "Success PCM header"},
{meta_ADP_KONAMI, "Konami ADP header"},
};
void get_vgmstream_coding_description(VGMSTREAM *vgmstream, char *out, size_t out_size) {

View File

@ -5,7 +5,7 @@
/* Decodes samples for blocked streams.
* Data is divided into headered blocks with a bunch of data. The layout calls external helper functions
* when a block is decoded, and those must parse the new block and move offsets accordingly. */
void render_vgmstream_blocked(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream) {
int samples_written = 0;
int frame_size, samples_per_frame, samples_this_block;
@ -52,7 +52,7 @@ void render_vgmstream_blocked(sample_t * buffer, int32_t sample_count, VGMSTREAM
break;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;

View File

@ -4,7 +4,7 @@
/* Decodes samples for flat streams.
* Data forms a single stream, and the decoder may internally skip chunks and move offsets as needed. */
void render_vgmstream_flat(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
void render_vgmstream_flat(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream) {
int samples_written = 0;
int samples_per_frame, samples_this_block;
@ -20,7 +20,7 @@ void render_vgmstream_flat(sample_t * buffer, int32_t sample_count, VGMSTREAM *
continue;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;

View File

@ -82,7 +82,7 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
continue;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;

View File

@ -12,9 +12,9 @@
* Similar to interleave layout, but decodec samples are mixed from complete vgmstreams, each
* with custom codecs and different number of channels, creating a single super-vgmstream.
* Usually combined with custom streamfiles to handle data interleaved in weird ways. */
void render_vgmstream_layered(sample_t * outbuf, int32_t sample_count, VGMSTREAM * vgmstream) {
void render_vgmstream_layered(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vgmstream) {
int samples_written = 0;
layered_layout_data *data = vgmstream->layout_data;
layered_layout_data* data = vgmstream->layout_data;
while (samples_written < sample_count) {

View File

@ -5,67 +5,67 @@
#include "../vgmstream.h"
/* blocked layouts */
void render_vgmstream_blocked(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void block_update(off_t block_offset, VGMSTREAM * vgmstream);
void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
void block_update(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ast(off_t block_ofset, VGMSTREAM * vgmstream);
void block_update_mxch(off_t block_ofset, VGMSTREAM * vgmstream);
void block_update_halpst(off_t block_ofset, VGMSTREAM * vgmstream);
void block_update_xa(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_caf(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_wsi(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_str_snds(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ws_aud(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_matx(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_dec(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_vs(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_mul(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_gsb(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_xvas(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_thp(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_filp(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ivaud(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_swvr(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_adm(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_bdsp(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_tra(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ps2_iab(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_vs_str(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_rws(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_hwas(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_awc(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_vgs(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_vawx(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_xvag_subsong(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_wve_au00(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_wve_ad10(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_sthd(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_h4m(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_xa_aiff(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_vs_square(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ast(off_t block_ofset, VGMSTREAM* vgmstream);
void block_update_mxch(off_t block_ofset, VGMSTREAM* vgmstream);
void block_update_halpst(off_t block_ofset, VGMSTREAM* vgmstream);
void block_update_xa(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ea_schl(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ea_1snh(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_caf(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_wsi(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_str_snds(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ws_aud(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_matx(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_dec(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vs(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_mul(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_gsb(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_xvas(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_thp(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_filp(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ivaud(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ea_swvr(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_adm(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_bdsp(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_tra(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ps2_iab(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vs_str(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_rws(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_hwas(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ea_sns(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_awc(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vgs(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vawx(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_xvag_subsong(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ea_wve_au00(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ea_wve_ad10(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_sthd(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_h4m(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_xa_aiff(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vs_square(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vid1(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ubi_sce(off_t block_offset, VGMSTREAM* vgmstream);
/* other layouts */
void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_interleave(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
void render_vgmstream_flat(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_flat(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
void render_vgmstream_segmented(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_segmented(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
segmented_layout_data* init_layout_segmented(int segment_count);
int setup_layout_segmented(segmented_layout_data* data);
void free_layout_segmented(segmented_layout_data *data);
void reset_layout_segmented(segmented_layout_data *data);
void free_layout_segmented(segmented_layout_data* data);
void reset_layout_segmented(segmented_layout_data* data);
VGMSTREAM *allocate_segmented_vgmstream(segmented_layout_data* data, int loop_flag, int loop_start_segment, int loop_end_segment);
void render_vgmstream_layered(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_layered(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
layered_layout_data* init_layout_layered(int layer_count);
int setup_layout_layered(layered_layout_data* data);
void free_layout_layered(layered_layout_data *data);
void reset_layout_layered(layered_layout_data *data);
void free_layout_layered(layered_layout_data* data);
void reset_layout_layered(layered_layout_data* data);
VGMSTREAM *allocate_layered_vgmstream(layered_layout_data* data);
#endif

View File

@ -9,9 +9,9 @@
/* Decodes samples for segmented streams.
* Chains together sequential vgmstreams, for data divided into separate sections or files
* (like one part for intro and other for loop segments, which may even use different codecs). */
void render_vgmstream_segmented(sample_t * outbuf, int32_t sample_count, VGMSTREAM * vgmstream) {
void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vgmstream) {
int samples_written = 0, loop_samples_skip = 0;
segmented_layout_data *data = vgmstream->layout_data;
segmented_layout_data* data = vgmstream->layout_data;
int use_internal_buffer = 0;
@ -34,8 +34,9 @@ void render_vgmstream_segmented(sample_t * outbuf, int32_t sample_count, VGMSTRE
while (total_samples < vgmstream->num_samples) {
int32_t segment_samples = data->segments[loop_segment]->num_samples;
if (vgmstream->loop_sample >= total_samples && vgmstream->loop_sample < total_samples + segment_samples) {
loop_samples_skip = vgmstream->loop_sample - total_samples;
if (vgmstream->loop_current_sample >= total_samples &&
vgmstream->loop_current_sample < total_samples + segment_samples) {
loop_samples_skip = vgmstream->loop_current_sample - total_samples;
break; /* loop_start falls within loop_segment's samples */
}
total_samples += segment_samples;
@ -58,7 +59,7 @@ void render_vgmstream_segmented(sample_t * outbuf, int32_t sample_count, VGMSTRE
continue;
}
samples_to_do = vgmstream_samples_to_do(samples_this_segment, sample_count, vgmstream);
samples_to_do = get_vgmstream_samples_to_do(samples_this_segment, sample_count, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;
if (samples_to_do > VGMSTREAM_SEGMENT_SAMPLE_BUFFER /*&& use_internal_buffer*/) /* always for fade/etc mixes */
@ -106,7 +107,7 @@ void render_vgmstream_segmented(sample_t * outbuf, int32_t sample_count, VGMSTRE
segmented_layout_data* init_layout_segmented(int segment_count) {
segmented_layout_data *data = NULL;
segmented_layout_data* data = NULL;
if (segment_count <= 0 || segment_count > VGMSTREAM_MAX_SEGMENTS)
goto fail;
@ -202,7 +203,7 @@ fail:
return 0; /* caller is expected to free */
}
void free_layout_segmented(segmented_layout_data *data) {
void free_layout_segmented(segmented_layout_data* data) {
int i, j;
if (!data)
@ -228,7 +229,7 @@ void free_layout_segmented(segmented_layout_data *data) {
free(data);
}
void reset_layout_segmented(segmented_layout_data *data) {
void reset_layout_segmented(segmented_layout_data* data) {
int i;
if (!data)

View File

@ -468,10 +468,14 @@
RelativePath=".\meta\acb.c"
>
</File>
<File
RelativePath=".\meta\acm.c"
>
</File>
<File
RelativePath=".\meta\acm.c"
>
</File>
<File
RelativePath=".\meta\adp_konami.c"
>
</File>
<File
RelativePath=".\meta\adpcm_capcom.c"
>
@ -1387,11 +1391,11 @@
>
</File>
<File
RelativePath=".\meta\ps2_svag.c"
RelativePath=".\meta\svag_kcet.c"
>
</File>
<File
RelativePath=".\meta\ps2_svag_snk.c"
RelativePath=".\meta\svag_snk.c"
>
</File>
<File

View File

@ -271,6 +271,7 @@
<ClCompile Include="meta\aax.c" />
<ClCompile Include="meta\acb.c" />
<ClCompile Include="meta\acm.c" />
<ClCompile Include="meta\adp_konami.c" />
<ClCompile Include="meta\adpcm_capcom.c" />
<ClCompile Include="meta\ads.c" />
<ClCompile Include="meta\adx.c" />
@ -454,8 +455,8 @@
<ClCompile Include="meta\ps2_snd.c" />
<ClCompile Include="meta\ps2_sps.c" />
<ClCompile Include="meta\ps2_ster.c" />
<ClCompile Include="meta\ps2_svag.c" />
<ClCompile Include="meta\ps2_svag_snk.c" />
<ClCompile Include="meta\svag_kcet.c" />
<ClCompile Include="meta\svag_snk.c" />
<ClCompile Include="meta\ps2_tec.c" />
<ClCompile Include="meta\ps2_tk5.c" />
<ClCompile Include="meta\vag.c" />

View File

@ -337,6 +337,9 @@
<ClCompile Include="meta\acm.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\adp_konami.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\adpcm_capcom.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -871,10 +874,10 @@
<ClCompile Include="meta\ps2_ster.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_svag.c">
<ClCompile Include="meta\svag_kcet.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_svag_snk.c">
<ClCompile Include="meta\svag_snk.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_tec.c">

51
src/meta/adp_konami.c Normal file
View File

@ -0,0 +1,51 @@
#include "meta.h"
#include "../coding/coding.h"
/* ADP - from Konami Viper arcade games [ParaParaParadise 2ndMIX (AC)] */
VGMSTREAM* init_vgmstream_adp_konami(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channels;
size_t data_size, file_size;
/* checks */
if (!check_extensions(sf, "adp"))
goto fail;
if (read_u32be(0x00,sf) != 0x41445002) /* "ADP\2" */
goto fail;
start_offset = 0x10;
channels = 2; /* probably @0x03 */
loop_flag = 0;
data_size = read_u32be(0x04,sf);
file_size = get_streamfile_size(sf);
if (!(data_size + start_offset - 0x04 <= file_size &&
data_size + start_offset + 0x04 >= file_size)) /* 1 byte padding in some files */
goto fail;
if (read_u32be(0x08,sf) != 0 || read_u32be(0x0c,sf) != 0) /* maybe reserved for loop points */
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_ADP_KONAMI;
vgmstream->sample_rate = 44100;
vgmstream->num_samples = oki_bytes_to_samples(data_size, channels);
vgmstream->coding_type = coding_OKI4S;
vgmstream->layout_type = layout_none;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -128,12 +128,8 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
/* Alt decoding without libvorbis (minor number of beginning samples difference).
* Otherwise same output with (inaudible) +-1 lower byte differences due to rounding. */
case 0x05: { /* Ogg Vorbis [Final Fantasy VI (iOS), Dragon Quest II-VI (iOS)] */
ffmpeg_codec_data *ffmpeg_data;
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* These oggs have loop info in the comments, too */
@ -149,12 +145,8 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
case 0x06: { /* M4A with AAC [The World Ends with You (iPad)] */
/* init_vgmstream_akb_mp4 above has priority, but this works fine too */
ffmpeg_codec_data *ffmpeg_data;
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size-start_offset);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset,stream_size-start_offset);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -112,8 +112,7 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
}
case 0x09: { /* XMA2 [Quantum Theory (PS3)] */
ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[200];
uint8_t buf[0x100];
int32_t bytes;
if (!find_chunk_be(streamHeader, 0x584D4558,first_offset,1, &chunk_offset,NULL)) /* "XMEX" */
@ -122,9 +121,8 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
/* 0x34: seek table */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, chunk_offset,0x34, data_size, streamHeader, 1);
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -10,69 +10,73 @@ static void find_hca_key(hca_codec_data* hca_data, uint64_t* p_keycode, uint16_t
/* CRI HCA - streamed audio from CRI ADX2/Atom middleware */
VGMSTREAM * init_vgmstream_hca(STREAMFILE *streamFile) {
return init_vgmstream_hca_subkey(streamFile, 0x0000);
VGMSTREAM * init_vgmstream_hca(STREAMFILE* sf) {
return init_vgmstream_hca_subkey(sf, 0x0000);
}
VGMSTREAM * init_vgmstream_hca_subkey(STREAMFILE *streamFile, uint16_t subkey) {
VGMSTREAM * init_vgmstream_hca_subkey(STREAMFILE* sf, uint16_t subkey) {
VGMSTREAM * vgmstream = NULL;
hca_codec_data * hca_data = NULL;
hca_codec_data* hca_data = NULL;
clHCA_stInfo* hca_info;
/* checks */
if ( !check_extensions(streamFile, "hca"))
if (!check_extensions(sf, "hca"))
return NULL;
if (((uint32_t)read_32bitBE(0x00,streamFile) & 0x7f7f7f7f) != 0x48434100) /* "HCA\0", possibly masked */
if ((read_u32be(0x00,sf) & 0x7F7F7F7F) != 0x48434100) /* "HCA\0", possibly masked */
goto fail;
/* init vgmstream and library's context, will validate the HCA */
hca_data = init_hca(streamFile);
hca_data = init_hca(sf);
if (!hca_data) goto fail;
hca_info = hca_get_info(hca_data);
/* find decryption key in external file or preloaded list */
if (hca_data->info.encryptionEnabled) {
if (hca_info->encryptionEnabled) {
uint64_t keycode = 0;
uint8_t keybuf[0x08+0x02];
size_t keysize;
keysize = read_key_file(keybuf, 0x08+0x04, streamFile);
keysize = read_key_file(keybuf, 0x08+0x04, sf);
if (keysize == 0x08) { /* standard */
keycode = (uint64_t)get_64bitBE(keybuf+0x00);
keycode = get_u64be(keybuf+0x00);
if (subkey) {
keycode = keycode * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) );
}
}
else if (keysize == 0x08+0x02) { /* seed key + AWB subkey */
uint64_t file_key = (uint64_t)get_64bitBE(keybuf+0x00);
uint16_t file_sub = (uint16_t)get_16bitBE(keybuf+0x08);
uint64_t file_key = get_u64be(keybuf+0x00);
uint16_t file_sub = get_u16be(keybuf+0x08);
keycode = file_key * ( ((uint64_t)file_sub << 16u) | ((uint16_t)~file_sub + 2u) );
}
#ifdef HCA_BRUTEFORCE
else if (1) {
bruteforce_hca_key(streamFile, hca_data, &keycode, subkey);
bruteforce_hca_key(sf, hca_data, &keycode, subkey);
}
#endif
else {
find_hca_key(hca_data, &keycode, subkey);
}
clHCA_SetKey(hca_data->handle, (unsigned long long)keycode); //maybe should be done through hca_decoder.c?
hca_set_encryption_key(hca_data, keycode);
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(hca_data->info.channelCount, hca_data->info.loopEnabled);
vgmstream = allocate_vgmstream(hca_info->channelCount, hca_info->loopEnabled);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_HCA;
vgmstream->sample_rate = hca_data->info.samplingRate;
vgmstream->sample_rate = hca_info->samplingRate;
vgmstream->num_samples = hca_data->info.blockCount * hca_data->info.samplesPerBlock -
hca_data->info.encoderDelay - hca_data->info.encoderPadding;
vgmstream->loop_start_sample = hca_data->info.loopStartBlock * hca_data->info.samplesPerBlock -
hca_data->info.encoderDelay + hca_data->info.loopStartDelay;
vgmstream->loop_end_sample = hca_data->info.loopEndBlock * hca_data->info.samplesPerBlock -
hca_data->info.encoderDelay + (hca_data->info.samplesPerBlock - hca_data->info.loopEndPadding);
vgmstream->num_samples = hca_info->blockCount * hca_info->samplesPerBlock -
hca_info->encoderDelay - hca_info->encoderPadding;
vgmstream->loop_start_sample = hca_info->loopStartBlock * hca_info->samplesPerBlock -
hca_info->encoderDelay + hca_info->loopStartDelay;
vgmstream->loop_end_sample = hca_info->loopEndBlock * hca_info->samplesPerBlock -
hca_info->encoderDelay + (hca_info->samplesPerBlock - hca_info->loopEndPadding);
/* After loop end CRI's encoder removes the rest of the original samples and puts some
* garbage in the last frame that should be ignored. Optionally it can encode fully preserving
* the file too, but it isn't detectable, so we'll allow the whole thing just in case */
@ -80,10 +84,10 @@ VGMSTREAM * init_vgmstream_hca_subkey(STREAMFILE *streamFile, uint16_t subkey) {
// vgmstream->num_samples = vgmstream->loop_end_sample;
/* this can happen in preloading HCA from memory AWB */
if (hca_data->info.blockCount * hca_data->info.blockSize > get_streamfile_size(streamFile)) {
unsigned int max_block = get_streamfile_size(streamFile) / hca_data->info.blockSize;
vgmstream->num_samples = max_block * hca_data->info.samplesPerBlock -
hca_data->info.encoderDelay - hca_data->info.encoderPadding;
if (hca_info->blockCount * hca_info->blockSize > get_streamfile_size(sf)) {
unsigned int max_block = get_streamfile_size(sf) / hca_info->blockSize;
vgmstream->num_samples = max_block * hca_info->samplesPerBlock -
hca_info->encoderDelay - hca_info->encoderPadding;
}
vgmstream->coding_type = coding_CRI_HCA;
@ -115,7 +119,7 @@ fail:
}
static inline void test_key(hca_codec_data * hca_data, uint64_t key, uint16_t subkey, int *best_score, uint64_t *best_keycode) {
static inline void test_key(hca_codec_data* hca_data, uint64_t key, uint16_t subkey, int* best_score, uint64_t* best_keycode) {
int score;
if (subkey) {

View File

@ -76,7 +76,7 @@ VGMSTREAM * init_vgmstream_raw_int(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_exst(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_svag(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_svag_kcet(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps_headerless(STREAMFILE *streamFile);
@ -565,7 +565,7 @@ VGMSTREAM * init_vgmstream_mca(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_btsnd(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_svag_snk(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_svag_snk(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_xma(STREAMFILE* streamFile);
@ -909,4 +909,6 @@ VGMSTREAM* init_vgmstream_pcm_success(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_ktsc(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_adp_konami(STREAMFILE* sf);
#endif /*_META_H*/

View File

@ -128,17 +128,15 @@ VGMSTREAM * init_vgmstream_msf(STREAMFILE *streamFile) {
#endif
#if defined(VGM_USE_MPEG)
case 0x07: { /* MPEG (CBR LAME MP3) [Dengeki Bunko Fighting Climax (PS3)] */
mpeg_codec_data *mpeg_data = NULL;
mpeg_data = init_mpeg(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels);
if (!mpeg_data) goto fail;
vgmstream->codec_data = mpeg_data;
vgmstream->codec_data = init_mpeg(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels);
if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = mpeg_bytes_to_samples(data_size, mpeg_data);
vgmstream->num_samples = mpeg_bytes_to_samples(data_size, vgmstream->codec_data);
if (loop_flag) {
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data);
vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data);
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, vgmstream->codec_data);
vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, vgmstream->codec_data);
/* loops are always aligned to CBR frame beginnings */
}

View File

@ -2,61 +2,56 @@
#include "../coding/coding.h"
/* .NAAC - from Namco 3DS games (Ace Combat - Assault Horizon Legacy, Taiko no Tatsujin Don to Katsu no Jikuu Daibouken) */
VGMSTREAM * init_vgmstream_naac(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_naac(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
/* check extension */
if ( !check_extensions(streamFile,"naac") )
if ( !check_extensions(sf,"naac") )
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x41414320) /* "AAC " */
if (read_32bitBE(0x00,sf) != 0x41414320) /* "AAC " */
goto fail;
if (read_32bitLE(0x04,streamFile) != 0x01) /* version? */
if (read_32bitLE(0x04,sf) != 0x01) /* version? */
goto fail;
start_offset = 0x1000;
loop_flag = (read_32bitLE(0x18,streamFile) != 0);
channel_count = read_32bitLE(0x08,streamFile);
loop_flag = (read_32bitLE(0x18,sf) != 0);
channel_count = read_32bitLE(0x08,sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x0c,streamFile);
vgmstream->num_samples = read_32bitLE(0x10,streamFile); /* without skip_samples */
vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile); /* with skip_samples */
vgmstream->loop_end_sample = read_32bitLE(0x18,streamFile);
vgmstream->sample_rate = read_32bitLE(0x0c,sf);
vgmstream->num_samples = read_32bitLE(0x10,sf); /* without skip_samples */
vgmstream->loop_start_sample = read_32bitLE(0x14,sf); /* with skip_samples */
vgmstream->loop_end_sample = read_32bitLE(0x18,sf);
/* 0x1c: loop start offset, 0x20: loop end offset (within data) */
data_size = read_32bitLE(0x24,streamFile);
data_size = read_32bitLE(0x24,sf);
/* 0x28: unknown; 0x2c: table start offset?; 0x30: seek table (always 0xFD0, padded) */
vgmstream->meta_type = meta_NAAC;
#ifdef VGM_USE_FFMPEG
{
ffmpeg_codec_data *ffmpeg_data = NULL;
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,data_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset,data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* observed default, some files start without silence though seems correct when loop_start=0 */
if (!ffmpeg_data->skipSamples) /* FFmpeg doesn't seem to use not report it */
ffmpeg_set_skip_samples(ffmpeg_data, 1024);
ffmpeg_set_skip_samples(vgmstream->codec_data, 1024); /* raw AAC doesn't set this */
vgmstream->num_samples -= 1024;
}
#else
goto fail;
#endif
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

View File

@ -29,8 +29,8 @@ struct dsp_header {
/* read the above struct; returns nonzero on failure */
static int read_dsp_header_endian(struct dsp_header *header, off_t offset, STREAMFILE *streamFile, int big_endian) {
int32_t (*get_32bit)(uint8_t *) = big_endian ? get_32bitBE : get_32bitLE;
int16_t (*get_16bit)(uint8_t *) = big_endian ? get_16bitBE : get_16bitLE;
int32_t (*get_32bit)(const uint8_t *) = big_endian ? get_32bitBE : get_32bitLE;
int16_t (*get_16bit)(const uint8_t *) = big_endian ? get_16bitBE : get_16bitLE;
int i;
uint8_t buf[0x4e];

View File

@ -1,18 +1,15 @@
#include "meta.h"
#include "../util.h"
#include "../coding/nwa_decoder.h"
#include "../coding/coding.h"
#include <string.h>
#include <ctype.h>
static int get_loops_nwainfo_ini(STREAMFILE *streamFile, int *out_loop_flag, int32_t *out_loop_start);
static int get_loops_gameexe_ini(STREAMFILE *streamFile, int *out_loop_flag, int32_t *out_loop_start, int32_t *out_loop_end);
static nwa_codec_data *open_nwa_vgmstream(STREAMFILE *streamFile);
static void free_nwa_vgmstream(nwa_codec_data *data);
static int get_loops_nwainfo_ini(STREAMFILE *sf, int *p_loop_flag, int32_t *p_loop_start);
static int get_loops_gameexe_ini(STREAMFILE *sf, int *p_loop_flag, int32_t *p_loop_start, int32_t *p_loop_end);
/* NWA - Visual Art's streams [Air (PC), Clannad (PC)] */
VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_nwa(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int channel_count, loop_flag = 0;
int32_t loop_start_sample = 0, loop_end_sample = 0;
@ -21,26 +18,26 @@ VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
/* checks */
if (!check_extensions(streamFile, "nwa"))
if (!check_extensions(sf, "nwa"))
goto fail;
channel_count = read_16bitLE(0x00,streamFile);
channel_count = read_16bitLE(0x00,sf);
if (channel_count != 1 && channel_count != 2) goto fail;
/* check if we're using raw pcm */
if ( read_32bitLE(0x08,streamFile)==-1 || /* compression level */
read_32bitLE(0x10,streamFile)==0 || /* block count */
read_32bitLE(0x18,streamFile)==0 || /* compressed data size */
read_32bitLE(0x20,streamFile)==0 || /* block size */
read_32bitLE(0x24,streamFile)==0 ) { /* restsize */
if ( read_32bitLE(0x08,sf)==-1 || /* compression level */
read_32bitLE(0x10,sf)==0 || /* block count */
read_32bitLE(0x18,sf)==0 || /* compressed data size */
read_32bitLE(0x20,sf)==0 || /* block size */
read_32bitLE(0x24,sf)==0 ) { /* restsize */
compression_level = -1;
} else {
compression_level = read_32bitLE(0x08,streamFile);
compression_level = read_32bitLE(0x08,sf);
}
/* loop points come from external files */
nwainfo_ini_found = get_loops_nwainfo_ini(streamFile, &loop_flag, &loop_start_sample);
gameexe_ini_found = !nwainfo_ini_found && get_loops_gameexe_ini(streamFile, &loop_flag, &loop_start_sample, &loop_end_sample);
nwainfo_ini_found = get_loops_nwainfo_ini(sf, &loop_flag, &loop_start_sample);
gameexe_ini_found = !nwainfo_ini_found && get_loops_gameexe_ini(sf, &loop_flag, &loop_start_sample, &loop_end_sample);
start_offset = 0x2c;
@ -48,12 +45,12 @@ VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x04,streamFile);
vgmstream->num_samples = read_32bitLE(0x1c,streamFile) / channel_count;
vgmstream->sample_rate = read_32bitLE(0x04,sf);
vgmstream->num_samples = read_32bitLE(0x1c,sf) / channel_count;
switch(compression_level) {
case -1:
switch (read_16bitLE(0x02,streamFile)) {
switch (read_16bitLE(0x02,sf)) {
case 8:
vgmstream->coding_type = coding_PCM8;
vgmstream->interleave_block_size = 0x01;
@ -76,7 +73,7 @@ VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
case 5:
vgmstream->coding_type = coding_NWA;
vgmstream->layout_type = layout_none;
vgmstream->codec_data = open_nwa_vgmstream(streamFile);
vgmstream->codec_data = init_nwa(sf);
if (!vgmstream->codec_data) goto fail;
break;
@ -103,7 +100,7 @@ VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;
@ -114,8 +111,8 @@ fail:
/* try to locate NWAINFO.INI in the same directory */
static int get_loops_nwainfo_ini(STREAMFILE *streamFile, int *out_loop_flag, int32_t *out_loop_start) {
STREAMFILE *streamLoops;
static int get_loops_nwainfo_ini(STREAMFILE *sf, int *p_loop_flag, int32_t *p_loop_start) {
STREAMFILE *sf_loop;
char namebase[PATH_LIMIT];
const char * ext;
int length;
@ -127,15 +124,15 @@ static int get_loops_nwainfo_ini(STREAMFILE *streamFile, int *out_loop_flag, int
int32_t loop_start_sample = 0;
streamLoops = open_streamfile_by_filename(streamFile, "NWAINFO.INI");
if (!streamLoops) goto fail;
sf_loop = open_streamfile_by_filename(sf, "NWAINFO.INI");
if (!sf_loop) goto fail;
get_streamfile_filename(streamFile,namebase,PATH_LIMIT);
get_streamfile_filename(sf,namebase,PATH_LIMIT);
/* ini found, try to find our name */
ext = filename_extension(namebase);
length = ext - 1 - namebase;
file_size = get_streamfile_size(streamLoops);
file_size = get_streamfile_size(sf_loop);
for (found = 0, offset = 0; !found && offset < file_size; offset++) {
off_t suboffset;
@ -145,12 +142,12 @@ static int get_loops_nwainfo_ini(STREAMFILE *streamFile, int *out_loop_flag, int
for (suboffset = offset;
suboffset < file_size &&
suboffset-offset < length &&
read_8bit(suboffset,streamLoops) == namebase[suboffset-offset];
read_8bit(suboffset,sf_loop) == namebase[suboffset-offset];
suboffset++) {
/* skip */
}
if (suboffset-offset==length && read_8bit(suboffset,streamLoops)==0x09) { /* tab */
if (suboffset-offset==length && read_8bit(suboffset,sf_loop)==0x09) { /* tab */
found = 1;
found_off = suboffset+1;
}
@ -160,7 +157,7 @@ static int get_loops_nwainfo_ini(STREAMFILE *streamFile, int *out_loop_flag, int
if (found) {
char loopstring[9] = {0};
if (read_streamfile((uint8_t*)loopstring,found_off,8,streamLoops) == 8) {
if (read_streamfile((uint8_t*)loopstring,found_off,8,sf_loop) == 8) {
loop_start_sample = atol(loopstring);
if (loop_start_sample > 0)
loop_flag = 1;
@ -168,22 +165,22 @@ static int get_loops_nwainfo_ini(STREAMFILE *streamFile, int *out_loop_flag, int
}
*out_loop_flag = loop_flag;
*out_loop_start = loop_start_sample;
*p_loop_flag = loop_flag;
*p_loop_start = loop_start_sample;
close_streamfile(streamLoops);
close_streamfile(sf_loop);
return 1;
fail:
close_streamfile(streamLoops);
close_streamfile(sf_loop);
return 0;
}
/* try to locate Gameexe.ini in the same directory */
static int get_loops_gameexe_ini(STREAMFILE *streamFile, int *out_loop_flag, int32_t *out_loop_start, int32_t *out_loop_end) {
STREAMFILE *streamLoops;
static int get_loops_gameexe_ini(STREAMFILE* sf, int* p_loop_flag, int32_t* p_loop_start, int32_t* p_loop_end) {
STREAMFILE*sf_loop;
char namebase[PATH_LIMIT];
const char * ext;
const char* ext;
int length;
int found;
off_t offset;
@ -193,15 +190,15 @@ static int get_loops_gameexe_ini(STREAMFILE *streamFile, int *out_loop_flag, int
int32_t loop_start_sample = 0, loop_end_sample = 0;
streamLoops = open_streamfile_by_filename(streamFile, "Gameexe.ini");
if (!streamLoops) goto fail;
sf_loop = open_streamfile_by_filename(sf, "Gameexe.ini");
if (!sf_loop) goto fail;
get_streamfile_filename(streamFile,namebase,PATH_LIMIT);
get_streamfile_filename(sf,namebase,PATH_LIMIT);
/* ini found, try to find our name */
ext = filename_extension(namebase);
length = ext-1-namebase;
file_size = get_streamfile_size(streamLoops);
file_size = get_streamfile_size(sf_loop);
/* format of line is:
* #DSTRACK = 00000000 - eeeeeeee - ssssssss = "name" = "name2?"
@ -212,20 +209,20 @@ static int get_loops_gameexe_ini(STREAMFILE *streamFile, int *out_loop_flag, int
off_t suboffset;
uint8_t buf[10];
if (read_8bit(offset,streamLoops)!='#') continue;
if (read_streamfile(buf,offset+1,10,streamLoops)!=10) break;
if (read_8bit(offset,sf_loop)!='#') continue;
if (read_streamfile(buf,offset+1,10,sf_loop)!=10) break;
if (memcmp("DSTRACK = ",buf,10)) continue;
if (read_8bit(offset+44,streamLoops)!='\"') continue;
if (read_8bit(offset+44,sf_loop)!='\"') continue;
for (suboffset = offset+45;
suboffset < file_size &&
suboffset-offset-45 < length &&
tolower(read_8bit(suboffset,streamLoops)) == tolower(namebase[suboffset-offset-45]);
tolower(read_8bit(suboffset,sf_loop)) == tolower(namebase[suboffset-offset-45]);
suboffset++) {
/* skip */
}
if (suboffset-offset-45==length && read_8bit(suboffset,streamLoops)=='\"') { /* tab */
if (suboffset-offset-45==length && read_8bit(suboffset,sf_loop)=='\"') { /* tab */
found = 1;
found_off = offset+22; /* loop end */
}
@ -234,9 +231,9 @@ static int get_loops_gameexe_ini(STREAMFILE *streamFile, int *out_loop_flag, int
if (found) {
char loopstring[9] = {0};
int start_ok = 0, end_ok = 0;
int32_t total_samples = read_32bitLE(0x1c,streamFile) / read_16bitLE(0x00,streamFile);
int32_t total_samples = read_32bitLE(0x1c,sf) / read_16bitLE(0x00,sf);
if (read_streamfile((uint8_t*)loopstring,found_off,8,streamLoops)==8)
if (read_streamfile((uint8_t*)loopstring,found_off,8,sf_loop)==8)
{
if (!memcmp("99999999",loopstring,8)) {
loop_end_sample = total_samples;
@ -246,7 +243,7 @@ static int get_loops_gameexe_ini(STREAMFILE *streamFile, int *out_loop_flag, int
}
end_ok = 1;
}
if (read_streamfile((uint8_t*)loopstring,found_off+11,8,streamLoops)==8)
if (read_streamfile((uint8_t*)loopstring,found_off+11,8,sf_loop)==8)
{
if (!memcmp("99999999",loopstring,8)) {
/* not ok to start at last sample,
@ -265,43 +262,14 @@ static int get_loops_gameexe_ini(STREAMFILE *streamFile, int *out_loop_flag, int
} /* if found file name in INI */
*out_loop_flag = loop_flag;
*out_loop_start = loop_start_sample;
*out_loop_end = loop_end_sample;
*p_loop_flag = loop_flag;
*p_loop_start = loop_start_sample;
*p_loop_end = loop_end_sample;
close_streamfile(streamLoops);
close_streamfile(sf_loop);
return 1;
fail:
close_streamfile(streamLoops);
close_streamfile(sf_loop);
return 0;
}
static nwa_codec_data *open_nwa_vgmstream(STREAMFILE *streamFile) {
nwa_codec_data *data = NULL;
char filename[PATH_LIMIT];
streamFile->get_name(streamFile,filename,sizeof(filename));
data = malloc(sizeof(nwa_codec_data));
if (!data) goto fail;
data->nwa = open_nwa(streamFile,filename);
if (!data->nwa) goto fail;
return data;
fail:
free_nwa_vgmstream(data);
return NULL;
}
static void free_nwa_vgmstream(nwa_codec_data *data) {
if (data) {
if (data->nwa) {
close_nwa(data->nwa);
}
free(data);
}
}

View File

@ -1,80 +0,0 @@
#include "meta.h"
#include "../util.h"
/* PS2 SVAG (SNK)
*
* Found in SNK's World Heroes Anthology and Fatal Fury Battle Archives 2, maybe others
* No relation with Konami's SVAG.
*/
VGMSTREAM * init_vgmstream_ps2_svag_snk(STREAMFILE* streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset = 0x20;
int loop_flag;
int channel_count;
int loop_start_block;
int loop_end_block;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("svag",filename_extension(filename))) goto fail;
/* check SNK SVAG Header ("VAGm") */
if (read_32bitBE(0x00,streamFile) != 0x5641476D)
goto fail;
channel_count = read_32bitLE(0x0c,streamFile);
loop_start_block = read_32bitLE(0x18,streamFile);
loop_end_block = read_32bitLE(0x1c,streamFile);
loop_flag = loop_end_block > 0; /* loop_start_block can be 0 */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* header data */
vgmstream->coding_type = coding_PSX;
vgmstream->meta_type = meta_PS2_SVAG_SNK;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
vgmstream->num_samples = read_32bitLE(0x10,streamFile) * 28; /* size in blocks */
if( vgmstream->loop_flag ) {
vgmstream->loop_start_sample = loop_start_block * 28;
vgmstream->loop_end_sample = loop_end_block * 28;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
/* 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;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -23,8 +23,8 @@ VGMSTREAM * init_vgmstream_redspark(STREAMFILE *streamFile) {
uint32_t key;
enum {encsize = 0x1000};
uint8_t buf[encsize];
int32_t(*get_32bit)(uint8_t *p) = NULL;
int16_t(*get_16bit)(uint8_t *p) = NULL;
int32_t(*get_32bit)(const uint8_t *p) = NULL;
int16_t(*get_16bit)(const uint8_t *p) = NULL;
get_16bit = get_16bitBE;
get_32bit = get_32bitBE;

View File

@ -3,36 +3,36 @@
/* SGXD - Sony/SCEI's format (SGB+SGH / SGD / SGX) */
VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamHeader = NULL;
VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sf_head = NULL;
off_t start_offset, data_offset, chunk_offset, name_offset = 0;
size_t stream_size;
int is_sgx, is_sgb = 0;
int loop_flag, channels, codec;
int sample_rate, num_samples, loop_start_sample, loop_end_sample;
int total_subsongs, target_subsong = streamFile->stream_index;
int total_subsongs, target_subsong = sf->stream_index;
/* check extension, case insensitive */
/* .sgx: header+data (Genji), .sgd: header+data, .sgh/sgd: header/data */
if (!check_extensions(streamFile,"sgx,sgd,sgb"))
if (!check_extensions(sf,"sgx,sgd,sgb"))
goto fail;
is_sgx = check_extensions(streamFile,"sgx");
is_sgb = check_extensions(streamFile,"sgb");
is_sgx = check_extensions(sf,"sgx");
is_sgb = check_extensions(sf,"sgb");
/* SGB+SGH: use SGH as header; otherwise use the current file as header */
if (is_sgb) {
streamHeader = open_streamfile_by_ext(streamFile, "sgh");
if (!streamHeader) goto fail;
sf_head = open_streamfile_by_ext(sf, "sgh");
if (!sf_head) goto fail;
} else {
streamHeader = streamFile;
sf_head = sf;
}
/* SGXD base (size 0x10) */
if (read_32bitBE(0x00,streamHeader) != 0x53475844) /* "SGXD" */
if (read_32bitBE(0x00,sf_head) != 0x53475844) /* "SGXD" */
goto fail;
/* 0x04 SGX: full header_size; SGD/SGH: unknown header_size (counting from 0x0/0x8/0x10, varies) */
/* 0x08 SGX: first chunk offset? (0x10); SGD/SGH: full header_size */
@ -40,24 +40,24 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
if (is_sgb) {
data_offset = 0x00;
} else if ( is_sgx ) {
data_offset = read_32bitLE(0x04,streamHeader);
data_offset = read_32bitLE(0x04,sf_head);
} else {
data_offset = read_32bitLE(0x08,streamHeader);
data_offset = read_32bitLE(0x08,sf_head);
}
/* typical chunks: WAVE, RGND, NAME (strings for WAVE or RGND), SEQD (related to SFX), WSUR, WMKR, BUSS */
/* WAVE chunk (size 0x10 + files * 0x38 + optional padding) */
if (is_sgx) { /* position after chunk+size */
if (read_32bitBE(0x10,streamHeader) != 0x57415645) goto fail; /* "WAVE" */
if (read_32bitBE(0x10,sf_head) != 0x57415645) goto fail; /* "WAVE" */
chunk_offset = 0x18;
} else {
if (!find_chunk_le(streamHeader, 0x57415645,0x10,0, &chunk_offset,NULL)) goto fail; /* "WAVE" */
if (!find_chunk_le(sf_head, 0x57415645,0x10,0, &chunk_offset,NULL)) goto fail; /* "WAVE" */
}
/* 0x04 SGX: unknown; SGD/SGH: chunk length, 0x08 null */
/* check multi-streams (usually only SE containers; Puppeteer) */
total_subsongs = read_32bitLE(chunk_offset+0x04,streamHeader);
total_subsongs = read_32bitLE(chunk_offset+0x04,sf_head);
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
@ -68,11 +68,11 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
/* 0x00 ? (00/01/02) */
if (!is_sgx) /* meaning unknown in .sgx; offset 0 = not a stream (a RGND sample) */
name_offset = read_32bitLE(chunk_offset+0x04,streamHeader);
codec = read_8bit(chunk_offset+0x08,streamHeader);
channels = read_8bit(chunk_offset+0x09,streamHeader);
name_offset = read_32bitLE(chunk_offset+0x04,sf_head);
codec = read_8bit(chunk_offset+0x08,sf_head);
channels = read_8bit(chunk_offset+0x09,sf_head);
/* 0x0a null */
sample_rate = read_32bitLE(chunk_offset+0x0c,streamHeader);
sample_rate = read_32bitLE(chunk_offset+0x0c,sf_head);
/* 0x10 info_type: meaning of the next value
* (00=null, 30/40=data size without padding (ADPCM, ATRAC3plus), 80/A0=block size (AC3) */
@ -80,15 +80,15 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
/* 0x18 unknown (ex. 0x0008/0010/3307/CC02/etc)x2 */
/* 0x1c null */
num_samples = read_32bitLE(chunk_offset+0x20,streamHeader);
loop_start_sample = read_32bitLE(chunk_offset+0x24,streamHeader);
loop_end_sample = read_32bitLE(chunk_offset+0x28,streamHeader);
stream_size = read_32bitLE(chunk_offset+0x2c,streamHeader); /* stream size (without padding) / interleave (for type3) */
num_samples = read_32bitLE(chunk_offset+0x20,sf_head);
loop_start_sample = read_32bitLE(chunk_offset+0x24,sf_head);
loop_end_sample = read_32bitLE(chunk_offset+0x28,sf_head);
stream_size = read_32bitLE(chunk_offset+0x2c,sf_head); /* stream size (without padding) / interleave (for type3) */
if (is_sgx) {
stream_offset = 0x0;
} else{
stream_offset = read_32bitLE(chunk_offset+0x30,streamHeader);
stream_offset = read_32bitLE(chunk_offset+0x30,sf_head);
}
/* 0x34 SGX: unknown; SGD/SGH: stream size (with padding) / interleave */
@ -109,7 +109,7 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
vgmstream->stream_size = stream_size;
vgmstream->meta_type = meta_SGXD;
if (name_offset)
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamHeader);
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sf_head);
switch (codec) {
@ -121,7 +121,7 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
#ifdef VGM_USE_VORBIS
case 0x02: /* Ogg Vorbis [Ni no Kuni: Wrath of the White Witch Remastered (PC)] (codec hijack?) */
vgmstream->codec_data = init_ogg_vorbis(streamFile, start_offset, stream_size, NULL);
vgmstream->codec_data = init_ogg_vorbis(sf, start_offset, stream_size, NULL);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_OGG_VORBIS;
vgmstream->layout_type = layout_none;
@ -143,7 +143,7 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
case 0x04: { /* ATRAC3plus [Kurohyo 1/2 (PSP), BraveStory (PSP)] */
vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, start_offset, NULL);
vgmstream->codec_data = init_ffmpeg_atrac3_riff(sf, start_offset, NULL);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -163,20 +163,15 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
case 0x06: { /* AC3 [Tokyo Jungle (PS3), Afrika (PS3)] */
ffmpeg_codec_data *ffmpeg_data;
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset, stream_size);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset, stream_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* manually set skip_samples if FFmpeg didn't do it */
if (ffmpeg_data->skipSamples <= 0) {
/* PS3 AC3 consistently has 256 encoder delay samples, and there are ~1000-2000 samples after num_samples.
* Skipping them marginally improves full loops in some Tokyo Jungle tracks (ex. a_1.sgd). */
ffmpeg_set_skip_samples(ffmpeg_data, 256);
}
/* PS3 AC3 consistently has 256 encoder delay samples, and there are ~1000-2000 samples after num_samples.
* Skipping them marginally improves full loops in some Tokyo Jungle tracks (ex. a_1.sgd). */
ffmpeg_set_skip_samples(vgmstream->codec_data, 256);
/* SGXD loop/sample values are relative (without skip samples), no need to adjust */
break;
@ -188,15 +183,14 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
goto fail;
}
/* open the file for reading */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
if (is_sgb && streamHeader) close_streamfile(streamHeader);
if (is_sgb && sf_head) close_streamfile(sf_head);
return vgmstream;
fail:
if (is_sgb && streamHeader) close_streamfile(streamHeader);
if (is_sgb && sf_head) close_streamfile(sf_head);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -241,22 +241,20 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG
case 0x07: { /* MPEG [Final Fantasy XIII (PS3)] */
mpeg_codec_data *mpeg_data = NULL;
mpeg_custom_config cfg = {0};
cfg.interleave = 0x800; /* for multistream [Final Fantasy XIII-2 (PS3)], otherwise ignored */
cfg.data_size = stream_size;
mpeg_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg);
if (!mpeg_data) goto fail;
vgmstream->codec_data = mpeg_data;
vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none;
/* some Drakengard 3, Kingdom Hearts HD have adjusted sample rate (47999, 44099), for looping? */
vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, mpeg_data);
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data);
vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data);
vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, vgmstream->codec_data);
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, vgmstream->codec_data);
vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, vgmstream->codec_data);
/* somehow loops offsets aren't always frame-aligned, and the code below supposedly helped,
* but there isn't much difference since MPEG loops are rough (1152-aligned). Seems it

View File

@ -230,7 +230,6 @@ VGMSTREAM* init_vgmstream_sqex_sead(STREAMFILE* sf) {
#ifdef VGM_USE_MPEG
case 0x06: { /* MSMP3 (MSF subfile) [Dragon Quest Builders (PS3)] */
mpeg_codec_data *mpeg_data = NULL;
mpeg_custom_config cfg = {0};
start_offset = sead.extradata_offset + sead.extradata_size;
@ -238,12 +237,11 @@ VGMSTREAM* init_vgmstream_sqex_sead(STREAMFILE* sf) {
/* extradata: */
/* proper MSF header, but sample rate/loops are ignored in favor of SAB's */
mpeg_data = init_mpeg_custom(sf, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_STANDARD, &cfg);
if (!mpeg_data) goto fail;
vgmstream->codec_data = mpeg_data;
vgmstream->codec_data = init_mpeg_custom(sf, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_STANDARD, &cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = mpeg_bytes_to_samples(sead.stream_size, mpeg_data);
vgmstream->num_samples = mpeg_bytes_to_samples(sead.stream_size, vgmstream->codec_data);
vgmstream->loop_start_sample = sead.loop_start;
vgmstream->loop_end_sample = sead.loop_end;
break;

View File

@ -3,32 +3,31 @@
/* .STRM - from Abylight 3DS games [Cursed Castilla (3DS)] */
VGMSTREAM * init_vgmstream_strm_abylight(STREAMFILE *streamFile) {
VGMSTREAM* init_vgmstream_strm_abylight(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, sample_rate;
size_t data_size;
/* check extension */
if ( !check_extensions(streamFile,"strm") )
/* checks */
if ( !check_extensions(sf,"strm") )
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x5354524D) /* "STRM" */
if (read_32bitBE(0x00,sf) != 0x5354524D) /* "STRM" */
goto fail;
if (read_32bitLE(0x04,streamFile) != 0x03E8) /* version 1000? */
if (read_32bitLE(0x04,sf) != 0x03E8) /* version 1000? */
goto fail;
loop_flag = 0;
channel_count = 2; /* there are various possible fields but all files are stereo */
sample_rate = read_32bitLE(0x08,streamFile);
sample_rate = read_32bitLE(0x08,sf);
start_offset = 0x1e;
data_size = read_32bitLE(0x10,streamFile);
if (data_size != get_streamfile_size(streamFile) - start_offset)
data_size = read_32bitLE(0x10,sf);
if (data_size != get_streamfile_size(sf) - start_offset)
goto fail;
if (data_size != read_32bitLE(0x18,streamFile))
if (data_size != read_32bitLE(0x18,sf))
goto fail;
@ -37,31 +36,26 @@ VGMSTREAM * init_vgmstream_strm_abylight(STREAMFILE *streamFile) {
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = aac_get_samples(streamFile, start_offset, data_size);
vgmstream->num_samples = aac_get_samples(sf, start_offset, data_size);
vgmstream->meta_type = meta_STRM_ABYLIGHT;
#ifdef VGM_USE_FFMPEG
{
ffmpeg_codec_data *ffmpeg_data = NULL;
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,data_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset, data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* apparently none, or maybe ~600 */
//if (!ffmpeg_data->skipSamples)
// ffmpeg_set_skip_samples(ffmpeg_data, 1024);
//ffmpeg_set_skip_samples(ffmpeg_data, 1024);
//vgmstream->num_samples -= 1024;
}
#else
goto fail;
#endif
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
if ( !vgmstream_open_stream(vgmstream, sf, start_offset) )
goto fail;
return vgmstream;

View File

@ -2,51 +2,54 @@
#include "../coding/coding.h"
/* SVAG - from Konami Tokyo games [OZ (PS2), Neo Contra (PS2), Silent Hill 2 (PS2)] */
VGMSTREAM * init_vgmstream_ps2_svag(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_svag_kcet(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
size_t data_size;
int loop_flag, channel_count;
/* checks */
if (!check_extensions(streamFile, "svag"))
if (!check_extensions(sf, "svag"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53766167) /* "Svag" */
if (read_32bitBE(0x00,sf) != 0x53766167) /* "Svag" */
goto fail;
channel_count = read_16bitLE(0x0C,streamFile); /* always 2? ("S"tereo vag?) */
loop_flag = (read_32bitLE(0x14,streamFile)==1);
channel_count = read_16bitLE(0x0C,sf); /* always 2? ("S"tereo vag?) */
loop_flag = (read_32bitLE(0x14,sf) ==1);
/* header repeated at 0x400 presumably for stereo */
if (channel_count > 1 && read_32bitBE(0x400,streamFile) != 0x53766167) /* "Svag" */
/* test padding (a set "KCE-Tokyo ..." phrase) after 0x1c to catch bad rips,
* at 0x400 may be header again (Silent Hill 2) or more padding (Silent Scope 2) */
if (channel_count > 1 &&
read_32bitBE(0x400,sf) != 0x53766167 && /* "Svag" */
read_32bitBE(0x400,sf) != 0x44657369) /* "Desi" */
goto fail;
start_offset = 0x800;
data_size = read_32bitLE(0x04,streamFile);
data_size = read_32bitLE(0x04,sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
vgmstream->sample_rate = read_32bitLE(0x08,sf);
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x04,streamFile), vgmstream->channels);
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x04,sf), vgmstream->channels);
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x18,streamFile)*vgmstream->channels, vgmstream->channels);
vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x18,sf)*vgmstream->channels, vgmstream->channels);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
vgmstream->meta_type = meta_PS2_SVAG;
vgmstream->meta_type = meta_SVAG_KCET;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile);
vgmstream->interleave_block_size = read_32bitLE(0x10,sf);
if (vgmstream->interleave_block_size)
vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

46
src/meta/svag_snk.c Normal file
View File

@ -0,0 +1,46 @@
#include "meta.h"
#include "../util.h"
/* .SVAG - from SNK games [World Heroes Anthology (PS2), Fatal Fury Battle Archives 2 (PS2)] */
VGMSTREAM* init_vgmstream_svag_snk(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, loop_start_block, loop_end_block;
/* checks */
if (!check_extensions(sf, "svag"))
goto fail;
if (read_32bitBE(0x00,sf) != 0x5641476D) /* "VAGm" */
goto fail;
channel_count = read_32bitLE(0x0c,sf);
loop_start_block = read_32bitLE(0x18,sf);
loop_end_block = read_32bitLE(0x1c,sf);
loop_flag = loop_end_block > 0; /* loop_start_block can be 0 */
start_offset = 0x20;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SVAG_SNK;
vgmstream->sample_rate = read_32bitLE(0x08,sf);
vgmstream->num_samples = read_32bitLE(0x10,sf) * 28; /* size in blocks */
vgmstream->loop_start_sample = loop_start_block * 28;
vgmstream->loop_end_sample = loop_end_block * 28;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -414,8 +414,8 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
/* get coefs */
{
int16_t (*read_16bit)(off_t , STREAMFILE*) = txth.coef_big_endian ? read_16bitBE : read_16bitLE;
int16_t (*get_16bit)(uint8_t * p) = txth.coef_big_endian ? get_16bitBE : get_16bitLE;
int16_t (*read_16bit)(off_t, STREAMFILE*) = txth.coef_big_endian ? read_16bitBE : read_16bitLE;
int16_t (*get_16bit)(const uint8_t* p) = txth.coef_big_endian ? get_16bitBE : get_16bitLE;
for (i = 0; i < vgmstream->channels; i++) {
if (txth.coef_mode == 0) { /* normal coefs */

View File

@ -479,14 +479,15 @@ static void apply_config(VGMSTREAM *vgmstream, txtp_entry *current) {
if (current->trim_set) {
if (current->trim_second != 0.0) {
current->trim_sample = current->trim_second * vgmstream->sample_rate;
/* trim sample can become 0 here when second is too small (rounded) */
current->trim_sample = (double)current->trim_second * (double)vgmstream->sample_rate;
}
if (current->trim_sample < 0) {
vgmstream->num_samples += current->trim_sample; /* trim from end (add negative) */
}
else if (vgmstream->num_samples > current->trim_sample) {
vgmstream->num_samples = current->trim_sample; /* trim to value */
else if (current->trim_sample > 0 && vgmstream->num_samples > current->trim_sample) {
vgmstream->num_samples = current->trim_sample; /* trim to value >0 */
}
/* readjust after triming if it went over (could check for more edge cases but eh) */

View File

@ -154,7 +154,6 @@ VGMSTREAM * init_vgmstream_ubi_lyn(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG
case 0x5051: { /* MPEG (PS3/PC), interleaved 1ch */
mpeg_codec_data *mpeg_data = NULL;
mpeg_custom_config cfg = {0};
int i;
@ -175,9 +174,8 @@ VGMSTREAM * init_vgmstream_ubi_lyn(STREAMFILE *streamFile) {
cfg.data_size = data_size;
//todo data parsing looks correct but some files decode a bit wrong at the end (ex. Tintin: Music~Boss~Allan~Victory~02)
mpeg_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_LYN, &cfg);
if (!mpeg_data) goto fail;
vgmstream->codec_data = mpeg_data;
vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_LYN, &cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none;
break;

View File

@ -1116,7 +1116,6 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
// Probably a beta/custom encoder that creates some buggy frames, that a real X360 handles ok, but trips FFmpeg
// xmaencode decodes correctly if counters are fixed (otherwise has clicks on every frame).
case FMT_XMA1: {
ffmpeg_codec_data *ffmpeg_data;
uint8_t buf[0x100];
uint32_t sec1_num, sec2_num, sec3_num, bits_per_frame;
uint8_t flag;
@ -1147,9 +1146,8 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, 0x100, header_offset, chunk_size, data_size, sf_data, 1);
ffmpeg_data = init_ffmpeg_header_offset(sf_data, buf, bytes, start_offset, data_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_header_offset(sf_data, buf, bytes, start_offset, data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -1158,7 +1156,6 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
}
case RAW_XMA1: {
ffmpeg_codec_data *ffmpeg_data;
uint8_t buf[0x100];
size_t bytes, chunk_size;
off_t header_offset;
@ -1173,9 +1170,8 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, 0x100, header_offset, chunk_size, sb->stream_size, sf_head, 1);
ffmpeg_data = init_ffmpeg_header_offset(sf_data, buf, bytes, start_offset, sb->stream_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_header_offset(sf_data, buf, bytes, start_offset, sb->stream_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -4,8 +4,8 @@
/* VAWX - found in feelplus games [No More Heroes: Heroes Paradise (PS3/X360), Moon Diver (PS3/X360)] */
VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_vawx(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, data_size;
int loop_flag = 0, channel_count, codec;
@ -13,15 +13,15 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
/* checks */
/* .xwv: actual extension [Moon Diver (PS3/X360)]
* .vawx: header id */
if ( !check_extensions(streamFile, "xwv,vawx") )
if ( !check_extensions(sf, "xwv,vawx") )
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x56415758) /* "VAWX" */
if (read_32bitBE(0x00,sf) != 0x56415758) /* "VAWX" */
goto fail;
loop_flag = read_8bit(0x37,streamFile);
channel_count = read_8bit(0x39,streamFile);
start_offset = 0x800; /* ? read_32bitLE(0x0c,streamFile); */
codec = read_8bit(0x36,streamFile); /* could be at 0x38 too */
loop_flag = read_8bit(0x37,sf);
channel_count = read_8bit(0x39,sf);
start_offset = 0x800; /* ? read_32bitLE(0x0c,sf); */
codec = read_8bit(0x36,sf); /* could be at 0x38 too */
/* build the VGMSTREAM */
@ -30,8 +30,8 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
/* 0x04: filesize */
/* 0x16: file id */
vgmstream->num_samples = read_32bitBE(0x3c,streamFile);
vgmstream->sample_rate = read_32bitBE(0x40,streamFile);
vgmstream->num_samples = read_32bitBE(0x3c,sf);
vgmstream->sample_rate = read_32bitBE(0x40,sf);
vgmstream->meta_type = meta_VAWX;
@ -41,53 +41,51 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
vgmstream->layout_type = channel_count == 6 ? layout_blocked_vawx : layout_interleave;
vgmstream->interleave_block_size = 0x10;
vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile);
vgmstream->loop_start_sample = read_32bitBE(0x44,sf);
vgmstream->loop_end_sample = read_32bitBE(0x48,sf);
break;
#ifdef VGM_USE_FFMPEG
case 1: { /* XMA2 */
ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[0x100];
int32_t bytes, block_size, block_count;
data_size = get_streamfile_size(streamFile)-start_offset;
data_size = get_streamfile_size(sf)-start_offset;
block_size = 0x10000; /* VAWX default */
block_count = (uint16_t)read_16bitBE(0x3A, streamFile); /* also at 0x56 */
block_count = (uint16_t)read_16bitBE(0x3A, sf); /* also at 0x56 */
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile);
vgmstream->loop_start_sample = read_32bitBE(0x44,sf);
vgmstream->loop_end_sample = read_32bitBE(0x48,sf);
//todo fix loops/samples vs ATRAC3
/* may be only applying end_skip to num_samples? */
xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0);
xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0);
break;
}
case 7: { /* ATRAC3 */
int block_align, encoder_delay;
data_size = read_32bitBE(0x54,streamFile);
data_size = read_32bitBE(0x54,sf);
block_align = 0x98 * vgmstream->channels;
encoder_delay = 1024 + 69*2; /* observed default, matches XMA (needed as many files start with garbage) */
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay; /* original samples break looping in some files otherwise */
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* set offset samples (offset 0 jumps to sample 0 > pre-applied delay, and offset end loops after sample end > adjusted delay) */
vgmstream->loop_start_sample = atrac3_bytes_to_samples(read_32bitBE(0x44,streamFile), block_align); //- encoder_delay
vgmstream->loop_end_sample = atrac3_bytes_to_samples(read_32bitBE(0x48,streamFile), block_align) - encoder_delay;
vgmstream->loop_start_sample = atrac3_bytes_to_samples(read_32bitBE(0x44,sf), block_align); //- encoder_delay
vgmstream->loop_end_sample = atrac3_bytes_to_samples(read_32bitBE(0x48,sf), block_align) - encoder_delay;
break;
}
#endif
@ -97,7 +95,7 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
}
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

View File

@ -2,61 +2,58 @@
#include "../coding/coding.h"
/* CXS - found in Eternal Sonata (X360) */
VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_x360_cxs(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* checks */
if ( !check_extensions(streamFile,"cxs"))
if ( !check_extensions(sf,"cxs"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x43585320) /* "CXS " */
if (read_32bitBE(0x00,sf) != 0x43585320) /* "CXS " */
goto fail;
loop_flag = read_32bitBE(0x18,streamFile) > 0;
channel_count = read_32bitBE(0x0c,streamFile);
start_offset = read_32bitBE(0x04,streamFile) + read_32bitBE(0x28,streamFile); /* assumed, seek table always at 0x800 */
loop_flag = read_32bitBE(0x18,sf) > 0;
channel_count = read_32bitBE(0x0c,sf);
start_offset = read_32bitBE(0x04,sf) + read_32bitBE(0x28,sf); /* assumed, seek table always at 0x800 */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* 0x04: data start? */
vgmstream->sample_rate = read_32bitBE(0x08,streamFile);
vgmstream->num_samples = read_32bitBE(0x10,streamFile);
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile);
vgmstream->sample_rate = read_32bitBE(0x08,sf);
vgmstream->num_samples = read_32bitBE(0x10,sf);
vgmstream->loop_start_sample = read_32bitBE(0x14,sf);
vgmstream->loop_end_sample = read_32bitBE(0x18,sf);
/* 0x1c: below */
vgmstream->meta_type = meta_X360_CXS;
#ifdef VGM_USE_FFMPEG
{
ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[100];
uint8_t buf[0x100];
size_t bytes, datasize, block_size, block_count;
block_count = read_32bitBE(0x1c,streamFile);
block_size = read_32bitBE(0x20,streamFile);
datasize = read_32bitBE(0x24,streamFile);
block_count = read_32bitBE(0x1c,sf);
block_size = read_32bitBE(0x20,sf);
datasize = read_32bitBE(0x24,sf);
bytes = ffmpeg_make_riff_xma2(buf,100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
if (bytes <= 0) goto fail;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,datasize);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset,datasize, 0, 0,1); /* num samples are ok */
xma_fix_raw_samples(vgmstream, sf, start_offset,datasize, 0, 0,1); /* num samples are ok */
}
#else
goto fail;
#endif
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
if ( !vgmstream_open_stream(vgmstream, sf, start_offset) )
goto fail;
return vgmstream;

View File

@ -142,7 +142,6 @@ VGMSTREAM *init_vgmstream_xmv_valve(STREAMFILE *streamFile) {
break;
#ifdef VGM_USE_FFMPEG
case 0x01: { /* XMA */
ffmpeg_codec_data *ffmpeg_data;
uint8_t buf[0x100];
int block_count, block_size;
size_t bytes;
@ -152,10 +151,8 @@ VGMSTREAM *init_vgmstream_xmv_valve(STREAMFILE *streamFile) {
bytes = ffmpeg_make_riff_xma2(buf, 0x100, num_samples, data_size, channels, sample_rate, block_count, block_size);
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, data_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->loop_end_sample -= loop_end_skip;
@ -166,16 +163,13 @@ VGMSTREAM *init_vgmstream_xmv_valve(STREAMFILE *streamFile) {
#endif
#ifdef VGM_USE_MPEG
case 0x03: { /* MP3 */
mpeg_codec_data *mpeg_data;
coding_t mpeg_coding;
if (loop_flag) /* should never happen, Source cannot loop MP3 */
goto fail;
mpeg_data = init_mpeg(streamFile, start_offset, &mpeg_coding, channels);
if (!mpeg_data) goto fail;
vgmstream->codec_data = mpeg_data;
vgmstream->codec_data = init_mpeg(streamFile, start_offset, &mpeg_coding, channels);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = mpeg_coding;
vgmstream->layout_type = layout_none;

View File

@ -67,7 +67,7 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none;
vgmstream->sample_rate = ((mpeg_codec_data*)vgmstream->codec_data)->sample_rate_per_frame;
vgmstream->sample_rate = mpeg_get_sample_rate(vgmstream->codec_data);
break;
}
#endif

View File

@ -65,13 +65,13 @@
* to do file operations, as plugins may need to provide their own callbacks.
* Reads from arbitrary offsets, meaning internally may need fseek equivalents during reads. */
typedef struct _STREAMFILE {
size_t (*read)(struct _STREAMFILE *, uint8_t * dst, off_t offset, size_t length);
size_t (*get_size)(struct _STREAMFILE *);
off_t (*get_offset)(struct _STREAMFILE *); //todo: DO NOT USE, NOT RESET PROPERLY (remove?)
size_t (*read)(struct _STREAMFILE*, uint8_t* dst, off_t offset, size_t length);
size_t (*get_size)(struct _STREAMFILE*);
off_t (*get_offset)(struct _STREAMFILE*); //todo: DO NOT USE, NOT RESET PROPERLY (remove?)
/* for dual-file support */
void (*get_name)(struct _STREAMFILE * ,char *name, size_t length);
struct _STREAMFILE * (*open)(struct _STREAMFILE *, const char * const filename, size_t buffersize);
void (*close)(struct _STREAMFILE *);
void (*get_name)(struct _STREAMFILE*, char* name, size_t length);
struct _STREAMFILE* (*open)(struct _STREAMFILE*, const char* const filename, size_t buffersize);
void (*close)(struct _STREAMFILE*);
/* Substream selection for files with subsongs. Manually used in metas if supported.
@ -86,152 +86,152 @@ typedef struct _STREAMFILE {
/* Opens a standard STREAMFILE, opening from path.
* Uses stdio (FILE) for operations, thus plugins may not want to use it. */
STREAMFILE* open_stdio_streamfile(const char *filename);
STREAMFILE* open_stdio_streamfile(const char* filename);
/* Opens a standard STREAMFILE from a pre-opened FILE. */
STREAMFILE* open_stdio_streamfile_by_file(FILE *file, const char *filename);
STREAMFILE* open_stdio_streamfile_by_file(FILE* file, const char* filename);
/* Opens a STREAMFILE that does buffered IO.
* Can be used when the underlying IO may be slow (like when using custom IO).
* Buffer size is optional. */
STREAMFILE* open_buffer_streamfile(STREAMFILE *streamfile, size_t buffer_size);
STREAMFILE* open_buffer_streamfile_f(STREAMFILE *streamfile, size_t buffer_size);
STREAMFILE* open_buffer_streamfile(STREAMFILE* sf, size_t buffer_size);
STREAMFILE* open_buffer_streamfile_f(STREAMFILE* sf, size_t buffer_size);
/* Opens a STREAMFILE that doesn't close the underlying streamfile.
* Calls to open won't wrap the new SF (assumes it needs to be closed).
* Can be used in metas to test custom IO without closing the external SF. */
STREAMFILE* open_wrap_streamfile(STREAMFILE *streamfile);
STREAMFILE* open_wrap_streamfile_f(STREAMFILE *streamfile);
STREAMFILE* open_wrap_streamfile(STREAMFILE* sf);
STREAMFILE* open_wrap_streamfile_f(STREAMFILE* sf);
/* Opens a STREAMFILE that clamps reads to a section of a larger streamfile.
* Can be used with subfiles inside a bigger file (to fool metas, or to simplify custom IO). */
STREAMFILE* open_clamp_streamfile(STREAMFILE *streamfile, off_t start, size_t size);
STREAMFILE* open_clamp_streamfile_f(STREAMFILE *streamfile, off_t start, size_t size);
STREAMFILE* open_clamp_streamfile(STREAMFILE* sf, off_t start, size_t size);
STREAMFILE* open_clamp_streamfile_f(STREAMFILE* sf, off_t start, size_t size);
/* Opens a STREAMFILE that uses custom IO for streamfile reads.
* Can be used to modify data on the fly (ex. decryption), or even transform it from a format to another.
* Data is an optional state struct of some size what will be malloc+copied on open. */
STREAMFILE* open_io_streamfile(STREAMFILE *streamfile, void *data, size_t data_size, void *read_callback, void *size_callback);
STREAMFILE* open_io_streamfile_f(STREAMFILE *streamfile, void *data, size_t data_size, void *read_callback, void *size_callback);
STREAMFILE* open_io_streamfile(STREAMFILE* sf, void* data, size_t data_size, void* read_callback, void* size_callback);
STREAMFILE* open_io_streamfile_f(STREAMFILE* sf, void* data, size_t data_size, void* read_callback, void* size_callback);
/* Same, but calls init on SF open and close on close, when malloc/free is needed.
* Data struct may be used to hold malloc'd pointers and stuff. */
STREAMFILE* open_io_streamfile_ex(STREAMFILE *streamfile, void *data, size_t data_size, void *read_callback, void *size_callback, void* init_callback, void* close_callback);
STREAMFILE* open_io_streamfile_ex_f(STREAMFILE *streamfile, void *data, size_t data_size, void *read_callback, void *size_callback, void* init_callback, void* close_callback);
STREAMFILE* open_io_streamfile_ex(STREAMFILE* sf, void* data, size_t data_size, void* read_callback, void* size_callback, void* init_callback, void* close_callback);
STREAMFILE* open_io_streamfile_ex_f(STREAMFILE* sf, void* data, size_t data_size, void* read_callback, void* size_callback, void* init_callback, void* close_callback);
/* Opens a STREAMFILE that reports a fake name, but still re-opens itself properly.
* Can be used to trick a meta's extension check (to call from another, with a modified SF).
* When fakename isn't supplied it's read from the streamfile, and the extension swapped with fakeext.
* If the fakename is an existing file, open won't work on it as it'll reopen the fake-named streamfile. */
STREAMFILE* open_fakename_streamfile(STREAMFILE *streamfile, const char * fakename, const char * fakeext);
STREAMFILE* open_fakename_streamfile_f(STREAMFILE *streamfile, const char * fakename, const char * fakeext);
STREAMFILE* open_fakename_streamfile(STREAMFILE* sf, const char* fakename, const char* fakeext);
STREAMFILE* open_fakename_streamfile_f(STREAMFILE* sf, const char* fakename, const char* fakeext);
/* Opens streamfile formed from multiple streamfiles, their data joined during reads.
* Can be used when data is segmented in multiple separate files.
* The first streamfile is used to get names, stream index and so on. */
STREAMFILE* open_multifile_streamfile(STREAMFILE **streamfiles, size_t streamfiles_size);
STREAMFILE* open_multifile_streamfile_f(STREAMFILE **streamfiles, size_t streamfiles_size);
STREAMFILE* open_multifile_streamfile(STREAMFILE** sfs, size_t sfs_size);
STREAMFILE* open_multifile_streamfile_f(STREAMFILE** sfs, size_t sfs_size);
/* Opens a STREAMFILE from a (path)+filename.
* Just a wrapper, to avoid having to access the STREAMFILE's callbacks directly. */
STREAMFILE* open_streamfile(STREAMFILE *streamfile, const char * pathname);
STREAMFILE* open_streamfile(STREAMFILE* sf, const char* pathname);
/* Opens a STREAMFILE from a base pathname + new extension
* Can be used to get companion headers. */
STREAMFILE* open_streamfile_by_ext(STREAMFILE *streamfile, const char * ext);
STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext);
/* Opens a STREAMFILE from a base path + new filename.
* Can be used to get companion files. Relative paths like
* './filename', '../filename', 'dir/filename' also work. */
STREAMFILE* open_streamfile_by_filename(STREAMFILE *streamfile, const char * filename);
STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename);
/* Reopen a STREAMFILE with a different buffer size, for fine-tuned bigfile parsing.
* Uses default buffer size when buffer_size is 0 */
STREAMFILE * reopen_streamfile(STREAMFILE *streamfile, size_t buffer_size);
STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size);
/* close a file, destroy the STREAMFILE object */
static inline void close_streamfile(STREAMFILE * streamfile) {
if (streamfile!=NULL)
streamfile->close(streamfile);
static inline void close_streamfile(STREAMFILE* sf) {
if (sf != NULL)
sf->close(sf);
}
/* read from a file, returns number of bytes read */
static inline size_t read_streamfile(uint8_t *dst, off_t offset, size_t length, STREAMFILE *streamfile) {
return streamfile->read(streamfile, dst, offset,length);
static inline size_t read_streamfile(uint8_t *dst, off_t offset, size_t length, STREAMFILE* sf) {
return sf->read(sf, dst, offset,length);
}
/* return file size */
static inline size_t get_streamfile_size(STREAMFILE * streamfile) {
return streamfile->get_size(streamfile);
static inline size_t get_streamfile_size(STREAMFILE* sf) {
return sf->get_size(sf);
}
/* Sometimes you just need an int, and we're doing the buffering.
* Note, however, that if these fail to read they'll return -1,
* so that should not be a valid value or there should be some backup. */
static inline int16_t read_16bitLE(off_t offset, STREAMFILE * streamfile) {
static inline int16_t read_16bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[2];
if (read_streamfile(buf,offset,2,streamfile)!=2) return -1;
if (read_streamfile(buf,offset,2,sf)!=2) return -1;
return get_16bitLE(buf);
}
static inline int16_t read_16bitBE(off_t offset, STREAMFILE * streamfile) {
static inline int16_t read_16bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[2];
if (read_streamfile(buf,offset,2,streamfile)!=2) return -1;
if (read_streamfile(buf,offset,2,sf)!=2) return -1;
return get_16bitBE(buf);
}
static inline int32_t read_32bitLE(off_t offset, STREAMFILE * streamfile) {
static inline int32_t read_32bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf,offset,4,streamfile)!=4) return -1;
if (read_streamfile(buf,offset,4,sf)!=4) return -1;
return get_32bitLE(buf);
}
static inline int32_t read_32bitBE(off_t offset, STREAMFILE * streamfile) {
static inline int32_t read_32bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf,offset,4,streamfile)!=4) return -1;
if (read_streamfile(buf,offset,4,sf)!=4) return -1;
return get_32bitBE(buf);
}
static inline int64_t read_64bitLE(off_t offset, STREAMFILE * streamfile) {
static inline int64_t read_64bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[8];
if (read_streamfile(buf,offset,8,streamfile)!=8) return -1;
if (read_streamfile(buf,offset,8,sf)!=8) return -1;
return get_64bitLE(buf);
}
static inline int64_t read_64bitBE(off_t offset, STREAMFILE * streamfile) {
static inline int64_t read_64bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[8];
if (read_streamfile(buf,offset,8,streamfile)!=8) return -1;
if (read_streamfile(buf,offset,8,sf)!=8) return -1;
return get_64bitBE(buf);
}
static inline int8_t read_8bit(off_t offset, STREAMFILE * streamfile) {
static inline int8_t read_8bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[1];
if (read_streamfile(buf,offset,1,streamfile)!=1) return -1;
if (read_streamfile(buf,offset,1,sf)!=1) return -1;
return buf[0];
}
/* alias of the above */
static inline int8_t read_s8 (off_t offset, STREAMFILE *sf) { return read_8bit(offset, sf); }
static inline uint8_t read_u8 (off_t offset, STREAMFILE *sf) { return (uint8_t) read_8bit(offset, sf); }
static inline int16_t read_s16le(off_t offset, STREAMFILE *sf) { return read_16bitLE(offset, sf); }
static inline uint16_t read_u16le(off_t offset, STREAMFILE *sf) { return (uint16_t)read_16bitLE(offset, sf); }
static inline int16_t read_s16be(off_t offset, STREAMFILE *sf) { return read_16bitBE(offset, sf); }
static inline uint16_t read_u16be(off_t offset, STREAMFILE *sf) { return (uint16_t)read_16bitBE(offset, sf); }
static inline int32_t read_s32le(off_t offset, STREAMFILE *sf) { return read_32bitLE(offset, sf); }
static inline uint32_t read_u32le(off_t offset, STREAMFILE *sf) { return (uint32_t)read_32bitLE(offset, sf); }
static inline int32_t read_s32be(off_t offset, STREAMFILE *sf) { return read_32bitBE(offset, sf); }
static inline uint32_t read_u32be(off_t offset, STREAMFILE *sf) { return (uint32_t)read_32bitBE(offset, sf); }
static inline int64_t read_s64be(off_t offset, STREAMFILE *sf) { return read_64bitBE(offset, sf); }
static inline uint64_t read_u64be(off_t offset, STREAMFILE *sf) { return (uint64_t)read_64bitBE(offset, sf); }
static inline int64_t read_s64le(off_t offset, STREAMFILE *sf) { return read_64bitLE(offset, sf); }
static inline uint64_t read_u64le(off_t offset, STREAMFILE *sf) { return (uint64_t)read_64bitLE(offset, sf); }
static inline int8_t read_s8 (off_t offset, STREAMFILE* sf) { return read_8bit(offset, sf); }
static inline uint8_t read_u8 (off_t offset, STREAMFILE* sf) { return (uint8_t) read_8bit(offset, sf); }
static inline int16_t read_s16le(off_t offset, STREAMFILE* sf) { return read_16bitLE(offset, sf); }
static inline uint16_t read_u16le(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitLE(offset, sf); }
static inline int16_t read_s16be(off_t offset, STREAMFILE* sf) { return read_16bitBE(offset, sf); }
static inline uint16_t read_u16be(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitBE(offset, sf); }
static inline int32_t read_s32le(off_t offset, STREAMFILE* sf) { return read_32bitLE(offset, sf); }
static inline uint32_t read_u32le(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitLE(offset, sf); }
static inline int32_t read_s32be(off_t offset, STREAMFILE* sf) { return read_32bitBE(offset, sf); }
static inline uint32_t read_u32be(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitBE(offset, sf); }
static inline int64_t read_s64be(off_t offset, STREAMFILE* sf) { return read_64bitBE(offset, sf); }
static inline uint64_t read_u64be(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitBE(offset, sf); }
static inline int64_t read_s64le(off_t offset, STREAMFILE* sf) { return read_64bitLE(offset, sf); }
static inline uint64_t read_u64le(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitLE(offset, sf); }
/* The recommended int-to-float type punning in C is through union, but pointer casting
* works too (though less portable due to aliasing rules?). For C++ memcpy seems
* recommended. Both work in GCC and VS2015+ (not sure about older, ifdef as needed). */
static inline float read_f32be(off_t offset, STREAMFILE *sf) {
static inline float read_f32be(off_t offset, STREAMFILE* sf) {
union {
uint32_t u32;
float f32;
@ -239,7 +239,7 @@ static inline float read_f32be(off_t offset, STREAMFILE *sf) {
temp.u32 = read_u32be(offset, sf);
return temp.f32;
}
static inline float read_f32le(off_t offset, STREAMFILE * sf) {
static inline float read_f32le(off_t offset, STREAMFILE* sf) {
union {
uint32_t u32;
float f32;
@ -248,12 +248,12 @@ static inline float read_f32le(off_t offset, STREAMFILE * sf) {
return temp.f32;
}
#if 0
static inline float read_f32be_p(off_t offset, STREAMFILE *sf) {
static inline float read_f32be_p(off_t offset, STREAMFILE* sf) {
uint32_t sample_int = read_u32be(offset, sf);
float* sample_float = (float*)&sample_int;
return *sample_float;
}
static inline float read_f32be_m(off_t offset, STREAMFILE *sf) {
static inline float read_f32be_m(off_t offset, STREAMFILE* sf) {
uint32_t sample_int = read_u32be(offset, sf);
float sample_float;
memcpy(&sample_float, &sample_int, sizeof(uint32_t));
@ -288,18 +288,18 @@ void sf_reader_init(sf_reader *r, int big_endian) {
*/
#endif
#if 0 //todo improve + test + simplify code (maybe not inline?)
static inline int read_s4h(off_t offset, STREAMFILE * streamfile) {
static inline int read_s4h(off_t offset, STREAMFILE* sf) {
uint8_t byte = read_u8(offset, streamfile);
return get_nibble_signed(byte, 1);
}
static inline int read_u4h(off_t offset, STREAMFILE * streamfile) {
static inline int read_u4h(off_t offset, STREAMFILE* sf) {
uint8_t byte = read_u8(offset, streamfile);
return (byte >> 4) & 0x0f;
}
static inline int read_s4l(off_t offset, STREAMFILE * streamfile) {
static inline int read_s4l(off_t offset, STREAMFILE* sf) {
...
}
static inline int read_u4l(off_t offset, STREAMFILE * streamfile) {
static inline int read_u4l(off_t offset, STREAMFILE* sf) {
...
}
static inline int max_s32(int32_t a, int32_t b) { return a > b ? a : b; }
@ -309,14 +309,14 @@ static inline int min_s32(int32_t a, int32_t b) { return a < b ? a : b; }
//TODO: maybe move to streamfile.c
/* guess byte endianness from a given value, return true if big endian and false if little endian */
static inline int guess_endianness16bit(off_t offset, STREAMFILE * streamfile) {
static inline int guess_endianness16bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[0x02];
if (read_streamfile(buf,offset,0x02,streamfile) != 0x02) return -1; /* ? */
if (read_streamfile(buf, offset, 0x02, sf) != 0x02) return -1; /* ? */
return (uint16_t)get_16bitLE(buf) > (uint16_t)get_16bitBE(buf) ? 1 : 0;
}
static inline int guess_endianness32bit(off_t offset, STREAMFILE * streamfile) {
static inline int guess_endianness32bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[0x04];
if (read_streamfile(buf,offset,0x04,streamfile) != 0x04) return -1; /* ? */
if (read_streamfile(buf, offset, 0x04, sf) != 0x04) return -1; /* ? */
return (uint32_t)get_32bitLE(buf) > (uint32_t)get_32bitBE(buf) ? 1 : 0;
}
@ -331,10 +331,10 @@ static inline size_t align_size_to_block(size_t value, size_t block_align) {
/* Read into dst a line delimited by CRLF (Windows) / LF (Unux) / CR (Mac) / EOF, null-terminated
* and without line feeds. Returns bytes read (including CR/LF), *not* the same as string length.
* p_line_ok is set to 1 if the complete line was read; pass NULL to ignore. */
size_t read_line(char *buf, int buf_size, off_t offset, STREAMFILE *sf, int *p_line_ok);
size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok);
/* reads a c-string (ANSI only), up to bufsize or NULL, returning size. buf is optional (works as get_string_size). */
size_t read_string(char *buf, size_t buf_size, off_t offset, STREAMFILE *sf);
size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
/* reads a UTF16 string... but actually only as ANSI (discards the upper byte) */
size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian);
size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
@ -343,31 +343,31 @@ size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE*
/* Opens a file containing decryption keys and copies to buffer.
* Tries "(name.ext)key" (per song), "(.ext)key" (per folder) keynames.
* returns size of key if found and copied */
size_t read_key_file(uint8_t *buf, size_t buf_size, STREAMFILE *sf);
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf);
/* hack to allow relative paths in various OSs */
void fix_dir_separators(char *filename);
void fix_dir_separators(char* filename);
/* Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix").
* Empty is ok to accept files without extension ("", "adx,,aix"). Returns 0 on failure */
int check_extensions(STREAMFILE *streamFile, const char * cmp_exts);
int check_extensions(STREAMFILE* sf, const char* cmp_exts);
/* chunk-style file helpers */
int find_chunk_be(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size);
int find_chunk_le(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size);
int find_chunk(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_size, int zero_size_end);
int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size);
int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size);
int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian_size, int zero_size_end);
/* find a RIFF-style chunk (with chunk_size not including id and size) */
int find_chunk_riff_le(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size);
int find_chunk_riff_be(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size);
int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size);
int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size);
/* same with chunk ids in variable endianess (so instead of "fmt " has " tmf" */
int find_chunk_riff_ve(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian);
int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian);
/* filename helpers */
void get_streamfile_name(STREAMFILE *streamFile, char * buffer, size_t size);
void get_streamfile_filename(STREAMFILE *streamFile, char * buffer, size_t size);
void get_streamfile_basename(STREAMFILE *streamFile, char * buffer, size_t size);
void get_streamfile_path(STREAMFILE *streamFile, char * buffer, size_t size);
void get_streamfile_ext(STREAMFILE *streamFile, char * filename, size_t size);
void get_streamfile_name(STREAMFILE* sf, char* buf, size_t size);
void get_streamfile_filename(STREAMFILE* sf, char* buf, size_t size);
void get_streamfile_basename(STREAMFILE* sf, char* buf, size_t size);
void get_streamfile_path(STREAMFILE* sf, char* buf, size_t size);
void get_streamfile_ext(STREAMFILE* sf, char* buf, size_t size);
void dump_streamfile(STREAMFILE *streamFile, int num);
void dump_streamfile(STREAMFILE* sf, int num);
#endif

View File

@ -11,55 +11,55 @@
/* host endian independent multi-byte integer reading */
static inline int16_t get_16bitBE(uint8_t * p) {
static inline int16_t get_16bitBE(const uint8_t* p) {
return (p[0]<<8) | (p[1]);
}
static inline int16_t get_16bitLE(uint8_t * p) {
static inline int16_t get_16bitLE(const uint8_t* p) {
return (p[0]) | (p[1]<<8);
}
static inline int32_t get_32bitBE(uint8_t * p) {
static inline int32_t get_32bitBE(const uint8_t* p) {
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | (p[3]);
}
static inline int32_t get_32bitLE(uint8_t * p) {
static inline int32_t get_32bitLE(const uint8_t* p) {
return (p[0]) | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
}
static inline int64_t get_64bitBE(uint8_t * p) {
static inline int64_t get_64bitBE(const uint8_t* p) {
return (uint64_t)(((uint64_t)p[0]<<56) | ((uint64_t)p[1]<<48) | ((uint64_t)p[2]<<40) | ((uint64_t)p[3]<<32) | ((uint64_t)p[4]<<24) | ((uint64_t)p[5]<<16) | ((uint64_t)p[6]<<8) | ((uint64_t)p[7]));
}
static inline int64_t get_64bitLE(uint8_t * p) {
static inline int64_t get_64bitLE(const uint8_t* p) {
return (uint64_t)(((uint64_t)p[0]) | ((uint64_t)p[1]<<8) | ((uint64_t)p[2]<<16) | ((uint64_t)p[3]<<24) | ((uint64_t)p[4]<<32) | ((uint64_t)p[5]<<40) | ((uint64_t)p[6]<<48) | ((uint64_t)p[7]<<56));
}
/* alias of the above */
static inline int8_t get_s8 (uint8_t *p) { return ( int8_t)p[0]; }
static inline uint8_t get_u8 (uint8_t *p) { return (uint8_t)p[0]; }
static inline int16_t get_s16le(uint8_t *p) { return ( int16_t)get_16bitLE(p); }
static inline uint16_t get_u16le(uint8_t *p) { return (uint16_t)get_16bitLE(p); }
static inline int16_t get_s16be(uint8_t *p) { return ( int16_t)get_16bitBE(p); }
static inline uint16_t get_u16be(uint8_t *p) { return (uint16_t)get_16bitBE(p); }
static inline int32_t get_s32le(uint8_t *p) { return ( int32_t)get_32bitLE(p); }
static inline uint32_t get_u32le(uint8_t *p) { return (uint32_t)get_32bitLE(p); }
static inline int32_t get_s32be(uint8_t *p) { return ( int32_t)get_32bitBE(p); }
static inline uint32_t get_u32be(uint8_t *p) { return (uint32_t)get_32bitBE(p); }
static inline int64_t get_s64be(uint8_t *p) { return ( int64_t)get_64bitLE(p); }
static inline uint64_t get_u64be(uint8_t *p) { return (uint64_t)get_64bitLE(p); }
static inline int64_t get_s64le(uint8_t *p) { return ( int64_t)get_64bitBE(p); }
static inline uint64_t get_u64le(uint8_t *p) { return (uint64_t)get_64bitBE(p); }
static inline int8_t get_s8 (const uint8_t* p) { return ( int8_t)p[0]; }
static inline uint8_t get_u8 (const uint8_t* p) { return (uint8_t)p[0]; }
static inline int16_t get_s16le(const uint8_t* p) { return ( int16_t)get_16bitLE(p); }
static inline uint16_t get_u16le(const uint8_t* p) { return (uint16_t)get_16bitLE(p); }
static inline int16_t get_s16be(const uint8_t* p) { return ( int16_t)get_16bitBE(p); }
static inline uint16_t get_u16be(const uint8_t* p) { return (uint16_t)get_16bitBE(p); }
static inline int32_t get_s32le(const uint8_t* p) { return ( int32_t)get_32bitLE(p); }
static inline uint32_t get_u32le(const uint8_t* p) { return (uint32_t)get_32bitLE(p); }
static inline int32_t get_s32be(const uint8_t* p) { return ( int32_t)get_32bitBE(p); }
static inline uint32_t get_u32be(const uint8_t* p) { return (uint32_t)get_32bitBE(p); }
static inline int64_t get_s64le(const uint8_t* p) { return ( int64_t)get_64bitLE(p); }
static inline uint64_t get_u64le(const uint8_t* p) { return (uint64_t)get_64bitLE(p); }
static inline int64_t get_s64be(const uint8_t* p) { return ( int64_t)get_64bitBE(p); }
static inline uint64_t get_u64be(const uint8_t* p) { return (uint64_t)get_64bitBE(p); }
void put_8bit(uint8_t * buf, int8_t i);
void put_8bit(uint8_t* buf, int8_t i);
void put_16bitLE(uint8_t * buf, int16_t i);
void put_16bitLE(uint8_t* buf, int16_t i);
void put_32bitLE(uint8_t * buf, int32_t i);
void put_32bitLE(uint8_t* buf, int32_t i);
void put_16bitBE(uint8_t * buf, int16_t i);
void put_16bitBE(uint8_t* buf, int16_t i);
void put_32bitBE(uint8_t * buf, int32_t i);
void put_32bitBE(uint8_t* buf, int32_t i);
/* alias of the above */ //TODO: improve
#define put_u8 put_8bit

File diff suppressed because it is too large Load Diff

View File

@ -349,7 +349,7 @@ typedef enum {
meta_PS2_RXWS, /* Sony games (Genji, Okage Shadow King, Arc The Lad Twilight of Spirits) */
meta_RAW_INT,
meta_PS2_EXST, /* Shadow of Colossus EXST */
meta_PS2_SVAG, /* Konami SVAG */
meta_SVAG_KCET,
meta_PS_HEADERLESS, /* headerless PS-ADPCM */
meta_PS2_MIB_MIH, /* MIB File + MIH Header*/
meta_PS2_MIC, /* KOEI MIC File */
@ -587,7 +587,7 @@ typedef enum {
meta_MCA, /* Capcom MCA "MADP" */
meta_XB3D_ADX, /* Xenoblade Chronicles 3D ADX */
meta_HCA, /* CRI HCA */
meta_PS2_SVAG_SNK, /* SNK PS2 SVAG */
meta_SVAG_SNK,
meta_PS2_VDS_VDM, /* Graffiti Kingdom */
meta_FFMPEG, /* any file supported by FFmpeg */
meta_X360_CXS, /* Eternal Sonata (Xbox 360) */
@ -734,6 +734,7 @@ typedef enum {
meta_KTSR,
meta_KAT,
meta_PCM_SUCCESS,
meta_ADP_KONAMI,
} meta_t;
/* standard WAVEFORMATEXTENSIBLE speaker positions */
@ -792,9 +793,10 @@ typedef struct {
int ignore_loop;
} play_config_t;
/* info for a single vgmstream channel */
typedef struct {
STREAMFILE * streamfile; /* file used by this channel */
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 */
@ -824,8 +826,8 @@ typedef struct {
int32_t adpcm_history4_32;
};
double adpcm_history1_double;
double adpcm_history2_double;
//double adpcm_history1_double;
//double adpcm_history2_double;
int adpcm_step_index; /* for IMA */
int adpcm_scale; /* for MS ADPCM */
@ -841,6 +843,7 @@ typedef struct {
} VGMSTREAMCHANNEL;
/* main vgmstream info */
typedef struct {
/* basic config */
@ -875,31 +878,35 @@ typedef struct {
/* other config */
int allow_dual_stereo; /* search for dual stereo (file_L.ext + file_R.ext = single stereo file) */
/* config requests, players must read and honor these values
* (ideally internally would work as a player, but for now player must do it manually) */
play_config_t config;
/* play state */
int loop_count; /* counter of complete loops (1=looped once) */
int loop_target; /* max loops before continuing with the stream end (loops forever if not set) */
/* layout/block state */
size_t full_block_size; /* actual data size of an entire block (ie. may be fixed, include padding/headers, etc) */
int32_t current_sample; /* number of samples we've passed (for loop detection) */
int32_t current_sample; /* sample point within the file (for loop detection) */
int32_t samples_into_block; /* number of samples into the current block/interleave/segment/etc */
off_t current_block_offset; /* start of this block (offset of block header) */
size_t current_block_size; /* size in usable bytes of the block we're in now (used to calculate num_samples per block) */
int32_t current_block_samples; /* size in samples of the block we're in now (used over current_block_size if possible) */
int32_t current_block_samples; /* size in samples of the block we're in now (used over current_block_size if possible) */
off_t next_block_offset; /* offset of header of the next block */
/* layout/block loop state */
int32_t loop_sample; /* saved from current_sample (same as loop_start_sample, but more state-like) */
/* loop state (saved when loop is hit to restore later) */
int32_t loop_current_sample; /* saved from current_sample (same as loop_start_sample, but more state-like) */
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 */
int32_t loop_block_samples; /* saved from current_block_samples */
int32_t loop_block_samples; /* saved from current_block_samples */
off_t loop_next_block_offset; /* saved from next_block_offset */
int hit_loop; /* save config when loop is hit, but first time only */
/* loop state */
int hit_loop; /* have we seen the loop yet? */
int loop_count; /* counter of complete loops (1=looped once) */
int loop_target; /* max loops before continuing with the stream end (loops forever if not set) */
/* decoder config/state */
int codec_endian; /* little/big endian marker; name is left vague but usually means big endian */
@ -908,248 +915,30 @@ typedef struct {
/* main state */
VGMSTREAMCHANNEL * ch; /* array of channels */
VGMSTREAMCHANNEL * start_ch; /* shallow copy of channels as they were at the beginning of the stream (for resets) */
VGMSTREAMCHANNEL * loop_ch; /* shallow copy of channels as they were at the loop point (for loops) */
VGMSTREAMCHANNEL* ch; /* array of channels */
VGMSTREAMCHANNEL* start_ch; /* shallow copy of channels as they were at the beginning of the stream (for resets) */
VGMSTREAMCHANNEL* loop_ch; /* shallow copy of channels as they were at the loop point (for loops) */
void* start_vgmstream; /* shallow copy of the VGMSTREAM as it was at the beginning of the stream (for resets) */
void * mixing_data; /* state for mixing effects */
void* mixing_data; /* state for mixing effects */
/* Optional data the codec needs for the whole stream. This is for codecs too
* different from vgmstream's structure to be reasonably shoehorned.
* 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;
void* codec_data;
/* Same, for special layouts. layout_data + codec_data may exist at the same time. */
void * layout_data;
void* layout_data;
} VGMSTREAM;
#ifdef VGM_USE_VORBIS
/* standard Ogg Vorbis */
typedef struct {
STREAMFILE *streamfile;
ogg_int64_t start; /* file offset where the Ogg starts */
ogg_int64_t offset; /* virtual offset, from 0 to size */
ogg_int64_t size; /* virtual size of the Ogg */
/* decryption setup */
void (*decryption_callback)(void *ptr, size_t size, size_t nmemb, void *datasource);
uint8_t scd_xor;
off_t scd_xor_length;
uint32_t xor_value;
} ogg_vorbis_io;
typedef struct ogg_vorbis_codec_data ogg_vorbis_codec_data;
/* custom Vorbis modes */
typedef enum {
VORBIS_FSB, /* FMOD FSB: simplified/external setup packets, custom packet headers */
VORBIS_WWISE, /* Wwise WEM: many variations (custom setup, headers and data) */
VORBIS_OGL, /* Shin'en OGL: custom packet headers */
VORBIS_SK, /* Silicon Knights AUD: "OggS" replaced by "SK" */
VORBIS_VID1, /* Neversoft VID1: custom packet blocks/headers */
} vorbis_custom_t;
/* config for Wwise Vorbis (3 types for flexibility though not all combinations exist) */
typedef enum { WWV_HEADER_TRIAD, WWV_FULL_SETUP, WWV_INLINE_CODEBOOKS, WWV_EXTERNAL_CODEBOOKS, WWV_AOTUV603_CODEBOOKS } wwise_setup_t;
typedef enum { WWV_TYPE_8, WWV_TYPE_6, WWV_TYPE_2 } wwise_header_t;
typedef enum { WWV_STANDARD, WWV_MODIFIED } wwise_packet_t;
typedef struct {
/* to reconstruct init packets */
int channels;
int sample_rate;
int blocksize_0_exp;
int blocksize_1_exp;
uint32_t setup_id; /* external setup */
int big_endian; /* flag */
/* Wwise Vorbis config */
wwise_setup_t setup_type;
wwise_header_t header_type;
wwise_packet_t packet_type;
/* output (kinda ugly here but to simplify) */
off_t data_start_offset;
} vorbis_custom_config;
/* custom Vorbis without Ogg layer */
typedef struct {
vorbis_info vi; /* stream settings */
vorbis_comment vc; /* stream comments */
vorbis_dsp_state vd; /* decoder global state */
vorbis_block vb; /* decoder local state */
ogg_packet op; /* fake packet for internal use */
uint8_t * buffer; /* internal raw data buffer */
size_t buffer_size;
size_t samples_to_discard; /* for looping purposes */
int samples_full; /* flag, samples available in vorbis buffers */
vorbis_custom_t type; /* Vorbis subtype */
vorbis_custom_config config; /* config depending on the mode */
/* Wwise Vorbis: saved data to reconstruct modified packets */
uint8_t mode_blockflag[64+1]; /* max 6b+1; flags 'n stuff */
int mode_bits; /* bits to store mode_number */
uint8_t prev_blockflag; /* blockflag in the last decoded packet */
/* Ogg-style Vorbis: packet within a page */
int current_packet;
/* reference for page/blocks */
off_t block_offset;
size_t block_size;
int prev_block_samples; /* count for optimization */
} vorbis_custom_codec_data;
#endif
#ifdef VGM_USE_MPEG
/* Custom MPEG modes, mostly differing in the data layout */
typedef enum {
MPEG_STANDARD, /* 1 stream */
MPEG_AHX, /* 1 stream with false frame headers */
MPEG_XVAG, /* N streams of fixed interleave (frame-aligned, several data-frames of fixed size) */
MPEG_FSB, /* N streams of 1 data-frame+padding (=interleave) */
MPEG_P3D, /* N streams of fixed interleave (not frame-aligned) */
MPEG_SCD, /* N streams of fixed interleave (not frame-aligned) */
MPEG_EA, /* 1 stream (maybe N streams in absolute offsets?) */
MPEG_EAL31, /* EALayer3 v1 (SCHl), custom frames with v1 header */
MPEG_EAL31b, /* EALayer3 v1 (SNS), custom frames with v1 header + minor changes */
MPEG_EAL32P, /* EALayer3 v2 "PCM", custom frames with v2 header + bigger PCM blocks? */
MPEG_EAL32S, /* EALayer3 v2 "Spike", custom frames with v2 header + smaller PCM blocks? */
MPEG_LYN, /* N streams of fixed interleave */
MPEG_AWC, /* N streams in block layout (music) or absolute offsets (sfx) */
MPEG_EAMP3 /* custom frame header + MPEG frame + PCM blocks */
} mpeg_custom_t;
/* config for the above modes */
typedef struct {
int channels; /* max channels */
int fsb_padding; /* fsb padding mode */
int chunk_size; /* size of a data portion */
int data_size; /* playable size */
int interleave; /* size of stream interleave */
int encryption; /* encryption mode */
int big_endian;
int skip_samples;
/* for AHX */
int cri_type;
uint16_t cri_key1;
uint16_t cri_key2;
uint16_t cri_key3;
} mpeg_custom_config;
/* represents a single MPEG stream */
typedef struct {
/* per stream as sometimes mpg123 must be fed in passes if data is big enough (ex. EALayer3 multichannel) */
uint8_t *buffer; /* raw data buffer */
size_t buffer_size;
size_t bytes_in_buffer;
int buffer_full; /* raw buffer has been filled */
int buffer_used; /* raw buffer has been fed to the decoder */
mpg123_handle *m; /* MPEG decoder */
uint8_t *output_buffer; /* decoded samples from this stream (in bytes for mpg123) */
size_t output_buffer_size;
size_t samples_filled; /* data in the buffer (in samples) */
size_t samples_used; /* data extracted from the buffer */
size_t current_size_count; /* data read (if the parser needs to know) */
size_t current_size_target; /* max data, until something happens */
size_t decode_to_discard; /* discard from this stream only (for EALayer3 or AWC) */
int channels_per_frame; /* for rare cases that streams don't share this */
} mpeg_custom_stream;
typedef struct {
/* regular/single MPEG internals */
uint8_t *buffer; /* raw data buffer */
size_t buffer_size;
size_t bytes_in_buffer;
int buffer_full; /* raw buffer has been filled */
int buffer_used; /* raw buffer has been fed to the decoder */
mpg123_handle *m; /* MPEG decoder */
struct mpg123_frameinfo mi; /* start info, so it's available even when resetting */
/* for internal use */
int channels_per_frame;
int samples_per_frame;
/* for some calcs */
int bitrate_per_frame;
int sample_rate_per_frame;
/* custom MPEG internals */
int custom; /* flag */
mpeg_custom_t type; /* mpeg subtype */
mpeg_custom_config config; /* config depending on the mode */
size_t default_buffer_size;
mpeg_custom_stream **streams; /* array of MPEG streams (ex. 2ch+2ch) */
size_t streams_size;
size_t skip_samples; /* base encoder delay */
size_t samples_to_discard; /* for custom mpeg looping */
} mpeg_codec_data;
#endif
#ifdef VGM_USE_G7221
typedef struct g7221_codec_data g7221_codec_data;
#endif
#ifdef VGM_USE_G719
typedef struct {
sample_t buffer[960];
void *handle;
} g719_codec_data;
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
typedef struct {
sample_t *buffer;
int channels;
int samples_discard;
void *handle;
} maiatrac3plus_codec_data;
#endif
#ifdef VGM_USE_ATRAC9
/* ATRAC9 config */
typedef struct {
int channels; /* to detect weird multichannel */
uint32_t config_data; /* ATRAC9 config header */
int encoder_delay; /* initial samples to discard */
} atrac9_config;
typedef struct atrac9_codec_data atrac9_codec_data;
#endif
#ifdef VGM_USE_CELT
typedef enum { CELT_0_06_1,CELT_0_11_0} celt_lib_t;
typedef struct celt_codec_data celt_codec_data;
#endif
/* libacm interface */
typedef struct {
STREAMFILE *streamfile;
void *handle;
void *io_config;
} acm_codec_data;
/* for files made of "continuous" segments, one per section of a song (using a complete sub-VGMSTREAM) */
typedef struct {
int segment_count;
VGMSTREAM **segments;
VGMSTREAM** segments;
int current_segment;
sample_t *buffer;
sample_t* buffer;
int input_channels; /* internal buffer channels */
int output_channels; /* resulting channels (after mixing, if applied) */
} segmented_layout_data;
@ -1157,39 +946,26 @@ typedef struct {
/* for files made of "parallel" layers, one per group of channels (using a complete sub-VGMSTREAM) */
typedef struct {
int layer_count;
VGMSTREAM **layers;
sample_t *buffer;
VGMSTREAM** layers;
sample_t* buffer;
int input_channels; /* internal buffer channels */
int output_channels; /* resulting channels (after mixing, if applied) */
} layered_layout_data;
/* for compressed NWA */
/* libacm interface */
typedef struct {
NWAData *nwa;
} nwa_codec_data;
typedef struct relic_codec_data relic_codec_data;
typedef struct {
STREAMFILE *streamfile;
clHCA_stInfo info;
signed short *sample_buffer;
size_t samples_filled;
size_t samples_consumed;
size_t samples_to_discard;
void* data_buffer;
unsigned int current_block;
STREAMFILE* streamfile;
void* handle;
} hca_codec_data;
void* io_config;
} acm_codec_data;
#ifdef VGM_USE_FFMPEG
typedef struct {
/*** IO internals ***/
STREAMFILE *streamfile;
STREAMFILE* streamfile;
uint64_t start; // absolute start within the streamfile
uint64_t offset; // absolute offset within the streamfile
@ -1245,7 +1021,7 @@ typedef struct {
#ifdef VGM_USE_MP4V2
typedef struct {
STREAMFILE *streamfile;
STREAMFILE* streamfile;
uint64_t start;
uint64_t offset;
uint64_t size;
@ -1263,87 +1039,44 @@ typedef struct {
INT_PCM sample_buffer[( (6) * (2048)*4 )];
} mp4_aac_codec_data;
#endif
#endif
#endif //VGM_USE_MP4V2
typedef struct ubi_adpcm_codec_data ubi_adpcm_codec_data;
typedef struct ea_mt_codec_data ea_mt_codec_data;
#if 0
//possible future public/opaque API
/* define standard C param call and name mangling (to avoid __stdcall / .defs) */
#define VGMSTREAM_CALL __cdecl //needed?
/* define external function types (during compilation) */
#if defined(VGMSTREAM_EXPORT)
#define VGMSTREAM_API __declspec(dllexport) /* when exporting/creating vgmstream DLL */
#elif defined(VGMSTREAM_IMPORT)
#define VGMSTREAM_API __declspec(dllimport) /* when importing/linking vgmstream DLL */
#else
#define VGMSTREAM_API /* nothing, internal/default */
#endif
//VGMSTREAM_API void VGMSTREAM_CALL vgmstream_function(void);
//info for opaque VGMSTREAM
typedef struct {
const int channels;
const int sample_rate;
const int num_samples;
const int loop_start_sample;
const int loop_end_sample;
const int loop_flag;
const int num_streams;
const int current_sample;
const int average_bitrate;
} VGMSTREAM_INFO;
void vgmstream_get_info(VGMSTREAM* vgmstream, VGMSTREAM_INFO *vgmstream_info);
//or maybe
enum vgmstream_value_t { VGMSTREAM_CHANNELS, VGMSTREAM_CURRENT_SAMPLE, ... };
int vgmstream_get_info(VGMSTREAM* vgmstream, vgmstream_value_t type);
// or
int vgmstream_get_current_sample(VGMSTREAM* vgmstream);
#endif
/* -------------------------------------------------------------------------*/
/* vgmstream "public" API */
/* -------------------------------------------------------------------------*/
/* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */
VGMSTREAM * init_vgmstream(const char * const filename);
VGMSTREAM* init_vgmstream(const char* const filename);
/* init with custom IO via streamfile */
VGMSTREAM * init_vgmstream_from_STREAMFILE(STREAMFILE *streamFile);
VGMSTREAM* init_vgmstream_from_STREAMFILE(STREAMFILE* sf);
/* reset a VGMSTREAM to start of stream */
void reset_vgmstream(VGMSTREAM * vgmstream);
void reset_vgmstream(VGMSTREAM* vgmstream);
/* close an open vgmstream */
void close_vgmstream(VGMSTREAM * vgmstream);
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);
int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM* vgmstream);
/* Decode data into sample buffer */
void render_vgmstream(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream(sample_t* buffer, int32_t sample_count, 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);
void describe_vgmstream(VGMSTREAM* vgmstream, char* desc, int length);
/* Return the average bitrate in bps of all unique files contained within this stream. */
int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream);
int get_vgmstream_average_bitrate(VGMSTREAM* vgmstream);
/* List supported formats and return elements in the list, for plugins that need to know.
* The list disables some common formats that may conflict (.wav, .ogg, etc). */
const char ** vgmstream_get_formats(size_t * size);
const char** vgmstream_get_formats(size_t* size);
/* same, but for common-but-disabled formats in the above list. */
const char ** vgmstream_get_common_formats(size_t * size);
const char** vgmstream_get_common_formats(size_t* size);
/* Force enable/disable internal looping. Should be done before playing anything (or after reset),
* and not all codecs support arbitrary loop values ATM. */
@ -1363,34 +1096,34 @@ int vgmstream_is_virtual_filename(const char* filename);
VGMSTREAM * allocate_vgmstream(int channel_count, int looped);
/* Prepare the VGMSTREAM's initial state once parsed and ready, but before playing. */
void setup_vgmstream(VGMSTREAM * vgmstream);
void setup_vgmstream(VGMSTREAM* vgmstream);
/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */
int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream);
int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream);
/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */
int get_vgmstream_frame_size(VGMSTREAM * vgmstream);
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);
int get_vgmstream_samples_per_shortframe(VGMSTREAM* vgmstream);
int get_vgmstream_shortframe_size(VGMSTREAM* vgmstream);
/* Decode samples into the buffer. Assume that we have written samples_written into the
* buffer already, and we have samples_to_do consecutive samples ahead of us. */
void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample_t * buffer);
void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_do, sample_t* 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);
int get_vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream);
/* Detect loop start and save values, or detect loop end and restore (loop back). Returns 1 if loop was done. */
int vgmstream_do_loop(VGMSTREAM * vgmstream);
int vgmstream_do_loop(VGMSTREAM* vgmstream);
/* Open the stream for reading at offset (taking into account layouts, channels and so on).
* Returns 0 on failure */
int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t start_offset);
int vgmstream_open_stream_bf(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t start_offset, int force_multibuffer);
int vgmstream_open_stream(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_offset);
int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_offset, int force_multibuffer);
/* Get description info */
void get_vgmstream_coding_description(VGMSTREAM *vgmstream, char *out, size_t out_size);
void get_vgmstream_layout_description(VGMSTREAM *vgmstream, char *out, size_t out_size);
void get_vgmstream_meta_description(VGMSTREAM *vgmstream, char *out, size_t out_size);
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size);
void get_vgmstream_layout_description(VGMSTREAM* vgmstream, char* out, size_t out_size);
void get_vgmstream_meta_description(VGMSTREAM* vgmstream, char* out, size_t out_size);
#endif