#include "coding.h" #include "../util.h" #ifdef VGM_USE_MAIATRAC3PLUS #include "maiatrac3plus.h" struct maiatrac3plus_codec_data { sample_t* buffer; int channels; int samples_discard; void* handle; }; 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; } void decode_at3plus(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) { VGMSTREAMCHANNEL *ch = &vgmstream->ch[0]; maiatrac3plus_codec_data *data = vgmstream->codec_data; int i; int first_sample = vgmstream->samples_into_block % 2048; if (0 == channel && (0 == first_sample || data->samples_discard == first_sample)) { uint8_t code_buffer[0x8000]; int blocks_to_decode = 1; int max_blocks_to_decode = (ch->offset - ch->channel_start_offset) / vgmstream->interleave_block_size + 1; 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--) { 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); } data->samples_discard = 0; } for (i = 0; i < samples_to_do; i++) { outbuf[i*channelspacing] = data->buffer[(first_sample+i)*data->channels+channel]; } if (0 == channel && 2048 == first_sample + samples_to_do) { ch->offset += vgmstream->interleave_block_size; } } void reset_at3plus(VGMSTREAM *vgmstream) { maiatrac3plus_codec_data *data = vgmstream->codec_data; if (!data) return; 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); if (!data) return; 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); } } #endif