mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-17 19:19:16 +01:00
relic decoder: fix some issues
This commit is contained in:
parent
88a74acb7f
commit
adf3d3d3b0
@ -310,6 +310,7 @@ void decode_relic(VGMSTREAMCHANNEL* stream, relic_codec_data* data, sample_t* ou
|
||||
void reset_relic(relic_codec_data* data);
|
||||
void seek_relic(relic_codec_data* data, int32_t num_sample);
|
||||
void free_relic(relic_codec_data* data);
|
||||
int32_t relic_bytes_to_samples(size_t bytes, int channels, int bitrate);
|
||||
|
||||
|
||||
/* hca_decoder */
|
||||
|
@ -7,13 +7,13 @@
|
||||
* files (released around 2003 through Relic Dev Network), accurate with minor +-1
|
||||
* samples due to double<>float ops or maybe original compiler (Intel's) diffs.
|
||||
*
|
||||
* TODO: clean API, improve validations (can segfault on bad data) and naming
|
||||
* TODO: clean API, fix looping
|
||||
*/
|
||||
|
||||
/* mixfft.c */
|
||||
extern void fft(int n, float *xRe, float *xIm, float *yRe, float *yIm);
|
||||
extern void fft(int n, float* xRe, float* xIm, float* yRe, float* yIm);
|
||||
|
||||
static relic_codec_data* init_codec(int channels, int bitrate, int codec_rate);
|
||||
static relic_codec_data* relic_init_codec(int channels, int bitrate, int codec_rate);
|
||||
static int decode_frame_next(VGMSTREAMCHANNEL* stream, relic_codec_data* data);
|
||||
static void copy_samples(relic_codec_data* data, sample_t* outbuf, int32_t samples_to_get);
|
||||
static void reset_codec(relic_codec_data* data);
|
||||
@ -30,11 +30,9 @@ static void reset_codec(relic_codec_data* data);
|
||||
#define RELIC_MAX_SIZE RELIC_SIZE_HIGH
|
||||
#define RELIC_MAX_FREQ (RELIC_MAX_SIZE / 2)
|
||||
#define RELIC_MAX_FFT (RELIC_MAX_SIZE / 4)
|
||||
#define RELIC_BITRATE_22 256
|
||||
#define RELIC_BITRATE_44 512
|
||||
#define RELIC_BITRATE_88 1024
|
||||
#define RELIC_BITRATE_176 2048
|
||||
#define RELIC_MAX_FRAME_SIZE ((RELIC_BITRATE_176 / 8) + 0x04) /* extra 0x04 for the bitreader */
|
||||
#define RELIC_MIN_BITRATE 256
|
||||
#define RELIC_MAX_BITRATE 2048
|
||||
#define RELIC_MAX_FRAME_SIZE ((RELIC_MAX_BITRATE / 8) + 0x04) /* extra 0x04 for the bitreader */
|
||||
|
||||
|
||||
struct relic_codec_data {
|
||||
@ -66,7 +64,7 @@ struct relic_codec_data {
|
||||
|
||||
|
||||
relic_codec_data* init_relic(int channels, int bitrate, int codec_rate) {
|
||||
return init_codec(channels, bitrate, codec_rate);
|
||||
return relic_init_codec(channels, bitrate, codec_rate);
|
||||
}
|
||||
|
||||
void decode_relic(VGMSTREAMCHANNEL* stream, relic_codec_data* data, sample_t* outbuf, int32_t samples_to_do) {
|
||||
@ -141,7 +139,7 @@ static const int16_t critical_band_data[RELIC_CRITICAL_BAND_COUNT] = {
|
||||
139, 180, 256
|
||||
};
|
||||
|
||||
static void init_dct(float *dct, int dct_size) {
|
||||
static void init_dct(float* dct, int dct_size) {
|
||||
int i;
|
||||
int dct_quarter = dct_size >> 2;
|
||||
|
||||
@ -152,7 +150,7 @@ static void init_dct(float *dct, int dct_size) {
|
||||
}
|
||||
}
|
||||
|
||||
static int apply_idct(const float *freq, float *wave, const float *dct, int dct_size) {
|
||||
static int apply_idct(const float* freq, float* wave, const float* dct, int dct_size) {
|
||||
int i;
|
||||
float factor;
|
||||
float out_re[RELIC_MAX_FFT];
|
||||
@ -198,7 +196,7 @@ static int apply_idct(const float *freq, float *wave, const float *dct, int dct_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void decode_frame(const float *freq1, const float *freq2, float *wave_cur, float *wave_prv, const float *dct, const float *window, int dct_size) {
|
||||
static void decode_frame(const float* freq1, const float* freq2, float* wave_cur, float* wave_prv, const float* dct, const float* window, int dct_size) {
|
||||
int i;
|
||||
float wave_tmp[RELIC_MAX_SIZE];
|
||||
int dct_half = dct_size >> 1;
|
||||
@ -225,7 +223,7 @@ static void init_window(float *window, int dct_size) {
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_frame_base(const float *freq1, const float *freq2, float *wave_cur, float *wave_prv, const float *dct, const float *window, int dct_mode, int samples_mode) {
|
||||
static void relic_decode_frame(const float* freq1, const float* freq2, float* wave_cur, float* wave_prv, const float* dct, const float* window, int dct_mode, int samples_mode) {
|
||||
int i;
|
||||
float wave_tmp[RELIC_MAX_SIZE];
|
||||
|
||||
@ -281,7 +279,7 @@ static void decode_frame_base(const float *freq1, const float *freq2, float *wav
|
||||
/* reads 32b max, packed in LSB order per byte (like Vorbis), ex.
|
||||
* with 0x45 6A=01000101 01101010 could read 4b=0101, 6b=100100, 3b=010 ...
|
||||
* assumes buf has enough extra bits to read 32b (size +0x04) */
|
||||
static uint32_t read_ubits(uint8_t bits, uint32_t offset, uint8_t *buf) {
|
||||
static uint32_t read_ubits(uint8_t bits, uint32_t offset, uint8_t* buf) {
|
||||
uint32_t shift, mask, pos, val;
|
||||
|
||||
shift = offset - 8 * (offset / 8);
|
||||
@ -290,7 +288,8 @@ static uint32_t read_ubits(uint8_t bits, uint32_t offset, uint8_t *buf) {
|
||||
val = (buf[pos+0]) | (buf[pos+1]<<8) | (buf[pos+2]<<16) | (buf[pos+3]<<24);
|
||||
return (val >> shift) & mask;
|
||||
}
|
||||
static int read_sbits(uint8_t bits, uint32_t offset, uint8_t *buf) {
|
||||
|
||||
static int read_sbits(uint8_t bits, uint32_t offset, uint8_t* buf) {
|
||||
uint32_t val = read_ubits(bits, offset, buf);
|
||||
int outval;
|
||||
if (val >> (bits - 1) == 1) { /* upper bit = sign */
|
||||
@ -316,12 +315,12 @@ static void init_dequantization(float* scales) {
|
||||
}
|
||||
}
|
||||
|
||||
static void unpack_frame(uint8_t *buf, int buf_size, float *freq1, float *freq2, const float* scales, uint8_t *exponents, int freq_size) {
|
||||
static int relic_unpack_frame(uint8_t* buf, int buf_size, float* freq1, float* freq2, const float* scales, uint8_t* exponents, int freq_size) {
|
||||
uint8_t flags, cb_bits, ev_bits, ei_bits, qv_bits;
|
||||
int qv;
|
||||
uint8_t ev;
|
||||
uint8_t move, pos;
|
||||
uint32_t bit_offset;
|
||||
uint32_t bit_offset, max_offset;
|
||||
int i, j;
|
||||
int freq_half = freq_size >> 1;
|
||||
|
||||
@ -334,6 +333,7 @@ static void unpack_frame(uint8_t *buf, int buf_size, float *freq1, float *freq2,
|
||||
ev_bits = read_ubits(2u, 5u, buf);
|
||||
ei_bits = read_ubits(4u, 7u, buf);
|
||||
bit_offset = 11;
|
||||
max_offset = buf_size * 8u;
|
||||
|
||||
/* reset exponents indexes */
|
||||
if ((flags & 1) == 1) {
|
||||
@ -344,43 +344,55 @@ static void unpack_frame(uint8_t *buf, int buf_size, float *freq1, float *freq2,
|
||||
if (cb_bits > 0 && ev_bits > 0) {
|
||||
pos = 0;
|
||||
for (i = 0; i < RELIC_CRITICAL_BAND_COUNT - 1; i++) {
|
||||
if (bit_offset >= 8u*buf_size)
|
||||
break;
|
||||
|
||||
if (bit_offset + cb_bits > max_offset)
|
||||
goto fail;
|
||||
move = read_ubits(cb_bits, bit_offset, buf);
|
||||
bit_offset += cb_bits;
|
||||
|
||||
if (i > 0 && move == 0)
|
||||
break;
|
||||
pos += move;
|
||||
|
||||
if (bit_offset + ev_bits > max_offset)
|
||||
goto fail;
|
||||
ev = read_ubits(ev_bits, bit_offset, buf);
|
||||
bit_offset += ev_bits;
|
||||
for (j = critical_band_data[pos]; j < critical_band_data[pos + 1]; j++)
|
||||
|
||||
if (pos + 1 >= sizeof(critical_band_data))
|
||||
goto fail;
|
||||
for (j = critical_band_data[pos]; j < critical_band_data[pos + 1]; j++) {
|
||||
exponents[j] = ev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* read quantized values */
|
||||
if (freq_half > 0 && ei_bits > 0) {
|
||||
|
||||
/* read first part */
|
||||
pos = 0;
|
||||
for (i = 0; i < RELIC_MAX_FREQ; i++) {
|
||||
if (bit_offset >= 8u*buf_size)
|
||||
break;
|
||||
|
||||
if (bit_offset + ei_bits > max_offset)
|
||||
goto fail;
|
||||
move = read_ubits(ei_bits, bit_offset, buf);
|
||||
bit_offset += ei_bits;
|
||||
|
||||
if (i > 0 && move == 0)
|
||||
break;
|
||||
pos += move;
|
||||
|
||||
if (pos >= RELIC_MAX_FREQ)
|
||||
goto fail;
|
||||
qv_bits = exponents[pos];
|
||||
|
||||
if (bit_offset + qv_bits + 2u > max_offset)
|
||||
goto fail;
|
||||
qv = read_sbits(qv_bits + 2u, bit_offset, buf);
|
||||
bit_offset += qv_bits + 2u;
|
||||
|
||||
if (qv != 0 && pos < freq_half && qv_bits < 6)
|
||||
if (qv != 0 && pos < freq_half && qv_bits < 6) {
|
||||
freq1[pos] = (float)qv * scales[qv_bits];
|
||||
}
|
||||
}
|
||||
|
||||
/* read second part, or clone it */
|
||||
@ -390,31 +402,43 @@ static void unpack_frame(uint8_t *buf, int buf_size, float *freq1, float *freq2,
|
||||
else {
|
||||
pos = 0;
|
||||
for (i = 0; i < RELIC_MAX_FREQ; i++) {
|
||||
if (bit_offset >= 8u*buf_size)
|
||||
break;
|
||||
|
||||
if (bit_offset + ei_bits > max_offset)
|
||||
goto fail;
|
||||
move = read_ubits(ei_bits, bit_offset, buf);
|
||||
bit_offset += ei_bits;
|
||||
|
||||
if (i > 0 && move == 0)
|
||||
break;
|
||||
pos += move;
|
||||
|
||||
if (pos >= RELIC_MAX_FREQ)
|
||||
goto fail;
|
||||
qv_bits = exponents[pos];
|
||||
|
||||
if (bit_offset + qv_bits + 2u > max_offset)
|
||||
goto fail;
|
||||
qv = read_sbits(qv_bits + 2u, bit_offset, buf);
|
||||
bit_offset += qv_bits + 2u;
|
||||
|
||||
if (qv != 0 && pos < freq_half && qv_bits < 6)
|
||||
if (qv != 0 && pos < freq_half && qv_bits < 6) {
|
||||
freq2[pos] = (float)qv * scales[qv_bits];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
VGM_LOG("RELIC: unpack fail\n");
|
||||
return 0; /* original code doesn't check bad sizes so no return errcode */
|
||||
}
|
||||
|
||||
static int decode_frame_next(VGMSTREAMCHANNEL* stream, relic_codec_data* data) {
|
||||
int ch;
|
||||
int bytes;
|
||||
int ok;
|
||||
uint8_t buf[RELIC_MAX_FRAME_SIZE];
|
||||
|
||||
|
||||
for (ch = 0; ch < data->channels; ch++) {
|
||||
/* clean extra bytes for bitreader */
|
||||
memset(buf + data->frame_size, 0, RELIC_MAX_FRAME_SIZE - data->frame_size);
|
||||
@ -422,10 +446,11 @@ static int decode_frame_next(VGMSTREAMCHANNEL* stream, relic_codec_data* data) {
|
||||
bytes = read_streamfile(buf, stream->offset, data->frame_size, stream->streamfile);
|
||||
if (bytes != data->frame_size) goto fail;
|
||||
stream->offset += data->frame_size;
|
||||
|
||||
unpack_frame(buf, sizeof(buf), data->freq1, data->freq2, data->scales, data->exponents[ch], data->freq_size);
|
||||
|
||||
decode_frame_base(data->freq1, data->freq2, data->wave_cur[ch], data->wave_prv[ch], data->dct, data->window, data->dct_mode, data->samples_mode);
|
||||
ok = relic_unpack_frame(buf, sizeof(buf), data->freq1, data->freq2, data->scales, data->exponents[ch], data->freq_size);
|
||||
if (!ok) goto fail;
|
||||
|
||||
relic_decode_frame(data->freq1, data->freq2, data->wave_cur[ch], data->wave_prv[ch], data->dct, data->window, data->dct_mode, data->samples_mode);
|
||||
}
|
||||
|
||||
data->samples_consumed = 0;
|
||||
@ -454,10 +479,10 @@ static void copy_samples(relic_codec_data* data, sample_t* outbuf, int32_t sampl
|
||||
}
|
||||
}
|
||||
|
||||
static relic_codec_data* init_codec(int channels, int bitrate, int codec_rate) {
|
||||
relic_codec_data *data = NULL;
|
||||
static relic_codec_data* relic_init_codec(int channels, int bitrate, int codec_rate) {
|
||||
relic_codec_data* data = NULL;
|
||||
|
||||
if (channels > RELIC_MAX_CHANNELS)
|
||||
if (channels < 0 || channels > RELIC_MAX_CHANNELS)
|
||||
goto fail;
|
||||
|
||||
data = calloc(1, sizeof(relic_codec_data));
|
||||
@ -468,9 +493,9 @@ static relic_codec_data* init_codec(int channels, int bitrate, int codec_rate) {
|
||||
/* dequantized freq1+2 size (separate from DCT) */
|
||||
if (codec_rate < 22050) /* probably 11025 only */
|
||||
data->freq_size = RELIC_SIZE_LOW;
|
||||
if (codec_rate == 22050)
|
||||
else if (codec_rate == 22050)
|
||||
data->freq_size = RELIC_SIZE_MID;
|
||||
if (codec_rate > 22050) /* probably 44100 only */
|
||||
else if (codec_rate > 22050) /* probably 44100 only */
|
||||
data->freq_size = RELIC_SIZE_HIGH;
|
||||
|
||||
/* default for streams (only a few mode combos are valid, see decode) */
|
||||
@ -483,16 +508,11 @@ static relic_codec_data* init_codec(int channels, int bitrate, int codec_rate) {
|
||||
init_dequantization(data->scales);
|
||||
memset(data->wave_prv, 0, RELIC_MAX_CHANNELS * RELIC_MAX_SIZE * sizeof(float));
|
||||
|
||||
switch(bitrate) {
|
||||
case RELIC_BITRATE_22:
|
||||
case RELIC_BITRATE_44:
|
||||
case RELIC_BITRATE_88:
|
||||
case RELIC_BITRATE_176:
|
||||
data->frame_size = (bitrate / 8); /* 0x100 and 0x80 are common */
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
/* known bitrates: 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400, 0x800
|
||||
* dec.exe doesn't validate this, so there may be more */
|
||||
if (bitrate < RELIC_MIN_BITRATE || bitrate > RELIC_MAX_BITRATE)
|
||||
goto fail;
|
||||
data->frame_size = (bitrate / 8); /* 0x100 and 0x80 are common */
|
||||
|
||||
|
||||
return data;
|
||||
@ -504,3 +524,7 @@ fail:
|
||||
static void reset_codec(relic_codec_data* data) {
|
||||
memset(data->wave_prv, 0, RELIC_MAX_CHANNELS * RELIC_MAX_SIZE * sizeof(float));
|
||||
}
|
||||
|
||||
int32_t relic_bytes_to_samples(size_t bytes, int channels, int bitrate) {
|
||||
return bytes / channels / (bitrate / 8) * 512;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user