diff --git a/src/coding/tac_decoder.c b/src/coding/tac_decoder.c index b46f4c18..2cce8df6 100644 --- a/src/coding/tac_decoder.c +++ b/src/coding/tac_decoder.c @@ -12,7 +12,7 @@ struct tac_codec_data { int encoder_delay; uint8_t buf[TAC_BLOCK_SIZE]; - int read_block; + int feed_block; off_t offset; int16_t* samples; @@ -38,7 +38,7 @@ tac_codec_data* init_tac(STREAMFILE* sf) { data->handle = tac_init(data->buf, bytes); if (!data->handle) goto fail; - data->read_block = 0; /* ok to use current block */ + data->feed_block = 0; /* ok to use current block */ data->offset = bytes; data->channels = TAC_CHANNELS; data->frame_samples = TAC_FRAME_SAMPLES; @@ -66,15 +66,17 @@ static int decode_frame(tac_codec_data* data) { err = tac_decode_frame(data->handle, data->buf); if (err == TAC_PROCESS_NEXT_BLOCK) { - data->read_block = 1; + data->feed_block = 1; return 1; } if (err == TAC_PROCESS_DONE) { + VGM_LOG("TAC: process done (EOF) %i\n", err); goto fail; /* shouldn't reach this */ } if (err != TAC_PROCESS_OK) { + VGM_LOG("TAC: process error %i\n", err); goto fail; } @@ -90,10 +92,10 @@ fail: static int read_frame(tac_codec_data* data, STREAMFILE* sf) { /* new block must be read only when signaled by lib */ - if (data->read_block) { + if (data->feed_block) { int bytes = read_streamfile(data->buf, data->offset, sizeof(data->buf), sf); data->offset += bytes; - data->read_block = 0; + data->feed_block = 0; if (bytes <= 0) goto fail; /* can read less that buf near EOF */ } @@ -139,7 +141,8 @@ void reset_tac(tac_codec_data* data) { tac_reset(data->handle); - data->read_block = 1; + data->offset = 0; + data->feed_block = 1; data->sbuf.filled = 0; data->samples_discard = data->encoder_delay; @@ -149,20 +152,19 @@ void reset_tac(tac_codec_data* data) { void seek_tac(tac_codec_data* data, int32_t num_sample) { int32_t loop_sample; const tac_header_t* hdr; - + if (!data) return; hdr = tac_get_header(data->handle); - loop_sample = hdr->loop_frame * TAC_FRAME_SAMPLES + hdr->loop_discard; + loop_sample = (hdr->loop_frame - 1) * TAC_FRAME_SAMPLES + hdr->loop_discard; if (loop_sample == num_sample) { - /* simulates original looping (that wouldn't clean codec internals) */ - tac_set_loop(data->handle); + tac_set_loop(data->handle); /* direct looping */ data->samples_discard = hdr->loop_discard; data->offset = hdr->loop_offset; - data->read_block = 1; + data->feed_block = 1; data->sbuf.filled = 0; } else { @@ -170,7 +172,7 @@ void seek_tac(tac_codec_data* data, int32_t num_sample) { data->samples_discard = num_sample; data->offset = 0; - data->read_block = 1; + data->feed_block = 1; data->sbuf.filled = 0; } } diff --git a/src/coding/tac_decoder_lib.c b/src/coding/tac_decoder_lib.c index 4627f645..7252e54b 100644 --- a/src/coding/tac_decoder_lib.c +++ b/src/coding/tac_decoder_lib.c @@ -16,8 +16,8 @@ * container?) and handler lib may be "Csd". Looks inspired by MPEG (much simplified) with bits * from other codecs (per-file codebook and 1024 samples). * - * Original decoder is implemented in the PS2's VU1, a coprocessor specialized in vector/SIMD and - * parallel instructions. As VU1 works with many 128 bit registers (typically x4 floats) algorithm + * Original decoder is mainly implemented in the PS2's VU1, a coprocessor specialized in vector/SIMD + * and parallel instructions. As VU1 works with many 128 bit registers (typically x4 floats) algorithm * was tailored to do multiple ops at once. This code tries to simplify it into standard C to a point, * but keeps this vector style in main decoding to ease porting (since tables are made with SIMD in * mind it would need some transposing around) and for PS2 float simulation. @@ -1053,7 +1053,7 @@ static int init_header(tac_header_t* header, const uint8_t* buf) { /* header size ia block-aligned (but actual size can be smaller, ex. VP 00000715) */ if (header->file_size % TAC_BLOCK_SIZE != 0) return TAC_PROCESS_HEADER_ERROR; - /* assumed but should be ok */ + /* loop_discard over max makes game crash, while frame_discard seems to ignore it */ if (header->loop_discard > TAC_FRAME_SAMPLES || header->frame_discard > TAC_FRAME_SAMPLES) return TAC_PROCESS_HEADER_ERROR; /* looping makes sense */ diff --git a/src/coding/tac_decoder_lib.h b/src/coding/tac_decoder_lib.h index 5094b42f..82a610a1 100644 --- a/src/coding/tac_decoder_lib.h +++ b/src/coding/tac_decoder_lib.h @@ -24,15 +24,15 @@ typedef struct tac_handle_t tac_handle_t; typedef struct { /* 0x20 header config */ uint32_t huffman_offset; /* setup */ - uint32_t unknown; /* ignored? may be CDVD stuff (divided/multiplied during PS2 process), not file size related */ - uint16_t loop_frame; /* aligned to block stard */ - uint16_t loop_discard; /* assumed */ - uint16_t frame_count; /* number of valid frames ("block end" frame not included) */ - uint16_t frame_discard; /* assumed */ - uint32_t loop_offset; /* file size if not looped */ - uint32_t file_size; /* actual file size can be a bit smaller if last block is truncated */ + uint32_t unknown; /* ignored? (may be CDVD stuff, divided/multiplied during PS2 process, not size related) */ + uint16_t loop_frame; /* aligned to block start */ + uint16_t loop_discard; /* discarded start samples in loop frame (lower = outputs more) */ + uint16_t frame_count; /* number of valid frames ("block end" frames not included) */ + uint16_t frame_discard; /* discarded end samples in final frame (lower = outputs less), even for non-looped files */ + uint32_t loop_offset; /* points to a block; file size if not looped */ + uint32_t file_size; /* block aligned; actual file size can be a bit smaller if last block is truncated */ uint32_t joint_stereo; /* usually 0 and rarely 1 */ - uint32_t empty; /* null? */ + uint32_t empty; /* always null */ } tac_header_t; diff --git a/src/meta/tac.c b/src/meta/tac.c index 16515a15..fe92ce19 100644 --- a/src/meta/tac.c +++ b/src/meta/tac.c @@ -35,7 +35,7 @@ VGMSTREAM* init_vgmstream_tac(STREAMFILE* sf) { goto fail; channel_count = 2; /* always stereo */ - loop_flag = (loop_offset != stream_size); + loop_flag = (loop_offset != stream_size); /* actual check may be loop_frame > 0? */ start_offset = 0; @@ -45,8 +45,8 @@ VGMSTREAM* init_vgmstream_tac(STREAMFILE* sf) { vgmstream->meta_type = meta_TAC; vgmstream->sample_rate = 48000; - vgmstream->num_samples = frame_count * 1024 - frame_discard; - vgmstream->loop_start_sample = loop_frame * 1024 + loop_discard; + vgmstream->num_samples = frame_count * 1024 - (1024 - frame_discard); + vgmstream->loop_start_sample = (loop_frame - 1) * 1024 + loop_discard; vgmstream->loop_end_sample = vgmstream->num_samples; {