mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-13 18:20:50 +01:00
commit
e14eb7eecc
@ -26,7 +26,7 @@ CODING_OBJS=coding/adx_decoder.o \
|
||||
coding/g719_decoder.o \
|
||||
coding/hca_decoder.o \
|
||||
coding/ffmpeg_decoder.o \
|
||||
coding/ffmpeg_decoder_utils.o \
|
||||
coding/coding_utils.o \
|
||||
coding/fsb_vorbis_decoder.o \
|
||||
coding/wwise_vorbis_decoder.o \
|
||||
coding/wwise_vorbis_utils.o
|
||||
@ -64,7 +64,7 @@ LAYOUT_OBJS=layout/ast_blocked.o \
|
||||
layout/ps2_strlr_blocked.o \
|
||||
layout/scd_int_layout.o
|
||||
|
||||
META_OBJS=meta/adx_header.o \
|
||||
META_OBJS=meta/adx.o \
|
||||
meta/afc_header.o \
|
||||
meta/agsc.o \
|
||||
meta/ast.o \
|
||||
|
@ -176,22 +176,22 @@ void decode_mp4_aac(mp4_aac_codec_data * data, sample * outbuf, int32_t samples_
|
||||
void decode_at3plus(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
/* ffmpeg_decoder */
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
void decode_ffmpeg(VGMSTREAM *stream, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
void reset_ffmpeg(VGMSTREAM *vgmstream);
|
||||
void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||
|
||||
void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples);
|
||||
#endif
|
||||
|
||||
/* ffmpeg_decoder_utils */
|
||||
/* coding_utils */
|
||||
int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, size_t chunk_size, uint16_t codec);
|
||||
int ffmpeg_make_riff_atrac3(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int joint_stereo, int encoder_delay);
|
||||
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(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_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);
|
||||
|
||||
@ -215,9 +215,9 @@ typedef struct {
|
||||
int32_t skip_samples;
|
||||
int32_t loop_start_sample;
|
||||
int32_t loop_end_sample;
|
||||
} xma_sample_data; /* ms_sample_data */
|
||||
void xma_get_samples(xma_sample_data * msd, STREAMFILE *streamFile);
|
||||
void wmapro_get_samples(xma_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags);
|
||||
} 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 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 * num_samples, int32_t * loop_start_sample, int32_t * loop_end_sample, int be);
|
||||
@ -226,6 +226,5 @@ void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * cha
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /*_CODING_H*/
|
||||
|
@ -2,7 +2,14 @@
|
||||
#include "math.h"
|
||||
#include "../vgmstream.h"
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
|
||||
/**
|
||||
* Various utils for formats that aren't handled their own decoder or meta
|
||||
*
|
||||
* ffmpeg_make_riff_* utils don't depend on FFmpeg, but rather, they make headers that FFmpeg
|
||||
* can use (it doesn't understand all valid RIFF headers, nor the utils make 100% correct headers).
|
||||
*/
|
||||
|
||||
|
||||
/* ******************************************** */
|
||||
/* INTERNAL UTILS */
|
||||
@ -254,7 +261,7 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s
|
||||
|
||||
/* Makes a XMA1/2 RIFF header for FFmpeg using a "fmt " chunk (XMAWAVEFORMAT or XMA2WAVEFORMATEX) as a base:
|
||||
* Useful to preserve the stream layout */
|
||||
int ffmpeg_make_riff_xma_from_fmt(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_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) {
|
||||
size_t riff_size = 4+4+ 4 + 4+4+fmt_size + 4+4;
|
||||
uint8_t chunk[0x100];
|
||||
|
||||
@ -425,7 +432,7 @@ fail:
|
||||
* The stream is made of packets, each containing N small frames of X samples. Frames are further divided into subframes.
|
||||
* XMA1/XMA2/WMAPRO only differ in the packet headers.
|
||||
*/
|
||||
static void ms_audio_get_samples(xma_sample_data * msd, STREAMFILE *streamFile, int bytes_per_packet, int samples_per_frame, int samples_per_subframe, int bits_frame_size) {
|
||||
static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int bytes_per_packet, int samples_per_frame, int samples_per_subframe, int bits_frame_size) {
|
||||
int frames = 0, samples = 0, loop_start_frame = 0, loop_end_frame = 0, skip_packets;
|
||||
#if XMA_CHECK_SKIPS
|
||||
int start_skip = 0, end_skip = 0, first_start_skip = 0, last_end_skip = 0;
|
||||
@ -619,14 +626,14 @@ static void ms_audio_get_samples(xma_sample_data * msd, STREAMFILE *streamFile,
|
||||
}
|
||||
}
|
||||
|
||||
void xma_get_samples(xma_sample_data * msd, STREAMFILE *streamFile) {
|
||||
void xma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile) {
|
||||
const int bytes_per_packet = 2048;
|
||||
const int samples_per_frame = 512;
|
||||
const int samples_per_subframe = 128;
|
||||
|
||||
ms_audio_get_samples(msd, streamFile, bytes_per_packet, samples_per_frame, samples_per_subframe, 15);
|
||||
}
|
||||
void wmapro_get_samples(xma_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags) {
|
||||
void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags) {
|
||||
int bytes_per_packet = block_align;
|
||||
int samples_per_frame = 0;
|
||||
int samples_per_subframe = 0;
|
||||
@ -768,5 +775,3 @@ size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align) {
|
||||
* so (full_block_align / channels) DOESN'T give the size of a single channel (common in ATRAC3plus) */
|
||||
return (bytes / full_block_align) * 2048;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,12 +1,11 @@
|
||||
#include "coding.h"
|
||||
#include <math.h>
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
#include <vorbis/codec.h>
|
||||
|
||||
#define FSB_VORBIS_ON 1 //todo remove once battle-tested
|
||||
#define FSB_VORBIS_USE_PRECOMPILED_FVS 1 /* if enabled vgmstream weights ~600kb more but doesn't need external .fvs packets */
|
||||
|
||||
#if FSB_VORBIS_ON
|
||||
#if FSB_VORBIS_USE_PRECOMPILED_FVS
|
||||
#include "fsb_vorbis_data.h"
|
||||
#endif
|
||||
@ -21,7 +20,6 @@ static int vorbis_make_header_setup(uint8_t * buf, size_t bufsize, uint32_t setu
|
||||
static int load_fvs_file_single(uint8_t * buf, size_t bufsize, uint32_t setup_id, STREAMFILE *streamFile);
|
||||
static int load_fvs_file_multi(uint8_t * buf, size_t bufsize, uint32_t setup_id, STREAMFILE *streamFile);
|
||||
static int load_fvs_array(uint8_t * buf, size_t bufsize, uint32_t setup_id, STREAMFILE *streamFile);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Inits a raw FSB vorbis stream.
|
||||
@ -37,7 +35,6 @@ static int load_fvs_array(uint8_t * buf, size_t bufsize, uint32_t setup_id, STRE
|
||||
* Also from the official docs (https://www.xiph.org/vorbis/doc/libvorbis/overview.html).
|
||||
*/
|
||||
vorbis_codec_data * init_fsb_vorbis_codec_data(STREAMFILE *streamfile, off_t start_offset, int channels, int sample_rate, uint32_t setup_id) {
|
||||
#if FSB_VORBIS_ON
|
||||
vorbis_codec_data * data = NULL;
|
||||
|
||||
/* init stuff */
|
||||
@ -80,7 +77,6 @@ vorbis_codec_data * init_fsb_vorbis_codec_data(STREAMFILE *streamfile, off_t sta
|
||||
|
||||
fail:
|
||||
free_fsb_vorbis(data);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -88,7 +84,6 @@ fail:
|
||||
* Decodes raw FSB vorbis
|
||||
*/
|
||||
void decode_fsb_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels) {
|
||||
#if FSB_VORBIS_ON
|
||||
VGMSTREAMCHANNEL *stream = &vgmstream->ch[0];
|
||||
vorbis_codec_data * data = vgmstream->codec_data;
|
||||
size_t stream_size = get_streamfile_size(stream->streamfile);
|
||||
@ -177,10 +172,8 @@ void decode_fsb_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_t
|
||||
decode_fail:
|
||||
/* on error just put some 0 samples */
|
||||
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if FSB_VORBIS_ON
|
||||
|
||||
static void pcm_convert_float_to_16(vorbis_codec_data * data, sample * outbuf, int samples_to_do, float ** pcm) {
|
||||
/* mostly from Xiph's decoder_example.c */
|
||||
@ -391,12 +384,9 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* ********************************************** */
|
||||
|
||||
void free_fsb_vorbis(vorbis_codec_data * data) {
|
||||
#if FSB_VORBIS_ON
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
@ -407,22 +397,18 @@ void free_fsb_vorbis(vorbis_codec_data * data) {
|
||||
|
||||
free(data->buffer);
|
||||
free(data);
|
||||
#endif
|
||||
}
|
||||
|
||||
void reset_fsb_vorbis(VGMSTREAM *vgmstream) {
|
||||
#if FSB_VORBIS_ON
|
||||
vorbis_codec_data *data = vgmstream->codec_data;
|
||||
|
||||
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
||||
* To avoid having to parse different formats we'll just discard until the expected sample */
|
||||
vorbis_synthesis_restart(&data->vd);
|
||||
data->samples_to_discard = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void seek_fsb_vorbis(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||
#if FSB_VORBIS_ON
|
||||
vorbis_codec_data *data = vgmstream->codec_data;
|
||||
|
||||
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
||||
@ -431,7 +417,6 @@ void seek_fsb_vorbis(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||
data->samples_to_discard = num_sample;
|
||||
if (vgmstream->loop_ch)
|
||||
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,10 +1,10 @@
|
||||
#include "coding.h"
|
||||
#include <math.h>
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
#include <vorbis/codec.h>
|
||||
|
||||
#define WWISE_VORBIS_ON 1 //todo remove once battle-tested
|
||||
#if WWISE_VORBIS_ON
|
||||
#define WWISE_VORBIS_ON 0 //todo remove once battle-tested
|
||||
#include "wwise_vorbis_utils.h"
|
||||
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
static void pcm_convert_float_to_16(vorbis_codec_data * data, sample * outbuf, int samples_to_do, float ** pcm);
|
||||
static int vorbis_make_header_identification(uint8_t * buf, size_t bufsize, int channels, int sample_rate, int blocksize_short, int blocksize_long);
|
||||
static int vorbis_make_header_comment(uint8_t * buf, size_t bufsize);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Inits a raw Wwise vorbis stream.
|
||||
@ -31,7 +30,6 @@ static int vorbis_make_header_comment(uint8_t * buf, size_t bufsize);
|
||||
*/
|
||||
vorbis_codec_data * init_wwise_vorbis_codec_data(STREAMFILE *streamFile, off_t start_offset, int channels, int sample_rate, int blocksize_0_exp, int blocksize_1_exp,
|
||||
wwise_setup_type setup_type, wwise_header_type header_type, wwise_packet_type packet_type, int big_endian) {
|
||||
#if WWISE_VORBIS_ON
|
||||
vorbis_codec_data * data = NULL;
|
||||
size_t header_size, packet_size;
|
||||
|
||||
@ -62,20 +60,21 @@ vorbis_codec_data * init_wwise_vorbis_codec_data(STREAMFILE *streamFile, off_t s
|
||||
/* normal identificacion packet */
|
||||
header_size = wwise_vorbis_get_header(streamFile, offset, data->header_type, (int*)&data->op.granulepos, &packet_size, big_endian);
|
||||
if (!header_size || packet_size > data->buffer_size) goto fail;
|
||||
if (read_streamfile(data->buffer,offset+header_size,packet_size, streamFile)!=packet_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer,offset+header_size,packet_size, streamFile);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse identification header */
|
||||
offset += header_size + packet_size;
|
||||
|
||||
/* normal comment packet */
|
||||
header_size = wwise_vorbis_get_header(streamFile, offset, data->header_type, (int*)&data->op.granulepos, &packet_size, big_endian);
|
||||
if (!header_size || packet_size > data->buffer_size) goto fail;
|
||||
if (read_streamfile(data->buffer,offset+header_size,packet_size, streamFile)!=packet_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer,offset+header_size,packet_size, streamFile);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0 ) goto fail; /* parse comment header */
|
||||
offset += header_size + packet_size;
|
||||
|
||||
/* modified setup packet */ //todo doesn't seem needed, may be copied as -is
|
||||
/* normal setup packet */
|
||||
header_size = wwise_vorbis_get_header(streamFile, offset, data->header_type, (int*)&data->op.granulepos, &packet_size, big_endian);
|
||||
data->op.bytes = wwise_vorbis_rebuild_setup(data->buffer, data->buffer_size, streamFile, offset, data, big_endian, channels);
|
||||
if (!header_size || packet_size > data->buffer_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer,offset+header_size,packet_size, streamFile);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse setup header */
|
||||
offset += header_size + packet_size;
|
||||
}
|
||||
@ -110,7 +109,6 @@ vorbis_codec_data * init_wwise_vorbis_codec_data(STREAMFILE *streamFile, off_t s
|
||||
|
||||
fail:
|
||||
free_wwise_vorbis(data);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -118,7 +116,6 @@ fail:
|
||||
* Decodes raw Wwise Vorbis
|
||||
*/
|
||||
void decode_wwise_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels) {
|
||||
#if WWISE_VORBIS_ON
|
||||
VGMSTREAMCHANNEL *stream = &vgmstream->ch[0];
|
||||
vorbis_codec_data * data = vgmstream->codec_data;
|
||||
size_t stream_size = get_streamfile_size(stream->streamfile);
|
||||
@ -210,10 +207,9 @@ void decode_wwise_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples
|
||||
decode_fail:
|
||||
/* on error just put some 0 samples */
|
||||
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if WWISE_VORBIS_ON
|
||||
/* *************************************************** */
|
||||
|
||||
static void pcm_convert_float_to_16(vorbis_codec_data * data, sample * outbuf, int samples_to_do, float ** pcm) {
|
||||
/* mostly from Xiph's decoder_example.c */
|
||||
@ -235,8 +231,6 @@ static void pcm_convert_float_to_16(vorbis_codec_data * data, sample * outbuf, i
|
||||
}
|
||||
}
|
||||
|
||||
/* *************************************************** */
|
||||
|
||||
static int vorbis_make_header_identification(uint8_t * buf, size_t bufsize, int channels, int sample_rate, int blocksize_0_exp, int blocksize_1_exp) {
|
||||
int bytes = 0x1e;
|
||||
uint8_t blocksizes;
|
||||
@ -274,12 +268,9 @@ static int vorbis_make_header_comment(uint8_t * buf, size_t bufsize) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* *************************************** */
|
||||
|
||||
void free_wwise_vorbis(vorbis_codec_data * data) {
|
||||
#if WWISE_VORBIS_ON
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
@ -290,22 +281,18 @@ void free_wwise_vorbis(vorbis_codec_data * data) {
|
||||
|
||||
free(data->buffer);
|
||||
free(data);
|
||||
#endif
|
||||
}
|
||||
|
||||
void reset_wwise_vorbis(VGMSTREAM *vgmstream) {
|
||||
#if WWISE_VORBIS_ON
|
||||
vorbis_codec_data *data = vgmstream->codec_data;
|
||||
|
||||
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
||||
* To avoid having to parse different formats we'll just discard until the expected sample */
|
||||
vorbis_synthesis_restart(&data->vd);
|
||||
data->samples_to_discard = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void seek_wwise_vorbis(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||
#if WWISE_VORBIS_ON
|
||||
vorbis_codec_data *data = vgmstream->codec_data;
|
||||
|
||||
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
||||
@ -314,7 +301,6 @@ void seek_wwise_vorbis(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||
data->samples_to_discard = num_sample;
|
||||
if (vgmstream->loop_ch) /* this func is only using for looping though */
|
||||
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -20,7 +20,6 @@ typedef struct {
|
||||
} ww_stream;
|
||||
|
||||
static int generate_vorbis_packet(ww_stream * ow, ww_stream * iw, STREAMFILE *streamFile, off_t offset, vorbis_codec_data * data, int big_endian);
|
||||
static int generate_vorbis_setup_from_triad(ww_stream * ow, ww_stream * iw, vorbis_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile);
|
||||
static int generate_vorbis_setup(ww_stream * ow, ww_stream * iw, vorbis_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile);
|
||||
|
||||
static int codebook_library_copy(ww_stream * ow, ww_stream * iw);
|
||||
@ -136,11 +135,7 @@ int wwise_vorbis_rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *stre
|
||||
iw.bufsize = ibufsize;
|
||||
iw.b_off = 0;
|
||||
|
||||
if (data->setup_type == HEADER_TRIAD) {
|
||||
rc = generate_vorbis_setup_from_triad(&ow,&iw, data, channels, packet_size, streamFile);
|
||||
} else {
|
||||
rc = generate_vorbis_setup(&ow,&iw, data, channels, packet_size, streamFile);
|
||||
}
|
||||
rc = generate_vorbis_setup(&ow,&iw, data, channels, packet_size, streamFile);
|
||||
if (!rc) goto fail;
|
||||
|
||||
if (ow.b_off % 8 != 0) {
|
||||
@ -280,58 +275,6 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
/* Parse a partially modified Wwise setup packet.
|
||||
* (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-650004.2.4) */
|
||||
static int generate_vorbis_setup_from_triad(ww_stream * ow, ww_stream * iw, vorbis_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile) {
|
||||
int i;
|
||||
uint32_t c = 0;
|
||||
|
||||
/* other packets from the triad should be memcpy'ed externally as they are untouched */
|
||||
|
||||
/* type */
|
||||
r_bits(iw, 8,&c);
|
||||
w_bits(ow, 8, c);
|
||||
|
||||
/* 'vorbis' */
|
||||
for (i = 0; i < 6; i++) {
|
||||
r_bits(iw, 8,&c);
|
||||
w_bits(iw, 8, c);
|
||||
}
|
||||
|
||||
/* codebook count */
|
||||
{
|
||||
uint32_t codebook_count_less1 = 0, codebook_count = 0;
|
||||
|
||||
r_bits(iw, 8,&codebook_count_less1);
|
||||
w_bits(iw, 8, codebook_count_less1);
|
||||
codebook_count = codebook_count_less1 + 1;
|
||||
|
||||
/* rebuild codebooks */
|
||||
for (i = 0; i < codebook_count; i++) {
|
||||
if(!codebook_library_copy(ow, iw)) goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* rest of setup is untouched, copy bits */
|
||||
{
|
||||
uint32_t bitly = 0;
|
||||
uint32_t total_bits_read = iw->b_off;
|
||||
uint32_t setup_packet_size_bits = packet_size*8;
|
||||
|
||||
while (total_bits_read < setup_packet_size_bits) {
|
||||
r_bits(iw, 1,&bitly);
|
||||
w_bits(ow, 1, bitly);
|
||||
total_bits_read = iw->b_off;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Rebuild a Wwise setup (simplified with removed stuff), recreating all six setup parts.
|
||||
* (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-650004.2.4) */
|
||||
static int generate_vorbis_setup(ww_stream * ow, ww_stream * iw, vorbis_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile) {
|
||||
|
@ -221,7 +221,7 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\adx_header.c"
|
||||
RelativePath=".\meta\adx.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
@ -1270,6 +1270,10 @@
|
||||
RelativePath=".\coding\aica_decoder.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\coding_utils.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\eaxa_decoder.c"
|
||||
>
|
||||
@ -1278,10 +1282,6 @@
|
||||
RelativePath=".\coding\ffmpeg_decoder.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\ffmpeg_decoder_utils.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\fsb_vorbis_decoder.c"
|
||||
>
|
||||
|
@ -124,8 +124,8 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="coding\at3_decoder.c" />
|
||||
<ClCompile Include="coding\coding_utils.c" />
|
||||
<ClCompile Include="coding\ffmpeg_decoder.c" />
|
||||
<ClCompile Include="coding\ffmpeg_decoder_utils.c" />
|
||||
<ClCompile Include="coding\lsf_decoder.c" />
|
||||
<ClCompile Include="coding\mp4_aac_decoder.c" />
|
||||
<ClCompile Include="coding\mtaf_decoder.c" />
|
||||
@ -178,7 +178,7 @@
|
||||
<ClCompile Include="meta\aax.c" />
|
||||
<ClCompile Include="meta\acm.c" />
|
||||
<ClCompile Include="meta\ads.c" />
|
||||
<ClCompile Include="meta\adx_header.c" />
|
||||
<ClCompile Include="meta\adx.c" />
|
||||
<ClCompile Include="meta\afc_header.c" />
|
||||
<ClCompile Include="meta\agsc.c" />
|
||||
<ClCompile Include="meta\ahx.c" />
|
||||
|
@ -112,7 +112,7 @@
|
||||
<ClCompile Include="meta\ads.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\adx_header.c">
|
||||
<ClCompile Include="meta\adx.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\afc_header.c">
|
||||
@ -1039,7 +1039,7 @@
|
||||
<ClCompile Include="coding\ffmpeg_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\ffmpeg_decoder_utils.c">
|
||||
<ClCompile Include="coding\coding_utils.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\xma.c">
|
||||
|
@ -6,7 +6,7 @@ AM_MAKEFLAGS=-f Makefile.unix
|
||||
libmeta_la_LDFLAGS =
|
||||
libmeta_la_SOURCES =
|
||||
libmeta_la_SOURCES += Cstr.c
|
||||
libmeta_la_SOURCES += adx_header.c
|
||||
libmeta_la_SOURCES += adx.c
|
||||
libmeta_la_SOURCES += afc_header.c
|
||||
libmeta_la_SOURCES += agsc.c
|
||||
libmeta_la_SOURCES += ast.c
|
||||
|
@ -11,138 +11,146 @@
|
||||
|
||||
static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add);
|
||||
|
||||
/* ADX - CRI Middleware format */
|
||||
VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t stream_offset;
|
||||
off_t start_offset, hist_offset = 0;
|
||||
int loop_flag = 0, channel_count;
|
||||
int32_t loop_start_sample = 0, loop_end_sample = 0;
|
||||
uint16_t version_signature;
|
||||
int loop_flag=0;
|
||||
int channel_count;
|
||||
int32_t loop_start_sample=0;
|
||||
int32_t loop_end_sample=0;
|
||||
|
||||
meta_t header_type;
|
||||
coding_t coding_type = coding_CRI_ADX;
|
||||
int16_t coef1, coef2;
|
||||
uint16_t cutoff;
|
||||
char filename[PATH_LIMIT];
|
||||
int coding_type = coding_CRI_ADX;
|
||||
uint16_t xor_start=0,xor_mult=0,xor_add=0;
|
||||
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("adx",filename_extension(filename))) goto fail;
|
||||
if (!check_extensions(streamFile,"adx")) goto fail;
|
||||
|
||||
/* check first 2 bytes */
|
||||
if ((uint16_t)read_16bitBE(0,streamFile)!=0x8000) goto fail;
|
||||
if ((uint16_t)read_16bitBE(0x00,streamFile)!=0x8000) goto fail;
|
||||
|
||||
/* get stream offset, check for CRI signature just before */
|
||||
stream_offset = (uint16_t)read_16bitBE(2,streamFile) + 4;
|
||||
if ((uint16_t)read_16bitBE(stream_offset-6,streamFile)!=0x2863 ||/* "(c" */
|
||||
(uint32_t)read_32bitBE(stream_offset-4,streamFile)!=0x29435249 /* ")CRI" */
|
||||
start_offset = (uint16_t)read_16bitBE(0x02,streamFile) + 4;
|
||||
if ((uint16_t)read_16bitBE(start_offset-6,streamFile)!=0x2863 || /* "(c" */
|
||||
(uint32_t)read_32bitBE(start_offset-4,streamFile)!=0x29435249 /* ")CRI" */
|
||||
) goto fail;
|
||||
|
||||
/* check for encoding type */
|
||||
/* 2 is for some unknown fixed filter, 3 is standard ADX, 4 is
|
||||
* ADX with exponential scale, 0x11 is AHX */
|
||||
if (read_8bit(4,streamFile) != 3) goto fail;
|
||||
/* 0x02 is for some unknown fixed filter, 0x03 is standard ADX, 0x04 is
|
||||
* ADX with exponential scale, 0x10 is AHX for DC, 0x11 is AHX */
|
||||
if (read_8bit(0x04,streamFile) != 3) goto fail;
|
||||
|
||||
/* check for frame size (only 18 is supported at the moment) */
|
||||
if (read_8bit(5,streamFile) != 18) goto fail;
|
||||
if (read_8bit(0x05,streamFile) != 18) goto fail;
|
||||
|
||||
/* check for bits per sample? (only 4 makes sense for ADX) */
|
||||
if (read_8bit(6,streamFile) != 4) goto fail;
|
||||
if (read_8bit(0x06,streamFile) != 4) goto fail;
|
||||
|
||||
/* older ADX (adxencd) up to 2ch, newer ADX (criatomencd) up to 8 */
|
||||
channel_count = read_8bit(0x07,streamFile);
|
||||
|
||||
/* check version signature, read loop info */
|
||||
version_signature = read_16bitBE(0x12,streamFile);
|
||||
|
||||
|
||||
/* encryption */
|
||||
if (version_signature == 0x0408) {
|
||||
if (find_key(streamFile, 8, &xor_start, &xor_mult, &xor_add))
|
||||
{
|
||||
if (find_key(streamFile, 8, &xor_start, &xor_mult, &xor_add)) {
|
||||
coding_type = coding_CRI_ADX_enc_8;
|
||||
version_signature = 0x0400;
|
||||
}
|
||||
}
|
||||
else if (version_signature == 0x0409) {
|
||||
if (find_key(streamFile, 9, &xor_start, &xor_mult, &xor_add))
|
||||
{
|
||||
if (find_key(streamFile, 9, &xor_start, &xor_mult, &xor_add)) {
|
||||
coding_type = coding_CRI_ADX_enc_9;
|
||||
version_signature = 0x0400;
|
||||
}
|
||||
}
|
||||
|
||||
if (version_signature == 0x0300) { /* type 03 */
|
||||
|
||||
/* version + extra data */
|
||||
if (version_signature == 0x0300) { /* early ADX (~2004?) */
|
||||
size_t base_size = 0x14, loops_size = 0x18;
|
||||
|
||||
header_type = meta_ADX_03;
|
||||
if (stream_offset-6 >= 0x2c) { /* enough space for loop info? */
|
||||
loop_flag = (read_32bitBE(0x18,streamFile) != 0);
|
||||
loop_start_sample = read_32bitBE(0x1c,streamFile);
|
||||
//loop_start_offset = read_32bitBE(0x20,streamFile);
|
||||
loop_end_sample = read_32bitBE(0x24,streamFile);
|
||||
//loop_end_offset = read_32bitBE(0x28,streamFile);
|
||||
|
||||
/* no sample history */
|
||||
|
||||
if (start_offset - 6 >= base_size + loops_size) { /* enough space for loop info? */
|
||||
off_t loops_offset = base_size;
|
||||
|
||||
/* off+0x00 (2): initial loop padding (the encoder adds a few blank samples so loop start is block-aligned; max 31)
|
||||
* ex. loop_start=12: enc_start=32, padding=20 (32-20=12); loop_start=35: enc_start=64, padding=29 (64-29=35)
|
||||
* off+0x02 (2): loop sample(?) flag (always 1) */
|
||||
loop_flag = read_32bitBE(loops_offset+0x04,streamFile) != 0; /* loop offset(?) flag (always 1) */
|
||||
loop_start_sample = read_32bitBE(loops_offset+0x08,streamFile);
|
||||
//loop_start_offset = read_32bitBE(loops_offset+0x0c,streamFile);
|
||||
loop_end_sample = read_32bitBE(loops_offset+0x10,streamFile);
|
||||
//loop_end_offset = read_32bitBE(loops_offset+0x14,streamFile);
|
||||
}
|
||||
} else if (version_signature == 0x0400) {
|
||||
|
||||
off_t ainf_info_length=0;
|
||||
|
||||
if((uint32_t)read_32bitBE(0x24,streamFile)==0x41494E46) /* AINF Header */
|
||||
ainf_info_length = (off_t)read_32bitBE(0x28,streamFile);
|
||||
}
|
||||
else if (version_signature == 0x0400) { /* common */
|
||||
size_t base_size = 0x18, hist_size, ainf_size = 0, loops_size = 0x18;
|
||||
off_t ainf_offset;
|
||||
|
||||
header_type = meta_ADX_04;
|
||||
if (stream_offset-ainf_info_length-6 >= 0x38) { /* enough space for loop info? */
|
||||
if (read_32bitBE(0x24,streamFile) == 0xFFFEFFFE)
|
||||
loop_flag = 0;
|
||||
else
|
||||
loop_flag = (read_32bitBE(0x24,streamFile) != 0);
|
||||
|
||||
loop_start_sample = read_32bitBE(0x28,streamFile);
|
||||
//loop_start_offset = read_32bitBE(0x2c,streamFile);
|
||||
loop_end_sample = read_32bitBE(0x30,streamFile);
|
||||
//loop_end_offset = read_32bitBE(0x34,streamFile);
|
||||
hist_offset = base_size; /* always present but often blank */
|
||||
hist_size = (channel_count > 1 ? 4*channel_count : 4+4); /* min is 8, even in 1ch files */
|
||||
|
||||
ainf_offset = base_size + hist_size + 0x4; /* not seen with >2ch though */
|
||||
if ((uint32_t)read_32bitBE(ainf_offset+0x00,streamFile) == 0x41494E46) /* "AINF" */
|
||||
ainf_size = read_32bitBE(ainf_offset+0x04,streamFile);
|
||||
|
||||
if (start_offset - ainf_size - 6 >= hist_offset + hist_size + loops_size) { /* enough space for loop info? */
|
||||
off_t loops_offset = base_size + hist_size;
|
||||
|
||||
/* off+0x00 (2): initial loop padding (the encoder adds a few blank samples so loop start is block-aligned; max 31)
|
||||
* ex. loop_start=12: enc_start=32, padding=20 (32-20=12); loop_start=35: enc_start=64, padding=29 (64-29=35)
|
||||
* off+0x02 (2): loop sample(?) flag (always 1) */
|
||||
loop_flag = read_32bitBE(loops_offset+0x04,streamFile) != 0; /* loop offset(?) flag (always 1) */
|
||||
loop_start_sample = read_32bitBE(loops_offset+0x08,streamFile);
|
||||
//loop_start_offset = read_32bitBE(loops_offset+0x0c,streamFile);
|
||||
loop_end_sample = read_32bitBE(loops_offset+0x10,streamFile);
|
||||
//loop_end_offset = read_32bitBE(loops_offset+0x14,streamFile);
|
||||
}
|
||||
|
||||
/* AINF header can also start after the loop points
|
||||
* (may be inserted by CRI's tools but is rarely used) */
|
||||
/* ainf_magic = read_32bitBE(0x38,streamFile); */ /* 0x41494E46 */
|
||||
/* ainf_length = read_32bitBE(0x3c,streamFile); */
|
||||
/* ainf_str_id = read_string(0x40,streamFile); */ /* max size 0x10 */
|
||||
/* ainf_volume = read_16bitBE(0x50,streamFile); */ /* 0=base/max?, negative=reduce */
|
||||
/* ainf_pan_l = read_16bitBE(0x54,streamFile); */ /* 0=base, max +-128 */
|
||||
/* ainf_pan_r = read_16bitBE(0x56,streamFile); */
|
||||
|
||||
} else if (version_signature == 0x0500) { /* found in some SFD : Buggy Heat, appears to have no loop */
|
||||
/* AINF header info (may be inserted by CRI's tools but is rarely used)
|
||||
* Can also start right after the loop points (base_size + hist_size + loops_size)
|
||||
* 0x00 (4): "AINF"; 0x04 (4): size; 0x08 (10): str_id
|
||||
* 0x18 (2): volume (0=base/max?, negative=reduce)
|
||||
* 0x1c (2): pan l; 0x1e (2): pan r (0=base, max +-128) */
|
||||
}
|
||||
else if (version_signature == 0x0500) { /* found in some SFD: Buggy Heat, appears to have no loop */
|
||||
header_type = meta_ADX_05;
|
||||
} else goto fail; /* not a known/supported version signature */
|
||||
|
||||
/* At this point we almost certainly have an ADX file,
|
||||
* so let's build the VGMSTREAM. */
|
||||
|
||||
/* high-pass cutoff frequency, always 500 that I've seen */
|
||||
cutoff = (uint16_t)read_16bitBE(0x10,streamFile);
|
||||
|
||||
if (loop_start_sample == 0 && loop_end_sample == 0) {
|
||||
loop_flag = 0;
|
||||
}
|
||||
else { /* not a known/supported version signature */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
channel_count = read_8bit(7,streamFile);
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = read_32bitBE(0xc,streamFile);
|
||||
vgmstream->sample_rate = read_32bitBE(8,streamFile);
|
||||
/* channels and loop flag are set by allocate_vgmstream */
|
||||
vgmstream->sample_rate = read_32bitBE(0x8,streamFile);
|
||||
vgmstream->loop_start_sample = loop_start_sample;
|
||||
vgmstream->loop_end_sample = loop_end_sample;
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
if (channel_count==1)
|
||||
vgmstream->layout_type = layout_none;
|
||||
else
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->layout_type = channel_count==1 ? layout_none : layout_interleave;
|
||||
vgmstream->interleave_block_size = 18;
|
||||
vgmstream->meta_type = header_type;
|
||||
|
||||
vgmstream->interleave_block_size=18;
|
||||
|
||||
/* calculate filter coefficients */
|
||||
{
|
||||
double x,y,z,a,b,c;
|
||||
/* high-pass cutoff frequency, always 500 that I've seen */
|
||||
uint16_t cutoff = (uint16_t)read_16bitBE(0x10,streamFile);
|
||||
|
||||
x = cutoff;
|
||||
y = vgmstream->sample_rate;
|
||||
@ -156,27 +164,22 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
coef2 = floor(c*c*-4096);
|
||||
}
|
||||
|
||||
/* init decoder */
|
||||
{
|
||||
int i;
|
||||
STREAMFILE * chstreamfile;
|
||||
|
||||
/* ADX is so tightly interleaved that having two buffers is silly */
|
||||
chstreamfile = streamFile->open(streamFile,filename,18*0x400);
|
||||
if (!chstreamfile) goto fail;
|
||||
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = chstreamfile;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=
|
||||
stream_offset+18*i;
|
||||
|
||||
vgmstream->ch[i].adpcm_coef[0] = coef1;
|
||||
vgmstream->ch[i].adpcm_coef[1] = coef2;
|
||||
|
||||
if (coding_type == coding_CRI_ADX_enc_8 ||
|
||||
coding_type == coding_CRI_ADX_enc_9)
|
||||
{
|
||||
/* 2 hist shorts per ch, corresponding to the very first original sample repeated (verified with CRI's encoders).
|
||||
* Not vital as their effect is small, after a few samples they don't matter, and most songs start in silence. */
|
||||
if (hist_offset) {
|
||||
vgmstream->ch[i].adpcm_history1_32 = read_16bitBE(hist_offset + i*4 + 0x00,streamFile);
|
||||
vgmstream->ch[i].adpcm_history2_32 = read_16bitBE(hist_offset + i*4 + 0x02,streamFile);
|
||||
}
|
||||
|
||||
if (coding_type == coding_CRI_ADX_enc_8 || coding_type == coding_CRI_ADX_enc_9) {
|
||||
int j;
|
||||
vgmstream->ch[i].adx_channels = channel_count;
|
||||
vgmstream->ch[i].adx_xor = xor_start;
|
||||
@ -189,11 +192,13 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -426,7 +431,7 @@ static struct {
|
||||
|
||||
};
|
||||
|
||||
/* type 9 keys */
|
||||
/* type 9 keys (may not be autodetected correctly) */
|
||||
static struct {
|
||||
uint16_t start,mult,add;
|
||||
} keys_9[] = {
|
||||
@ -442,6 +447,10 @@ static struct {
|
||||
* guessed with degod */
|
||||
{0x0005,0x0bcd,0x1add},
|
||||
|
||||
/* Raramagi [Android]
|
||||
* found in 2ch */
|
||||
{0x0000,0x0b99,0x1e33},
|
||||
|
||||
};
|
||||
|
||||
static const int keys_8_count = sizeof(keys_8)/sizeof(keys_8[0]);
|
@ -113,7 +113,7 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
|
||||
if (!find_chunk_be(streamFileGSP, 0x584D4558,first_offset,1, &chunk_offset,NULL)) goto fail; /*"XMEX"*/
|
||||
/* 0x00: fmt0x166 header (BE), 0x34: seek table */
|
||||
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt(buf,200, chunk_offset,0x34, datasize, streamFileGSP, 1);
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, chunk_offset,0x34, datasize, streamFileGSP, 1);
|
||||
if (bytes <= 0) goto fail;
|
||||
|
||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
|
||||
|
@ -358,7 +358,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
|
||||
/* post_meta_offset+0x00: fmt0x166 header (BE), post_meta_offset+0x34: seek table */
|
||||
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt(buf,200, post_meta_offset,0x34, stream_size, streamFile, 1);
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, post_meta_offset,0x34, stream_size, streamFile, 1);
|
||||
if (bytes <= 0) goto fail;
|
||||
|
||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size);
|
||||
|
@ -137,7 +137,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
case 0x0001: ww.codec = PCM; break; /* older Wwise */
|
||||
case 0x0002: ww.codec = IMA; break; /* newer Wwise (conflicts with MSADPCM, probably means "platform's ADPCM") */
|
||||
//case 0x0011: ww.codec = IMA; break; /* older Wwise (used?) */
|
||||
case 0x0069: ww.codec = IMA; break; /* older Wwise (Spiderman Web of Shadows X360) */
|
||||
case 0x0069: ww.codec = IMA; break; /* older Wwise (Spiderman Web of Shadows X360, LotR Conquest PC) */
|
||||
case 0x0161: ww.codec = XWMA; break;
|
||||
case 0x0162: ww.codec = XWMA; break;
|
||||
case 0x0165: ww.codec = XMA2; break; /* always with the "XMA2" chunk, Wwise doesn't use XMA1 */
|
||||
@ -146,7 +146,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
case 0xFFF0: ww.codec = DSP; break;
|
||||
case 0xFFFB: ww.codec = HEVAG; break;
|
||||
case 0xFFFC: ww.codec = ATRAC9; break;
|
||||
case 0xFFFE: ww.codec = PCM; break; /* newer Wwise ("PCM for Wwise Authoring") (conflicts with WAVEFORMATEXTENSIBLE) */
|
||||
case 0xFFFE: ww.codec = PCM; break; /* "PCM for Wwise Authoring" */
|
||||
case 0xFFFF: ww.codec = VORBIS; break;
|
||||
default:
|
||||
VGM_LOG("WWISE: unknown codec 0x%x \n", ww.format);
|
||||
@ -162,7 +162,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
* We'll add basic support to avoid complaints of this or that .wem not playing */
|
||||
if (ww.data_size > ww.file_size) {
|
||||
//VGM_LOG("WWISE: truncated data size (prefetch): (real=0x%x > riff=0x%x)\n", ww.data_size, ww.file_size);
|
||||
if (ww.codec == IMA || ww.codec == VORBIS) /* only seen in those, probably other exist */
|
||||
if (ww.codec == IMA || ww.codec == VORBIS) /* only seen those, probably others exist */
|
||||
ww.truncated = 1;
|
||||
else
|
||||
goto fail;
|
||||
@ -227,9 +227,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
/* older Wwise (~<2012) */
|
||||
|
||||
switch(vorb_size) {
|
||||
#if 0
|
||||
case 0x28: /* early (~2009), some Divinity II files? */
|
||||
case 0x2C: /* early (~2009), some EVE Online Apocrypha files? */
|
||||
//case 0x2C: /* early (~2009), some EVE Online Apocrypha files? */
|
||||
case 0x28: /* early (~2009), ex. The Lord of the Rings: Conquest PC */
|
||||
data_offsets = 0x18;
|
||||
block_offsets = 0; /* no need, full headers are present */
|
||||
header_type = TYPE_8;
|
||||
@ -237,16 +236,15 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
setup_type = HEADER_TRIAD;
|
||||
break;
|
||||
|
||||
case 0x32: /* ? */
|
||||
#endif
|
||||
//case 0x32: /* ? */
|
||||
case 0x34: /* common (2010~2011) */
|
||||
data_offsets = 0x18;
|
||||
block_offsets = 0x30;
|
||||
header_type = TYPE_6;
|
||||
packet_type = STANDARD;
|
||||
/* setup_type: autodetect later */
|
||||
setup_type = EXTERNAL_CODEBOOKS; /* setup_type will be corrected later */
|
||||
break;
|
||||
case 0x2a: /* infamous 2 (mid 2011) */
|
||||
case 0x2a: /* uncommon (mid 2011), ex. infamous 2 PS3 */
|
||||
data_offsets = 0x10;
|
||||
block_offsets = 0x28;
|
||||
header_type = TYPE_2;
|
||||
@ -282,9 +280,6 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
else if (setup_size > 0x200) { /* an external setup it's ~0x100 max + some threshold */
|
||||
setup_type = INLINE_CODEBOOKS;
|
||||
}
|
||||
else {
|
||||
setup_type = EXTERNAL_CODEBOOKS;
|
||||
}
|
||||
}
|
||||
|
||||
vgmstream->codec_data = init_wwise_vorbis_codec_data(streamFile, start_offset + setup_offset, ww.channels, ww.sample_rate, blocksize_0_exp,blocksize_1_exp,
|
||||
@ -302,16 +297,16 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
block_offsets = 0x28;
|
||||
header_type = TYPE_2;
|
||||
packet_type = MODIFIED;
|
||||
//packet_type = STANDARD;
|
||||
|
||||
/* setup not detectable by header, so we'll try both; hopefully libvorbis will reject wrong codebooks
|
||||
* - standard: early (<2012), ex. The King of Fighters XIII X360 (2011/11), .ogg
|
||||
* - standard: early (<2012), ex. The King of Fighters XIII X360 (2011/11), .ogg (cbs are from aoTuV, too)
|
||||
* - aoTuV603: later (>2012), ex. Sonic & All-Stars Racing Transformed PC (2012/11), .wem */
|
||||
setup_type = is_wem ? AOTUV603_CODEBOOKS : EXTERNAL_CODEBOOKS; /* aoTuV came along .wem */
|
||||
break;
|
||||
|
||||
//case 0x2a: /* Rocksmith 2011 X360? */
|
||||
//non mod packets? TYPE_06? (possibly detectable by checking setup's granule, should be 0)
|
||||
default:
|
||||
//todo apparently some 0x2a + non mod_packets exist
|
||||
//todo TYPE_06 possibly detectable by checking setup's granule (should be 0)
|
||||
VGM_LOG("WWISE: unknown extra size 0x%x\n", vorb_size);
|
||||
goto fail;
|
||||
}
|
||||
@ -404,7 +399,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
if (find_chunk(streamFile, 0x584D4132,first_offset,0, &xma2_offset,&xma2_size, ww.big_endian, 0)) { /*"XMA2"*/ /* older Wwise */
|
||||
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf,0x100, xma2_offset, xma2_size, ww.data_size, streamFile);
|
||||
} else { /* newer Wwise */
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt(buf,0x100, ww.fmt_offset, ww.fmt_size, ww.data_size, streamFile, ww.big_endian);
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, ww.fmt_offset, ww.fmt_size, ww.data_size, streamFile, ww.big_endian);
|
||||
}
|
||||
if (bytes <= 0) goto fail;
|
||||
|
||||
@ -441,8 +436,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
|
||||
/* manually find total samples, why don't they put this in the header is beyond me */
|
||||
if (ww.format == 0x0162) { /* WMAPRO */
|
||||
xma_sample_data msd;
|
||||
memset(&msd,0,sizeof(xma_sample_data));
|
||||
ms_sample_data msd;
|
||||
memset(&msd,0,sizeof(ms_sample_data));
|
||||
|
||||
msd.channels = ww.channels;
|
||||
msd.data_offset = ww.data_offset;
|
||||
@ -535,7 +530,7 @@ fail:
|
||||
0x31 (1): blocksize_0_exp (large)
|
||||
0x32 (2): empty
|
||||
|
||||
"vorb" size 0x2a
|
||||
"vorb" size 0x28 / 0x2a
|
||||
0x00 (4): num_samples
|
||||
0x04 (4): loop offset after seek table+setup (offset after setup if file doesn't loop)
|
||||
0x08 (4): data size without seek table (setup+packets)
|
||||
@ -547,8 +542,8 @@ fail:
|
||||
0x1c (4): ? (mid, 0~0x5000)
|
||||
0x20 (4): ? (mid, 0~0x5000)
|
||||
0x24 (4): parent bank/event id? (shared by several .wem a game, but not all need to share it)
|
||||
0x28 (1): blocksize_1_exp (small)
|
||||
0x29 (1): blocksize_0_exp (large)
|
||||
0x28 (1): blocksize_1_exp (small) [removed when size is 0x28]
|
||||
0x29 (1): blocksize_0_exp (large) [removed when size is 0x28]
|
||||
|
||||
|
||||
- new format:
|
||||
|
@ -37,29 +37,29 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
|
||||
vgmstream->sample_rate = read_32bitBE(0x40,streamFile);
|
||||
vgmstream->meta_type = meta_X360_AST;
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
{
|
||||
/* manually find sample offsets (XMA1 nonsense again) */
|
||||
xma_sample_data xma_sd;
|
||||
memset(&xma_sd,0,sizeof(xma_sample_data));
|
||||
ms_sample_data msd;
|
||||
memset(&msd,0,sizeof(ms_sample_data));
|
||||
|
||||
xma_sd.xma_version = 1;
|
||||
xma_sd.channels = channel_count;
|
||||
xma_sd.data_offset = start_offset;
|
||||
xma_sd.data_size = data_size;
|
||||
xma_sd.loop_flag = loop_flag;
|
||||
xma_sd.loop_start_b = read_32bitBE(0x44,streamFile);
|
||||
xma_sd.loop_end_b = read_32bitBE(0x48,streamFile);
|
||||
xma_sd.loop_start_subframe = read_8bit(0x4c,streamFile) & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
|
||||
xma_sd.loop_end_subframe = read_8bit(0x4c,streamFile) >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
|
||||
msd.xma_version = 1;
|
||||
msd.channels = channel_count;
|
||||
msd.data_offset = start_offset;
|
||||
msd.data_size = data_size;
|
||||
msd.loop_flag = loop_flag;
|
||||
msd.loop_start_b = read_32bitBE(0x44,streamFile);
|
||||
msd.loop_end_b = read_32bitBE(0x48,streamFile);
|
||||
msd.loop_start_subframe = read_8bit(0x4c,streamFile) & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
|
||||
msd.loop_end_subframe = read_8bit(0x4c,streamFile) >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
|
||||
|
||||
xma_get_samples(&xma_sd, streamFile);
|
||||
vgmstream->num_samples = xma_sd.num_samples;
|
||||
vgmstream->loop_start_sample = xma_sd.loop_start_sample;
|
||||
vgmstream->loop_end_sample = xma_sd.loop_end_sample;
|
||||
//skip_samples = xma_sd.skip_samples; //todo add skip samples
|
||||
xma_get_samples(&msd, streamFile);
|
||||
vgmstream->num_samples = msd.num_samples;
|
||||
vgmstream->loop_start_sample = msd.loop_start_sample;
|
||||
vgmstream->loop_end_sample = msd.loop_end_sample;
|
||||
//skip_samples = msd.skip_samples; //todo add skip samples
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
{
|
||||
uint8_t buf[100];
|
||||
size_t bytes;
|
||||
@ -68,7 +68,7 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
|
||||
size_t fmt_size = 0x0c + xma_streams * 0x14;
|
||||
|
||||
/* XMA1 "fmt" chunk @ 0x20 (BE, unlike the usual LE) */
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt(buf,100, fmt_offset,fmt_size, data_size, streamFile, 1);
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,100, fmt_offset,fmt_size, data_size, streamFile, 1);
|
||||
if (bytes <= 0) goto fail;
|
||||
|
||||
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
||||
|
@ -286,7 +286,7 @@ fail:
|
||||
|
||||
|
||||
static void fix_samples(xma_header_data * xma, STREAMFILE *streamFile) {
|
||||
xma_sample_data xma_sd;
|
||||
ms_sample_data msd;
|
||||
|
||||
/* for now only XMA1 is fixed, but xmaencode.exe doesn't seem to use
|
||||
* XMA2 sample values in the headers, and the exact number of samples may not be exact.
|
||||
@ -296,26 +296,26 @@ static void fix_samples(xma_header_data * xma, STREAMFILE *streamFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&xma_sd,0,sizeof(xma_sample_data));
|
||||
memset(&msd,0,sizeof(ms_sample_data));
|
||||
|
||||
/* call xma parser (copy to its own struct, a bit clunky but oh well...) */
|
||||
xma_sd.xma_version = xma->fmt_codec==0x165 ? 1 : 2;
|
||||
xma_sd.channels = xma->channels;
|
||||
xma_sd.data_offset = xma->data_offset;
|
||||
xma_sd.data_size = xma->data_size;
|
||||
xma_sd.loop_flag = xma->loop_flag;
|
||||
xma_sd.loop_start_b = xma->loop_start_b;
|
||||
xma_sd.loop_end_b = xma->loop_end_b;
|
||||
xma_sd.loop_start_subframe = xma->loop_subframe & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
|
||||
xma_sd.loop_end_subframe = xma->loop_subframe >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
|
||||
msd.xma_version = xma->fmt_codec==0x165 ? 1 : 2;
|
||||
msd.channels = xma->channels;
|
||||
msd.data_offset = xma->data_offset;
|
||||
msd.data_size = xma->data_size;
|
||||
msd.loop_flag = xma->loop_flag;
|
||||
msd.loop_start_b = xma->loop_start_b;
|
||||
msd.loop_end_b = xma->loop_end_b;
|
||||
msd.loop_start_subframe = xma->loop_subframe & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
|
||||
msd.loop_end_subframe = xma->loop_subframe >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
|
||||
|
||||
xma_get_samples(&xma_sd, streamFile);
|
||||
xma_get_samples(&msd, streamFile);
|
||||
|
||||
/* and recieve results */
|
||||
xma->num_samples = xma_sd.num_samples;
|
||||
xma->skip_samples = xma_sd.skip_samples;
|
||||
xma->loop_start_sample = xma_sd.loop_start_sample;
|
||||
xma->loop_end_sample = xma_sd.loop_end_sample;
|
||||
xma->num_samples = msd.num_samples;
|
||||
xma->skip_samples = msd.skip_samples;
|
||||
xma->loop_start_sample = msd.loop_start_sample;
|
||||
xma->loop_end_sample = msd.loop_end_sample;
|
||||
/* XMA2 loop/num_samples don't seem to skip_samples */
|
||||
}
|
||||
|
||||
|
@ -255,25 +255,24 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
}
|
||||
else if (xwb.xact == 2 && xwb.version <= 38 /* v38: byte offset, v40+: sample offset, v39: ? */
|
||||
&& (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) {
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
/* need to manually find sample offsets, thanks to Microsoft dumb headers */
|
||||
xma_sample_data xma_sd;
|
||||
memset(&xma_sd,0,sizeof(xma_sample_data));
|
||||
ms_sample_data msd;
|
||||
memset(&msd,0,sizeof(ms_sample_data));
|
||||
|
||||
xma_sd.xma_version = xwb.codec == XMA1 ? 1 : 2;
|
||||
xma_sd.channels = xwb.channels;
|
||||
xma_sd.data_offset = xwb.stream_offset;
|
||||
xma_sd.data_size = xwb.stream_size;
|
||||
xma_sd.loop_flag = xwb.loop_flag;
|
||||
xma_sd.loop_start_b = xwb.loop_start; /* bit offset in the stream */
|
||||
xma_sd.loop_end_b = (xwb.loop_end >> 4); /*28b */
|
||||
msd.xma_version = xwb.codec == XMA1 ? 1 : 2;
|
||||
msd.channels = xwb.channels;
|
||||
msd.data_offset = xwb.stream_offset;
|
||||
msd.data_size = xwb.stream_size;
|
||||
msd.loop_flag = xwb.loop_flag;
|
||||
msd.loop_start_b = xwb.loop_start; /* bit offset in the stream */
|
||||
msd.loop_end_b = (xwb.loop_end >> 4); /*28b */
|
||||
/* XACT adds +1 to the subframe, but this means 0 can't be used? */
|
||||
xma_sd.loop_end_subframe = ((xwb.loop_end >> 2) & 0x3) + 1; /* 2b */
|
||||
xma_sd.loop_start_subframe = ((xwb.loop_end >> 0) & 0x3) + 1; /* 2b */
|
||||
msd.loop_end_subframe = ((xwb.loop_end >> 2) & 0x3) + 1; /* 2b */
|
||||
msd.loop_start_subframe = ((xwb.loop_end >> 0) & 0x3) + 1; /* 2b */
|
||||
|
||||
xma_get_samples(&xma_sd, streamFile);
|
||||
xwb.loop_start_sample = xma_sd.loop_start_sample;
|
||||
xwb.loop_end_sample = xma_sd.loop_end_sample;
|
||||
xma_get_samples(&msd, streamFile);
|
||||
xwb.loop_start_sample = msd.loop_start_sample;
|
||||
xwb.loop_end_sample = msd.loop_end_sample;
|
||||
|
||||
// todo fix properly (XWB loop_start/end seem to count padding samples while XMA1 RIFF doesn't)
|
||||
//this doesn't seem ok because can fall within 0 to 512 (ie.- first frame)
|
||||
@ -283,9 +282,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
//add padding back until it's fixed (affects looping)
|
||||
// (in rare cases this causes a glitch in FFmpeg since it has a bug where it's missing some samples)
|
||||
xwb.num_samples += 64 + 512;
|
||||
#else
|
||||
goto fail;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user