cleanup: riff helpers

This commit is contained in:
bnnm 2023-01-21 22:08:46 +01:00
parent 8e39b511eb
commit af71e611c1
7 changed files with 222 additions and 228 deletions

View File

@ -619,10 +619,12 @@ STREAMFILE* ffmpeg_get_streamfile(ffmpeg_codec_data* data);
/* ffmpeg_decoder_utils.c (helper-things) */
ffmpeg_codec_data* init_ffmpeg_atrac3_raw(STREAMFILE* sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay);
ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* out_samples);
ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size, int skip_samples);
ffmpeg_codec_data* init_ffmpeg_xwma(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int format, int channels, int sample_rate, int avg_bitrate, int block_size);
//TODO: make init_ffmpeg_xwma_fmt(be) too to pass fmt chunk
ffmpeg_codec_data* init_ffmpeg_atrac3plus_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int32_t sample_count, int channels, int sample_rate, int block_align, int encoder_delay);
ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size, int skip_samples);
ffmpeg_codec_data* init_ffmpeg_xwma(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int format, int channels, int sample_rate, int avg_bitrate, int block_size);
//TODO: make init_ffmpeg_xwma_fmt(be) too to pass fmt chunk?
ffmpeg_codec_data* init_ffmpeg_xma1_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int channels, int sample_rate, int stream_mode);
ffmpeg_codec_data* init_ffmpeg_xma2_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int32_t sample_count, int channels, int sample_rate, int block_size, int block_count);
ffmpeg_codec_data* init_ffmpeg_xma_chunk(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, uint32_t chunk_offset, uint32_t chunk_size);
@ -683,10 +685,6 @@ ffmpeg_codec_data* init_ffmpeg_mp4_custom_lyn(STREAMFILE* sf, mp4_custom_t* mp4)
#endif
/* coding_utils */
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_xwma(uint8_t* buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align);
/* MS audio format's sample info (struct to avoid passing so much stuff, separate for reusing) */
typedef struct {
/* input */

View File

@ -5,20 +5,14 @@
/**
* 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 */
/* XMA PARSING */
/* ******************************************** */
/**
* read num_bits (up to 25) from a bit offset.
* 25 since we read a 32 bit int, and need to adjust up to 7 bits from the byte-rounded fseek (32-7=25)
*/
/* read num_bits (up to 25) from a bit offset.
* 25 since we read a 32 bit int, and need to adjust up to 7 bits from the byte-rounded fseek (32-7=25) */
static uint32_t read_bitsBE_b(int64_t bit_offset, int num_bits, STREAMFILE* sf) {
uint32_t num, mask;
if (num_bits > 25) return -1; //???
@ -32,117 +26,6 @@ static uint32_t read_bitsBE_b(int64_t bit_offset, int num_bits, STREAMFILE* sf)
}
/* ******************************************** */
/* FAKE RIFF HELPERS */
/* ******************************************** */
/* 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_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 */
size_t riff_size = 4+4+ 4 + 0x3c + 0x14 + 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, 0x34);/*fmt size*/
put_16bitLE(buf+0x14, codec_ATRAC3plus);
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, 0x22); /* extra data size */
put_16bitLE(buf+0x26, 0x0800); /* samples per block */
put_32bitLE(buf+0x28, 0x0000003); /* unknown */
put_32bitBE(buf+0x2c, 0xBFAA23E9); /* GUID1 */
put_32bitBE(buf+0x30, 0x58CB7144); /* GUID2 */
put_32bitBE(buf+0x34, 0xA119FFFA); /* GUID3 */
put_32bitBE(buf+0x38, 0x01E4CE62); /* GUID4 */
put_16bitBE(buf+0x3c, 0x0010); /* unknown */
put_16bitBE(buf+0x3e, 0x0000); /* config */ //todo this varies with block size, but FFmpeg doesn't use it
put_32bitBE(buf+0x40, 0x00000000); /* empty */
put_32bitBE(buf+0x44, 0x00000000); /* empty */
memcpy(buf+0x48, "fact", 4);
put_32bitLE(buf+0x4c, 0x0c); /* fact size */
put_32bitLE(buf+0x50, sample_count);
put_32bitLE(buf+0x54, 0); /* unknown */
put_32bitLE(buf+0x58, encoder_delay);
memcpy(buf+0x5c, "data", 4);
put_32bitLE(buf+0x60, data_size); /* data size */
return riff_size;
}
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) {
size_t riff_size = 4+4+ 4 + 0x1a + 4+4;
if (buf_size < riff_size)
return -1;
/* XWMA encoder only allows a few channel/sample rate/bitrate combinations,
* but some create identical files with fake bitrate (1ch 22050hz at
* 20/48/192kbps are all 20kbps, with the exact same codec data).
* Decoder needs correct bitrate to work, so it's normalized here. */
/* (may be removed once FFmpeg fixes this) */
if (codec == 0x161) { /* WMAv2 only */
int ch = channels;
int sr = sample_rate;
int br = avg_bps * 8;
/* Must be a bug in MS's encoder, as later versions of xWMAEncode remove these bitrates */
if (ch == 1) {
if (sr == 22050 && (br==48000 || br==192000))
br = 20000;
else if (sr == 32000 && (br==48000 || br==192000))
br = 20000;
else if (sr == 44100 && (br==96000 || br==192000))
br = 48000;
}
else if (ch == 2) {
if (sr == 22050 && (br==48000 || br==192000))
br = 32000;
else if (sr == 32000 && (br==192000))
br = 48000;
}
avg_bps = br / 8;
}
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "XWMA", 4);
memcpy(buf+0x0c, "fmt ", 4);
put_32bitLE(buf+0x10, 0x12);/*fmt size*/
put_16bitLE(buf+0x14, codec);
put_16bitLE(buf+0x16, channels);
put_32bitLE(buf+0x18, sample_rate);
put_32bitLE(buf+0x1c, avg_bps); /* average bytes per second, somehow vital for XWMA */
put_16bitLE(buf+0x20, block_align); /* block align */
put_16bitLE(buf+0x22, 16); /* bits per sample */
put_16bitLE(buf+0x24, 0); /* extra size */
/* here goes the "dpds" seek table, but it's optional and not needed by FFmpeg (and also buggy) */
memcpy(buf+0x26, "data", 4);
put_32bitLE(buf+0x2a, data_size); /* data size */
return riff_size;
}
/* ******************************************** */
/* XMA PARSING */
/* ******************************************** */
static void ms_audio_parse_header(STREAMFILE* sf, int xma_version, int64_t offset_b, int bits_frame_size, size_t *first_frame_b, size_t *packet_skip_count, size_t *header_size_b) {
if (xma_version == 1) { /* XMA1 */

View File

@ -2,9 +2,12 @@
#ifdef VGM_USE_FFMPEG
/* Helper inits for FFmpeg's codecs. RIFF utils make headers for FFmpeg (it doesn't understand all valid RIFF headers,
* nor the utils make 100% correct headers). */
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) {
int buf_max = (0x04 * 2 + 0x4) + (0x04 * 2 + 0x20) + (0x04 * 2 + 0x08) + (0x04 * 2);
int buf_max = (0x04 * 2 + 0x04) + (0x04 * 2 + 0x20) + (0x04 * 2 + 0x08) + (0x04 * 2);
if (buf_max > buf_size)
return 0;
@ -182,6 +185,80 @@ fail:
return NULL;
}
static int ffmpeg_make_riff_atrac3plus(uint8_t* buf, int buf_size, uint32_t data_size, int32_t sample_count, int channels, int sample_rate, int block_align, int encoder_delay) {
int buf_max = (0x04 * 2 + 0x04) + (0x04 * 2 + 0x34) + (0x04 * 2 + 0x0c) + (0x04 * 2);
if (buf_max > buf_size)
return 0;
/* standard */
int channel_layout = 0;
switch(channels) {
case 1: channel_layout = mapping_MONO; break;
case 2: channel_layout = mapping_STEREO; break;
case 3: channel_layout = mapping_2POINT1; break;
case 4: channel_layout = mapping_QUAD; break;
case 5: channel_layout = mapping_5POINT0; break;
case 6: channel_layout = mapping_5POINT1; break;
default: break;
}
memcpy (buf+0x00, "RIFF", 0x04);
put_u32le(buf+0x04, buf_max - (0x04 * 2) + data_size);
memcpy (buf+0x08, "WAVE", 0x04);
memcpy (buf+0x0c, "fmt ", 0x04);
put_u32le(buf+0x10, 0x34);
put_u16le(buf+0x14, 0xfffe); /* WAVEFORMATEXTENSIBLE */
put_u16le(buf+0x16, channels);
put_u32le(buf+0x18, sample_rate);
put_u32le(buf+0x1c, sample_rate * channels / sizeof(sample)); /* average bytes per second (wrong) */
put_u32le(buf+0x20, block_align); /* block align */
put_u16le(buf+0x24, 0x22); /* extra data size */
put_u16le(buf+0x26, 0x0800); /* samples per block */
put_u32le(buf+0x28, channel_layout);
put_u32be(buf+0x2c, 0xBFAA23E9); /* GUID1 */
put_u32be(buf+0x30, 0x58CB7144); /* GUID2 */
put_u32be(buf+0x34, 0xA119FFFA); /* GUID3 */
put_u32be(buf+0x38, 0x01E4CE62); /* GUID4 */
put_u16be(buf+0x3c, 0x0010); /* unknown */
put_u16be(buf+0x3e, 0x0000); /* unknown, atrac3plus config (varies with block size, FFmpeg doesn't use it) */
put_u32be(buf+0x40, 0x00000000); /* reserved? */
put_u32be(buf+0x44, 0x00000000); /* reserved? */
memcpy (buf+0x48, "fact", 0x04);
put_u32le(buf+0x4c, 0x0c); /* fact size */
put_u32le(buf+0x50, sample_count);
put_u32le(buf+0x54, 0); /* unknown */
put_u32le(buf+0x58, encoder_delay);
memcpy (buf+0x5c, "data", 0x04);
put_u32le(buf+0x60, data_size); /* data size */
return buf_max;
}
ffmpeg_codec_data* init_ffmpeg_atrac3plus_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int32_t sample_count, int channels, int sample_rate, int block_align, int encoder_delay) {
ffmpeg_codec_data* data = NULL;
uint8_t buf[0x100];
int bytes;
bytes = ffmpeg_make_riff_atrac3plus(buf,sizeof(buf), data_size, sample_count, channels, sample_rate, block_align, encoder_delay);
data = init_ffmpeg_header_offset(sf, buf, bytes, data_offset, data_size);
if (!data) goto fail;
ffmpeg_set_skip_samples(data, encoder_delay);
return data;
fail:
free_ffmpeg(data);
return NULL;
}
ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size, int skip_samples) {
ffmpeg_codec_data* data = NULL;
@ -202,12 +279,69 @@ fail:
return NULL;
}
static int ffmpeg_make_riff_xwma(uint8_t* buf, size_t buf_size, uint32_t data_size, int format, int channels, int sample_rate, int avg_bps, int block_align) {
int buf_max = (0x04 * 2 + 0x04) + (0x04 * 2 + 0x12) + (0x04 * 2);
if (buf_max > buf_size)
return 0;
/* XWMA encoder only allows a few channel/sample rate/bitrate combinations,
* but some create identical files with fake bitrate (1ch 22050hz at
* 20/48/192kbps are all 20kbps, with the exact same codec data).
* Decoder needs correct bitrate to work, so it's normalized here. */
/* (may be removed once FFmpeg fixes this) */
if (format == 0x161) { /* WMAv2 only */
int ch = channels;
int sr = sample_rate;
int br = avg_bps * 8;
/* Must be a bug in MS's encoder, as later versions of xWMAEncode remove these bitrates */
if (ch == 1) {
if (sr == 22050 && (br==48000 || br==192000)) {
br = 20000;
}
else if (sr == 32000 && (br==48000 || br==192000))
br = 20000;
else if (sr == 44100 && (br==96000 || br==192000))
br = 48000;
}
else if (ch == 2) {
if (sr == 22050 && (br==48000 || br==192000))
br = 32000;
else if (sr == 32000 && (br==192000))
br = 48000;
}
avg_bps = br / 8;
}
memcpy (buf+0x00, "RIFF", 0x04);
put_u32le(buf+0x04, buf_max - (0x04 * 2) + data_size); /* riff size */
memcpy (buf+0x08, "XWMA", 0x04);
memcpy (buf+0x0c, "fmt ", 0x04);
put_u32le(buf+0x10, 0x12); /* fmt size */
put_u16le(buf+0x14, format);
put_u16le(buf+0x16, channels);
put_u32le(buf+0x18, sample_rate);
put_u32le(buf+0x1c, avg_bps); /* average bytes per second, somehow vital for XWMA */
put_u16le(buf+0x20, block_align); /* block align */
put_u16le(buf+0x22, 16); /* bits per sample */
put_u16le(buf+0x24, 0); /* extra size */
/* here goes the "dpds" seek table, but it's optional and not needed by FFmpeg (and also buggy) */
memcpy (buf+0x26, "data", 4);
put_u32le(buf+0x2a, data_size);
return buf_max;
}
ffmpeg_codec_data* init_ffmpeg_xwma(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int format, int channels, int sample_rate, int avg_bitrate, int block_size) {
ffmpeg_codec_data* data = NULL;
uint8_t buf[0x100];
int bytes;
bytes = ffmpeg_make_riff_xwma(buf, sizeof(buf), format, data_size, channels, sample_rate, avg_bitrate, block_size);
bytes = ffmpeg_make_riff_xwma(buf, sizeof(buf), data_size, format, channels, sample_rate, avg_bitrate, block_size);
data = init_ffmpeg_header_offset(sf, buf,bytes, data_offset, data_size);
if (!data) goto fail;

View File

@ -309,42 +309,35 @@ VGMSTREAM* init_vgmstream_genh(STREAMFILE *sf) {
//if (vgmstream->num_samples == 0)
// vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data); /* sometimes works */
}
else if (genh.codec == ATRAC3) {
int block_align, encoder_delay;
block_align = genh.interleave;
encoder_delay = genh.skip_samples;
ffmpeg_data = init_ffmpeg_atrac3_raw(sf, 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) {
int block_size = genh.interleave;
ffmpeg_data = init_ffmpeg_atrac3plus_raw(sf, genh.start_offset, genh.data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, genh.skip_samples);
if (!ffmpeg_data) goto fail;
}
else if (genh.codec == XMA1) {
int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0;
ffmpeg_data = init_ffmpeg_xma1_raw(sf, genh.start_offset, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
if (!ffmpeg_data) goto fail;
}
else if (genh.codec == XMA2) {
int block_size = genh.interleave;
ffmpeg_data = init_ffmpeg_xma2_raw(sf, genh.start_offset, genh.data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0);
if (!ffmpeg_data) goto fail;
}
else {
/* fake header FFmpeg */
uint8_t buf[200];
int32_t bytes;
if (genh.codec == ATRAC3) {
int block_align, encoder_delay;
block_align = genh.interleave;
encoder_delay = genh.skip_samples;
ffmpeg_data = init_ffmpeg_atrac3_raw(sf, 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) {
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);
ffmpeg_data = init_ffmpeg_header_offset(sf, buf,bytes, genh.start_offset,genh.data_size);
if ( !ffmpeg_data ) goto fail;
}
else if (genh.codec == XMA1) {
int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0;
ffmpeg_data = init_ffmpeg_xma1_raw(sf, genh.start_offset, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
if (!ffmpeg_data) goto fail;
}
else if (genh.codec == XMA2) {
int block_size = genh.interleave;
ffmpeg_data = init_ffmpeg_xma2_raw(sf, genh.start_offset, genh.data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0);
if (!ffmpeg_data) goto fail;
}
else {
goto fail;
}
goto fail;
}
vgmstream->codec_data = ffmpeg_data;

View File

@ -550,42 +550,35 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
ffmpeg_data = init_ffmpeg_aac(txth.sf_body, txth.start_offset, txth.data_size, 0);
if (!ffmpeg_data) goto fail;
}
else if (txth.codec == ATRAC3) {
int block_align, encoder_delay;
block_align = txth.interleave;
encoder_delay = txth.skip_samples;
ffmpeg_data = init_ffmpeg_atrac3_raw(txth.sf_body, 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) {
int block_size = txth.interleave;
ffmpeg_data = init_ffmpeg_atrac3plus_raw(txth.sf_body, txth.start_offset, txth.data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, txth.skip_samples);
if (!ffmpeg_data) goto fail;
}
else if (txth.codec == XMA1) {
int xma_stream_mode = txth.codec_mode == 1 ? 1 : 0;
ffmpeg_data = init_ffmpeg_xma1_raw(txth.sf_body, txth.start_offset, txth.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
if (!ffmpeg_data) goto fail;
}
else if (txth.codec == XMA2) {
int block_size = txth.interleave;
ffmpeg_data = init_ffmpeg_xma2_raw(sf, txth.start_offset, txth.data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0);
if (!ffmpeg_data) goto fail;
}
else {
/* fake header FFmpeg */
uint8_t buf[0x100];
int32_t bytes;
if (txth.codec == ATRAC3) {
int block_align, encoder_delay;
block_align = txth.interleave;
encoder_delay = txth.skip_samples;
ffmpeg_data = init_ffmpeg_atrac3_raw(txth.sf_body, 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) {
int block_size = txth.interleave;
bytes = ffmpeg_make_riff_atrac3plus(buf, sizeof(buf), vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, txth.skip_samples);
ffmpeg_data = init_ffmpeg_header_offset(txth.sf_body, buf,bytes, txth.start_offset,txth.data_size);
if ( !ffmpeg_data ) goto fail;
}
else if (txth.codec == XMA1) {
int xma_stream_mode = txth.codec_mode == 1 ? 1 : 0;
ffmpeg_data = init_ffmpeg_xma1_raw(txth.sf_body, txth.start_offset, txth.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
if (!ffmpeg_data) goto fail;
}
else if (txth.codec == XMA2) {
int block_size = txth.interleave;
ffmpeg_data = init_ffmpeg_xma2_raw(sf, txth.start_offset, txth.data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0);
if (!ffmpeg_data) goto fail;
}
else {
goto fail;
}
goto fail;
}
vgmstream->codec_data = ffmpeg_data;
@ -593,7 +586,7 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
if (txth.codec == XMA1 || txth.codec == XMA2) {
xma_fix_raw_samples(vgmstream, txth.sf_body, txth.start_offset,txth.data_size, 0, 0,0);
} else if (txth.skip_samples_set && txth.codec != ATRAC3) { /* force encoder delay */
} else if (txth.skip_samples_set && txth.codec != ATRAC3 && txth.codec != ATRAC3PLUS) { /* force encoder delay */
ffmpeg_set_skip_samples(ffmpeg_data, txth.skip_samples);
}

View File

@ -528,8 +528,7 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) {
}
case XWMA: { /* WMAudio2 (WMA v2): BlazBlue (X360), WMAudio3 (WMA Pro): Bullet Witch (PC) voices */
uint8_t buf[0x100];
int bytes, bps_index, block_align, block_index, avg_bps, wma_codec;
int bps_index, block_align, block_index, avg_bps, wma_codec;
bps_index = (xwb.block_align >> 5); /* upper 3b bytes-per-second index (docs say 2b+6b but are wrong) */
block_index = (xwb.block_align) & 0x1F; /*lower 5b block alignment index */
@ -540,8 +539,7 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) {
block_align = wma_block_align_index[block_index];
wma_codec = xwb.bits_per_sample ? 0x162 : 0x161; /* 0=WMAudio2, 1=WMAudio3 */
bytes = ffmpeg_make_riff_xwma(buf, sizeof(buf), wma_codec, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, avg_bps, block_align);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, xwb.stream_offset,xwb.stream_size);
vgmstream->codec_data = init_ffmpeg_xwma(sf, xwb.stream_offset, xwb.stream_size, wma_codec, vgmstream->channels, vgmstream->sample_rate, avg_bps, block_align);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -4,30 +4,30 @@
/* MSFC - Konami (Armature?) variation [Metal Gear Solid 2 HD (X360), Metal Gear Solid 3 HD (X360)] */
VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_xwma_konami(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, codec, sample_rate;
int loop_flag, channels, codec, sample_rate;
size_t data_size;
STREAMFILE *temp_streamFile = NULL;
STREAMFILE *temp_sf = NULL;
/* checks */
if (!check_extensions(streamFile,"xwma"))
if (!is_id32be(0x00,sf, "XWMA"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x58574D41) /* "XWMA" */
if (!check_extensions(sf,"xwma"))
goto fail;
codec = read_32bitBE(0x04,streamFile);
channel_count = read_32bitBE(0x08,streamFile);
sample_rate = read_32bitBE(0x0c,streamFile);
data_size = read_32bitBE(0x10,streamFile); /* data size without padding */
codec = read_32bitBE(0x04,sf);
channels = read_32bitBE(0x08,sf);
sample_rate = read_32bitBE(0x0c,sf);
data_size = read_32bitBE(0x10,sf); /* data size without padding */
loop_flag = 0;
start_offset = 0x20;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
@ -35,19 +35,15 @@ VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[0x100];
int bytes, avg_bps, block_align;
/* 0x10: related to size? */
avg_bps = read_32bitBE(0x14, streamFile);
block_align = read_32bitBE(0x18, streamFile);
int avg_bps = read_32bitBE(0x14, sf);
int block_align = read_32bitBE(0x18, sf);
/* data has padding (unrelated to KCEJ blocks) */
temp_streamFile = setup_xwma_konami_streamfile(streamFile, start_offset, block_align);
if (!temp_streamFile) goto fail;
temp_sf = setup_xwma_konami_streamfile(sf, start_offset, block_align);
if (!temp_sf) goto fail;
bytes = ffmpeg_make_riff_xwma(buf,0x100, codec, data_size, channel_count, sample_rate, avg_bps, block_align);
vgmstream->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, 0x00,data_size);
vgmstream->codec_data = init_ffmpeg_xwma(temp_sf, 0x00, data_size, codec, channels, sample_rate, avg_bps, block_align);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -62,7 +58,7 @@ VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) {
if (codec == 0x0161)
wma_get_samples(&msd, temp_streamFile, block_align, vgmstream->sample_rate,0x001F);
wma_get_samples(&msd, temp_sf, block_align, vgmstream->sample_rate,0x001F);
//else //todo not correct
// wmapro_get_samples(&msd, temp_streamFile, block_align, vgmstream->sample_rate,0x00E0);
@ -76,11 +72,10 @@ VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) {
goto fail;
#endif
close_streamfile(temp_streamFile);
close_streamfile(temp_sf);
return vgmstream;
fail:
close_streamfile(temp_streamFile);
close_streamfile(temp_sf);
close_vgmstream(vgmstream);
return NULL;
}