mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-31 12:23:44 +01:00
commit
41914bc09c
16
README.md
16
README.md
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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*/
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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_ */
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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" />
|
||||
|
@ -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
51
src/meta/adp_konami.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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*/
|
||||
|
@ -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 */
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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];
|
||||
|
||||
|
138
src/meta/nwa.c
138
src/meta/nwa.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
46
src/meta/svag_snk.c
Normal 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;
|
||||
}
|
@ -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 */
|
||||
|
@ -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) */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
180
src/streamfile.h
180
src/streamfile.h
@ -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
|
||||
|
50
src/util.h
50
src/util.h
@ -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
|
||||
|
757
src/vgmstream.c
757
src/vgmstream.c
File diff suppressed because it is too large
Load Diff
395
src/vgmstream.h
395
src/vgmstream.h
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user