Improve UE4OPUS encoder delay and fix get_opus_samples_per_frame

This commit is contained in:
bnnm 2018-09-23 12:17:23 +02:00
parent d717f21189
commit c5b514b577
2 changed files with 33 additions and 9 deletions

View File

@ -15,7 +15,7 @@
static size_t make_oggs_first(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate);
static size_t make_oggs_page(uint8_t * buf, int buf_size, size_t data_size, int page_sequence, int granule);
static uint32_t get_opus_samples_per_frame(const uint8_t * data, int Fs);
static size_t opus_get_packet_samples(const uint8_t * buf, int len);
typedef enum { OPUS_SWITCH, OPUS_UE4 } opus_type_t;
typedef struct {
@ -117,7 +117,7 @@ static size_t opus_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset,
/* create fake OggS page (full page for checksums) */
read_streamfile(data->page_buffer+oggs_size, data->physical_offset + skip_size, data_size, streamfile); /* store page data */
data->samples_done += get_opus_samples_per_frame(data->page_buffer+oggs_size, 48000);
data->samples_done += opus_get_packet_samples(data->page_buffer+oggs_size, data_size);
make_oggs_page(data->page_buffer,sizeof(data->page_buffer), data_size, data->sequence, data->samples_done);
data->sequence++;
}
@ -288,8 +288,8 @@ static uint32_t get_oggs_checksum(uint8_t * data, int bytes) {
return crc_reg;
}
/* from opus_decoder.c */
static uint32_t get_opus_samples_per_frame(const uint8_t * data, int Fs) {
/* from opus_decoder.c's opus_packet_get_samples_per_frame */
static uint32_t opus_packet_get_samples_per_frame(const uint8_t * data, int Fs) {
int audiosize;
if (data[0]&0x80)
{
@ -308,6 +308,22 @@ static uint32_t get_opus_samples_per_frame(const uint8_t * data, int Fs) {
return audiosize;
}
/* from opus_decoder.c's opus_packet_get_nb_frames */
static int opus_packet_get_nb_frames(const uint8_t * packet, int len) {
int count;
if (len<1)
return 0;
count = packet[0]&0x3;
if (count==0)
return 1;
else if (count!=3)
return 2;
else if (len<2)
return 0;
else
return packet[1]&0x3F;
}
/* ******************************** */
static size_t make_oggs_page(uint8_t * buf, int buf_size, size_t data_size, int page_sequence, int granule) {
@ -440,6 +456,10 @@ fail:
#ifdef VGM_USE_FFMPEG
static size_t opus_get_packet_samples(const uint8_t * buf, int len) {
return opus_packet_get_nb_frames(buf, len) * opus_packet_get_samples_per_frame(buf, 48000);
}
static size_t custom_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile, opus_type_t type) {
size_t num_samples = 0;
off_t end_offset = offset + data_size;
@ -467,8 +487,8 @@ static size_t custom_opus_get_samples(off_t offset, size_t data_size, int sample
return 0;
}
read_streamfile(buf, offset+skip_size, 0x04, streamFile);
num_samples += get_opus_samples_per_frame(buf, sample_rate);
read_streamfile(buf, offset+skip_size, 0x04, streamFile); /* at least 0x02 */
num_samples += opus_get_packet_samples(buf, 0x04);
offset += skip_size + data_size;
}

View File

@ -21,12 +21,16 @@ VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile) {
sample_rate = (uint16_t)read_16bitLE(0x08, streamFile);
num_samples = read_32bitLE(0x0a, streamFile);
num_samples = read_32bitLE(0x0a, streamFile); /* may be less or equal to file num_samples */
channel_count = read_8bit(0x0e, streamFile);
/* 0x0f(2): frame count */
skip = 0; //todo test
loop_flag = 0;
/* UE4Opus encodes 60ms (music) or 120ms (voice) frames, and encoder delay seems 1/8
* of samples per frame (may be more complex but wave looks ok-ish) */
//todo does UE4 actually care about encoder delay?
skip = (60 * 48000 / 1000) / 8; /* 48000 is the internal/resampled rate */
start_offset = 0x11;
data_size = get_streamfile_size(streamFile) - start_offset;
@ -37,7 +41,7 @@ VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_UE4OPUS;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->num_samples = num_samples - skip;
#ifdef VGM_USE_FFMPEG
{