Update EA-MT API a bit

This commit is contained in:
bnnm 2018-09-09 00:51:35 +02:00
parent 47b5a189cf
commit a3f2231ba1
2 changed files with 49 additions and 49 deletions

View File

@ -17,7 +17,12 @@
#define UTK_MAX(x,y) ((x)>(y)?(x):(y)) #define UTK_MAX(x,y) ((x)>(y)?(x):(y))
#define UTK_CLAMP(x,min,max) UTK_MIN(UTK_MAX(x,min),max) #define UTK_CLAMP(x,min,max) UTK_MIN(UTK_MAX(x,min),max)
#define UTK_BUFFER_SIZE 0x1000
struct ea_mt_codec_data { struct ea_mt_codec_data {
STREAMFILE *streamfile;
uint8_t buffer[UTK_BUFFER_SIZE];
off_t offset;
int pcm_blocks; int pcm_blocks;
int samples_filled; int samples_filled;
int samples_used; int samples_used;
@ -27,6 +32,8 @@ struct ea_mt_codec_data {
void* utk_context; void* utk_context;
}; };
static size_t ea_mt_read_callback(void *dest, int size, void *arg);
ea_mt_codec_data *init_ea_mt(int channels, int pcm_blocks, int reset_sample) { ea_mt_codec_data *init_ea_mt(int channels, int pcm_blocks, int reset_sample) {
ea_mt_codec_data *data = NULL; ea_mt_codec_data *data = NULL;
@ -42,6 +49,8 @@ ea_mt_codec_data *init_ea_mt(int channels, int pcm_blocks, int reset_sample) {
data[i].pcm_blocks = pcm_blocks; data[i].pcm_blocks = pcm_blocks;
data[i].reset_sample = reset_sample; data[i].reset_sample = reset_sample;
utk_set_callback(data[i].utk_context, data[i].buffer, UTK_BUFFER_SIZE, &data[i], &ea_mt_read_callback);
} }
return data; return data;
@ -121,7 +130,6 @@ void decode_ea_mt(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, in
static void flush_ea_mt_offsets(VGMSTREAM *vgmstream, int is_start, int samples_discard) { static void flush_ea_mt_offsets(VGMSTREAM *vgmstream, int is_start, int samples_discard) {
ea_mt_codec_data *data = vgmstream->codec_data; ea_mt_codec_data *data = vgmstream->codec_data;
int i; int i;
size_t bytes;
if (!data) return; if (!data) return;
@ -133,20 +141,16 @@ static void flush_ea_mt_offsets(VGMSTREAM *vgmstream, int is_start, int samples_
for (i = 0; i < vgmstream->channels; i++) { for (i = 0; i < vgmstream->channels; i++) {
UTKContext* ctx = data[i].utk_context; UTKContext* ctx = data[i].utk_context;
ctx->streamfile = vgmstream->ch[i].streamfile; /* maybe should keep its own STREAMFILE? */ data[i].streamfile = vgmstream->ch[i].streamfile; /* maybe should keep its own STREAMFILE? */
if (is_start) if (is_start)
ctx->offset = vgmstream->ch[i].channel_start_offset; data[i].offset = vgmstream->ch[i].channel_start_offset;
else else
ctx->offset = vgmstream->ch[i].offset; data[i].offset = vgmstream->ch[i].offset;
//todo no need to read, allow to do it manually?
bytes = read_streamfile(ctx->buffer,ctx->offset,sizeof(ctx->buffer),ctx->streamfile);
ctx->offset = ctx->offset + bytes;
ctx->ptr = ctx->buffer; utk_set_ptr(ctx, 0, 0); /* reset the buffer reader */
ctx->end = ctx->buffer + bytes;
ctx->bits_count = 0;
if (is_start) { if (is_start) {
//utk_reset(ctx); //todo
ctx->parsed_header = 0; ctx->parsed_header = 0;
data[i].samples_done = 0; data[i].samples_done = 0;
} }
@ -179,3 +183,16 @@ void free_ea_mt(ea_mt_codec_data *data, int channels) {
} }
free(data); free(data);
} }
/* ********************** */
static size_t ea_mt_read_callback(void *dest, int size, void *arg) {
ea_mt_codec_data *ch_data = arg;
int bytes_read;
bytes_read = read_streamfile(dest,ch_data->offset,size,ch_data->streamfile);
ch_data->offset += bytes_read;
return bytes_read;
}

View File

@ -7,11 +7,10 @@
/* Note: This struct assumes a member alignment of 4 bytes. /* Note: This struct assumes a member alignment of 4 bytes.
** This matters when pitch_lag > 216 on the first subframe of any given frame. */ ** This matters when pitch_lag > 216 on the first subframe of any given frame. */
typedef struct UTKContext { typedef struct UTKContext {
uint8_t buffer[4096]; //vgmstream extra uint8_t *buffer;
STREAMFILE * streamfile; //vgmstream extra size_t buffer_size;
unsigned int offset; //vgmstream extra void *arg;
size_t (*read_callback)(void *dest, int size, void *arg);
FILE *fp;
const uint8_t *ptr, *end; const uint8_t *ptr, *end;
int parsed_header; int parsed_header;
@ -131,14 +130,9 @@ static int utk_read_byte(UTKContext *ctx)
if (ctx->ptr < ctx->end) if (ctx->ptr < ctx->end)
return *ctx->ptr++; return *ctx->ptr++;
//vgmstream extra: this reads from FILE if static buffer was exhausted, now from a context buffer and STREAMFILE instead if (ctx->read_callback) {
if (ctx->streamfile) { //if (ctx->fp) { size_t bytes_copied = ctx->read_callback(ctx->buffer, ctx->buffer_size, ctx->arg);
//static uint8_t buffer[4096]; if (bytes_copied > 0 && bytes_copied <= ctx->buffer_size) {
//size_t bytes_copied = fread(buffer, 1, sizeof(buffer), ctx->fp);
size_t bytes_copied = read_streamfile(ctx->buffer, ctx->offset, sizeof(ctx->buffer), ctx->streamfile);
ctx->offset += bytes_copied;
if (bytes_copied > 0 && bytes_copied <= sizeof(ctx->buffer)) {
ctx->ptr = ctx->buffer; ctx->ptr = ctx->buffer;
ctx->end = ctx->buffer + bytes_copied; ctx->end = ctx->buffer + bytes_copied;
return *ctx->ptr++; return *ctx->ptr++;
@ -394,9 +388,10 @@ static void utk_init(UTKContext *ctx)
memset(ctx, 0, sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx));
} }
static void utk_reset(UTKContext *ctx) //vgmstream extra static void utk_reset(UTKContext *ctx)
{ {
/* resets the internal state, leaving the external config/buffers set */ /* resets the internal state, leaving the external config/buffers
* untouched (could be reset externally or using utk_set_x) */
ctx->parsed_header = 0; ctx->parsed_header = 0;
ctx->bits_value = 0; ctx->bits_value = 0;
ctx->bits_count = 0; ctx->bits_count = 0;
@ -408,10 +403,14 @@ static void utk_reset(UTKContext *ctx) //vgmstream extra
memset(ctx->adapt_cb, 0, sizeof(ctx->adapt_cb)); memset(ctx->adapt_cb, 0, sizeof(ctx->adapt_cb));
memset(ctx->decompressed_frame, 0, sizeof(ctx->decompressed_frame)); memset(ctx->decompressed_frame, 0, sizeof(ctx->decompressed_frame));
} }
#if 0 //vgmstream extra
static void utk_set_fp(UTKContext *ctx, FILE *fp) static void utk_set_callback(UTKContext *ctx, uint8_t *buffer, size_t buffer_size, void *arg, size_t (*read_callback)(void *, int , void *))
{ {
ctx->fp = fp; /* prepares for external reading */
ctx->buffer = buffer;
ctx->buffer_size = buffer_size;
ctx->arg = arg;
ctx->read_callback = read_callback;
/* reset the bit reader */ /* reset the bit reader */
ctx->bits_count = 0; ctx->bits_count = 0;
@ -419,13 +418,14 @@ static void utk_set_fp(UTKContext *ctx, FILE *fp)
static void utk_set_ptr(UTKContext *ctx, const uint8_t *ptr, const uint8_t *end) static void utk_set_ptr(UTKContext *ctx, const uint8_t *ptr, const uint8_t *end)
{ {
/* sets the pointer to an external data buffer (can also be used to
* reset the buffered data if set to ptr/end 0) */
ctx->ptr = ptr; ctx->ptr = ptr;
ctx->end = end; ctx->end = end;
/* reset the bit reader */ /* reset the bit reader */
ctx->bits_count = 0; ctx->bits_count = 0;
} }
#endif
/* /*
** MicroTalk Revision 3 decoding function. ** MicroTalk Revision 3 decoding function.
@ -453,34 +453,17 @@ static int utk_rev3_decode_frame(UTKContext *ctx)
** crafted MT5:1 file can crash sx.exe. ** crafted MT5:1 file can crash sx.exe.
** We will throw an error instead. */ ** We will throw an error instead. */
if (offset < 0 || offset > 432) { if (offset < 0 || offset > 432) {
//fprintf(stderr, "error: invalid PCM offset %d\n", offset); return -1; /* invalid PCM offset */
//exit(EXIT_FAILURE);
return -1; //vgmstream extra
} }
if (count < 0 || count > 432 - offset) { if (count < 0 || count > 432 - offset) {
//fprintf(stderr, "error: invalid PCM count %d\n", count); return -2; /* invalid PCM count */
//exit(EXIT_FAILURE);
return -2; //vgmstream extra
} }
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
ctx->decompressed_frame[offset+i] = (float)utk_read_i16(ctx); ctx->decompressed_frame[offset+i] = (float)utk_read_i16(ctx);
} }
return 0; //vgmstream extra return 0;
} }
#if 0 //vgmstream extra
static const char * utk_get_error_string(int error)
{
switch(error) {
case -1:
return "invalid rev3 PCM offset";
case -2:
return "invalid rev3 PCM count";
default:
return "unknown error";
}
}
#endif
#endif /* _EA_MT_DECODER_UTK_H_ */ #endif /* _EA_MT_DECODER_UTK_H_ */