2019-12-27 01:29:56 +01:00
|
|
|
#include "coding.h"
|
2021-08-08 00:11:55 +02:00
|
|
|
#include "relic_decoder_lib.h"
|
2019-12-27 01:29:56 +01:00
|
|
|
|
2021-08-08 00:11:55 +02:00
|
|
|
//TODO: fix looping
|
2019-12-27 01:29:56 +01:00
|
|
|
|
|
|
|
struct relic_codec_data {
|
2021-08-08 00:11:55 +02:00
|
|
|
relic_handle_t* handle;
|
2019-12-27 01:29:56 +01:00
|
|
|
int channels;
|
|
|
|
int frame_size;
|
|
|
|
|
|
|
|
int32_t samples_discard;
|
|
|
|
int32_t samples_consumed;
|
|
|
|
int32_t samples_filled;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
relic_codec_data* init_relic(int channels, int bitrate, int codec_rate) {
|
2021-08-08 00:11:55 +02:00
|
|
|
relic_codec_data* data = NULL;
|
|
|
|
|
|
|
|
data = calloc(1, sizeof(relic_codec_data));
|
|
|
|
if (!data) goto fail;
|
|
|
|
|
|
|
|
data->handle = relic_init(channels, bitrate, codec_rate);
|
|
|
|
if (!data->handle) goto fail;
|
|
|
|
|
|
|
|
data->channels = channels;
|
|
|
|
data->frame_size = relic_get_frame_size(data->handle);
|
|
|
|
|
|
|
|
return data;
|
|
|
|
fail:
|
|
|
|
free_relic(data);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int decode_frame_next(VGMSTREAMCHANNEL* stream, relic_codec_data* data) {
|
|
|
|
int ch;
|
|
|
|
int bytes;
|
|
|
|
int ok;
|
|
|
|
uint8_t buf[RELIC_BUFFER_SIZE];
|
|
|
|
|
|
|
|
for (ch = 0; ch < data->channels; ch++) {
|
|
|
|
bytes = read_streamfile(buf, stream->offset, data->frame_size, stream->streamfile);
|
|
|
|
if (bytes != data->frame_size) goto fail;
|
|
|
|
stream->offset += data->frame_size;
|
|
|
|
|
|
|
|
ok = relic_decode_frame(data->handle, buf, ch);
|
|
|
|
if (!ok) goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->samples_consumed = 0;
|
|
|
|
data->samples_filled = RELIC_SAMPLES_PER_FRAME;
|
|
|
|
return 1;
|
|
|
|
fail:
|
|
|
|
return 0;
|
2019-12-27 01:29:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void decode_relic(VGMSTREAMCHANNEL* stream, relic_codec_data* data, sample_t* outbuf, int32_t samples_to_do) {
|
|
|
|
|
|
|
|
while (samples_to_do > 0) {
|
|
|
|
|
|
|
|
if (data->samples_consumed < data->samples_filled) {
|
|
|
|
/* consume samples */
|
|
|
|
int samples_to_get = (data->samples_filled - data->samples_consumed);
|
|
|
|
|
|
|
|
if (data->samples_discard) {
|
|
|
|
/* discard samples for looping */
|
|
|
|
if (samples_to_get > data->samples_discard)
|
|
|
|
samples_to_get = data->samples_discard;
|
|
|
|
data->samples_discard -= samples_to_get;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* get max samples and copy */
|
|
|
|
if (samples_to_get > samples_to_do)
|
|
|
|
samples_to_get = samples_to_do;
|
|
|
|
|
2021-08-08 00:11:55 +02:00
|
|
|
relic_get_pcm16(data->handle, outbuf, samples_to_get, data->samples_consumed);
|
2019-12-27 01:29:56 +01:00
|
|
|
|
|
|
|
samples_to_do -= samples_to_get;
|
|
|
|
outbuf += samples_to_get * data->channels;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mark consumed samples */
|
|
|
|
data->samples_consumed += samples_to_get;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int ok = decode_frame_next(stream, data);
|
|
|
|
if (!ok) goto decode_fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
decode_fail:
|
|
|
|
/* on error just put some 0 samples */
|
|
|
|
VGM_LOG("RELIC: decode fail, missing %i samples\n", samples_to_do);
|
|
|
|
memset(outbuf, 0, samples_to_do * data->channels * sizeof(sample));
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset_relic(relic_codec_data* data) {
|
|
|
|
if (!data) return;
|
|
|
|
|
2021-08-08 00:11:55 +02:00
|
|
|
relic_reset(data->handle);
|
2019-12-27 01:29:56 +01:00
|
|
|
data->samples_filled = 0;
|
|
|
|
data->samples_consumed = 0;
|
|
|
|
data->samples_discard = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void seek_relic(relic_codec_data* data, int32_t num_sample) {
|
|
|
|
if (!data) return;
|
|
|
|
|
|
|
|
reset_relic(data);
|
|
|
|
data->samples_discard = num_sample;
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_relic(relic_codec_data* data) {
|
|
|
|
if (!data) return;
|
|
|
|
|
2021-08-08 00:11:55 +02:00
|
|
|
relic_free(data->handle);
|
2019-12-27 01:29:56 +01:00
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
|
2021-08-07 12:31:15 +02:00
|
|
|
int32_t relic_bytes_to_samples(size_t bytes, int channels, int bitrate) {
|
|
|
|
return bytes / channels / (bitrate / 8) * 512;
|
|
|
|
}
|