mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-23 22:41:05 +01:00
Add .awc Opus/RIFF [Red Dead Redemption (PC)]
This commit is contained in:
parent
b92af8657d
commit
995cdcf4e2
@ -156,7 +156,7 @@ VGMSTREAM* init_vgmstream_awc(STREAMFILE* sf) {
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
case 0x0F: { /* ATRAC9 (PC) [Red Dead Redemption (PS4)] */
|
||||
case 0x0F: { /* ATRAC9 (PS4) [Red Dead Redemption (PS4)] */
|
||||
if (awc.is_streamed) {
|
||||
vgmstream->layout_data = build_layered_awc(sf_body, &awc);
|
||||
if (!vgmstream->layout_data) goto fail;
|
||||
@ -205,6 +205,50 @@ VGMSTREAM* init_vgmstream_awc(STREAMFILE* sf) {
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
case 0x0D: { /* OPUS (PC) [Red Dead Redemption (PC)] */
|
||||
if (awc.is_streamed) {
|
||||
vgmstream->layout_data = build_layered_awc(sf_body, &awc);
|
||||
if (!vgmstream->layout_data) goto fail;
|
||||
vgmstream->layout_type = layout_layered;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
}
|
||||
else {
|
||||
VGM_LOG("AWC: unknown non-streamed Opus mode\n");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case 0x11: { /* RIFF-MSADPCM (PC) [Red Dead Redemption (PC)] */
|
||||
if (awc.is_streamed) {
|
||||
VGM_LOG("AWC: unknown streamed mode for codec 0x%02x\n", awc.codec);
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
VGMSTREAM* temp_vs = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
|
||||
temp_sf = setup_subfile_streamfile(sf_body, awc.stream_offset, awc.stream_size, "wav");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
temp_vs = init_vgmstream_riff(temp_sf);
|
||||
close_streamfile(temp_sf);
|
||||
if (!temp_vs) goto fail;
|
||||
|
||||
temp_vs->num_streams = vgmstream->num_streams;
|
||||
temp_vs->stream_size = vgmstream->stream_size;
|
||||
temp_vs->meta_type = vgmstream->meta_type;
|
||||
strcpy(temp_vs->stream_name, vgmstream->stream_name);
|
||||
|
||||
close_vgmstream(vgmstream);
|
||||
//vgmstream = temp_vs;
|
||||
return temp_vs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xFF:
|
||||
vgmstream->coding_type = coding_SILENCE;
|
||||
snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "[%s]", "midi");
|
||||
@ -617,6 +661,24 @@ static VGMSTREAM* build_blocks_vgmstream(STREAMFILE* sf, awc_header* awc, int ch
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 0x0D: {
|
||||
opus_config cfg = {0};
|
||||
|
||||
/* read from first block (all blocks have it but same thing), see awc_streamfile.h */
|
||||
uint32_t frame_size_offset = awc->stream_offset + 0x10 * awc->channels + 0x70 * channel + 0x04;
|
||||
|
||||
cfg.frame_size = read_u16le(frame_size_offset, sf); // always 0x50?
|
||||
cfg.channels = 1;
|
||||
|
||||
vgmstream->codec_data = init_ffmpeg_fixed_opus(temp_sf, substream_offset, substream_size, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
case 0x0F: {
|
||||
atrac9_config cfg = {0};
|
||||
@ -669,9 +731,8 @@ fail:
|
||||
// independently.
|
||||
//
|
||||
// This can be simulated by making one decoder per block (segmented, but opens too many SFs and can't skip
|
||||
// samples correctly), or with a custom STREAMFILE that skips repeated block (works ok-ish but not all codecs).
|
||||
// samples correctly), or with a custom STREAMFILE that skips repeated block (works ok-ish).
|
||||
static layered_layout_data* build_layered_awc(STREAMFILE* sf, awc_header* awc) {
|
||||
int i;
|
||||
layered_layout_data* data = NULL;
|
||||
|
||||
|
||||
@ -680,7 +741,7 @@ static layered_layout_data* build_layered_awc(STREAMFILE* sf, awc_header* awc) {
|
||||
if (!data) goto fail;
|
||||
|
||||
/* open each layer subfile */
|
||||
for (i = 0; i < awc->channels; i++) {
|
||||
for (int i = 0; i < awc->channels; i++) {
|
||||
data->layers[i] = build_blocks_vgmstream(sf, awc, i);
|
||||
if (!data->layers[i]) goto fail;
|
||||
}
|
||||
|
@ -61,9 +61,9 @@ typedef struct {
|
||||
* 0x00: "D11A"
|
||||
* 0x04: frame size
|
||||
* 0x06: frame samples
|
||||
* 0x08: flags? (0x0103=AT9, 0x0104=DSP)
|
||||
* 0x08: flags? (0x0101=OPUS, 0x0103=AT9, 0x0104=DSP)
|
||||
* 0x0a: sample rate
|
||||
* 0x0c: ATRAC9 config (repeated but same for all blocks) or "D11E" (DSP)
|
||||
* 0x0c: ATRAC9 config (repeated but same for all blocks) or "D11E" (OPUS/DSP)
|
||||
* 0x10-0x70: padding with 0x77 (ATRAC3) or standard DSP header for original full file (DSP)
|
||||
* - padding up to data start, depending on codec (DSP/ATRAC9: none, others: aligned to 0x800)
|
||||
*/
|
||||
@ -91,6 +91,7 @@ static bool read_awc_block(STREAMFILE* sf, awc_block_info_t* bi) {
|
||||
extra_entry_size = 0x00;
|
||||
header_padding = 0x800;
|
||||
break;
|
||||
case 0x0D: /* OPUS */
|
||||
case 0x0F: /* ATRAC9 */
|
||||
channel_entry_size = 0x10;
|
||||
seek_entry_size = 0x00;
|
||||
@ -136,6 +137,7 @@ static bool read_awc_block(STREAMFILE* sf, awc_block_info_t* bi) {
|
||||
bi->blk[ch].chunk_size = align_size_to_block(bi->blk[ch].channel_size, 0x10);
|
||||
//bi->blk[ch].channel_size = (pre-loaded);
|
||||
break;
|
||||
case 0x0D: /* OPUS */
|
||||
case 0x0F: /* ATRAC9 */
|
||||
bi->blk[ch].frame_size = read_u16(offset + 0x04, sf);
|
||||
bi->blk[ch].chunk_size = bi->blk[ch].entries * bi->blk[ch].frame_size;
|
||||
@ -217,6 +219,7 @@ static uint32_t get_block_repeated_size(STREAMFILE* sf, awc_block_info_t* bi, in
|
||||
return skip_size; /* skip_size fills frame size */
|
||||
}
|
||||
|
||||
case 0x0D: /* OPUS */
|
||||
case 0x0F: /* ATRAC9 */
|
||||
default:
|
||||
VGM_LOG("AWC: found channel skip in codec %x\n", bi->codec); /* not seen */
|
||||
|
Loading…
Reference in New Issue
Block a user