diff --git a/src/coding/coding.h b/src/coding/coding.h index f9ec5b3b..bb90b3f5 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -317,6 +317,16 @@ clHCA_stInfo* hca_get_info(hca_codec_data* data); STREAMFILE* hca_get_streamfile(hca_codec_data* data); +/* tac_decoder */ +typedef struct tac_codec_data tac_codec_data; + +tac_codec_data* init_tac(STREAMFILE* sf); +void decode_tac(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do); +void reset_tac(tac_codec_data* data); +void seek_tac(tac_codec_data* data, int32_t num_sample); +void free_tac(tac_codec_data* data); + + #ifdef VGM_USE_VORBIS /* ogg_vorbis_decoder */ typedef struct ogg_vorbis_codec_data ogg_vorbis_codec_data; diff --git a/src/coding/tac_decoder.c b/src/coding/tac_decoder.c new file mode 100644 index 00000000..b46f4c18 --- /dev/null +++ b/src/coding/tac_decoder.c @@ -0,0 +1,185 @@ +#include "coding.h" +#include "coding_utils_samples.h" + +#include "tac_decoder_lib.h" + + +/* opaque struct */ +struct tac_codec_data { + /* config */ + int channels; + int samples_discard; + int encoder_delay; + + uint8_t buf[TAC_BLOCK_SIZE]; + int read_block; + off_t offset; + + int16_t* samples; + int frame_samples; + + /* frame state */ + s16buf_t sbuf; + + void* handle; +}; + + +/* raw SPEEX */ +tac_codec_data* init_tac(STREAMFILE* sf) { + tac_codec_data* data = NULL; + int bytes; + + + data = calloc(1, sizeof(tac_codec_data)); + if (!data) goto fail; + + bytes = read_streamfile(data->buf, 0x00, sizeof(data->buf), sf); + data->handle = tac_init(data->buf, bytes); + if (!data->handle) goto fail; + + data->read_block = 0; /* ok to use current block */ + data->offset = bytes; + data->channels = TAC_CHANNELS; + data->frame_samples = TAC_FRAME_SAMPLES; + + data->encoder_delay = 0; + data->samples_discard = data->encoder_delay; + + data->samples = malloc(data->channels * data->frame_samples * sizeof(int16_t)); + if (!data->samples) goto fail; + + return data; +fail: + free_tac(data); + return NULL; +} + + +static int decode_frame(tac_codec_data* data) { + int err; + + data->sbuf.samples = data->samples; + data->sbuf.channels = 2; + data->sbuf.filled = 0; + + err = tac_decode_frame(data->handle, data->buf); + + if (err == TAC_PROCESS_NEXT_BLOCK) { + data->read_block = 1; + return 1; + } + + if (err == TAC_PROCESS_DONE) { + goto fail; /* shouldn't reach this */ + } + + if (err != TAC_PROCESS_OK) { + goto fail; + } + + + tac_get_samples_pcm16(data->handle, data->sbuf.samples); + data->sbuf.filled = data->frame_samples; + + return 1; +fail: + return 0; +} + +static int read_frame(tac_codec_data* data, STREAMFILE* sf) { + + /* new block must be read only when signaled by lib */ + if (data->read_block) { + int bytes = read_streamfile(data->buf, data->offset, sizeof(data->buf), sf); + data->offset += bytes; + data->read_block = 0; + if (bytes <= 0) goto fail; /* can read less that buf near EOF */ + } + + return 1; +fail: + return 0; +} + +void decode_tac(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do) { + VGMSTREAMCHANNEL* stream = &vgmstream->ch[0]; + tac_codec_data* data = vgmstream->codec_data; + int ok; + + + while (samples_to_do > 0) { + s16buf_t* sbuf = &data->sbuf; + + if (sbuf->filled <= 0) { + ok = read_frame(data, stream->streamfile); + if (!ok) goto fail; + + ok = decode_frame(data); + if (!ok) goto fail; + } + + if (data->samples_discard) + s16buf_discard(&outbuf, sbuf, &data->samples_discard); + else + s16buf_consume(&outbuf, sbuf, &samples_to_do); + } + + return; + +fail: + /* on error just put some 0 samples */ + VGM_LOG("TAC: decode fail at %x, missing %i samples\n", (uint32_t)data->offset, samples_to_do); + s16buf_silence(&outbuf, &samples_to_do, data->channels); +} + + +void reset_tac(tac_codec_data* data) { + if (!data) return; + + tac_reset(data->handle); + + data->read_block = 1; + data->sbuf.filled = 0; + data->samples_discard = data->encoder_delay; + + return; +} + +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; + if (loop_sample == num_sample) { + /* simulates original looping (that wouldn't clean codec internals) */ + tac_set_loop(data->handle); + + data->samples_discard = hdr->loop_discard; + data->offset = hdr->loop_offset; + data->read_block = 1; + data->sbuf.filled = 0; + } + else { + tac_reset(data->handle); + + data->samples_discard = num_sample; + data->offset = 0; + data->read_block = 1; + data->sbuf.filled = 0; + } +} + +void free_tac(tac_codec_data* data) { + if (!data) + return; + + tac_free(data->handle); + free(data->samples); + free(data); +} diff --git a/src/coding/tac_decoder_lib.c b/src/coding/tac_decoder_lib.c new file mode 100644 index 00000000..2e0d145f --- /dev/null +++ b/src/coding/tac_decoder_lib.c @@ -0,0 +1,1225 @@ +#include +#include +#include +#include +#include + +/* tri-Ace PS2 DCT-style codec. + * + * Adapted from Nisto's decoder w/ VU1 emulation: + * - https://github.com/Nisto/pk3dec + * Info: + * - https://psi-rockin.github.io/ps2tek/ + * - https://github.com/PCSX2/pcsx2/blob/master/pcsx2/VUops.cpp + * + * Codec has no apparent name, but most functions mention "St" (stream?) and "Sac" (sound audio + * 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 + * 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. + * + * Codec returns float samples then converted to PCM16. Output samples are +-1 vs Nisto's/PCSX2's + * results, due to various quirks: + * - simplified PS2 float handling (PS2 VU floats don't map 1:1 to PC IEEE floats), can be re-enabled (slow) + * - various heisenbugs (PC 80b register floats <> 32b memory floats conversions, see transform). + * + * Files are divided into blocks (size 0x4E000). At file start is a simple header and huffman codebook + * then N VBR frames (of size around 0x200~300) containing huffman codes of spectral data. A frame has + * codes for 2 channels, decoded separatedly (first all L then all R). Spectrum coefs are processeed, + * then MDCT(?) + window overlap to get final samples. When a "block end frame" is found, handler must + * get next block and resume decoding (blocks may be pre/post padded, for looping porposes). Game reads + * a couple of blocks at once though. + */ + +/**********************************************************************************/ +/* DEFINITIONS */ +/**********************************************************************************/ +#include "tac_decoder_lib_data.h" +#include "tac_decoder_lib_ops.h" +#include "tac_decoder_lib.h" + +//#define TAC_MAX_FRAME_SIZE 0x300 /* typically around ~0x1d0, observed max is ~0x2e2 */ +#define TAC_CODED_BANDS 27 +#define TAC_CODED_COEFS 32 +#define TAC_TOTAL_POINTS 32 /* not sure about this term */ + + +struct tac_handle_t { + /* base header */ + tac_header_t header; + + /* general state */ + int data_start; /* first frame after huffman tables, within first block */ + int frame_offset; /* current position within block */ + int frame_number; /* frames must be sequential */ + + /* decoding huffman tree state */ + int16_t huff_table_1[257]; /* init once */ + int16_t huff_table_2[TAC_CHANNELS][32]; /* saved between (some) frames */ + int16_t huff_table_3[258]; /* init once */ + uint8_t huff_table_4[16383]; /* init once */ + + int16_t codes[TAC_CHANNELS][TAC_FRAME_SAMPLES]; + + /* decoding vector state */ + REG_VF spectrum[TAC_FRAME_SAMPLES / 4]; /* temp huffman-to-coefs (could be stack) */ + REG_VF wave[TAC_CHANNELS][TAC_FRAME_SAMPLES / 4]; /* final samples, in vector form */ + REG_VF hist[TAC_CHANNELS][TAC_FRAME_SAMPLES / 4]; /* saved between frames */ +}; + + +/**********************************************************************************/ +/* MAIN DECODE */ +/**********************************************************************************/ + +/* similar to MP3's alias reduction step with pre-made SIMD tables: + * lo_out.M = (lo_in.M * AT[0x0+j].N) - (AT[0xF-j].M * lo_hi.N) + * hi_out.N = (lo_hi.N * AT[0x7-j].M) + (AT[0x8+j].N * lo_in.M) */ +static void unpack_antialias(REG_VF* spectrum) { + const REG_VF* AT = ANTIALIASING_TABLE; + int i; + int pos_lo = 0x7; + int pos_hi = 0x8; + + for (i = 0; i < TAC_CODED_BANDS; i++) { + for (int j = 0; j < 4; j++) { + REG_VF lo_in, hi_in, lo_out, hi_out; + + LOAD (_xyzw, &lo_in, spectrum, pos_lo - j); + LOAD (_xyzw, &hi_in, spectrum, pos_hi + j); + + MULx (____w, &lo_out, &lo_in, &AT[0x0+j]); + MSUBx(____w, &lo_out, &AT[0xF-j], &hi_in); + MULw (_x___, &hi_out, &hi_in, &AT[0x7-j]); + MADDw(_x___, &hi_out, &AT[0x8+j], &lo_in); + + MULy (___z_, &lo_out, &lo_in, &AT[0x0+j]); + MSUBy(___z_, &lo_out, &AT[0xF-j], &hi_in); + MULz (__y__, &hi_out, &hi_in, &AT[0x7-j]); + MADDz(__y__, &hi_out, &AT[0x8+j], &lo_in); + + MULz (__y__, &lo_out, &lo_in, &AT[0x0+j]); + MSUBz(__y__, &lo_out, &AT[0xF-j], &hi_in); + MULy (___z_, &hi_out, &hi_in, &AT[0x7-j]); + MADDy(___z_, &hi_out, &AT[0x8+j], &lo_in); + + MULw (_x___, &lo_out, &lo_in, &AT[0x0+j]); + MSUBw(_x___, &lo_out, &AT[0xF-j], &hi_in); + MULx (____w, &hi_out, &hi_in, &AT[0x7-j]); + MADDx(____w, &hi_out, &AT[0x8+j], &lo_in); + + STORE(_xyzw, spectrum, &lo_out, pos_lo - j); + STORE(_xyzw, spectrum, &hi_out, pos_hi + j); + } + + pos_lo += 0x8; + pos_hi += 0x8; + } +} + +/* converts 4 huffman codes to 4 spectrums coefs */ +//SUB_1188 +static void unpack_code4(REG_VF* spectrum, const REG_VF* spc1, const REG_VF* spc2, const REG_VF* code, const REG_VF* idx, int out_pos) { + const REG_VF* ST = SCALE_TABLE; + REG_VF tbc1, tbc2, out; + + /* copy table coefs .N, unless huffman code was 0 */ + if (code->f.x != 0) { + MOVEx(_x___, &tbc1, &ST[idx->i.x + 0]); + MOVEx(_x___, &tbc2, &ST[idx->i.x + 1]); + } else { + MOVEx(_x___, &tbc1, &VECTOR_ZERO); + MOVEx(_x___, &tbc2, &VECTOR_ZERO); + } + + if (code->f.y != 0) { + MOVEx(__y__, &tbc1, &ST[idx->i.y + 0]); + MOVEx(__y__, &tbc2, &ST[idx->i.y + 1]); + } else { + MOVEx(__y__, &tbc1, &VECTOR_ZERO); + MOVEx(__y__, &tbc2, &VECTOR_ZERO); + } + + if (code->f.z != 0) { + MOVEx(___z_, &tbc1, &ST[idx->i.z + 0]); + MOVEx(___z_, &tbc2, &ST[idx->i.z + 1]); + } else { + MOVEx(___z_, &tbc1, &VECTOR_ZERO); + MOVEx(___z_, &tbc2, &VECTOR_ZERO); + } + + if (code->f.w != 0) { + MOVEx(____w, &tbc1, &ST[idx->i.w + 0]); + MOVEx(____w, &tbc2, &ST[idx->i.w + 1]); + } else { + MOVEx(____w, &tbc1, &VECTOR_ZERO); + MOVEx(____w, &tbc2, &VECTOR_ZERO); + } + + /* out = [signed] (scp1/scp2) * (tbc2 - tbc1) + tbc1 */ + DIV (_xyzw, &out, spc1, spc2); + SUB (_xyzw, &tbc2, &tbc2, &tbc1); + MUL (_xyzw, &out, &out, &tbc2); + ADD (_xyzw, &out, &out, &tbc1); + SIGN (_xyzw, &out, code); + + STORE(_xyzw, spectrum, &out, out_pos); +} + +/* Unpacks huffman codes in one band into 32 spectrum coefs, using selected scales for that band. */ +// SUB_C88 +static void unpack_band(REG_VF* spectrum, const int16_t* codes, int band_pos, int* code_pos, int out_pos) { + const REG_VF* ST = SCALE_TABLE; + int i; + int16_t base_index = codes[0]; /* vector table index, max ~35 */ + int16_t band_index = codes[band_pos]; /* vector too */ + REG_VF scale; + + /* index zero = band is not coded and all of its coefs are 0 */ + if (band_index == 0) { + for (i = 0; i < (TAC_CODED_COEFS / 4); i++) { + STORE(_xyzw, spectrum, &VECTOR_ZERO, out_pos+i); + } + return; + } + + /* put final band scale at .y */ + MULy (__y__, &scale, &ST[0x80 + band_index], &ST[base_index]); + + /* unpack coefs */ + for (i = 0; i < 8; i++) { + REG_VF code, idx, tm01, tm02, tm03; + REG_VF spc1, spc2; + + COPY (_xyzw, &code, &codes[(*code_pos)]); + (*code_pos) += 4; + + /* scale coef then round down to int to get table indexes (!!!) */ + ABS (_xyzw, &tm01, &code); + MULy (_xyzw, &tm01, &tm01, &scale); + FMUL (_xyzw, &tm02, &tm01, 512.0); + ADD (_xyzw, &tm03, &tm02, &VECTOR_ONE); + + FTOI0(_xyzw, &idx, &tm02); /* keep idx as int for later (probably could use (int)f.N too) */ + ITOF0(_xyzw, &tm02, &idx); + FMULf(_xyzw, &tm02, 0.00195313); + + FTOI0(_xyzw, &tm03, &tm03); + ITOF0(_xyzw, &tm03, &tm03); + FMULf(_xyzw, &tm03, 0.00195313); + + SUB (_xyzw, &spc1, &tm01, &tm02); + SUB (_xyzw, &spc2, &tm03, &tm02); + + unpack_code4(spectrum, &spc1, &spc2, &code, &idx, out_pos + i); + } +} + +/* Unpacks frame's huffman codes to spectrum coefs. Also done in the VU1 (uses VIFcode UNPACK V4-16 + * to copy 16b huffman codes to VU1 memory as 32b first) but simplified a bit here. */ +// SUB_6E0 +static void unpack_channel(REG_VF* spectrum, const int16_t* codes) { + int i; + + /* Huffman codes has 1 base scale + 27 bands scales + N coefs (up to 27*32). + * Not all bands store codes so an index is needed, after scales */ + int code_pos = TAC_CODED_BANDS + 1; + int out_pos = 0x00; + + /* unpack bands */ + for (i = 1; i < TAC_CODED_BANDS + 1; i++) { + unpack_band(spectrum, codes, i, &code_pos, out_pos); + out_pos += (TAC_CODED_COEFS / 4); /* 8 vectors of 4 coefs, per band */ + } + + /* memset rest up to max (27*32/4)..(32*32/4) */ + for (i = 0xD8; i < 0x100; i++) { + STORE (_xyzw, spectrum, &VECTOR_ZERO, i); + } + + /* tweak spectrum */ + unpack_antialias(spectrum); +} + + +/* in GCC this function seems to cause heisenbugs, copy x4 below to get original results */ +static void transform_dot_product(REG_VF* mac, const REG_VF* spectrum, const REG_VF* TT, int pos_i, int pos_t) { + MUL (_xyzw, mac, &spectrum[pos_i+0], &TT[pos_t+0]); /* resets mac */ + MADD (_xyzw, mac, &spectrum[pos_i+1], &TT[pos_t+1]); + MADD (_xyzw, mac, &spectrum[pos_i+2], &TT[pos_t+2]); + MADD (_xyzw, mac, &spectrum[pos_i+3], &TT[pos_t+3]); + MADD (_xyzw, mac, &spectrum[pos_i+4], &TT[pos_t+4]); + MADD (_xyzw, mac, &spectrum[pos_i+5], &TT[pos_t+5]); + MADD (_xyzw, mac, &spectrum[pos_i+6], &TT[pos_t+6]); + MADD (_xyzw, mac, &spectrum[pos_i+7], &TT[pos_t+7]); +} + +/* take spectrum coefs and, ahem, transform somehow, possibly using a SIMD'd FFT/DCT table. */ +//SUB_1410 +static void transform(REG_VF* wave, const REG_VF* spectrum) { + const REG_VF* TT = TRANSFORM_TABLE; + int i, j; + + int pos_t = 0; + int pos_o = 0; + + for (i = 0; i < TAC_TOTAL_POINTS; i++) { + int pos_i = 0; + REG_VF mac, ror, out; + + for (j = 0; j < 8; j++) { + transform_dot_product(&mac, spectrum, TT, pos_i, pos_t); + pos_i += 8; + MR32 (_xyzw, &ror, &mac); + ADD (_x_z_, &ror, &ror, &mac); + ADDz (_x___, &out, &ror, &ror); + + transform_dot_product(&mac, spectrum, TT, pos_i, pos_t); + pos_i += 8; + MR32 (_xyzw, &ror, &mac); + ADD (__y_w, &ror, &ror, &mac); + ADDw (__y__, &out, &ror, &ror); + + transform_dot_product(&mac, spectrum, TT, pos_i, pos_t); + pos_i += 8; + MR32 (_xyzw, &ror, &mac); + ADD (_x_z_, &ror, &ror, &mac); + ADDx (___z_, &out, &ror, &ror); + + transform_dot_product(&mac, spectrum, TT, pos_i, pos_t); + pos_i += 8; + MR32 (_xyzw, &ror, &mac); + ADD (__y_w, &ror, &ror, &mac); + ADDy (____w, &out, &ror, &ror); + + FMULf(_xyzw, &out, 0.25); + STORE(_xyzw, wave, &out, pos_o++); + } + + pos_t += 0x08; + } +} + + +/* process and apply window/overlap. Similar to MP3's synth granule function. */ +//SUB_1690 +static void process(REG_VF* wave, REG_VF* hist) { + const REG_VF* ST = SYNTH_TABLE; + int i, j; + + int pos_o = 0; + int pos_w = 0; + int pos_h; + int pos_r = 0x200; /* rolls down to 0, becoming 0x10 steps (0x00, 0xF0, 0xE0, ..., 0x00, 0xF0, ...) */ + + for (i = 0; i < TAC_TOTAL_POINTS; i++) { + REG_VF zero, neg1; + /* Sorry... hopefully compiler optimizes. Probably could be simplified with some rearranging below */ + REG_VF tm00, tm01, tm02, tm03, tm04, tm05, tm06, tm07, + tm10, tm11, tm12, tm13, tm14, tm15, tm16, tm17, + tm20, tm21, tm22, tm23, tm24, tm25, tm26, tm27, + tm30, tm31, tm32, tm33, tm34; + /* tmp calcs, meant to be used nearby */ + REG_VF tmpZ; + /* output temps, could STORE as calc'd (like VU1) but thought would be easier to read at the end */ + REG_VF out0, out1, out2, out3, out4, out5, out6, out7, + out8, out9, outA, outB, outC, outD, outE, outF; + + pos_h = pos_r & 0xFF; + pos_r = pos_r - 0x10; + + LOAD (_xyzw, &tm00, wave, pos_w+0); + LOAD (_xyzw, &tm01, wave, pos_w+1); + LOAD (_xyzw, &tm02, wave, pos_w+2); + LOAD (_xyzw, &tm03, wave, pos_w+3); + LOAD (_xyzw, &tm04, wave, pos_w+4); + LOAD (_xyzw, &tm05, wave, pos_w+5); + LOAD (_xyzw, &tm06, wave, pos_w+6); + LOAD (_xyzw, &tm07, wave, pos_w+7); + pos_w += 8; + + MOVE (_xyzw, &zero, &VECTOR_ZERO); /* always 0, used for copying */ + MOVE (_xyzw, &neg1, &VECTOR_M_ONE); /* always -1, used for negating */ + + + /* WTF is going on here? Yeah, no clue. Probably some multi-step FFT/DCT twiddle thing. + * Remember all those separate ops are left as-is to allow PS2 float simulation (disabled though). + * Tried cleaning up some more but... */ + ADDw (_x___, &tm10, &tm01, &tm00); + ADDx (____w, &tm10, &tm01, &tm02); + ADDx (____w, &tm11, &tm02, &tm03); + ADDw (_x___, &tm12, &tm04, &tm03); + ADDw (_x___, &tm13, &tm05, &tm04); + ADDx (____w, &tm13, &tm05, &tm06); + ADDx (____w, &tm12, &tm06, &tm07); + ADDx (__y__, &tm11, &zero, &tm10); + ADDw (___z_, &tm11, &zero, &tm10); + ADDx (__y__, &tm12, &zero, &tm13); + ADDw (___z_, &tm12, &zero, &tm13); + ADDw (_x___, &tm14, &tm00, &tm07); + SUBw (_x___, &tm15, &tm00, &tm07); + ADDz (___z_, &tm16, &tm11, &tm12); + ADDx (___z_, &tm17, &zero, &tm14); + ADDx (____w, &tm16, &zero, &tm15); + SUBz (___z_, &tm10, &tm11, &tm12); + ADDz (_x___, &tm16, &tm12, &tm17); + MULx (___z_, &tm13, &tm10, &ST[0x4]); + ADDz (_x___, &tm17, &tm16, &tm16); + ADDz (__y__, &tm16, &zero, &tm13); + SUBx (___z_, &tm17, &tm17, &tm12); + ADDy (____w, &tm14, &tm11, &tm12); + ADDw (__y__, &tm17, &tm16, &tm16); + SUBy (____w, &tm17, &tm16, &tm16); + SUBz (_x___, &tm20, &tm16, &tm16); + ADDw (__y__, &tm16, &tm11, &tm11); + ADDw (___z_, &tm16, &zero, &tm14); + ADDy (____w, &tm16, &tm12, &tm12); + ADDw (__y__, &tm10, &tm11, &tm12); + SUBw (__y__, &tm13, &tm11, &tm12); + ADDw (__y__, &tm21, &tm11, &tm12); + SUBw (__y__, &tm14, &tm16, &tm16); + + ADDy (___z_, &tm22, &tm16, &tm10); + ADDy (____w, &tm22, &zero, &tm13); + SUBz (__y__, &tm21, &tm21, &tm16); + MULx (__y__, &tm16, &tm14, &ST[0x4]); + ADDz (_x___, &tm23, &tm17, &tm22); + ADDx (_x___, &tm24, &zero, &tm20); + MULx (__y__, &tm21, &tm21, &ST[0x4]); + ADDy (____w, &tm10, &tm22, &tm16); + SUBy (____w, &tm14, &tm22, &tm16); + SUBz (_x___, &tm25, &tm17, &tm22); + ADDy (___z_, &tm23, &tm17, &tm21); + MULw (_x___, &tm21, &ST[0x2], &tm10); + MULx (____w, &tm14, &tm14, &ST[0x6]); + + ADDz (___z_, &tm20, &zero, &tm23); + ADDx (__y__, &tm23, &tm17, &tm21); + ADDw (___z_, &tm21, &zero, &tm14); + ADDy (____w, &tm20, &zero, &tm23); + ADDz (____w, &tm23, &tm17, &tm21); + SUBz (____w, &tm25, &tm17, &tm21); + SUBy (___z_, &tm24, &tm17, &tm21); + SUBx (__y__, &tm25, &tm17, &tm21); + ADDw (__y__, &tm20, &zero, &tm23); + ADDw (__y__, &tm24, &zero, &tm25); + ADDz (___z_, &tm25, &zero, &tm24); + ADDy (____w, &tm24, &zero, &tm25); + ADDz (__y__, &tm10, &tm00, &tm00); + ADDz (__y__, &tm13, &tm03, &tm03); + ADDz (__y__, &tm11, &tm01, &tm01); + ADDy (___z_, &tm11, &tm02, &tm02); + ADDy (_x___, &tm11, &zero, &tm10); + ADDy (____w, &tm11, &zero, &tm13); + ADDz (__y__, &tm10, &tm04, &tm04); + ADDz (__y__, &tm13, &tm07, &tm07); + ADDz (__y__, &tm12, &tm05, &tm05); + ADDy (___z_, &tm12, &tm06, &tm06); + ADDy (_x___, &tm12, &zero, &tm10); + ADDy (____w, &tm12, &zero, &tm13); + ADDz (__y__, &tm26, &tm11, &tm11); + ADDz (__y__, &tm15, &tm12, &tm12); + ADDx (____w, &tm14, &tm11, &tm12); + ADDw (_x___, &tm27, &tm11, &tm12); + SUBw (_x___, &tm10, &tm11, &tm12); + ADDy (____w, &tm26, &zero, &tm15); + ADDw (___z_, &tm26, &zero, &tm14); + ADDy (_x___, &tm16, &tm11, &tm11); + ADDx (____w, &tm16, &zero, &tm10); + ADDw (__y__, &tm22, &tm26, &tm26); + ADDz (_x___, &tm22, &tm27, &tm26); + SUBw (__y__, &tm16, &tm26, &tm26); + SUBz (_x___, &tm14, &tm27, &tm26); + ADDw (___z_, &tm15, &tm11, &tm11); + ADDy (_x___, &tm17, &tm22, &tm22); + MULx (__y__, &tm16, &tm16, &ST[0x4]); + ADDx (___z_, &tm17, &zero, &tm14); + + ADDy (_x___, &tm10, &tm12, &tm12); + ADDw (__y__, &tm17, &tm16, &tm16); + SUBy (____w, &tm17, &tm16, &tm16); + ADDz (____w, &tm16, &tm12, &tm12); + ADDx (___z_, &tm16, &zero, &tm10); + ADDz (__y__, &tm16, &zero, &tm15); + ADDx (_x___, &tm30, &tm23, &tm17); + FMULf(_x___, &tm30, -1.0); + MOVE (_x___, &outC, &tm30); + ADDw (_x___, &tm27, &tm16, &tm16); + ADDz (__y__, &tm27, &tm16, &tm16); + SUBw (_x___, &tm13, &tm16, &tm16); + ADDy (_x___, &tm14, &tm16, &tm16); + ADDz (____w, &tm27, &tm16, &tm16); + ADDx (____w, &tm22, &zero, &tm13); + ADDx (___z_, &tm27, &zero, &tm14); + SUBy (_x___, &tm13, &tm27, &tm27); + SUBw (___z_, &tm15, &tm27, &tm27); + MULx (_x___, &tm13, &tm13, &ST[0x4]); + MULx (___z_, &tm15, &tm15, &ST[0x4]); + ADDx (__y__, &tm21, &zero, &tm13); + ADDz (____w, &tm27, &zero, &tm15); + ADDw (____w, &tm14, &tm22, &tm27); + SUBw (____w, &tm13, &tm22, &tm27); + MULx (____w, &tm14, &tm14, &ST[0x2]); + MULx (____w, &tm13, &tm13, &ST[0x6]); + ADDw (_x___, &tm21, &zero, &tm14); + ADDw (___z_, &tm21, &zero, &tm13); + + ADDx (__y__, &tmpZ, &tm17, &tm21); + ADDy (___z_, &tmpZ, &tm17, &tm21); + ADDz (____w, &tmpZ, &tm17, &tm21); + SUBy (_x___, &tmpZ, &tm22, &tm22); + MULx (__y__, &tm10, &tmpZ, &ST[0x1]); + MULx (___z_, &tm10, &tmpZ, &ST[0x2]); + MULx (____w, &tm10, &tmpZ, &ST[0x3]); + MULx (_x___, &tm10, &tmpZ, &ST[0x4]); + + SUBx (_x___, &tm23, &tm23, &tm17); /* .x not used after this */ + MULx (_x___, &out0, &tm23, &ST[0x4]); + + SUBy (__y__, &tm23, &tm23, &tm10); + SUBz (___z_, &tm23, &tm23, &tm10); + SUBw (____w, &tm23, &tm23, &tm10); + ADDw (__y__, &tm20, &tm20, &tm10); + ADDz (___z_, &tm20, &tm20, &tm10); + ADDy (____w, &tm20, &tm20, &tm10); + ADDx (_x___, &tm20, &tm20, &tm10); + SUBx (_x___, &tm24, &tm24, &tm10); + + SUBx (__y__, &tmpZ, &tm17, &tm21); + SUBy (___z_, &tmpZ, &tm17, &tm21); + SUBz (____w, &tmpZ, &tm17, &tm21); + MULx (__y__, &tm10, &tmpZ, &ST[0x7]); + MULx (___z_, &tm10, &tmpZ, &ST[0x6]); + MULx (____w, &tm10, &tmpZ, &ST[0x5]); + + SUBw (__y__, &tm24, &tm24, &tm10); + SUBz (___z_, &tm24, &tm24, &tm10); + SUBy (____w, &tm24, &tm24, &tm10); + + ADDy (__y__, &tm25, &tm25, &tm10); + ADDz (___z_, &tm25, &tm25, &tm10); + ADDw (____w, &tm25, &tm25, &tm10); + + ADDy (_x___, &tm00, &tm00, &tm00); + FMULf(_x___, &tm00, -1.0); + ADDw (___z_, &tm10, &tm00, &tm00); + ADDy (_x___, &tm10, &tm01, &tm01); + FMULf(_x___, &tm10, -1.0); + ADDz (____w, &tm00, &tm01, &tm01); + ADDz (__y__, &tm00, &zero, &tm10); + ADDy (_x___, &tm01, &tm02, &tm02); + FMULf(_x___, &tm01, -1.0); + ADDw (___z_, &tm10, &tm02, &tm02); + ADDy (_x___, &tm13, &tm03, &tm03); + FMULf(_x___, &tm13, -1.0); + ADDx (___z_, &tm00, &zero, &tm10); + ADDz (__y__, &tm01, &zero, &tm10); + ADDz (____w, &tm01, &tm03, &tm03); + ADDy (_x___, &tm02, &tm04, &tm04); + FMULf(_x___, &tm02, -1.0); + ADDw (___z_, &tm10, &tm04, &tm04); + ADDx (___z_, &tm01, &zero, &tm13); + ADDy (_x___, &tm13, &tm05, &tm05); + FMULf(_x___, &tm13, -1.0); + ADDz (__y__, &tm02, &zero, &tm10); + ADDz (____w, &tm02, &tm05, &tm05); + ADDy (_x___, &tm03, &tm06, &tm06); + FMULf(_x___, &tm03, -1.0); + ADDw (___z_, &tm10, &tm06, &tm06); + ADDy (_x___, &tm14, &tm07, &tm07); + FMULf(_x___, &tm14, -1.0); + ADDx (___z_, &tm02, &zero, &tm13); + ADDz (__y__, &tm03, &zero, &tm10); + ADDz (____w, &tm03, &tm07, &tm07); + + ADDx (___z_, &tm03, &zero, &tm14); + ADDz (__y__, &tm11, &tm00, &tm00); + ADDx (____w, &tm10, &tm00, &tm01); + ADDz (__y__, &tm10, &tm01, &tm01); + ADDw (_x___, &tm12, &tm02, &tm01); + ADDz (__y__, &tm12, &tm02, &tm02); + ADDw (___z_, &tm11, &zero, &tm10); + ADDy (____w, &tm11, &zero, &tm10); + ADDx (____w, &tm10, &tm02, &tm03); + ADDz (__y__, &tm10, &tm03, &tm03); + ADDy (__y__, &tm13, &tm11, &tm12); + ADDw (__y__, &tm26, &tm11, &tm11); + ADDw (___z_, &tm12, &zero, &tm10); + ADDy (____w, &tm12, &zero, &tm10); + SUBw (__y__, &tm13, &tm13, &tm11); + ADDy (____w, &tm10, &tm11, &tm12); + ADDy (____w, &tm26, &tm12, &tm12); + SUBz (___z_, &tm14, &tm11, &tm12); + SUBw (__y__, &tm13, &tm13, &tm12); + ADDw (___z_, &tm26, &zero, &tm10); + ADDw (__y__, &tm10, &tm26, &tm26); + MULx (__y__, &tm10, &tm10, &ST[0x4]); + ADDz (__y__, &tm21, &zero, &tm14); + ADDy (_x___, &tm31, &zero, &tm13); + SUBw (__y__, &tm13, &tm26, &tm26); + MULx (__y__, &tm13, &tm13, &ST[0x4]); + + ADDy (___z_, &tm21, &zero, &tm10); + ADDy (___z_, &tm17, &zero, &tm13); + ADDz (___z_, &tm10, &tm21, &tm26); + SUBz (___z_, &tm13, &tm21, &tm26); + ADDz (___z_, &tm30, &tm11, &tm12); + MULx (___z_, &tm10, &tm10, &ST[0x2]); + MULx (___z_, &tm13, &tm13, &ST[0x6]); + MULx (___z_, &tm30, &tm30, &ST[0x4]); + ADDz (__y__, &tm17, &zero, &tm10); + ADDz (____w, &tm17, &zero, &tm13); + ADDz (____w, &tm22, &zero, &tm30); + SUBx (____w, &tm10, &tm22, &tm12); + ADDw (_x___, &tm21, &tm12, &tm22); + + ADDw (___z_, &tm21, &zero, &tm10); + ADDx (__y__, &tm32, &tm17, &tm21); + ADDy (___z_, &tm32, &tm17, &tm21); + FMUL (_x___, &tm33, &tm31, -1.0); + ADDz (____w, &tm32, &tm17, &tm21); + FMUL (__y__, &tm10, &tm32, -1.0); + FMUL (___z_, &tm33, &tm32, -1.0); + SUBz (____w, &tm14, &tm17, &tm21); + FMUL (____w, &tm13, &tm32, -1.0); + ADDy (____w, &tm33, &zero, &tm10); + SUBy (___z_, &tm31, &tm17, &tm21); + ADDw (__y__, &tm31, &zero, &tm14); + ADDw (__y__, &tm33, &zero, &tm13); + SUBx (__y__, &tm13, &tm17, &tm21); + FMUL (___z_, &tm34, &tm31, -1.0); + FMUL (__y__, &tm10, &tm31, -1.0); + ADDy (____w, &tm31, &zero, &tm13); + ADDy (____w, &tm34, &zero, &tm10); + FMUL (____w, &tm10, &tm31, -1.0); + ADDw (__y__, &tm34, &zero, &tm10); + ADDy (_x___, &tm11, &tm00, &tm00); + ADDw (___z_, &tm10, &tm00, &tm00); + ADDy (_x___, &tm13, &tm01, &tm01); + ADDz (____w, &tm11, &tm01, &tm01); + ADDy (_x___, &tm12, &tm02, &tm02); + ADDz (__y__, &tm11, &zero, &tm10); + ADDx (___z_, &tm11, &zero, &tm13); + ADDw (___z_, &tm10, &tm02, &tm02); + ADDy (_x___, &tm13, &tm03, &tm03); + ADDz (____w, &tm12, &tm03, &tm03); + + ADDz (__y__, &tm12, &zero, &tm10); + ADDx (___z_, &tm12, &zero, &tm13); + SUBy (_x___, &tm34, &tm11, &tm11); + SUBw (___z_, &tm10, &tm11, &tm11); + SUBy (_x___, &tm13, &tm12, &tm12); + SUBw (___z_, &tm14, &tm12, &tm12); + ADDz (__y__, &tm15, &tm12, &tm12); + ADDz (_x___, &tm34, &tm34, &tm10); + ADDx (____w, &tm10, &tm11, &tm12); + ADDz (_x___, &tm13, &tm13, &tm14); + ADDy (____w, &tm16, &zero, &tm15); + ADDz (__y__, &tm16, &tm11, &tm11); + ADDw (___z_, &tm16, &zero, &tm10); + ADDx (_x___, &tm34, &tm34, &tm13); + ADDz (____w, &tm26, &tm12, &tm12); + ADDy (_x___, &tm14, &tm12, &tm12); + ADDw (___z_, &tm15, &tm11, &tm11); + ADDy (_x___, &tm26, &tm11, &tm11); + ADDx (___z_, &tm26, &zero, &tm14); + ADDz (__y__, &tm26, &zero, &tm15); + ADDw (___z_, &tm13, &tm26, &tm26); + ADDy (_x___, &tm27, &tm26, &tm26); + ADDz (__y__, &tm10, &tm26, &tm26); + ADDz (__y__, &tm27, &zero, &tm13); + ADDy (____w, &tm27, &zero, &tm10); + ADDy (_x___, &tm10, &tm27, &tm27); + SUBy (_x___, &tm14, &tm27, &tm27); + ADDy (____w, &tm22, &tm16, &tm16); + SUBw (__y__, &tm21, &tm16, &tm16); + MULx (_x___, &tm10, &tm10, &ST[0x4]); + MULx (_x___, &tm14, &tm14, &ST[0x4]); + MULx (____w, &tm22, &tm22, &ST[0x4]); + ADDx (___z_, &tm21, &zero, &tm10); + ADDx (___z_, &tm17, &zero, &tm14); + SUBz (____w, &tm30, &tm22, &tm16); + ADDw (___z_, &tm10, &tm21, &tm27); + SUBw (___z_, &tm14, &tm21, &tm27); + ADDz (____w, &tmpZ, &tm22, &tm16); + ADDw (_x___, &tm21, &zero, &tmpZ); + ADDw (___z_, &tm21, &zero, &tm30); + MULx (___z_, &tm10, &tm10, &ST[0x2]); + MULx (___z_, &tm14, &tm14, &ST[0x6]); + ADDz (__y__, &tm17, &zero, &tm10); + ADDz (____w, &tm17, &zero, &tm14); + SUBy (_x___, &tm30, &tm26, &tm26); + ADDx (__y__, &tm10, &tm17, &tm21); + ADDy (___z_, &tm10, &tm17, &tm21); + ADDz (____w, &tm10, &tm17, &tm21); + ADDz (_x___, &tm30, &tm30, &tm26); + MULx (__y__, &tm10, &tm10, &ST[0x1]); + MULx (___z_, &tm10, &tm10, &ST[0x2]); + MULx (____w, &tm10, &tm10, &ST[0x3]); + SUBw (_x___, &tm30, &tm30, &tm26); + MULx (_x___, &tm30, &tm30, &ST[0x4]); + + ADDy (__y__, &tmpZ, &tm32, &tm10); + ADDz (___z_, &tmpZ, &tm32, &tm10); + ADDw (____w, &tmpZ, &tm32, &tm10); + MULz (__y__, &tm32, &tmpZ, &ST[0x0]); + MULx (___z_, &tm32, &tmpZ, &ST[0x1]); + MULz (____w, &tm32, &tmpZ, &ST[0x1]); + MOVE (_x___, &tm32, &zero); + + ADDy (____w, &tm33, &tm33, &tm10); + ADDz (___z_, &tm33, &tm33, &tm10); + ADDw (__y__, &tm33, &tm33, &tm10); + ADDx (_x___, &tm33, &tm33, &tm30); + MULx (_x___, &tm33, &tm33, &ST[0x6]); + + SUBz (____w, &tmpZ, &tm17, &tm21); + SUBy (___z_, &tmpZ, &tm17, &tm21); + SUBx (__y__, &tmpZ, &tm17, &tm21); + MULx (____w, &tm10, &tmpZ, &ST[0x5]); + MULx (___z_, &tm10, &tmpZ, &ST[0x6]); + MULx (__y__, &tm10, &tmpZ, &ST[0x7]); + + ADDx (_x___, &tmpZ, &tm31, &tm30); + ADDw (__y__, &tmpZ, &tm31, &tm10); + ADDz (___z_, &tmpZ, &tm31, &tm10); + ADDy (____w, &tmpZ, &tm31, &tm10); + MULx (_x___, &tm31, &tmpZ, &ST[0x2]); + MULz (__y__, &tm31, &tmpZ, &ST[0x2]); + MULx (___z_, &tm31, &tmpZ, &ST[0x3]); + MULz (____w, &tm31, &tmpZ, &ST[0x3]); + + ADDy (__y__, &tmpZ, &tm23, &tm32); + ADDz (___z_, &tmpZ, &tm23, &tm32); + ADDw (____w, &tmpZ, &tm23, &tm32); + ADDx (_x___, &tmpZ, &tm24, &tm31); + MULy (__y__, &out0, &tmpZ, &ST[0x4]); + MULz (___z_, &out0, &tmpZ, &ST[0x4]); + MULw (____w, &out0, &tmpZ, &ST[0x4]); + MULx (_x___, &out1, &tmpZ, &ST[0x5]); + MULy (____w, &out7, &neg1, &out0); + MULz (___z_, &out7, &neg1, &out0); + MULw (__y__, &out7, &neg1, &out0); + MULx (_x___, &out7, &neg1, &out1); + + SUBy (__y__, &tmpZ, &tm32, &tm23); + SUBz (___z_, &tmpZ, &tm32, &tm23); + SUBw (____w, &tmpZ, &tm32, &tm23); + SUBx (_x___, &tmpZ, &tm31, &tm24); + MULy (____w, &outF, &ST[0x3], &tmpZ); + MULz (___z_, &outF, &ST[0x3], &tmpZ); + MULw (__y__, &outF, &ST[0x3], &tmpZ); + MULx (_x___, &outF, &ST[0x3], &tmpZ); + ADDw (__y__, &out8, &zero, &outF); + ADDz (___z_, &out8, &zero, &outF); + ADDy (____w, &out8, &zero, &outF); + ADDx (_x___, &out9, &zero, &outF); + + ADDw (____w, &tmpZ, &tm34, &tm10); + ADDz (___z_, &tmpZ, &tm34, &tm10); + ADDy (__y__, &tmpZ, &tm34, &tm10); + MULz (__y__, &tm34, &tmpZ, &ST[0x4]); + MULx (___z_, &tm34, &tmpZ, &ST[0x5]); + MULz (____w, &tm34, &tmpZ, &ST[0x5]); + MULx (_x___, &tm34, &tm34, &ST[0x4]); + + ADDy (__y__, &tmpZ, &tm24, &tm31); + ADDz (___z_, &tmpZ, &tm24, &tm31); + ADDw (____w, &tmpZ, &tm24, &tm31); + ADDx (_x___, &tmpZ, &tm25, &tm34); + MULy (__y__, &out1, &tmpZ, &ST[0x5]); + MULz (___z_, &out1, &tmpZ, &ST[0x5]); + MULw (____w, &out1, &tmpZ, &ST[0x5]); + MULx (_x___, &out2, &tmpZ, &ST[0x6]); + MULy (____w, &out6, &neg1, &out1); + MULz (___z_, &out6, &neg1, &out1); + MULw (__y__, &out6, &neg1, &out1); + MULx (_x___, &out6, &neg1, &out2); + + SUBy (__y__, &tmpZ, &tm31, &tm24); + SUBz (___z_, &tmpZ, &tm31, &tm24); + SUBw (____w, &tmpZ, &tm31, &tm24); + SUBx (_x___, &tmpZ, &tm34, &tm25); + MULw (__y__, &outE, &ST[0x2], &tmpZ); + MULz (___z_, &outE, &ST[0x2], &tmpZ); + MULy (____w, &outE, &ST[0x2], &tmpZ); + MULx (_x___, &outE, &ST[0x2], &tmpZ); + ADDw (__y__, &out9, &zero, &outE); + ADDz (___z_, &out9, &zero, &outE); + ADDy (____w, &out9, &zero, &outE); + ADDx (_x___, &outA, &zero, &outE); + + ADDy (__y__, &tmpZ, &tm25, &tm34); + ADDz (___z_, &tmpZ, &tm25, &tm34); + ADDw (____w, &tmpZ, &tm25, &tm34); + ADDx (_x___, &tmpZ, &tm20, &tm33); + MULy (__y__, &out2, &tmpZ, &ST[0x6]); + MULz (___z_, &out2, &tmpZ, &ST[0x6]); + MULw (____w, &out2, &tmpZ, &ST[0x6]); + MULx (_x___, &out3, &tmpZ, &ST[0x7]); + MULy (____w, &out5, &neg1, &out2); + MULz (___z_, &out5, &neg1, &out2); + MULw (__y__, &out5, &neg1, &out2); + MULx (_x___, &out5, &neg1, &out3); + + SUBy (__y__, &tmpZ, &tm34, &tm25); + SUBz (___z_, &tmpZ, &tm34, &tm25); + SUBw (____w, &tmpZ, &tm34, &tm25); + SUBx (_x___, &tmpZ, &tm33, &tm20); + MULw (__y__, &outD, &ST[0x1], &tmpZ); + MULz (___z_, &outD, &ST[0x1], &tmpZ); + MULy (____w, &outD, &ST[0x1], &tmpZ); + MULx (_x___, &outD, &ST[0x1], &tmpZ); + ADDw (__y__, &outA, &zero, &outD); + ADDz (___z_, &outA, &zero, &outD); + ADDy (____w, &outA, &zero, &outD); + ADDx (_x___, &outB, &zero, &outD); + + MULz (__y__, &tm33, &tm33, &ST[0x6]); + MULx (___z_, &tm33, &tm33, &ST[0x7]); + MULz (____w, &tm33, &tm33, &ST[0x7]); + + ADDy (__y__, &tmpZ, &tm20, &tm33); + ADDz (___z_, &tmpZ, &tm20, &tm33); + ADDw (____w, &tmpZ, &tm20, &tm33); + MULw (____w, &out3, &tmpZ, &ST[0x7]); + MULz (___z_, &out3, &tmpZ, &ST[0x7]); + MULy (__y__, &out3, &tmpZ, &ST[0x7]); + MULw (__y__, &out4, &neg1, &out3); + MULz (___z_, &out4, &neg1, &out3); + MULy (____w, &out4, &neg1, &out3); + MOVE (_x___, &out4, &zero); + + SUBy (__y__, &tmpZ, &tm33, &tm20); + SUBz (___z_, &tmpZ, &tm33, &tm20); + SUBw (____w, &tmpZ, &tm33, &tm20); + MULw (__y__, &outC, &ST[0x0], &tmpZ); + MULz (___z_, &outC, &ST[0x0], &tmpZ); + MULy (____w, &outC, &ST[0x0], &tmpZ); + ADDw (__y__, &outB, &zero, &outC); + ADDz (___z_, &outB, &zero, &outC); + ADDy (____w, &outB, &zero, &outC); + MULx (_x___, &out8, &neg1, &out0); + + /* current output */ + STORE(_xyzw, hist, &out0, pos_h + 0x0); + STORE(_xyzw, hist, &out1, pos_h + 0x1); + STORE(_xyzw, hist, &out2, pos_h + 0x2); + STORE(_xyzw, hist, &out3, pos_h + 0x3); + STORE(_xyzw, hist, &out4, pos_h + 0x4); + STORE(_xyzw, hist, &out5, pos_h + 0x5); + STORE(_xyzw, hist, &out6, pos_h + 0x6); + STORE(_xyzw, hist, &out7, pos_h + 0x7); + STORE(_xyzw, hist, &out8, pos_h + 0x8); + STORE(_xyzw, hist, &out9, pos_h + 0x9); + STORE(_xyzw, hist, &outA, pos_h + 0xA); + STORE(_xyzw, hist, &outB, pos_h + 0xB); + STORE(_xyzw, hist, &outC, pos_h + 0xC); + STORE(_xyzw, hist, &outD, pos_h + 0xD); + STORE(_xyzw, hist, &outE, pos_h + 0xE); + STORE(_xyzw, hist, &outF, pos_h + 0xF); + + /* hist/window overlap and update final wave */ + for (j = 0; j < 8; j++) { + const REG_VF* WT = WINDOW_TABLE; + REG_VF out, rnd; + + MUL (_xyzw, &out, &hist[(pos_h + 0x00) & 0xFF], &WT[0x00+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0x18) & 0xFF], &WT[0x08+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0x20) & 0xFF], &WT[0x10+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0x38) & 0xFF], &WT[0x18+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0x40) & 0xFF], &WT[0x20+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0x58) & 0xFF], &WT[0x28+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0x60) & 0xFF], &WT[0x30+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0x78) & 0xFF], &WT[0x38+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0x80) & 0xFF], &WT[0x40+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0x98) & 0xFF], &WT[0x48+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0xA0) & 0xFF], &WT[0x50+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0xB8) & 0xFF], &WT[0x58+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0xC0) & 0xFF], &WT[0x60+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0xD8) & 0xFF], &WT[0x68+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0xE0) & 0xFF], &WT[0x70+j]); + MADD (_xyzw, &out, &hist[(pos_h + 0xF8) & 0xFF], &WT[0x78+j]); + + pos_h++; + + /* base volume and +-0.5 to final sample (+-32767.0) */ + MUL (_xyzw, &out, &out, &VECTOR_VOLUME); + + MOVE (_xyzw, &rnd, &VECTOR_ROUND); + SIGN (_xyzw, &rnd, &out); + ADD (_xyzw, &out, &out, &rnd); + + STORE(_xyzw, wave, &out, pos_o++); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +/* main decoding in the VU1 coprocessor */ +static void decode_vu1(tac_handle_t* h) { + int ch; + + for (ch = 0; ch < TAC_CHANNELS; ch++) { + unpack_channel(h->spectrum, h->codes[ch]); + + transform(h->wave[ch], h->spectrum); + + process(h->wave[ch], h->hist[ch]); + } + + /* Decoded data is originally stored in VUMem1 as clamped ints, though final step + * seems may be done done externally (StFlushWriteBuffer/StMakeFinalOut?) */ +} + +/* read huffman codes for all channels */ +static int read_codes(tac_handle_t* h, const uint8_t* ptr, uint16_t huff_flag, uint32_t huff_cfg) { + int huff_count = 0; + int ch; + uint32_t unkA = 0; + uint32_t unkB = huff_cfg; + uint32_t unkC = 0; + uint32_t unkD = 0xFFFFFFFF; + + for (ch = 0; ch < TAC_CHANNELS; ch++) { + int huff_done = 0; + int huff_todo = 28; + int16_t huff_val = 0; + + for (; huff_done < huff_todo; huff_done++) { + unkD = unkD >> 14; + unkA = h->huff_table_4[(unkB - unkC) / unkD]; + unkC += h->huff_table_3[unkA] * unkD; + unkD *= h->huff_table_1[unkA]; + + while (0xFFFFFF >= (unkC ^ (unkC + unkD))) { + unkB = (unkB << 8) | (*ptr++); + unkD = (unkD << 8); + unkC = (unkC << 8); + } + + while (0xFFFF >= unkD) { + unkD = (((~unkC) + 1) & 0xFFFF) << 8; + unkB = (unkB << 8) | (*ptr++); + unkC = (unkC << 8); + } + + if (unkA >= 0xFE) { + uint32_t unkT; + unkT = unkA == 0xFE; + unkD = unkD >> (unkT ? 8 : 13); + unkA = (unkB - unkC) / unkD; + unkC = unkC + (unkA * unkD); + if (unkT) + unkA += 0xFE; + + while (0xFFFFFF >= (unkC ^ (unkC + unkD))) { + unkB = (unkB << 8) | (*ptr++); + unkD = (unkD << 8); + unkC = (unkC << 8); + } + + while (0xFFFF >= unkD) { + unkD = (((~unkC) + 1) & 0xFFFF) << 8; + unkB = (unkB << 8) | (*ptr++); + unkC = (unkC << 8); + } + } + + if (unkA & 1) { + huff_val = -((((int16_t)unkA) + 1) / 2); + } else { + huff_val = unkA / 2; + } + + if (huff_done < 28) { + if (huff_flag) { + huff_val += h->huff_table_2[ch][huff_done]; + } + + h->huff_table_2[ch][huff_done] = huff_val; + + if (huff_done != 0 && (huff_val << 16) != 0) { + huff_todo += 32; + } + } + + h->codes[ch][huff_done] = huff_val; + } + + huff_count += huff_done; + } + + return huff_count; +} + + +/* CRC-16/GENIBUS implementation */ +/* https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-genibus */ + +#define CRC16_INIT 0xFFFF +#define CRC16_POLY 0x1021 +#define CRC16_XOR_OUT 0xFFFF + +static uint16_t crc16(const uint8_t* data, int length) { + uint16_t i, crc = CRC16_INIT; + + while (length--) { + for (crc ^= *data++ << 8, i = 0; i < 8; i++) { + crc = (crc & 0x8000) ? crc << 1 ^ CRC16_POLY : crc << 1; + } + } + + return crc ^ CRC16_XOR_OUT; +} + +/* ************************************************************************* */ +/* SETUP */ +/* ************************************************************************* */ + +static uint32_t get_u32be(const uint8_t* mem) { + return (mem[0] << 24) | (mem[1] << 16) | (mem[2] << 8) | mem[3]; +} + +static uint32_t get_u32le(const uint8_t* mem) { + return (mem[3] << 24) | (mem[2] << 16) | (mem[1] << 8) | mem[0]; +} + +static uint16_t get_u16le(const uint8_t* mem) { + return (mem[1] << 8) | mem[0]; +} + +static int init_header(tac_header_t* header, const uint8_t* buf) { + header->huffman_offset = get_u32le(buf+0x00); + header->unknown1 = get_u32le(buf+0x04); + header->loop_frame = get_u16le(buf+0x08); + header->loop_discard = get_u16le(buf+0x0A); + header->frame_count = get_u16le(buf+0x0C); + header->frame_discard = get_u16le(buf+0x0E); + header->loop_offset = get_u32le(buf+0x10); + header->file_size = get_u32le(buf+0x14); + header->unknown2 = get_u32le(buf+0x18); + header->empty = get_u32le(buf+0x1c); + + /* huffman table offset should make sense */ + if (header->huffman_offset < 0x20 || header->huffman_offset > TAC_BLOCK_SIZE) + return TAC_PROCESS_HEADER_ERROR; + /* 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 */ + if (header->loop_discard > TAC_FRAME_SAMPLES || header->frame_discard > TAC_FRAME_SAMPLES) + return TAC_PROCESS_HEADER_ERROR; + /* looping makes sense */ + if (header->loop_frame > header->frame_count || header->loop_offset > header->file_size) + return TAC_PROCESS_HEADER_ERROR; + /* just in case */ + if ((header->unknown2 != 0 && header->unknown2 != 1) || header->empty != 0) + return TAC_PROCESS_HEADER_ERROR; + + return TAC_PROCESS_OK; +} + + +/* AKA RangeDecodeInit (Csd module) */ +static int init_huffman(tac_handle_t* h, const uint8_t* buf) { + uint8_t idx = 0; + int offset = 0; + int i, j; + + /* initialize huff_table_1 with values from header */ + for (i = 0; i < 256; i++) { + int16_t n = buf[offset++]; + + if (n & 0x80) { + n &= 0x7F; + n |= buf[offset++] << 7; + } + + h->huff_table_1[i] = n; + } + + /* zero-initialize huff_table_2 */ + for (i = 0; i < TAC_CHANNELS; i++) { + for (j = 0; j < 32; j++) { + h->huff_table_2[i][j] = 0; + } + } + + /* initialize huff_table_3 */ + h->huff_table_1[256] = 1; + h->huff_table_3[0] = 0; + for (i = 1, j = 0; i < 258; i++, j++) { + h->huff_table_3[i] = h->huff_table_3[j] + h->huff_table_1[j]; + } + + /* initialize huff_table_4 */ + for (idx = 0; !h->huff_table_1[idx]; idx++) { + ; + } + + for (i = 0; i < 16383; i++) { + if (i >= h->huff_table_3[idx+1]) { + while (!h->huff_table_1[++idx]) { + ; + } + } + h->huff_table_4[i] = idx; + } + + return offset; +} + +/* ************************************************************************* */ +/* API */ +/* ************************************************************************* */ + +tac_handle_t* tac_init(const uint8_t* buf, int buf_size) { + tac_handle_t* handle = NULL; + + /* assumes 1 block */ + if (buf_size < TAC_BLOCK_SIZE) + goto fail; + + handle = malloc(sizeof(tac_handle_t)); + if (!handle) goto fail; + + { + int res, pos; + + res = init_header(&handle->header, buf); + if (res != TAC_PROCESS_OK) goto fail; + + pos = init_huffman(handle, &buf[handle->header.huffman_offset]); + if (pos <= 0) goto fail; + + handle->data_start = handle->header.huffman_offset + pos; + if (handle->data_start > TAC_BLOCK_SIZE) + goto fail; + } + + tac_reset(handle); + + return handle; +fail: + tac_free(handle); + return NULL; +} + +const tac_header_t* tac_get_header(tac_handle_t* handle) { + if (!handle) + return NULL; + return &handle->header; +} + +void tac_free(tac_handle_t* handle) { + if (!handle) + return; + free(handle); +} + +void tac_reset(tac_handle_t* handle) { + if (!handle) + return; + + handle->frame_offset = handle->data_start; + handle->frame_number = 1; + + memset(handle->hist, 0, sizeof(REG_VF) * TAC_CHANNELS * (TAC_FRAME_SAMPLES / 4)); + memset(handle->huff_table_2, 0, sizeof(int16_t) * TAC_CHANNELS * 32); +} + + +int tac_decode_frame(tac_handle_t* handle, const uint8_t* block) { + int pos = handle->frame_offset; + + if (handle->frame_number > handle->header.frame_count) + return TAC_PROCESS_DONE; + + if (pos + 0x04 > TAC_BLOCK_SIZE) + return TAC_PROCESS_ERROR_SIZE; + + /* new block marker (may be right at block's end) */ + if (get_u32le(block + pos) == 0xFFFFFFFF) { + handle->frame_offset = 0; /* start at the beginning of next block */ + return TAC_PROCESS_NEXT_BLOCK; + } + + if (pos + 0x0C > TAC_BLOCK_SIZE) + return TAC_PROCESS_ERROR_SIZE; + + + /* read new frame */ + { + const uint8_t* buf = &block[pos]; /* current frame */ + uint16_t frame_crc = get_u16le(buf + 0x00); /* checksum of data starting at 0x04 */ + uint16_t huff_flag = get_u16le(buf + 0x02) >> 15; /* 0 every 64th frame, 1 for others */ + uint16_t frame_size = get_u16le(buf + 0x02) & 0x7FFF; /* not including base header (0x08) */ + uint16_t frame_id = get_u16le(buf + 0x04); /* current number */ + uint16_t huff_count = get_u16le(buf + 0x06); /* huffman decoded length */ + + uint32_t huff_cfg = get_u32be(buf + 0x08); /* huffman table setup */ + uint16_t crc_calc, huff_read; + + if (frame_id != handle->frame_number) + return TAC_PROCESS_ERROR_ID; + + if (pos + 0x08 + frame_size > TAC_BLOCK_SIZE) + return TAC_PROCESS_ERROR_SIZE; + + /* from tests seems CRC errors cause current frame to be skipped */ + handle->frame_number++; + handle->frame_offset += 0x08 + frame_size; + + crc_calc = crc16(buf + 0x04, 0x04 + frame_size); + if (frame_crc != crc_calc) + return TAC_PROCESS_ERROR_CRC; + + /* extract huffman frame codes */ + huff_read = read_codes(handle, buf + 0x0C, huff_flag, huff_cfg); + if (huff_read != huff_count) + return TAC_PROCESS_ERROR_HUFFMAN; + + /* main decode */ + decode_vu1(handle); + } + + /* current frame decoded and samples can be requested */ + return TAC_PROCESS_OK; +} + + +static inline int16_t clamp16f(float sample) { + if (sample > 32767.0) + return 32767; + else if (sample < -32768.0) + return -32768; + return (int16_t)sample; +} + +void tac_get_samples_pcm16(tac_handle_t* handle, int16_t* dst) { + int ch, i; + int chs = TAC_CHANNELS; + + for (ch = 0; ch < chs; ch++) { + int s = 0; + for (i = 0; i < TAC_FRAME_SAMPLES / 4; i++) { + dst[(s+0)*chs + ch] = clamp16f(handle->wave[ch][i].f.x); + dst[(s+1)*chs + ch] = clamp16f(handle->wave[ch][i].f.y); + dst[(s+2)*chs + ch] = clamp16f(handle->wave[ch][i].f.z); + dst[(s+3)*chs + ch] = clamp16f(handle->wave[ch][i].f.w); + s += 4; + } + } +} + + +void tac_set_loop(tac_handle_t* handle) { + handle->frame_number = handle->header.loop_frame; + handle->frame_offset = 0; +} diff --git a/src/coding/tac_decoder_lib.h b/src/coding/tac_decoder_lib.h new file mode 100644 index 00000000..e2a743b7 --- /dev/null +++ b/src/coding/tac_decoder_lib.h @@ -0,0 +1,55 @@ +#ifndef _TAC_DECODER_LIB_H_ +#define _TAC_DECODER_LIB_H_ + +/* tri-Ace Codec (TAC) lib, found in PS2 games */ + +#include + +#define TAC_SAMPLE_RATE 48000 +#define TAC_CHANNELS 2 +#define TAC_FRAME_SAMPLES 1024 +#define TAC_BLOCK_SIZE 0x4E000 /* size of a single block with N VBR frames */ + +#define TAC_PROCESS_OK 0 /* frame decoded correctly */ +#define TAC_PROCESS_NEXT_BLOCK 1 /* must pass next block (didn't decode) */ +#define TAC_PROCESS_DONE 2 /* no more frames to do (didn't decode) */ +#define TAC_PROCESS_HEADER_ERROR -1 /* file doesn't match expected header */ +#define TAC_PROCESS_ERROR_SIZE -2 /* buffer is smaller than needed */ +#define TAC_PROCESS_ERROR_ID -3 /* expected frame id mismatch */ +#define TAC_PROCESS_ERROR_CRC -4 /* expected frame crc mismatch */ +#define TAC_PROCESS_ERROR_HUFFMAN -5 /* expected huffman count mismatch */ + +typedef struct tac_handle_t tac_handle_t; + +typedef struct { + /* 0x20 header config */ + uint32_t huffman_offset; /* setup */ + uint32_t unknown1; /* 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 unknown2; /* usually 0 and rarely 1 (R channel has less data, joint stereo mode?) */ + uint32_t empty; /* null? */ +} tac_header_t; + + +/* inits codec with data from at least one block */ +tac_handle_t* tac_init(const uint8_t* buf, int buf_size); + +const tac_header_t* tac_get_header(tac_handle_t* handle); + +void tac_reset(tac_handle_t* handle); + +void tac_free(tac_handle_t* handle); + +/* decodes a frame from current block (of TAC_BLOCK_SIZE), returning TAC_PROCESS_* codes */ +int tac_decode_frame(tac_handle_t* handle, const uint8_t* block); + +void tac_get_samples_pcm16(tac_handle_t* handle, int16_t* dst); + +void tac_set_loop(tac_handle_t* handle); + +#endif /* _TAC_DECODER_LIB_H_ */ diff --git a/src/coding/tac_decoder_lib_data.h b/src/coding/tac_decoder_lib_data.h new file mode 100644 index 00000000..a53b8269 --- /dev/null +++ b/src/coding/tac_decoder_lib_data.h @@ -0,0 +1,1002 @@ +#ifndef _TAC_DECODER_LIB_DATA_H_ +#define _TAC_DECODER_LIB_DATA_H_ + +/* VU1 register simulation, needs type conversion at times (should be optimized out by compiler). */ +typedef union { + struct { + float x,y,z,w; + } f; + + struct { + uint32_t x,y,z,w; + } i; + + float F[4]; + uint32_t UL[4]; + int32_t SL[4]; + /* can access as US/SS/etc but not needed by current code */ +} _REG_VF; +typedef _REG_VF REG_VF; + + static const int _xyzw = 0xF; +//static const int _xyz_ = 0xE; +//static const int _xy_w = 0xD; +//static const int _xy__ = 0xC; +//static const int _x_zw = 0xB; + static const int _x_z_ = 0xA; +//static const int _x__w = 0x9; + static const int _x___ = 0x8; + static const int __yzw = 0x7; +//static const int __yz_ = 0x6; + static const int __y_w = 0x5; + static const int __y__ = 0x4; +//static const int ___zw = 0x3; + static const int ___z_ = 0x2; + static const int ____w = 0x1; + + +/* "Sac" master volume. Originally an int array (volume=16256, unused=0, unused=16397, unused=0) + * loaded into memory then copied to float register via code. May depend on global volume settings + * rather than fixed though (this value is for the opening). */ +static REG_VF VECTOR_VOLUME = { .f = {16256.0f, 16256.0f, 16256.0f, 16256.0f} }; +static REG_VF VECTOR_ZERO = { .f = {0.0f, 0.0f, 0.0f, 0.0f} }; +static REG_VF VECTOR_ONE = { .f = {1.0f, 1.0f, 1.0f, 1.0f} }; +static REG_VF VECTOR_ROUND = { .f = {0.5f, 0.5f, 0.5f, 0.5f} }; +static REG_VF VECTOR_M_ONE = { .f = {-1.0f, -1.0f, -1.0f, -1.0f} }; + + +/* Tables found in the main ELF, then loaded to VU1 memory. + * Floats are an approximate representation of the hex value, but should end up correctly using that hex + * (ex. 0.857492924 and 0.857492925 both are 0x3F5B84A8). 9 decimals should be enough for all? tables. */ + +/* MPEG antialiasing table */ +static const REG_VF ANTIALIASING_TABLE[64/4] = { + { .i = {0x3F5B84A8,0x3F5E682F,0x3F61B9D7,0x3F6B2DE7} }, //+0.857492924f, +0.868777215f, +0.881741941f, +0.918669164f + { .i = {0x3F731ADE,0x3F77C337,0x3F7BBA82,0x3F7D8708} }, //+0.949628711f, +0.967822492f, +0.983314633f, +0.990341663f + { .i = {0x3F7EDA43,0x3F51B92F,0x3F7FC8FC,0x3F7B0756} }, //+0.995517910f, +0.819231927f, +0.999160528f, +0.980580688f + { .i = {0x3F7FF966,0x3F7FFE66,0x3F7FFF8E,0x3F800000} }, //+0.999899268f, +0.999975562f, +0.999993205f, +1.000000000f + { .i = {0x3F800000,0x3F7FFF8E,0x3F7FFE66,0x3F7FF966} }, //+1.000000000f, +0.999993205f, +0.999975562f, +0.999899268f + { .i = {0x3F7B0756,0x3F7FC8FC,0x3F51B92F,0x3F7EDA43} }, //+0.980580688f, +0.999160528f, +0.819231927f, +0.995517910f + { .i = {0x3F7D8708,0x3F7BBA82,0x3F77C337,0x3F731ADE} }, //+0.990341663f, +0.983314633f, +0.967822492f, +0.949628711f + { .i = {0x3F6B2DE7,0x3F61B9D7,0x3F5E682F,0x3F5B84A8} }, //+0.918669164f, +0.881741941f, +0.868777215f, +0.857492924f + { .i = {0xBF03B5FF,0xBEFD8B40,0xBEF186DA,0xBECA4114} }, //-0.514495790f, -0.495203018f, -0.471731961f, -0.395027757f + { .i = {0xBEA07304,0xBE80D626,0xBE3A4775,0xBE0DF9B3} }, //-0.313377500f, -0.251633823f, -0.181913212f, -0.138647839f + { .i = {0xBDC1B01E,0xBF12CE6D,0xBD27CB87,0xBE48D2AC} }, //-0.094574198f, -0.573462307f, -0.040965583f, -0.196116149f + { .i = {0xBC68A11E,0xBBE55ED3,0xBB727B47,0x00000000} }, //-0.014198570f, -0.006999829f, -0.003699975f, +0.000000000f + { .i = {0x00000000,0xBB727B47,0xBBE55ED3,0xBC68A11E} }, //+0.000000000f, -0.003699975f, -0.006999829f, -0.014198570f + { .i = {0xBE48D2AC,0xBD27CB87,0xBF12CE6D,0xBDC1B01E} }, //-0.196116149f, -0.040965583f, -0.573462307f, -0.094574198f + { .i = {0xBE0DF9B3,0xBE3A4775,0xBE80D626,0xBEA07304} }, //-0.138647839f, -0.181913212f, -0.251633823f, -0.313377500f + { .i = {0xBECA4114,0xBEF186DA,0xBEFD8B40,0xBF03B5FF} }, //-0.395027757f, -0.471731961f, -0.495203018f, -0.514495790f +}; + +/* Seemingly scale factor table (needs an extra index, see end). + * ELF seems to store only xy, zw is just mirrored. */ +static const REG_VF SCALE_TABLE[2048/4 + 4/4] = { + /* part 1 */ + { .i = {0x00000000,0x3F7F8000,0x00000000,0x3F7F8000} }, //+0.000000000f, +0.998046875f, +0.000000000f, +0.998046875f + { .i = {0x3A000000,0x3F5744FD,0x3A000000,0x3F5744FD} }, //+0.000488281f, +0.840896428f, +0.000488281f, +0.840896428f + { .i = {0x3AA14518,0x3F3504F3,0x3AA14518,0x3F3504F3} }, //+0.001230392f, +0.707106769f, +0.001230392f, +0.707106769f + { .i = {0x3B0A74BA,0x3F1837F0,0x3B0A74BA,0x3F1837F0} }, //+0.002112670f, +0.594603539f, +0.002112670f, +0.594603539f + { .i = {0x3B4B2FF5,0x3F000000,0x3B4B2FF5,0x3F000000} }, //+0.003100393f, +0.500000000f, +0.003100393f, +0.500000000f + { .i = {0x3B88CC4F,0x3ED744FD,0x3B88CC4F,0x3ED744FD} }, //+0.004174746f, +0.420448214f, +0.004174746f, +0.420448214f + { .i = {0x3BAE718E,0x3EB504F3,0x3BAE718E,0x3EB504F3} }, //+0.005323595f, +0.353553385f, +0.005323595f, +0.353553385f + { .i = {0x3BD63F90,0x3E9837F0,0x3BD63F90,0x3E9837F0} }, //+0.006538339f, +0.297301769f, +0.006538339f, +0.297301769f + { .i = {0x3C000000,0x3E800000,0x3C000000,0x3E800000} }, //+0.007812500f, +0.250000000f, +0.007812500f, +0.250000000f + { .i = {0x3C15C41B,0x3E5744FD,0x3C15C41B,0x3E5744FD} }, //+0.009140993f, +0.210224107f, +0.009140993f, +0.210224107f + { .i = {0x3C2C5AD3,0x3E3504F3,0x3C2C5AD3,0x3E3504F3} }, //+0.010519701f, +0.176776692f, +0.010519701f, +0.176776692f + { .i = {0x3C43B5D3,0x3E1837F0,0x3C43B5D3,0x3E1837F0} }, //+0.011945206f, +0.148650885f, +0.011945206f, +0.148650885f + { .i = {0x3C5BC8FF,0x3E000000,0x3C5BC8FF,0x3E000000} }, //+0.013414620f, +0.125000000f, +0.013414620f, +0.125000000f + { .i = {0x3C7489EF,0x3DD744FD,0x3C7489EF,0x3DD744FD} }, //+0.014925464f, +0.105112053f, +0.014925464f, +0.105112053f + { .i = {0x3C86F7CD,0x3DB504F3,0x3C86F7CD,0x3DB504F3} }, //+0.016475582f, +0.088388346f, +0.016475582f, +0.088388346f + { .i = {0x3C93F904,0x3D9837F0,0x3C93F904,0x3D9837F0} }, //+0.018063076f, +0.074325442f, +0.018063076f, +0.074325442f + { .i = {0x3CA14518,0x3D800000,0x3CA14518,0x3D800000} }, //+0.019686267f, +0.062500000f, +0.019686267f, +0.062500000f + { .i = {0x3CAED8DF,0x3D5744FD,0x3CAED8DF,0x3D5744FD} }, //+0.021343647f, +0.052556027f, +0.021343647f, +0.052556027f + { .i = {0x3CBCB181,0x3D3504F3,0x3CBCB181,0x3D3504F3} }, //+0.023033859f, +0.044194173f, +0.023033859f, +0.044194173f + { .i = {0x3CCACC6C,0x3D1837F0,0x3CCACC6C,0x3D1837F0} }, //+0.024755679f, +0.037162721f, +0.024755679f, +0.037162721f + { .i = {0x3CD92746,0x3D000000,0x3CD92746,0x3D000000} }, //+0.026507985f, +0.031250000f, +0.026507985f, +0.031250000f + { .i = {0x3CE7BFE8,0x3CD744FD,0x3CE7BFE8,0x3CD744FD} }, //+0.028289750f, +0.026278013f, +0.028289750f, +0.026278013f + { .i = {0x3CF69458,0x3CB504F3,0x3CF69458,0x3CB504F3} }, //+0.030100033f, +0.022097087f, +0.030100033f, +0.022097087f + { .i = {0x3D02D161,0x3C9837F0,0x3D02D161,0x3C9837F0} }, //+0.031937961f, +0.018581361f, +0.031937961f, +0.018581361f + { .i = {0x3D0A74BA,0x3C800000,0x3D0A74BA,0x3C800000} }, //+0.033802725f, +0.015625000f, +0.033802725f, +0.015625000f + { .i = {0x3D12336D,0x3C5744FD,0x3D12336D,0x3C5744FD} }, //+0.035693575f, +0.013139007f, +0.035693575f, +0.013139007f + { .i = {0x3D1A0CBF,0x3C3504F3,0x3D1A0CBF,0x3C3504F3} }, //+0.037609812f, +0.011048543f, +0.037609812f, +0.011048543f + { .i = {0x3D220000,0x3C1837F0,0x3D220000,0x3C1837F0} }, //+0.039550781f, +0.009290680f, +0.039550781f, +0.009290680f + { .i = {0x3D2A0C8A,0x3C000000,0x3D2A0C8A,0x3C000000} }, //+0.041515864f, +0.007812500f, +0.041515864f, +0.007812500f + { .i = {0x3D3231C3,0x3BD744FD,0x3D3231C3,0x3BD744FD} }, //+0.043504488f, +0.006569503f, +0.043504488f, +0.006569503f + { .i = {0x3D3A6F17,0x3BB504F3,0x3D3A6F17,0x3BB504F3} }, //+0.045516100f, +0.005524272f, +0.045516100f, +0.005524272f + { .i = {0x3D42C3FE,0x3B9837F0,0x3D42C3FE,0x3B9837F0} }, //+0.047550194f, +0.004645340f, +0.047550194f, +0.004645340f + { .i = {0x3D4B2FF5,0x3B800000,0x3D4B2FF5,0x3B800000} }, //+0.049606282f, +0.003906250f, +0.049606282f, +0.003906250f + { .i = {0x3D53B280,0x3B5744FD,0x3D53B280,0x3B5744FD} }, //+0.051683903f, +0.003284752f, +0.051683903f, +0.003284752f + { .i = {0x3D5C4B2A,0x3B3504F3,0x3D5C4B2A,0x3B3504F3} }, //+0.053782620f, +0.002762136f, +0.053782620f, +0.002762136f + { .i = {0x3D64F982,0x3B1837F0,0x3D64F982,0x3B1837F0} }, //+0.055902012f, +0.002322670f, +0.055902012f, +0.002322670f + { .i = {0x3D6DBD20,0x3B000000,0x3D6DBD20,0x3B000000} }, //+0.058041692f, +0.001953125f, +0.058041692f, +0.001953125f + { .i = {0x3D76959C,0x3AD744FD,0x3D76959C,0x3AD744FD} }, //+0.060201272f, +0.001642376f, +0.060201272f, +0.001642376f + { .i = {0x3D7F8298,0x3AB504F3,0x3D7F8298,0x3AB504F3} }, //+0.062380403f, +0.001381068f, +0.062380403f, +0.001381068f + { .i = {0x3D8441DB,0x3A9837F0,0x3D8441DB,0x3A9837F0} }, //+0.064578734f, +0.001161335f, +0.064578734f, +0.001161335f + { .i = {0x3D88CC4F,0x3A800000,0x3D88CC4F,0x3A800000} }, //+0.066795938f, +0.000976563f, +0.066795938f, +0.000976563f + { .i = {0x3D8D607D,0x3A5744FD,0x3D8D607D,0x3A5744FD} }, //+0.069031693f, +0.000821188f, +0.069031693f, +0.000821188f + { .i = {0x3D91FE3D,0x3A3504F3,0x3D91FE3D,0x3A3504F3} }, //+0.071285702f, +0.000690534f, +0.071285702f, +0.000690534f + { .i = {0x3D96A568,0x3A1837F0,0x3D96A568,0x3A1837F0} }, //+0.073557675f, +0.000580668f, +0.073557675f, +0.000580668f + { .i = {0x3D9B55D8,0x3A000000,0x3D9B55D8,0x3A000000} }, //+0.075847328f, +0.000488281f, +0.075847328f, +0.000488281f + { .i = {0x3DA00F69,0x39D744FD,0x3DA00F69,0x39D744FD} }, //+0.078154393f, +0.000410594f, +0.078154393f, +0.000410594f + { .i = {0x3DA4D1F9,0x39B504F3,0x3DA4D1F9,0x39B504F3} }, //+0.080478616f, +0.000345267f, +0.080478616f, +0.000345267f + { .i = {0x3DA99D65,0x399837F0,0x3DA99D65,0x399837F0} }, //+0.082819737f, +0.000290334f, +0.082819737f, +0.000290334f + { .i = {0x3DAE718E,0x39800000,0x3DAE718E,0x39800000} }, //+0.085177526f, +0.000244141f, +0.085177526f, +0.000244141f + { .i = {0x3DB34E55,0x395744FD,0x3DB34E55,0x395744FD} }, //+0.087551750f, +0.000205297f, +0.087551750f, +0.000205297f + { .i = {0x3DB8339A,0x393504F3,0x3DB8339A,0x393504F3} }, //+0.089942172f, +0.000172633f, +0.089942172f, +0.000172633f + { .i = {0x3DBD2142,0x391837F0,0x3DBD2142,0x391837F0} }, //+0.092348590f, +0.000145167f, +0.092348590f, +0.000145167f + { .i = {0x3DC21730,0x39000000,0x3DC21730,0x39000000} }, //+0.094770789f, +0.000122070f, +0.094770789f, +0.000122070f + { .i = {0x3DC71549,0x38D744FD,0x3DC71549,0x38D744FD} }, //+0.097208567f, +0.000102648f, +0.097208567f, +0.000102648f + { .i = {0x3DCC1B72,0x38B504F3,0x3DCC1B72,0x38B504F3} }, //+0.099661723f, +0.000086317f, +0.099661723f, +0.000086317f + { .i = {0x3DD12992,0x389837F0,0x3DD12992,0x389837F0} }, //+0.102130070f, +0.000072583f, +0.102130070f, +0.000072583f + { .i = {0x3DD63F90,0x38800000,0x3DD63F90,0x38800000} }, //+0.104613423f, +0.000061035f, +0.104613423f, +0.000061035f + { .i = {0x3DDB5D54,0x385744FD,0x3DDB5D54,0x385744FD} }, //+0.107111603f, +0.000051324f, +0.107111603f, +0.000051324f + { .i = {0x3DE082C7,0x383504F3,0x3DE082C7,0x383504F3} }, //+0.109624438f, +0.000043158f, +0.109624438f, +0.000043158f + { .i = {0x3DE5AFD1,0x381837F0,0x3DE5AFD1,0x381837F0} }, //+0.112151749f, +0.000036292f, +0.112151749f, +0.000036292f + { .i = {0x3DEAE45E,0x38000000,0x3DEAE45E,0x38000000} }, //+0.114693388f, +0.000030518f, +0.114693388f, +0.000030518f + { .i = {0x3DF02057,0x37D744FD,0x3DF02057,0x37D744FD} }, //+0.117249183f, +0.000025662f, +0.117249183f, +0.000025662f + { .i = {0x3DF563A8,0x37B504F3,0x3DF563A8,0x37B504F3} }, //+0.119818985f, +0.000021579f, +0.119818985f, +0.000021579f + { .i = {0x3DFAAE3C,0x379837F0,0x3DFAAE3C,0x379837F0} }, //+0.122402638f, +0.000018146f, +0.122402638f, +0.000018146f + { .i = {0x3E000000,0x37800000,0x3E000000,0x37800000} }, //+0.125000000f, +0.000015259f, +0.125000000f, +0.000015259f + { .i = {0x3E02AC70,0x375744FD,0x3E02AC70,0x375744FD} }, //+0.127610922f, +0.000012831f, +0.127610922f, +0.000012831f + { .i = {0x3E055C65,0x373504F3,0x3E055C65,0x373504F3} }, //+0.130235270f, +0.000010790f, +0.130235270f, +0.000010790f + { .i = {0x3E080FD6,0x371837F0,0x3E080FD6,0x371837F0} }, //+0.132872909f, +0.000009073f, +0.132872909f, +0.000009073f + { .i = {0x3E0AC6BA,0x37000000,0x3E0AC6BA,0x37000000} }, //+0.135523707f, +0.000007629f, +0.135523707f, +0.000007629f + { .i = {0x3E0D8108,0x36D744FD,0x3E0D8108,0x36D744FD} }, //+0.138187528f, +0.000006416f, +0.138187528f, +0.000006416f + { .i = {0x3E103EB7,0x36B504F3,0x3E103EB7,0x36B504F3} }, //+0.140864238f, +0.000005395f, +0.140864238f, +0.000005395f + { .i = {0x3E12FFC0,0x369837F0,0x3E12FFC0,0x369837F0} }, //+0.143553734f, +0.000004536f, +0.143553734f, +0.000004536f + { .i = {0x3E15C41B,0x36800000,0x3E15C41B,0x36800000} }, //+0.146255895f, +0.000003815f, +0.146255895f, +0.000003815f + { .i = {0x3E188BBF,0x365744FD,0x3E188BBF,0x365744FD} }, //+0.148970589f, +0.000003208f, +0.148970589f, +0.000003208f + { .i = {0x3E1B56A5,0x363504F3,0x3E1B56A5,0x363504F3} }, //+0.151697710f, +0.000002697f, +0.151697710f, +0.000002697f + { .i = {0x3E1E24C5,0x361837F0,0x3E1E24C5,0x361837F0} }, //+0.154437140f, +0.000002268f, +0.154437140f, +0.000002268f + { .i = {0x3E20F618,0x36000000,0x3E20F618,0x36000000} }, //+0.157188773f, +0.000001907f, +0.157188773f, +0.000001907f + { .i = {0x3E23CA96,0x35D744FD,0x3E23CA96,0x35D744FD} }, //+0.159952492f, +0.000001604f, +0.159952492f, +0.000001604f + { .i = {0x3E26A239,0x35B504F3,0x3E26A239,0x35B504F3} }, //+0.162728205f, +0.000001349f, +0.162728205f, +0.000001349f + { .i = {0x3E297CFA,0x359837F0,0x3E297CFA,0x359837F0} }, //+0.165515810f, +0.000001134f, +0.165515810f, +0.000001134f + { .i = {0x3E2C5AD3,0x35800000,0x3E2C5AD3,0x35800000} }, //+0.168315217f, +0.000000954f, +0.168315217f, +0.000000954f + { .i = {0x3E2F3BBB,0x355744FD,0x3E2F3BBB,0x355744FD} }, //+0.171126291f, +0.000000802f, +0.171126291f, +0.000000802f + { .i = {0x3E321FAD,0x353504F3,0x3E321FAD,0x353504F3} }, //+0.173948959f, +0.000000674f, +0.173948959f, +0.000000674f + { .i = {0x3E3506A4,0x351837F0,0x3E3506A4,0x351837F0} }, //+0.176783144f, +0.000000567f, +0.176783144f, +0.000000567f + { .i = {0x3E37F097,0x35000000,0x3E37F097,0x35000000} }, //+0.179628715f, +0.000000477f, +0.179628715f, +0.000000477f + { .i = {0x3E3ADD82,0x34D744FD,0x3E3ADD82,0x34D744FD} }, //+0.182485610f, +0.000000401f, +0.182485610f, +0.000000401f + { .i = {0x3E3DCD5E,0x34B504F3,0x3E3DCD5E,0x34B504F3} }, //+0.185353726f, +0.000000337f, +0.185353726f, +0.000000337f + { .i = {0x3E40C025,0x349837F0,0x3E40C025,0x349837F0} }, //+0.188232973f, +0.000000284f, +0.188232973f, +0.000000284f + { .i = {0x3E43B5D3,0x34800000,0x3E43B5D3,0x34800000} }, //+0.191123292f, +0.000000238f, +0.191123292f, +0.000000238f + { .i = {0x3E46AE60,0x345744FD,0x3E46AE60,0x345744FD} }, //+0.194024563f, +0.000000200f, +0.194024563f, +0.000000200f + { .i = {0x3E49A9C8,0x343504F3,0x3E49A9C8,0x343504F3} }, //+0.196936727f, +0.000000169f, +0.196936727f, +0.000000169f + { .i = {0x3E4CA806,0x341837F0,0x3E4CA806,0x341837F0} }, //+0.199859709f, +0.000000142f, +0.199859709f, +0.000000142f + { .i = {0x3E4FA913,0x34000000,0x3E4FA913,0x34000000} }, //+0.202793404f, +0.000000119f, +0.202793404f, +0.000000119f + { .i = {0x3E52ACEA,0x33D744FD,0x3E52ACEA,0x33D744FD} }, //+0.205737740f, +0.000000100f, +0.205737740f, +0.000000100f + { .i = {0x3E55B388,0x33B504F3,0x3E55B388,0x33B504F3} }, //+0.208692670f, +0.000000084f, +0.208692670f, +0.000000084f + { .i = {0x3E58BCE5,0x339837F0,0x3E58BCE5,0x339837F0} }, //+0.211658075f, +0.000000071f, +0.211658075f, +0.000000071f + { .i = {0x3E5BC8FF,0x33800000,0x3E5BC8FF,0x33800000} }, //+0.214633927f, +0.000000060f, +0.214633927f, +0.000000060f + { .i = {0x3E5ED7CE,0x335744FD,0x3E5ED7CE,0x335744FD} }, //+0.217620105f, +0.000000050f, +0.217620105f, +0.000000050f + { .i = {0x3E61E950,0x333504F3,0x3E61E950,0x333504F3} }, //+0.220616579f, +0.000000042f, +0.220616579f, +0.000000042f + { .i = {0x3E64FD7F,0x331837F0,0x3E64FD7F,0x331837F0} }, //+0.223623261f, +0.000000035f, +0.223623261f, +0.000000035f + { .i = {0x3E681456,0x33000000,0x3E681456,0x33000000} }, //+0.226640075f, +0.000000030f, +0.226640075f, +0.000000030f + { .i = {0x3E6B2DD2,0x32D744FD,0x3E6B2DD2,0x32D744FD} }, //+0.229666978f, +0.000000025f, +0.229666978f, +0.000000025f + { .i = {0x3E6E49ED,0x32B504F3,0x3E6E49ED,0x32B504F3} }, //+0.232703879f, +0.000000021f, +0.232703879f, +0.000000021f + { .i = {0x3E7168A3,0x329837F0,0x3E7168A3,0x329837F0} }, //+0.235750720f, +0.000000018f, +0.235750720f, +0.000000018f + { .i = {0x3E7489EF,0x32800000,0x3E7489EF,0x32800000} }, //+0.238807425f, +0.000000015f, +0.238807425f, +0.000000015f + { .i = {0x3E77ADCF,0x325744FD,0x3E77ADCF,0x325744FD} }, //+0.241873965f, +0.000000013f, +0.241873965f, +0.000000013f + { .i = {0x3E7AD43C,0x323504F3,0x3E7AD43C,0x323504F3} }, //+0.244950235f, +0.000000011f, +0.244950235f, +0.000000011f + { .i = {0x3E7DFD34,0x321837F0,0x3E7DFD34,0x321837F0} }, //+0.248036206f, +0.000000009f, +0.248036206f, +0.000000009f + { .i = {0x3E809459,0x32000000,0x3E809459,0x32000000} }, //+0.251131803f, +0.000000007f, +0.251131803f, +0.000000007f + { .i = {0x3E822B59,0x31D744FD,0x3E822B59,0x31D744FD} }, //+0.254236966f, +0.000000006f, +0.254236966f, +0.000000006f + { .i = {0x3E83C399,0x31B504F3,0x3E83C399,0x31B504F3} }, //+0.257351667f, +0.000000005f, +0.257351667f, +0.000000005f + { .i = {0x3E855D15,0x319837F0,0x3E855D15,0x319837F0} }, //+0.260475785f, +0.000000004f, +0.260475785f, +0.000000004f + { .i = {0x3E86F7CD,0x31800000,0x3E86F7CD,0x31800000} }, //+0.263609320f, +0.000000004f, +0.263609320f, +0.000000004f + { .i = {0x3E8893BE,0x315744FD,0x3E8893BE,0x315744FD} }, //+0.266752183f, +0.000000003f, +0.266752183f, +0.000000003f + { .i = {0x3E8A30E6,0x313504F3,0x3E8A30E6,0x313504F3} }, //+0.269904315f, +0.000000003f, +0.269904315f, +0.000000003f + { .i = {0x3E8BCF45,0x311837F0,0x3E8BCF45,0x311837F0} }, //+0.273065716f, +0.000000002f, +0.273065716f, +0.000000002f + { .i = {0x3E8D6ED7,0x31000000,0x3E8D6ED7,0x31000000} }, //+0.276236266f, +0.000000002f, +0.276236266f, +0.000000002f + { .i = {0x3E8F0F9C,0x30D744FD,0x3E8F0F9C,0x30D744FD} }, //+0.279415965f, +0.000000002f, +0.279415965f, +0.000000002f + { .i = {0x3E90B190,0x30B504F3,0x3E90B190,0x30B504F3} }, //+0.282604694f, +0.000000001f, +0.282604694f, +0.000000001f + { .i = {0x3E9254B4,0x309837F0,0x3E9254B4,0x309837F0} }, //+0.285802484f, +0.000000001f, +0.285802484f, +0.000000001f + { .i = {0x3E93F904,0x30800000,0x3E93F904,0x30800000} }, //+0.289009213f, +0.000000001f, +0.289009213f, +0.000000001f + { .i = {0x3E959E80,0x305744FD,0x3E959E80,0x305744FD} }, //+0.292224884f, +0.000000001f, +0.292224884f, +0.000000001f + { .i = {0x3E974526,0x303504F3,0x3E974526,0x303504F3} }, //+0.295449436f, +0.000000001f, +0.295449436f, +0.000000001f + { .i = {0x3E98ECF3,0x301837F0,0x3E98ECF3,0x301837F0} }, //+0.298682779f, +0.000000001f, +0.298682779f, +0.000000001f + { .i = {0x3E9A95E7,0x30000000,0x3E9A95E7,0x30000000} }, //+0.301924914f, +0.000000000f, +0.301924914f, +0.000000000f + { .i = {0x3E9C4000,0x2FD744FD,0x3E9C4000,0x2FD744FD} }, //+0.305175781f, +0.000000000f, +0.305175781f, +0.000000000f + { .i = {0x3E9DEB3C,0x2FB504F3,0x3E9DEB3C,0x2FB504F3} }, //+0.308435321f, +0.000000000f, +0.308435321f, +0.000000000f + { .i = {0x3E9F979A,0x2F9837F0,0x3E9F979A,0x2F9837F0} }, //+0.311703503f, +0.000000000f, +0.311703503f, +0.000000000f + /* part 2 */ + { .i = {0x3EA14518,0x3F800000,0x3EA14518,0x3F800000} }, //+0.314980268f, +1.000000000f, +0.314980268f, +1.000000000f + { .i = {0x3EA2F3B4,0x3F000000,0x3EA2F3B4,0x3F000000} }, //+0.318265557f, +0.500000000f, +0.318265557f, +0.500000000f + { .i = {0x3EA4A36E,0x3E800000,0x3EA4A36E,0x3E800000} }, //+0.321559370f, +0.250000000f, +0.321559370f, +0.250000000f + { .i = {0x3EA65444,0x3E000000,0x3EA65444,0x3E000000} }, //+0.324861646f, +0.125000000f, +0.324861646f, +0.125000000f + { .i = {0x3EA80634,0x3D800000,0x3EA80634,0x3D800000} }, //+0.328172326f, +0.062500000f, +0.328172326f, +0.062500000f + { .i = {0x3EA9B93D,0x3D000000,0x3EA9B93D,0x3D000000} }, //+0.331491381f, +0.031250000f, +0.331491381f, +0.031250000f + { .i = {0x3EAB6D5D,0x3C800000,0x3EAB6D5D,0x3C800000} }, //+0.334818751f, +0.015625000f, +0.334818751f, +0.015625000f + { .i = {0x3EAD2294,0x3C000000,0x3EAD2294,0x3C000000} }, //+0.338154435f, +0.007812500f, +0.338154435f, +0.007812500f + { .i = {0x3EAED8DF,0x3B800000,0x3EAED8DF,0x3B800000} }, //+0.341498345f, +0.003906250f, +0.341498345f, +0.003906250f + { .i = {0x3EB0903D,0x3B000000,0x3EB0903D,0x3B000000} }, //+0.344850451f, +0.001953125f, +0.344850451f, +0.001953125f + { .i = {0x3EB248AE,0x3A800000,0x3EB248AE,0x3A800000} }, //+0.348210752f, +0.000976563f, +0.348210752f, +0.000976563f + { .i = {0x3EB4022F,0x3A000000,0x3EB4022F,0x3A000000} }, //+0.351579159f, +0.000488281f, +0.351579159f, +0.000488281f + { .i = {0x3EB5BCBF,0x39800000,0x3EB5BCBF,0x39800000} }, //+0.354955643f, +0.000244141f, +0.354955643f, +0.000244141f + { .i = {0x3EB7785E,0x39000000,0x3EB7785E,0x39000000} }, //+0.358340204f, +0.000122070f, +0.358340204f, +0.000122070f + { .i = {0x3EB93509,0x38800000,0x3EB93509,0x38800000} }, //+0.361732751f, +0.000061035f, +0.361732751f, +0.000061035f + { .i = {0x3EBAF2C0,0x38000000,0x3EBAF2C0,0x38000000} }, //+0.365133286f, +0.000030518f, +0.365133286f, +0.000030518f + { .i = {0x3EBCB181,0x00000000,0x3EBCB181,0x00000000} }, //+0.368541747f, +0.000000000f, +0.368541747f, +0.000000000f + { .i = {0x3EBE714C,0x00000000,0x3EBE714C,0x00000000} }, //+0.371958137f, +0.000000000f, +0.371958137f, +0.000000000f + { .i = {0x3EC0321E,0x00000000,0x3EC0321E,0x00000000} }, //+0.375382364f, +0.000000000f, +0.375382364f, +0.000000000f + { .i = {0x3EC1F3F6,0x00000000,0x3EC1F3F6,0x00000000} }, //+0.378814399f, +0.000000000f, +0.378814399f, +0.000000000f + { .i = {0x3EC3B6D5,0x00000000,0x3EC3B6D5,0x00000000} }, //+0.382254273f, +0.000000000f, +0.382254273f, +0.000000000f + { .i = {0x3EC57AB7,0x00000000,0x3EC57AB7,0x00000000} }, //+0.385701865f, +0.000000000f, +0.385701865f, +0.000000000f + { .i = {0x3EC73F9C,0x00000000,0x3EC73F9C,0x00000000} }, //+0.389157176f, +0.000000000f, +0.389157176f, +0.000000000f + { .i = {0x3EC90584,0x00000000,0x3EC90584,0x00000000} }, //+0.392620206f, +0.000000000f, +0.392620206f, +0.000000000f + { .i = {0x3ECACC6C,0x00000000,0x3ECACC6C,0x00000000} }, //+0.396090865f, +0.000000000f, +0.396090865f, +0.000000000f + { .i = {0x3ECC9454,0x00000000,0x3ECC9454,0x00000000} }, //+0.399569154f, +0.000000000f, +0.399569154f, +0.000000000f + { .i = {0x3ECE5D3A,0x00000000,0x3ECE5D3A,0x00000000} }, //+0.403055012f, +0.000000000f, +0.403055012f, +0.000000000f + { .i = {0x3ED0271E,0x00000000,0x3ED0271E,0x00000000} }, //+0.406548440f, +0.000000000f, +0.406548440f, +0.000000000f + { .i = {0x3ED1F1FF,0x00000000,0x3ED1F1FF,0x00000000} }, //+0.410049409f, +0.000000000f, +0.410049409f, +0.000000000f + { .i = {0x3ED3BDDA,0x00000000,0x3ED3BDDA,0x00000000} }, //+0.413557827f, +0.000000000f, +0.413557827f, +0.000000000f + { .i = {0x3ED58AB0,0x00000000,0x3ED58AB0,0x00000000} }, //+0.417073727f, +0.000000000f, +0.417073727f, +0.000000000f + { .i = {0x3ED7587F,0x00000000,0x3ED7587F,0x00000000} }, //+0.420597047f, +0.000000000f, +0.420597047f, +0.000000000f + { .i = {0x3ED92746,0x00000000,0x3ED92746,0x00000000} }, //+0.424127758f, +0.000000000f, +0.424127758f, +0.000000000f + { .i = {0x3EDAF704,0x00000000,0x3EDAF704,0x00000000} }, //+0.427665830f, +0.000000000f, +0.427665830f, +0.000000000f + { .i = {0x3EDCC7B8,0x00000000,0x3EDCC7B8,0x00000000} }, //+0.431211233f, +0.000000000f, +0.431211233f, +0.000000000f + { .i = {0x3EDE9961,0x00000000,0x3EDE9961,0x00000000} }, //+0.434763938f, +0.000000000f, +0.434763938f, +0.000000000f + { .i = {0x3EE06BFE,0x00000000,0x3EE06BFE,0x00000000} }, //+0.438323915f, +0.000000000f, +0.438323915f, +0.000000000f + { .i = {0x3EE23F8F,0x00000000,0x3EE23F8F,0x00000000} }, //+0.441891164f, +0.000000000f, +0.441891164f, +0.000000000f + { .i = {0x3EE41411,0x00000000,0x3EE41411,0x00000000} }, //+0.445465595f, +0.000000000f, +0.445465595f, +0.000000000f + { .i = {0x3EE5E984,0x00000000,0x3EE5E984,0x00000000} }, //+0.449047208f, +0.000000000f, +0.449047208f, +0.000000000f + { .i = {0x3EE7BFE8,0x00000000,0x3EE7BFE8,0x00000000} }, //+0.452636003f, +0.000000000f, +0.452636003f, +0.000000000f + { .i = {0x3EE9973A,0x00000000,0x3EE9973A,0x00000000} }, //+0.456231892f, +0.000000000f, +0.456231892f, +0.000000000f + { .i = {0x3EEB6F7B,0x00000000,0x3EEB6F7B,0x00000000} }, //+0.459834903f, +0.000000000f, +0.459834903f, +0.000000000f + { .i = {0x3EED48AA,0x00000000,0x3EED48AA,0x00000000} }, //+0.463445008f, +0.000000000f, +0.463445008f, +0.000000000f + { .i = {0x3EEF22C4,0x00000000,0x3EEF22C4,0x00000000} }, //+0.467062116f, +0.000000000f, +0.467062116f, +0.000000000f + { .i = {0x3EF0FDCA,0x00000000,0x3EF0FDCA,0x00000000} }, //+0.470686257f, +0.000000000f, +0.470686257f, +0.000000000f + { .i = {0x3EF2D9BB,0x00000000,0x3EF2D9BB,0x00000000} }, //+0.474317402f, +0.000000000f, +0.474317402f, +0.000000000f + { .i = {0x3EF4B695,0x00000000,0x3EF4B695,0x00000000} }, //+0.477955490f, +0.000000000f, +0.477955490f, +0.000000000f + { .i = {0x3EF69458,0x00000000,0x3EF69458,0x00000000} }, //+0.481600523f, +0.000000000f, +0.481600523f, +0.000000000f + { .i = {0x3EF87302,0x00000000,0x3EF87302,0x00000000} }, //+0.485252440f, +0.000000000f, +0.485252440f, +0.000000000f + { .i = {0x3EFA5294,0x00000000,0x3EFA5294,0x00000000} }, //+0.488911271f, +0.000000000f, +0.488911271f, +0.000000000f + { .i = {0x3EFC330C,0x00000000,0x3EFC330C,0x00000000} }, //+0.492576957f, +0.000000000f, +0.492576957f, +0.000000000f + { .i = {0x3EFE1469,0x00000000,0x3EFE1469,0x00000000} }, //+0.496249467f, +0.000000000f, +0.496249467f, +0.000000000f + { .i = {0x3EFFF6AB,0x00000000,0x3EFFF6AB,0x00000000} }, //+0.499928802f, +0.000000000f, +0.499928802f, +0.000000000f + { .i = {0x3F00ECE8,0x00000000,0x3F00ECE8,0x00000000} }, //+0.503614902f, +0.000000000f, +0.503614902f, +0.000000000f + { .i = {0x3F01DEEC,0x00000000,0x3F01DEEC,0x00000000} }, //+0.507307768f, +0.000000000f, +0.507307768f, +0.000000000f + { .i = {0x3F02D161,0x00000000,0x3F02D161,0x00000000} }, //+0.511007369f, +0.000000000f, +0.511007369f, +0.000000000f + { .i = {0x3F03C446,0x00000000,0x3F03C446,0x00000000} }, //+0.514713645f, +0.000000000f, +0.514713645f, +0.000000000f + { .i = {0x3F04B79C,0x00000000,0x3F04B79C,0x00000000} }, //+0.518426657f, +0.000000000f, +0.518426657f, +0.000000000f + { .i = {0x3F05AB61,0x00000000,0x3F05AB61,0x00000000} }, //+0.522146285f, +0.000000000f, +0.522146285f, +0.000000000f + { .i = {0x3F069F96,0x00000000,0x3F069F96,0x00000000} }, //+0.525872588f, +0.000000000f, +0.525872588f, +0.000000000f + { .i = {0x3F079439,0x00000000,0x3F079439,0x00000000} }, //+0.529605448f, +0.000000000f, +0.529605448f, +0.000000000f + { .i = {0x3F08894B,0x00000000,0x3F08894B,0x00000000} }, //+0.533344924f, +0.000000000f, +0.533344924f, +0.000000000f + { .i = {0x3F097ECC,0x00000000,0x3F097ECC,0x00000000} }, //+0.537091017f, +0.000000000f, +0.537091017f, +0.000000000f + { .i = {0x3F0A74BA,0x00000000,0x3F0A74BA,0x00000000} }, //+0.540843606f, +0.000000000f, +0.540843606f, +0.000000000f + { .i = {0x3F0B6B15,0x00000000,0x3F0B6B15,0x00000000} }, //+0.544602692f, +0.000000000f, +0.544602692f, +0.000000000f + { .i = {0x3F0C61DE,0x00000000,0x3F0C61DE,0x00000000} }, //+0.548368335f, +0.000000000f, +0.548368335f, +0.000000000f + { .i = {0x3F0D5913,0x00000000,0x3F0D5913,0x00000000} }, //+0.552140415f, +0.000000000f, +0.552140415f, +0.000000000f + { .i = {0x3F0E50B4,0x00000000,0x3F0E50B4,0x00000000} }, //+0.555918932f, +0.000000000f, +0.555918932f, +0.000000000f + { .i = {0x3F0F48C2,0x00000000,0x3F0F48C2,0x00000000} }, //+0.559703946f, +0.000000000f, +0.559703946f, +0.000000000f + { .i = {0x3F10413A,0x00000000,0x3F10413A,0x00000000} }, //+0.563495278f, +0.000000000f, +0.563495278f, +0.000000000f + { .i = {0x3F113A1E,0x00000000,0x3F113A1E,0x00000000} }, //+0.567293048f, +0.000000000f, +0.567293048f, +0.000000000f + { .i = {0x3F12336D,0x00000000,0x3F12336D,0x00000000} }, //+0.571097195f, +0.000000000f, +0.571097195f, +0.000000000f + { .i = {0x3F132D27,0x00000000,0x3F132D27,0x00000000} }, //+0.574907720f, +0.000000000f, +0.574907720f, +0.000000000f + { .i = {0x3F14274A,0x00000000,0x3F14274A,0x00000000} }, //+0.578724504f, +0.000000000f, +0.578724504f, +0.000000000f + { .i = {0x3F1521D7,0x00000000,0x3F1521D7,0x00000000} }, //+0.582547605f, +0.000000000f, +0.582547605f, +0.000000000f + { .i = {0x3F161CCE,0x00000000,0x3F161CCE,0x00000000} }, //+0.586377025f, +0.000000000f, +0.586377025f, +0.000000000f + { .i = {0x3F17182D,0x00000000,0x3F17182D,0x00000000} }, //+0.590212643f, +0.000000000f, +0.590212643f, +0.000000000f + { .i = {0x3F1813F6,0x00000000,0x3F1813F6,0x00000000} }, //+0.594054580f, +0.000000000f, +0.594054580f, +0.000000000f + { .i = {0x3F191027,0x00000000,0x3F191027,0x00000000} }, //+0.597902715f, +0.000000000f, +0.597902715f, +0.000000000f + { .i = {0x3F1A0CBF,0x00000000,0x3F1A0CBF,0x00000000} }, //+0.601756990f, +0.000000000f, +0.601756990f, +0.000000000f + { .i = {0x3F1B09C0,0x00000000,0x3F1B09C0,0x00000000} }, //+0.605617523f, +0.000000000f, +0.605617523f, +0.000000000f + { .i = {0x3F1C0728,0x00000000,0x3F1C0728,0x00000000} }, //+0.609484196f, +0.000000000f, +0.609484196f, +0.000000000f + { .i = {0x3F1D04F7,0x00000000,0x3F1D04F7,0x00000000} }, //+0.613357008f, +0.000000000f, +0.613357008f, +0.000000000f + { .i = {0x3F1E032C,0x00000000,0x3F1E032C,0x00000000} }, //+0.617235899f, +0.000000000f, +0.617235899f, +0.000000000f + { .i = {0x3F1F01C9,0x00000000,0x3F1F01C9,0x00000000} }, //+0.621120989f, +0.000000000f, +0.621120989f, +0.000000000f + { .i = {0x3F2000CB,0x00000000,0x3F2000CB,0x00000000} }, //+0.625012100f, +0.000000000f, +0.625012100f, +0.000000000f + { .i = {0x3F210033,0x00000000,0x3F210033,0x00000000} }, //+0.628909290f, +0.000000000f, +0.628909290f, +0.000000000f + { .i = {0x3F220000,0x00000000,0x3F220000,0x00000000} }, //+0.632812500f, +0.000000000f, +0.632812500f, +0.000000000f + { .i = {0x3F230033,0x00000000,0x3F230033,0x00000000} }, //+0.636721790f, +0.000000000f, +0.636721790f, +0.000000000f + { .i = {0x3F2400CA,0x00000000,0x3F2400CA,0x00000000} }, //+0.640637040f, +0.000000000f, +0.640637040f, +0.000000000f + { .i = {0x3F2501C6,0x00000000,0x3F2501C6,0x00000000} }, //+0.644558311f, +0.000000000f, +0.644558311f, +0.000000000f + { .i = {0x3F260326,0x00000000,0x3F260326,0x00000000} }, //+0.648485541f, +0.000000000f, +0.648485541f, +0.000000000f + { .i = {0x3F2704EA,0x00000000,0x3F2704EA,0x00000000} }, //+0.652418733f, +0.000000000f, +0.652418733f, +0.000000000f + { .i = {0x3F280711,0x00000000,0x3F280711,0x00000000} }, //+0.656357825f, +0.000000000f, +0.656357825f, +0.000000000f + { .i = {0x3F29099C,0x00000000,0x3F29099C,0x00000000} }, //+0.660302877f, +0.000000000f, +0.660302877f, +0.000000000f + { .i = {0x3F2A0C8A,0x00000000,0x3F2A0C8A,0x00000000} }, //+0.664253831f, +0.000000000f, +0.664253831f, +0.000000000f + { .i = {0x3F2B0FDB,0x00000000,0x3F2B0FDB,0x00000000} }, //+0.668210685f, +0.000000000f, +0.668210685f, +0.000000000f + { .i = {0x3F2C138E,0x00000000,0x3F2C138E,0x00000000} }, //+0.672173381f, +0.000000000f, +0.672173381f, +0.000000000f + { .i = {0x3F2D17A3,0x00000000,0x3F2D17A3,0x00000000} }, //+0.676141918f, +0.000000000f, +0.676141918f, +0.000000000f + { .i = {0x3F2E1C1A,0x00000000,0x3F2E1C1A,0x00000000} }, //+0.680116296f, +0.000000000f, +0.680116296f, +0.000000000f + { .i = {0x3F2F20F2,0x00000000,0x3F2F20F2,0x00000000} }, //+0.684096456f, +0.000000000f, +0.684096456f, +0.000000000f + { .i = {0x3F30262C,0x00000000,0x3F30262C,0x00000000} }, //+0.688082457f, +0.000000000f, +0.688082457f, +0.000000000f + { .i = {0x3F312BC7,0x00000000,0x3F312BC7,0x00000000} }, //+0.692074239f, +0.000000000f, +0.692074239f, +0.000000000f + { .i = {0x3F3231C3,0x00000000,0x3F3231C3,0x00000000} }, //+0.696071804f, +0.000000000f, +0.696071804f, +0.000000000f + { .i = {0x3F33381F,0x00000000,0x3F33381F,0x00000000} }, //+0.700075090f, +0.000000000f, +0.700075090f, +0.000000000f + { .i = {0x3F343EDB,0x00000000,0x3F343EDB,0x00000000} }, //+0.704084098f, +0.000000000f, +0.704084098f, +0.000000000f + { .i = {0x3F3545F7,0x00000000,0x3F3545F7,0x00000000} }, //+0.708098829f, +0.000000000f, +0.708098829f, +0.000000000f + { .i = {0x3F364D72,0x00000000,0x3F364D72,0x00000000} }, //+0.712119222f, +0.000000000f, +0.712119222f, +0.000000000f + { .i = {0x3F37554D,0x00000000,0x3F37554D,0x00000000} }, //+0.716145337f, +0.000000000f, +0.716145337f, +0.000000000f + { .i = {0x3F385D87,0x00000000,0x3F385D87,0x00000000} }, //+0.720177114f, +0.000000000f, +0.720177114f, +0.000000000f + { .i = {0x3F396620,0x00000000,0x3F396620,0x00000000} }, //+0.724214554f, +0.000000000f, +0.724214554f, +0.000000000f + { .i = {0x3F3A6F17,0x00000000,0x3F3A6F17,0x00000000} }, //+0.728257596f, +0.000000000f, +0.728257596f, +0.000000000f + { .i = {0x3F3B786D,0x00000000,0x3F3B786D,0x00000000} }, //+0.732306302f, +0.000000000f, +0.732306302f, +0.000000000f + { .i = {0x3F3C8221,0x00000000,0x3F3C8221,0x00000000} }, //+0.736360610f, +0.000000000f, +0.736360610f, +0.000000000f + { .i = {0x3F3D8C32,0x00000000,0x3F3D8C32,0x00000000} }, //+0.740420461f, +0.000000000f, +0.740420461f, +0.000000000f + { .i = {0x3F3E96A1,0x00000000,0x3F3E96A1,0x00000000} }, //+0.744485915f, +0.000000000f, +0.744485915f, +0.000000000f + { .i = {0x3F3FA16D,0x00000000,0x3F3FA16D,0x00000000} }, //+0.748556912f, +0.000000000f, +0.748556912f, +0.000000000f + { .i = {0x3F40AC96,0x00000000,0x3F40AC96,0x00000000} }, //+0.752633452f, +0.000000000f, +0.752633452f, +0.000000000f + { .i = {0x3F41B81C,0x00000000,0x3F41B81C,0x00000000} }, //+0.756715536f, +0.000000000f, +0.756715536f, +0.000000000f + { .i = {0x3F42C3FE,0x00000000,0x3F42C3FE,0x00000000} }, //+0.760803103f, +0.000000000f, +0.760803103f, +0.000000000f + { .i = {0x3F43D03D,0x00000000,0x3F43D03D,0x00000000} }, //+0.764896214f, +0.000000000f, +0.764896214f, +0.000000000f + { .i = {0x3F44DCD8,0x00000000,0x3F44DCD8,0x00000000} }, //+0.768994808f, +0.000000000f, +0.768994808f, +0.000000000f + { .i = {0x3F45E9CE,0x00000000,0x3F45E9CE,0x00000000} }, //+0.773098826f, +0.000000000f, +0.773098826f, +0.000000000f + { .i = {0x3F46F720,0x00000000,0x3F46F720,0x00000000} }, //+0.777208328f, +0.000000000f, +0.777208328f, +0.000000000f + { .i = {0x3F4804CD,0x00000000,0x3F4804CD,0x00000000} }, //+0.781323254f, +0.000000000f, +0.781323254f, +0.000000000f + { .i = {0x3F4912D5,0x00000000,0x3F4912D5,0x00000000} }, //+0.785443604f, +0.000000000f, +0.785443604f, +0.000000000f + { .i = {0x3F4A2138,0x00000000,0x3F4A2138,0x00000000} }, //+0.789569378f, +0.000000000f, +0.789569378f, +0.000000000f + { .i = {0x3F4B2FF5,0x00000000,0x3F4B2FF5,0x00000000} }, //+0.793700516f, +0.000000000f, +0.793700516f, +0.000000000f + { .i = {0x3F4C3F0D,0x00000000,0x3F4C3F0D,0x00000000} }, //+0.797837079f, +0.000000000f, +0.797837079f, +0.000000000f + { .i = {0x3F4D4E7F,0x00000000,0x3F4D4E7F,0x00000000} }, //+0.801979005f, +0.000000000f, +0.801979005f, +0.000000000f + { .i = {0x3F4E5E4A,0x00000000,0x3F4E5E4A,0x00000000} }, //+0.806126237f, +0.000000000f, +0.806126237f, +0.000000000f + { .i = {0x3F4F6E70,0x00000000,0x3F4F6E70,0x00000000} }, //+0.810278893f, +0.000000000f, +0.810278893f, +0.000000000f + { .i = {0x3F507EEE,0x00000000,0x3F507EEE,0x00000000} }, //+0.814436793f, +0.000000000f, +0.814436793f, +0.000000000f + { .i = {0x3F518FC6,0x00000000,0x3F518FC6,0x00000000} }, //+0.818600059f, +0.000000000f, +0.818600059f, +0.000000000f + { .i = {0x3F52A0F7,0x00000000,0x3F52A0F7,0x00000000} }, //+0.822768629f, +0.000000000f, +0.822768629f, +0.000000000f + { .i = {0x3F53B280,0x00000000,0x3F53B280,0x00000000} }, //+0.826942444f, +0.000000000f, +0.826942444f, +0.000000000f + { .i = {0x3F54C462,0x00000000,0x3F54C462,0x00000000} }, //+0.831121564f, +0.000000000f, +0.831121564f, +0.000000000f + { .i = {0x3F55D69C,0x00000000,0x3F55D69C,0x00000000} }, //+0.835305929f, +0.000000000f, +0.835305929f, +0.000000000f + { .i = {0x3F56E92E,0x00000000,0x3F56E92E,0x00000000} }, //+0.839495540f, +0.000000000f, +0.839495540f, +0.000000000f + { .i = {0x3F57FC18,0x00000000,0x3F57FC18,0x00000000} }, //+0.843690395f, +0.000000000f, +0.843690395f, +0.000000000f + { .i = {0x3F590F5A,0x00000000,0x3F590F5A,0x00000000} }, //+0.847890496f, +0.000000000f, +0.847890496f, +0.000000000f + { .i = {0x3F5A22F2,0x00000000,0x3F5A22F2,0x00000000} }, //+0.852095723f, +0.000000000f, +0.852095723f, +0.000000000f + { .i = {0x3F5B36E3,0x00000000,0x3F5B36E3,0x00000000} }, //+0.856306255f, +0.000000000f, +0.856306255f, +0.000000000f + { .i = {0x3F5C4B2A,0x00000000,0x3F5C4B2A,0x00000000} }, //+0.860521913f, +0.000000000f, +0.860521913f, +0.000000000f + { .i = {0x3F5D5FC7,0x00000000,0x3F5D5FC7,0x00000000} }, //+0.864742696f, +0.000000000f, +0.864742696f, +0.000000000f + { .i = {0x3F5E74BC,0x00000000,0x3F5E74BC,0x00000000} }, //+0.868968725f, +0.000000000f, +0.868968725f, +0.000000000f + { .i = {0x3F5F8A06,0x00000000,0x3F5F8A06,0x00000000} }, //+0.873199821f, +0.000000000f, +0.873199821f, +0.000000000f + { .i = {0x3F609FA7,0x00000000,0x3F609FA7,0x00000000} }, //+0.877436101f, +0.000000000f, +0.877436101f, +0.000000000f + { .i = {0x3F61B59D,0x00000000,0x3F61B59D,0x00000000} }, //+0.881677449f, +0.000000000f, +0.881677449f, +0.000000000f + { .i = {0x3F62CBE9,0x00000000,0x3F62CBE9,0x00000000} }, //+0.885923922f, +0.000000000f, +0.885923922f, +0.000000000f + { .i = {0x3F63E28B,0x00000000,0x3F63E28B,0x00000000} }, //+0.890175521f, +0.000000000f, +0.890175521f, +0.000000000f + { .i = {0x3F64F982,0x00000000,0x3F64F982,0x00000000} }, //+0.894432187f, +0.000000000f, +0.894432187f, +0.000000000f + { .i = {0x3F6610CE,0x00000000,0x3F6610CE,0x00000000} }, //+0.898693919f, +0.000000000f, +0.898693919f, +0.000000000f + { .i = {0x3F67286F,0x00000000,0x3F67286F,0x00000000} }, //+0.902960718f, +0.000000000f, +0.902960718f, +0.000000000f + { .i = {0x3F684065,0x00000000,0x3F684065,0x00000000} }, //+0.907232583f, +0.000000000f, +0.907232583f, +0.000000000f + { .i = {0x3F6958AF,0x00000000,0x3F6958AF,0x00000000} }, //+0.911509454f, +0.000000000f, +0.911509454f, +0.000000000f + { .i = {0x3F6A714D,0x00000000,0x3F6A714D,0x00000000} }, //+0.915791333f, +0.000000000f, +0.915791333f, +0.000000000f + { .i = {0x3F6B8A3F,0x00000000,0x3F6B8A3F,0x00000000} }, //+0.920078218f, +0.000000000f, +0.920078218f, +0.000000000f + { .i = {0x3F6CA386,0x00000000,0x3F6CA386,0x00000000} }, //+0.924370170f, +0.000000000f, +0.924370170f, +0.000000000f + { .i = {0x3F6DBD20,0x00000000,0x3F6DBD20,0x00000000} }, //+0.928667068f, +0.000000000f, +0.928667068f, +0.000000000f + { .i = {0x3F6ED70D,0x00000000,0x3F6ED70D,0x00000000} }, //+0.932968915f, +0.000000000f, +0.932968915f, +0.000000000f + { .i = {0x3F6FF14E,0x00000000,0x3F6FF14E,0x00000000} }, //+0.937275767f, +0.000000000f, +0.937275767f, +0.000000000f + { .i = {0x3F710BE1,0x00000000,0x3F710BE1,0x00000000} }, //+0.941587508f, +0.000000000f, +0.941587508f, +0.000000000f + { .i = {0x3F7226C8,0x00000000,0x3F7226C8,0x00000000} }, //+0.945904255f, +0.000000000f, +0.945904255f, +0.000000000f + { .i = {0x3F734202,0x00000000,0x3F734202,0x00000000} }, //+0.950225949f, +0.000000000f, +0.950225949f, +0.000000000f + { .i = {0x3F745D8E,0x00000000,0x3F745D8E,0x00000000} }, //+0.954552531f, +0.000000000f, +0.954552531f, +0.000000000f + { .i = {0x3F75796C,0x00000000,0x3F75796C,0x00000000} }, //+0.958884001f, +0.000000000f, +0.958884001f, +0.000000000f + { .i = {0x3F76959C,0x00000000,0x3F76959C,0x00000000} }, //+0.963220358f, +0.000000000f, +0.963220358f, +0.000000000f + { .i = {0x3F77B21F,0x00000000,0x3F77B21F,0x00000000} }, //+0.967561662f, +0.000000000f, +0.967561662f, +0.000000000f + { .i = {0x3F78CEF3,0x00000000,0x3F78CEF3,0x00000000} }, //+0.971907794f, +0.000000000f, +0.971907794f, +0.000000000f + { .i = {0x3F79EC19,0x00000000,0x3F79EC19,0x00000000} }, //+0.976258814f, +0.000000000f, +0.976258814f, +0.000000000f + { .i = {0x3F7B0990,0x00000000,0x3F7B0990,0x00000000} }, //+0.980614662f, +0.000000000f, +0.980614662f, +0.000000000f + { .i = {0x3F7C2759,0x00000000,0x3F7C2759,0x00000000} }, //+0.984975398f, +0.000000000f, +0.984975398f, +0.000000000f + { .i = {0x3F7D4572,0x00000000,0x3F7D4572,0x00000000} }, //+0.989340901f, +0.000000000f, +0.989340901f, +0.000000000f + { .i = {0x3F7E63DD,0x00000000,0x3F7E63DD,0x00000000} }, //+0.993711293f, +0.000000000f, +0.993711293f, +0.000000000f + { .i = {0x3F7F8298,0x00000000,0x3F7F8298,0x00000000} }, //+0.998086452f, +0.000000000f, +0.998086452f, +0.000000000f + { .i = {0x3F8050D2,0x00000000,0x3F8050D2,0x00000000} }, //+1.002466440f, +0.000000000f, +1.002466440f, +0.000000000f + { .i = {0x3F80E080,0x00000000,0x3F80E080,0x00000000} }, //+1.006851196f, +0.000000000f, +1.006851196f, +0.000000000f + { .i = {0x3F817056,0x00000000,0x3F817056,0x00000000} }, //+1.011240721f, +0.000000000f, +1.011240721f, +0.000000000f + { .i = {0x3F820054,0x00000000,0x3F820054,0x00000000} }, //+1.015635014f, +0.000000000f, +1.015635014f, +0.000000000f + { .i = {0x3F82907A,0x00000000,0x3F82907A,0x00000000} }, //+1.020034075f, +0.000000000f, +1.020034075f, +0.000000000f + { .i = {0x3F8320C8,0x00000000,0x3F8320C8,0x00000000} }, //+1.024437904f, +0.000000000f, +1.024437904f, +0.000000000f + { .i = {0x3F83B13E,0x00000000,0x3F83B13E,0x00000000} }, //+1.028846502f, +0.000000000f, +1.028846502f, +0.000000000f + { .i = {0x3F8441DB,0x00000000,0x3F8441DB,0x00000000} }, //+1.033259749f, +0.000000000f, +1.033259749f, +0.000000000f + { .i = {0x3F84D2A0,0x00000000,0x3F84D2A0,0x00000000} }, //+1.037677765f, +0.000000000f, +1.037677765f, +0.000000000f + { .i = {0x3F85638C,0x00000000,0x3F85638C,0x00000000} }, //+1.042100430f, +0.000000000f, +1.042100430f, +0.000000000f + { .i = {0x3F85F4A0,0x00000000,0x3F85F4A0,0x00000000} }, //+1.046527863f, +0.000000000f, +1.046527863f, +0.000000000f + { .i = {0x3F8685DB,0x00000000,0x3F8685DB,0x00000000} }, //+1.050959945f, +0.000000000f, +1.050959945f, +0.000000000f + { .i = {0x3F87173D,0x00000000,0x3F87173D,0x00000000} }, //+1.055396676f, +0.000000000f, +1.055396676f, +0.000000000f + { .i = {0x3F87A8C7,0x00000000,0x3F87A8C7,0x00000000} }, //+1.059838176f, +0.000000000f, +1.059838176f, +0.000000000f + { .i = {0x3F883A77,0x00000000,0x3F883A77,0x00000000} }, //+1.064284205f, +0.000000000f, +1.064284205f, +0.000000000f + { .i = {0x3F88CC4F,0x00000000,0x3F88CC4F,0x00000000} }, //+1.068735003f, +0.000000000f, +1.068735003f, +0.000000000f + { .i = {0x3F895E4D,0x00000000,0x3F895E4D,0x00000000} }, //+1.073190331f, +0.000000000f, +1.073190331f, +0.000000000f + { .i = {0x3F89F072,0x00000000,0x3F89F072,0x00000000} }, //+1.077650309f, +0.000000000f, +1.077650309f, +0.000000000f + { .i = {0x3F8A82BE,0x00000000,0x3F8A82BE,0x00000000} }, //+1.082114935f, +0.000000000f, +1.082114935f, +0.000000000f + { .i = {0x3F8B1531,0x00000000,0x3F8B1531,0x00000000} }, //+1.086584210f, +0.000000000f, +1.086584210f, +0.000000000f + { .i = {0x3F8BA7CA,0x00000000,0x3F8BA7CA,0x00000000} }, //+1.091058016f, +0.000000000f, +1.091058016f, +0.000000000f + { .i = {0x3F8C3A8A,0x00000000,0x3F8C3A8A,0x00000000} }, //+1.095536470f, +0.000000000f, +1.095536470f, +0.000000000f + { .i = {0x3F8CCD70,0x00000000,0x3F8CCD70,0x00000000} }, //+1.100019455f, +0.000000000f, +1.100019455f, +0.000000000f + { .i = {0x3F8D607D,0x00000000,0x3F8D607D,0x00000000} }, //+1.104507089f, +0.000000000f, +1.104507089f, +0.000000000f + { .i = {0x3F8DF3B0,0x00000000,0x3F8DF3B0,0x00000000} }, //+1.108999252f, +0.000000000f, +1.108999252f, +0.000000000f + { .i = {0x3F8E8709,0x00000000,0x3F8E8709,0x00000000} }, //+1.113495946f, +0.000000000f, +1.113495946f, +0.000000000f + { .i = {0x3F8F1A88,0x00000000,0x3F8F1A88,0x00000000} }, //+1.117997169f, +0.000000000f, +1.117997169f, +0.000000000f + { .i = {0x3F8FAE2D,0x00000000,0x3F8FAE2D,0x00000000} }, //+1.122502923f, +0.000000000f, +1.122502923f, +0.000000000f + { .i = {0x3F9041F8,0x00000000,0x3F9041F8,0x00000000} }, //+1.127013206f, +0.000000000f, +1.127013206f, +0.000000000f + { .i = {0x3F90D5EA,0x00000000,0x3F90D5EA,0x00000000} }, //+1.131528139f, +0.000000000f, +1.131528139f, +0.000000000f + { .i = {0x3F916A00,0x00000000,0x3F916A00,0x00000000} }, //+1.136047363f, +0.000000000f, +1.136047363f, +0.000000000f + { .i = {0x3F91FE3D,0x00000000,0x3F91FE3D,0x00000000} }, //+1.140571237f, +0.000000000f, +1.140571237f, +0.000000000f + { .i = {0x3F92929F,0x00000000,0x3F92929F,0x00000000} }, //+1.145099521f, +0.000000000f, +1.145099521f, +0.000000000f + { .i = {0x3F932727,0x00000000,0x3F932727,0x00000000} }, //+1.149632335f, +0.000000000f, +1.149632335f, +0.000000000f + { .i = {0x3F93BBD5,0x00000000,0x3F93BBD5,0x00000000} }, //+1.154169679f, +0.000000000f, +1.154169679f, +0.000000000f + { .i = {0x3F9450A8,0x00000000,0x3F9450A8,0x00000000} }, //+1.158711433f, +0.000000000f, +1.158711433f, +0.000000000f + { .i = {0x3F94E5A0,0x00000000,0x3F94E5A0,0x00000000} }, //+1.163257599f, +0.000000000f, +1.163257599f, +0.000000000f + { .i = {0x3F957ABD,0x00000000,0x3F957ABD,0x00000000} }, //+1.167808175f, +0.000000000f, +1.167808175f, +0.000000000f + { .i = {0x3F961000,0x00000000,0x3F961000,0x00000000} }, //+1.172363281f, +0.000000000f, +1.172363281f, +0.000000000f + { .i = {0x3F96A568,0x00000000,0x3F96A568,0x00000000} }, //+1.176922798f, +0.000000000f, +1.176922798f, +0.000000000f + { .i = {0x3F973AF5,0x00000000,0x3F973AF5,0x00000000} }, //+1.181486726f, +0.000000000f, +1.181486726f, +0.000000000f + { .i = {0x3F97D0A7,0x00000000,0x3F97D0A7,0x00000000} }, //+1.186055064f, +0.000000000f, +1.186055064f, +0.000000000f + { .i = {0x3F98667E,0x00000000,0x3F98667E,0x00000000} }, //+1.190627813f, +0.000000000f, +1.190627813f, +0.000000000f + { .i = {0x3F98FC7A,0x00000000,0x3F98FC7A,0x00000000} }, //+1.195204973f, +0.000000000f, +1.195204973f, +0.000000000f + { .i = {0x3F99929A,0x00000000,0x3F99929A,0x00000000} }, //+1.199786425f, +0.000000000f, +1.199786425f, +0.000000000f + { .i = {0x3F9A28DF,0x00000000,0x3F9A28DF,0x00000000} }, //+1.204372287f, +0.000000000f, +1.204372287f, +0.000000000f + { .i = {0x3F9ABF49,0x00000000,0x3F9ABF49,0x00000000} }, //+1.208962560f, +0.000000000f, +1.208962560f, +0.000000000f + { .i = {0x3F9B55D8,0x00000000,0x3F9B55D8,0x00000000} }, //+1.213557243f, +0.000000000f, +1.213557243f, +0.000000000f + { .i = {0x3F9BEC8B,0x00000000,0x3F9BEC8B,0x00000000} }, //+1.218156219f, +0.000000000f, +1.218156219f, +0.000000000f + { .i = {0x3F9C8363,0x00000000,0x3F9C8363,0x00000000} }, //+1.222759604f, +0.000000000f, +1.222759604f, +0.000000000f + { .i = {0x3F9D1A5E,0x00000000,0x3F9D1A5E,0x00000000} }, //+1.227367163f, +0.000000000f, +1.227367163f, +0.000000000f + { .i = {0x3F9DB17F,0x00000000,0x3F9DB17F,0x00000000} }, //+1.231979251f, +0.000000000f, +1.231979251f, +0.000000000f + { .i = {0x3F9E48C3,0x00000000,0x3F9E48C3,0x00000000} }, //+1.236595511f, +0.000000000f, +1.236595511f, +0.000000000f + { .i = {0x3F9EE02C,0x00000000,0x3F9EE02C,0x00000000} }, //+1.241216183f, +0.000000000f, +1.241216183f, +0.000000000f + { .i = {0x3F9F77B8,0x00000000,0x3F9F77B8,0x00000000} }, //+1.245841026f, +0.000000000f, +1.245841026f, +0.000000000f + { .i = {0x3FA00F69,0x00000000,0x3FA00F69,0x00000000} }, //+1.250470281f, +0.000000000f, +1.250470281f, +0.000000000f + { .i = {0x3FA0A73E,0x00000000,0x3FA0A73E,0x00000000} }, //+1.255103827f, +0.000000000f, +1.255103827f, +0.000000000f + { .i = {0x3FA13F37,0x00000000,0x3FA13F37,0x00000000} }, //+1.259741664f, +0.000000000f, +1.259741664f, +0.000000000f + { .i = {0x3FA1D753,0x00000000,0x3FA1D753,0x00000000} }, //+1.264383674f, +0.000000000f, +1.264383674f, +0.000000000f + { .i = {0x3FA26F93,0x00000000,0x3FA26F93,0x00000000} }, //+1.269029975f, +0.000000000f, +1.269029975f, +0.000000000f + { .i = {0x3FA307F7,0x00000000,0x3FA307F7,0x00000000} }, //+1.273680568f, +0.000000000f, +1.273680568f, +0.000000000f + { .i = {0x3FA3A07F,0x00000000,0x3FA3A07F,0x00000000} }, //+1.278335452f, +0.000000000f, +1.278335452f, +0.000000000f + { .i = {0x3FA4392A,0x00000000,0x3FA4392A,0x00000000} }, //+1.282994509f, +0.000000000f, +1.282994509f, +0.000000000f + { .i = {0x3FA4D1F9,0x00000000,0x3FA4D1F9,0x00000000} }, //+1.287657857f, +0.000000000f, +1.287657857f, +0.000000000f + { .i = {0x3FA56AEB,0x00000000,0x3FA56AEB,0x00000000} }, //+1.292325377f, +0.000000000f, +1.292325377f, +0.000000000f + { .i = {0x3FA60400,0x00000000,0x3FA60400,0x00000000} }, //+1.296997070f, +0.000000000f, +1.296997070f, +0.000000000f + { .i = {0x3FA69D39,0x00000000,0x3FA69D39,0x00000000} }, //+1.301673055f, +0.000000000f, +1.301673055f, +0.000000000f + { .i = {0x3FA73695,0x00000000,0x3FA73695,0x00000000} }, //+1.306353211f, +0.000000000f, +1.306353211f, +0.000000000f + { .i = {0x3FA7D015,0x00000000,0x3FA7D015,0x00000000} }, //+1.311037660f, +0.000000000f, +1.311037660f, +0.000000000f + { .i = {0x3FA869B7,0x00000000,0x3FA869B7,0x00000000} }, //+1.315726161f, +0.000000000f, +1.315726161f, +0.000000000f + { .i = {0x3FA9037D,0x00000000,0x3FA9037D,0x00000000} }, //+1.320418954f, +0.000000000f, +1.320418954f, +0.000000000f + { .i = {0x3FA99D65,0x00000000,0x3FA99D65,0x00000000} }, //+1.325115800f, +0.000000000f, +1.325115800f, +0.000000000f + { .i = {0x3FAA3771,0x00000000,0x3FAA3771,0x00000000} }, //+1.329816937f, +0.000000000f, +1.329816937f, +0.000000000f + { .i = {0x3FAAD19F,0x00000000,0x3FAAD19F,0x00000000} }, //+1.334522128f, +0.000000000f, +1.334522128f, +0.000000000f + { .i = {0x3FAB6BF0,0x00000000,0x3FAB6BF0,0x00000000} }, //+1.339231491f, +0.000000000f, +1.339231491f, +0.000000000f + { .i = {0x3FAC0664,0x00000000,0x3FAC0664,0x00000000} }, //+1.343945026f, +0.000000000f, +1.343945026f, +0.000000000f + { .i = {0x3FACA0FB,0x00000000,0x3FACA0FB,0x00000000} }, //+1.348662734f, +0.000000000f, +1.348662734f, +0.000000000f + { .i = {0x3FAD3BB4,0x00000000,0x3FAD3BB4,0x00000000} }, //+1.353384495f, +0.000000000f, +1.353384495f, +0.000000000f + { .i = {0x3FADD690,0x00000000,0x3FADD690,0x00000000} }, //+1.358110428f, +0.000000000f, +1.358110428f, +0.000000000f + { .i = {0x3FAE718E,0x00000000,0x3FAE718E,0x00000000} }, //+1.362840414f, +0.000000000f, +1.362840414f, +0.000000000f + { .i = {0x3FAF0CAF,0x00000000,0x3FAF0CAF,0x00000000} }, //+1.367574573f, +0.000000000f, +1.367574573f, +0.000000000f + { .i = {0x3FAFA7F2,0x00000000,0x3FAFA7F2,0x00000000} }, //+1.372312784f, +0.000000000f, +1.372312784f, +0.000000000f + { .i = {0x3FB04358,0x00000000,0x3FB04358,0x00000000} }, //+1.377055168f, +0.000000000f, +1.377055168f, +0.000000000f + { .i = {0x3FB0DEE0,0x00000000,0x3FB0DEE0,0x00000000} }, //+1.381801605f, +0.000000000f, +1.381801605f, +0.000000000f + { .i = {0x3FB17A8A,0x00000000,0x3FB17A8A,0x00000000} }, //+1.386552095f, +0.000000000f, +1.386552095f, +0.000000000f + { .i = {0x3FB21656,0x00000000,0x3FB21656,0x00000000} }, //+1.391306639f, +0.000000000f, +1.391306639f, +0.000000000f + { .i = {0x3FB2B244,0x00000000,0x3FB2B244,0x00000000} }, //+1.396065235f, +0.000000000f, +1.396065235f, +0.000000000f + { .i = {0x3FB34E55,0x00000000,0x3FB34E55,0x00000000} }, //+1.400828004f, +0.000000000f, +1.400828004f, +0.000000000f + { .i = {0x3FB3EA87,0x00000000,0x3FB3EA87,0x00000000} }, //+1.405594707f, +0.000000000f, +1.405594707f, +0.000000000f + { .i = {0x3FB486DB,0x00000000,0x3FB486DB,0x00000000} }, //+1.410365462f, +0.000000000f, +1.410365462f, +0.000000000f + { .i = {0x3FB52352,0x00000000,0x3FB52352,0x00000000} }, //+1.415140390f, +0.000000000f, +1.415140390f, +0.000000000f + { .i = {0x3FB5BFE9,0x00000000,0x3FB5BFE9,0x00000000} }, //+1.419919133f, +0.000000000f, +1.419919133f, +0.000000000f + { .i = {0x3FB65CA3,0x00000000,0x3FB65CA3,0x00000000} }, //+1.424702048f, +0.000000000f, +1.424702048f, +0.000000000f + { .i = {0x3FB6F97F,0x00000000,0x3FB6F97F,0x00000000} }, //+1.429489017f, +0.000000000f, +1.429489017f, +0.000000000f + { .i = {0x3FB7967C,0x00000000,0x3FB7967C,0x00000000} }, //+1.434279919f, +0.000000000f, +1.434279919f, +0.000000000f + { .i = {0x3FB8339A,0x00000000,0x3FB8339A,0x00000000} }, //+1.439074755f, +0.000000000f, +1.439074755f, +0.000000000f + { .i = {0x3FB8D0DB,0x00000000,0x3FB8D0DB,0x00000000} }, //+1.443873763f, +0.000000000f, +1.443873763f, +0.000000000f + { .i = {0x3FB96E3C,0x00000000,0x3FB96E3C,0x00000000} }, //+1.448676586f, +0.000000000f, +1.448676586f, +0.000000000f + { .i = {0x3FBA0BBF,0x00000000,0x3FBA0BBF,0x00000000} }, //+1.453483462f, +0.000000000f, +1.453483462f, +0.000000000f + { .i = {0x3FBAA964,0x00000000,0x3FBAA964,0x00000000} }, //+1.458294392f, +0.000000000f, +1.458294392f, +0.000000000f + { .i = {0x3FBB472A,0x00000000,0x3FBB472A,0x00000000} }, //+1.463109255f, +0.000000000f, +1.463109255f, +0.000000000f + { .i = {0x3FBBE511,0x00000000,0x3FBBE511,0x00000000} }, //+1.467928052f, +0.000000000f, +1.467928052f, +0.000000000f + { .i = {0x3FBC8319,0x00000000,0x3FBC8319,0x00000000} }, //+1.472750783f, +0.000000000f, +1.472750783f, +0.000000000f + { .i = {0x3FBD2142,0x00000000,0x3FBD2142,0x00000000} }, //+1.477577448f, +0.000000000f, +1.477577448f, +0.000000000f + { .i = {0x3FBDBF8D,0x00000000,0x3FBDBF8D,0x00000000} }, //+1.482408166f, +0.000000000f, +1.482408166f, +0.000000000f + { .i = {0x3FBE5DF8,0x00000000,0x3FBE5DF8,0x00000000} }, //+1.487242699f, +0.000000000f, +1.487242699f, +0.000000000f + { .i = {0x3FBEFC85,0x00000000,0x3FBEFC85,0x00000000} }, //+1.492081285f, +0.000000000f, +1.492081285f, +0.000000000f + { .i = {0x3FBF9B32,0x00000000,0x3FBF9B32,0x00000000} }, //+1.496923685f, +0.000000000f, +1.496923685f, +0.000000000f + { .i = {0x3FC03A01,0x00000000,0x3FC03A01,0x00000000} }, //+1.501770139f, +0.000000000f, +1.501770139f, +0.000000000f + { .i = {0x3FC0D8F0,0x00000000,0x3FC0D8F0,0x00000000} }, //+1.506620407f, +0.000000000f, +1.506620407f, +0.000000000f + { .i = {0x3FC17800,0x00000000,0x3FC17800,0x00000000} }, //+1.511474609f, +0.000000000f, +1.511474609f, +0.000000000f + { .i = {0x3FC21730,0x00000000,0x3FC21730,0x00000000} }, //+1.516332626f, +0.000000000f, +1.516332626f, +0.000000000f + { .i = {0x3FC2B682,0x00000000,0x3FC2B682,0x00000000} }, //+1.521194696f, +0.000000000f, +1.521194696f, +0.000000000f + { .i = {0x3FC355F3,0x00000000,0x3FC355F3,0x00000000} }, //+1.526060462f, +0.000000000f, +1.526060462f, +0.000000000f + { .i = {0x3FC3F586,0x00000000,0x3FC3F586,0x00000000} }, //+1.530930281f, +0.000000000f, +1.530930281f, +0.000000000f + { .i = {0x3FC49539,0x00000000,0x3FC49539,0x00000000} }, //+1.535803914f, +0.000000000f, +1.535803914f, +0.000000000f + { .i = {0x3FC5350C,0x00000000,0x3FC5350C,0x00000000} }, //+1.540681362f, +0.000000000f, +1.540681362f, +0.000000000f + { .i = {0x3FC5D500,0x00000000,0x3FC5D500,0x00000000} }, //+1.545562744f, +0.000000000f, +1.545562744f, +0.000000000f + { .i = {0x3FC67514,0x00000000,0x3FC67514,0x00000000} }, //+1.550447941f, +0.000000000f, +1.550447941f, +0.000000000f + { .i = {0x3FC71549,0x00000000,0x3FC71549,0x00000000} }, //+1.555337071f, +0.000000000f, +1.555337071f, +0.000000000f + { .i = {0x3FC7B59E,0x00000000,0x3FC7B59E,0x00000000} }, //+1.560230017f, +0.000000000f, +1.560230017f, +0.000000000f + { .i = {0x3FC85613,0x00000000,0x3FC85613,0x00000000} }, //+1.565126777f, +0.000000000f, +1.565126777f, +0.000000000f + { .i = {0x3FC8F6A8,0x00000000,0x3FC8F6A8,0x00000000} }, //+1.570027351f, +0.000000000f, +1.570027351f, +0.000000000f + { .i = {0x3FC9975D,0x00000000,0x3FC9975D,0x00000000} }, //+1.574931741f, +0.000000000f, +1.574931741f, +0.000000000f + { .i = {0x3FCA3832,0x00000000,0x3FCA3832,0x00000000} }, //+1.579839945f, +0.000000000f, +1.579839945f, +0.000000000f + { .i = {0x3FCAD928,0x00000000,0x3FCAD928,0x00000000} }, //+1.584752083f, +0.000000000f, +1.584752083f, +0.000000000f + { .i = {0x3FCB7A3D,0x00000000,0x3FCB7A3D,0x00000000} }, //+1.589667916f, +0.000000000f, +1.589667916f, +0.000000000f + { .i = {0x3FCC1B72,0x00000000,0x3FCC1B72,0x00000000} }, //+1.594587564f, +0.000000000f, +1.594587564f, +0.000000000f + { .i = {0x3FCCBCC7,0x00000000,0x3FCCBCC7,0x00000000} }, //+1.599511027f, +0.000000000f, +1.599511027f, +0.000000000f + { .i = {0x3FCD5E3C,0x00000000,0x3FCD5E3C,0x00000000} }, //+1.604438305f, +0.000000000f, +1.604438305f, +0.000000000f + { .i = {0x3FCDFFD1,0x00000000,0x3FCDFFD1,0x00000000} }, //+1.609369397f, +0.000000000f, +1.609369397f, +0.000000000f + { .i = {0x3FCEA185,0x00000000,0x3FCEA185,0x00000000} }, //+1.614304185f, +0.000000000f, +1.614304185f, +0.000000000f + { .i = {0x3FCF4359,0x00000000,0x3FCF4359,0x00000000} }, //+1.619242787f, +0.000000000f, +1.619242787f, +0.000000000f + { .i = {0x3FCFE54C,0x00000000,0x3FCFE54C,0x00000000} }, //+1.624185085f, +0.000000000f, +1.624185085f, +0.000000000f + { .i = {0x3FD0875F,0x00000000,0x3FD0875F,0x00000000} }, //+1.629131198f, +0.000000000f, +1.629131198f, +0.000000000f + { .i = {0x3FD12992,0x00000000,0x3FD12992,0x00000000} }, //+1.634081125f, +0.000000000f, +1.634081125f, +0.000000000f + { .i = {0x3FD1CBE4,0x00000000,0x3FD1CBE4,0x00000000} }, //+1.639034748f, +0.000000000f, +1.639034748f, +0.000000000f + { .i = {0x3FD26E56,0x00000000,0x3FD26E56,0x00000000} }, //+1.643992186f, +0.000000000f, +1.643992186f, +0.000000000f + { .i = {0x3FD310E7,0x00000000,0x3FD310E7,0x00000000} }, //+1.648953319f, +0.000000000f, +1.648953319f, +0.000000000f + { .i = {0x3FD3B397,0x00000000,0x3FD3B397,0x00000000} }, //+1.653918147f, +0.000000000f, +1.653918147f, +0.000000000f + { .i = {0x3FD45666,0x00000000,0x3FD45666,0x00000000} }, //+1.658886671f, +0.000000000f, +1.658886671f, +0.000000000f + { .i = {0x3FD4F955,0x00000000,0x3FD4F955,0x00000000} }, //+1.663859010f, +0.000000000f, +1.663859010f, +0.000000000f + { .i = {0x3FD59C63,0x00000000,0x3FD59C63,0x00000000} }, //+1.668835044f, +0.000000000f, +1.668835044f, +0.000000000f + { .i = {0x3FD63F90,0x00000000,0x3FD63F90,0x00000000} }, //+1.673814774f, +0.000000000f, +1.673814774f, +0.000000000f + { .i = {0x3FD6E2DC,0x00000000,0x3FD6E2DC,0x00000000} }, //+1.678798199f, +0.000000000f, +1.678798199f, +0.000000000f + { .i = {0x3FD78647,0x00000000,0x3FD78647,0x00000000} }, //+1.683785319f, +0.000000000f, +1.683785319f, +0.000000000f + { .i = {0x3FD829D2,0x00000000,0x3FD829D2,0x00000000} }, //+1.688776255f, +0.000000000f, +1.688776255f, +0.000000000f + { .i = {0x3FD8CD7B,0x00000000,0x3FD8CD7B,0x00000000} }, //+1.693770766f, +0.000000000f, +1.693770766f, +0.000000000f + { .i = {0x3FD97143,0x00000000,0x3FD97143,0x00000000} }, //+1.698768973f, +0.000000000f, +1.698768973f, +0.000000000f + { .i = {0x3FDA152A,0x00000000,0x3FDA152A,0x00000000} }, //+1.703770876f, +0.000000000f, +1.703770876f, +0.000000000f + { .i = {0x3FDAB930,0x00000000,0x3FDAB930,0x00000000} }, //+1.708776474f, +0.000000000f, +1.708776474f, +0.000000000f + { .i = {0x3FDB5D54,0x00000000,0x3FDB5D54,0x00000000} }, //+1.713785648f, +0.000000000f, +1.713785648f, +0.000000000f + { .i = {0x3FDC0197,0x00000000,0x3FDC0197,0x00000000} }, //+1.718798518f, +0.000000000f, +1.718798518f, +0.000000000f + { .i = {0x3FDCA5F9,0x00000000,0x3FDCA5F9,0x00000000} }, //+1.723815084f, +0.000000000f, +1.723815084f, +0.000000000f + { .i = {0x3FDD4A7A,0x00000000,0x3FDD4A7A,0x00000000} }, //+1.728835344f, +0.000000000f, +1.728835344f, +0.000000000f + { .i = {0x3FDDEF19,0x00000000,0x3FDDEF19,0x00000000} }, //+1.733859181f, +0.000000000f, +1.733859181f, +0.000000000f + { .i = {0x3FDE93D7,0x00000000,0x3FDE93D7,0x00000000} }, //+1.738886714f, +0.000000000f, +1.738886714f, +0.000000000f + { .i = {0x3FDF38B3,0x00000000,0x3FDF38B3,0x00000000} }, //+1.743917823f, +0.000000000f, +1.743917823f, +0.000000000f + { .i = {0x3FDFDDAE,0x00000000,0x3FDFDDAE,0x00000000} }, //+1.748952627f, +0.000000000f, +1.748952627f, +0.000000000f + { .i = {0x3FE082C7,0x00000000,0x3FE082C7,0x00000000} }, //+1.753991008f, +0.000000000f, +1.753991008f, +0.000000000f + { .i = {0x3FE127FE,0x00000000,0x3FE127FE,0x00000000} }, //+1.759032965f, +0.000000000f, +1.759032965f, +0.000000000f + { .i = {0x3FE1CD54,0x00000000,0x3FE1CD54,0x00000000} }, //+1.764078617f, +0.000000000f, +1.764078617f, +0.000000000f + { .i = {0x3FE272C8,0x00000000,0x3FE272C8,0x00000000} }, //+1.769127846f, +0.000000000f, +1.769127846f, +0.000000000f + { .i = {0x3FE3185A,0x00000000,0x3FE3185A,0x00000000} }, //+1.774180651f, +0.000000000f, +1.774180651f, +0.000000000f + { .i = {0x3FE3BE0B,0x00000000,0x3FE3BE0B,0x00000000} }, //+1.779237151f, +0.000000000f, +1.779237151f, +0.000000000f + { .i = {0x3FE463DA,0x00000000,0x3FE463DA,0x00000000} }, //+1.784297228f, +0.000000000f, +1.784297228f, +0.000000000f + { .i = {0x3FE509C6,0x00000000,0x3FE509C6,0x00000000} }, //+1.789360762f, +0.000000000f, +1.789360762f, +0.000000000f + { .i = {0x3FE5AFD1,0x00000000,0x3FE5AFD1,0x00000000} }, //+1.794427991f, +0.000000000f, +1.794427991f, +0.000000000f + { .i = {0x3FE655FA,0x00000000,0x3FE655FA,0x00000000} }, //+1.799498796f, +0.000000000f, +1.799498796f, +0.000000000f + { .i = {0x3FE6FC41,0x00000000,0x3FE6FC41,0x00000000} }, //+1.804573178f, +0.000000000f, +1.804573178f, +0.000000000f + { .i = {0x3FE7A2A6,0x00000000,0x3FE7A2A6,0x00000000} }, //+1.809651136f, +0.000000000f, +1.809651136f, +0.000000000f + { .i = {0x3FE84929,0x00000000,0x3FE84929,0x00000000} }, //+1.814732671f, +0.000000000f, +1.814732671f, +0.000000000f + { .i = {0x3FE8EFC9,0x00000000,0x3FE8EFC9,0x00000000} }, //+1.819817662f, +0.000000000f, +1.819817662f, +0.000000000f + { .i = {0x3FE99688,0x00000000,0x3FE99688,0x00000000} }, //+1.824906349f, +0.000000000f, +1.824906349f, +0.000000000f + { .i = {0x3FEA3D64,0x00000000,0x3FEA3D64,0x00000000} }, //+1.829998493f, +0.000000000f, +1.829998493f, +0.000000000f + { .i = {0x3FEAE45E,0x00000000,0x3FEAE45E,0x00000000} }, //+1.835094213f, +0.000000000f, +1.835094213f, +0.000000000f + { .i = {0x3FEB8B76,0x00000000,0x3FEB8B76,0x00000000} }, //+1.840193510f, +0.000000000f, +1.840193510f, +0.000000000f + { .i = {0x3FEC32AB,0x00000000,0x3FEC32AB,0x00000000} }, //+1.845296264f, +0.000000000f, +1.845296264f, +0.000000000f + { .i = {0x3FECD9FE,0x00000000,0x3FECD9FE,0x00000000} }, //+1.850402594f, +0.000000000f, +1.850402594f, +0.000000000f + { .i = {0x3FED816E,0x00000000,0x3FED816E,0x00000000} }, //+1.855512381f, +0.000000000f, +1.855512381f, +0.000000000f + { .i = {0x3FEE28FC,0x00000000,0x3FEE28FC,0x00000000} }, //+1.860625744f, +0.000000000f, +1.860625744f, +0.000000000f + { .i = {0x3FEED0A8,0x00000000,0x3FEED0A8,0x00000000} }, //+1.865742683f, +0.000000000f, +1.865742683f, +0.000000000f + { .i = {0x3FEF7871,0x00000000,0x3FEF7871,0x00000000} }, //+1.870863080f, +0.000000000f, +1.870863080f, +0.000000000f + { .i = {0x3FF02057,0x00000000,0x3FF02057,0x00000000} }, //+1.875986934f, +0.000000000f, +1.875986934f, +0.000000000f + { .i = {0x3FF0C85B,0x00000000,0x3FF0C85B,0x00000000} }, //+1.881114364f, +0.000000000f, +1.881114364f, +0.000000000f + { .i = {0x3FF1707C,0x00000000,0x3FF1707C,0x00000000} }, //+1.886245251f, +0.000000000f, +1.886245251f, +0.000000000f + { .i = {0x3FF218BA,0x00000000,0x3FF218BA,0x00000000} }, //+1.891379595f, +0.000000000f, +1.891379595f, +0.000000000f + { .i = {0x3FF2C116,0x00000000,0x3FF2C116,0x00000000} }, //+1.896517515f, +0.000000000f, +1.896517515f, +0.000000000f + { .i = {0x3FF3698F,0x00000000,0x3FF3698F,0x00000000} }, //+1.901658893f, +0.000000000f, +1.901658893f, +0.000000000f + { .i = {0x3FF41225,0x00000000,0x3FF41225,0x00000000} }, //+1.906803727f, +0.000000000f, +1.906803727f, +0.000000000f + { .i = {0x3FF4BAD8,0x00000000,0x3FF4BAD8,0x00000000} }, //+1.911952019f, +0.000000000f, +1.911952019f, +0.000000000f + { .i = {0x3FF563A8,0x00000000,0x3FF563A8,0x00000000} }, //+1.917103767f, +0.000000000f, +1.917103767f, +0.000000000f + { .i = {0x3FF60C95,0x00000000,0x3FF60C95,0x00000000} }, //+1.922258973f, +0.000000000f, +1.922258973f, +0.000000000f + { .i = {0x3FF6B59F,0x00000000,0x3FF6B59F,0x00000000} }, //+1.927417636f, +0.000000000f, +1.927417636f, +0.000000000f + { .i = {0x3FF75EC7,0x00000000,0x3FF75EC7,0x00000000} }, //+1.932579875f, +0.000000000f, +1.932579875f, +0.000000000f + { .i = {0x3FF8080B,0x00000000,0x3FF8080B,0x00000000} }, //+1.937745452f, +0.000000000f, +1.937745452f, +0.000000000f + { .i = {0x3FF8B16C,0x00000000,0x3FF8B16C,0x00000000} }, //+1.942914486f, +0.000000000f, +1.942914486f, +0.000000000f + { .i = {0x3FF95AEA,0x00000000,0x3FF95AEA,0x00000000} }, //+1.948086977f, +0.000000000f, +1.948086977f, +0.000000000f + { .i = {0x3FFA0485,0x00000000,0x3FFA0485,0x00000000} }, //+1.953262925f, +0.000000000f, +1.953262925f, +0.000000000f + { .i = {0x3FFAAE3C,0x00000000,0x3FFAAE3C,0x00000000} }, //+1.958442211f, +0.000000000f, +1.958442211f, +0.000000000f + { .i = {0x3FFB5810,0x00000000,0x3FFB5810,0x00000000} }, //+1.963624954f, +0.000000000f, +1.963624954f, +0.000000000f + { .i = {0x3FFC0201,0x00000000,0x3FFC0201,0x00000000} }, //+1.968811154f, +0.000000000f, +1.968811154f, +0.000000000f + { .i = {0x3FFCAC0F,0x00000000,0x3FFCAC0F,0x00000000} }, //+1.974000812f, +0.000000000f, +1.974000812f, +0.000000000f + { .i = {0x3FFD5639,0x00000000,0x3FFD5639,0x00000000} }, //+1.979193807f, +0.000000000f, +1.979193807f, +0.000000000f + { .i = {0x3FFE0080,0x00000000,0x3FFE0080,0x00000000} }, //+1.984390259f, +0.000000000f, +1.984390259f, +0.000000000f + { .i = {0x3FFEAAE4,0x00000000,0x3FFEAAE4,0x00000000} }, //+1.989590168f, +0.000000000f, +1.989590168f, +0.000000000f + { .i = {0x3FFF5564,0x00000000,0x3FFF5564,0x00000000} }, //+1.994793415f, +0.000000000f, +1.994793415f, +0.000000000f + + /* this value isn't part of the original table but index is sometimes accesed (this seems like a bug in original + * code, o perhaps a byproduct of inexact Ps2 float emulation), return 0 as a previsible result */ + { .i = {0x00000000,0x00000000,0x00000000,0x00000000} }, //+0.000000000f, +0.000000000f, +0.000000000f, +0.000000000f +}; + +/* FFT?/DCT? table (Hanning window?) */ +static const REG_VF TRANSFORM_TABLE[1024/4] = { + { .i = {0x3F3504F3,0x3F7FB10F,0x3F7EC46D,0x3F7D3AAC} }, //+0.707106769f, +0.998795450f, +0.995184720f, +0.989176512f + { .i = {0x3F7B14BE,0x3F7853F8,0x3F74FA0B,0x3F710908} }, //+0.980785251f, +0.970031261f, +0.956940353f, +0.941544056f + { .i = {0x3F6C835E,0x3F676BD8,0x3F61C597,0x3F5B941A} }, //+0.923879504f, +0.903989315f, +0.881921232f, +0.857728601f + { .i = {0x3F54DB31,0x3F4D9F02,0x3F45E403,0x3F3DAEF9} }, //+0.831469595f, +0.803207517f, +0.773010433f, +0.740951121f + { .i = {0x3F3504F3,0x3F2BEB49,0x3F226799,0x3F187FC0} }, //+0.707106769f, +0.671558917f, +0.634393275f, +0.595699310f + { .i = {0x3F0E39D9,0x3F039C3C,0x3EF15AE7,0x3EDAE881} }, //+0.555570185f, +0.514102697f, +0.471396655f, +0.427555114f + { .i = {0x3EC3EF15,0x3EAC7CD3,0x3E94A030,0x3E78CFC8} }, //+0.382683426f, +0.336889833f, +0.290284634f, +0.242980123f + { .i = {0x3E47C5BC,0x3E164085,0x3DC8BD35,0x3D48FB29} }, //+0.195090234f, +0.146730497f, +0.098017134f, +0.049067650f + { .i = {0x3F3504F3,0x3F7D3AAC,0x3F74FA0B,0x3F676BD8} }, //+0.707106769f, +0.989176512f, +0.956940353f, +0.903989315f + { .i = {0x3F54DB31,0x3F3DAEF9,0x3F226799,0x3F039C3C} }, //+0.831469595f, +0.740951121f, +0.634393275f, +0.514102697f + { .i = {0x3EC3EF15,0x3E78CFC8,0x3DC8BD35,0xBD48FB41} }, //+0.382683426f, +0.242980123f, +0.098017134f, -0.049067739f + { .i = {0xBE47C5C2,0xBEAC7CD6,0xBEF15AED,0xBF187FC1} }, //-0.195090324f, -0.336889923f, -0.471396834f, -0.595699370f + { .i = {0xBF3504F3,0xBF4D9F04,0xBF61C599,0xBF710909} }, //-0.707106769f, -0.803207636f, -0.881921351f, -0.941544116f + { .i = {0xBF7B14BF,0xBF7FB10F,0xBF7EC46D,0xBF7853F8} }, //-0.980785310f, -0.998795450f, -0.995184720f, -0.970031261f + { .i = {0xBF6C835E,0xBF5B9419,0xBF45E402,0xBF2BEB49} }, //-0.923879504f, -0.857728541f, -0.773010373f, -0.671558917f + { .i = {0xBF0E39D6,0xBEDAE87B,0xBE94A02D,0xBE16407F} }, //-0.555570006f, -0.427554935f, -0.290284544f, -0.146730408f + { .i = {0x3F3504F3,0x3F7853F8,0x3F61C597,0x3F3DAEF9} }, //+0.707106769f, +0.970031261f, +0.881921232f, +0.740951121f + { .i = {0x3F0E39D9,0x3EAC7CD3,0x3DC8BD35,0xBE16408A} }, //+0.555570185f, +0.336889833f, +0.098017134f, -0.146730572f + { .i = {0xBEC3EF18,0xBF187FC1,0xBF45E404,0xBF676BD8} }, //-0.382683516f, -0.595699370f, -0.773010492f, -0.903989315f + { .i = {0xBF7B14BF,0xBF7FB10F,0xBF74FA0A,0xBF5B9419} }, //-0.980785310f, -0.998795450f, -0.956940293f, -0.857728541f + { .i = {0xBF3504F1,0xBF039C3E,0xBE94A02D,0xBD48FAD2} }, //-0.707106650f, -0.514102817f, -0.290284544f, -0.049067326f + { .i = {0x3E47C5C8,0x3EDAE88A,0x3F22679A,0x3F4D9F05} }, //+0.195090413f, +0.427555382f, +0.634393334f, +0.803207695f + { .i = {0x3F6C835F,0x3F7D3AAD,0x3F7EC46D,0x3F710908} }, //+0.923879564f, +0.989176571f, +0.995184720f, +0.941544056f + { .i = {0x3F54DB31,0x3F2BEB49,0x3EF15AE7,0x3E78CFC8} }, //+0.831469595f, +0.671558917f, +0.471396655f, +0.242980123f + { .i = {0x3F3504F3,0x3F710908,0x3F45E403,0x3F039C3C} }, //+0.707106769f, +0.941544056f, +0.773010433f, +0.514102697f + { .i = {0x3E47C5BC,0xBE16408A,0xBEF15AED,0xBF3DAEFB} }, //+0.195090234f, -0.146730572f, -0.471396834f, -0.740951240f + { .i = {0xBF6C8360,0xBF7FB10F,0xBF74FA0A,0xBF4D9F02} }, //-0.923879623f, -0.998795450f, -0.956940293f, -0.803207517f + { .i = {0xBF0E39D6,0xBE78CFBA,0x3DC8BD5D,0x3EDAE88A} }, //-0.555570006f, -0.242979914f, +0.098017432f, +0.427555382f + { .i = {0x3F3504F7,0x3F676BDA,0x3F7EC46E,0x3F7853F8} }, //+0.707107008f, +0.903989434f, +0.995184779f, +0.970031261f + { .i = {0x3F54DB31,0x3F187FC0,0x3E94A030,0xBD48FB41} }, //+0.831469595f, +0.595699310f, +0.290284634f, -0.049067739f + { .i = {0xBEC3EF18,0xBF2BEB4B,0xBF61C599,0xBF7D3AAC} }, //-0.382683516f, -0.671559036f, -0.881921351f, -0.989176512f + { .i = {0xBF7B14BE,0xBF5B9419,0xBF22679A,0xBEAC7CD4} }, //-0.980785251f, -0.857728541f, -0.634393334f, -0.336889863f + { .i = {0x3F3504F3,0x3F676BD8,0x3F226799,0x3E78CFC8} }, //+0.707106769f, +0.903989315f, +0.634393275f, +0.242980123f + { .i = {0xBE47C5C2,0xBF187FC1,0xBF61C599,0xBF7FB10F} }, //-0.195090324f, -0.595699370f, -0.881921351f, -0.998795450f + { .i = {0xBF6C835E,0xBF2BEB49,0xBE94A02D,0x3E164080} }, //-0.923879504f, -0.671558917f, -0.290284544f, +0.146730423f + { .i = {0x3F0E39DD,0x3F5B941B,0x3F7EC46E,0x3F710908} }, //+0.555570424f, +0.857728660f, +0.995184779f, +0.941544056f + { .i = {0x3F3504F3,0x3EAC7CD3,0xBDC8BD41,0xBF039C3D} }, //+0.707106769f, +0.336889833f, -0.098017223f, -0.514102757f + { .i = {0xBF54DB32,0xBF7D3AAC,0xBF74FA0A,0xBF3DAEF9} }, //-0.831469655f, -0.989176512f, -0.956940293f, -0.740951121f + { .i = {0xBEC3EF0B,0x3D48FB58,0x3EF15AE9,0x3F4D9F05} }, //-0.382683128f, +0.049067825f, +0.471396714f, +0.803207695f + { .i = {0x3F7B14BF,0x3F7853F8,0x3F45E403,0x3EDAE881} }, //+0.980785310f, +0.970031261f, +0.773010433f, +0.427555114f + { .i = {0x3F3504F3,0x3F5B941A,0x3EF15AE7,0xBD48FB41} }, //+0.707106769f, +0.857728601f, +0.471396655f, -0.049067739f + { .i = {0xBF0E39DC,0xBF676BD8,0xBF7EC46D,0xBF4D9F02} }, //-0.555570364f, -0.903989315f, -0.995184720f, -0.803207517f + { .i = {0xBEC3EF0B,0x3E164080,0x3F22679A,0x3F710909} }, //-0.382683128f, +0.146730423f, +0.634393334f, +0.941544116f + { .i = {0x3F7B14BE,0x3F3DAEF9,0x3E94A030,0xBE78CFCD} }, //+0.980785251f, +0.740951121f, +0.290284634f, -0.242980197f + { .i = {0xBF3504F3,0xBF7853F8,0xBF74FA0A,0xBF2BEB49} }, //-0.707106769f, -0.970031261f, -0.956940293f, -0.671558917f + { .i = {0xBE47C5C6,0x3EAC7CD5,0x3F45E405,0x3F7D3AAD} }, //-0.195090383f, +0.336889893f, +0.773010552f, +0.989176571f + { .i = {0x3F6C835E,0x3F187FC0,0x3DC8BD35,0xBEDAE880} }, //+0.923879504f, +0.595699310f, +0.098017134f, -0.427555084f + { .i = {0xBF54DB32,0xBF7FB10F,0xBF61C597,0xBF039C3E} }, //-0.831469655f, -0.998795450f, -0.881921232f, -0.514102817f + { .i = {0x3F3504F3,0x3F4D9F02,0x3E94A030,0xBEAC7CD6} }, //+0.707106769f, +0.803207517f, +0.290284634f, -0.336889923f + { .i = {0xBF54DB32,0xBF7FB10F,0xBF45E402,0xBE78CFBA} }, //-0.831469655f, -0.998795450f, -0.773010373f, -0.242979914f + { .i = {0x3EC3EF1B,0x3F5B941B,0x3F7EC46D,0x3F3DAEF9} }, //+0.382683605f, +0.857728660f, +0.995184720f, +0.740951121f + { .i = {0x3E47C5BC,0xBEDAE880,0xBF61C599,0xBF7D3AAC} }, //+0.195090234f, -0.427555084f, -0.881921351f, -0.989176512f + { .i = {0xBF3504F1,0xBE16407F,0x3EF15AE9,0x3F676BDA} }, //-0.707106650f, -0.146730408f, +0.471396714f, +0.903989434f + { .i = {0x3F7B14BE,0x3F2BEB49,0x3DC8BD35,0xBF039C3D} }, //+0.980785251f, +0.671558917f, +0.098017134f, -0.514102757f + { .i = {0xBF6C8360,0xBF7853F8,0xBF22679A,0xBD48FAD2} }, //-0.923879623f, -0.970031261f, -0.634393334f, -0.049067326f + { .i = {0x3F0E39DD,0x3F710909,0x3F74FA0B,0x3F187FC0} }, //+0.555570424f, +0.941544116f, +0.956940353f, +0.595699310f + { .i = {0x3F3504F3,0x3F3DAEF9,0x3DC8BD35,0xBF187FC1} }, //+0.707106769f, +0.740951121f, +0.098017134f, -0.595699370f + { .i = {0xBF7B14BF,0xBF5B9419,0xBE94A02D,0x3EDAE88A} }, //-0.980785310f, -0.857728541f, -0.290284544f, +0.427555382f + { .i = {0x3F6C835F,0x3F710908,0x3EF15AE7,0xBE78CFCD} }, //+0.923879564f, +0.941544056f, +0.471396655f, -0.242980197f + { .i = {0xBF54DB32,0xBF7D3AAC,0xBF22679A,0x3D48FB58} }, //-0.831469655f, -0.989176512f, -0.634393334f, +0.049067825f + { .i = {0x3F3504F7,0x3F7FB10F,0x3F45E403,0x3E164085} }, //+0.707107008f, +0.998795450f, +0.773010433f, +0.146730497f + { .i = {0xBF0E39DC,0xBF7853F8,0xBF61C597,0xBEAC7CD4} }, //-0.555570364f, -0.970031261f, -0.881921232f, -0.336889863f + { .i = {0x3EC3EF1B,0x3F676BDA,0x3F74FA0B,0x3F039C3C} }, //+0.382683605f, +0.903989434f, +0.956940353f, +0.514102697f + { .i = {0xBE47C5C2,0xBF4D9F04,0xBF7EC46D,0xBF2BEB49} }, //-0.195090324f, -0.803207636f, -0.995184720f, -0.671558917f + { .i = {0x3F3504F3,0x3F2BEB49,0xBDC8BD41,0xBF4D9F04} }, //+0.707106769f, +0.671558917f, -0.098017223f, -0.803207636f + { .i = {0xBF7B14BE,0xBF039C3E,0x3E94A03D,0x3F676BDA} }, //-0.980785251f, -0.514102817f, +0.290285021f, +0.903989434f + { .i = {0x3F6C835E,0x3EAC7CD3,0xBEF15AED,0xBF7853F8} }, //+0.923879504f, +0.336889833f, -0.471396834f, -0.970031261f + { .i = {0xBF54DB30,0xBE16407F,0x3F22679A,0x3F7FB10F} }, //-0.831469536f, -0.146730408f, +0.634393334f, +0.998795450f + { .i = {0x3F3504F3,0xBD48FB41,0xBF45E404,0xBF7D3AAC} }, //+0.707106769f, -0.049067739f, -0.773010492f, -0.989176512f + { .i = {0xBF0E39D6,0x3E78CFDB,0x3F61C599,0x3F710908} }, //-0.555570006f, +0.242980406f, +0.881921351f, +0.941544056f + { .i = {0x3EC3EF15,0xBEDAE880,0xBF74FA0B,0xBF5B9419} }, //+0.382683426f, -0.427555084f, -0.956940353f, -0.857728541f + { .i = {0xBE47C5C6,0x3F187FBF,0x3F7EC46E,0x3F3DAEF9} }, //-0.195090383f, +0.595699251f, +0.995184779f, +0.740951121f + { .i = {0x3F3504F3,0x3F187FC0,0xBE94A033,0xBF710909} }, //+0.707106769f, +0.595699310f, -0.290284723f, -0.941544116f + { .i = {0xBF54DB30,0xBD48FAD2,0x3F45E405,0x3F7853F8} }, //-0.831469536f, -0.049067326f, +0.773010552f, +0.970031261f + { .i = {0x3EC3EF15,0xBF039C3D,0xBF7EC46D,0xBF2BEB49} }, //+0.382683426f, -0.514102757f, -0.995184720f, -0.671558917f + { .i = {0x3E47C5C8,0x3F676BDA,0x3F61C597,0x3E164085} }, //+0.195090413f, +0.903989434f, +0.881921232f, +0.146730497f + { .i = {0xBF3504F3,0xBF7D3AAC,0xBEF15AE8,0x3EDAE88A} }, //-0.707106769f, -0.989176512f, -0.471396685f, +0.427555382f + { .i = {0x3F7B14BF,0x3F3DAEF9,0xBDC8BD41,0xBF5B941A} }, //+0.980785310f, +0.740951121f, -0.098017223f, -0.857728601f + { .i = {0xBF6C835E,0xBE78CFBA,0x3F22679A,0x3F7FB10F} }, //-0.923879504f, -0.242979914f, +0.634393334f, +0.998795450f + { .i = {0x3F0E39D9,0xBEAC7CD6,0xBF74FA0B,0xBF4D9F02} }, //+0.555570185f, -0.336889923f, -0.956940353f, -0.803207517f + { .i = {0x3F3504F3,0x3F039C3C,0xBEF15AED,0xBF7FB10F} }, //+0.707106769f, +0.514102697f, -0.471396834f, -0.998795450f + { .i = {0xBF0E39D6,0x3EDAE88A,0x3F7EC46E,0x3F187FC0} }, //-0.555570006f, +0.427555382f, +0.995184779f, +0.595699310f + { .i = {0xBEC3EF18,0xBF7D3AAC,0xBF22679A,0x3EAC7CD5} }, //-0.382683516f, -0.989176512f, -0.634393334f, +0.336889893f + { .i = {0x3F7B14BF,0x3F2BEB49,0xBE94A033,0xBF7853F8} }, //+0.980785310f, +0.671558917f, -0.290284723f, -0.970031261f + { .i = {0xBF3504F1,0x3E78CFDB,0x3F74FA0C,0x3F3DAEF9} }, //-0.707106650f, +0.242980406f, +0.956940413f, +0.740951121f + { .i = {0xBE47C5C2,0xBF710909,0xBF45E402,0x3E164080} }, //-0.195090324f, -0.941544116f, -0.773010373f, +0.146730423f + { .i = {0x3F6C835F,0x3F4D9F02,0xBDC8BD41,0xBF676BD8} }, //+0.923879564f, +0.803207517f, -0.098017223f, -0.903989315f + { .i = {0xBF54DB30,0x3D48FB58,0x3F61C599,0x3F5B941A} }, //-0.831469536f, +0.049067825f, +0.881921351f, +0.857728601f + { .i = {0x3F3504F3,0x3EDAE881,0xBF226799,0xBF7853F8} }, //+0.707106769f, +0.427555114f, -0.634393275f, -0.970031261f + { .i = {0xBE47C5C6,0x3F4D9F05,0x3F61C597,0xBD48FB41} }, //-0.195090383f, +0.803207695f, +0.881921232f, -0.049067739f + { .i = {0xBF6C8360,0xBF3DAEF9,0x3E94A03D,0x3F7D3AAD} }, //-0.923879623f, -0.740951121f, +0.290285021f, +0.989176571f + { .i = {0x3F0E39D9,0xBF039C3D,0xBF7EC46D,0xBEAC7CD4} }, //+0.555570185f, -0.514102757f, -0.995184720f, -0.336889863f + { .i = {0x3F3504F7,0x3F710908,0x3DC8BD35,0xBF5B941A} }, //+0.707107008f, +0.941544056f, +0.098017134f, -0.857728601f + { .i = {0xBF54DB30,0x3E164080,0x3F74FA0C,0x3F2BEB49} }, //-0.831469536f, +0.146730423f, +0.956940413f, +0.671558917f + { .i = {0xBEC3EF18,0xBF7FB10F,0xBEF15AE8,0x3F187FBF} }, //-0.382683516f, -0.998795450f, -0.471396685f, +0.595699251f + { .i = {0x3F7B14BE,0x3E78CFC8,0xBF45E404,0xBF676BD7} }, //+0.980785251f, +0.242980123f, -0.773010492f, -0.903989255f + { .i = {0x3F3504F3,0x3EAC7CD3,0xBF45E404,0xBF5B9419} }, //+0.707106769f, +0.336889833f, -0.773010492f, -0.857728541f + { .i = {0x3E47C5C8,0x3F7D3AAD,0x3EF15AE7,0xBF2BEB4B} }, //+0.195090413f, +0.989176571f, +0.471396655f, -0.671559036f + { .i = {0xBF6C835E,0x3D48FB58,0x3F74FA0C,0x3F187FC0} }, //-0.923879504f, +0.049067825f, +0.956940413f, +0.595699310f + { .i = {0xBF0E39DC,0xBF7853F8,0xBDC8BD1A,0x3F676BDA} }, //-0.555570364f, -0.970031261f, -0.098016933f, +0.903989434f + { .i = {0x3F3504F3,0xBEDAE880,0xBF7EC46D,0xBE78CFBA} }, //+0.707106769f, -0.427555084f, -0.995184720f, -0.242979914f + { .i = {0x3F54DB31,0x3F4D9F02,0xBE94A033,0xBF7FB10F} }, //+0.831469595f, +0.803207517f, -0.290284723f, -0.998795450f + { .i = {0xBEC3EF0B,0x3F3DAEF9,0x3F61C597,0xBE16408A} }, //-0.382683128f, +0.740951121f, +0.881921232f, -0.146730572f + { .i = {0xBF7B14BF,0xBF039C3E,0x3F22679A,0x3F710908} }, //-0.980785310f, -0.514102817f, +0.634393334f, +0.941544056f + { .i = {0x3F3504F3,0x3E78CFC8,0xBF61C599,0xBF2BEB49} }, //+0.707106769f, +0.242980123f, -0.881921351f, -0.671558917f + { .i = {0x3F0E39DD,0x3F710908,0xBDC8BD41,0xBF7D3AAC} }, //+0.555570424f, +0.941544056f, -0.098017223f, -0.989176512f + { .i = {0xBEC3EF0B,0x3F4D9F05,0x3F45E403,0xBEDAE880} }, //-0.382683128f, +0.803207695f, +0.773010433f, -0.427555084f + { .i = {0xBF7B14BE,0xBD48FAD2,0x3F74FA0C,0x3F039C3C} }, //-0.980785251f, -0.049067326f, +0.956940413f, +0.514102697f + { .i = {0xBF3504F3,0xBF5B9419,0x3E94A03D,0x3F7FB10F} }, //-0.707106769f, -0.857728541f, +0.290285021f, +0.998795450f + { .i = {0x3E47C5BC,0xBF676BD8,0xBF22679A,0x3F187FBF} }, //+0.195090234f, -0.903989315f, -0.634393334f, +0.595699251f + { .i = {0x3F6C835E,0xBE16408A,0xBF7EC46D,0xBEAC7CD4} }, //+0.923879504f, -0.146730572f, -0.995184720f, -0.336889863f + { .i = {0x3F54DB31,0x3F3DAEF9,0xBEF15AED,0xBF7853F8} }, //+0.831469595f, +0.740951121f, -0.471396834f, -0.970031261f + { .i = {0x3F3504F3,0x3E164085,0xBF74FA0B,0xBEDAE87B} }, //+0.707106769f, +0.146730497f, -0.956940353f, -0.427554935f + { .i = {0x3F54DB31,0x3F2BEB49,0xBF226799,0xBF5B9419} }, //+0.831469595f, +0.671558917f, -0.634393275f, -0.857728541f + { .i = {0x3EC3EF1B,0x3F7853F8,0xBDC8BD41,0xBF7FB10F} }, //+0.382683605f, +0.970031261f, -0.098017223f, -0.998795450f + { .i = {0xBE47C5C6,0x3F710909,0x3EF15AE7,0xBF4D9F04} }, //-0.195090383f, +0.941544116f, +0.471396655f, -0.803207636f + { .i = {0xBF3504F1,0x3F187FBF,0x3F61C597,0xBEAC7CD6} }, //-0.707106650f, +0.595699251f, +0.881921232f, -0.336889923f + { .i = {0xBF7B14BE,0x3D48FB58,0x3F7EC46E,0x3E78CFC8} }, //-0.980785251f, +0.049067825f, +0.995184779f, +0.242980123f + { .i = {0xBF6C8360,0xBF039C3E,0x3F45E405,0x3F3DAEF9} }, //-0.923879623f, -0.514102817f, +0.773010552f, +0.740951121f + { .i = {0xBF0E39DC,0xBF676BD7,0x3E94A03D,0x3F7D3AAC} }, //-0.555570364f, -0.903989255f, +0.290285021f, +0.989176512f + { .i = {0x3F3504F3,0x3D48FB29,0xBF7EC46D,0xBE16407F} }, //+0.707106769f, +0.049067650f, -0.995184720f, -0.146730408f + { .i = {0x3F7B14BF,0x3E78CFC8,0xBF74FA0B,0xBEAC7CD4} }, //+0.980785310f, +0.242980123f, -0.956940353f, -0.336889863f + { .i = {0x3F6C835F,0x3EDAE881,0xBF61C599,0xBF039C3E} }, //+0.923879564f, +0.427555114f, -0.881921351f, -0.514102817f + { .i = {0x3F54DB31,0x3F187FC0,0xBF45E404,0xBF2BEB49} }, //+0.831469595f, +0.595699310f, -0.773010492f, -0.671558917f + { .i = {0x3F3504F7,0x3F3DAEF9,0xBF226799,0xBF4D9F02} }, //+0.707107008f, +0.740951121f, -0.634393275f, -0.803207517f + { .i = {0x3F0E39DD,0x3F5B941A,0xBEF15AED,0xBF676BD7} }, //+0.555570424f, +0.857728601f, -0.471396834f, -0.903989255f + { .i = {0x3EC3EF1B,0x3F710908,0xBE94A033,0xBF7853F8} }, //+0.382683605f, +0.941544056f, -0.290284723f, -0.970031261f + { .i = {0x3E47C5C8,0x3F7D3AAC,0xBDC8BD41,0xBF7FB10F} }, //+0.195090413f, +0.989176512f, -0.098017223f, -0.998795450f + { .i = {0x3F3504F3,0xBD48FB41,0xBF7EC46D,0x3E164080} }, //+0.707106769f, -0.049067739f, -0.995184720f, +0.146730423f + { .i = {0x3F7B14BE,0xBE78CFCD,0xBF74FA0A,0x3EAC7CD5} }, //+0.980785251f, -0.242980197f, -0.956940293f, +0.336889893f + { .i = {0x3F6C835E,0xBEDAE880,0xBF61C597,0x3F039C3E} }, //+0.923879504f, -0.427555084f, -0.881921232f, +0.514102817f + { .i = {0x3F54DB31,0xBF187FC1,0xBF45E402,0x3F2BEB4C} }, //+0.831469595f, -0.595699370f, -0.773010373f, +0.671559095f + { .i = {0x3F3504F3,0xBF3DAEFB,0xBF22679A,0x3F4D9F05} }, //+0.707106769f, -0.740951240f, -0.634393334f, +0.803207695f + { .i = {0x3F0E39D9,0xBF5B941A,0xBEF15AE8,0x3F676BDA} }, //+0.555570185f, -0.857728601f, -0.471396685f, +0.903989434f + { .i = {0x3EC3EF15,0xBF710909,0xBE94A02D,0x3F7853F8} }, //+0.382683426f, -0.941544116f, -0.290284544f, +0.970031261f + { .i = {0x3E47C5BC,0xBF7D3AAC,0xBDC8BD1A,0x3F7FB10F} }, //+0.195090234f, -0.989176512f, -0.098016933f, +0.998795450f + { .i = {0x3F3504F3,0xBE16408A,0xBF74FA0A,0x3EDAE88A} }, //+0.707106769f, -0.146730572f, -0.956940293f, +0.427555382f + { .i = {0x3F54DB31,0xBF2BEB4B,0xBF22679A,0x3F5B941B} }, //+0.831469595f, -0.671559036f, -0.634393334f, +0.857728660f + { .i = {0x3EC3EF15,0xBF7853F8,0xBDC8BD1A,0x3F7FB10F} }, //+0.382683426f, -0.970031261f, -0.098016933f, +0.998795450f + { .i = {0xBE47C5C2,0xBF710908,0x3EF15AE9,0x3F4D9F02} }, //-0.195090324f, -0.941544056f, +0.471396714f, +0.803207517f + { .i = {0xBF3504F3,0xBF187FBE,0x3F61C599,0x3EAC7CD3} }, //-0.707106769f, -0.595699191f, +0.881921351f, +0.336889833f + { .i = {0xBF7B14BF,0xBD48FAD2,0x3F7EC46D,0xBE78CFCD} }, //-0.980785310f, -0.049067326f, +0.995184720f, -0.242980197f + { .i = {0xBF6C835E,0x3F039C3E,0x3F45E403,0xBF3DAEFB} }, //-0.923879504f, +0.514102817f, +0.773010433f, -0.740951240f + { .i = {0xBF0E39D6,0x3F676BDA,0x3E94A030,0xBF7D3AAC} }, //-0.555570006f, +0.903989434f, +0.290284634f, -0.989176512f + { .i = {0x3F3504F3,0xBE78CFCD,0xBF61C597,0x3F2BEB4C} }, //+0.707106769f, -0.242980197f, -0.881921232f, +0.671559095f + { .i = {0x3F0E39D9,0xBF710909,0xBDC8BD1A,0x3F7D3AAC} }, //+0.555570185f, -0.941544116f, -0.098016933f, +0.989176512f + { .i = {0xBEC3EF18,0xBF4D9F02,0x3F45E405,0x3EDAE881} }, //-0.382683516f, -0.803207517f, +0.773010552f, +0.427555114f + { .i = {0xBF7B14BF,0x3D48FB58,0x3F74FA0B,0xBF039C3D} }, //-0.980785310f, +0.049067825f, +0.956940353f, -0.514102757f + { .i = {0xBF3504F1,0x3F5B941B,0x3E94A030,0xBF7FB10F} }, //-0.707106650f, +0.857728660f, +0.290284634f, -0.998795450f + { .i = {0x3E47C5C8,0x3F676BD8,0xBF226799,0xBF187FBE} }, //+0.195090413f, +0.903989315f, -0.634393275f, -0.595699191f + { .i = {0x3F6C835F,0x3E164085,0xBF7EC46D,0x3EAC7CD5} }, //+0.923879564f, +0.146730497f, -0.995184720f, +0.336889893f + { .i = {0x3F54DB31,0xBF3DAEFB,0xBEF15AE8,0x3F7853F8} }, //+0.831469595f, -0.740951240f, -0.471396685f, +0.970031261f + { .i = {0x3F3504F3,0xBEAC7CD6,0xBF45E402,0x3F5B941B} }, //+0.707106769f, -0.336889923f, -0.773010373f, +0.857728660f + { .i = {0x3E47C5BC,0xBF7D3AAC,0x3EF15AE9,0x3F2BEB49} }, //+0.195090234f, -0.989176512f, +0.471396714f, +0.671558917f + { .i = {0xBF6C8360,0xBD48FAD2,0x3F74FA0B,0xBF187FC1} }, //-0.923879623f, -0.049067326f, +0.956940353f, -0.595699370f + { .i = {0xBF0E39D6,0x3F7853F8,0xBDC8BD41,0xBF676BD7} }, //-0.555570006f, +0.970031261f, -0.098017223f, -0.903989255f + { .i = {0x3F3504F7,0x3EDAE881,0xBF7EC46D,0x3E78CFDB} }, //+0.707107008f, +0.427555114f, -0.995184720f, +0.242980406f + { .i = {0x3F54DB31,0xBF4D9F04,0xBE94A02D,0x3F7FB10F} }, //+0.831469595f, -0.803207636f, -0.290284544f, +0.998795450f + { .i = {0xBEC3EF18,0xBF3DAEF9,0x3F61C599,0x3E164085} }, //-0.382683516f, -0.740951121f, +0.881921351f, +0.146730497f + { .i = {0xBF7B14BE,0x3F039C3E,0x3F226799,0xBF710909} }, //-0.980785251f, +0.514102817f, +0.634393275f, -0.941544116f + { .i = {0x3F3504F3,0xBEDAE880,0xBF22679A,0x3F7853F8} }, //+0.707106769f, -0.427555084f, -0.634393334f, +0.970031261f + { .i = {0xBE47C5C2,0xBF4D9F02,0x3F61C599,0x3D48FB29} }, //-0.195090324f, -0.803207517f, +0.881921351f, +0.049067650f + { .i = {0xBF6C835E,0x3F3DAEF9,0x3E94A030,0xBF7D3AAC} }, //-0.923879504f, +0.740951121f, +0.290284634f, -0.989176512f + { .i = {0x3F0E39DD,0x3F039C3C,0xBF7EC46D,0x3EAC7CD5} }, //+0.555570424f, +0.514102697f, -0.995184720f, +0.336889893f + { .i = {0x3F3504F3,0xBF710909,0x3DC8BD5D,0x3F5B941A} }, //+0.707106769f, -0.941544116f, +0.098017432f, +0.857728601f + { .i = {0xBF54DB32,0xBE16407F,0x3F74FA0B,0xBF2BEB4B} }, //-0.831469655f, -0.146730408f, +0.956940353f, -0.671559036f + { .i = {0xBEC3EF0B,0x3F7FB10F,0xBEF15AED,0xBF187FBE} }, //-0.382683128f, +0.998795450f, -0.471396834f, -0.595699191f + { .i = {0x3F7B14BF,0xBE78CFCD,0xBF45E402,0x3F676BDA} }, //+0.980785310f, -0.242980197f, -0.773010373f, +0.903989434f + { .i = {0x3F3504F3,0xBF039C3D,0xBEF15AE8,0x3F7FB10F} }, //+0.707106769f, -0.514102757f, -0.471396685f, +0.998795450f + { .i = {0xBF0E39DC,0xBEDAE87B,0x3F7EC46D,0xBF187FC1} }, //-0.555570364f, -0.427554935f, +0.995184720f, -0.595699370f + { .i = {0xBEC3EF0B,0x3F7D3AAC,0xBF226799,0xBEAC7CD4} }, //-0.382683128f, +0.989176512f, -0.634393275f, -0.336889863f + { .i = {0x3F7B14BE,0xBF2BEB4B,0xBE94A02D,0x3F7853F8} }, //+0.980785251f, -0.671559036f, -0.290284544f, +0.970031261f + { .i = {0xBF3504F3,0xBE78CFBA,0x3F74FA0B,0xBF3DAEFB} }, //-0.707106769f, -0.242979914f, +0.956940353f, -0.740951240f + { .i = {0xBE47C5C6,0x3F710908,0xBF45E404,0xBE16407F} }, //-0.195090383f, +0.941544056f, -0.773010492f, -0.146730408f + { .i = {0x3F6C835E,0xBF4D9F04,0xBDC8BD1A,0x3F676BD8} }, //+0.923879504f, -0.803207636f, -0.098016933f, +0.903989315f + { .i = {0xBF54DB32,0xBD48FAD2,0x3F61C597,0xBF5B941A} }, //-0.831469655f, -0.049067326f, +0.881921232f, -0.857728601f + { .i = {0x3F3504F3,0xBF187FC1,0xBE94A02D,0x3F710908} }, //+0.707106769f, -0.595699370f, -0.290284544f, +0.941544056f + { .i = {0xBF54DB32,0x3D48FB58,0x3F45E403,0xBF7853F8} }, //-0.831469655f, +0.049067825f, +0.773010433f, -0.970031261f + { .i = {0x3EC3EF1B,0x3F039C3C,0xBF7EC46D,0x3F2BEB4C} }, //+0.382683605f, +0.514102697f, -0.995184720f, +0.671559095f + { .i = {0x3E47C5BC,0xBF676BD7,0x3F61C599,0xBE16408A} }, //+0.195090234f, -0.903989255f, +0.881921351f, -0.146730572f + { .i = {0xBF3504F1,0x3F7D3AAD,0xBEF15AED,0xBEDAE87B} }, //-0.707106650f, +0.989176571f, -0.471396834f, -0.427554935f + { .i = {0x3F7B14BE,0xBF3DAEFB,0xBDC8BD1A,0x3F5B941A} }, //+0.980785251f, -0.740951240f, -0.098016933f, +0.857728601f + { .i = {0xBF6C8360,0x3E78CFDB,0x3F226799,0xBF7FB10F} }, //-0.923879623f, +0.242980406f, +0.634393275f, -0.998795450f + { .i = {0x3F0E39DD,0x3EAC7CD3,0xBF74FA0A,0x3F4D9F05} }, //+0.555570424f, +0.336889833f, -0.956940293f, +0.803207695f + { .i = {0x3F3504F3,0xBF2BEB4B,0xBDC8BD1A,0x3F4D9F02} }, //+0.707106769f, -0.671559036f, -0.098016933f, +0.803207517f + { .i = {0xBF7B14BF,0x3F039C3E,0x3E94A030,0xBF676BD7} }, //-0.980785310f, +0.514102817f, +0.290284634f, -0.903989255f + { .i = {0x3F6C835F,0xBEAC7CD6,0xBEF15AE8,0x3F7853F8} }, //+0.923879564f, -0.336889923f, -0.471396685f, +0.970031261f + { .i = {0xBF54DB32,0x3E164080,0x3F226799,0xBF7FB10F} }, //-0.831469655f, +0.146730423f, +0.634393275f, -0.998795450f + { .i = {0x3F3504F7,0x3D48FB29,0xBF45E402,0x3F7D3AAD} }, //+0.707107008f, +0.049067650f, -0.773010373f, +0.989176571f + { .i = {0xBF0E39DC,0xBE78CFBA,0x3F61C597,0xBF710909} }, //-0.555570364f, -0.242979914f, +0.881921232f, -0.941544116f + { .i = {0x3EC3EF1B,0x3EDAE881,0xBF74FA0A,0x3F5B941B} }, //+0.382683605f, +0.427555114f, -0.956940293f, +0.857728660f + { .i = {0xBE47C5C2,0xBF187FBE,0x3F7EC46D,0xBF3DAEFB} }, //-0.195090324f, -0.595699191f, +0.995184720f, -0.740951240f + { .i = {0x3F3504F3,0xBF3DAEFB,0x3DC8BD5D,0x3F187FC0} }, //+0.707106769f, -0.740951240f, +0.098017432f, +0.595699310f + { .i = {0xBF7B14BE,0x3F5B941B,0xBE94A033,0xBEDAE87B} }, //-0.980785251f, +0.857728660f, -0.290284723f, -0.427554935f + { .i = {0x3F6C835E,0xBF710909,0x3EF15AE9,0x3E78CFC8} }, //+0.923879504f, -0.941544116f, +0.471396714f, +0.242980123f + { .i = {0xBF54DB30,0x3F7D3AAD,0xBF226799,0xBD48FAD2} }, //-0.831469536f, +0.989176571f, -0.634393275f, -0.049067326f + { .i = {0x3F3504F3,0xBF7FB10F,0x3F45E405,0xBE16408A} }, //+0.707106769f, -0.998795450f, +0.773010552f, -0.146730572f + { .i = {0xBF0E39D6,0x3F7853F8,0xBF61C599,0x3EAC7CD5} }, //-0.555570006f, +0.970031261f, -0.881921351f, +0.336889893f + { .i = {0x3EC3EF15,0xBF676BD7,0x3F74FA0C,0xBF039C3D} }, //+0.382683426f, -0.903989255f, +0.956940413f, -0.514102757f + { .i = {0xBE47C5C6,0x3F4D9F02,0xBF7EC46D,0x3F2BEB4C} }, //-0.195090383f, +0.803207517f, -0.995184720f, +0.671559095f + { .i = {0x3F3504F3,0xBF4D9F04,0x3E94A03D,0x3EAC7CD3} }, //+0.707106769f, -0.803207636f, +0.290285021f, +0.336889833f + { .i = {0xBF54DB30,0x3F7FB10F,0xBF45E404,0x3E78CFDB} }, //-0.831469536f, +0.998795450f, -0.773010492f, +0.242980406f + { .i = {0x3EC3EF15,0xBF5B9419,0x3F7EC46E,0xBF3DAEFB} }, //+0.382683426f, -0.857728541f, +0.995184779f, -0.740951240f + { .i = {0x3E47C5C8,0x3EDAE881,0xBF61C597,0x3F7D3AAD} }, //+0.195090413f, +0.427555114f, -0.881921232f, +0.989176571f + { .i = {0xBF3504F3,0x3E164080,0x3EF15AE7,0xBF676BD7} }, //-0.707106769f, +0.146730423f, +0.471396655f, -0.903989255f + { .i = {0x3F7B14BF,0xBF2BEB4B,0x3DC8BD5D,0x3F039C3C} }, //+0.980785310f, -0.671559036f, +0.098017432f, +0.514102697f + { .i = {0xBF6C835E,0x3F7853F8,0xBF226799,0x3D48FB58} }, //-0.923879504f, +0.970031261f, -0.634393275f, +0.049067825f + { .i = {0x3F0E39D9,0xBF710908,0x3F74FA0C,0xBF187FC1} }, //+0.555570185f, -0.941544056f, +0.956940413f, -0.595699370f + { .i = {0x3F3504F3,0xBF5B941A,0x3EF15AE9,0x3D48FB29} }, //+0.707106769f, -0.857728601f, +0.471396714f, +0.049067650f + { .i = {0xBF0E39D6,0x3F676BD8,0xBF7EC46D,0x3F4D9F05} }, //-0.555570006f, +0.903989315f, -0.995184720f, +0.803207695f + { .i = {0xBEC3EF18,0xBE16407F,0x3F226799,0xBF710908} }, //-0.382683516f, -0.146730408f, +0.634393275f, -0.941544056f + { .i = {0x3F7B14BF,0xBF3DAEFB,0x3E94A03D,0x3E78CFC8} }, //+0.980785310f, -0.740951240f, +0.290285021f, +0.242980123f + { .i = {0xBF3504F1,0x3F7853F8,0xBF74FA0B,0x3F2BEB4C} }, //-0.707106650f, +0.970031261f, -0.956940353f, +0.671559095f + { .i = {0xBE47C5C2,0xBEAC7CD4,0x3F45E403,0xBF7D3AAC} }, //-0.195090324f, -0.336889863f, +0.773010433f, -0.989176512f + { .i = {0x3F6C835F,0xBF187FC1,0x3DC8BD5D,0x3EDAE881} }, //+0.923879564f, -0.595699370f, +0.098017432f, +0.427555114f + { .i = {0xBF54DB30,0x3F7FB10F,0xBF61C599,0x3F039C3E} }, //-0.831469536f, +0.998795450f, -0.881921351f, +0.514102817f + { .i = {0x3F3504F3,0xBF676BD8,0x3F22679A,0xBE78CFCD} }, //+0.707106769f, -0.903989315f, +0.634393334f, -0.242980197f + { .i = {0xBE47C5C6,0x3F187FC0,0xBF61C597,0x3F7FB10F} }, //-0.195090383f, +0.595699310f, -0.881921232f, +0.998795450f + { .i = {0xBF6C8360,0x3F2BEB4C,0xBE94A033,0xBE16407F} }, //-0.923879623f, +0.671559095f, -0.290284723f, -0.146730408f + { .i = {0x3F0E39D9,0xBF5B9419,0x3F7EC46D,0xBF710909} }, //+0.555570185f, -0.857728541f, +0.995184720f, -0.941544116f + { .i = {0x3F3504F7,0xBEAC7CD6,0xBDC8BD1A,0x3F039C3C} }, //+0.707107008f, -0.336889923f, -0.098016933f, +0.514102697f + { .i = {0xBF54DB30,0x3F7D3AAC,0xBF74FA0B,0x3F3DAEF9} }, //-0.831469536f, +0.989176512f, -0.956940353f, +0.740951121f + { .i = {0xBEC3EF18,0xBD48FAD2,0x3EF15AE7,0xBF4D9F02} }, //-0.382683516f, -0.049067326f, +0.471396655f, -0.803207517f + { .i = {0x3F7B14BE,0xBF7853F8,0x3F45E405,0xBEDAE880} }, //+0.980785251f, -0.970031261f, +0.773010552f, -0.427555084f + { .i = {0x3F3504F3,0xBF710909,0x3F45E405,0xBF039C3D} }, //+0.707106769f, -0.941544116f, +0.773010552f, -0.514102757f + { .i = {0x3E47C5C8,0x3E164085,0xBEF15AE8,0x3F3DAEF9} }, //+0.195090413f, +0.146730497f, -0.471396685f, +0.740951121f + { .i = {0xBF6C835E,0x3F7FB10F,0xBF74FA0B,0x3F4D9F05} }, //-0.923879504f, +0.998795450f, -0.956940353f, +0.803207695f + { .i = {0xBF0E39DC,0x3E78CFDB,0x3DC8BD35,0xBEDAE87B} }, //-0.555570364f, +0.242980406f, +0.098017134f, -0.427554935f + { .i = {0x3F3504F3,0xBF676BD7,0x3F7EC46D,0xBF7853F8} }, //+0.707106769f, -0.903989255f, +0.995184720f, -0.970031261f + { .i = {0x3F54DB31,0xBF187FC1,0x3E94A03D,0x3D48FB29} }, //+0.831469595f, -0.595699370f, +0.290285021f, +0.049067650f + { .i = {0xBEC3EF0B,0x3F2BEB49,0xBF61C597,0x3F7D3AAC} }, //-0.382683128f, +0.671558917f, -0.881921232f, +0.989176512f + { .i = {0xBF7B14BF,0x3F5B941B,0xBF226799,0x3EAC7CD5} }, //-0.980785310f, +0.857728660f, -0.634393275f, +0.336889893f + { .i = {0x3F3504F3,0xBF7853F8,0x3F61C599,0xBF3DAEFB} }, //+0.707106769f, -0.970031261f, +0.881921351f, -0.740951240f + { .i = {0x3F0E39DD,0xBEAC7CD6,0x3DC8BD5D,0x3E164085} }, //+0.555570424f, -0.336889923f, +0.098017432f, +0.146730497f + { .i = {0xBEC3EF0B,0x3F187FC0,0xBF45E402,0x3F676BD8} }, //-0.382683128f, +0.595699310f, -0.773010373f, +0.903989315f + { .i = {0xBF7B14BE,0x3F7FB10F,0xBF74FA0B,0x3F5B941B} }, //-0.980785251f, +0.998795450f, -0.956940353f, +0.857728660f + { .i = {0xBF3504F3,0x3F039C3E,0xBE94A033,0x3D48FB58} }, //-0.707106769f, +0.514102817f, -0.290284723f, +0.049067825f + { .i = {0x3E47C5BC,0xBEDAE87B,0x3F226799,0xBF4D9F02} }, //+0.195090234f, -0.427554935f, +0.634393275f, -0.803207517f + { .i = {0x3F6C835E,0xBF7D3AAC,0x3F7EC46E,0xBF710909} }, //+0.923879504f, -0.989176512f, +0.995184779f, -0.941544116f + { .i = {0x3F54DB31,0xBF2BEB4B,0x3EF15AE9,0xBE78CFCD} }, //+0.831469595f, -0.671559036f, +0.471396714f, -0.242980197f + { .i = {0x3F3504F3,0xBF7D3AAC,0x3F74FA0C,0xBF676BD8} }, //+0.707106769f, -0.989176512f, +0.956940413f, -0.903989315f + { .i = {0x3F54DB31,0xBF3DAEFB,0x3F22679A,0xBF039C3D} }, //+0.831469595f, -0.740951240f, +0.634393334f, -0.514102757f + { .i = {0x3EC3EF1B,0xBE78CFCD,0x3DC8BD5D,0x3D48FB29} }, //+0.382683605f, -0.242980197f, +0.098017432f, +0.049067650f + { .i = {0xBE47C5C6,0x3EAC7CD3,0xBEF15AE8,0x3F187FC0} }, //-0.195090383f, +0.336889833f, -0.471396685f, +0.595699310f + { .i = {0xBF3504F1,0x3F4D9F02,0xBF61C597,0x3F710908} }, //-0.707106650f, +0.803207517f, -0.881921232f, +0.941544056f + { .i = {0xBF7B14BE,0x3F7FB10F,0xBF7EC46D,0x3F7853F8} }, //-0.980785251f, +0.998795450f, -0.995184720f, +0.970031261f + { .i = {0xBF6C8360,0x3F5B941B,0xBF45E404,0x3F2BEB4C} }, //-0.923879623f, +0.857728660f, -0.773010492f, +0.671559095f + { .i = {0xBF0E39DC,0x3EDAE88A,0xBE94A033,0x3E164080} }, //-0.555570364f, +0.427555382f, -0.290284723f, +0.146730423f + { .i = {0x3F3504F3,0xBF7FB10F,0x3F7EC46E,0xBF7D3AAC} }, //+0.707106769f, -0.998795450f, +0.995184779f, -0.989176512f + { .i = {0x3F7B14BF,0xBF7853F8,0x3F74FA0C,0xBF710909} }, //+0.980785310f, -0.970031261f, +0.956940413f, -0.941544116f + { .i = {0x3F6C835F,0xBF676BD8,0x3F61C599,0xBF5B941A} }, //+0.923879564f, -0.903989315f, +0.881921351f, -0.857728601f + { .i = {0x3F54DB31,0xBF4D9F04,0x3F45E405,0xBF3DAEFB} }, //+0.831469595f, -0.803207636f, +0.773010552f, -0.740951240f + { .i = {0x3F3504F7,0xBF2BEB4B,0x3F22679A,0xBF187FC1} }, //+0.707107008f, -0.671559036f, +0.634393334f, -0.595699370f + { .i = {0x3F0E39DD,0xBF039C3D,0x3EF15AE9,0xBEDAE880} }, //+0.555570424f, -0.514102757f, +0.471396714f, -0.427555084f + { .i = {0x3EC3EF1B,0xBEAC7CD6,0x3E94A03D,0xBE78CFCD} }, //+0.382683605f, -0.336889923f, +0.290285021f, -0.242980197f + { .i = {0x3E47C5C8,0xBE16408A,0x3DC8BD5D,0xBD48FB41} }, //+0.195090413f, -0.146730572f, +0.098017432f, -0.049067739f +}; + +/* standard MPEG1 filter bank (synth_window) + * Seems divided into 2 parts, or at least loaded to VU1 memory in 2 steps */ +static const REG_VF WINDOW_TABLE[512/4] = { + /* part 1 */ + { .i = {0x00000000,0xB7800074,0xB7800074,0xB7800074} }, //+0.000000000f, -0.000015259f, -0.000015259f, -0.000015259f + { .i = {0xB7800074,0xB7800074,0xB7800074,0xB8000074} }, //-0.000015259f, -0.000015259f, -0.000015259f, -0.000030518f + { .i = {0xB8000074,0xB8000074,0xB8000074,0xB83FFF9B} }, //-0.000030518f, -0.000030518f, -0.000030518f, -0.000045776f + { .i = {0xB83FFF9B,0xB87FFFD5,0xB87FFFD5,0xB8A00008} }, //-0.000045776f, -0.000061035f, -0.000061035f, -0.000076294f + { .i = {0xB8A00008,0xB8C00025,0xB8E00041,0xB8E00041} }, //-0.000076294f, -0.000091553f, -0.000106812f, -0.000106812f + { .i = {0xB8FFFFD5,0xB90FFFF9,0xB9200008,0xB9300016} }, //-0.000122070f, -0.000137329f, -0.000152588f, -0.000167847f + { .i = {0xB94FFFEE,0xB95FFFFD,0xB980000D,0xB987FFF2} }, //-0.000198364f, -0.000213623f, -0.000244141f, -0.000259399f + { .i = {0xB9980000,0xB9A8000F,0xB9C00002,0xB9D00011} }, //-0.000289917f, -0.000320435f, -0.000366211f, -0.000396729f + { .i = {0xB9E80004,0xB9F7FFF0,0xBA0C0007,0xBA180000} }, //-0.000442505f, -0.000473022f, -0.000534058f, -0.000579834f + { .i = {0xBA23FFFA,0xBA340008,0xBA440006,0xBA540003} }, //-0.000625610f, -0.000686646f, -0.000747681f, -0.000808716f + { .i = {0xBA680004,0xBA7C0005,0xBA880003,0xBA920003} }, //-0.000885010f, -0.000961304f, -0.001037598f, -0.001113892f + { .i = {0xBA9DFFFD,0xBAA9FFFF,0xBAB60002,0xBAC20004} }, //-0.001205444f, -0.001296997f, -0.001388550f, -0.001480103f + { .i = {0xBACFFFFF,0xBADE0004,0xBAE9FFFD,0xBAFA0003} }, //-0.001586914f, -0.001693726f, -0.001785278f, -0.001907349f + { .i = {0xBB03FFFF,0xBB0B0001,0xBB130000,0xBB1A0002} }, //-0.002014160f, -0.002120972f, -0.002243042f, -0.002349854f + { .i = {0xBB210000,0xBB28FFFE,0xBB300001,0xBB36FFFE} }, //-0.002456665f, -0.002578735f, -0.002685547f, -0.002792358f + { .i = {0xBB3E0000,0xBB440001,0xBB49FFFE,0xBB4FFFFF} }, //-0.002899170f, -0.002990723f, -0.003082275f, -0.003173828f + { .i = {0x3B550000,0x3B5A0000,0x3B5DFFFF,0x3B610002} }, //+0.003250122f, +0.003326416f, +0.003387451f, +0.003433228f + { .i = {0x3B62FFFF,0x3B640000,0x3B640000,0x3B62FFFF} }, //+0.003463745f, +0.003479004f, +0.003479004f, +0.003463745f + { .i = {0x3B600001,0x3B5CFFFE,0x3B570002,0x3B4FFFFF} }, //+0.003417969f, +0.003372192f, +0.003280640f, +0.003173828f + { .i = {0x3B480001,0x3B3CFFFF,0x3B310001,0x3B230002} }, //+0.003051758f, +0.002883911f, +0.002700806f, +0.002487183f + { .i = {0x3B11FFFF,0x3AFDFFFE,0x3AD40003,0x3AA5FFFC} }, //+0.002227783f, +0.001937866f, +0.001617432f, +0.001266479f + { .i = {0x3A640000,0x39E80004,0xB8000074,0xBA0FFFF9} }, //+0.000869751f, +0.000442505f, -0.000030518f, -0.000549316f + { .i = {0xBA900002,0xBADE0004,0xBB190001,0xBB44FFFE} }, //-0.001098633f, -0.001693726f, -0.002334595f, -0.003005981f + { .i = {0xBB740002,0xBB930000,0xBBAD8000,0xBBC87FFF} }, //-0.003723145f, -0.004486084f, -0.005294800f, -0.006118774f + { .i = {0xBBE58000,0xBC01C001,0xBC114000,0xBC214000} }, //-0.007003784f, -0.007919312f, -0.008865356f, -0.009841919f + { .i = {0xBC31C000,0xBC42C000,0xBC540000,0xBC65C000} }, //-0.010848999f, -0.011886597f, -0.012939453f, -0.014022827f + { .i = {0xBC77C000,0xBC850000,0xBC8E2000,0xBC974000} }, //-0.015121460f, -0.016235352f, -0.017349243f, -0.018463135f + { .i = {0xBCA06000,0xBCA98000,0xBCB28000,0xBCBB4000} }, //-0.019577026f, -0.020690918f, -0.021789551f, -0.022857666f + { .i = {0xBCC3E000,0xBCCC4000,0xBCD44000,0xBCDBE000} }, //-0.023910522f, -0.024932861f, -0.025909424f, -0.026840210f + { .i = {0xBCE32000,0xBCE9C000,0xBCEFE000,0xBCF54000} }, //-0.027725220f, -0.028533936f, -0.029281616f, -0.029937744f + { .i = {0xBCFA2000,0xBCFE0000,0xBD009000,0xBD01B000} }, //-0.030532837f, -0.031005859f, -0.031387329f, -0.031661987f + { .i = {0xBD025000,0xBD027000,0xBD020000,0xBD00F000} }, //-0.031814575f, -0.031845093f, -0.031738281f, -0.031478882f + { .i = {0x3CFEA000,0x3CFA0000,0x3CF40000,0x3CECA000} }, //+0.031082153f, +0.030517578f, +0.029785156f, +0.028884888f + { .i = {0x3CE3C000,0x3CD96000,0x3CCD8000,0x3CBFE000} }, //+0.027801514f, +0.026535034f, +0.025085449f, +0.023422241f + { .i = {0x3CB0C000,0x3CA00000,0x3C8D6000,0x3C728000} }, //+0.021575928f, +0.019531250f, +0.017257690f, +0.014801025f + { .i = {0x3C468001,0x3C174000,0x3BC90000,0x3B390000} }, //+0.012115479f, +0.009231567f, +0.006134033f, +0.002822876f + { .i = {0xBA340008,0xBB8FFFFF,0xBC084000,0xBC4B8000} }, //-0.000686646f, -0.004394531f, -0.008316040f, -0.012420654f + { .i = {0xBC88E000,0xBCAD8000,0xBCD38000,0xBCFAC000} }, //-0.016708374f, -0.021179199f, -0.025817871f, -0.030609131f + { .i = {0xBD11A000,0xBD267000,0xBD3BC000,0xBD517000} }, //-0.035552979f, -0.040634155f, -0.045837402f, -0.051132202f + { .i = {0xBD679000,0xBD7DF000,0xBD8A4800,0xBD95A000} }, //-0.056533813f, -0.061996460f, -0.067520142f, -0.073059082f + { .i = {0xBDA10800,0xBDAC6800,0xBDB7B800,0xBDC2E800} }, //-0.078628540f, -0.084182739f, -0.089706421f, -0.095169067f + { .i = {0xBDCDE800,0xBDD8B800,0xBDE33800,0xBDED6800} }, //-0.100540161f, -0.105819702f, -0.110946655f, -0.115921021f + { .i = {0xBDF73000,0xBE004400,0xBE04AC00,0xBE08CC00} }, //-0.120697021f, -0.125259399f, -0.129562378f, -0.133590698f + { .i = {0xBE0C9800,0xBE100C00,0xBE132000,0xBE15C400} }, //-0.137298584f, -0.140670776f, -0.143676758f, -0.146255493f + { .i = {0xBE17FC00,0xBE19B800,0xBE1AF000,0xBE1B9C00} }, //-0.148422241f, -0.150115967f, -0.151306152f, -0.151962280f + { .i = {0xBE1BB800,0xBE1B3C00,0xBE1A1C00,0xBE185800} }, //-0.152069092f, -0.151596069f, -0.150497437f, -0.148773193f + { .i = {0xBE15E000,0xBE12B400,0xBE0ECC00,0xBE0A2000} }, //-0.146362305f, -0.143264771f, -0.139450073f, -0.134887695f + { .i = {0xBE04B000,0xBDFCE000,0xBDEEC000,0xBDDEF000} }, //-0.129577637f, -0.123474121f, -0.116577148f, -0.108856201f + { .i = {0x3DCD7000,0x3DBA3800,0x3DA54000,0x3D8E8800} }, //+0.100311279f, +0.090927124f, +0.080688477f, +0.069595337f + { .i = {0x3D6C0000,0x3D377000,0x3CFEA000,0x3C874000} }, //+0.057617188f, +0.044784546f, +0.031082153f, +0.016510010f + { .i = {0x3A8BFFFE,0xBC797FFF,0xBD04A000,0xBD4E4000} }, //+0.001068115f, -0.015228271f, -0.032379150f, -0.050354004f + { .i = {0xBD8DA800,0xBDB5D000,0xBDDF9000,0xBE057000} }, //-0.069168091f, -0.088775635f, -0.109161377f, -0.130310059f + { .i = {0xBE1BDC00,0xBE32FC00,0xBE4AD000,0xBE635000} }, //-0.152206421f, -0.174789429f, -0.198059082f, -0.221984863f + { .i = {0xBE7C6C00,0xBE8B0E00,0xBE982C00,0xBEA58A00} }, //-0.246505737f, -0.271591187f, -0.297210693f, -0.323318481f + { .i = {0xBEB32200,0xBEC0EC00,0xBECEE400,0xBEDD0200} }, //-0.349868774f, -0.376800537f, -0.404083252f, -0.431655884f + { .i = {0xBEEB4000,0xBEF99600,0xBF03FF00,0xBF0B3800} }, //-0.459472656f, -0.487472534f, -0.515609741f, -0.543823242f + { .i = {0xBF127100,0xBF19A800,0xBF20D800,0xBF27FE00} }, //-0.572036743f, -0.600219727f, -0.628295898f, -0.656219482f + { .i = {0xBF2F1500,0xBF361900,0xBF3D0600,0xBF43D900} }, //-0.683914185f, -0.711318970f, -0.738372803f, -0.765029907f + { .i = {0xBF4A8D00,0xBF511E00,0xBF578A00,0xBF5DCA00} }, //-0.791213989f, -0.816864014f, -0.841949463f, -0.866363525f + { .i = {0xBF63DD00,0xBF69BE00,0xBF6F6900,0xBF74DC00} }, //-0.890090942f, -0.913055420f, -0.935195923f, -0.956481934f + { .i = {0xBF7A1300,0xBF7F0A00,0xBF81DF00,0xBF841680} }, //-0.976852417f, -0.996246338f, -1.014617920f, -1.031936646f + { .i = {0xBF862A00,0xBF881780,0xBF89DF00,0xBF8B7E00} }, //-1.048156738f, -1.063217163f, -1.077117920f, -1.089782715f + { .i = {0xBF8CF480,0xBF8E4180,0xBF8F6380,0xBF905A00} }, //-1.101211548f, -1.111373901f, -1.120223999f, -1.127746582f + { .i = {0xBF912480,0xBF91C300,0xBF923400,0xBF927800} }, //-1.133926392f, -1.138763428f, -1.142211914f, -1.144287109f + /* part 2 */ + { .i = {0x3F928F00,0x3F927800,0x3F923400,0x3F91C300} }, //+1.144989014f, +1.144287109f, +1.142211914f, +1.138763428f + { .i = {0x3F912480,0x3F905A00,0x3F8F6380,0x3F8E4180} }, //+1.133926392f, +1.127746582f, +1.120223999f, +1.111373901f + { .i = {0x3F8CF480,0x3F8B7E00,0x3F89DF00,0x3F881780} }, //+1.101211548f, +1.089782715f, +1.077117920f, +1.063217163f + { .i = {0x3F862A00,0x3F841680,0x3F81DF00,0x3F7F0A00} }, //+1.048156738f, +1.031936646f, +1.014617920f, +0.996246338f + { .i = {0x3F7A1300,0x3F74DC00,0x3F6F6900,0x3F69BE00} }, //+0.976852417f, +0.956481934f, +0.935195923f, +0.913055420f + { .i = {0x3F63DD00,0x3F5DCA00,0x3F578A00,0x3F511E00} }, //+0.890090942f, +0.866363525f, +0.841949463f, +0.816864014f + { .i = {0x3F4A8D00,0x3F43D900,0x3F3D0600,0x3F361900} }, //+0.791213989f, +0.765029907f, +0.738372803f, +0.711318970f + { .i = {0x3F2F1500,0x3F27FE00,0x3F20D800,0x3F19A800} }, //+0.683914185f, +0.656219482f, +0.628295898f, +0.600219727f + { .i = {0x3F127100,0x3F0B3800,0x3F03FF00,0x3EF99600} }, //+0.572036743f, +0.543823242f, +0.515609741f, +0.487472534f + { .i = {0x3EEB4000,0x3EDD0200,0x3ECEE400,0x3EC0EC00} }, //+0.459472656f, +0.431655884f, +0.404083252f, +0.376800537f + { .i = {0x3EB32200,0x3EA58A00,0x3E982C00,0x3E8B0E00} }, //+0.349868774f, +0.323318481f, +0.297210693f, +0.271591187f + { .i = {0x3E7C6C00,0x3E635000,0x3E4AD000,0x3E32FC00} }, //+0.246505737f, +0.221984863f, +0.198059082f, +0.174789429f + { .i = {0x3E1BDC00,0x3E057000,0x3DDF9000,0x3DB5D000} }, //+0.152206421f, +0.130310059f, +0.109161377f, +0.088775635f + { .i = {0x3D8DA800,0x3D4E4000,0x3D04A000,0x3C797FFF} }, //+0.069168091f, +0.050354004f, +0.032379150f, +0.015228271f + { .i = {0xBA8BFFFE,0xBC874000,0xBCFEA000,0xBD377000} }, //-0.001068115f, -0.016510010f, -0.031082153f, -0.044784546f + { .i = {0xBD6C0000,0xBD8E8800,0xBDA54000,0xBDBA3800} }, //-0.057617188f, -0.069595337f, -0.080688477f, -0.090927124f + { .i = {0x3DCD7000,0x3DDEF000,0x3DEEC000,0x3DFCE000} }, //+0.100311279f, +0.108856201f, +0.116577148f, +0.123474121f + { .i = {0x3E04B000,0x3E0A2000,0x3E0ECC00,0x3E12B400} }, //+0.129577637f, +0.134887695f, +0.139450073f, +0.143264771f + { .i = {0x3E15E000,0x3E185800,0x3E1A1C00,0x3E1B3C00} }, //+0.146362305f, +0.148773193f, +0.150497437f, +0.151596069f + { .i = {0x3E1BB800,0x3E1B9C00,0x3E1AF000,0x3E19B800} }, //+0.152069092f, +0.151962280f, +0.151306152f, +0.150115967f + { .i = {0x3E17FC00,0x3E15C400,0x3E132000,0x3E100C00} }, //+0.148422241f, +0.146255493f, +0.143676758f, +0.140670776f + { .i = {0x3E0C9800,0x3E08CC00,0x3E04AC00,0x3E004400} }, //+0.137298584f, +0.133590698f, +0.129562378f, +0.125259399f + { .i = {0x3DF73000,0x3DED6800,0x3DE33800,0x3DD8B800} }, //+0.120697021f, +0.115921021f, +0.110946655f, +0.105819702f + { .i = {0x3DCDE800,0x3DC2E800,0x3DB7B800,0x3DAC6800} }, //+0.100540161f, +0.095169067f, +0.089706421f, +0.084182739f + { .i = {0x3DA10800,0x3D95A000,0x3D8A4800,0x3D7DF000} }, //+0.078628540f, +0.073059082f, +0.067520142f, +0.061996460f + { .i = {0x3D679000,0x3D517000,0x3D3BC000,0x3D267000} }, //+0.056533813f, +0.051132202f, +0.045837402f, +0.040634155f + { .i = {0x3D11A000,0x3CFAC000,0x3CD38000,0x3CAD8000} }, //+0.035552979f, +0.030609131f, +0.025817871f, +0.021179199f + { .i = {0x3C88E000,0x3C4B8000,0x3C084000,0x3B8FFFFF} }, //+0.016708374f, +0.012420654f, +0.008316040f, +0.004394531f + { .i = {0x3A340008,0xBB390000,0xBBC90000,0xBC174000} }, //+0.000686646f, -0.002822876f, -0.006134033f, -0.009231567f + { .i = {0xBC468001,0xBC728000,0xBC8D6000,0xBCA00000} }, //-0.012115479f, -0.014801025f, -0.017257690f, -0.019531250f + { .i = {0xBCB0C000,0xBCBFE000,0xBCCD8000,0xBCD96000} }, //-0.021575928f, -0.023422241f, -0.025085449f, -0.026535034f + { .i = {0xBCE3C000,0xBCECA000,0xBCF40000,0xBCFA0000} }, //-0.027801514f, -0.028884888f, -0.029785156f, -0.030517578f + { .i = {0x3CFEA000,0x3D00F000,0x3D020000,0x3D027000} }, //+0.031082153f, +0.031478882f, +0.031738281f, +0.031845093f + { .i = {0x3D025000,0x3D01B000,0x3D009000,0x3CFE0000} }, //+0.031814575f, +0.031661987f, +0.031387329f, +0.031005859f + { .i = {0x3CFA2000,0x3CF54000,0x3CEFE000,0x3CE9C000} }, //+0.030532837f, +0.029937744f, +0.029281616f, +0.028533936f + { .i = {0x3CE32000,0x3CDBE000,0x3CD44000,0x3CCC4000} }, //+0.027725220f, +0.026840210f, +0.025909424f, +0.024932861f + { .i = {0x3CC3E000,0x3CBB4000,0x3CB28000,0x3CA98000} }, //+0.023910522f, +0.022857666f, +0.021789551f, +0.020690918f + { .i = {0x3CA06000,0x3C974000,0x3C8E2000,0x3C850000} }, //+0.019577026f, +0.018463135f, +0.017349243f, +0.016235352f + { .i = {0x3C77C000,0x3C65C000,0x3C540000,0x3C42C000} }, //+0.015121460f, +0.014022827f, +0.012939453f, +0.011886597f + { .i = {0x3C31C000,0x3C214000,0x3C114000,0x3C01C001} }, //+0.010848999f, +0.009841919f, +0.008865356f, +0.007919312f + { .i = {0x3BE58000,0x3BC87FFF,0x3BAD8000,0x3B930000} }, //+0.007003784f, +0.006118774f, +0.005294800f, +0.004486084f + { .i = {0x3B740002,0x3B44FFFE,0x3B190001,0x3ADE0004} }, //+0.003723145f, +0.003005981f, +0.002334595f, +0.001693726f + { .i = {0x3A900002,0x3A0FFFF9,0x38000074,0xB9E80004} }, //+0.001098633f, +0.000549316f, +0.000030518f, -0.000442505f + { .i = {0xBA640000,0xBAA5FFFC,0xBAD40003,0xBAFDFFFE} }, //-0.000869751f, -0.001266479f, -0.001617432f, -0.001937866f + { .i = {0xBB11FFFF,0xBB230002,0xBB310001,0xBB3CFFFF} }, //-0.002227783f, -0.002487183f, -0.002700806f, -0.002883911f + { .i = {0xBB480001,0xBB4FFFFF,0xBB570002,0xBB5CFFFE} }, //-0.003051758f, -0.003173828f, -0.003280640f, -0.003372192f + { .i = {0xBB600001,0xBB62FFFF,0xBB640000,0xBB640000} }, //-0.003417969f, -0.003463745f, -0.003479004f, -0.003479004f + { .i = {0xBB62FFFF,0xBB610002,0xBB5DFFFF,0xBB5A0000} }, //-0.003463745f, -0.003433228f, -0.003387451f, -0.003326416f + { .i = {0x3B550000,0x3B4FFFFF,0x3B49FFFE,0x3B440001} }, //+0.003250122f, +0.003173828f, +0.003082275f, +0.002990723f + { .i = {0x3B3E0000,0x3B36FFFE,0x3B300001,0x3B28FFFE} }, //+0.002899170f, +0.002792358f, +0.002685547f, +0.002578735f + { .i = {0x3B210000,0x3B1A0002,0x3B130000,0x3B0B0001} }, //+0.002456665f, +0.002349854f, +0.002243042f, +0.002120972f + { .i = {0x3B03FFFF,0x3AFA0003,0x3AE9FFFD,0x3ADE0004} }, //+0.002014160f, +0.001907349f, +0.001785278f, +0.001693726f + { .i = {0x3ACFFFFF,0x3AC20004,0x3AB60002,0x3AA9FFFF} }, //+0.001586914f, +0.001480103f, +0.001388550f, +0.001296997f + { .i = {0x3A9DFFFD,0x3A920003,0x3A880003,0x3A7C0005} }, //+0.001205444f, +0.001113892f, +0.001037598f, +0.000961304f + { .i = {0x3A680004,0x3A540003,0x3A440006,0x3A340008} }, //+0.000885010f, +0.000808716f, +0.000747681f, +0.000686646f + { .i = {0x3A23FFFA,0x3A180000,0x3A0C0007,0x39F7FFF0} }, //+0.000625610f, +0.000579834f, +0.000534058f, +0.000473022f + { .i = {0x39E80004,0x39D00011,0x39C00002,0x39A8000F} }, //+0.000442505f, +0.000396729f, +0.000366211f, +0.000320435f + { .i = {0x39980000,0x3987FFF2,0x3980000D,0x395FFFFD} }, //+0.000289917f, +0.000259399f, +0.000244141f, +0.000213623f + { .i = {0x394FFFEE,0x39300016,0x39200008,0x390FFFF9} }, //+0.000198364f, +0.000167847f, +0.000152588f, +0.000137329f + { .i = {0x38FFFFD5,0x38E00041,0x38E00041,0x38C00025} }, //+0.000122070f, +0.000106812f, +0.000106812f, +0.000091553f + { .i = {0x38A00008,0x38A00008,0x387FFFD5,0x387FFFD5} }, //+0.000076294f, +0.000076294f, +0.000061035f, +0.000061035f + { .i = {0x383FFF9B,0x383FFF9B,0x38000074,0x38000074} }, //+0.000045776f, +0.000045776f, +0.000030518f, +0.000030518f + { .i = {0x38000074,0x38000074,0x37800074,0x37800074} }, //+0.000030518f, +0.000030518f, +0.000015259f, +0.000015259f + { .i = {0x37800074,0x37800074,0x37800074,0x37800074} }, //+0.000015259f, +0.000015259f, +0.000015259f, +0.000015259f +}; + +/* DCT-II table? */ +static const REG_VF SYNTH_TABLE[32/4] = { + { .i = {0x3F000000,0x3F002785,0x3F009E8D,0x3F01668B} }, //+0.500000000f, +0.500603020f, +0.502419293f, +0.505470932f + { .i = {0x3F0281F6,0x3F03F45A,0x3F05C278,0x3F07F268} }, //+0.509795547f, +0.515447259f, +0.522498608f, +0.531042576f + { .i = {0x3F0A8BD4,0x3F0D9837,0x3F11233F,0x3F153B3A} }, //+0.541196108f, +0.553103864f, +0.566944063f, +0.582934976f + { .i = {0x3F19F1BD,0x3F1F5C6E,0x3F25961C,0x3F2CC03D} }, //+0.601344883f, +0.622504115f, +0.646821737f, +0.674808323f + { .i = {0x3F3504F2,0x3F3E99ED,0x3F49C480,0x3F56DF9E} }, //+0.707106709f, +0.744536221f, +0.788154602f, +0.839349627f + { .i = {0x3F6664D7,0x3F78FA3B,0x3F87C449,0x3F95B034} }, //+0.899976194f, +0.972568214f, +1.060677648f, +1.169439793f + { .i = {0x3FA73D74,0x3FBDF91B,0x3FDC7925,0x4003B2AF} }, //+1.306562901f, +1.484164596f, +1.722447038f, +2.057780981f + { .i = {0x402406CE,0x405A1641,0x40A33C9C,0x41230A46} }, //+2.562915325f, +3.407608271f, +5.101148605f, +10.190008163f +}; + +#endif /* _TAC_DECODER_LIB_DATA_H_ */ diff --git a/src/coding/tac_decoder_lib_ops.h b/src/coding/tac_decoder_lib_ops.h new file mode 100644 index 00000000..1f3e77d5 --- /dev/null +++ b/src/coding/tac_decoder_lib_ops.h @@ -0,0 +1,377 @@ +#ifndef _TAC_DECODER_LIB_OPS_H_ +#define _TAC_DECODER_LIB_OPS_H_ + +#include +#include "tac_decoder_lib_ops.h" + +/* The following ops are similar to VU1's ops, but not quite the same. For example VU1 has special op + * registers like the ACC, and updates zero/neg/etc flags per op (plus added here a few helper ops). + * Main reason to use them vs doing standard +*-/ in code is allowing to simulate PS2 floats. + * See Nisto's decoder for actual emulation. */ + + +/* PS2 floats are slightly different vs IEEE 754 floats: + * - NaN and Inf (exp 255) don't exist on the PS2, meaning it has a bigger range of floats + * - denormals (exp 0) don't exist either, and ops truncate to 0 + * - rounding on PS2 always rounds towards zero + * The code below (partially) simulates this, but for audio it only means +-1 differences, + * plus we can't fully emulate exact behaviour, so it's disabled for performance + * (function call is optimized out by compiler). */ +#define TAC_ENABLE_PS2_FLOATS 0 + +static inline void UPDATE_FLOATS(uint8_t dest, REG_VF *vf) { +#if TAC_ENABLE_PS2_FLOATS + int i; + + for (i = 0; i < 4; i++) { + int shift = 3 - i; + if (dest & (1 << shift)) { + + if (vf->F[i] == 0.0) { + uint32_t v = vf->UL[i]; + int exp = (v >> 23) & 0xff; + uint32_t s = v & 0x80000000; + + switch (exp) { + case 0: + vf->UL[i] = s; + break; + case 255: + vf->UL[i] = s|0x7f7fffff; /* max allowed */ + break; + default: /* standard */ + vf->UL[i] = v; + break; + } + } + } + } +#endif +} + +static inline void _DIV_INTERNAL(REG_VF *fd, const REG_VF *fs, const REG_VF *ft, int from) { + float dividend = fs->F[from]; + float divisor = ft->F[from]; + +#if TAC_ENABLE_PS2_FLOATS + if (divisor == 0.0) { + if ((ft->UL[from] & 0x80000000) != (0x80000000 & fs->UL[from])) { + fd->UL[from] = 0xFF7FFFFF; + } + else { + fd->UL[from] = 0x7F7FFFFF; + } + + } + else { + fd->F[from] = dividend / divisor; + } +#else + fd->F[from] = dividend / divisor; +#endif +} + +/////////////////////////////////////////////////////////////////////////////// + +static inline void DIV(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) _DIV_INTERNAL(fd, fs, ft, 0); + if (dest & __y__) _DIV_INTERNAL(fd, fs, ft, 1); + if (dest & ___z_) _DIV_INTERNAL(fd, fs, ft, 2); + if (dest & ____w) _DIV_INTERNAL(fd, fs, ft, 3); + UPDATE_FLOATS(dest, fd); +} + +/////////////////////////////////////////////////////////////////////////////// + +static inline void ADD(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x + ft->f.x; + if (dest & __y__) fd->f.y = fs->f.y + ft->f.y; + if (dest & ___z_) fd->f.z = fs->f.z + ft->f.z; + if (dest & ____w) fd->f.w = fs->f.w + ft->f.w; + UPDATE_FLOATS(dest, fd); +} + +static inline void ADDx(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x + ft->f.x; + if (dest & __y__) fd->f.y = fs->f.y + ft->f.x; + if (dest & ___z_) fd->f.z = fs->f.z + ft->f.x; + if (dest & ____w) fd->f.w = fs->f.w + ft->f.x; + UPDATE_FLOATS(dest, fd); +} + +static inline void ADDy(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x + ft->f.y; + if (dest & __y__) fd->f.y = fs->f.y + ft->f.y; + if (dest & ___z_) fd->f.z = fs->f.z + ft->f.y; + if (dest & ____w) fd->f.w = fs->f.w + ft->f.y; + UPDATE_FLOATS(dest, fd); +} + +static inline void ADDz(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x + ft->f.z; + if (dest & __y__) fd->f.y = fs->f.y + ft->f.z; + if (dest & ___z_) fd->f.z = fs->f.z + ft->f.z; + if (dest & ____w) fd->f.w = fs->f.w + ft->f.z; + UPDATE_FLOATS(dest, fd); +} + +static inline void ADDw(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x + ft->f.w; + if (dest & __y__) fd->f.y = fs->f.y + ft->f.w; + if (dest & ___z_) fd->f.z = fs->f.z + ft->f.w; + if (dest & ____w) fd->f.w = fs->f.w + ft->f.w; + UPDATE_FLOATS(dest, fd); +} + +/////////////////////////////////////////////////////////////////////////////// + +static inline void SUB(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x - ft->f.x; + if (dest & __y__) fd->f.y = fs->f.y - ft->f.y; + if (dest & ___z_) fd->f.z = fs->f.z - ft->f.z; + if (dest & ____w) fd->f.w = fs->f.w - ft->f.w; + UPDATE_FLOATS(dest, fd); +} + +static inline void SUBx(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x - ft->f.x; + if (dest & __y__) fd->f.y = fs->f.y - ft->f.x; + if (dest & ___z_) fd->f.z = fs->f.z - ft->f.x; + if (dest & ____w) fd->f.w = fs->f.w - ft->f.x; + UPDATE_FLOATS(dest, fd); +} + +static inline void SUBy(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x - ft->f.y; + if (dest & __y__) fd->f.y = fs->f.y - ft->f.y; + if (dest & ___z_) fd->f.z = fs->f.z - ft->f.y; + if (dest & ____w) fd->f.w = fs->f.w - ft->f.y; + UPDATE_FLOATS(dest, fd); +} + +static inline void SUBz(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x - ft->f.z; + if (dest & __y__) fd->f.y = fs->f.y - ft->f.z; + if (dest & ___z_) fd->f.z = fs->f.z - ft->f.z; + if (dest & ____w) fd->f.w = fs->f.w - ft->f.z; + UPDATE_FLOATS(dest, fd); +} + +static inline void SUBw(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x - ft->f.w; + if (dest & __y__) fd->f.y = fs->f.y - ft->f.w; + if (dest & ___z_) fd->f.z = fs->f.z - ft->f.w; + if (dest & ____w) fd->f.w = fs->f.w - ft->f.w; + UPDATE_FLOATS(dest, fd); +} + +/////////////////////////////////////////////////////////////////////////////// + +static inline void MUL(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x * ft->f.x; + if (dest & __y__) fd->f.y = fs->f.y * ft->f.y; + if (dest & ___z_) fd->f.z = fs->f.z * ft->f.z; + if (dest & ____w) fd->f.w = fs->f.w * ft->f.w; + UPDATE_FLOATS(dest, fd); +} + +static inline void MULx(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x * ft->f.x; + if (dest & __y__) fd->f.y = fs->f.y * ft->f.x; + if (dest & ___z_) fd->f.z = fs->f.z * ft->f.x; + if (dest & ____w) fd->f.w = fs->f.w * ft->f.x; + UPDATE_FLOATS(dest, fd); +} + +static inline void MULy(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x * ft->f.y; + if (dest & __y__) fd->f.y = fs->f.y * ft->f.y; + if (dest & ___z_) fd->f.z = fs->f.z * ft->f.y; + if (dest & ____w) fd->f.w = fs->f.w * ft->f.y; + UPDATE_FLOATS(dest, fd); +} + +static inline void MULz(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x * ft->f.z; + if (dest & __y__) fd->f.y = fs->f.y * ft->f.z; + if (dest & ___z_) fd->f.z = fs->f.z * ft->f.z; + if (dest & ____w) fd->f.w = fs->f.w * ft->f.z; + UPDATE_FLOATS(dest, fd); +} + +static inline void MULw(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fs->f.x * ft->f.w; + if (dest & __y__) fd->f.y = fs->f.y * ft->f.w; + if (dest & ___z_) fd->f.z = fs->f.z * ft->f.w; + if (dest & ____w) fd->f.w = fs->f.w * ft->f.w; + UPDATE_FLOATS(dest, fd); +} + +/////////////////////////////////////////////////////////////////////////////// + +static inline void MADD(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fd->f.x + (fs->f.x * ft->f.x); + if (dest & __y__) fd->f.y = fd->f.y + (fs->f.y * ft->f.y); + if (dest & ___z_) fd->f.z = fd->f.z + (fs->f.z * ft->f.z); + if (dest & ____w) fd->f.w = fd->f.w + (fs->f.w * ft->f.w); + UPDATE_FLOATS(dest, fd); +} + +static inline void MADDx(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fd->f.x + (fs->f.x * ft->f.x); + if (dest & __y__) fd->f.y = fd->f.y + (fs->f.y * ft->f.x); + if (dest & ___z_) fd->f.z = fd->f.z + (fs->f.z * ft->f.x); + if (dest & ____w) fd->f.w = fd->f.w + (fs->f.w * ft->f.x); + UPDATE_FLOATS(dest, fd); +} + +static inline void MADDy(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fd->f.x + (fs->f.x * ft->f.y); + if (dest & __y__) fd->f.y = fd->f.y + (fs->f.y * ft->f.y); + if (dest & ___z_) fd->f.z = fd->f.z + (fs->f.z * ft->f.y); + if (dest & ____w) fd->f.w = fd->f.w + (fs->f.w * ft->f.y); + UPDATE_FLOATS(dest, fd); +} + +static inline void MADDz(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fd->f.x + (fs->f.x * ft->f.z); + if (dest & __y__) fd->f.y = fd->f.y + (fs->f.y * ft->f.z); + if (dest & ___z_) fd->f.z = fd->f.z + (fs->f.z * ft->f.z); + if (dest & ____w) fd->f.w = fd->f.w + (fs->f.w * ft->f.z); + UPDATE_FLOATS(dest, fd); +} + +static inline void MADDw(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fd->f.x + (fs->f.x * ft->f.w); + if (dest & __y__) fd->f.y = fd->f.y + (fs->f.y * ft->f.w); + if (dest & ___z_) fd->f.z = fd->f.z + (fs->f.z * ft->f.w); + if (dest & ____w) fd->f.w = fd->f.w + (fs->f.w * ft->f.w); + UPDATE_FLOATS(dest, fd); +} + +static inline void MSUBx(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fd->f.x - (fs->f.x * ft->f.x); + if (dest & __y__) fd->f.y = fd->f.y - (fs->f.y * ft->f.x); + if (dest & ___z_) fd->f.z = fd->f.z - (fs->f.z * ft->f.x); + if (dest & ____w) fd->f.w = fd->f.w - (fs->f.w * ft->f.x); + UPDATE_FLOATS(dest, fd); +} + +static inline void MSUBy(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fd->f.x - (fs->f.x * ft->f.y); + if (dest & __y__) fd->f.y = fd->f.y - (fs->f.y * ft->f.y); + if (dest & ___z_) fd->f.z = fd->f.z - (fs->f.z * ft->f.y); + if (dest & ____w) fd->f.w = fd->f.w - (fs->f.w * ft->f.y); + UPDATE_FLOATS(dest, fd); +} + +static inline void MSUBz(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fd->f.x - (fs->f.x * ft->f.z); + if (dest & __y__) fd->f.y = fd->f.y - (fs->f.y * ft->f.z); + if (dest & ___z_) fd->f.z = fd->f.z - (fs->f.z * ft->f.z); + if (dest & ____w) fd->f.w = fd->f.w - (fs->f.w * ft->f.z); + UPDATE_FLOATS(dest, fd); +} + +static inline void MSUBw(uint8_t dest, REG_VF *fd, const REG_VF *fs, const REG_VF *ft) { + if (dest & _x___) fd->f.x = fd->f.x - (fs->f.x * ft->f.w); + if (dest & __y__) fd->f.y = fd->f.y - (fs->f.y * ft->f.w); + if (dest & ___z_) fd->f.z = fd->f.z - (fs->f.z * ft->f.w); + if (dest & ____w) fd->f.w = fd->f.w - (fs->f.w * ft->f.w); + UPDATE_FLOATS(dest, fd); +} + +/////////////////////////////////////////////////////////////////////////////// + +static inline void FMUL(uint8_t dest, REG_VF *fd, const REG_VF *fs, const float I_F) { + if (dest & _x___) fd->f.x = fs->f.x * I_F; + if (dest & __y__) fd->f.y = fs->f.y * I_F; + if (dest & ___z_) fd->f.z = fs->f.z * I_F; + if (dest & ____w) fd->f.w = fs->f.w * I_F; + UPDATE_FLOATS(dest, fd); +} + +static inline void FMULf(uint8_t dest, REG_VF *fd, const float fs) { + if (dest & _x___) fd->f.x = fd->f.x * fs; + if (dest & __y__) fd->f.y = fd->f.y * fs; + if (dest & ___z_) fd->f.z = fd->f.z * fs; + if (dest & ____w) fd->f.w = fd->f.w * fs; + UPDATE_FLOATS(dest, fd); +} + +/////////////////////////////////////////////////////////////////////////////// + +static inline void ABS(uint8_t dest, REG_VF *ft, const REG_VF *fs) { + if (dest & _x___) ft->f.x = fabsf(fs->f.x); + if (dest & __y__) ft->f.y = fabsf(fs->f.y); + if (dest & ___z_) ft->f.z = fabsf(fs->f.z); + if (dest & ____w) ft->f.w = fabsf(fs->f.w); +} + +static inline void FTOI0(uint8_t dest, REG_VF *ft, const REG_VF *fs) { + if (dest & _x___) ft->SL[0] = (int32_t)fs->f.x; + if (dest & __y__) ft->SL[1] = (int32_t)fs->f.y; + if (dest & ___z_) ft->SL[2] = (int32_t)fs->f.z; + if (dest & ____w) ft->SL[3] = (int32_t)fs->f.w; +} + +static inline void ITOF0(uint8_t dest, REG_VF *ft, const REG_VF *fs) { + if (dest & _x___) ft->f.x = (float)fs->SL[0]; + if (dest & __y__) ft->f.y = (float)fs->SL[1]; + if (dest & ___z_) ft->f.z = (float)fs->SL[2]; + if (dest & ____w) ft->f.w = (float)fs->SL[3]; +} + +static inline void MR32(uint8_t dest, REG_VF *ft, const REG_VF *fs) { + float x = fs->f.x; + if (dest & _x___) ft->f.x = fs->f.y; + if (dest & __y__) ft->f.y = fs->f.z; + if (dest & ___z_) ft->f.z = fs->f.w; + if (dest & ____w) ft->f.w = x; +} + +/////////////////////////////////////////////////////////////////////////////// + +static inline void LOAD(uint8_t dest, REG_VF *ft, REG_VF* src, int pos) { + if (dest & _x___) ft->f.x = src[pos].f.x; + if (dest & __y__) ft->f.y = src[pos].f.y; + if (dest & ___z_) ft->f.z = src[pos].f.z; + if (dest & ____w) ft->f.w = src[pos].f.w; +} + +static inline void STORE(uint8_t dest, REG_VF* dst, const REG_VF *fs, int pos) { + if (dest & _x___) dst[pos].f.x = fs->f.x; + if (dest & __y__) dst[pos].f.y = fs->f.y; + if (dest & ___z_) dst[pos].f.z = fs->f.z; + if (dest & ____w) dst[pos].f.w = fs->f.w; +} + +static inline void MOVE(uint8_t dest, REG_VF *fd, const REG_VF *fs) { + if (dest & _x___) fd->f.x = fs->f.x; + if (dest & __y__) fd->f.y = fs->f.y; + if (dest & ___z_) fd->f.z = fs->f.z; + if (dest & ____w) fd->f.w = fs->f.w; +} + +static inline void MOVEx(uint8_t dest, REG_VF *fd, const REG_VF *fs) { + if (dest & _x___) fd->f.x = fs->f.x; + if (dest & __y__) fd->f.y = fs->f.x; + if (dest & ___z_) fd->f.z = fs->f.x; + if (dest & ____w) fd->f.w = fs->f.x; +} + +static inline void SIGN(uint8_t dest, REG_VF *fd, const REG_VF *fs) { + if (dest & _x___) if (fs->f.x < 0) fd->f.x = -fd->f.x; + if (dest & __y__) if (fs->f.y < 0) fd->f.y = -fd->f.y; + if (dest & ___z_) if (fs->f.z < 0) fd->f.z = -fd->f.z; + if (dest & ____w) if (fs->f.w < 0) fd->f.w = -fd->f.w; +} + +static inline void COPY(uint8_t dest, REG_VF *fd, const int16_t* buf) { + if (dest & _x___) fd->f.x = buf[0]; + if (dest & __y__) fd->f.y = buf[1]; + if (dest & ___z_) fd->f.z = buf[2]; + if (dest & ____w) fd->f.w = buf[3]; +} + +#endif /* _TAC_DECODER_LIB_OPS_H_ */ diff --git a/src/decode.c b/src/decode.c index 50001273..e5a1af2e 100644 --- a/src/decode.c +++ b/src/decode.c @@ -32,6 +32,10 @@ void free_codec(VGMSTREAM* vgmstream) { free_hca(vgmstream->codec_data); } + if (vgmstream->coding_type == coding_TAC) { + free_tac(vgmstream->codec_data); + } + if (vgmstream->coding_type == coding_UBI_ADPCM) { free_ubi_adpcm(vgmstream->codec_data); } @@ -125,8 +129,8 @@ void seek_codec(VGMSTREAM* vgmstream) { seek_relic(vgmstream->codec_data, vgmstream->loop_current_sample); } - if (vgmstream->coding_type == coding_CRI_HCA) { - loop_hca(vgmstream->codec_data, vgmstream->loop_current_sample); + if (vgmstream->coding_type == coding_TAC) { + seek_tac(vgmstream->codec_data, vgmstream->loop_current_sample); } if (vgmstream->coding_type == coding_UBI_ADPCM) { @@ -227,8 +231,8 @@ void reset_codec(VGMSTREAM* vgmstream) { reset_relic(vgmstream->codec_data); } - if (vgmstream->coding_type == coding_CRI_HCA) { - reset_hca(vgmstream->codec_data); + if (vgmstream->coding_type == coding_TAC) { + reset_tac(vgmstream->codec_data); } if (vgmstream->coding_type == coding_UBI_ADPCM) { @@ -509,6 +513,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) { return 0; /* 512 */ case coding_CRI_HCA: return 0; /* 1024 - delay/padding (which can be bigger than 1024) */ + case coding_TAC: + return 0; /* 1024 - delay/padding */ #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) case coding_MP4_AAC: return ((mp4_aac_codec_data*)vgmstream->codec_data)->samples_per_frame; @@ -705,27 +711,16 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) { return vgmstream->interleave_block_size; case coding_PTADPCM: return vgmstream->interleave_block_size; - case coding_UBI_ADPCM: - return 0; /* varies per mode? */ - case coding_IMUSE: - return 0; /* varies per frame */ - case coding_COMPRESSWAVE: - return 0; /* huffman bits */ - case coding_EA_MT: - return 0; /* variable (frames of bit counts or PCM frames) */ -#ifdef VGM_USE_ATRAC9 - case coding_ATRAC9: - return 0; /* varies with config data, usually 0x100-200 */ -#endif -#ifdef VGM_USE_CELT - case coding_CELT_FSB: - return 0; /* varies, usually 0x80-100 */ -#endif -#ifdef VGM_USE_SPEEX - case coding_SPEEX: - return 0; /* varies, usually 0x40-60 */ -#endif - default: /* Vorbis, MPEG, ACM, etc */ + /* UBI_ADPCM: varies per mode? */ + /* IMUSE: VBR */ + /* EA_MT: VBR, frames of bit counts or PCM frames */ + /* COMPRESSWAVE: VBR/huffman bits */ + /* ATRAC9: CBR around 0x100-200 */ + /* CELT FSB: varies, usually 0x80-100 */ + /* SPEEX: varies, usually 0x40-60 */ + /* TAC: VBR around ~0x200-300 */ + /* Vorbis, MPEG, ACM, etc: varies */ + default: /* (VBR or managed by decoder) */ return 0; } } @@ -1038,6 +1033,9 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ case coding_CRI_HCA: decode_hca(vgmstream->codec_data, buffer, samples_to_do); break; + case coding_TAC: + decode_tac(vgmstream, buffer, samples_to_do); + break; #ifdef VGM_USE_FFMPEG case coding_FFmpeg: decode_ffmpeg(vgmstream, buffer, samples_to_do, vgmstream->channels); diff --git a/src/formats.c b/src/formats.c index a9e4a88e..7eb9dc02 100644 --- a/src/formats.c +++ b/src/formats.c @@ -803,7 +803,8 @@ static const coding_info coding_info_list[] = { {coding_CIRCUS_VQ, "Circus VQ"}, {coding_RELIC, "Relic Codec"}, {coding_CRI_HCA, "CRI HCA"}, - + {coding_TAC, "tri-Ace Codec"}, + #ifdef VGM_USE_VORBIS {coding_OGG_VORBIS, "Ogg Vorbis"}, {coding_VORBIS_custom, "Custom Vorbis"}, @@ -1338,6 +1339,7 @@ static const meta_info meta_info_list[] = { {meta_KTAC, "Koei Tecmo KTAC header"}, {meta_MJB_MJH, "Sony MultiStream MJH+MJB header"}, {meta_BSNF, "id Software BSNF header"}, + {meta_TAC, "tri-Ace Codec header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index cc6a194d..89eea00c 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -1741,6 +1741,10 @@ + + - - + + + + + + + + @@ -2326,6 +2342,14 @@ RelativePath=".\coding\speex_decoder.c" > + + + + diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 58abb602..0c6a95e5 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -163,6 +163,9 @@ + + + @@ -535,6 +538,7 @@ + @@ -639,6 +643,8 @@ + + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 7d53917c..4b94d6d1 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -251,6 +251,15 @@ coding\Header Files + + coding\Header Files + + + coding\Header Files + + + coding\Header Files + layout\Header Files @@ -1102,6 +1111,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1390,6 +1402,12 @@ coding\Source Files + + coding\Source Files + + + coding\Source Files + coding\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 77f259f7..f84f56a7 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -944,4 +944,6 @@ VGMSTREAM* init_vgmstream_ktac(STREAMFILE* sf); VGMSTREAM* init_vgmstream_mjb_mjh(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_tac(STREAMFILE* sf); + #endif /*_META_H*/ diff --git a/src/meta/tac.c b/src/meta/tac.c new file mode 100644 index 00000000..16515a15 --- /dev/null +++ b/src/meta/tac.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* tri-Ace codec file [Star Ocean 3 (PS2), Valkyrie Profile 2 (PS2), Radiata Stories (PS2)] */ +VGMSTREAM* init_vgmstream_tac(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + int loop_flag, channel_count; + uint16_t loop_frame, frame_count, loop_discard, frame_discard; + uint32_t info_offset, loop_offset, stream_size, file_size; + off_t start_offset; + + + /* checks */ + /* (extensionless): bigfiles have no known names (libs calls mention "St*" and "Sac*" though) + * .aac: fake for convenience given it's a tri-Ace AAC's grandpa (but don't use unless you must) + * .pk3/.20: extremely ugly fake extensions randomly given by an old extractor, *DON'T* */ + if (!check_extensions(sf, ",aac,laac")) + goto fail; + /* file is validated on decoder init, early catch of simple errors (see decoder for full header) */ + info_offset = read_u32le(0x00,sf); + if (info_offset > 0x4E000 || info_offset < 0x20) /* offset points to value inside first "block" */ + goto fail; + loop_frame = read_u16le(0x08,sf); + loop_discard = read_u16le(0x0a,sf); + frame_count = read_u16le(0x0c,sf); + frame_discard = read_u16le(0x0e,sf); + loop_offset = read_u32le(0x10,sf); + stream_size = read_u32le(0x14,sf); + if (stream_size % 0x4E000 != 0) /* multiple of blocks */ + goto fail; + + /* actual file can truncate last block */ + file_size = get_streamfile_size(sf); + if (file_size > stream_size || file_size < stream_size - 0x4E000) + goto fail; + + channel_count = 2; /* always stereo */ + loop_flag = (loop_offset != stream_size); + start_offset = 0; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + 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->loop_end_sample = vgmstream->num_samples; + + { + vgmstream->codec_data = init_tac(sf); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_TAC; + vgmstream->layout_type = layout_none; + } + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index 0e52a00f..e74bab1d 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -522,6 +522,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_mjb_mjh, init_vgmstream_mzrt_v1, init_vgmstream_bsnf, + init_vgmstream_tac, /* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */ init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */ diff --git a/src/vgmstream.h b/src/vgmstream.h index 86975a01..ff918a08 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -193,6 +193,7 @@ typedef enum { coding_CIRCUS_VQ, /* Circus VQ */ coding_RELIC, /* Relic Codec (DCT-based) */ coding_CRI_HCA, /* CRI High Compression Audio (MDCT-based) */ + coding_TAC, /* tri-Ace Codec (MDCT-based) */ #ifdef VGM_USE_VORBIS coding_OGG_VORBIS, /* Xiph Vorbis with Ogg layer (MDCT-based) */ @@ -754,6 +755,7 @@ typedef enum { meta_KTAC, meta_MJB_MJH, meta_BSNF, + meta_TAC, } meta_t; /* standard WAVEFORMATEXTENSIBLE speaker positions */ @@ -1048,7 +1050,7 @@ typedef struct { uint64_t size; // max size within the streamfile uint64_t logical_offset; // computed offset FFmpeg sees (including fake header) uint64_t logical_size; // computed size FFmpeg sees (including fake header) - + uint64_t header_size; // fake header (parseable by FFmpeg) prepended on reads uint8_t* header_block; // fake header data (ie. RIFF) @@ -1061,7 +1063,7 @@ typedef struct { int64_t totalSamples; // estimated count (may not be accurate for some demuxers) int64_t skipSamples; // number of start samples that will be skipped (encoder delay), for looping adjustments int streamCount; // number of FFmpeg audio streams - + /*** internal state ***/ // config int channel_remap_set; @@ -1073,7 +1075,7 @@ typedef struct { // FFmpeg context used for metadata AVCodec *codec; - + // FFmpeg decoder state unsigned char *buffer; AVIOContext *ioCtx;