2017-04-29 22:37:15 +02:00
|
|
|
#include "coding.h"
|
|
|
|
#include "../util.h"
|
2013-06-26 11:54:15 +02:00
|
|
|
|
|
|
|
#ifdef VGM_USE_MAIATRAC3PLUS
|
|
|
|
#include "maiatrac3plus.h"
|
|
|
|
|
2017-12-27 01:02:24 +01:00
|
|
|
maiatrac3plus_codec_data *init_at3plus() {
|
|
|
|
|
|
|
|
maiatrac3plus_codec_data *data = malloc(sizeof(maiatrac3plus_codec_data));
|
|
|
|
data->buffer = 0;
|
|
|
|
data->samples_discard = 0;
|
|
|
|
data->handle = Atrac3plusDecoder_openContext();
|
|
|
|
if (!data->handle) goto fail;
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-04-29 22:37:15 +02:00
|
|
|
void decode_at3plus(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
|
2013-06-26 11:54:15 +02:00
|
|
|
VGMSTREAMCHANNEL *ch = &vgmstream->ch[0];
|
|
|
|
maiatrac3plus_codec_data *data = vgmstream->codec_data;
|
|
|
|
int i;
|
|
|
|
|
2013-06-26 20:13:44 +02:00
|
|
|
int first_sample = vgmstream->samples_into_block % 2048;
|
|
|
|
|
|
|
|
if (0 == channel && (0 == first_sample || data->samples_discard == first_sample))
|
2013-06-26 11:54:15 +02:00
|
|
|
{
|
|
|
|
uint8_t code_buffer[0x8000];
|
2013-06-26 12:46:31 +02:00
|
|
|
int blocks_to_decode = 1;
|
2013-06-26 20:13:44 +02:00
|
|
|
int max_blocks_to_decode = (ch->offset - ch->channel_start_offset) / vgmstream->interleave_block_size + 1;
|
2013-06-26 12:46:31 +02:00
|
|
|
if (data->samples_discard) blocks_to_decode = 8;
|
|
|
|
if (blocks_to_decode > max_blocks_to_decode) blocks_to_decode = max_blocks_to_decode;
|
|
|
|
while (blocks_to_decode--) {
|
2013-06-26 20:13:44 +02:00
|
|
|
ch->streamfile->read(ch->streamfile, code_buffer, ch->offset - blocks_to_decode * vgmstream->interleave_block_size, vgmstream->interleave_block_size);
|
|
|
|
Atrac3plusDecoder_decodeFrame(data->handle, code_buffer, vgmstream->interleave_block_size, &data->channels, (void**)&data->buffer);
|
2013-06-26 12:46:31 +02:00
|
|
|
}
|
2013-06-26 11:54:15 +02:00
|
|
|
data->samples_discard = 0;
|
|
|
|
}
|
|
|
|
|
2017-12-27 01:02:24 +01:00
|
|
|
for (i = 0; i < samples_to_do; i++) {
|
2013-06-26 20:13:44 +02:00
|
|
|
outbuf[i*channelspacing] = data->buffer[(first_sample+i)*data->channels+channel];
|
2013-06-26 11:54:15 +02:00
|
|
|
}
|
2013-06-26 20:13:44 +02:00
|
|
|
|
|
|
|
if (0 == channel && 2048 == first_sample + samples_to_do) {
|
|
|
|
ch->offset += vgmstream->interleave_block_size;
|
|
|
|
}
|
2013-06-26 11:54:15 +02:00
|
|
|
}
|
|
|
|
|
2017-04-29 22:37:15 +02:00
|
|
|
|
|
|
|
void reset_at3plus(VGMSTREAM *vgmstream) {
|
|
|
|
maiatrac3plus_codec_data *data = vgmstream->codec_data;
|
2018-03-10 16:59:00 +01:00
|
|
|
if (!data) return;
|
2017-04-29 22:37:15 +02:00
|
|
|
|
|
|
|
if (data->handle)
|
|
|
|
Atrac3plusDecoder_closeContext(data->handle);
|
|
|
|
data->handle = Atrac3plusDecoder_openContext();
|
|
|
|
data->samples_discard = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void seek_at3plus(VGMSTREAM *vgmstream, int32_t num_sample) {
|
|
|
|
int blocks_to_skip = num_sample / 2048;
|
|
|
|
int samples_to_discard = num_sample % 2048;
|
|
|
|
maiatrac3plus_codec_data *data = (maiatrac3plus_codec_data *)(vgmstream->codec_data);
|
2018-03-10 16:59:00 +01:00
|
|
|
if (!data) return;
|
|
|
|
|
2017-04-29 22:37:15 +02:00
|
|
|
vgmstream->loop_ch[0].offset =
|
|
|
|
vgmstream->loop_ch[0].channel_start_offset +
|
|
|
|
vgmstream->interleave_block_size * blocks_to_skip;
|
|
|
|
data->samples_discard = samples_to_discard;
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_at3plus(maiatrac3plus_codec_data *data) {
|
|
|
|
if (data) {
|
|
|
|
if (data->handle) Atrac3plusDecoder_closeContext(data->handle);
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-26 11:54:15 +02:00
|
|
|
#endif
|