mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-18 07:44:43 +01:00
Merge branch 'master' of git://github.com/kode54/vgmstream
This commit is contained in:
commit
837b04866b
@ -293,7 +293,19 @@ void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples);
|
|||||||
uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data * data);
|
uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data * data);
|
||||||
void ffmpeg_set_channel_remapping(ffmpeg_codec_data * data, int *channels_remap);
|
void ffmpeg_set_channel_remapping(ffmpeg_codec_data * data, int *channels_remap);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int channels;
|
||||||
|
int skip;
|
||||||
|
int sample_rate;
|
||||||
|
/* multichannel-only */
|
||||||
|
int coupled_count;
|
||||||
|
int stream_count;
|
||||||
|
int channel_mapping[8];
|
||||||
|
} opus_config;
|
||||||
|
|
||||||
/* ffmpeg_decoder_custom_opus.c (helper-things) */
|
/* ffmpeg_decoder_custom_opus.c (helper-things) */
|
||||||
|
ffmpeg_codec_data * init_ffmpeg_switch_opus_config(STREAMFILE *streamFile, off_t start_offset, size_t data_size, opus_config* cfg);
|
||||||
ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
|
ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
|
||||||
ffmpeg_codec_data * init_ffmpeg_ue4_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
|
ffmpeg_codec_data * init_ffmpeg_ue4_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
|
||||||
ffmpeg_codec_data * init_ffmpeg_ea_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
|
ffmpeg_codec_data * init_ffmpeg_ea_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
|
||||||
|
@ -2,18 +2,22 @@
|
|||||||
#include "../streamfile.h"
|
#include "../streamfile.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef VGM_USE_FFMPEG
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transmogrifies custom Opus (no Ogg layer and custom packet headers) into is Xiph Opus, creating
|
* Transmogrifies custom Opus (no Ogg layer and custom packet headers) into is Xiph Opus, creating
|
||||||
* valid Ogg pages with single Opus packets.
|
* valid Ogg pages with single Opus packets.
|
||||||
* Uses an intermediate buffer to make full Ogg pages, since checksums are calculated with the whole page.
|
* Uses an intermediate buffer to make full Ogg pages, since checksums are calculated with the whole page.
|
||||||
*
|
*
|
||||||
|
* Mostly as an experiment/demonstration, until some details are sorted out before adding actual libopus.
|
||||||
|
*
|
||||||
* Info, CRC and stuff:
|
* Info, CRC and stuff:
|
||||||
* https://www.opus-codec.org/docs/
|
* https://www.opus-codec.org/docs/
|
||||||
* https://tools.ietf.org/html/rfc7845.html
|
* https://tools.ietf.org/html/rfc7845.html
|
||||||
* https://github.com/hcs64/ww2ogg
|
* https://github.com/hcs64/ww2ogg
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static size_t make_oggs_first(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate);
|
static size_t make_oggs_first(uint8_t * buf, int buf_size, opus_config *cfg);
|
||||||
static size_t make_oggs_page(uint8_t * buf, int buf_size, size_t data_size, int page_sequence, int granule);
|
static size_t make_oggs_page(uint8_t * buf, int buf_size, size_t data_size, int page_sequence, int granule);
|
||||||
static size_t opus_get_packet_samples(const uint8_t * buf, int len);
|
static size_t opus_get_packet_samples(const uint8_t * buf, int len);
|
||||||
static size_t get_xopus_packet_size(int packet, STREAMFILE * streamfile);
|
static size_t get_xopus_packet_size(int packet, STREAMFILE * streamfile);
|
||||||
@ -230,7 +234,7 @@ static size_t opus_io_size(STREAMFILE *streamfile, opus_io_data* data) {
|
|||||||
|
|
||||||
|
|
||||||
/* Prepares custom IO for custom Opus, that is converted to Ogg Opus on the fly */
|
/* Prepares custom IO for custom Opus, that is converted to Ogg Opus on the fly */
|
||||||
static STREAMFILE* setup_opus_streamfile(STREAMFILE *streamFile, int channels, int skip, int sample_rate, off_t stream_offset, size_t stream_size, opus_type_t type) {
|
static STREAMFILE* setup_opus_streamfile(STREAMFILE *streamFile, opus_config *cfg, off_t stream_offset, size_t stream_size, opus_type_t type) {
|
||||||
STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
|
STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
|
||||||
opus_io_data io_data = {0};
|
opus_io_data io_data = {0};
|
||||||
size_t io_data_size = sizeof(opus_io_data);
|
size_t io_data_size = sizeof(opus_io_data);
|
||||||
@ -239,7 +243,7 @@ static STREAMFILE* setup_opus_streamfile(STREAMFILE *streamFile, int channels, i
|
|||||||
io_data.stream_offset = stream_offset;
|
io_data.stream_offset = stream_offset;
|
||||||
io_data.stream_size = stream_size;
|
io_data.stream_size = stream_size;
|
||||||
io_data.physical_offset = stream_offset;
|
io_data.physical_offset = stream_offset;
|
||||||
io_data.head_size = make_oggs_first(io_data.head_buffer, sizeof(io_data.head_buffer), channels, skip, sample_rate);
|
io_data.head_size = make_oggs_first(io_data.head_buffer, sizeof(io_data.head_buffer), cfg);
|
||||||
if (!io_data.head_size) goto fail;
|
if (!io_data.head_size) goto fail;
|
||||||
io_data.sequence = 2;
|
io_data.sequence = 2;
|
||||||
io_data.logical_size = opus_io_size(streamFile, &io_data); /* force init */
|
io_data.logical_size = opus_io_size(streamFile, &io_data); /* force init */
|
||||||
@ -405,26 +409,16 @@ fail:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t make_opus_header(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate) {
|
static size_t make_opus_header(uint8_t * buf, int buf_size, opus_config *cfg) {
|
||||||
size_t header_size = 0x13;
|
size_t header_size = 0x13;
|
||||||
int mapping_family = 0; /* channel config: 0=standard (single stream mono/stereo), 1=vorbis, 255: not defined */
|
int mapping_family = 0;
|
||||||
#if 0
|
|
||||||
int stream_count = 1; /* number of internal mono/stereo streams (N mono/stereo streams form M channels) */
|
|
||||||
int coupled_count = channels - 1; /* number of stereo streams (packet has which one is mono or stereo) */
|
|
||||||
|
|
||||||
/* special multichannel config */
|
/* special multichannel config */
|
||||||
if (channels > 2) {
|
if (cfg->channels > 2) {
|
||||||
header_size += 0x01+0x01+channels;
|
/* channel config: 0=standard (single stream mono/stereo), 1=vorbis, 255: not defined */
|
||||||
switch(type) {
|
mapping_family = 1;
|
||||||
|
header_size += 0x01+0x01+cfg->channels;
|
||||||
case ...:
|
|
||||||
...
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (header_size > buf_size) {
|
if (header_size > buf_size) {
|
||||||
VGM_LOG("OPUS: buffer can't hold header\n");
|
VGM_LOG("OPUS: buffer can't hold header\n");
|
||||||
@ -434,23 +428,24 @@ static size_t make_opus_header(uint8_t * buf, int buf_size, int channels, int sk
|
|||||||
put_32bitBE(buf+0x00, 0x4F707573); /* "Opus" header magic */
|
put_32bitBE(buf+0x00, 0x4F707573); /* "Opus" header magic */
|
||||||
put_32bitBE(buf+0x04, 0x48656164); /* "Head" header magic */
|
put_32bitBE(buf+0x04, 0x48656164); /* "Head" header magic */
|
||||||
put_8bit (buf+0x08, 1); /* version */
|
put_8bit (buf+0x08, 1); /* version */
|
||||||
put_8bit (buf+0x09, channels);
|
put_8bit (buf+0x09, cfg->channels);
|
||||||
put_16bitLE(buf+0x0A, skip);
|
put_16bitLE(buf+0x0A, cfg->skip);
|
||||||
put_32bitLE(buf+0x0c, sample_rate);
|
put_32bitLE(buf+0x0c, cfg->sample_rate);
|
||||||
put_16bitLE(buf+0x10, 0); /* output gain */
|
put_16bitLE(buf+0x10, 0); /* output gain */
|
||||||
put_8bit (buf+0x12, mapping_family);
|
put_8bit (buf+0x12, mapping_family);
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (mapping_family > 0) {
|
if (mapping_family > 0) {
|
||||||
int 0;
|
int i;
|
||||||
|
|
||||||
put_8bit(buf+0x13, stream_count);
|
/* internal mono/stereo streams (N mono/stereo streams form M channels) */
|
||||||
put_8bit(buf+0x14, coupled_count);
|
put_8bit(buf+0x13, cfg->stream_count);
|
||||||
for (i = 0; i < channels; i++) {
|
/* joint stereo streams (rest would be mono, so 6ch can be 2ch+2ch+1ch+1ch = 2 coupled */
|
||||||
put_8bit(buf+0x15+i, i); /* channel mapping (may need to change per family) */
|
put_8bit(buf+0x14, cfg->coupled_count);
|
||||||
|
/* mapping bits per channel? */
|
||||||
|
for (i = 0; i < cfg->channels; i++) {
|
||||||
|
put_8bit(buf+0x15+i, cfg->channel_mapping[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return header_size;
|
return header_size;
|
||||||
fail:
|
fail:
|
||||||
@ -485,7 +480,7 @@ fail:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t make_oggs_first(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate) {
|
static size_t make_oggs_first(uint8_t * buf, int buf_size, opus_config *cfg) {
|
||||||
int buf_done = 0;
|
int buf_done = 0;
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
|
|
||||||
@ -493,7 +488,7 @@ static size_t make_oggs_first(uint8_t * buf, int buf_size, int channels, int ski
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* make header */
|
/* make header */
|
||||||
bytes = make_opus_header(buf+buf_done + 0x1c,buf_size, channels, skip, sample_rate);
|
bytes = make_opus_header(buf+buf_done + 0x1c,buf_size, cfg);
|
||||||
make_oggs_page(buf+buf_done + 0x00,buf_size, bytes, 0, 0);
|
make_oggs_page(buf+buf_done + 0x00,buf_size, bytes, 0, 0);
|
||||||
buf_done += 0x1c + bytes;
|
buf_done += 0x1c + bytes;
|
||||||
|
|
||||||
@ -521,8 +516,6 @@ static size_t get_xopus_packet_size(int packet, STREAMFILE * streamfile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
|
||||||
|
|
||||||
static size_t custom_opus_get_samples(off_t offset, size_t stream_size, STREAMFILE *streamFile, opus_type_t type) {
|
static size_t custom_opus_get_samples(off_t offset, size_t stream_size, STREAMFILE *streamFile, opus_type_t type) {
|
||||||
size_t num_samples = 0;
|
size_t num_samples = 0;
|
||||||
off_t end_offset = offset + stream_size;
|
off_t end_offset = offset + stream_size;
|
||||||
@ -610,14 +603,16 @@ size_t ea_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ******************************************************* */
|
/* ******************************************************* */
|
||||||
|
|
||||||
static ffmpeg_codec_data * init_ffmpeg_custom_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate, opus_type_t type) {
|
/* actual FFmpeg only-code starts here (the above is universal enough but no point to compile) */
|
||||||
|
//#ifdef VGM_USE_FFMPEG
|
||||||
|
|
||||||
|
static ffmpeg_codec_data * init_ffmpeg_custom_opus_config(STREAMFILE *streamFile, off_t start_offset, size_t data_size, opus_config *cfg, opus_type_t type) {
|
||||||
ffmpeg_codec_data * ffmpeg_data = NULL;
|
ffmpeg_codec_data * ffmpeg_data = NULL;
|
||||||
STREAMFILE *temp_streamFile = NULL;
|
STREAMFILE *temp_streamFile = NULL;
|
||||||
|
|
||||||
temp_streamFile = setup_opus_streamfile(streamFile, channels, skip, sample_rate, start_offset, data_size, type);
|
temp_streamFile = setup_opus_streamfile(streamFile, cfg, start_offset, data_size, type);
|
||||||
if (!temp_streamFile) goto fail;
|
if (!temp_streamFile) goto fail;
|
||||||
|
|
||||||
ffmpeg_data = init_ffmpeg_offset(temp_streamFile, 0x00,get_streamfile_size(temp_streamFile));
|
ffmpeg_data = init_ffmpeg_offset(temp_streamFile, 0x00,get_streamfile_size(temp_streamFile));
|
||||||
@ -637,7 +632,18 @@ fail:
|
|||||||
close_streamfile(temp_streamFile);
|
close_streamfile(temp_streamFile);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
static ffmpeg_codec_data * init_ffmpeg_custom_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate, opus_type_t type) {
|
||||||
|
opus_config cfg = {0};
|
||||||
|
cfg.channels = channels;
|
||||||
|
cfg.skip = skip;
|
||||||
|
cfg.sample_rate = sample_rate;
|
||||||
|
|
||||||
|
return init_ffmpeg_custom_opus_config(streamFile, start_offset, data_size, &cfg, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ffmpeg_codec_data * init_ffmpeg_switch_opus_config(STREAMFILE *streamFile, off_t start_offset, size_t data_size, opus_config* cfg) {
|
||||||
|
return init_ffmpeg_custom_opus_config(streamFile, start_offset, data_size, cfg, OPUS_SWITCH);
|
||||||
|
}
|
||||||
ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate) {
|
ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate) {
|
||||||
return init_ffmpeg_custom_opus(streamFile, start_offset, data_size, channels, skip, sample_rate, OPUS_SWITCH);
|
return init_ffmpeg_custom_opus(streamFile, start_offset, data_size, channels, skip, sample_rate, OPUS_SWITCH);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <math.h>
|
||||||
#include "meta.h"
|
#include "meta.h"
|
||||||
#include "../layout/layout.h"
|
#include "../layout/layout.h"
|
||||||
#include "../coding/coding.h"
|
#include "../coding/coding.h"
|
||||||
|
@ -32,53 +32,79 @@ VGMSTREAM * init_vgmstream_ktss(STREAMFILE *streamFile) {
|
|||||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||||
if (!vgmstream) goto fail;
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
/* fill in the vital statistics */
|
|
||||||
vgmstream->num_samples = read_32bitLE(0x30, streamFile);
|
|
||||||
vgmstream->sample_rate = read_32bitLE(0x2c, streamFile);
|
vgmstream->sample_rate = read_32bitLE(0x2c, streamFile);
|
||||||
|
vgmstream->num_samples = read_32bitLE(0x30, streamFile);
|
||||||
vgmstream->loop_start_sample = read_32bitLE(0x34, streamFile);
|
vgmstream->loop_start_sample = read_32bitLE(0x34, streamFile);
|
||||||
vgmstream->loop_end_sample = vgmstream->loop_start_sample + loop_length;
|
vgmstream->loop_end_sample = vgmstream->loop_start_sample + loop_length;
|
||||||
vgmstream->meta_type = meta_KTSS;
|
vgmstream->meta_type = meta_KTSS;
|
||||||
start_offset = read_32bitLE(0x24, streamFile) + 0x20;
|
start_offset = read_32bitLE(0x24, streamFile) + 0x20;
|
||||||
|
|
||||||
switch (codec_id) {
|
switch (codec_id) {
|
||||||
case 0x2: /* DSP ADPCM - Hyrule Warriors, Fire Emblem Warriors, and other Koei Tecmo games */
|
case 0x2: /* DSP ADPCM - Hyrule Warriors, Fire Emblem Warriors, and other Koei Tecmo games */
|
||||||
/* check type details */
|
/* check type details */
|
||||||
version = read_8bit(0x22, streamFile);
|
version = read_8bit(0x22, streamFile);
|
||||||
if (version == 1) {
|
if (version == 1) {
|
||||||
coef_start_offset = 0x40;
|
coef_start_offset = 0x40;
|
||||||
coef_spacing = 0x2e;
|
coef_spacing = 0x2e;
|
||||||
}
|
}
|
||||||
else if (version == 3) { // Fire Emblem Warriors (Switch)
|
else if (version == 3) { // Fire Emblem Warriors (Switch)
|
||||||
coef_start_offset = 0x5c;
|
coef_start_offset = 0x5c;
|
||||||
coef_spacing = 0x60;
|
coef_spacing = 0x60;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
vgmstream->coding_type = coding_NGC_DSP;
|
vgmstream->coding_type = coding_NGC_DSP;
|
||||||
vgmstream->layout_type = layout_interleave;
|
vgmstream->layout_type = layout_interleave;
|
||||||
vgmstream->interleave_block_size = 0x8;
|
vgmstream->interleave_block_size = 0x8;
|
||||||
dsp_read_coefs_le(vgmstream, streamFile, coef_start_offset, coef_spacing);
|
dsp_read_coefs_le(vgmstream, streamFile, coef_start_offset, coef_spacing);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
case 0x9: /* Opus - Dead or Alive Xtreme 3: Scarlet */
|
case 0x9: { /* Opus - Dead or Alive Xtreme 3: Scarlet, Fire Emblem: Three Houses */
|
||||||
data_size = read_32bitLE(0x44, streamFile);
|
opus_config cfg = {0};
|
||||||
{
|
|
||||||
vgmstream->codec_data = init_ffmpeg_switch_opus(streamFile, start_offset, data_size, vgmstream->channels, skip, vgmstream->sample_rate);
|
data_size = read_32bitLE(0x44, streamFile);
|
||||||
|
|
||||||
|
cfg.channels = vgmstream->channels;
|
||||||
|
cfg.skip = read_32bitLE(0x58, streamFile);
|
||||||
|
cfg.sample_rate = vgmstream->sample_rate; /* also at 0x54 */
|
||||||
|
|
||||||
|
/* this info seems always included even for stereo streams */
|
||||||
|
if (vgmstream->channels <= 8) {
|
||||||
|
int i;
|
||||||
|
cfg.stream_count = read_8bit(0x5a,streamFile);
|
||||||
|
cfg.coupled_count = read_8bit(0x5b,streamFile);
|
||||||
|
for (i = 0; i < vgmstream->channels; i++) {
|
||||||
|
cfg.channel_mapping[i] = read_8bit(0x5c + i,streamFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vgmstream->codec_data = init_ffmpeg_switch_opus_config(streamFile, start_offset, data_size, &cfg);
|
||||||
if (!vgmstream->codec_data) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
vgmstream->channel_layout = ffmpeg_get_channel_layout(vgmstream->codec_data);
|
||||||
|
|
||||||
|
/* apparently KTSS doesn't need standard Opus reordering, so we undo their thing */
|
||||||
|
switch(vgmstream->channels) {
|
||||||
|
case 6: {
|
||||||
|
/* FL FC FR BL LFE BR > FL FR FC LFE BL BR */
|
||||||
|
int channel_remap[] = { 0, 2, 2, 3, 3, 5 };
|
||||||
|
ffmpeg_set_channel_remapping(vgmstream->codec_data, channel_remap);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (vgmstream->num_samples == 0) {
|
if (vgmstream->num_samples == 0) {
|
||||||
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, streamFile) - skip;
|
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, streamFile) - skip;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
goto fail;
|
|
||||||
#endif
|
#endif
|
||||||
|
default:
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
|
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
|
||||||
|
@ -9,7 +9,7 @@ static VGMSTREAM * init_vgmstream_opus(STREAMFILE *streamFile, meta_t meta_type,
|
|||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM * vgmstream = NULL;
|
||||||
off_t start_offset;
|
off_t start_offset;
|
||||||
int loop_flag = 0, channel_count;
|
int loop_flag = 0, channel_count;
|
||||||
off_t data_offset;
|
off_t data_offset, multichannel_offset = 0;
|
||||||
size_t data_size, skip = 0;
|
size_t data_size, skip = 0;
|
||||||
|
|
||||||
|
|
||||||
@ -22,6 +22,11 @@ static VGMSTREAM * init_vgmstream_opus(STREAMFILE *streamFile, meta_t meta_type,
|
|||||||
skip = read_16bitLE(offset + 0x1c, streamFile);
|
skip = read_16bitLE(offset + 0x1c, streamFile);
|
||||||
/* 0x1e: ? (seen in Lego Movie 2 (Switch)) */
|
/* 0x1e: ? (seen in Lego Movie 2 (Switch)) */
|
||||||
|
|
||||||
|
/* recent >2ch info [Clannad (Switch)] */
|
||||||
|
if ((uint32_t)read_32bitLE(offset + 0x20, streamFile) == 0x80000005) {
|
||||||
|
multichannel_offset = offset + 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
if ((uint32_t)read_32bitLE(data_offset, streamFile) != 0x80000004)
|
if ((uint32_t)read_32bitLE(data_offset, streamFile) != 0x80000004)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -45,10 +50,26 @@ static VGMSTREAM * init_vgmstream_opus(STREAMFILE *streamFile, meta_t meta_type,
|
|||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
{
|
{
|
||||||
vgmstream->codec_data = init_ffmpeg_switch_opus(streamFile, start_offset,data_size, vgmstream->channels, skip, vgmstream->sample_rate);
|
opus_config cfg = {0};
|
||||||
|
|
||||||
|
cfg.channels = vgmstream->channels;
|
||||||
|
cfg.skip = skip;
|
||||||
|
cfg.sample_rate = vgmstream->sample_rate;
|
||||||
|
|
||||||
|
if (multichannel_offset && vgmstream->channels <= 8) {
|
||||||
|
int i;
|
||||||
|
cfg.stream_count = read_8bit(multichannel_offset + 0x08,streamFile);
|
||||||
|
cfg.coupled_count = read_8bit(multichannel_offset + 0x09,streamFile);
|
||||||
|
for (i = 0; i < vgmstream->channels; i++) {
|
||||||
|
cfg.channel_mapping[i] = read_8bit(multichannel_offset + 0x0a + i,streamFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vgmstream->codec_data = init_ffmpeg_switch_opus_config(streamFile, start_offset,data_size, &cfg);
|
||||||
if (!vgmstream->codec_data) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
vgmstream->channel_layout = ffmpeg_get_channel_layout(vgmstream->codec_data);
|
||||||
|
|
||||||
if (vgmstream->num_samples == 0) {
|
if (vgmstream->num_samples == 0) {
|
||||||
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, streamFile) - skip;
|
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, streamFile) - skip;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user