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;
|
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 0
|
||||||
{
|
if (msd->xma_version == 1 || msd->xma_version == 2) {
|
||||||
msd->num_samples += 128; /* final extra IMDCT samples */
|
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 -= start_skip; /* can be less but fixed to 512 in practice */
|
||||||
msd->num_samples -= end_skip;
|
msd->num_samples -= end_skip;
|
||||||
@ -630,6 +631,14 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
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;
|
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",
|
"xwb",
|
||||||
"xmd",
|
"xmd",
|
||||||
"xwc",
|
"xwc",
|
||||||
"xwm", //FFmpeg, not parsed (XWMA)
|
"xwm",
|
||||||
"xwma", //FFmpeg, not parsed (XWMA)
|
"xwma",
|
||||||
"xws",
|
"xws",
|
||||||
"xwv",
|
"xwv",
|
||||||
|
|
||||||
@ -1088,6 +1088,7 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_NXA, "Entergram NXA header"},
|
{meta_NXA, "Entergram NXA header"},
|
||||||
{meta_ADPCM_CAPCOM, "Capcom .ADPCM header"},
|
{meta_ADPCM_CAPCOM, "Capcom .ADPCM header"},
|
||||||
{meta_UE4OPUS, "Epic Games UE4OPUS header"},
|
{meta_UE4OPUS, "Epic Games UE4OPUS header"},
|
||||||
|
{meta_XWMA, "Microsoft XWMA RIFF header"},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1609,6 +1609,10 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\meta\xwc.c"
|
RelativePath=".\meta\xwc.c"
|
||||||
>
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\meta\xwma.c"
|
||||||
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\meta\ydsp.c"
|
RelativePath=".\meta\ydsp.c"
|
||||||
|
@ -474,6 +474,7 @@
|
|||||||
<ClCompile Include="meta\xmd.c" />
|
<ClCompile Include="meta\xmd.c" />
|
||||||
<ClCompile Include="meta\xwb.c" />
|
<ClCompile Include="meta\xwb.c" />
|
||||||
<ClCompile Include="meta\xwc.c" />
|
<ClCompile Include="meta\xwc.c" />
|
||||||
|
<ClCompile Include="meta\xwma.c" />
|
||||||
<ClCompile Include="meta\ydsp.c" />
|
<ClCompile Include="meta\ydsp.c" />
|
||||||
<ClCompile Include="meta\zsd.c" />
|
<ClCompile Include="meta\zsd.c" />
|
||||||
<ClCompile Include="meta\zwdsp.c" />
|
<ClCompile Include="meta\zwdsp.c" />
|
||||||
|
@ -991,6 +991,9 @@
|
|||||||
<ClCompile Include="meta\xwc.c">
|
<ClCompile Include="meta\xwc.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="meta\xwma.c">
|
||||||
|
<Filter>meta\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="meta\ydsp.c">
|
<ClCompile Include="meta\ydsp.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -793,4 +793,6 @@ VGMSTREAM * init_vgmstream_adpcm_capcom(STREAMFILE *streamFile);
|
|||||||
|
|
||||||
VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile);
|
VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_xwma(STREAMFILE * streamFile);
|
||||||
|
|
||||||
#endif /*_META_H*/
|
#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_utk,
|
||||||
init_vgmstream_adpcm_capcom,
|
init_vgmstream_adpcm_capcom,
|
||||||
init_vgmstream_ue4opus,
|
init_vgmstream_ue4opus,
|
||||||
|
init_vgmstream_xwma,
|
||||||
|
|
||||||
|
|
||||||
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
|
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
|
||||||
|
@ -698,6 +698,7 @@ typedef enum {
|
|||||||
meta_NXA,
|
meta_NXA,
|
||||||
meta_ADPCM_CAPCOM,
|
meta_ADPCM_CAPCOM,
|
||||||
meta_UE4OPUS,
|
meta_UE4OPUS,
|
||||||
|
meta_XWMA,
|
||||||
|
|
||||||
} meta_t;
|
} meta_t;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user