mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-29 00:34:33 +01:00
Add/fix XWMA start and num samples
This commit is contained in:
parent
edd7226ee0
commit
80aad4f15a
@ -612,9 +612,10 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i
|
||||
msd->loop_end_sample = loop_end_frame * samples_per_frame + (msd->loop_end_subframe) * samples_per_subframe;
|
||||
}
|
||||
|
||||
//todo apply once FFmpeg decode is ok (must internal skip 64 samples + apply skips + output extra 128 IMDCT samples) and remove skip_samples output
|
||||
//todo apply once FFmpeg decode is ok
|
||||
// for XMA must internal skip 64 samples + apply skips + output extra 128 IMDCT samples) and remove skip_samples output
|
||||
#if 0
|
||||
{
|
||||
if (msd->xma_version == 1 || msd->xma_version == 2) {
|
||||
msd->num_samples += 128; /* final extra IMDCT samples */
|
||||
msd->num_samples -= start_skip; /* can be less but fixed to 512 in practice */
|
||||
msd->num_samples -= end_skip;
|
||||
@ -630,6 +631,14 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* the above can't properly read skips for WMAPro ATM, but should fixed to 1 frame anyway */
|
||||
if (msd->xma_version == 0) {
|
||||
msd->num_samples -= samples_per_frame; /* FFmpeg does skip this */
|
||||
#if 0
|
||||
msd->num_samples += (samples_per_frame / 2); /* but doesn't add extra samples */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int wma_get_samples_per_frame(int version, int sample_rate, uint32_t decode_flags) {
|
||||
@ -744,6 +753,11 @@ void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_ali
|
||||
}
|
||||
|
||||
msd->num_samples = num_frames * samples_per_frame;
|
||||
|
||||
#if 0 //todo apply once FFmpeg decode is ok
|
||||
msd->num_samples += (samples_per_frame / 2); /* last IMDCT samples */
|
||||
msd->num_samples -= (samples_per_frame * 2); /* WMA default encoder delay */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -456,8 +456,8 @@ static const char* extension_list[] = {
|
||||
"xwb",
|
||||
"xmd",
|
||||
"xwc",
|
||||
"xwm", //FFmpeg, not parsed (XWMA)
|
||||
"xwma", //FFmpeg, not parsed (XWMA)
|
||||
"xwm",
|
||||
"xwma",
|
||||
"xws",
|
||||
"xwv",
|
||||
|
||||
@ -1088,6 +1088,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_NXA, "Entergram NXA header"},
|
||||
{meta_ADPCM_CAPCOM, "Capcom .ADPCM header"},
|
||||
{meta_UE4OPUS, "Epic Games UE4OPUS header"},
|
||||
{meta_XWMA, "Microsoft XWMA RIFF header"},
|
||||
|
||||
};
|
||||
|
||||
|
@ -1609,6 +1609,10 @@
|
||||
<File
|
||||
RelativePath=".\meta\xwc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\xwma.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ydsp.c"
|
||||
|
@ -474,6 +474,7 @@
|
||||
<ClCompile Include="meta\xmd.c" />
|
||||
<ClCompile Include="meta\xwb.c" />
|
||||
<ClCompile Include="meta\xwc.c" />
|
||||
<ClCompile Include="meta\xwma.c" />
|
||||
<ClCompile Include="meta\ydsp.c" />
|
||||
<ClCompile Include="meta\zsd.c" />
|
||||
<ClCompile Include="meta\zwdsp.c" />
|
||||
|
@ -991,6 +991,9 @@
|
||||
<ClCompile Include="meta\xwc.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\xwma.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\ydsp.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -793,4 +793,6 @@ VGMSTREAM * init_vgmstream_adpcm_capcom(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_xwma(STREAMFILE * streamFile);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
87
src/meta/xwma.c
Normal file
87
src/meta/xwma.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* XWMA - Microsoft WMA container [The Elder Scrolls: Skyrim (PC/X360), Hydrophobia (PC)] */
|
||||
VGMSTREAM * init_vgmstream_xwma(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t fmt_offset, data_offset, first_offset = 0xc;
|
||||
size_t fmt_size, data_size;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
|
||||
/* checks */
|
||||
/* .xwma: standard
|
||||
* .xwm: The Elder Scrolls: Skyrim (PC), Blade Arcus from Shining (PC) */
|
||||
if (!check_extensions(streamFile, "xwma,xwm"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x52494646) /* "RIFF" */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x08,streamFile) != 0x58574D41) /* "XWMA" */
|
||||
goto fail;
|
||||
|
||||
if ( !find_chunk_le(streamFile, 0x666d7420,first_offset,0, &fmt_offset,&fmt_size) ) /* "fmt "*/
|
||||
goto fail;
|
||||
if ( !find_chunk_le(streamFile, 0x64617461,first_offset,0, &data_offset,&data_size) ) /* "data"*/
|
||||
goto fail;
|
||||
|
||||
channel_count = read_16bitLE(fmt_offset+0x02,streamFile);
|
||||
loop_flag = 0;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = read_32bitLE(fmt_offset+0x04, streamFile);
|
||||
vgmstream->meta_type = meta_XWMA;
|
||||
|
||||
/* the main purpose of this meta is redoing the XWMA header to:
|
||||
* - redo header to fix XWMA with buggy bit rates so FFmpeg can play them ok
|
||||
* - skip seek table to fix FFmpeg buggy XWMA seeking (see init_seek)
|
||||
* - read num_samples correctly
|
||||
*/
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
{
|
||||
uint8_t buf[0x100];
|
||||
int bytes, avg_bps, block_align, wma_codec;
|
||||
|
||||
avg_bps = read_32bitLE(fmt_offset+0x08, streamFile);
|
||||
block_align = (uint16_t)read_16bitLE(fmt_offset+0x0c, streamFile);
|
||||
wma_codec = (uint16_t)read_16bitLE(fmt_offset+0x00, streamFile);
|
||||
|
||||
bytes = ffmpeg_make_riff_xwma(buf,0x100, wma_codec, data_size, vgmstream->channels, vgmstream->sample_rate, avg_bps, block_align);
|
||||
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, data_offset,data_size);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
/* manually find total samples, why don't they put this in the header is beyond me */
|
||||
{
|
||||
ms_sample_data msd = {0};
|
||||
|
||||
msd.channels = vgmstream->channels;
|
||||
msd.data_offset = data_offset;
|
||||
msd.data_size = data_size;
|
||||
|
||||
if (wma_codec == 0x0162)
|
||||
wmapro_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x00E0);
|
||||
else
|
||||
wma_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x001F);
|
||||
|
||||
vgmstream->num_samples = msd.num_samples;
|
||||
if (vgmstream->num_samples == 0)
|
||||
vgmstream->num_samples = (int32_t)((ffmpeg_codec_data*)vgmstream->codec_data)->totalSamples; /* from avg-br */
|
||||
//num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2
|
||||
}
|
||||
}
|
||||
#else
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -441,6 +441,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_utk,
|
||||
init_vgmstream_adpcm_capcom,
|
||||
init_vgmstream_ue4opus,
|
||||
init_vgmstream_xwma,
|
||||
|
||||
|
||||
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
|
||||
|
@ -698,6 +698,7 @@ typedef enum {
|
||||
meta_NXA,
|
||||
meta_ADPCM_CAPCOM,
|
||||
meta_UE4OPUS,
|
||||
meta_XWMA,
|
||||
|
||||
} meta_t;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user