vgmstream/src/coding/relic_decoder.c

124 lines
3.2 KiB
C
Raw Normal View History

#include "coding.h"
#include "relic_decoder_lib.h"
//TODO: fix looping
struct relic_codec_data {
relic_handle_t* handle;
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) {
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;
}
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;
relic_get_pcm16(data->handle, outbuf, samples_to_get, data->samples_consumed);
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;
relic_reset(data->handle);
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;
relic_free(data->handle);
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;
}