mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 15:00:11 +01:00
Improve raw ATRAC3 decoding accuracy and cleanup
This commit is contained in:
parent
6f2999cd3d
commit
84038b0fea
@ -147,7 +147,6 @@ codec = (codec string)
|
|||||||
Changes the behavior of some codecs:
|
Changes the behavior of some codecs:
|
||||||
```
|
```
|
||||||
# - NGC_DSP: 0=normal interleave, 1=byte interleave, 2=no interleave
|
# - NGC_DSP: 0=normal interleave, 1=byte interleave, 2=no interleave
|
||||||
# - ATRAC3: 0=autodetect joint stereo, 1=force joint stereo, 2=force normal stereo
|
|
||||||
# - XMA1|XMA2: 0=dual multichannel (2ch xN), 1=single multichannel (1ch xN)
|
# - XMA1|XMA2: 0=dual multichannel (2ch xN), 1=single multichannel (1ch xN)
|
||||||
# - XBOX: 0=standard (mono or stereo interleave), 1=force mono interleave mode
|
# - XBOX: 0=standard (mono or stereo interleave), 1=force mono interleave mode
|
||||||
# - PCFX: 0=standard, 1='buggy encoder' mode, 2/3=same as 0/1 but with double volume
|
# - PCFX: 0=standard, 1='buggy encoder' mode, 2/3=same as 0/1 but with double volume
|
||||||
|
@ -298,6 +298,7 @@ void ffmpeg_set_channel_remapping(ffmpeg_codec_data * data, int *channels_remap)
|
|||||||
|
|
||||||
|
|
||||||
/* ffmpeg_decoder_utils.c (helper-things) */
|
/* 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_riff(STREAMFILE *sf, off_t offset, int* out_samples);
|
||||||
|
|
||||||
|
|
||||||
@ -328,7 +329,6 @@ size_t ea_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile);
|
|||||||
|
|
||||||
/* coding_utils */
|
/* coding_utils */
|
||||||
int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, size_t chunk_size, uint16_t codec);
|
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_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_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_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);
|
||||||
|
@ -37,45 +37,6 @@ static uint32_t read_bitsBE_b(off_t bit_offset, int num_bits, STREAMFILE *stream
|
|||||||
/* ******************************************** */
|
/* ******************************************** */
|
||||||
/* All helpers copy a RIFF header to buf and returns the number of bytes in buf or -1 when buf is not big enough */
|
/* All helpers copy a RIFF header to buf and returns the number of bytes in buf or -1 when buf is not big enough */
|
||||||
|
|
||||||
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) {
|
|
||||||
uint16_t codec_ATRAC3 = 0x0270;
|
|
||||||
size_t riff_size = 4+4+ 4 + 0x28 + 0x10 + 4+4;
|
|
||||||
|
|
||||||
if (buf_size < riff_size)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
memcpy(buf+0x00, "RIFF", 4);
|
|
||||||
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
|
|
||||||
memcpy(buf+0x08, "WAVE", 4);
|
|
||||||
|
|
||||||
memcpy(buf+0x0c, "fmt ", 4);
|
|
||||||
put_32bitLE(buf+0x10, 0x20);/*fmt size*/
|
|
||||||
put_16bitLE(buf+0x14, codec_ATRAC3);
|
|
||||||
put_16bitLE(buf+0x16, channels);
|
|
||||||
put_32bitLE(buf+0x18, sample_rate);
|
|
||||||
put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong) */
|
|
||||||
put_32bitLE(buf+0x20, (int16_t)(block_align)); /* block align */
|
|
||||||
|
|
||||||
put_16bitLE(buf+0x24, 0x0e); /* extra data size */
|
|
||||||
put_16bitLE(buf+0x26, 1); /* unknown, always 1 */
|
|
||||||
put_16bitLE(buf+0x28, 0x0800 * channels); /* unknown (some size? 0x1000=2ch, 0x0800=1ch) */
|
|
||||||
put_16bitLE(buf+0x2a, 0); /* unknown, always 0 */
|
|
||||||
put_16bitLE(buf+0x2c, joint_stereo ? 0x0001 : 0x0000);
|
|
||||||
put_16bitLE(buf+0x2e, joint_stereo ? 0x0001 : 0x0000); /* repeated? */
|
|
||||||
put_16bitLE(buf+0x30, 1); /* unknown, always 1 (frame_factor?) */
|
|
||||||
put_16bitLE(buf+0x32, 0); /* unknown, always 0 */
|
|
||||||
|
|
||||||
memcpy(buf+0x34, "fact", 4);
|
|
||||||
put_32bitLE(buf+0x38, 0x8); /* fact size */
|
|
||||||
put_32bitLE(buf+0x3c, sample_count);
|
|
||||||
put_32bitLE(buf+0x40, encoder_delay);
|
|
||||||
|
|
||||||
memcpy(buf+0x44, "data", 4);
|
|
||||||
put_32bitLE(buf+0x48, data_size); /* data size */
|
|
||||||
|
|
||||||
return riff_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_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) {
|
||||||
uint16_t codec_ATRAC3plus = 0xfffe; /* wave format extensible */
|
uint16_t codec_ATRAC3plus = 0xfffe; /* wave format extensible */
|
||||||
size_t riff_size = 4+4+ 4 + 0x3c + 0x14 + 4+4;
|
size_t riff_size = 4+4+ 4 + 0x3c + 0x14 + 4+4;
|
||||||
|
@ -2,6 +2,77 @@
|
|||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
|
|
||||||
|
static 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) {
|
||||||
|
uint16_t codec_ATRAC3 = 0x0270;
|
||||||
|
size_t riff_size = 4+4+ 4 + 0x28 + 0x10 + 4+4;
|
||||||
|
|
||||||
|
if (buf_size < riff_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(buf+0x00, "RIFF", 4);
|
||||||
|
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
|
||||||
|
memcpy(buf+0x08, "WAVE", 4);
|
||||||
|
|
||||||
|
memcpy(buf+0x0c, "fmt ", 4);
|
||||||
|
put_32bitLE(buf+0x10, 0x20);/*fmt size*/
|
||||||
|
put_16bitLE(buf+0x14, codec_ATRAC3);
|
||||||
|
put_16bitLE(buf+0x16, channels);
|
||||||
|
put_32bitLE(buf+0x18, sample_rate);
|
||||||
|
put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong) */
|
||||||
|
put_32bitLE(buf+0x20, (int16_t)(block_align)); /* block align */
|
||||||
|
|
||||||
|
put_16bitLE(buf+0x24, 0x0e); /* extra data size */
|
||||||
|
put_16bitLE(buf+0x26, 1); /* unknown, always 1 */
|
||||||
|
put_16bitLE(buf+0x28, 0x0800 * channels); /* unknown (some size? 0x1000=2ch, 0x0800=1ch) */
|
||||||
|
put_16bitLE(buf+0x2a, 0); /* unknown, always 0 */
|
||||||
|
put_16bitLE(buf+0x2c, joint_stereo ? 0x0001 : 0x0000);
|
||||||
|
put_16bitLE(buf+0x2e, joint_stereo ? 0x0001 : 0x0000); /* repeated? */
|
||||||
|
put_16bitLE(buf+0x30, 1); /* unknown, always 1 (frame_factor?) */
|
||||||
|
put_16bitLE(buf+0x32, 0); /* unknown, always 0 */
|
||||||
|
|
||||||
|
memcpy(buf+0x34, "fact", 4);
|
||||||
|
put_32bitLE(buf+0x38, 0x8); /* fact size */
|
||||||
|
put_32bitLE(buf+0x3c, sample_count);
|
||||||
|
put_32bitLE(buf+0x40, encoder_delay);
|
||||||
|
|
||||||
|
memcpy(buf+0x44, "data", 4);
|
||||||
|
put_32bitLE(buf+0x48, data_size); /* data size */
|
||||||
|
|
||||||
|
return riff_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 *ffmpeg_data = NULL;
|
||||||
|
uint8_t buf[0x100];
|
||||||
|
int bytes;
|
||||||
|
int joint_stereo = (block_align == 0x60*channels) && channels > 1; /* only lowest block size does joint stereo */
|
||||||
|
int is_at3 = 1; /* could detect using block size */
|
||||||
|
|
||||||
|
/* create fake header + init ffmpeg + apply fixes to FFmpeg decoding */
|
||||||
|
bytes = ffmpeg_make_riff_atrac3(buf,sizeof(buf), sample_count, data_size, channels, sample_rate, block_align, joint_stereo, encoder_delay);
|
||||||
|
ffmpeg_data = init_ffmpeg_header_offset(sf, buf,bytes, offset,data_size);
|
||||||
|
if (!ffmpeg_data) goto fail;
|
||||||
|
|
||||||
|
/* unlike with RIFF ATRAC3 we don't set implicit delay, as raw ATRAC3 headers often give loop/samples
|
||||||
|
* in offsets, so calcs are expected to be handled externally (presumably the game would call raw decoding API
|
||||||
|
* and any skips would be handled manually) */
|
||||||
|
|
||||||
|
/* FFmpeg reads this but just in case they fiddle with it in the future */
|
||||||
|
ffmpeg_data->totalSamples = sample_count;
|
||||||
|
|
||||||
|
/* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame)
|
||||||
|
* FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */
|
||||||
|
ffmpeg_set_skip_samples(ffmpeg_data, encoder_delay);
|
||||||
|
|
||||||
|
/* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */
|
||||||
|
if (is_at3) {
|
||||||
|
ffmpeg_data->invert_audio_set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ffmpeg_data;
|
||||||
|
fail:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* init ATRAC3/plus while adding some fixes */
|
/* init ATRAC3/plus while adding some fixes */
|
||||||
ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* out_samples) {
|
ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* out_samples) {
|
||||||
@ -26,7 +97,7 @@ ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* o
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* init file + apply fixes to FFmpeg decoding (with these fixes should be
|
/* init ffmpeg + apply fixes to FFmpeg decoding (with these fixes should be
|
||||||
* sample-accurate vs official tools, except usual +-1 float-to-pcm conversion) */
|
* sample-accurate vs official tools, except usual +-1 float-to-pcm conversion) */
|
||||||
ffmpeg_data = init_ffmpeg_offset(sf, offset, riff_size);
|
ffmpeg_data = init_ffmpeg_offset(sf, offset, riff_size);
|
||||||
if (!ffmpeg_data) goto fail;
|
if (!ffmpeg_data) goto fail;
|
||||||
|
@ -27,13 +27,13 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
|
|||||||
|
|
||||||
codec = read_32bitLE(0x0c,streamFile);
|
codec = read_32bitLE(0x0c,streamFile);
|
||||||
file_size = read_32bitLE(0x10,streamFile);
|
file_size = read_32bitLE(0x10,streamFile);
|
||||||
/*file_id = read_32bitLE(0x14,streamFile);*/
|
/* file_id = read_32bitLE(0x14,streamFile); */
|
||||||
block_size = read_32bitLE(0x18,streamFile);
|
block_size = read_32bitLE(0x18,streamFile);
|
||||||
loop_start = read_32bitLE(0x1c,streamFile);
|
loop_start = read_32bitLE(0x1c,streamFile);
|
||||||
sample_rate = (read_32bitLE(0x20,streamFile) + read_32bitLE(0x24,streamFile)) & 0x7FFFFFFF; /* bizarrely obfuscated sample rate */
|
sample_rate = (read_32bitLE(0x20,streamFile) + read_32bitLE(0x24,streamFile)) & 0x7FFFFFFF; /* bizarrely obfuscated sample rate */
|
||||||
start_offset = read_32bitLE(0x28,streamFile);
|
start_offset = read_32bitLE(0x28,streamFile);
|
||||||
/*0x2c: unk (vol?) */
|
/* 0x2c: unk (vol?) */
|
||||||
/*0x2d: unk (0x10?) */
|
/* 0x2d: unk (0x10?) */
|
||||||
channel_count = read_8bit(0x2e,streamFile);
|
channel_count = read_8bit(0x2e,streamFile);
|
||||||
block_align = (uint8_t)read_8bit(0x2f,streamFile);
|
block_align = (uint8_t)read_8bit(0x2f,streamFile);
|
||||||
|
|
||||||
@ -65,31 +65,26 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
|
|||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
case 3: { /* ATRAC3 (encrypted) */
|
case 3: { /* ATRAC3 (encrypted) */
|
||||||
uint8_t buf[0x100];
|
|
||||||
int bytes, joint_stereo, skip_samples;
|
|
||||||
size_t data_size = file_size - start_offset;
|
size_t data_size = file_size - start_offset;
|
||||||
|
int encoder_delay, block_align;
|
||||||
|
|
||||||
vgmstream->num_samples = block_size; /* atrac3_bytes_to_samples gives the same value */
|
encoder_delay = 1024*2 + 69*2; /* observed value, all files start at +2200 (PS-ADPCM also starts around 50-150 samples in) */
|
||||||
if (loop_flag) {
|
block_align = 0xC0 * vgmstream->channels; /* 0x00 in header */
|
||||||
vgmstream->loop_start_sample = loop_start;
|
vgmstream->num_samples = block_size - encoder_delay; /* atrac3_bytes_to_samples gives block_size */
|
||||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
block_align = 0xC0 * vgmstream->channels; /* 0x00 in header */
|
|
||||||
joint_stereo = 0;
|
|
||||||
skip_samples = 0;
|
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, 0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_align, joint_stereo, skip_samples);
|
|
||||||
if (bytes <= 0) goto fail;
|
|
||||||
|
|
||||||
temp_streamFile = setup_bgw_atrac3_streamfile(streamFile, start_offset,data_size, 0xC0,channel_count);
|
temp_streamFile = setup_bgw_atrac3_streamfile(streamFile, start_offset,data_size, 0xC0,channel_count);
|
||||||
if (!temp_streamFile) goto fail;
|
if (!temp_streamFile) goto fail;
|
||||||
|
|
||||||
vgmstream->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, 0,data_size);
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(temp_streamFile, 0x00,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
if (!vgmstream->codec_data) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
|
if (loop_flag) {
|
||||||
|
vgmstream->loop_start_sample = loop_start - encoder_delay;
|
||||||
|
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||||
|
}
|
||||||
|
|
||||||
close_streamfile(temp_streamFile);
|
close_streamfile(temp_streamFile);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -132,13 +127,13 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
|
|||||||
|
|
||||||
file_size = read_32bitLE(0x08,streamFile);
|
file_size = read_32bitLE(0x08,streamFile);
|
||||||
codec = read_32bitLE(0x0c,streamFile);
|
codec = read_32bitLE(0x0c,streamFile);
|
||||||
/*file_id = read_32bitLE(0x10,streamFile);*/
|
/* file_id = read_32bitLE(0x10,streamFile);*/
|
||||||
block_size = read_32bitLE(0x14,streamFile);
|
block_size = read_32bitLE(0x14,streamFile);
|
||||||
loop_start = read_32bitLE(0x18,streamFile);
|
loop_start = read_32bitLE(0x18,streamFile);
|
||||||
sample_rate = (read_32bitLE(0x1c,streamFile) + read_32bitLE(0x20,streamFile)) & 0x7FFFFFFF; /* bizarrely obfuscated sample rate */
|
sample_rate = (read_32bitLE(0x1c,streamFile) + read_32bitLE(0x20,streamFile)) & 0x7FFFFFFF; /* bizarrely obfuscated sample rate */
|
||||||
start_offset = read_32bitLE(0x24,streamFile);
|
start_offset = read_32bitLE(0x24,streamFile);
|
||||||
/*0x2c: unk (0x00?) */
|
/* 0x2c: unk (0x00?) */
|
||||||
/*0x2d: unk (0x00/01?) */
|
/* 0x2d: unk (0x00/01?) */
|
||||||
channel_count = read_8bit(0x2a,streamFile);
|
channel_count = read_8bit(0x2a,streamFile);
|
||||||
/*0x2b: unk (0x01 when PCM, 0x10 when VAG?) */
|
/*0x2b: unk (0x01 when PCM, 0x10 when VAG?) */
|
||||||
block_align = read_8bit(0x2c,streamFile);
|
block_align = read_8bit(0x2c,streamFile);
|
||||||
@ -184,31 +179,26 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
|
|||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
case 3: { /* ATRAC3 (encrypted) */
|
case 3: { /* ATRAC3 (encrypted) */
|
||||||
uint8_t buf[0x100];
|
|
||||||
int bytes, joint_stereo, skip_samples;
|
|
||||||
size_t data_size = file_size - start_offset;
|
size_t data_size = file_size - start_offset;
|
||||||
|
int encoder_delay, block_align;
|
||||||
|
|
||||||
vgmstream->num_samples = block_size; /* atrac3_bytes_to_samples gives the same value */
|
encoder_delay = 1024*2 + 69*2; /* observed value, all files start at +2200 (PS-ADPCM also starts around 50-150 samples in) */
|
||||||
if (loop_flag) {
|
block_align = 0xC0 * vgmstream->channels; /* 0x00 in header */
|
||||||
vgmstream->loop_start_sample = loop_start;
|
vgmstream->num_samples = block_size - encoder_delay; /* atrac3_bytes_to_samples gives block_size */
|
||||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
block_align = 0xC0 * vgmstream->channels; /* 0x00 in header */
|
|
||||||
joint_stereo = 0;
|
|
||||||
skip_samples = 0;
|
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, 0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_align, joint_stereo, skip_samples);
|
|
||||||
if (bytes <= 0) goto fail;
|
|
||||||
|
|
||||||
temp_streamFile = setup_bgw_atrac3_streamfile(streamFile, start_offset,data_size, 0xC0,channel_count);
|
temp_streamFile = setup_bgw_atrac3_streamfile(streamFile, start_offset,data_size, 0xC0,channel_count);
|
||||||
if (!temp_streamFile) goto fail;
|
if (!temp_streamFile) goto fail;
|
||||||
|
|
||||||
vgmstream->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, 0,data_size);
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(temp_streamFile, 0x00,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
if (!vgmstream->codec_data) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
|
if (loop_flag) {
|
||||||
|
vgmstream->loop_start_sample = loop_start - encoder_delay;
|
||||||
|
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||||
|
}
|
||||||
|
|
||||||
close_streamfile(temp_streamFile);
|
close_streamfile(temp_streamFile);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -313,39 +313,41 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||||||
int32_t bytes;
|
int32_t bytes;
|
||||||
|
|
||||||
if (genh.codec == ATRAC3) {
|
if (genh.codec == ATRAC3) {
|
||||||
int block_size = genh.interleave;
|
int block_align, encoder_delay;
|
||||||
int joint_stereo;
|
|
||||||
switch(genh.codec_mode) {
|
|
||||||
case 0: joint_stereo = vgmstream->channels > 1 && genh.interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */
|
|
||||||
case 1: joint_stereo = 1; break; /* force joint stereo */
|
|
||||||
case 2: joint_stereo = 0; break; /* force stereo */
|
|
||||||
default: goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, genh.skip_samples);
|
block_align = genh.interleave;
|
||||||
|
encoder_delay = genh.skip_samples;
|
||||||
|
|
||||||
|
ffmpeg_data = init_ffmpeg_atrac3_raw(streamFile, genh.start_offset,genh.data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
|
if (!ffmpeg_data) goto fail;
|
||||||
}
|
}
|
||||||
else if (genh.codec == ATRAC3PLUS) {
|
else if (genh.codec == ATRAC3PLUS) {
|
||||||
int block_size = genh.interleave;
|
int block_size = genh.interleave;
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, genh.skip_samples);
|
bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, genh.skip_samples);
|
||||||
|
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
|
||||||
|
if ( !ffmpeg_data ) goto fail;
|
||||||
}
|
}
|
||||||
else if (genh.codec == XMA1) {
|
else if (genh.codec == XMA1) {
|
||||||
int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0;
|
int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0;
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
|
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
|
||||||
|
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
|
||||||
|
if ( !ffmpeg_data ) goto fail;
|
||||||
}
|
}
|
||||||
else if (genh.codec == XMA2) {
|
else if (genh.codec == XMA2) {
|
||||||
int block_size = genh.interleave ? genh.interleave : 2048;
|
int block_count, block_size;
|
||||||
int block_count = genh.data_size / block_size;
|
|
||||||
|
block_size = genh.interleave ? genh.interleave : 2048;
|
||||||
|
block_count = genh.data_size / block_size;
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
|
bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
|
||||||
|
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
|
||||||
|
if ( !ffmpeg_data ) goto fail;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
|
|
||||||
if ( !ffmpeg_data ) goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vgmstream->codec_data = ffmpeg_data;
|
vgmstream->codec_data = ffmpeg_data;
|
||||||
@ -353,7 +355,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||||||
|
|
||||||
if (genh.codec == XMA1 || genh.codec == XMA2) {
|
if (genh.codec == XMA1 || genh.codec == XMA2) {
|
||||||
xma_fix_raw_samples(vgmstream, streamFile, genh.start_offset,genh.data_size, 0, 0,0);
|
xma_fix_raw_samples(vgmstream, streamFile, genh.start_offset,genh.data_size, 0, 0,0);
|
||||||
} else if (genh.skip_samples_mode && genh.skip_samples >= 0) { /* force encoder delay */
|
} else if (genh.skip_samples_mode && genh.skip_samples >= 0 && genh.codec != ATRAC3) { /* force encoder delay */
|
||||||
ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples);
|
ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
|
VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
|
||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM * vgmstream = NULL;
|
||||||
STREAMFILE * streamHeader = NULL;
|
STREAMFILE * streamHeader = NULL;
|
||||||
int loop_flag, channel_count;
|
int loop_flag, channel_count, sample_rate, num_samples, loop_start, loop_end;
|
||||||
off_t start_offset, chunk_offset, first_offset;
|
off_t start_offset, chunk_offset, first_offset;
|
||||||
size_t datasize;
|
size_t data_size;
|
||||||
int codec_id;
|
int codec;
|
||||||
|
|
||||||
|
|
||||||
/* checks */
|
/* checks */
|
||||||
@ -19,16 +19,43 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
|
|||||||
streamHeader = open_streamfile_by_ext(streamFile, "gsp");
|
streamHeader = open_streamfile_by_ext(streamFile, "gsp");
|
||||||
if (!streamHeader) goto fail;
|
if (!streamHeader) goto fail;
|
||||||
|
|
||||||
/* check header */
|
|
||||||
if (read_32bitBE(0x00,streamHeader) != 0x47534E44) /* "GSND" */
|
if (read_32bitBE(0x00,streamHeader) != 0x47534E44) /* "GSND" */
|
||||||
goto fail;
|
goto fail;
|
||||||
/* 0x04: version?, 0x08: 1?, 0x0c: 0?, */
|
/* 0x04: version? */
|
||||||
first_offset = read_32bitBE(0x10,streamHeader); /* usually 0x14*/
|
/* 0x08: 1? */
|
||||||
|
/* 0x0c: 0? */
|
||||||
|
first_offset = read_32bitBE(0x10,streamHeader); /* usually 0x14 */
|
||||||
|
|
||||||
|
if (!find_chunk_be(streamHeader, 0x48454144,first_offset,1, &chunk_offset,NULL)) /* "HEAD" */
|
||||||
|
goto fail;
|
||||||
|
/* 0x00: header size */
|
||||||
|
/* 0x04: num_chunks */
|
||||||
|
|
||||||
|
if (!find_chunk_be(streamHeader, 0x44415441,first_offset,1, &chunk_offset,NULL)) /* "DATA" */
|
||||||
|
goto fail;
|
||||||
|
data_size = read_32bitBE(chunk_offset + 0x00,streamHeader);
|
||||||
|
codec = read_32bitBE(chunk_offset + 0x04,streamHeader);
|
||||||
|
sample_rate = read_32bitBE(chunk_offset + 0x08,streamHeader);
|
||||||
|
/* 0x0c: always 16? */
|
||||||
|
channel_count = read_16bitBE(chunk_offset + 0x0e,streamHeader);
|
||||||
|
/* 0x10: always 0? */
|
||||||
|
num_samples = read_32bitBE(chunk_offset + 0x14,streamHeader);
|
||||||
|
/* 0x18: always 0? */
|
||||||
|
/* 0x1c: unk (varies with codec_id) */
|
||||||
|
|
||||||
|
if (!find_chunk_be(streamHeader, 0x42534943,first_offset,1, &chunk_offset,NULL)) /* "BSIC" */
|
||||||
|
goto fail;
|
||||||
|
/* 0x00/0x04: probably volume/pan/etc floats (1.0) */
|
||||||
|
/* 0x08: null? */
|
||||||
|
loop_flag = read_8bit(chunk_offset+0x0c,streamHeader);
|
||||||
|
loop_start = read_32bitBE(chunk_offset+0x10,streamHeader);
|
||||||
|
loop_end = read_32bitBE(chunk_offset+0x14,streamHeader);
|
||||||
|
|
||||||
|
//if (!find_chunk_be(streamHeader, 0x4E414D45,first_offset,1, &chunk_offset,NULL)) /* "NAME" */
|
||||||
|
// goto fail;
|
||||||
|
/* 0x00: name_size */
|
||||||
|
/* 0x04+: name (same as filename) */
|
||||||
|
|
||||||
if (!find_chunk_be(streamHeader, 0x44415441,first_offset,1, &chunk_offset,NULL)) goto fail; /*"DATA"*/
|
|
||||||
channel_count = read_16bitBE(chunk_offset+0x0e,streamHeader);
|
|
||||||
if (!find_chunk_be(streamHeader, 0x42534943,first_offset,1, &chunk_offset,NULL)) goto fail; /*"BSIC"*/
|
|
||||||
loop_flag = read_8bit(chunk_offset+0x0c,streamHeader);
|
|
||||||
|
|
||||||
start_offset = 0x00;
|
start_offset = 0x00;
|
||||||
|
|
||||||
@ -39,27 +66,12 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
|
|||||||
|
|
||||||
vgmstream->meta_type = meta_GSP_GSB;
|
vgmstream->meta_type = meta_GSP_GSB;
|
||||||
|
|
||||||
|
vgmstream->sample_rate = sample_rate;
|
||||||
|
vgmstream->num_samples = num_samples;
|
||||||
|
vgmstream->loop_start_sample = loop_start;
|
||||||
|
vgmstream->loop_end_sample = loop_end;
|
||||||
|
|
||||||
if (!find_chunk_be(streamHeader, 0x48454144,first_offset,1, &chunk_offset,NULL)) goto fail; /*"HEAD"*/
|
switch (codec) {
|
||||||
/* 0x00: header_size, 0x04: num_chunks */
|
|
||||||
|
|
||||||
if (!find_chunk_be(streamHeader, 0x44415441,first_offset,1, &chunk_offset,NULL)) goto fail; /*"DATA"*/
|
|
||||||
/* 0x00: filesize, 0x0c: always 10?, 0x10: always 0?, 0x18: always 0? */
|
|
||||||
datasize = read_32bitBE(chunk_offset+0x00,streamHeader);
|
|
||||||
codec_id = read_32bitBE(chunk_offset+0x04,streamHeader);
|
|
||||||
vgmstream->sample_rate = read_32bitBE(chunk_offset+0x08,streamHeader);
|
|
||||||
vgmstream->num_samples = read_32bitBE(chunk_offset+0x14,streamHeader);
|
|
||||||
/* 0x1c: unk (varies with codec_id) */
|
|
||||||
|
|
||||||
if (!find_chunk_be(streamHeader, 0x42534943,first_offset,1, &chunk_offset,NULL)) goto fail; /*"BSIC"*/
|
|
||||||
/* 0x00+: probably volume/pan/etc */
|
|
||||||
vgmstream->loop_start_sample = read_32bitBE(chunk_offset+0x10,streamHeader);
|
|
||||||
vgmstream->loop_end_sample = read_32bitBE(chunk_offset+0x14,streamHeader);
|
|
||||||
|
|
||||||
//if (!find_chunk_be(streamHeader, 0x4E414D45,first_offset,1, &chunk_offset,NULL)) goto fail; /*"NAME"*/
|
|
||||||
/* 0x00: name_size, 0x04+: name*/
|
|
||||||
|
|
||||||
switch (codec_id) {
|
|
||||||
case 0x04: { /* DSP [Super Swing Golf (Wii)] */
|
case 0x04: { /* DSP [Super Swing Golf (Wii)] */
|
||||||
size_t block_header_size;
|
size_t block_header_size;
|
||||||
size_t num_blocks;
|
size_t num_blocks;
|
||||||
@ -67,12 +79,13 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
|
|||||||
vgmstream->coding_type = coding_NGC_DSP;
|
vgmstream->coding_type = coding_NGC_DSP;
|
||||||
vgmstream->layout_type = layout_blocked_gsb;
|
vgmstream->layout_type = layout_blocked_gsb;
|
||||||
|
|
||||||
if (!find_chunk_be(streamHeader, 0x47434558,first_offset,1, &chunk_offset,NULL)) goto fail; /*"GCEX"*/
|
if (!find_chunk_be(streamHeader, 0x47434558,first_offset,1, &chunk_offset,NULL)) /* "GCEX" */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
//vgmstream->current_block_size = read_32bitBE(chunk_offset+0x00,streamHeader);
|
//vgmstream->current_block_size = read_32bitBE(chunk_offset+0x00,streamHeader);
|
||||||
block_header_size = read_32bitBE(chunk_offset+0x04,streamHeader);
|
block_header_size = read_32bitBE(chunk_offset+0x04,streamHeader);
|
||||||
num_blocks = read_32bitBE(chunk_offset+0x08,streamHeader);
|
num_blocks = read_32bitBE(chunk_offset+0x08,streamHeader);
|
||||||
vgmstream->num_samples = (datasize - block_header_size * num_blocks) / 8 / vgmstream->channels * 14;
|
vgmstream->num_samples = (data_size - block_header_size * num_blocks) / 8 / vgmstream->channels * 14;
|
||||||
/* 0x0c+: unk */
|
/* 0x0c+: unk */
|
||||||
|
|
||||||
dsp_read_coefs_be(vgmstream, streamHeader, chunk_offset+0x18, 0x30);
|
dsp_read_coefs_be(vgmstream, streamHeader, chunk_offset+0x18, 0x30);
|
||||||
@ -80,30 +93,21 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
|
|||||||
}
|
}
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
case 0x08: { /* ATRAC3 [Quantum Theory (PS3)] */
|
case 0x08: { /* ATRAC3 [Quantum Theory (PS3)] */
|
||||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
int block_align, encoder_delay;
|
||||||
uint8_t buf[100];
|
|
||||||
int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples;
|
|
||||||
|
|
||||||
block_size = 0x98 * vgmstream->channels;
|
block_align = 0x98 * vgmstream->channels;
|
||||||
joint_stereo = 0;
|
encoder_delay = 1024 + 69*2; /* observed default, matches XMA (needed as many files start with garbage) */
|
||||||
max_samples = atrac3_bytes_to_samples(datasize, block_size);;
|
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay;
|
||||||
encoder_delay = max_samples - vgmstream->num_samples; /* todo guessed */
|
/* fix num_samples as header samples seem to be modified to match altered (49999/48001) sample rates somehow */
|
||||||
|
|
||||||
vgmstream->num_samples += encoder_delay;
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
/* make a fake riff so FFmpeg can parse the ATRAC3 */
|
if (!vgmstream->codec_data) goto fail;
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf,100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
|
|
||||||
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->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
vgmstream->loop_start_sample = (vgmstream->loop_start_sample / ffmpeg_data->blockAlign) * ffmpeg_data->frameSize;
|
/* set offset samples (offset 0 jumps to sample 0 > pre-applied delay, and offset end loops after sample end > adjusted delay) */
|
||||||
vgmstream->loop_end_sample = (vgmstream->loop_end_sample / ffmpeg_data->blockAlign) * ffmpeg_data->frameSize;
|
vgmstream->loop_start_sample = atrac3_bytes_to_samples(loop_start, block_align); //- encoder_delay
|
||||||
|
vgmstream->loop_end_sample = atrac3_bytes_to_samples(loop_end, block_align) - encoder_delay;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,17 +116,19 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
|
|||||||
uint8_t buf[200];
|
uint8_t buf[200];
|
||||||
int32_t bytes;
|
int32_t bytes;
|
||||||
|
|
||||||
if (!find_chunk_be(streamHeader, 0x584D4558,first_offset,1, &chunk_offset,NULL)) goto fail; /*"XMEX"*/
|
if (!find_chunk_be(streamHeader, 0x584D4558,first_offset,1, &chunk_offset,NULL)) /* "XMEX" */
|
||||||
/* 0x00: fmt0x166 header (BE), 0x34: seek table */
|
goto fail;
|
||||||
|
/* 0x00: fmt0x166 header (BE) */
|
||||||
|
/* 0x34: seek table */
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, chunk_offset,0x34, datasize, streamHeader, 1);
|
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,datasize);
|
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
||||||
if ( !ffmpeg_data ) goto fail;
|
if ( !ffmpeg_data ) goto fail;
|
||||||
vgmstream->codec_data = ffmpeg_data;
|
vgmstream->codec_data = ffmpeg_data;
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
xma_fix_raw_samples(vgmstream, streamFile, start_offset,datasize, 0, 0,0); /* samples are ok */
|
xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); /* samples are ok */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -99,38 +99,27 @@ VGMSTREAM * init_vgmstream_msf(STREAMFILE *streamFile) {
|
|||||||
case 0x04: /* ATRAC3 low (66 kbps, frame size 96, Joint Stereo) [Silent Hill HD (PS3)] */
|
case 0x04: /* ATRAC3 low (66 kbps, frame size 96, Joint Stereo) [Silent Hill HD (PS3)] */
|
||||||
case 0x05: /* ATRAC3 mid (105 kbps, frame size 152) [Atelier Rorona (PS3)] */
|
case 0x05: /* ATRAC3 mid (105 kbps, frame size 152) [Atelier Rorona (PS3)] */
|
||||||
case 0x06: { /* ATRAC3 high (132 kbps, frame size 192) [Tekken Tag Tournament HD (PS3)] */
|
case 0x06: { /* ATRAC3 high (132 kbps, frame size 192) [Tekken Tag Tournament HD (PS3)] */
|
||||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
int block_align, encoder_delay;
|
||||||
uint8_t buf[100];
|
|
||||||
int32_t bytes, block_size, encoder_delay, joint_stereo;
|
|
||||||
|
|
||||||
block_size = (codec==4 ? 0x60 : (codec==5 ? 0x98 : 0xC0)) * vgmstream->channels;
|
|
||||||
joint_stereo = (codec==4); /* interleaved joint stereo (ch must be even) */
|
|
||||||
|
|
||||||
/* MSF skip samples: from tests with MSEnc and real files (ex. TTT2 eddy.msf v43, v01 demos) seems like 1162 is consistent.
|
/* MSF skip samples: from tests with MSEnc and real files (ex. TTT2 eddy.msf v43, v01 demos) seems like 1162 is consistent.
|
||||||
* Atelier Rorona bt_normal01 needs it to properly skip the beginning garbage but usually doesn't matter.
|
* Atelier Rorona bt_normal01 needs it to properly skip the beginning garbage but usually doesn't matter.
|
||||||
* (note that encoder may add a fade-in with looping/resampling enabled but should be skipped) */
|
* (note that encoder may add a fade-in with looping/resampling enabled but should be skipped) */
|
||||||
encoder_delay = 1162;
|
encoder_delay = 1024 + 69*2;
|
||||||
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_size) - encoder_delay;
|
block_align = (codec==4 ? 0x60 : (codec==5 ? 0x98 : 0xC0)) * vgmstream->channels;
|
||||||
|
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay;
|
||||||
if (vgmstream->sample_rate == 0xFFFFFFFF) /* some MSFv1 (Digi World SP) */
|
if (vgmstream->sample_rate == 0xFFFFFFFF) /* some MSFv1 (Digi World SP) */
|
||||||
vgmstream->sample_rate = 44100; /* voice tracks seems to use 44khz, not sure about other tracks */
|
vgmstream->sample_rate = 44100; /* voice tracks seems to use 44khz, not sure about other tracks */
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
if (!vgmstream->codec_data) goto fail;
|
||||||
if (!ffmpeg_data) goto fail;
|
|
||||||
vgmstream->codec_data = ffmpeg_data;
|
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
|
/* MSF loop/sample values are offsets so trickier to adjust but this seems correct */
|
||||||
/* manually set skip_samples if FFmpeg didn't do it */
|
|
||||||
if (ffmpeg_data->skipSamples <= 0) {
|
|
||||||
ffmpeg_set_skip_samples(ffmpeg_data, encoder_delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MSF loop/sample values are offsets so trickier to adjust the skip_samples but this seems correct */
|
|
||||||
if (loop_flag) {
|
if (loop_flag) {
|
||||||
vgmstream->loop_start_sample = atrac3_bytes_to_samples(loop_start, block_size) /* - encoder_delay*/;
|
/* set offset samples (offset 0 jumps to sample 0 > pre-applied delay, and offset end loops after sample end > adjusted delay) */
|
||||||
vgmstream->loop_end_sample = atrac3_bytes_to_samples(loop_end, block_size) - encoder_delay;
|
vgmstream->loop_start_sample = atrac3_bytes_to_samples(loop_start, block_align); //- encoder_delay
|
||||||
|
vgmstream->loop_end_sample = atrac3_bytes_to_samples(loop_end, block_align) - encoder_delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -9,17 +9,19 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
|
|||||||
off_t start_offset, chunk_offset, name_offset = 0;
|
off_t start_offset, chunk_offset, name_offset = 0;
|
||||||
size_t stream_size, chunk_size;
|
size_t stream_size, chunk_size;
|
||||||
int loop_flag = 0, channel_count, is_separate = 0, type, sample_rate;
|
int loop_flag = 0, channel_count, is_separate = 0, type, sample_rate;
|
||||||
int32_t loop_start, loop_end;
|
int32_t num_samples, loop_start;
|
||||||
int total_subsongs, target_subsong = streamFile->stream_index;
|
int total_subsongs, target_subsong = streamFile->stream_index;
|
||||||
|
|
||||||
/* check extensions */
|
/* checks */
|
||||||
/* .xws: header and data, .xwh+xwb: header + data (.bin+dat are also found in Wild Arms 4/5) */
|
/* .xws: header and data
|
||||||
if (!check_extensions(streamFile,"xws,xwb")) goto fail;
|
* .xwh+xwb: header + data (.bin+dat are also found in Wild Arms 4/5) */
|
||||||
|
if (!check_extensions(streamFile,"xws,xwb"))
|
||||||
|
goto fail;
|
||||||
is_separate = check_extensions(streamFile,"xwb");
|
is_separate = check_extensions(streamFile,"xwb");
|
||||||
|
|
||||||
/* xwh+xwb: use xwh as header; otherwise use the current file */
|
/* xwh+xwb: use xwh as header; otherwise use the current file */
|
||||||
if (is_separate) {
|
if (is_separate) {
|
||||||
/* extra check to avoid hijacking Microsoft's XWB */
|
/* extra check to reject Microsoft's XWB faster */
|
||||||
if ((read_32bitBE(0x00,streamFile) == 0x57424E44) || /* "WBND" (LE) */
|
if ((read_32bitBE(0x00,streamFile) == 0x57424E44) || /* "WBND" (LE) */
|
||||||
(read_32bitBE(0x00,streamFile) == 0x444E4257)) /* "DNBW" (BE) */
|
(read_32bitBE(0x00,streamFile) == 0x444E4257)) /* "DNBW" (BE) */
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -62,7 +64,7 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
|
|||||||
channel_count = read_8bit(header_offset+0x09, streamHeader);
|
channel_count = read_8bit(header_offset+0x09, streamHeader);
|
||||||
sample_rate = (uint16_t)read_16bitLE(header_offset+0x0a,streamHeader);
|
sample_rate = (uint16_t)read_16bitLE(header_offset+0x0a,streamHeader);
|
||||||
stream_offset = read_32bitLE(header_offset+0x10,streamHeader);
|
stream_offset = read_32bitLE(header_offset+0x10,streamHeader);
|
||||||
loop_end = read_32bitLE(header_offset+0x14,streamHeader);
|
num_samples = read_32bitLE(header_offset+0x14,streamHeader);
|
||||||
loop_start = read_32bitLE(header_offset+0x18,streamHeader);
|
loop_start = read_32bitLE(header_offset+0x18,streamHeader);
|
||||||
loop_flag = (loop_start != 0xFFFFFFFF);
|
loop_flag = (loop_start != 0xFFFFFFFF);
|
||||||
|
|
||||||
@ -84,7 +86,7 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (target_subsong == total_subsongs) {
|
if (target_subsong == total_subsongs) {
|
||||||
next_stream_offset = data_offset + get_streamfile_size(is_separate ? streamFile : streamHeader);
|
next_stream_offset = get_streamfile_size(is_separate ? streamFile : streamHeader) - data_offset;
|
||||||
} else {
|
} else {
|
||||||
off_t next_header_offset = chunk_offset + 0x4 + 0x1c * (target_subsong);
|
off_t next_header_offset = chunk_offset + 0x4 + 0x1c * (target_subsong);
|
||||||
next_stream_offset = read_32bitLE(next_header_offset+0x10,streamHeader);
|
next_stream_offset = read_32bitLE(next_header_offset+0x10,streamHeader);
|
||||||
@ -120,41 +122,36 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
|
|||||||
vgmstream->layout_type = layout_interleave;
|
vgmstream->layout_type = layout_interleave;
|
||||||
vgmstream->interleave_block_size = 0x10;
|
vgmstream->interleave_block_size = 0x10;
|
||||||
|
|
||||||
vgmstream->num_samples = ps_bytes_to_samples(loop_end, channel_count);
|
vgmstream->num_samples = ps_bytes_to_samples(num_samples, channel_count);
|
||||||
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count);
|
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count);
|
||||||
vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, channel_count);
|
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x01: /* PCM */
|
case 0x01: /* PCM */
|
||||||
vgmstream->coding_type = coding_PCM16LE;
|
vgmstream->coding_type = coding_PCM16LE;
|
||||||
vgmstream->layout_type = channel_count==1 ? layout_none : layout_interleave;
|
vgmstream->layout_type = layout_interleave;
|
||||||
vgmstream->interleave_block_size = 0x2;
|
vgmstream->interleave_block_size = 0x2;
|
||||||
|
|
||||||
vgmstream->num_samples = pcm_bytes_to_samples(loop_end, channel_count, 16);
|
vgmstream->num_samples = pcm_bytes_to_samples(num_samples, channel_count, 16);
|
||||||
vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channel_count, 16);
|
vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channel_count, 16);
|
||||||
vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, channel_count, 16);
|
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
case 0x02: { /* ATRAC3 */
|
case 0x02: { /* ATRAC3 */
|
||||||
uint8_t buf[0x100];
|
int block_align, encoder_delay;
|
||||||
int32_t bytes, block_size, encoder_delay, joint_stereo;
|
|
||||||
|
|
||||||
block_size = 0xc0 * channel_count;
|
block_align = 0xc0 * channel_count;
|
||||||
joint_stereo = 0;
|
encoder_delay = 1024 + 69*2; /* observed default */
|
||||||
encoder_delay = 0x0;
|
vgmstream->num_samples = num_samples - encoder_delay;
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, 0x100, vgmstream->num_samples, stream_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,stream_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
if (bytes <= 0) goto fail;
|
|
||||||
|
|
||||||
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size);
|
|
||||||
if (!vgmstream->codec_data) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
vgmstream->num_samples = loop_end;
|
|
||||||
vgmstream->loop_start_sample = loop_start;
|
vgmstream->loop_start_sample = loop_start;
|
||||||
vgmstream->loop_end_sample = loop_end;
|
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_va3(STREAMFILE *streamFile) {
|
|||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM * vgmstream = NULL;
|
||||||
off_t start_offset;
|
off_t start_offset;
|
||||||
int loop_flag, channel_count;
|
int loop_flag, channel_count;
|
||||||
uint32_t data_size, loop_start, loop_end;
|
uint32_t data_size;
|
||||||
|
|
||||||
/* check extension, case insensitive */
|
/* check extension, case insensitive */
|
||||||
if (!check_extensions(streamFile, "va3"))
|
if (!check_extensions(streamFile, "va3"))
|
||||||
@ -29,41 +29,23 @@ VGMSTREAM * init_vgmstream_va3(STREAMFILE *streamFile) {
|
|||||||
/* build the VGMSTREAM */
|
/* build the VGMSTREAM */
|
||||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||||
if (!vgmstream) goto fail;
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->meta_type = meta_VA3;
|
||||||
vgmstream->sample_rate = read_32bitLE(0x14, streamFile);
|
vgmstream->sample_rate = read_32bitLE(0x14, streamFile);
|
||||||
vgmstream->num_samples = read_32bitLE(0x08, streamFile);
|
vgmstream->num_samples = read_32bitLE(0x08, streamFile);
|
||||||
vgmstream->channels = channel_count;
|
vgmstream->channels = channel_count;
|
||||||
vgmstream->meta_type = meta_VA3;
|
|
||||||
loop_start = 0;
|
|
||||||
loop_end = 0;
|
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
{
|
{
|
||||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
int block_align, encoder_delay;
|
||||||
uint8_t buf[200];
|
|
||||||
int32_t bytes, samples_size = 1024, block_size, encoder_delay, joint_stereo;
|
|
||||||
block_size = 0xC0 * vgmstream->channels;
|
|
||||||
//max_samples = (data_size / block_size) * samples_size;
|
|
||||||
encoder_delay = 0x0;
|
|
||||||
joint_stereo = 0;
|
|
||||||
|
|
||||||
/* make a fake riff so FFmpeg can parse the ATRAC3 */
|
block_align = 0xC0 * vgmstream->channels;
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
|
encoder_delay = 0; //todo
|
||||||
if (bytes <= 0) goto fail;
|
|
||||||
|
|
||||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, data_size);
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
if (!ffmpeg_data) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->codec_data = ffmpeg_data;
|
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
//vgmstream->num_samples = max_samples;
|
|
||||||
|
|
||||||
if (loop_flag) {
|
|
||||||
vgmstream->loop_start_sample = (loop_start / block_size) * samples_size;
|
|
||||||
vgmstream->loop_end_sample = (loop_end / block_size) * samples_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -48,17 +48,13 @@ VGMSTREAM * init_vgmstream_smp(STREAMFILE *streamFile) {
|
|||||||
switch(codec) {
|
switch(codec) {
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
case 0x01: {
|
case 0x01: {
|
||||||
uint8_t buf[0x100];
|
int block_align, encoder_delay;
|
||||||
int bytes, block_size, joint_stereo, skip_samples;
|
|
||||||
|
|
||||||
if (bps != 16) goto fail;
|
if (bps != 16) goto fail;
|
||||||
|
|
||||||
block_size = 0x98 * vgmstream->channels;
|
block_align = 0x98 * vgmstream->channels;
|
||||||
joint_stereo = 0;
|
encoder_delay = 0; /* 1024 looks ok, but num_samples needs to be adjusted too */
|
||||||
skip_samples = 0; /* unknown */
|
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf,sizeof(buf), vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, skip_samples);
|
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_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
|
||||||
if (!vgmstream->codec_data) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
@ -176,30 +176,20 @@ VGMSTREAM * init_vgmstream_ta_aac_ps3(STREAMFILE *streamFile) {
|
|||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
{
|
{
|
||||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
int block_align, encoder_delay;
|
||||||
uint8_t buf[100];
|
|
||||||
int32_t bytes, samples_size = 1024, block_size, encoder_delay, joint_stereo, max_samples;
|
|
||||||
block_size = (codec_id == 4 ? 0x60 : (codec_id == 5 ? 0x98 : 0xC0)) * vgmstream->channels;
|
|
||||||
max_samples = (data_size / block_size) * samples_size;
|
|
||||||
encoder_delay = 0x0;
|
|
||||||
joint_stereo = 0;
|
|
||||||
|
|
||||||
/* make a fake riff so FFmpeg can parse the ATRAC3 */
|
block_align = (codec_id == 4 ? 0x60 : (codec_id == 5 ? 0x98 : 0xC0)) * vgmstream->channels;
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
|
encoder_delay = 1024 + 69; /* approximate, gets good loops */
|
||||||
if (bytes <= 0) goto fail;
|
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay;
|
||||||
|
|
||||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, data_size);
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
if (!ffmpeg_data) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->codec_data = ffmpeg_data;
|
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
vgmstream->num_samples = max_samples;
|
|
||||||
|
|
||||||
if (loop_flag) {
|
|
||||||
vgmstream->loop_start_sample = (loop_start / block_size) * samples_size;
|
|
||||||
vgmstream->loop_end_sample = (loop_end / block_size) * samples_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 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(loop_start, block_align); // - encoder_delay
|
||||||
|
vgmstream->loop_end_sample = atrac3_bytes_to_samples(loop_end, block_align) - encoder_delay;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -432,26 +432,27 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
|
|||||||
int32_t bytes;
|
int32_t bytes;
|
||||||
|
|
||||||
if (txth.codec == ATRAC3) {
|
if (txth.codec == ATRAC3) {
|
||||||
int block_size = txth.interleave;
|
int block_align, encoder_delay;
|
||||||
int joint_stereo;
|
|
||||||
switch(txth.codec_mode) {
|
|
||||||
case 0: joint_stereo = vgmstream->channels > 1 && txth.interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */
|
|
||||||
case 1: joint_stereo = 1; break; /* force joint stereo */
|
|
||||||
case 2: joint_stereo = 0; break; /* force stereo */
|
|
||||||
default: goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, txth.skip_samples);
|
block_align = txth.interleave;
|
||||||
|
encoder_delay = txth.skip_samples;
|
||||||
|
|
||||||
|
ffmpeg_data = init_ffmpeg_atrac3_raw(txth.streamBody, txth.start_offset,txth.data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
|
if (!ffmpeg_data) goto fail;
|
||||||
}
|
}
|
||||||
else if (txth.codec == ATRAC3PLUS) {
|
else if (txth.codec == ATRAC3PLUS) {
|
||||||
int block_size = txth.interleave;
|
int block_size = txth.interleave;
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, txth.skip_samples);
|
bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, txth.skip_samples);
|
||||||
|
ffmpeg_data = init_ffmpeg_header_offset(txth.streamBody, buf,bytes, txth.start_offset,txth.data_size);
|
||||||
|
if ( !ffmpeg_data ) goto fail;
|
||||||
}
|
}
|
||||||
else if (txth.codec == XMA1) {
|
else if (txth.codec == XMA1) {
|
||||||
int xma_stream_mode = txth.codec_mode == 1 ? 1 : 0;
|
int xma_stream_mode = txth.codec_mode == 1 ? 1 : 0;
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
|
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
|
||||||
|
ffmpeg_data = init_ffmpeg_header_offset(txth.streamBody, buf,bytes, txth.start_offset,txth.data_size);
|
||||||
|
if ( !ffmpeg_data ) goto fail;
|
||||||
}
|
}
|
||||||
else if (txth.codec == XMA2) {
|
else if (txth.codec == XMA2) {
|
||||||
int block_count, block_size;
|
int block_count, block_size;
|
||||||
@ -460,13 +461,12 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
|
|||||||
block_count = txth.data_size / block_size;
|
block_count = txth.data_size / block_size;
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
|
bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
|
||||||
|
ffmpeg_data = init_ffmpeg_header_offset(txth.streamBody, buf,bytes, txth.start_offset,txth.data_size);
|
||||||
|
if ( !ffmpeg_data ) goto fail;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ffmpeg_data = init_ffmpeg_header_offset(txth.streamBody, buf,bytes, txth.start_offset,txth.data_size);
|
|
||||||
if ( !ffmpeg_data ) goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vgmstream->codec_data = ffmpeg_data;
|
vgmstream->codec_data = ffmpeg_data;
|
||||||
@ -474,7 +474,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
|
|||||||
|
|
||||||
if (txth.codec == XMA1 || txth.codec == XMA2) {
|
if (txth.codec == XMA1 || txth.codec == XMA2) {
|
||||||
xma_fix_raw_samples(vgmstream, txth.streamBody, txth.start_offset,txth.data_size, 0, 0,0);
|
xma_fix_raw_samples(vgmstream, txth.streamBody, txth.start_offset,txth.data_size, 0, 0,0);
|
||||||
} else if (txth.skip_samples_set) { /* force encoder delay */
|
} else if (txth.skip_samples_set && txth.codec != ATRAC3) { /* force encoder delay */
|
||||||
ffmpeg_set_skip_samples(ffmpeg_data, txth.skip_samples);
|
ffmpeg_set_skip_samples(ffmpeg_data, txth.skip_samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,15 +360,12 @@ static VGMSTREAM * init_vgmstream_ubi_bao_base(ubi_bao_header * bao, STREAMFILE
|
|||||||
|
|
||||||
case RAW_AT3_105:
|
case RAW_AT3_105:
|
||||||
case RAW_AT3: {
|
case RAW_AT3: {
|
||||||
uint8_t buf[0x100];
|
int block_align, encoder_delay;
|
||||||
int32_t bytes, block_size, encoder_delay, joint_stereo;
|
|
||||||
|
|
||||||
block_size = (bao->codec == RAW_AT3_105 ? 0x98 : 0xc0) * vgmstream->channels;
|
block_align = (bao->codec == RAW_AT3_105 ? 0x98 : 0xc0) * vgmstream->channels;
|
||||||
joint_stereo = 0;
|
|
||||||
encoder_delay = 0; /* num_samples is full bytes-to-samples (unlike FMT_AT3) and comparing X360 vs PS3 games seems ok */
|
encoder_delay = 0; /* num_samples is full bytes-to-samples (unlike FMT_AT3) and comparing X360 vs PS3 games seems ok */
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, 0x100, vgmstream->num_samples, vgmstream->stream_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamData, start_offset,vgmstream->stream_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
vgmstream->codec_data = init_ffmpeg_header_offset(streamData, buf, bytes, start_offset, bao->stream_size);
|
|
||||||
if (!vgmstream->codec_data) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
@ -581,18 +581,13 @@ static VGMSTREAM * init_vgmstream_ubi_sb_base(ubi_sb_header *sb, STREAMFILE *str
|
|||||||
}
|
}
|
||||||
|
|
||||||
case RAW_AT3: {
|
case RAW_AT3: {
|
||||||
ffmpeg_codec_data *ffmpeg_data;
|
int block_align, encoder_delay;
|
||||||
uint8_t buf[0x100];
|
|
||||||
int32_t bytes, block_size, encoder_delay, joint_stereo;
|
|
||||||
|
|
||||||
block_size = 0x98 * sb->channels;
|
block_align = 0x98 * sb->channels;
|
||||||
joint_stereo = 0;
|
encoder_delay = 0; /* TODO: this is may be incorrect */
|
||||||
encoder_delay = 0x00; /* TODO: this is may be incorrect */
|
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, 0x100, sb->num_samples, sb->stream_size, sb->channels, sb->sample_rate, block_size, joint_stereo, encoder_delay);
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamData, start_offset,sb->stream_size, sb->num_samples,sb->channels,sb->sample_rate, block_align, encoder_delay);
|
||||||
ffmpeg_data = init_ffmpeg_header_offset(streamData, buf, bytes, start_offset, sb->stream_size);
|
if (!vgmstream->codec_data) goto fail;
|
||||||
if (!ffmpeg_data) goto fail;
|
|
||||||
vgmstream->codec_data = ffmpeg_data;
|
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
break;
|
break;
|
||||||
|
@ -66,34 +66,28 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
|
|||||||
vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile);
|
vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile);
|
||||||
vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile);
|
vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile);
|
||||||
|
|
||||||
|
//todo fix loops/samples vs ATRAC3
|
||||||
/* may be only applying end_skip to num_samples? */
|
/* 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, streamFile, start_offset,data_size, 0, 0,0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 7: { /* ATRAC3 */
|
case 7: { /* ATRAC3 */
|
||||||
uint8_t buf[0x100];
|
int block_align, encoder_delay;
|
||||||
int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples;
|
|
||||||
|
|
||||||
data_size = read_32bitBE(0x54,streamFile);
|
data_size = read_32bitBE(0x54,streamFile);
|
||||||
block_size = 0x98 * vgmstream->channels;
|
block_align = 0x98 * vgmstream->channels;
|
||||||
joint_stereo = 0;
|
encoder_delay = 1024 + 69*2; /* observed default, matches XMA (needed as many files start with garbage) */
|
||||||
max_samples = atrac3_bytes_to_samples(data_size, block_size);
|
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay; /* original samples break looping in some files otherwise */
|
||||||
encoder_delay = 0x0; //max_samples - vgmstream->num_samples; /* todo not correct */
|
|
||||||
vgmstream->num_samples = max_samples; /* use calc samples since loop points are too, breaks looping in some files otherwise */
|
|
||||||
|
|
||||||
/* make a fake riff so FFmpeg can parse the ATRAC3 */
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
|
|
||||||
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
|
||||||
if (!vgmstream->codec_data) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
vgmstream->loop_start_sample = atrac3_bytes_to_samples(read_32bitBE(0x44,streamFile), block_size);
|
/* set offset samples (offset 0 jumps to sample 0 > pre-applied delay, and offset end loops after sample end > adjusted delay) */
|
||||||
vgmstream->loop_end_sample = atrac3_bytes_to_samples(read_32bitBE(0x48,streamFile), block_size);
|
vgmstream->loop_start_sample = atrac3_bytes_to_samples(read_32bitBE(0x44,streamFile), block_align); //- encoder_delay
|
||||||
//vgmstream->loop_start_sample -= encoder_delay;
|
vgmstream->loop_end_sample = atrac3_bytes_to_samples(read_32bitBE(0x48,streamFile), block_align) - encoder_delay;
|
||||||
//vgmstream->loop_end_sample -= encoder_delay;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -528,16 +528,14 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case ATRAC3: { /* Techland PS3 extension [Sniper Ghost Warrior (PS3)] */
|
case ATRAC3: { /* Techland PS3 extension [Sniper Ghost Warrior (PS3)] */
|
||||||
uint8_t buf[0x100];
|
int block_align, encoder_delay;
|
||||||
int bytes;
|
|
||||||
|
|
||||||
int block_size = xwb.block_align * vgmstream->channels;
|
block_align = xwb.block_align * vgmstream->channels;
|
||||||
int joint_stereo = xwb.block_align == 0x60; /* untested, ATRAC3 default */
|
encoder_delay = 1024; /* assumed */
|
||||||
int skip_samples = 0; /* unknown */
|
vgmstream->num_samples -= encoder_delay;
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf,0x100, vgmstream->num_samples, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, skip_samples);
|
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, xwb.stream_offset,xwb.stream_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||||
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, xwb.stream_offset,xwb.stream_size);
|
if (!vgmstream->codec_data) goto fail;
|
||||||
if ( !vgmstream->codec_data ) goto fail;
|
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user