mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-13 18:20:50 +01:00
Fix some XMA .awc [Red Dead Redemption (X360)]
This commit is contained in:
parent
2efdcb651f
commit
4ae8549e50
@ -335,7 +335,7 @@ static int parse_awc_header(STREAMFILE* sf, awc_header* awc) {
|
|||||||
awc->total_subsongs = 1;
|
awc->total_subsongs = 1;
|
||||||
target_subsong = 1;
|
target_subsong = 1;
|
||||||
/* array access below */
|
/* array access below */
|
||||||
if (entries >= AWC_MAX_MUSIC_CHANNELS)
|
if (entries > AWC_MAX_MUSIC_CHANNELS)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
else { /* sfx pack, each stream is a sound */
|
else { /* sfx pack, each stream is a sound */
|
||||||
|
@ -67,7 +67,7 @@ typedef struct {
|
|||||||
* 0xNN: may have padding between channels depending on codec (mainly MPEG/XMA)
|
* 0xNN: may have padding between channels depending on codec (mainly MPEG/XMA)
|
||||||
* - padding until this block's end
|
* - padding until this block's end
|
||||||
*/
|
*/
|
||||||
static bool read_awb_block(STREAMFILE* sf, awc_block_info_t* bi) {
|
static bool read_awc_block(STREAMFILE* sf, awc_block_info_t* bi) {
|
||||||
read_s32_t read_s32 = bi->big_endian ? read_s32be : read_s32le;
|
read_s32_t read_s32 = bi->big_endian ? read_s32be : read_s32le;
|
||||||
read_u16_t read_u16 = bi->big_endian ? read_u16be : read_u16le;
|
read_u16_t read_u16 = bi->big_endian ? read_u16be : read_u16le;
|
||||||
|
|
||||||
@ -167,34 +167,9 @@ static uint32_t get_block_repeated_size(STREAMFILE* sf, awc_block_info_t* bi, in
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch(bi->codec) {
|
switch(bi->codec) {
|
||||||
case 0x05: { /* XMA2 */
|
case 0x05: /* XMA2 */
|
||||||
const uint32_t samples_per_subframe = 512;
|
|
||||||
uint32_t samples_this_frame;
|
|
||||||
uint8_t subframes;
|
|
||||||
uint32_t offset = bi->block_offset + bi->blk[channel].chunk_start;
|
|
||||||
int repeat_samples = bi->blk[channel].channel_skip;
|
|
||||||
|
|
||||||
//TODO: fix (needs proper decoder + sample discard)
|
|
||||||
/* Repeat samples are the number of decoded samples to discard, but in this streamfile we can't do that.
|
|
||||||
* Also XMA is VBR, and may encode silent frames with up to 63 subframes yet we may have few repeat samples.
|
|
||||||
* We could find out how many subframes of 512 samples to skip, then adjust the XMA frame header, though
|
|
||||||
* output will be slightly off since subframes are related.
|
|
||||||
*
|
|
||||||
* For now just skip a full frame depending on the number of subframes vs repeat samples.
|
|
||||||
* Most files work ok-ish but channels may desync slightly. */
|
|
||||||
|
|
||||||
subframes = (read_u8(offset,sf) >> 2) & 0x3F; /* peek into frame header */
|
|
||||||
samples_this_frame = subframes * samples_per_subframe;
|
|
||||||
if (repeat_samples >= (int)(samples_this_frame * 0.13)) { /* skip mosts */
|
|
||||||
return bi->blk[channel].frame_size;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x08: /* Vorbis */
|
case 0x08: /* Vorbis */
|
||||||
/* when data repeats seems to clone exactly the last super-frame */
|
/* when data repeats seems to clone the last (super-)frame */
|
||||||
return bi->blk[channel].frame_size;
|
return bi->blk[channel].frame_size;
|
||||||
|
|
||||||
case 0x0F: /* ATRAC9 */
|
case 0x0F: /* ATRAC9 */
|
||||||
@ -215,7 +190,7 @@ static void block_callback(STREAMFILE *sf, deblock_io_data* data) {
|
|||||||
bi.channels = data->cfg.track_count;
|
bi.channels = data->cfg.track_count;
|
||||||
bi.codec = data->cfg.track_type;
|
bi.codec = data->cfg.track_type;
|
||||||
|
|
||||||
if (!read_awb_block(sf, &bi))
|
if (!read_awc_block(sf, &bi))
|
||||||
return; //???
|
return; //???
|
||||||
|
|
||||||
uint32_t repeat_size = get_block_repeated_size(sf, &bi, channel);
|
uint32_t repeat_size = get_block_repeated_size(sf, &bi, channel);
|
||||||
@ -230,7 +205,7 @@ static STREAMFILE* setup_awc_streamfile(STREAMFILE* sf, uint32_t stream_offset,
|
|||||||
STREAMFILE* new_sf = NULL;
|
STREAMFILE* new_sf = NULL;
|
||||||
deblock_config_t cfg = {0};
|
deblock_config_t cfg = {0};
|
||||||
|
|
||||||
if (channels >= AWC_MAX_MUSIC_CHANNELS)
|
if (channels > AWC_MAX_MUSIC_CHANNELS || channel >= channels)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cfg.track_number = channel;
|
cfg.track_number = channel;
|
||||||
@ -241,7 +216,7 @@ static STREAMFILE* setup_awc_streamfile(STREAMFILE* sf, uint32_t stream_offset,
|
|||||||
cfg.track_type = codec;
|
cfg.track_type = codec;
|
||||||
cfg.big_endian = big_endian;
|
cfg.big_endian = big_endian;
|
||||||
//cfg.physical_offset = stream_offset;
|
//cfg.physical_offset = stream_offset;
|
||||||
//cfg.logical_size = awc_xma_io_size(sf, &cfg); /* force init */
|
//cfg.logical_size = awc_io_size(sf, &cfg); /* force init */
|
||||||
cfg.block_callback = block_callback;
|
cfg.block_callback = block_callback;
|
||||||
|
|
||||||
new_sf = open_wrap_streamfile(sf);
|
new_sf = open_wrap_streamfile(sf);
|
||||||
|
Loading…
Reference in New Issue
Block a user