aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2015-12-23 20:53:29 +0100
committerSylvain Munaut <tnt@246tNt.com>2015-12-23 20:53:29 +0100
commit39141a86bbaf43ccc7543e0bdf46107d59f539c0 (patch)
treef45ac20895394e558fedd9d19ce52db13fd722df
parent30e476ab5f4302f12c6f1af08d3b7c35a3cd6416 (diff)
codec: Import current codec code
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
-rw-r--r--codec/Makefile12
-rw-r--r--codec/ambe.c176
-rw-r--r--codec/ambe.h44
-rw-r--r--codec/ecc.c270
-rw-r--r--codec/ecc_tables.h571
-rw-r--r--codec/frame.c483
-rw-r--r--codec/ir77_ambe_decode.c199
-rw-r--r--codec/math.c177
-rw-r--r--codec/private.h178
-rw-r--r--codec/synth.c381
-rw-r--r--codec/tables.c1590
-rw-r--r--codec/tone.c175
12 files changed, 4256 insertions, 0 deletions
diff --git a/codec/Makefile b/codec/Makefile
new file mode 100644
index 0000000..4393d97
--- /dev/null
+++ b/codec/Makefile
@@ -0,0 +1,12 @@
+CC=gcc
+CFLAGS=`pkg-config libosmocore --cflags` -Wall -O2 -march=native
+LDLIBS=`pkg-config libosmocore --libs` -lm
+
+OBJS=ir77_ambe_decode
+
+all: $(OBJS)
+
+ir77_ambe_decode: ir77_ambe_decode.o ambe.o ecc.o frame.o math.o synth.o tables.o tone.o
+
+clean:
+ rm -f *.o $(OBJS)
diff --git a/codec/ambe.c b/codec/ambe.c
new file mode 100644
index 0000000..705ffab
--- /dev/null
+++ b/codec/ambe.c
@@ -0,0 +1,176 @@
+/* Iridium AMBE vocoder - AMBE API */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \addtogroup codec
+ * @{
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ambe.h"
+#include "private.h"
+
+
+/*! \brief Allocates and inits a decoder object
+ * \returns A newly allocated and initialized decoder
+ */
+struct ir77_ambe_decoder *
+ir77_ambe_decode_alloc(void)
+{
+ struct ir77_ambe_decoder *dec;
+
+ dec = calloc(1, sizeof(struct ir77_ambe_decoder));
+ if (!dec)
+ return NULL;
+
+ ir77_ambe_synth_init(&dec->synth);
+
+ dec->sf_prev.w0 = 0.09378;
+ dec->sf_prev.f0 = dec->sf_prev.w0 / (2 * M_PIf);
+ dec->sf_prev.L = 30;
+
+ return dec;
+}
+
+/*! \brief Release a decoder object created by \ref ir77_ambe_decode_alloc
+ * \param[in] dec Decoder object
+ */
+void
+ir77_ambe_decode_release(struct ir77_ambe_decoder *dec)
+{
+ free(dec);
+}
+
+
+/*! \brief Decodes an AMBE frame to audio
+ * \param[in] dec Decoder object
+ * \param[out] audio Output audio buffers
+ * \param[in] N number of audio samples to produce (== 360 for now)
+ * \param[in] frame Frame data (as de-prioritized 103 ubits), Must be speech !
+ * \returns 0 for success. Negative error code otherwise.
+ */
+static int
+ir77_ambe_decode_speech(struct ir77_ambe_decoder *dec,
+ int16_t *audio, int N, const ubit_t *frame_lin)
+{
+ struct ir77_ambe_raw_params rp;
+ struct ir77_ambe_subframe sf[2];
+
+ /* Read out params */
+ ir77_ambe_frame_unpack_raw(&rp, frame_lin);
+
+ /* Decode params */
+ ir77_ambe_frame_decode_params(sf, &dec->sf_prev, &rp);
+
+ /* Expand them */
+ ir77_ambe_subframe_expand(&sf[0]);
+ ir77_ambe_subframe_expand(&sf[1]);
+
+ /* Perform the actual audio synthesis */
+ ir77_ambe_synth_enhance(&dec->synth, &sf[0]);
+ ir77_ambe_synth_enhance(&dec->synth, &sf[1]);
+
+ ir77_ambe_synth_audio(&dec->synth, audio , &sf[0], &dec->sf_prev);
+ ir77_ambe_synth_audio(&dec->synth, audio + 180, &sf[1], &sf[0]);
+
+ /* Save previous subframe */
+ memcpy(&dec->sf_prev, &sf[1], sizeof(struct ir77_ambe_subframe));
+
+ return 0;
+}
+
+/*! \brief Decodes an AMBE superframe to audio
+ * \param[in] dec Decoder object
+ * \param[out] audio Output audio buffers
+ * \param[in] N number of audio samples to produce (== 720 for now)
+ * \param[in] superframe SuperFrame data (39 bytes = 312 bits)
+ * \returns 0 for success. Negative error code otherwise.
+ */
+int
+ir77_ambe_decode_superframe(struct ir77_ambe_decoder *dec,
+ int16_t *audio, int N,
+ const uint8_t *superframe)
+{
+ ubit_t superframe_bits[312];
+ ubit_t frame_bits[156];
+ int i;
+
+ /* Unpack to ubits */
+ osmo_pbit2ubit_ext(superframe_bits, 0, superframe, 0, 312, 1);
+
+ /* Process each frame */
+ for (i=0; i<2; i++)
+ {
+ ubit_t frame[103], frame_lin[103];
+ enum ir77_ambe_frame_type type;
+ int err[6];
+ uint32_t seed;
+
+ /* De-interleave */
+ ir77_ambe_interleave(frame_bits, superframe_bits+i, 2, 156, 1);
+
+ /* De-FEC */
+ err[0] = ir77_ambe_golay24_decode(&frame[ 0], &frame_bits[ 0], &seed);
+
+ ir77_ambe_scramble(&frame_bits[24], &frame_bits[24], 156-24-33, seed);
+
+ err[1] = ir77_ambe_golay23_decode (&frame[12], &frame_bits[ 24], NULL);
+ err[2] = ir77_ambe_golay23_decode (&frame[24], &frame_bits[ 47], NULL);
+ err[3] = ir77_ambe_golay23_decode (&frame[36], &frame_bits[ 70], NULL);
+ err[4] = ir77_ambe_hamming1511_decode(&frame[48], &frame_bits[ 93]);
+ err[5] = ir77_ambe_hamming1511_decode(&frame[59], &frame_bits[108]);
+
+ memcpy(&frame[70], &frame_bits[123], 33);
+
+ /* Skip bad frames */
+ if ((err[1] + err[2] + err[3]) > 6) {
+ memset(&audio[360*i], 0x0, sizeof(int16_t) * 360);
+ continue;
+ }
+
+ /* De-prioritize */
+ ir77_ambe_prioritize(frame_lin, frame, 1);
+
+ /* Classify frame */
+ type = ir77_ambe_frame_classify(frame_lin);
+
+ /* Decode appropriately */
+ switch (type)
+ {
+ case AMBE_SPEECH:
+ ir77_ambe_decode_speech(dec, &audio[360*i], 360, frame_lin);
+ break;
+
+ case AMBE_TONE:
+ ir77_ambe_decode_tone(dec, &audio[360*i], 360, frame_lin);
+ break;
+
+ case AMBE_SILENCE:
+ case AMBE_INVALID:
+ memset(&audio[360*i], 0x0, sizeof(int16_t) * 360);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*! @} */
diff --git a/codec/ambe.h b/codec/ambe.h
new file mode 100644
index 0000000..4784cf5
--- /dev/null
+++ b/codec/ambe.h
@@ -0,0 +1,44 @@
+/* Iridium AMBE vocoder - AMBE API */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OSMO_IR77_AMBE_AMBE_H__
+#define __OSMO_IR77_AMBE_AMBE_H__
+
+/*! \defgroup codec AMBE vocoder
+ * \ingroup codec
+ * @{
+ */
+
+/*! \file codec/ambe.h
+ * \brief Iridium AMBE vocoder header
+ */
+
+#include <stdint.h>
+
+struct ir77_ambe_decoder;
+
+struct ir77_ambe_decoder *ir77_ambe_decode_alloc(void);
+void ir77_ambe_decode_release(struct ir77_ambe_decoder *dec);
+int ir77_ambe_decode_superframe(struct ir77_ambe_decoder *dec,
+ int16_t *audio, int N,
+ const uint8_t *superframe);
+
+/*! @} */
+
+#endif /* __OSMO_IR77_AMBE_AMBE_H__ */
diff --git a/codec/ecc.c b/codec/ecc.c
new file mode 100644
index 0000000..d282a8a
--- /dev/null
+++ b/codec/ecc.c
@@ -0,0 +1,270 @@
+/* Iridium AMBE vocoder - ECC routines */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \addtogroup codec_private
+ * @{
+ */
+
+/*! \file codec/ecc.c
+ * \brief Iridium AMBE vocoder ECC routines
+ */
+
+#include <osmocom/core/bits.h>
+
+#include "ecc_tables.h"
+
+
+/* Local helpers ---------------------------------------------------------- */
+
+/*! \brief Writes a given word as ubits (MSBs first)
+ * \param[out] bits Pointer where to write the ubits
+ * \param[in] word Word to write
+ * \param[in] N Number of bits
+ */
+static void
+_ubit_write(ubit_t *bits, uint32_t word, int N)
+{
+ int i, s;
+
+ s = N - 1;
+ for (i=0; i<N; i++)
+ bits[i] = (word >> s--) & 1;
+}
+
+/*! \brief Reads a word from ubits (MSBs first)
+ * \param[in] bits Pointer where to read the ubits from
+ * \param[in] N Number of bits
+ * \returns The reconstructed value (unsigned)
+ */
+static uint32_t
+_ubit_read(ubit_t *bits, int N)
+{
+ uint32_t rv = 0;
+ int i;
+
+ for (i=0; i<N; i++)
+ rv = (rv << 1) | bits[i];
+
+ return rv;
+}
+
+/*! \brief Computed the hamming weight of a given word (number of 1 bits)
+ * \param[in] v Value
+ * \returns Hamming weight of 'v'
+ */
+static int
+_weight(uint32_t v)
+{
+ const int hw[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+ int i, t;
+
+ t = 0;
+ for (i=0; i<32; i+=4)
+ t += hw[(v >> i) & 0xf];
+
+ return t;
+}
+
+
+/* Golay 23/12 & 24/12 ---------------------------------------------------- */
+
+/*! \brief Computes Golay Syndrome of given word
+ * \param[in] data Data word
+ * \param[in] tbl Mask table to use
+ * \returns Syndrome of 'data' using 'tbl'
+ */
+static uint32_t
+_golay_syndrome(uint32_t data, const uint32_t *tbl)
+{
+ uint32_t syndrome, mask;
+ int i;
+
+ syndrome = 0;
+ mask = 1<<11;
+
+ for (i=0; i<12; i++) {
+ if (data & mask)
+ syndrome ^= tbl[i];
+ mask >>= 1;
+ }
+
+ return syndrome;
+}
+
+/*! \brief Encode one word using Golay 23/12
+ * \param[out] out 23 ubits output buffer
+ * \param[in] in 12 ubits input buffer
+ */
+void
+ir77_ambe_golay23_encode(ubit_t *out, ubit_t *in)
+{
+ uint32_t cw;
+
+ cw = _ubit_read(in, 12);
+ cw = (cw << 11) | _golay_syndrome(cw, _golay23_syn_tbl);
+
+ _ubit_write(out, cw, 23);
+}
+
+/*! \brief Decode one word using Golay 23/12 code
+ * \param[out] out 12 ubits output buffer
+ * \param[in] in 23 ubits input buffer
+ * \param[out] data_p Optional return pointer for the decoded word
+ * \returns Number of bits errors
+ */
+int
+ir77_ambe_golay23_decode(ubit_t *out, ubit_t *in, uint32_t *data_p)
+{
+ uint32_t cw, data, ecc_rx, ecc_ex, syn;
+ int w = 0;
+
+ cw = _ubit_read(in, 23);
+
+ data = cw >> 11;
+ ecc_rx = cw & 0x7ff;
+ ecc_ex = _golay_syndrome(data, _golay23_syn_tbl);
+
+ syn = ecc_ex ^ ecc_rx;
+
+ if (syn) {
+ uint32_t errors = _golay23_dec_tbl[syn];
+ data ^= errors >> 11;
+ w = _weight(errors);
+ }
+
+ _ubit_write(out, data, 12);
+
+ if (data_p)
+ *data_p = data;
+
+ return w;
+}
+
+/*! \brief Encode one word using Golay 24/12
+ * \param[out] out 24 ubits output buffer
+ * \param[in] in 12 ubits input buffer
+ */
+void
+ir77_ambe_golay24_encode(ubit_t *out, ubit_t *in)
+{
+ uint32_t cw;
+
+ cw = _ubit_read(in, 12);
+ cw = (cw << 12) | _golay_syndrome(cw, _golay24_syn_tbl);
+
+ _ubit_write(out, cw, 24);
+}
+
+/*! \brief Decode one word using Golay 24/12 code
+ * \param[out] out 12 ubits output buffer
+ * \param[in] in 24 ubits input buffer
+ * \param[out] data_p Optional return pointer for the decoded word
+ * \returns Number of bits errors
+ */
+int
+ir77_ambe_golay24_decode(ubit_t *out, ubit_t *in, uint32_t *data_p)
+{
+ uint32_t cw, data, ecc_rx, ecc_ex, syn;
+ int w = 0;
+
+ cw = _ubit_read(in, 24);
+
+ data = cw >> 12;
+ ecc_rx = cw & 0xfff;
+ ecc_ex = _golay_syndrome(data, _golay24_syn_tbl);
+
+ syn = ecc_ex ^ ecc_rx;
+
+ if (syn) {
+ uint32_t errors = _golay23_dec_tbl[syn >> 1];
+ data ^= errors >> 11;
+ w = _weight(errors);
+
+ //w += (syn & 1) ^ (w & 1); /* FIXME */
+ }
+
+ _ubit_write(out, data, 12);
+
+ if (data_p)
+ *data_p = data;
+
+ return w;
+}
+
+
+/* Hamming 15/11 codes ---------------------------------------------------- */
+
+/*! \brief Computes Hamming 15/11 syndrome of a given value
+ * \param[in] v Value
+ * \returns Hamming 15/11 syndrome of 'v'
+ */
+static uint32_t
+_hamming1511_syndrome(uint32_t v)
+{
+ uint32_t s = 0;
+ int i;
+
+ for (i=0; i<4; i++) {
+ s <<= 1;
+ s |= _weight(v & _ham1511_mask_tbl[i]) & 1;
+ }
+
+ return s;
+}
+
+/*! \brief Encode one word using Hamming 15/11
+ * \param[out] out 15 ubits output buffer
+ * \param[in] in 11 ubits input buffer
+ */
+void
+ir77_ambe_hamming1511_encode(ubit_t *out, ubit_t *in)
+{
+ uint32_t cw;
+
+ cw = _ubit_read(in, 11) << 4;
+ cw |= _hamming1511_syndrome(cw);
+
+ _ubit_write(out, cw, 15);
+}
+
+/*! \brief Decode one word using Hamming 15/11
+ * \param[out] out 11 ubits output buffer
+ * \param[in] in 15 ubits input buffer
+ * \returns 0 if no errors, 1 if errors
+ */
+int
+ir77_ambe_hamming1511_decode(ubit_t *out, ubit_t *in)
+{
+ uint32_t cw = _ubit_read(in, 15);
+ uint32_t syndrome;
+ int w = 0;
+
+ syndrome = _hamming1511_syndrome(cw);
+
+ if (syndrome) {
+ cw ^= 1 << _ham1511_fix_tbl[syndrome];
+ w = 1;
+ }
+
+ _ubit_write(out, cw >> 4, 11);
+
+ return w;
+}
+
+/*! @} */
diff --git a/codec/ecc_tables.h b/codec/ecc_tables.h
new file mode 100644
index 0000000..724a571
--- /dev/null
+++ b/codec/ecc_tables.h
@@ -0,0 +1,571 @@
+/* Iridium AMBE vocoder - ECC tables */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OSMO_IR77_AMBE_ECC_TABLES_H__
+#define __OSMO_IR77_AMBE_ECC_TABLES_H__
+
+/*! \addtogroup codec_private
+ * @{
+ */
+
+/*! \file codec/ecc_tables.h
+ * \brief Iridium AMBE vocoder ECC tables
+ */
+
+/*! \brief Golay 23,12 - syndrome table */
+static const uint32_t _golay23_syn_tbl[] = {
+ 0x63a, 0x31d, 0x7b4, 0x3da, 0x1ed, 0x6cc,
+ 0x366, 0x1b3, 0x6e3, 0x54b, 0x49f, 0x475,
+};
+
+/*! \brief Golay 24,12 - syndrome table */
+static const uint32_t _golay24_syn_tbl[] = {
+ 0xc75, 0x63b, 0xf68, 0x7b4, 0x3da, 0xd99,
+ 0x6cd, 0x367, 0xdc6, 0xa97, 0x93e, 0x8eb,
+};
+
+/*! \brief Golay 23,12 - Decoding table (idx=syndrome, value=error_mask) */
+static const uint32_t _golay23_dec_tbl[] = {
+ 0x000000, 0x000001, 0x000002, 0x000003,
+ 0x000004, 0x000005, 0x000006, 0x000007,
+ 0x000008, 0x000009, 0x00000a, 0x00000b,
+ 0x00000c, 0x00000d, 0x00000e, 0x024020,
+ 0x000010, 0x000011, 0x000012, 0x000013,
+ 0x000014, 0x000015, 0x000016, 0x412000,
+ 0x000018, 0x000019, 0x00001a, 0x180800,
+ 0x00001c, 0x200300, 0x048040, 0x001480,
+ 0x000020, 0x000021, 0x000022, 0x000023,
+ 0x000024, 0x000025, 0x000026, 0x024008,
+ 0x000028, 0x000029, 0x00002a, 0x024004,
+ 0x00002c, 0x024002, 0x024001, 0x024000,
+ 0x000030, 0x000031, 0x000032, 0x008180,
+ 0x000034, 0x000c40, 0x301000, 0x0c0200,
+ 0x000038, 0x043000, 0x400600, 0x210040,
+ 0x090080, 0x508000, 0x002900, 0x024010,
+ 0x000040, 0x000041, 0x000042, 0x000043,
+ 0x000044, 0x000045, 0x000046, 0x280080,
+ 0x000048, 0x000049, 0x00004a, 0x002500,
+ 0x00004c, 0x111000, 0x048010, 0x400a00,
+ 0x000050, 0x000051, 0x000052, 0x021200,
+ 0x000054, 0x000c20, 0x048008, 0x104100,
+ 0x000058, 0x404080, 0x048004, 0x210020,
+ 0x048002, 0x0a2000, 0x048000, 0x048001,
+ 0x000060, 0x000061, 0x000062, 0x540000,
+ 0x000064, 0x000c10, 0x010300, 0x00b000,
+ 0x000068, 0x088200, 0x001880, 0x210010,
+ 0x602000, 0x040180, 0x180400, 0x024040,
+ 0x000070, 0x000c04, 0x086000, 0x210008,
+ 0x000c01, 0x000c00, 0x420080, 0x000c02,
+ 0x120100, 0x210002, 0x210001, 0x210000,
+ 0x005200, 0x000c08, 0x048020, 0x210004,
+ 0x000080, 0x000081, 0x000082, 0x000083,
+ 0x000084, 0x000085, 0x000086, 0x280040,
+ 0x000088, 0x000089, 0x00008a, 0x050200,
+ 0x00008c, 0x00a800, 0x500100, 0x001410,
+ 0x000090, 0x000091, 0x000092, 0x008120,
+ 0x000094, 0x160000, 0x004a00, 0x001408,
+ 0x000098, 0x404040, 0x222000, 0x001404,
+ 0x090020, 0x001402, 0x001401, 0x001400,
+ 0x0000a0, 0x0000a1, 0x0000a2, 0x008110,
+ 0x0000a4, 0x401200, 0x042400, 0x110800,
+ 0x0000a8, 0x300400, 0x001840, 0x482000,
+ 0x090010, 0x040140, 0x208200, 0x024080,
+ 0x0000b0, 0x008102, 0x008101, 0x008100,
+ 0x090008, 0x206000, 0x420040, 0x008104,
+ 0x090004, 0x020a00, 0x144000, 0x008108,
+ 0x090000, 0x090001, 0x090002, 0x001420,
+ 0x0000c0, 0x0000c1, 0x0000c2, 0x280004,
+ 0x0000c4, 0x280002, 0x280001, 0x280000,
+ 0x0000c8, 0x404010, 0x001820, 0x128000,
+ 0x020600, 0x040120, 0x016000, 0x280008,
+ 0x0000d0, 0x404008, 0x110400, 0x042800,
+ 0x003100, 0x018200, 0x420020, 0x280010,
+ 0x404001, 0x404000, 0x080300, 0x404002,
+ 0x300800, 0x404004, 0x048080, 0x001440,
+ 0x0000e0, 0x032000, 0x001808, 0x004600,
+ 0x10c000, 0x040108, 0x420010, 0x280020,
+ 0x001802, 0x040104, 0x001800, 0x001801,
+ 0x040101, 0x040100, 0x001804, 0x040102,
+ 0x240200, 0x181000, 0x420004, 0x008140,
+ 0x420002, 0x000c80, 0x420000, 0x420001,
+ 0x00a400, 0x404020, 0x001810, 0x210080,
+ 0x090040, 0x040110, 0x420008, 0x102200,
+ 0x000100, 0x000101, 0x000102, 0x000103,
+ 0x000104, 0x000105, 0x000106, 0x041800,
+ 0x000108, 0x000109, 0x00010a, 0x002440,
+ 0x00010c, 0x200210, 0x500080, 0x098000,
+ 0x000110, 0x000111, 0x000112, 0x0080a0,
+ 0x000114, 0x200208, 0x0a0400, 0x104040,
+ 0x000118, 0x200204, 0x015000, 0x460000,
+ 0x200201, 0x200200, 0x002820, 0x200202,
+ 0x000120, 0x000121, 0x000122, 0x008090,
+ 0x000124, 0x182000, 0x010240, 0x600400,
+ 0x000128, 0x410800, 0x2c0000, 0x101200,
+ 0x009400, 0x0400c0, 0x002810, 0x024100,
+ 0x000130, 0x008082, 0x008081, 0x008080,
+ 0x444000, 0x031000, 0x002808, 0x008084,
+ 0x120040, 0x084400, 0x002804, 0x008088,
+ 0x002802, 0x200220, 0x002800, 0x002801,
+ 0x000140, 0x000141, 0x000142, 0x002408,
+ 0x000144, 0x428000, 0x010220, 0x104010,
+ 0x000148, 0x002402, 0x002401, 0x002400,
+ 0x084800, 0x0400a0, 0x221000, 0x002404,
+ 0x000150, 0x0d0000, 0x600800, 0x104004,
+ 0x003080, 0x104002, 0x104001, 0x104000,
+ 0x120020, 0x009800, 0x080280, 0x002410,
+ 0x410400, 0x200240, 0x048100, 0x104008,
+ 0x000160, 0x205000, 0x010204, 0x0a0800,
+ 0x010202, 0x040088, 0x010200, 0x010201,
+ 0x120010, 0x040084, 0x40c000, 0x002420,
+ 0x040081, 0x040080, 0x010208, 0x040082,
+ 0x120008, 0x402200, 0x041400, 0x0080c0,
+ 0x288000, 0x000d00, 0x010210, 0x104020,
+ 0x120000, 0x120001, 0x120002, 0x210100,
+ 0x120004, 0x040090, 0x002840, 0x481000,
+ 0x000180, 0x000181, 0x000182, 0x008030,
+ 0x000184, 0x014400, 0x500008, 0x022200,
+ 0x000188, 0x0a1000, 0x500004, 0x204800,
+ 0x500002, 0x040060, 0x500000, 0x500001,
+ 0x000190, 0x008022, 0x008021, 0x008020,
+ 0x003040, 0x480800, 0x250000, 0x008024,
+ 0x040c00, 0x112000, 0x080240, 0x008028,
+ 0x02c000, 0x200280, 0x500010, 0x001500,
+ 0x0001a0, 0x008012, 0x008011, 0x008010,
+ 0x220800, 0x040048, 0x085000, 0x008014,
+ 0x006200, 0x040044, 0x030400, 0x008018,
+ 0x040041, 0x040040, 0x500020, 0x040042,
+ 0x008003, 0x008002, 0x008001, 0x008000,
+ 0x100600, 0x008006, 0x008005, 0x008004,
+ 0x601000, 0x00800a, 0x008009, 0x008008,
+ 0x090100, 0x040050, 0x002880, 0x00800c,
+ 0x0001c0, 0x100a00, 0x064000, 0x411000,
+ 0x003010, 0x040028, 0x008c00, 0x280100,
+ 0x218000, 0x040024, 0x080210, 0x002480,
+ 0x040021, 0x040020, 0x500040, 0x040022,
+ 0x003004, 0x220400, 0x080208, 0x008060,
+ 0x003000, 0x003001, 0x003002, 0x104080,
+ 0x080202, 0x404100, 0x080200, 0x080201,
+ 0x003008, 0x040030, 0x080204, 0x030800,
+ 0x480400, 0x04000c, 0x302000, 0x008050,
+ 0x040009, 0x040008, 0x010280, 0x04000a,
+ 0x040005, 0x040004, 0x001900, 0x040006,
+ 0x040001, 0x040000, 0x040003, 0x040002,
+ 0x014800, 0x008042, 0x008041, 0x008040,
+ 0x003020, 0x040018, 0x420100, 0x008044,
+ 0x120080, 0x040014, 0x080220, 0x008048,
+ 0x040011, 0x040010, 0x204400, 0x040012,
+ 0x000200, 0x000201, 0x000202, 0x000203,
+ 0x000204, 0x000205, 0x000206, 0x108400,
+ 0x000208, 0x000209, 0x00020a, 0x050080,
+ 0x00020c, 0x200110, 0x083000, 0x400840,
+ 0x000210, 0x000211, 0x000212, 0x021040,
+ 0x000214, 0x200108, 0x004880, 0x0c0020,
+ 0x000218, 0x200104, 0x400420, 0x00e000,
+ 0x200101, 0x200100, 0x130000, 0x200102,
+ 0x000220, 0x000221, 0x000222, 0x202800,
+ 0x000224, 0x401080, 0x010140, 0x0c0010,
+ 0x000228, 0x088040, 0x400410, 0x101100,
+ 0x140800, 0x012400, 0x208080, 0x024200,
+ 0x000230, 0x114000, 0x400408, 0x0c0004,
+ 0x02a000, 0x0c0002, 0x0c0001, 0x0c0000,
+ 0x400402, 0x020880, 0x400400, 0x400401,
+ 0x005040, 0x200120, 0x400404, 0x0c0008,
+ 0x000240, 0x000241, 0x000242, 0x021010,
+ 0x000244, 0x046000, 0x010120, 0x400808,
+ 0x000248, 0x088020, 0x304000, 0x400804,
+ 0x020480, 0x400802, 0x400801, 0x400800,
+ 0x000250, 0x021002, 0x021001, 0x021000,
+ 0x580000, 0x018080, 0x202400, 0x021004,
+ 0x012800, 0x140400, 0x080180, 0x021008,
+ 0x005020, 0x200140, 0x048200, 0x400810,
+ 0x000260, 0x088008, 0x010104, 0x004480,
+ 0x010102, 0x320000, 0x010100, 0x010101,
+ 0x088001, 0x088000, 0x062000, 0x088002,
+ 0x005010, 0x088004, 0x010108, 0x400820,
+ 0x240080, 0x402100, 0x108800, 0x021020,
+ 0x005008, 0x000e00, 0x010110, 0x0c0040,
+ 0x005004, 0x088010, 0x400440, 0x210200,
+ 0x005000, 0x005001, 0x005002, 0x102080,
+ 0x000280, 0x000281, 0x000282, 0x050008,
+ 0x000284, 0x401020, 0x004810, 0x022100,
+ 0x000288, 0x050002, 0x050001, 0x050000,
+ 0x020440, 0x184000, 0x208020, 0x050004,
+ 0x000290, 0x082400, 0x004804, 0x700000,
+ 0x004802, 0x018040, 0x004800, 0x004801,
+ 0x109000, 0x020820, 0x080140, 0x050010,
+ 0x442000, 0x200180, 0x004808, 0x001600,
+ 0x0002a0, 0x401004, 0x1a0000, 0x004440,
+ 0x401001, 0x401000, 0x208008, 0x401002,
+ 0x006100, 0x020810, 0x208004, 0x050020,
+ 0x208002, 0x401008, 0x208000, 0x208001,
+ 0x240040, 0x020808, 0x013000, 0x008300,
+ 0x100500, 0x401010, 0x004820, 0x0c0080,
+ 0x020801, 0x020800, 0x400480, 0x020802,
+ 0x090200, 0x020804, 0x208010, 0x102040,
+ 0x0002c0, 0x100900, 0x40a000, 0x004420,
+ 0x020408, 0x018010, 0x141000, 0x280200,
+ 0x020404, 0x203000, 0x080110, 0x050040,
+ 0x020400, 0x020401, 0x020402, 0x400880,
+ 0x240020, 0x018004, 0x080108, 0x021080,
+ 0x018001, 0x018000, 0x004840, 0x018002,
+ 0x080102, 0x404200, 0x080100, 0x080101,
+ 0x020410, 0x018008, 0x080104, 0x102020,
+ 0x240010, 0x004402, 0x004401, 0x004400,
+ 0x082800, 0x401040, 0x010180, 0x004404,
+ 0x510000, 0x088080, 0x001a00, 0x004408,
+ 0x020420, 0x040300, 0x208040, 0x102010,
+ 0x240000, 0x240001, 0x240002, 0x004410,
+ 0x240004, 0x018020, 0x420200, 0x102008,
+ 0x240008, 0x020840, 0x080120, 0x102004,
+ 0x005080, 0x102002, 0x102001, 0x102000,
+ 0x000300, 0x000301, 0x000302, 0x484000,
+ 0x000304, 0x200018, 0x010060, 0x022080,
+ 0x000308, 0x200014, 0x028800, 0x101020,
+ 0x200011, 0x200010, 0x044400, 0x200012,
+ 0x000310, 0x20000c, 0x142000, 0x010c00,
+ 0x200009, 0x200008, 0x409000, 0x20000a,
+ 0x200005, 0x200004, 0x0800c0, 0x200006,
+ 0x200001, 0x200000, 0x200003, 0x200002,
+ 0x000320, 0x060400, 0x010044, 0x101008,
+ 0x010042, 0x00c800, 0x010040, 0x010041,
+ 0x006080, 0x101002, 0x101001, 0x101000,
+ 0x4a0000, 0x200030, 0x010048, 0x101004,
+ 0x081800, 0x402040, 0x224000, 0x008280,
+ 0x100480, 0x200028, 0x010050, 0x0c0100,
+ 0x058000, 0x200024, 0x400500, 0x101010,
+ 0x200021, 0x200020, 0x002a00, 0x200022,
+ 0x000340, 0x100880, 0x010024, 0x248000,
+ 0x010022, 0x081400, 0x010020, 0x010021,
+ 0x441000, 0x034000, 0x080090, 0x002600,
+ 0x10a000, 0x200050, 0x010028, 0x400900,
+ 0x00c400, 0x402020, 0x080088, 0x021100,
+ 0x060800, 0x200048, 0x010030, 0x104200,
+ 0x080082, 0x200044, 0x080080, 0x080081,
+ 0x200041, 0x200040, 0x080084, 0x200042,
+ 0x010006, 0x402010, 0x010004, 0x010005,
+ 0x010002, 0x010003, 0x010000, 0x010001,
+ 0x200c00, 0x088100, 0x01000c, 0x101040,
+ 0x01000a, 0x040280, 0x010008, 0x010009,
+ 0x402001, 0x402000, 0x010014, 0x402002,
+ 0x010012, 0x402004, 0x010010, 0x010011,
+ 0x120200, 0x402008, 0x0800a0, 0x044800,
+ 0x005100, 0x200060, 0x010018, 0x028400,
+ 0x000380, 0x100840, 0x201400, 0x022004,
+ 0x0c8000, 0x022002, 0x022001, 0x022000,
+ 0x006020, 0x408400, 0x080050, 0x050100,
+ 0x011800, 0x200090, 0x500200, 0x022008,
+ 0x430000, 0x045000, 0x080048, 0x008220,
+ 0x100420, 0x200088, 0x004900, 0x022010,
+ 0x080042, 0x200084, 0x080040, 0x080041,
+ 0x200081, 0x200080, 0x080044, 0x200082,
+ 0x006008, 0x290000, 0x440800, 0x008210,
+ 0x100410, 0x401100, 0x0100c0, 0x022020,
+ 0x006000, 0x006001, 0x006002, 0x101080,
+ 0x006004, 0x040240, 0x208100, 0x080c00,
+ 0x100404, 0x008202, 0x008201, 0x008200,
+ 0x100400, 0x100401, 0x100402, 0x008204,
+ 0x006010, 0x020900, 0x080060, 0x008208,
+ 0x100408, 0x2000a0, 0x061000, 0x414000,
+ 0x100801, 0x100800, 0x080018, 0x100802,
+ 0x604000, 0x100804, 0x0100a0, 0x022040,
+ 0x080012, 0x100808, 0x080010, 0x080011,
+ 0x020500, 0x040220, 0x080014, 0x00d000,
+ 0x08000a, 0x100810, 0x080008, 0x080009,
+ 0x003200, 0x018100, 0x08000c, 0x440400,
+ 0x080002, 0x080003, 0x080000, 0x080001,
+ 0x080006, 0x2000c0, 0x080004, 0x080005,
+ 0x029000, 0x100820, 0x010084, 0x004500,
+ 0x010082, 0x040208, 0x010080, 0x010081,
+ 0x006040, 0x040204, 0x080030, 0x620000,
+ 0x040201, 0x040200, 0x010088, 0x040202,
+ 0x240100, 0x402080, 0x080028, 0x008240,
+ 0x100440, 0x0a4000, 0x010090, 0x201800,
+ 0x080022, 0x011400, 0x080020, 0x080021,
+ 0x408800, 0x040210, 0x080024, 0x102100,
+ 0x000400, 0x000401, 0x000402, 0x000403,
+ 0x000404, 0x000405, 0x000406, 0x108200,
+ 0x000408, 0x000409, 0x00040a, 0x002140,
+ 0x00040c, 0x4c0000, 0x210800, 0x001090,
+ 0x000410, 0x000411, 0x000412, 0x244000,
+ 0x000414, 0x000860, 0x0a0100, 0x001088,
+ 0x000418, 0x038000, 0x400220, 0x001084,
+ 0x106000, 0x001082, 0x001081, 0x001080,
+ 0x000420, 0x000421, 0x000422, 0x091000,
+ 0x000424, 0x000850, 0x042080, 0x600100,
+ 0x000428, 0x300080, 0x400210, 0x048800,
+ 0x009100, 0x012200, 0x180040, 0x024400,
+ 0x000430, 0x000844, 0x400208, 0x122000,
+ 0x000841, 0x000840, 0x01c000, 0x000842,
+ 0x400202, 0x084100, 0x400200, 0x400201,
+ 0x260000, 0x000848, 0x400204, 0x0010a0,
+ 0x000440, 0x000441, 0x000442, 0x002108,
+ 0x000444, 0x000830, 0x405000, 0x070000,
+ 0x000448, 0x002102, 0x002101, 0x002100,
+ 0x020280, 0x20c000, 0x180020, 0x002104,
+ 0x000450, 0x000824, 0x110080, 0x488000,
+ 0x000821, 0x000820, 0x202200, 0x000822,
+ 0x281000, 0x140200, 0x024800, 0x002110,
+ 0x410100, 0x000828, 0x048400, 0x0010c0,
+ 0x000460, 0x000814, 0x228000, 0x004280,
+ 0x000811, 0x000810, 0x180008, 0x000812,
+ 0x054000, 0x421000, 0x180004, 0x002120,
+ 0x180002, 0x000818, 0x180000, 0x180001,
+ 0x000805, 0x000804, 0x041100, 0x000806,
+ 0x000801, 0x000800, 0x000803, 0x000802,
+ 0x00a080, 0x00080c, 0x400240, 0x210400,
+ 0x000809, 0x000808, 0x180010, 0x00080a,
+ 0x000480, 0x000481, 0x000482, 0x420800,
+ 0x000484, 0x014100, 0x042020, 0x001018,
+ 0x000488, 0x300020, 0x08c000, 0x001014,
+ 0x020240, 0x001012, 0x001011, 0x001010,
+ 0x000490, 0x082200, 0x110040, 0x00100c,
+ 0x608000, 0x00100a, 0x001009, 0x001008,
+ 0x040900, 0x001006, 0x001005, 0x001004,
+ 0x001003, 0x001002, 0x001001, 0x001000,
+ 0x0004a0, 0x300008, 0x042004, 0x004240,
+ 0x042002, 0x0a8000, 0x042000, 0x042001,
+ 0x300001, 0x300000, 0x030100, 0x300002,
+ 0x404800, 0x300004, 0x042008, 0x001030,
+ 0x025000, 0x450000, 0x280800, 0x008500,
+ 0x100300, 0x0008c0, 0x042010, 0x001028,
+ 0x00a040, 0x300010, 0x400280, 0x001024,
+ 0x090400, 0x001022, 0x001021, 0x001020,
+ 0x0004c0, 0x049000, 0x110010, 0x004220,
+ 0x020208, 0x502000, 0x008900, 0x280400,
+ 0x020204, 0x090800, 0x640000, 0x002180,
+ 0x020200, 0x020201, 0x020202, 0x001050,
+ 0x110002, 0x220100, 0x110000, 0x110001,
+ 0x0c4000, 0x0008a0, 0x110004, 0x001048,
+ 0x00a020, 0x404400, 0x110008, 0x001044,
+ 0x020210, 0x001042, 0x001041, 0x001040,
+ 0x480100, 0x004202, 0x004201, 0x004200,
+ 0x211000, 0x000890, 0x042040, 0x004204,
+ 0x00a010, 0x300040, 0x001c00, 0x004208,
+ 0x020220, 0x040500, 0x180080, 0x418000,
+ 0x00a008, 0x000884, 0x110020, 0x004210,
+ 0x000881, 0x000880, 0x420400, 0x000882,
+ 0x00a000, 0x00a001, 0x00a002, 0x0e0000,
+ 0x00a004, 0x000888, 0x204100, 0x001060,
+ 0x000500, 0x000501, 0x000502, 0x002048,
+ 0x000504, 0x014080, 0x0a0010, 0x600020,
+ 0x000508, 0x002042, 0x002041, 0x002040,
+ 0x009020, 0x120800, 0x044200, 0x002044,
+ 0x000510, 0x501000, 0x0a0004, 0x010a00,
+ 0x0a0002, 0x04a000, 0x0a0000, 0x0a0001,
+ 0x040880, 0x084020, 0x308000, 0x002050,
+ 0x410040, 0x200600, 0x0a0008, 0x001180,
+ 0x000520, 0x060200, 0x104800, 0x600004,
+ 0x009008, 0x600002, 0x600001, 0x600000,
+ 0x009004, 0x084010, 0x030080, 0x002060,
+ 0x009000, 0x009001, 0x009002, 0x600008,
+ 0x212000, 0x084008, 0x041040, 0x008480,
+ 0x100280, 0x000940, 0x0a0020, 0x600010,
+ 0x084001, 0x084000, 0x400300, 0x084002,
+ 0x009010, 0x084004, 0x002c00, 0x150000,
+ 0x000540, 0x00200a, 0x002009, 0x002008,
+ 0x340000, 0x081200, 0x008880, 0x00200c,
+ 0x002003, 0x002002, 0x002001, 0x002000,
+ 0x410010, 0x002006, 0x002005, 0x002004,
+ 0x00c200, 0x220080, 0x041020, 0x002018,
+ 0x410008, 0x000920, 0x0a0040, 0x104400,
+ 0x410004, 0x002012, 0x002011, 0x002010,
+ 0x410000, 0x410001, 0x410002, 0x002014,
+ 0x480080, 0x118000, 0x041010, 0x002028,
+ 0x026000, 0x000910, 0x010600, 0x600040,
+ 0x200a00, 0x002022, 0x002021, 0x002020,
+ 0x009040, 0x040480, 0x180100, 0x002024,
+ 0x041002, 0x000904, 0x041000, 0x041001,
+ 0x000901, 0x000900, 0x041004, 0x000902,
+ 0x120400, 0x084040, 0x041008, 0x002030,
+ 0x410020, 0x000908, 0x204080, 0x028200,
+ 0x000580, 0x014004, 0x201200, 0x1c0000,
+ 0x014001, 0x014000, 0x008840, 0x014002,
+ 0x040810, 0x408200, 0x030020, 0x0020c0,
+ 0x282000, 0x014008, 0x500400, 0x001110,
+ 0x040808, 0x220040, 0x406000, 0x008420,
+ 0x100220, 0x014010, 0x0a0080, 0x001108,
+ 0x040800, 0x040801, 0x040802, 0x001104,
+ 0x040804, 0x001102, 0x001101, 0x001100,
+ 0x480040, 0x003800, 0x030008, 0x008410,
+ 0x100210, 0x014020, 0x042100, 0x600080,
+ 0x030002, 0x300100, 0x030000, 0x030001,
+ 0x009080, 0x040440, 0x030004, 0x080a00,
+ 0x100204, 0x008402, 0x008401, 0x008400,
+ 0x100200, 0x100201, 0x100202, 0x008404,
+ 0x040820, 0x084080, 0x030010, 0x008408,
+ 0x100208, 0x422000, 0x204040, 0x001120,
+ 0x480020, 0x220010, 0x008804, 0x002088,
+ 0x008802, 0x014040, 0x008800, 0x008801,
+ 0x105000, 0x002082, 0x002081, 0x002080,
+ 0x020300, 0x040420, 0x008808, 0x002084,
+ 0x220001, 0x220000, 0x110100, 0x220002,
+ 0x003400, 0x220004, 0x008810, 0x440200,
+ 0x040840, 0x220008, 0x080600, 0x002090,
+ 0x410080, 0x188000, 0x204020, 0x001140,
+ 0x480000, 0x480001, 0x480002, 0x004300,
+ 0x480004, 0x040408, 0x008820, 0x121000,
+ 0x480008, 0x040404, 0x030040, 0x0020a0,
+ 0x040401, 0x040400, 0x204010, 0x040402,
+ 0x480010, 0x220020, 0x041080, 0x008440,
+ 0x100240, 0x000980, 0x204008, 0x092000,
+ 0x00a100, 0x011200, 0x204004, 0x500800,
+ 0x204002, 0x040410, 0x204000, 0x204001,
+ 0x000600, 0x000601, 0x000602, 0x108004,
+ 0x000604, 0x108002, 0x108001, 0x108000,
+ 0x000608, 0x005800, 0x400030, 0x2a0000,
+ 0x0200c0, 0x012020, 0x044100, 0x108008,
+ 0x000610, 0x082080, 0x400028, 0x010900,
+ 0x051000, 0x424000, 0x202040, 0x108010,
+ 0x400022, 0x140040, 0x400020, 0x400021,
+ 0x088800, 0x200500, 0x400024, 0x001280,
+ 0x000620, 0x060100, 0x400018, 0x0040c0,
+ 0x284000, 0x012008, 0x021800, 0x108020,
+ 0x400012, 0x012004, 0x400010, 0x400011,
+ 0x012001, 0x012000, 0x400014, 0x012002,
+ 0x40000a, 0x209000, 0x400008, 0x400009,
+ 0x100180, 0x000a40, 0x40000c, 0x0c0400,
+ 0x400002, 0x400003, 0x400000, 0x400001,
+ 0x400006, 0x012010, 0x400004, 0x400005,
+ 0x000640, 0x610000, 0x0c0800, 0x0040a0,
+ 0x020088, 0x081100, 0x202010, 0x108040,
+ 0x020084, 0x140010, 0x019000, 0x002300,
+ 0x020080, 0x020081, 0x020082, 0x400c00,
+ 0x00c100, 0x140008, 0x202004, 0x021400,
+ 0x202002, 0x000a20, 0x202000, 0x202001,
+ 0x140001, 0x140000, 0x400060, 0x140002,
+ 0x020090, 0x140004, 0x202008, 0x094000,
+ 0x103000, 0x004082, 0x004081, 0x004080,
+ 0x448000, 0x000a10, 0x010500, 0x004084,
+ 0x200900, 0x088400, 0x400050, 0x004088,
+ 0x0200a0, 0x012040, 0x180200, 0x241000,
+ 0x0b0000, 0x000a04, 0x400048, 0x004090,
+ 0x000a01, 0x000a00, 0x202020, 0x000a02,
+ 0x400042, 0x140020, 0x400040, 0x400041,
+ 0x005400, 0x000a08, 0x400044, 0x028100,
+ 0x000680, 0x082010, 0x201100, 0x004060,
+ 0x020048, 0x240800, 0x490000, 0x108080,
+ 0x020044, 0x408100, 0x102800, 0x050400,
+ 0x020040, 0x020041, 0x020042, 0x001210,
+ 0x082001, 0x082000, 0x068000, 0x082002,
+ 0x100120, 0x082004, 0x004c00, 0x001208,
+ 0x214000, 0x082008, 0x4000a0, 0x001204,
+ 0x020050, 0x001202, 0x001201, 0x001200,
+ 0x018800, 0x004042, 0x004041, 0x004040,
+ 0x100110, 0x401400, 0x042200, 0x004044,
+ 0x0c1000, 0x300200, 0x400090, 0x004048,
+ 0x020060, 0x012080, 0x208400, 0x080900,
+ 0x100104, 0x082020, 0x400088, 0x004050,
+ 0x100100, 0x100101, 0x100102, 0x230000,
+ 0x400082, 0x020c00, 0x400080, 0x400081,
+ 0x100108, 0x04c000, 0x400084, 0x001220,
+ 0x02000c, 0x004022, 0x004021, 0x004020,
+ 0x020008, 0x020009, 0x02000a, 0x004024,
+ 0x020004, 0x020005, 0x020006, 0x004028,
+ 0x020000, 0x020001, 0x020002, 0x020003,
+ 0x401800, 0x082040, 0x110200, 0x004030,
+ 0x020018, 0x018400, 0x202080, 0x440100,
+ 0x020014, 0x140080, 0x080500, 0x208800,
+ 0x020010, 0x020011, 0x020012, 0x001240,
+ 0x004003, 0x004002, 0x004001, 0x004000,
+ 0x020028, 0x004006, 0x004005, 0x004004,
+ 0x020024, 0x00400a, 0x004009, 0x004008,
+ 0x020020, 0x020021, 0x020022, 0x00400c,
+ 0x240400, 0x004012, 0x004011, 0x004010,
+ 0x100140, 0x000a80, 0x089000, 0x004014,
+ 0x00a200, 0x011100, 0x4000c0, 0x004018,
+ 0x020030, 0x680000, 0x050800, 0x102400,
+ 0x000700, 0x060020, 0x201080, 0x010810,
+ 0x402800, 0x081040, 0x044008, 0x108100,
+ 0x190000, 0x408080, 0x044004, 0x002240,
+ 0x044002, 0x200410, 0x044000, 0x044001,
+ 0x00c040, 0x010802, 0x010801, 0x010800,
+ 0x1000a0, 0x200408, 0x0a0200, 0x010804,
+ 0x023000, 0x200404, 0x400120, 0x010808,
+ 0x200401, 0x200400, 0x044010, 0x200402,
+ 0x060001, 0x060000, 0x08a000, 0x060002,
+ 0x100090, 0x060004, 0x010440, 0x600200,
+ 0x200840, 0x060008, 0x400110, 0x101400,
+ 0x009200, 0x012100, 0x044020, 0x080880,
+ 0x100084, 0x060010, 0x400108, 0x010820,
+ 0x100080, 0x100081, 0x100082, 0x007000,
+ 0x400102, 0x084200, 0x400100, 0x400101,
+ 0x100088, 0x200420, 0x400104, 0x028040,
+ 0x00c010, 0x081004, 0x520000, 0x002208,
+ 0x081001, 0x081000, 0x010420, 0x081002,
+ 0x200820, 0x002202, 0x002201, 0x002200,
+ 0x020180, 0x081008, 0x044040, 0x002204,
+ 0x00c000, 0x00c001, 0x00c002, 0x010840,
+ 0x00c004, 0x081010, 0x202100, 0x440080,
+ 0x00c008, 0x140100, 0x080480, 0x002210,
+ 0x410200, 0x200440, 0x101800, 0x028020,
+ 0x200808, 0x060040, 0x010404, 0x004180,
+ 0x010402, 0x081020, 0x010400, 0x010401,
+ 0x200800, 0x200801, 0x200802, 0x002220,
+ 0x200804, 0x504000, 0x010408, 0x028010,
+ 0x00c020, 0x402400, 0x041200, 0x380000,
+ 0x1000c0, 0x000b00, 0x010410, 0x028008,
+ 0x200810, 0x011080, 0x400140, 0x028004,
+ 0x0c2000, 0x028002, 0x028001, 0x028000,
+ 0x201002, 0x408008, 0x201000, 0x201001,
+ 0x100030, 0x014200, 0x201004, 0x022400,
+ 0x408001, 0x408000, 0x201008, 0x408002,
+ 0x020140, 0x408004, 0x044080, 0x080820,
+ 0x100024, 0x082100, 0x201010, 0x010880,
+ 0x100020, 0x100021, 0x100022, 0x440040,
+ 0x040a00, 0x408010, 0x080440, 0x124000,
+ 0x100028, 0x200480, 0x01a000, 0x001300,
+ 0x100014, 0x060080, 0x201020, 0x004140,
+ 0x100010, 0x100011, 0x100012, 0x080808,
+ 0x006400, 0x408020, 0x030200, 0x080804,
+ 0x100018, 0x080802, 0x080801, 0x080800,
+ 0x100004, 0x100005, 0x100006, 0x008600,
+ 0x100000, 0x100001, 0x100002, 0x100003,
+ 0x10000c, 0x011040, 0x400180, 0x242000,
+ 0x100008, 0x100009, 0x10000a, 0x080810,
+ 0x052000, 0x100c00, 0x201040, 0x004120,
+ 0x020108, 0x081080, 0x008a00, 0x440010,
+ 0x020104, 0x408040, 0x080410, 0x002280,
+ 0x020100, 0x020101, 0x020102, 0x310000,
+ 0x00c080, 0x220200, 0x080408, 0x440004,
+ 0x100060, 0x440002, 0x440001, 0x440000,
+ 0x080402, 0x011020, 0x080400, 0x080401,
+ 0x020110, 0x006800, 0x080404, 0x440008,
+ 0x480200, 0x004102, 0x004101, 0x004100,
+ 0x100050, 0x20a000, 0x010480, 0x004104,
+ 0x200880, 0x011010, 0x148000, 0x004108,
+ 0x020120, 0x040600, 0x403000, 0x080840,
+ 0x100044, 0x011008, 0x022800, 0x004110,
+ 0x100040, 0x100041, 0x100042, 0x440020,
+ 0x011001, 0x011000, 0x080420, 0x011002,
+ 0x100048, 0x011004, 0x204200, 0x028080,
+};
+
+/*! \brief Hamming 15,11 - Mask to select which bits to use for each ECC bit */
+static const uint32_t _ham1511_mask_tbl[] = {
+ 0x7f08, 0x78e4, 0x66d2, 0x55b1
+};
+
+/*! \brief Hamming 15,11 - Correction table (bit index to flip for each syndrome) */
+static const int _ham1511_fix_tbl[] = {
+ -1, 0, 1, 4, 2, 5, 6, 7, 3, 8, 9, 10, 11, 12, 13, 14
+};
+
+/*! @} */
+
+#endif /* __OSMO_IR77_AMBE_ECC_TABLES_H__ */
diff --git a/codec/frame.c b/codec/frame.c
new file mode 100644
index 0000000..7a3eb3e
--- /dev/null
+++ b/codec/frame.c
@@ -0,0 +1,483 @@
+/* Iridium AMBE vocoder - Speech parameters to/from frame */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \addtogroup codec_private
+ * @{
+ */
+
+/*! \file codec/frame.c
+ * \brief Iridium AMBE speech parameters to/from frame
+ */
+
+#include <stdint.h>
+#include <stdio.h> /* DEBUG */
+#include <stdlib.h>
+#include <string.h>
+
+#include <math.h>
+
+#include <osmocom/core/bits.h>
+
+#include "private.h"
+
+
+/*! \brief Apply/Remove interleaving
+ * Can be used to do both intra & inter using il_step
+ * \param[inout] lin_buf Linear bit buffer
+ * \param[inout] il_buf Interleaved bit buffer
+ * \param[in] il_step step to use when accesing il_buf
+ * \param[in] N Number of bits
+ * \param[in] dir Directon (0=interleave 1=de-interleave)
+ */
+void
+ir77_ambe_interleave(ubit_t *lin_buf, ubit_t *il_buf,
+ int il_step, int N, int dir)
+{
+ int div, mod;
+ int lin_idx, il_idx;
+ int i, j;
+
+ div = N / 24;
+ mod = N % 24;
+
+ il_idx = 0;
+ i = j = 0;
+
+ for (lin_idx=0; lin_idx<N; lin_idx++)
+ {
+ /* Data move */
+ if (dir)
+ lin_buf[lin_idx] = il_buf[il_idx];
+ else
+ il_buf[il_idx] = lin_buf[lin_idx];
+
+ /* Next index */
+ i++;
+
+ if (i == 24) {
+ i = 0;
+ il_idx = il_step * ++j;
+ } else
+ il_idx += il_step * (div + ((i > mod) ? 0 : 1));
+ }
+}
+
+/*! \brief Apply/Remove the scramnling
+ * \param[out] out Output unpacked bit buffer (can be == in)
+ * \param[in] in Input unpacked bit buffer
+ * \param[in] N Number of bits
+ * \param[in] seed Seed value of the PRNG
+ */
+void
+ir77_ambe_scramble(ubit_t *out, ubit_t *in, int N, uint32_t seed)
+{
+ uint32_t v;
+ int i;
+
+ v = seed << 3;
+
+ for (i=0; i<N; i++)
+ {
+ v = ((v * 173) + 13849) & 0xffff;
+ out[i] = in[i] ^ (v >> 15);
+ }
+}
+
+/*! \brief Apply or remove prioritization of bits
+ * \param[inout] lin_buf Buffer containing linearized bits
+ * \param[inout] prio_buf Buffer containing prioritized bits
+ * \param[in] dir Directon (0=prioritize 1=de-prioritize)
+ */
+void
+ir77_ambe_prioritize(ubit_t *lin_buf, ubit_t *prio_buf, int dir)
+{
+ int lin_idx, prio_idx, i, j;
+
+ prio_idx = 0;
+
+ for (i=0; ir77_ambe_prio_tbl[i].len; i++)
+ {
+ lin_idx = ir77_ambe_prio_tbl[i].pos;
+
+ for (j=0; j<ir77_ambe_prio_tbl[i].len; j++)
+ {
+ if (dir)
+ lin_buf[lin_idx] = prio_buf[prio_idx];
+ else
+ prio_buf[lin_idx] = lin_buf[prio_idx];
+
+ prio_idx++;
+ lin_idx++;
+ }
+ }
+}
+
+/*! \brief Grabs the requests bits from a frame (MSB first)
+ * \param[in] p Pointer to the first bit to read (MSB)
+ * \param[in] len Number of bits to grab (max 8)
+ * \returns The selected bits as a uint8_t
+ */
+static inline uint8_t
+_get_bits(const ubit_t **p, int len)
+{
+ uint8_t v = 0;
+
+ while (len--)
+ v = (v << 1) | *(*p)++;
+
+ return v;
+}
+
+/*! \brief Classify a frame into the different frame types
+ * \param[in] frame Frame data (as de-prioritized 103 ubits)
+ * \returns The frame type
+ */
+enum ir77_ambe_frame_type
+ir77_ambe_frame_classify(const ubit_t *frame)
+{
+ const ubit_t *p = frame;
+ uint8_t t;
+
+ t = _get_bits(&p, 4);
+
+ if (t == 0xf) {
+ /* Special */
+ t = _get_bits(&p, 2);
+
+ switch (t) {
+ case 0:
+ return AMBE_SILENCE;
+ case 1:
+ return AMBE_TONE;
+ default:
+ return AMBE_INVALID;
+ }
+ } else {
+ return AMBE_SPEECH;
+ }
+}
+
+/*! \brief Unpacks a frame into its raw encoded parameters
+ * \param[out] rp Encoded frame raw parameters to unpack into
+ * \param[in] frame Frame data (as de-prioritized 103 ubits)
+ */
+void
+ir77_ambe_frame_unpack_raw(struct ir77_ambe_raw_params *rp, const ubit_t *frame)
+{
+ const ubit_t *p = frame;
+ int i;
+
+ rp->pitch_mean = _get_bits(&p, 4);
+ rp->pitch_diff = _get_bits(&p, 6);
+ rp->gain_mean = _get_bits(&p, 5);
+ rp->gain_diff = _get_bits(&p, 5);
+ rp->v_uv[0] = _get_bits(&p, 4);
+ rp->v_uv[1] = _get_bits(&p, 4);
+
+ rp->prba_sum12 = _get_bits(&p, 8);
+ rp->prba_sum34 = _get_bits(&p, 6);
+ rp->prba_sum57 = _get_bits(&p, 7);
+ rp->prba_dif13 = _get_bits(&p, 8);
+ rp->prba_dif47 = _get_bits(&p, 6);
+
+ for (i=0; i<4; i++)
+ {
+ rp->hoc_sum[i] = _get_bits(&p, 7);
+ rp->hoc_dif[i] = _get_bits(&p, 3);
+ }
+
+#ifdef DEBUG
+ printf("--- RAW frame:\n");
+ for (i=0; i<103; i++)
+ printf("%d", frame[i]);
+ printf("\n");
+
+ printf("--- RAW params:\n");
+ printf(" .pitch_mean : %3d\n", rp->pitch_mean);
+ printf(" .pitch_diff : %3d\n", rp->pitch_diff);
+ printf(" .gain_mean : %3d\n", rp->gain_mean);
+ printf(" .gain_diff : %3d\n", rp->gain_diff);
+ printf(" .v_uv[0] : %3d\n", rp->v_uv[0]);
+ printf(" .v_uv[1] : %3d\n", rp->v_uv[1]);
+ printf(" .prba_sum12 : %3d\n", rp->prba_sum12);
+ printf(" .prba_sum34 : %3d\n", rp->prba_sum34);
+ printf(" .prba_sum57 : %3d\n", rp->prba_sum57);
+ printf(" .prba_dif13 : %3d\n", rp->prba_dif13);
+ printf(" .prba_dif47 : %3d\n", rp->prba_dif47);
+
+ for (i=0; i<4; i++)
+ {
+ printf(" .hoc_sum[%d] : %3d\n", i, rp->hoc_sum[i]);
+ printf(" .hoc_dif[%d] : %3d\n", i, rp->hoc_dif[i]);
+ }
+#endif
+}
+
+/*! \brief Computes and fill-in f0, L and Lb vaues for a given subframe
+ * (from f0log_mean and f0log_diff)
+ * \param[out] sf Subframe
+ * \param[in] f0log_mean f0 mean value for this subframe pair
+ * \param[in] f0log_diff f0 diff value for this subframe
+ */
+static void
+ir77_ambe_subframe_compute_f0_L_Lb(struct ir77_ambe_subframe *sf,
+ float f0log_mean, float f0log_diff)
+{
+ float f0;
+
+ sf->f0log = f0log_mean + f0log_diff;
+
+ f0 = powf(2.0f, sf->f0log);
+ f0 = fmaxf(fminf(f0, 0.05222f), 0.00810f);
+ sf->f0 = f0;
+
+ sf->L = (int)floorf(0.4627f / sf->f0);
+ sf->L = (sf->L < 9) ? 9 : ((sf->L > 56) ? 56 : sf->L);
+
+ sf->Lb[0] = ir77_ambe_hpg_tbl[sf->L - 9][0];
+ sf->Lb[1] = ir77_ambe_hpg_tbl[sf->L - 9][1];
+ sf->Lb[2] = ir77_ambe_hpg_tbl[sf->L - 9][2];
+ sf->Lb[3] = ir77_ambe_hpg_tbl[sf->L - 9][3];
+
+#ifdef DEBUG
+ printf("---- Decoded f0/L/Lb\n");
+ printf(" .f0log_mean : %f\n", f0log_mean);
+ printf(" .f0log_diff : %f\n", f0log_diff);
+ printf(" .f0 : %f [%04x]\n", f0, (int)(roundf(f0 * (1<<19))));
+ printf(" .L : %d\n", sf->L);
+ printf(" .Lb0 : %d\n", sf->Lb[0]);
+ printf(" .Lb1 : %d\n", sf->Lb[1]);
+ printf(" .Lb2 : %d\n", sf->Lb[2]);
+ printf(" .Lb3 : %d\n", sf->Lb[3]);
+#endif
+}
+
+/*! \brief Resample and "ac-couple" (remove mean) a magnitude array to a new L
+ * \param[in] mag_dst Destination magnitude array (L_dst elements)
+ * \param[in] L_dst Target number of magnitudes
+ * \param[in] mag_src Source magnitude array (L_src elements)
+ * \param[in] L_src Source number of magnitudes
+ */
+static void
+ir77_ambe_resample_mag(float *mag_dst, int L_dst, float *mag_src, int L_src)
+{
+ float avg, step, pos;
+ int i;
+
+ avg = 0.0f;
+ step = (float)L_src / (float)L_dst;
+ pos = step;
+
+ for (i=0; i<L_dst; i++)
+ {
+ int posi = (int)floorf(pos);
+
+ if (posi == 0) {
+ mag_dst[i] = mag_src[0];
+ } else if (posi >= L_src) {
+ mag_dst[i] = mag_src[L_src-1];
+ } else {
+ float alpha = pos - posi;
+ mag_dst[i] = mag_src[posi-1] * (1.0f - alpha)
+ + mag_src[posi] * alpha;
+ }
+
+ avg += mag_dst[i];
+ pos += step;
+ }
+
+ avg /= L_dst;
+
+ for (i=0; i<L_dst; i++)
+ mag_dst[i] -= avg;
+}
+
+/*! \brief Decodes the speech parameters for both subframes from raw params
+ * \param[out] sf Array of 2 subframes data to fill-in
+ * \param[in] sf_prev Previous subframe 1 data
+ * \param[in] rp Encoded frame raw parameters
+ */
+void
+ir77_ambe_frame_decode_params(struct ir77_ambe_subframe *sf,
+ struct ir77_ambe_subframe *sf_prev,
+ struct ir77_ambe_raw_params *rp)
+{
+ float f0log, gain;
+ int i, j;
+
+ /* f0 / L / Lb for each subframe */
+ f0log = -4.4f - 1.777e-1f * rp->pitch_mean;
+
+ for (i=0; i<2; i++)
+ ir77_ambe_subframe_compute_f0_L_Lb(&sf[i],
+ f0log, ir77_ambe_pitch_diff_vq[rp->pitch_diff][i]);
+
+ /* Gain */
+ gain = 0.34375f * (rp->gain_mean + 0.5f);
+
+ for (i=0; i<2; i++)
+ sf[i].gain = gain + ir77_ambe_gain_diff_vq[rp->gain_diff][i] - (0.5f * log2f(sf[i].L));
+
+#ifdef DEBUG
+ printf("---- Decoded Gain\n");
+ printf(" .mean : %f\n", gain);
+ printf(" .diff0 : %f\n", ir77_ambe_gain_diff_vq[rp->gain_diff][0]);
+ printf(" .diff1 : %f\n", ir77_ambe_gain_diff_vq[rp->gain_diff][1]);
+ printf(" .final0 : %f [%04x]\n", sf[0].gain, (int)(roundf(2048.0f * sf[0].gain)));
+ printf(" .final1 : %f [%04x]\n", sf[1].gain, (int)(roundf(2048.0f * sf[1].gain)));
+#endif
+
+ /* V/UV */
+ for (i=0; i<2; i++)
+ {
+ uint8_t v_uv = ir77_ambe_v_uv_tbl[rp->v_uv[i]];
+
+ for (j=0; j<8; j++)
+ sf[i].v_uv[j] = (v_uv >> (7-j)) & 1;
+ }
+
+#ifdef DEBUG
+ printf("---- Decode V/UV\n");
+ printf(" .v_uv[0] : ");
+ for (i=0; i<8; i++)
+ printf("%d", sf[0].v_uv[i]);
+ printf("\n");
+ printf(" .v_uv[1] : ");
+ for (i=0; i<8; i++)
+ printf("%d", sf[1].v_uv[i]);
+ printf("\n");
+#endif
+
+ /* Spectral magnitudes */
+ for (i=0; i<2; i++)
+ {
+ int j, k, l;
+
+ /* Prediction */
+ ir77_ambe_resample_mag(sf[i].Mlog, sf[i].L, sf_prev->Mlog, sf_prev->L);
+
+ for (j=0; j<sf[i].L; j++)
+ sf[i].Mlog[j] *= 0.8f;
+
+ /* PRBA */
+ float d = (i == 0) ? -1.0f : 1.0f;
+ float prba[8];
+ float Ri[8];
+
+ prba[0] = 0.0f;
+ prba[1] = ir77_ambe_prba_sum12_vq[rp->prba_sum12][0] +
+ d * ir77_ambe_prba_dif13_vq[rp->prba_dif13][0];
+ prba[2] = ir77_ambe_prba_sum12_vq[rp->prba_sum12][1] +
+ d * ir77_ambe_prba_dif13_vq[rp->prba_dif13][1];
+ prba[3] = ir77_ambe_prba_sum34_vq[rp->prba_sum34][0] +
+ d * ir77_ambe_prba_dif13_vq[rp->prba_dif13][2];
+ prba[4] = ir77_ambe_prba_sum34_vq[rp->prba_sum34][1] +
+ d * ir77_ambe_prba_dif47_vq[rp->prba_dif47][0];
+ prba[5] = ir77_ambe_prba_sum57_vq[rp->prba_sum57][0] +
+ d * ir77_ambe_prba_dif47_vq[rp->prba_dif47][1];
+ prba[6] = ir77_ambe_prba_sum57_vq[rp->prba_sum57][1] +
+ d * ir77_ambe_prba_dif47_vq[rp->prba_dif47][2];
+ prba[7] = ir77_ambe_prba_sum57_vq[rp->prba_sum57][2] +
+ d * ir77_ambe_prba_dif47_vq[rp->prba_dif47][3];
+
+ ir77_ambe_idct(Ri, prba, 8, 8);
+
+ /* Process each block */
+ float rconst = (1.0f / (2.0f * (float)M_SQRT2));
+ float sum = 0.0f;
+
+ k = 0;
+
+ for (j=0; j<4; j++) {
+ const float *hoc_sum_tbl[] = {
+ ir77_ambe_hoc0_sum_vq[rp->hoc_sum[0]],
+ ir77_ambe_hoc1_sum_vq[rp->hoc_sum[1]],
+ ir77_ambe_hoc2_sum_vq[rp->hoc_sum[2]],
+ ir77_ambe_hoc3_sum_vq[rp->hoc_sum[3]],
+ };
+ const float *hoc_dif_tbl[] = {
+ ir77_ambe_hoc0_dif_vq[rp->hoc_dif[0]],
+ ir77_ambe_hoc1_dif_vq[rp->hoc_dif[1]],
+ ir77_ambe_hoc2_dif_vq[rp->hoc_dif[2]],
+ ir77_ambe_hoc3_dif_vq[rp->hoc_dif[3]],
+ };
+ float C[6], c[17];
+
+ /* From PRBA through 2x2 xform */
+ C[0] = (Ri[j<<1] + Ri[(j<<1)+1]) * 0.5f;
+ C[1] = (Ri[j<<1] - Ri[(j<<1)+1]) * rconst;
+
+ /* HOC */
+ /* Default to use all available */
+ C[2] = hoc_sum_tbl[j][0] + d * hoc_dif_tbl[j][0];
+ C[3] = hoc_sum_tbl[j][1] + d * hoc_dif_tbl[j][1];
+ C[4] = hoc_sum_tbl[j][2] + d * hoc_dif_tbl[j][2];
+ C[5] = hoc_sum_tbl[j][3] + d * hoc_dif_tbl[j][3];
+
+ /* Zero unused value and if len differ for
+ * sf0/1, then diff vector is not used */
+ for (l=2; l<6; l++)
+ {
+ if (l >= sf[i].Lb[j])
+ C[l] = 0.0f;
+ else if (l >= sf[i^1].Lb[j])
+ C[l] = hoc_sum_tbl[j][l-2];
+ }
+
+ /* De-DCT */
+ ir77_ambe_idct(c, C, sf[i].Lb[j], (sf[i].Lb[j] < 6) ? sf[i].Lb[j] : 6);
+
+ /* Set magnitudes */
+ for (l=0; l<sf[i].Lb[j]; l++)
+ sf[i].Mlog[k++] += c[l];
+
+ sum += C[0] * sf[i].Lb[j];
+ }
+
+ /* Adjust to final gain value */
+ float ofs = sf[i].gain - (sum / sf[i].L);
+
+ for (j=0; j<sf[i].L; j++)
+ sf[i].Mlog[j] += ofs;
+ }
+}
+
+/*! \brief Expands the decoded subframe params to prepare for synthesis
+ * \param[in] sf The subframe to expand
+ */
+void
+ir77_ambe_subframe_expand(struct ir77_ambe_subframe *sf)
+{
+ float unvc;
+ int i;
+
+ sf->w0 = sf->f0 * (2.0f * M_PIf);
+
+ unvc = 0.2046f / sqrtf(sf->w0); /* ??? */
+
+ for (i=0; i<sf->L; i++) {
+ int j = (int)(i * 16.0f * sf->f0);
+ sf->Vl[i] = sf->v_uv[j];
+ sf->Ml[i] = powf(2.0, sf->Mlog[i]) / 8.0f;
+ if (!sf->Vl[i])
+ sf->Ml[i] *= unvc;
+ }
+}
+
+/*! @} */
diff --git a/codec/ir77_ambe_decode.c b/codec/ir77_ambe_decode.c
new file mode 100644
index 0000000..4d8fd7b
--- /dev/null
+++ b/codec/ir77_ambe_decode.c
@@ -0,0 +1,199 @@
+/* Iridium AMBE vocoder - Decoder tool */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "ambe.h"
+
+
+static const uint8_t wav_hdr[] = {
+ /* WAV header */
+ 'R', 'I', 'F', 'F', /* ChunkID */
+ 0x00, 0x00, 0x00, 0x00, /* ChunkSize */
+ 'W', 'A', 'V', 'E', /* Format */
+
+ /* Sub chunk: format */
+ 'f', 'm', 't', ' ', /* Subchunk1ID */
+ 0x10, 0x00, 0x00, 0x00, /* Subchunk1Size */
+ 0x01, 0x00, /* AudioFormat: PCM */
+ 0x01, 0x00, /* NumChannels: Mono */
+ 0x40, 0x1f, 0x00, 0x00, /* SampleRate: 8000 Hz */
+ 0x80, 0x3e, 0x00, 0x00, /* ByteRate: 16k/s */
+ 0x02, 0x00, /* BlockAlign: 2 bytes */
+ 0x10, 0x00, /* BitsPerSample: 16 */
+
+ /* Sub chunk: data */
+ 'd', 'a', 't', 'a', /* Subchunk2ID */
+ 0x00, 0x00, 0x00, 0x00, /* Subchunk2Size */
+};
+
+static uint32_t
+le32(uint32_t v)
+{
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ return v;
+#else
+ return ((v & 0x000000ff) << 24) |
+ ((v & 0x0000ff00) << 8) |
+ ((v & 0x00ff0000) >> 8) |
+ ((v & 0xff000000) >> 24);
+#endif
+}
+
+static uint16_t
+le16(uint16_t v)
+{
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ return v;
+#else
+ return ((v & 0x00ff) << 8) |
+ ((v & 0xff00) >> 8);
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ struct ir77_ambe_decoder *dec = NULL;
+ FILE *fin, *fout;
+ int is_wave = 0, l, rv;
+
+ /* Arguments */
+ if (argc > 3) {
+ fprintf(stderr, "Usage: %s [in_file [out_file]]\n", argv[0]);
+ return -1;
+ }
+
+ if ((argc < 2) || !strcmp(argv[1], "-"))
+ fin = stdin;
+ else {
+ fin = fopen(argv[1], "rb");
+ if (!fin) {
+ fprintf(stderr, "[!] Unable to open input file\n");
+ return -1;
+ }
+ }
+
+ if ((argc < 3) || !strcmp(argv[2], "-"))
+ fout = stdout;
+ else {
+ fout = fopen(argv[2], "wb");
+ if (!fout) {
+ fprintf(stderr, "[!] Unable to open output file\n");
+ return -1;
+ }
+
+ l = strlen(argv[2]);
+
+ if ((l > 4) && (!strcmp(".wav", &argv[2][l-4])))
+ is_wave = 1;
+ }
+
+ /* Write inital wave header */
+ if (is_wave) {
+ rv = fwrite(wav_hdr, sizeof(wav_hdr), 1, fout);
+ if (rv != 1) {
+ fprintf(stderr, "[!] Failed to write WAV header\n");
+ goto exit;
+ }
+ }
+
+ /* Init decoder */
+ dec = ir77_ambe_decode_alloc();
+ if (!dec)
+ goto exit;
+
+ /* Process all frames */
+ l = 0;
+
+ while (!feof(fin))
+ {
+ uint8_t superframe[39];
+ int16_t audio[2*360];
+ int rv, i;
+
+ /* Read input frame */
+ rv = fread(superframe, 1, 39, fin);
+ if (rv != 39)
+ break;
+
+ /* Skip dummy frames */
+ if ((superframe[0] == 0xff) && (superframe[38] == 0xff))
+ continue;
+
+ /* Decompress */
+ rv = ir77_ambe_decode_superframe(dec, audio, 2*360, superframe);
+ if (rv) {
+ fprintf(stderr, "[!] codec error\n");
+ break;
+ }
+
+ /* Write audio output */
+ for (i=0; i<2*360; i++)
+ audio[i] = le16(audio[i]);
+
+ rv = fwrite(audio, 2, 2*360, fout);
+ if (rv != 2*360) {
+ fprintf(stderr, "[!] short write\n");
+ break;
+ }
+
+ /* Keep track of number of samples */
+ l += 2*360;
+ }
+
+ /* Release decoder */
+ ir77_ambe_decode_release(dec);
+
+ /* Fix wave header */
+ if (is_wave)
+ {
+ uint32_t v;
+
+ /* Fixup Subchunk2Size */
+ v = le32(l * 2);
+
+ rv = fseek(fout, 40, SEEK_SET);
+ if (rv < 0)
+ goto exit;
+
+ rv = fwrite(&v, 4, 1, fout);
+ if (rv < 0)
+ goto exit;
+
+ /* Fixup ChunkSize */
+ v = le32(l * 2 + 36);
+
+ rv = fseek(fout, 4, SEEK_SET);
+ if (rv < 0)
+ goto exit;
+
+ rv = fwrite(&v, 4, 1, fout);
+ if (rv < 0)
+ goto exit;
+ }
+
+exit:
+ /* Close in/out */
+ fclose(fout);
+ fclose(fin);
+
+ /* All done ! */
+ return 0;
+}
diff --git a/codec/math.c b/codec/math.c
new file mode 100644
index 0000000..44a9e21
--- /dev/null
+++ b/codec/math.c
@@ -0,0 +1,177 @@
+/* Iridium AMBE vocoder - Math functions */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \addtogroup codec_private
+ * @{
+ */
+
+/*! \file codec/math.c
+ * \brief Iridium AMBE vocoder math functions
+ */
+
+#include <math.h>
+
+#include "private.h"
+
+
+/*! \brief Table for \ref cosf_fast and \ref sinf_fast */
+static float cos_tbl[1024];
+
+/*! \brief Initializes \ref cos_tbl for \ref cosf_fast */
+static void __attribute__ ((constructor))
+cos_tbl_init(void)
+{
+ int i;
+
+ for (i=0; i<1024; i++)
+ cos_tbl[i] = cosf((M_PIf * i) / 512.0f);
+}
+
+/*! \brief Fast Cosinus approximation using a simple table
+ * \param[in] angle The angle value
+ * \returns The cosinus of the angle
+ */
+float
+cosf_fast(float angle)
+{
+ const float f = 512.0f / M_PIf;
+ return cos_tbl[(int)(angle*f) & 1023];
+}
+
+/*! \brief Fast Sinus approximation using a simple table
+ * \param[in] angle The angle value
+ * \returns The sinus of the angle
+ */
+float
+sinf_fast(float angle)
+{
+ const float f = 512.0f / M_PIf;
+ return cos_tbl[((int)(angle*f) + 768) & 1023];
+}
+
+/*! \brief Forward Discrete Cosine Transform (fDCT)
+ * \param[out] out fDCT result buffer (freq domain, M elements)
+ * \param[in] in fDCT input buffer (time domain, N elements)
+ * \param[in] N Number of points of the DCT
+ * \param[in] M Limit to the number of frequency components (M <= N)
+ */
+void
+ir77_ambe_fdct(float *out, float *in, int N, int M)
+{
+ int i, j;
+
+ for (i=0; i<M; i++)
+ {
+ float v = 0.0f;
+
+ for (j=0; j<N; j++)
+ {
+ v += in[j] * cosf_fast( (M_PIf / N) * (j + .5f) * i );
+ }
+
+ out[i] = v / (float)N;
+ }
+}
+
+/*! \brief Inverse Discrete Cosine Transform (iDCT)
+ * \param[out] out iDCT result buffer (time domain, N elements)
+ * \param[in] in iDCT input buffer (freq domain, M elements)
+ * \param[in] N Number of points of the DCT
+ * \param[in] M Limit to the number of frequency components (M <= N)
+ */
+void
+ir77_ambe_idct(float *out, float *in, int N, int M)
+{
+ int i, j;
+
+ for (i=0; i<N; i++)
+ {
+ float v = in[0];
+
+ for (j=1; j<M; j++)
+ {
+ v += 2.0f * in[j] * cosf_fast( (M_PIf / N) * j * (i + .5f) );
+ }
+
+ out[i] = v;
+ }
+}
+
+/*! \brief Forward Discrete Fourrier Transform (float->complex)
+ * \param[out] out_i Real component result buffer (freq domain, N/2+1 elements)
+ * \param[out] out_q Imag component result buffer (freq domain, N/2+1 elements)
+ * \param[in] in Input buffer (time domain, M elements)
+ * \param[in] N Number of points of the DFT
+ * \param[in] M Limit to to the number of available time domain elements
+ *
+ * Since the input is float, the result is symmetric and so only one side
+ * is computed. The output index 0 is DC.
+ */
+void
+ir77_ambe_fdft_fc(float *out_i, float *out_q, float *in, int N, int M)
+{
+ int fb, ts;
+
+ for (fb=0; fb<=(N/2); fb++)
+ {
+ float i=0.0f, q=0.0f;
+
+ for (ts=0; ts<M; ts++)
+ {
+ float angle = (- 2.0f * M_PIf / N) * fb * ts;
+ i += in[ts] * cosf_fast(angle);
+ q += in[ts] * sinf_fast(angle);
+ }
+
+ out_i[fb] = i;
+ out_q[fb] = q;
+ }
+}
+
+/*! \brief Inverse Discret Fourrier Transform (complex->float)
+ * \param[out] out Result buffer (time domain, M
+ * \param[in] in_i Real component input buffer (freq domain, N/2+1 elements)
+ * \param[in] in_q Imag component input buffer (freq domain, N/2+1 elements)
+ * \param[in] N Number of points of the DFT
+ * \param[in] M Limit to the number of time domain elements to generate
+ *
+ * The input is assumed to be symmetric and so only N/2+1 inputs are
+ * needed. DC component must be input index 0.
+ */
+void
+ir77_ambe_idft_cf(float *out, float *in_i, float *in_q, int N, int M)
+{
+ int fb, ts;
+
+ for (ts=0; ts<M; ts++)
+ {
+ float r=0.0f;
+
+ for (fb=0; fb<=(N/2); fb++)
+ {
+ float angle = (- 2.0f * M_PIf / N) * fb * ts;
+ float m = (fb == 0 || fb == (N/2)) ? 1.0f : 2.0f;
+ r += m * (in_i[fb] * cosf_fast(angle) + in_q[fb] * sinf_fast(angle));
+ }
+
+ out[ts] = r / N;
+ }
+}
+
+/*! @} */
diff --git a/codec/private.h b/codec/private.h
new file mode 100644
index 0000000..b64252d
--- /dev/null
+++ b/codec/private.h
@@ -0,0 +1,178 @@
+/* Iridium AMBE vocoder - private header */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OSMO_IR77_AMBE_PRIVATE_H__
+#define __OSMO_IR77_AMBE_PRIVATE_H__
+
+/*! \defgroup codec_private Iridium AMBE vocoder - internal API
+ * \ingroup codec
+ * @{
+ */
+
+/*! \file codec/private.h
+ * \brief Iridium AMBE vocoder private header
+ */
+
+#include <osmocom/core/bits.h>
+
+
+#define AMBE_RATE 8000 /*!< \brief AMBE sample rate (Hz) */
+
+/*! \brief AMBE possible frame types */
+enum ir77_ambe_frame_type
+{
+ AMBE_INVALID, /*!< \brief Invalid frame */
+ AMBE_SPEECH, /*!< \brief Speech frame */
+ AMBE_SILENCE, /*!< \brief Silence indication frame */
+ AMBE_TONE, /*!< \brief Tone frame */
+};
+
+/*! \brief AMBE encoded frame raw parameters */
+struct ir77_ambe_raw_params
+{
+ uint8_t pitch_mean; /*!< \brief Pitch mean value scalar quantized */
+ uint8_t pitch_diff; /*!< \brief Pitch diff VQ */
+ uint8_t gain_mean; /*!< \brief Gain mean value scalar quantized */
+ uint8_t gain_diff; /*!< \brief Gain diff VQ */
+ uint8_t v_uv[2]; /*!< \brief V/UV VQ for each subframe */
+
+ uint8_t prba_sum12; /*!< \brief PRBA Sum 1-2 VQ */
+ uint8_t prba_sum34; /*!< \brief PRBA Sum 3-4 VQ */
+ uint8_t prba_sum57; /*!< \brief PRBA Sum 5-7 VQ */
+ uint8_t prba_dif13; /*!< \brief PRBA Diff 1-3 VQ */
+ uint8_t prba_dif47; /*!< \brief PRBA Diff 4-7 VQ */
+
+ uint8_t hoc_sum[4]; /*!< \brief HOC Sum VQ for each block */
+ uint8_t hoc_dif[4]; /*!< \brief HOC Diff VQ for each block */
+};
+
+/*! \brief AMBE subframe parameters */
+struct ir77_ambe_subframe
+{
+ float f0; /*!< \brief fundamental normalized frequency */
+ float f0log; /*!< \brief log2(f0) */
+ float w0; /*!< \brief fundamental frequency (rad/samp) */
+ int L; /*!< \brief Number of harmonics */
+ int Lb[4]; /*!< \brief Harmonics per block */
+ int v_uv[8]; /*!< \brief Voicing state */
+ int Vl[56]; /*!< \brief Per-harmonic voicing state */
+ float gain; /*!< \brief Gain */
+ float Mlog[56]; /*!< \brief log spectral magnitudes */
+ float Ml[56]; /*!< \brief spectral magnitudes */
+};
+
+/*! \brief AMBE synthesizer state */
+struct ir77_ambe_synth
+{
+ int16_t u_prev; /*!< \brief Last 'u' of previous subframe */
+ float uw_prev[231]; /*!< \brief Unvoiced data from previous subframe */
+ float psi1; /*!< \brief Current PSI angle for fundamental */
+ float phi[56]; /*!< \brief Current phase for each harmonic */
+ float SE; /*!< \brief Current energy parameter */
+};
+
+/*! \brief AMBE decoder state */
+struct ir77_ambe_decoder
+{
+ float tone_phase_f1; /*!< \brief Phase frequency 1 for tone frames */
+ float tone_phase_f2; /*!< \brief Phase frequency 2 for tone frames */
+
+ struct ir77_ambe_subframe sf_prev; /*!< \brief Previous subframe */
+ struct ir77_ambe_synth synth; /*!< \brief Synthesizer state */
+};
+
+
+
+/* From ecc.c */
+void ir77_ambe_golay23_encode(ubit_t *out, ubit_t *in);
+int ir77_ambe_golay23_decode(ubit_t *out, ubit_t *in, uint32_t *data_p);
+
+void ir77_ambe_golay24_encode(ubit_t *out, ubit_t *in);
+int ir77_ambe_golay24_decode(ubit_t *out, ubit_t *in, uint32_t *data_p);
+
+void ir77_ambe_hamming1511_encode(ubit_t *out, ubit_t *in);
+int ir77_ambe_hamming1511_decode(ubit_t *out, ubit_t *in);
+
+
+/* From frame.c */
+void ir77_ambe_interleave(ubit_t *lin_buf, ubit_t *il_buf,
+ int il_step, int N, int dir);
+void ir77_ambe_scramble(ubit_t *out, ubit_t *in, int N, uint32_t seed);
+void ir77_ambe_prioritize(ubit_t *lin_buf, ubit_t *prio_buf, int dir);
+
+enum ir77_ambe_frame_type ir77_ambe_frame_classify(const ubit_t *frame);
+
+void ir77_ambe_frame_unpack_raw(struct ir77_ambe_raw_params *rp,
+ const ubit_t *frame);
+void ir77_ambe_frame_decode_params(struct ir77_ambe_subframe *sf,
+ struct ir77_ambe_subframe *sf_prev,
+ struct ir77_ambe_raw_params *rp);
+void ir77_ambe_subframe_expand(struct ir77_ambe_subframe *sf);
+
+
+/* From synth.c */
+void ir77_ambe_synth_init(struct ir77_ambe_synth *synth);
+void ir77_ambe_synth_enhance(struct ir77_ambe_synth *synth, struct ir77_ambe_subframe *sf);
+void ir77_ambe_synth_audio(struct ir77_ambe_synth *synth, int16_t *audio,
+ struct ir77_ambe_subframe *sf,
+ struct ir77_ambe_subframe *sf_prev);
+
+
+/* From math.c */
+#define M_PIf (3.141592653589793f) /*!< \brief Value of pi as a float */
+
+float cosf_fast(float angle);
+float sinf_fast(float angle);
+void ir77_ambe_fdct(float *out, float *in, int N, int M);
+void ir77_ambe_idct(float *out, float *in, int N, int M);
+void ir77_ambe_fdft_fc(float *out_i, float *out_q, float *in, int N, int M);
+void ir77_ambe_idft_cf(float *out, float *in_i, float *in_q, int N, int M);
+
+
+/* From tables.c */
+extern const struct { uint8_t pos; uint8_t len; } ir77_ambe_prio_tbl[];
+
+extern const float ir77_ambe_pitch_diff_vq[64][2];
+extern const uint8_t ir77_ambe_hpg_tbl[48][4];
+extern const float ir77_ambe_gain_diff_vq[32][2];
+extern const uint8_t ir77_ambe_v_uv_tbl[16];
+
+extern const float ir77_ambe_prba_sum12_vq[256][2];
+extern const float ir77_ambe_prba_sum34_vq[ 64][2];
+extern const float ir77_ambe_prba_sum57_vq[128][3];
+extern const float ir77_ambe_prba_dif13_vq[256][3];
+extern const float ir77_ambe_prba_dif47_vq[ 64][4];
+
+extern const float ir77_ambe_hoc0_sum_vq[128][4];
+extern const float ir77_ambe_hoc0_dif_vq[128][4];
+extern const float ir77_ambe_hoc1_sum_vq[128][4];
+extern const float ir77_ambe_hoc1_dif_vq[128][4];
+extern const float ir77_ambe_hoc2_sum_vq[128][4];
+extern const float ir77_ambe_hoc2_dif_vq[128][4];
+extern const float ir77_ambe_hoc3_sum_vq[128][4];
+extern const float ir77_ambe_hoc3_dif_vq[128][4];
+
+/* From tones.c */
+int ir77_ambe_decode_tone(struct ir77_ambe_decoder *dec,
+ int16_t *audio, int N, const ubit_t *frame);
+
+
+/*! @} */
+
+#endif /* __OSMO_IR77_AMBE_PRIVATE_H__ */
diff --git a/codec/synth.c b/codec/synth.c
new file mode 100644
index 0000000..69ce9ff
--- /dev/null
+++ b/codec/synth.c
@@ -0,0 +1,381 @@
+/* Iridium AMBE vocoder - Speech synthesis */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \addtogroup codec_private
+ * @{
+ */
+
+/*! \file codec/synth.c
+ * \brief Iridium AMBE vocoder speech synthesis
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <math.h>
+#include <string.h>
+
+#include "private.h"
+
+/*! \brief Synthesis window (49 samples overlap) */
+static const float ws[] = {
+ 0.00f, 0.02f,
+ 0.04f, 0.06f, 0.08f, 0.10f, 0.12f, 0.14f, 0.16f, 0.18f,
+ 0.20f, 0.22f, 0.24f, 0.26f, 0.28f, 0.30f, 0.32f, 0.34f,
+ 0.36f, 0.38f, 0.40f, 0.42f, 0.44f, 0.46f, 0.48f, 0.50f,
+ 0.52f, 0.54f, 0.56f, 0.58f, 0.60f, 0.62f, 0.64f, 0.66f,
+ 0.68f, 0.70f, 0.72f, 0.74f, 0.76f, 0.78f, 0.80f, 0.82f,
+ 0.84f, 0.86f, 0.88f, 0.90f, 0.92f, 0.94f, 0.96f, 0.98f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f,
+ 0.98f, 0.96f, 0.94f, 0.92f, 0.90f, 0.88f, 0.86f, 0.84f,
+ 0.82f, 0.80f, 0.78f, 0.76f, 0.74f, 0.72f, 0.70f, 0.68f,
+ 0.66f, 0.64f, 0.62f, 0.60f, 0.58f, 0.56f, 0.54f, 0.52f,
+ 0.50f, 0.48f, 0.46f, 0.44f, 0.42f, 0.40f, 0.38f, 0.36f,
+ 0.34f, 0.32f, 0.30f, 0.28f, 0.26f, 0.24f, 0.22f, 0.20f,
+ 0.18f, 0.16f, 0.14f, 0.12f, 0.10f, 0.08f, 0.06f, 0.04f,
+ 0.02f, 0.00f,
+};
+
+/*! \brief Random phase increment (precomputed) */
+static const float rho[] = {
+ 3.002978f, -0.385743f, -1.804058f, 0.708389f, 3.080091f, 0.234237f,
+ -2.601564f, 2.564900f, 0.101063f, -0.241570f, -2.283176f, 0.460491f,
+ -1.611275f, 2.258339f, -2.055267f, 1.733923f, 2.517236f, -1.766211f,
+ 0.897032f, -2.360999f, -0.280836f, -2.714514f, 2.100092f, 2.300326f,
+ -1.158767f, -2.044268f, -2.668387f, -2.578737f, 0.185036f, 1.551429f,
+ 2.726814f, 2.655614f, 3.046857f, 0.834348f, -0.513595f, 1.466037f,
+ 0.691121f, 0.127319f, -2.034924f, -1.070655f, 0.456588f, -2.278682f,
+ 1.229021f, -2.139595f, -0.119750f, -0.301534f, 0.029391f, 0.068775f,
+ 0.520336f, 2.339119f, -0.808328f, 1.332154f, 2.929768f, -0.338316f,
+ 0.022767f, -1.063795f,
+};
+
+
+/*! \brief Generates random sequence of uint16_t according to spec
+ * \param[out] u_seq Result buffer
+ * \param[in] u_prev Last 'u' value of where to resume from
+ * \param[in] n Number of items to generate
+ */
+static void
+ir77_ambe_gen_random(uint16_t *u_seq, uint16_t u_prev, int n)
+{
+ uint32_t u = u_prev;
+ int i;
+
+ for (i=0; i<n; i++) {
+ u = (u * 171 + 11213) % 53125;
+ u_seq[i] = u;
+ }
+}
+
+/*! \brief Perform unvoiced synthesis
+ * \param[in] synth Synthesizer state structure
+ * \param[out] suv Result buffer (180 samples)
+ * \param[in] sf Expanded subframe data
+ */
+static void
+ir77_ambe_synth_unvoiced(struct ir77_ambe_synth *synth, float *suv,
+ struct ir77_ambe_subframe *sf)
+{
+ uint16_t u[231];
+ float uw[231];
+ float Uwi[129], Uwq[129];
+ int i, al, bl, l;
+
+ /* Generate the white noise sequence and window it with ws */
+ ir77_ambe_gen_random(u, synth->u_prev, 231);
+ synth->u_prev = u[179];
+
+ for (i=0; i<231; i++)
+ uw[i] = (float)u[i] * ws[i];
+
+ /* Compute the DFT */
+ ir77_ambe_fdft_fc(Uwi, Uwq, uw, 256, 231);
+
+ /* Apply the spectral magnitude */
+ bl = ceilf(256.0f / (2 * M_PIf) * (.5f) * sf->w0);
+
+ for (i=0; i<bl; i++) {
+ Uwi[i] = 0.0f;
+ Uwq[i] = 0.0f;
+ }
+
+ for (l=0; l<sf->L; l++)
+ {
+ float ampl;
+
+ /* Edges */
+ al = bl;
+ bl = ceilf(256.0f / (2 * M_PIf) * (l + 1.5f) * sf->w0);
+
+ /* Compute factor */
+ ampl = 0.0f;
+
+ for (i=al; i<bl; i++) {
+ ampl += Uwi[i] * Uwi[i] + Uwq[i] * Uwq[i];
+ }
+
+ ampl = 76.89f * sf->Ml[l] / sqrtf(ampl / (bl - al));
+
+ /* Set magnitude */
+ for (i=al; i<bl; i++) {
+ if (sf->Vl[l]) {
+ Uwi[i] = 0.0f;
+ Uwq[i] = 0.0f;
+ } else {
+ Uwi[i] *= ampl;
+ Uwq[i] *= ampl;
+ }
+ }
+ }
+
+ for (i=bl; i<=128; i++) {
+ Uwi[i] = 0.0f;
+ Uwq[i] = 0.0f;
+ }
+
+ /* Get time-domain samples via iDFT */
+ ir77_ambe_idft_cf(uw, Uwi, Uwq, 256, 231);
+
+ /* Weighted Overlap And Add */
+ for (i=0; i<66; i++) {
+ suv[i] = synth->uw_prev[i + 115];
+ }
+
+ for (i=66; i<115; i++) {
+ suv[i] = (ws[i + 115] * synth->uw_prev[i + 115] + ws[i - 65] * uw[i - 65])
+ / (ws[i + 115] * ws[i + 115] + ws[i - 65] * ws[i - 65]);
+ }
+
+ for (i=115; i<180; i++) {
+ suv[i] = uw[i - 65];
+ }
+
+ memcpy(synth->uw_prev, uw, sizeof(float) * 231);
+}
+
+/*! \brief Perform voiced synthesis
+ * \param[in] synth Synthesizer state structure
+ * \param[out] sv Result buffer (180 samples)
+ * \param[in] sf Expanded subframe data for current subframe
+ * \param[in] sf_prev Expanded subframe data for prevous subframe
+ */
+static void
+ir77_ambe_synth_voiced(struct ir77_ambe_synth *synth, float *sv,
+ struct ir77_ambe_subframe *sf,
+ struct ir77_ambe_subframe *sf_prev)
+{
+ int i, l, L_max, L_uv;
+
+ /* Pre-clear */
+ memset(sv, 0x00, sizeof(float) * 180);
+
+ /* How many subband to process */
+ L_max = sf_prev->L > sf->L ? sf_prev->L : sf->L;
+
+ /* psi update */
+ L_uv = 0;
+ for (l=0; l<L_max; l++)
+ L_uv += sf->Vl[l] ? 0 : 1;
+
+ synth->psi1 = remainderf(synth->psi1 + (sf->w0 + sf_prev->w0) * 90.0f, 2 * M_PIf);
+
+ /* Scan each band */
+ for (l=0; l<L_max; l++)
+ {
+ int Vl_cur, Vl_prev;
+ float Ml_cur, Ml_prev;
+ float phi_cur, phi_prev;
+ float w_cur, w_prev;
+ int fine;
+
+ /* Handle out-of-bound for Vl and Ml */
+ Vl_cur = l >= sf->L ? 0 : sf->Vl[l];
+ Vl_prev = l >= sf_prev->L ? 0 : sf_prev->Vl[l];
+
+ Ml_cur = l >= sf->L ? 0.0f : sf->Ml[l];
+ Ml_prev = l >= sf_prev->L ? 0.0f : sf_prev->Ml[l];
+
+ /* Phase and Angular speed */
+ w_cur = (l+1) * sf->w0;
+ w_prev = (l+1) * sf_prev->w0;
+
+ phi_prev = synth->phi[l];
+ phi_cur = synth->psi1 * (l+1);
+
+ if (l >= (sf->L / 4))
+ phi_cur += ((float)L_uv / (float)sf->L) * rho[l];
+
+ synth->phi[l] = phi_cur;
+
+ /* Actual synthesis */
+ /* Can we do a fine transistion ? */
+ fine = Vl_cur && Vl_prev && (l < 7) && (fabsf(w_cur - w_prev) < (.1f * w_cur));
+
+ /* Fine transition */
+ if (fine)
+ {
+ float Ml_step = (Ml_cur - Ml_prev) / 180.0f;
+ float Dpl = phi_cur - phi_prev - (w_cur + w_prev) * 90.0f;
+ float Dwl = (Dpl - 2 * M_PIf * floorf((Dpl + M_PIf) / (2 * M_PIf))) / 180.0f;
+ float THa = w_prev + Dwl;
+ float THb = (w_cur - w_prev) / 360.0f;
+
+ for (i=0; i<180; i++)
+ sv[i] += (Ml_prev + i * Ml_step) * cosf_fast(
+ phi_prev + (THa + THb * i) * i
+ );
+ }
+
+ /* Coarse transition: Current frame (if voiced) */
+ if (!fine && Vl_cur)
+ {
+ for (i=66; i<180; i++)
+ sv[i] += ws[i-65] * Ml_cur * cosf_fast(phi_cur + w_cur * (i - 180));
+ }
+
+ /* Coarse transition: Previous frame (if voiced) */
+ if (!fine && Vl_prev)
+ {
+ for (i=0; i<115; i++)
+ sv[i] += ws[i+115] * Ml_prev * cosf_fast(phi_prev + w_prev * i);
+ }
+ }
+
+ /* Still need to update phi for the rest of the bands */
+ for (l=L_max; l<56; l++)
+ synth->phi[l] = (synth->psi1 * (l+1)) + (((float)L_uv / (float)sf->L) * rho[l]);
+}
+
+
+/*! \brief Initialized Synthesizer state
+ * \param[out] synth The structure to reset
+ */
+void
+ir77_ambe_synth_init(struct ir77_ambe_synth *synth)
+{
+ memset(synth, 0x00, sizeof(struct ir77_ambe_synth));
+ synth->u_prev = 3147;
+}
+
+/*! \brief Apply the spectral magnitude enhancement on the subframe
+ * \param[in] synth Synthesizer state structure
+ * \param[in] sf Expanded subframe data for subframe to enhance
+ */
+void
+ir77_ambe_synth_enhance(struct ir77_ambe_synth *synth,
+ struct ir77_ambe_subframe *sf)
+{
+ float rm0, rm1;
+ float k1, k2, k3;
+ float gamma;
+ int l;
+
+ /* Compute RM0 and RM1 */
+ rm0 = 0.0f;
+ rm1 = 0.0f;
+
+ for (l=0; l<sf->L; l++)
+ {
+ float sq = sf->Ml[l] * sf->Ml[l];
+ rm0 += sq;
+ rm1 += sq * cosf_fast(sf->w0 * (l+1));
+ }
+
+ /* Pre compute some constants */
+ k1 = 0.96f * M_PIf / (sf->w0 * rm0 * (rm0 * rm0 - rm1 * rm1));
+ k2 = rm0 * rm0 + rm1 * rm1;
+ k3 = 2.0f * rm0 * rm1;
+
+ /* Apply to the amplitudes */
+ gamma = 0.0f;
+
+ for (l=0; l<sf->L; l++)
+ {
+ float w;
+
+ if ( (l+1)*8 <= sf->L ) {
+ w = 1.0f;
+ } else {
+ w = sqrtf(sf->Ml[l]) * powf(
+ k1 * (k2 - k3 * cosf_fast(sf->w0 * (l+1))),
+ 0.25f
+ );
+
+ if (w > 1.2f)
+ w = 1.2f;
+ else if (w < 0.5f)
+ w = 0.5f;
+ }
+
+ sf->Ml[l] *= w;
+
+ gamma += sf->Ml[l] * sf->Ml[l];
+ }
+
+ /* Compute final gamma and apply it */
+ gamma = sqrtf(rm0 / gamma);
+
+ for (l=0; l<sf->L; l++)
+ {
+ sf->Ml[l] *= gamma;
+ }
+
+ /* Update SE */
+ synth->SE = 0.95f * synth->SE + 0.05f * rm0;
+ if (synth->SE < 1e4f)
+ synth->SE = 1e4f;
+}
+
+/*! \brief Generate audio for a given subframe
+ * \param[in] synth Synthesizer state structure
+ * \param[out] audio Result buffer (180 samples)
+ * \param[in] sf Expanded subframe data for current subframe
+ * \param[in] sf_prev Expanded subframe data for prevous subframe
+ */
+void
+ir77_ambe_synth_audio(struct ir77_ambe_synth *synth, int16_t *audio,
+ struct ir77_ambe_subframe *sf,
+ struct ir77_ambe_subframe *sf_prev)
+{
+ float suv[180], sv[180];
+ int i;
+
+ ir77_ambe_synth_unvoiced(synth, suv, sf);
+ ir77_ambe_synth_voiced(synth, sv, sf, sf_prev);
+ for (i=0; i<180; i++)
+ audio[i] = (int16_t)((suv[i] + 2.0f * sv[i]) * 4.0f);
+}
+
+/*! @} */
diff --git a/codec/tables.c b/codec/tables.c
new file mode 100644
index 0000000..512d59f
--- /dev/null
+++ b/codec/tables.c
@@ -0,0 +1,1590 @@
+/* Iridium AMBE vocoder - Tables */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \addtogroup codec_private
+ * @{
+ */
+
+/*! \file codec/tables.c
+ * \brief Iridium AMBE vocoder tables
+ */
+
+#include <stdint.h>
+
+/*! \brief Bit prioritization table */
+const struct {
+ uint8_t pos;
+ uint8_t len;
+} ir77_ambe_prio_tbl[] = {
+ { 0, 6 },
+ { 10, 3 },
+ { 15, 3 },
+ { 28, 8 },
+ { 36, 6 },
+ { 49, 8 },
+ { 63, 7 },
+ { 73, 7 },
+ { 20, 2 },
+ { 24, 2 },
+ { 42, 7 },
+ { 13, 1 },
+ { 83, 4 },
+ { 93, 4 },
+ { 6, 4 },
+ { 14, 1 },
+ { 18, 2 },
+ { 87, 3 },
+ { 97, 3 },
+ { 57, 6 },
+ { 70, 3 },
+ { 80, 3 },
+ { 90, 3 },
+ { 100, 3 },
+ { 22, 2 },
+ { 26, 2 },
+ { 0, 0 }, /* Termination */
+};
+
+/*! \brief f0log/pitch difference vector quantization table */
+const float ir77_ambe_pitch_diff_vq[64][2] = {
+ { -0.9111f, 0.8867f },
+ { -0.7461f, 0.8027f },
+ { -0.7188f, 0.6191f },
+ { -0.5527f, 0.6084f },
+ { -0.5635f, 0.4619f },
+ { -0.3809f, 0.4971f },
+ { -0.4189f, 0.4209f },
+ { -0.3809f, 0.2744f },
+ { -0.2324f, 0.3340f },
+ { -0.2490f, 0.2051f },
+ { -0.1357f, 0.2393f },
+ { -0.2217f, 0.1006f },
+ { -0.0566f, 0.1670f },
+ { -0.1289f, 0.0898f },
+ { -0.1357f, 0.0029f },
+ { -0.0498f, 0.0898f },
+ { 0.0088f, 0.1211f },
+ { -0.0576f, 0.0322f },
+ { -0.0723f, -0.0117f },
+ { 0.0146f, 0.0664f },
+ { 0.0498f, 0.0996f },
+ { -0.0898f, -0.0469f },
+ { -0.0107f, 0.0342f },
+ { -0.0283f, -0.0088f },
+ { -0.0400f, -0.0420f },
+ { 0.0000f, 0.0000f },
+ { 0.0576f, 0.0557f },
+ { -0.0732f, -0.0762f },
+ { 0.0313f, 0.0254f },
+ { 0.0840f, 0.0801f },
+ { 0.0166f, -0.0137f },
+ { -0.0381f, -0.0762f },
+ { -0.0020f, -0.0508f },
+ { 0.0986f, 0.0449f },
+ { 0.0674f, 0.0098f },
+ { -0.0498f, -0.1094f },
+ { 0.0420f, -0.0254f },
+ { -0.0010f, -0.0869f },
+ { 0.1211f, 0.0107f },
+ { 0.0371f, -0.0771f },
+ { -0.0098f, -0.1299f },
+ { 0.0977f, -0.0381f },
+ { 0.0615f, -0.1328f },
+ { 0.1748f, -0.0410f },
+ { 0.1260f, -0.1182f },
+ { 0.0596f, -0.2080f },
+ { 0.2305f, -0.1152f },
+ { 0.1357f, -0.2100f },
+ { 0.2256f, -0.2383f },
+ { 0.2949f, -0.2021f },
+ { 0.3711f, -0.2314f },
+ { 0.2480f, -0.3701f },
+ { 0.3652f, -0.3994f },
+ { 0.4443f, -0.3740f },
+ { 0.4316f, -0.5420f },
+ { 0.5410f, -0.4580f },
+ { 0.5410f, -0.5791f },
+ { 0.7012f, -0.5859f },
+ { 0.5977f, -0.7402f },
+ { 0.7139f, -0.7588f },
+ { 0.8369f, -0.7471f },
+ { 0.8369f, -0.9160f },
+ { 0.9873f, -0.9453f },
+ { 1.0732f, -1.1279f },
+};
+
+/*! \brief Number of harmonics per group for a given L (starts at L=9) */
+const uint8_t ir77_ambe_hpg_tbl[48][4] = {
+ { 2, 2, 2, 3 }, /* L = 9 */
+ { 2, 2, 3, 3 },
+ { 2, 3, 3, 3 },
+ { 2, 3, 3, 4 },
+ { 3, 3, 3, 4 },
+ { 3, 3, 4, 4 },
+ { 3, 3, 4, 5 },
+ { 3, 4, 4, 5 },
+ { 3, 4, 5, 5 },
+ { 4, 4, 5, 5 },
+ { 4, 4, 5, 6 },
+ { 4, 4, 6, 6 },
+ { 4, 5, 6, 6 },
+ { 4, 5, 6, 7 },
+ { 5, 5, 6, 7 },
+ { 5, 5, 7, 7 },
+ { 5, 6, 7, 7 },
+ { 5, 6, 7, 8 },
+ { 5, 6, 8, 8 },
+ { 6, 6, 8, 8 },
+ { 6, 6, 8, 9 },
+ { 6, 7, 8, 9 },
+ { 6, 7, 9, 9 },
+ { 6, 7, 9, 10 },
+ { 7, 7, 9, 10 },
+ { 7, 8, 9, 10 },
+ { 7, 8, 10, 10 },
+ { 7, 8, 10, 11 },
+ { 8, 8, 10, 11 },
+ { 8, 9, 10, 11 },
+ { 8, 9, 11, 11 },
+ { 8, 9, 11, 12 },
+ { 8, 9, 11, 13 },
+ { 8, 9, 12, 13 },
+ { 8, 10, 12, 13 },
+ { 9, 10, 12, 13 },
+ { 9, 10, 12, 14 },
+ { 9, 10, 13, 14 },
+ { 9, 11, 13, 14 },
+ { 10, 11, 13, 14 },
+ { 10, 11, 13, 15 },
+ { 10, 11, 14, 15 },
+ { 10, 12, 14, 15 },
+ { 10, 12, 14, 16 },
+ { 11, 12, 14, 16 },
+ { 11, 12, 15, 16 },
+ { 11, 12, 15, 17 },
+ { 11, 13, 15, 17 }, /* L = 56 */
+};
+
+/*! \brief Gain difference (in dual-subframe quant) vector quantization table */
+const float ir77_ambe_gain_diff_vq[32][2] = {
+ { -3.2695f, 3.2710f },
+ { -2.7949f, 2.7544f },
+ { -2.3730f, 2.3701f },
+ { -1.8853f, 1.8672f },
+ { -1.5293f, 1.5093f },
+ { -1.2393f, 1.2842f },
+ { -1.0020f, 1.0195f },
+ { -0.9229f, 0.7280f },
+ { -0.6196f, 0.7944f },
+ { -0.6592f, 0.4897f },
+ { -0.3691f, 0.5425f },
+ { -0.4219f, 0.2510f },
+ { -0.1582f, 0.3042f },
+ { -0.2373f, 0.0791f },
+ { -0.1450f, -0.0532f },
+ { 0.0264f, 0.1851f },
+ { 0.0103f, -0.0239f },
+ { 0.1592f, 0.0596f },
+ { 0.0103f, -0.2153f },
+ { 0.2549f, -0.0957f },
+ { 0.1699f, -0.3350f },
+ { 0.4033f, -0.2275f },
+ { 0.3076f, -0.4907f },
+ { 0.4883f, -0.6460f },
+ { 0.5732f, -0.3950f },
+ { 0.7964f, -0.6221f },
+ { 0.7222f, -0.8735f },
+ { 1.0195f, -0.9570f },
+ { 1.2529f, -1.2324f },
+ { 1.5293f, -1.5552f },
+ { 1.9326f, -1.9502f },
+ { 2.7080f, -2.9189f },
+};
+
+/*! \brief V/UV decisions (MSBs = low freq) */
+const uint8_t ir77_ambe_v_uv_tbl[16] = {
+ 0x00, 0x80, 0xc0, 0xc1, 0xe0, 0xe1, 0xf0, 0xf1,
+ 0xf9, 0xf8, 0xfb, 0xdf, 0xfc, 0xfe, 0xfd, 0xff,
+};
+
+/*! \brief PRBA[1:2] Sum vector quantization table */
+const float ir77_ambe_prba_sum12_vq[256][2] = {
+ { 0.1758f, -0.1240f },
+ { -0.2070f, -0.1523f },
+ { 0.5034f, -0.0322f },
+ { 0.1270f, 0.0137f },
+ { -0.1704f, -0.2300f },
+ { -0.7412f, -0.3330f },
+ { 0.1211f, -0.0293f },
+ { -0.2129f, -0.0063f },
+ { -0.0186f, 0.0195f },
+ { -0.5044f, 0.1113f },
+ { 0.2544f, 0.1719f },
+ { -0.0552f, 0.2490f },
+ { -0.5107f, 0.0024f },
+ { -1.0205f, 0.1919f },
+ { -0.0796f, 0.1401f },
+ { -0.5410f, 0.3867f },
+ { 0.2827f, 0.0679f },
+ { -0.0210f, 0.1226f },
+ { 0.6826f, 0.3813f },
+ { 0.2207f, 0.3008f },
+ { -0.0483f, 0.0762f },
+ { -0.4487f, 0.2202f },
+ { 0.2134f, 0.2373f },
+ { -0.1177f, 0.4199f },
+ { 0.0825f, 0.2544f },
+ { -0.2207f, 0.3560f },
+ { 0.4067f, 0.5469f },
+ { 0.1172f, 0.5298f },
+ { -0.4004f, 0.4961f },
+ { -1.0483f, 0.5596f },
+ { -0.0210f, 0.6274f },
+ { -0.2207f, 1.1494f },
+ { 0.4546f, -0.4072f },
+ { 0.1714f, -0.1772f },
+ { 1.0742f, -0.2739f },
+ { 0.4678f, -0.0869f },
+ { 0.1055f, -0.3828f },
+ { -0.2705f, -0.4189f },
+ { 0.4087f, -0.1372f },
+ { 0.0791f, -0.1011f },
+ { 0.2173f, -0.0908f },
+ { -0.0464f, -0.0303f },
+ { 0.5601f, 0.0742f },
+ { 0.1978f, 0.0864f },
+ { -0.0659f, -0.0889f },
+ { -0.5801f, -0.1108f },
+ { 0.1909f, 0.0381f },
+ { -0.1055f, 0.0845f },
+ { 0.6553f, -0.0361f },
+ { 0.2363f, 0.0181f },
+ { 1.0098f, 0.1489f },
+ { 0.6123f, 0.1577f },
+ { 0.2417f, -0.0249f },
+ { -0.1021f, -0.0361f },
+ { 0.4727f, 0.1035f },
+ { 0.1665f, 0.1128f },
+ { 0.3706f, 0.1938f },
+ { 0.0806f, 0.1577f },
+ { 0.6768f, 0.5283f },
+ { 0.3599f, 0.4219f },
+ { 0.0322f, 0.2168f },
+ { -0.3438f, 0.3452f },
+ { 0.3115f, 0.3115f },
+ { -0.0054f, 0.4561f },
+ { 0.4946f, -0.1411f },
+ { 0.2036f, -0.0498f },
+ { 0.8926f, -0.0313f },
+ { 0.4219f, 0.0767f },
+ { 0.1646f, -0.0830f },
+ { -0.1411f, -0.0977f },
+ { 0.4121f, 0.0186f },
+ { 0.1211f, 0.0913f },
+ { 0.2954f, 0.1079f },
+ { 0.0239f, 0.1553f },
+ { 0.5430f, 0.2241f },
+ { 0.2568f, 0.3794f },
+ { 0.0044f, 0.0664f },
+ { -0.3301f, 0.1909f },
+ { 0.2666f, 0.2324f },
+ { -0.0439f, 0.3486f },
+ { 0.7178f, 0.2471f },
+ { 0.3057f, 0.2007f },
+ { 1.1772f, 0.3525f },
+ { 0.5415f, 0.4644f },
+ { 0.2524f, 0.1187f },
+ { -0.0239f, 0.1909f },
+ { 0.5532f, 0.3457f },
+ { 0.2524f, 0.4941f },
+ { 0.4590f, 0.3853f },
+ { 0.1113f, 0.4219f },
+ { 1.1128f, 0.9194f },
+ { 0.4648f, 0.9521f },
+ { 0.0581f, 0.3560f },
+ { -0.3066f, 0.7578f },
+ { 0.5234f, 0.6426f },
+ { 0.0171f, 0.8335f },
+ { 0.9063f, -0.4927f },
+ { 0.4883f, -0.2866f },
+ { 1.7275f, -0.2300f },
+ { 1.0479f, -0.0308f },
+ { 0.4458f, -0.2134f },
+ { 0.1274f, -0.1304f },
+ { 0.8921f, -0.2202f },
+ { 0.4248f, -0.0273f },
+ { 0.5732f, -0.0073f },
+ { 0.2832f, 0.0259f },
+ { 0.9771f, 0.3452f },
+ { 0.4741f, 0.1924f },
+ { 0.1982f, -0.0073f },
+ { -0.0566f, 0.0225f },
+ { 0.5308f, 0.1426f },
+ { 0.1841f, 0.1792f },
+ { 1.4692f, 0.1084f },
+ { 0.7202f, 0.1387f },
+ { 1.8579f, 0.2144f },
+ { 1.4692f, 0.4258f },
+ { 0.6553f, 0.0542f },
+ { 0.2373f, 0.0630f },
+ { 1.2026f, 0.1235f },
+ { 0.6118f, 0.2656f },
+ { 0.8711f, 0.5254f },
+ { 0.3887f, 0.3262f },
+ { 1.5845f, 0.8184f },
+ { 0.7993f, 0.7397f },
+ { 0.3599f, 0.2563f },
+ { 0.0288f, 0.2900f },
+ { 1.1089f, 0.5947f },
+ { 0.2661f, 0.6797f },
+ { 0.0000f, -0.4746f },
+ { -0.6055f, -0.4746f },
+ { 0.2271f, -0.2246f },
+ { -0.0908f, -0.2759f },
+ { -0.3105f, -0.7300f },
+ { -1.0898f, -0.7383f },
+ { -0.1665f, -0.3325f },
+ { -0.6963f, -0.6392f },
+ { -0.3711f, -0.2617f },
+ { -0.9312f, -0.2646f },
+ { 0.0527f, -0.0264f },
+ { -0.3784f, -0.0347f },
+ { -1.2490f, -0.3608f },
+ { -1.6650f, -0.2192f },
+ { -0.4771f, -0.0972f },
+ { -1.2339f, -0.0688f },
+ { 0.0791f, -0.1548f },
+ { -0.2896f, -0.1143f },
+ { 0.3613f, -0.0171f },
+ { 0.0645f, 0.0635f },
+ { -0.2827f, -0.1880f },
+ { -0.7744f, -0.1377f },
+ { 0.0068f, -0.0239f },
+ { -0.3115f, 0.0737f },
+ { -0.1597f, 0.1206f },
+ { -0.6079f, 0.2114f },
+ { 0.1514f, 0.2349f },
+ { -0.1377f, 0.2886f },
+ { -0.7959f, 0.1172f },
+ { -1.4468f, 0.2446f },
+ { -0.2681f, 0.2515f },
+ { -0.6802f, 0.6611f },
+ { 0.2607f, -0.7041f },
+ { 0.0327f, -0.6387f },
+ { 0.5161f, -0.5391f },
+ { 0.2495f, -0.2993f },
+ { -0.0396f, -0.8564f },
+ { -0.5337f, -0.9341f },
+ { 0.1938f, -0.3677f },
+ { -0.1504f, -0.4458f },
+ { 0.0996f, -0.2900f },
+ { -0.3613f, -0.3833f },
+ { 0.3105f, -0.1499f },
+ { -0.0337f, -0.1528f },
+ { -0.3950f, -0.5513f },
+ { -0.8667f, -0.4736f },
+ { -0.0728f, -0.2061f },
+ { -0.6001f, -0.2588f },
+ { 0.3052f, -0.2334f },
+ { 0.0190f, -0.1802f },
+ { 0.5674f, -0.1064f },
+ { 0.2954f, -0.0176f },
+ { 0.0190f, -0.3257f },
+ { -0.2622f, -0.2900f },
+ { 0.2715f, -0.1104f },
+ { 0.0386f, -0.0684f },
+ { 0.1646f, -0.0327f },
+ { -0.1509f, 0.0356f },
+ { 0.3687f, 0.1226f },
+ { 0.1357f, 0.1450f },
+ { -0.1606f, -0.0366f },
+ { -0.6406f, 0.0317f },
+ { 0.1064f, 0.0508f },
+ { -0.2524f, 0.1470f },
+ { 0.3076f, -0.3652f },
+ { -0.0127f, -0.2559f },
+ { 0.5674f, -0.2183f },
+ { 0.2593f, -0.1772f },
+ { -0.0728f, -0.3652f },
+ { -0.5020f, -0.3599f },
+ { 0.2173f, -0.1421f },
+ { -0.1211f, -0.1494f },
+ { 0.1206f, -0.0752f },
+ { -0.2178f, -0.0825f },
+ { 0.3682f, 0.0386f },
+ { 0.0903f, 0.1055f },
+ { -0.3750f, -0.1440f },
+ { -0.9429f, -0.0474f },
+ { 0.0420f, 0.0200f },
+ { -0.3994f, 0.0850f },
+ { 0.3906f, -0.0649f },
+ { 0.0894f, 0.0044f },
+ { 0.8457f, 0.1577f },
+ { 0.3140f, 0.1484f },
+ { 0.0830f, -0.0513f },
+ { -0.2886f, -0.0234f },
+ { 0.3394f, 0.0811f },
+ { 0.0381f, 0.1064f },
+ { 0.2114f, 0.1411f },
+ { -0.1025f, 0.1948f },
+ { 0.4805f, 0.2852f },
+ { 0.1602f, 0.3687f },
+ { -0.1733f, 0.1948f },
+ { -0.7690f, 0.3433f },
+ { 0.1343f, 0.3013f },
+ { -0.2310f, 0.5215f },
+ { 0.6050f, -0.7075f },
+ { 0.3267f, -0.4951f },
+ { 1.3008f, -0.4463f },
+ { 0.6958f, -0.4771f },
+ { 0.1597f, -0.5156f },
+ { -0.1743f, -0.5640f },
+ { 0.5913f, -0.3438f },
+ { 0.1597f, -0.2539f },
+ { 0.3896f, -0.2974f },
+ { 0.1113f, -0.2002f },
+ { 0.6606f, -0.1616f },
+ { 0.3198f, -0.0669f },
+ { 0.0483f, -0.2310f },
+ { -0.4453f, -0.2080f },
+ { 0.2642f, -0.0645f },
+ { -0.0073f, -0.0747f },
+ { 0.7197f, -0.2764f },
+ { 0.3511f, -0.1099f },
+ { 1.2910f, -0.1123f },
+ { 0.7676f, 0.0303f },
+ { 0.3687f, -0.1958f },
+ { 0.0234f, -0.1172f },
+ { 0.7617f, -0.1240f },
+ { 0.3213f, 0.0303f },
+ { 0.4761f, 0.0352f },
+ { 0.1543f, 0.0615f },
+ { 0.8208f, 0.3232f },
+ { 0.4224f, 0.2378f },
+ { 0.1606f, 0.0112f },
+ { -0.1904f, 0.0664f },
+ { 0.4165f, 0.1494f },
+ { 0.1187f, 0.1948f },
+};
+
+/*! \brief PRBA[3:4] Sum vector quantization table */
+const float ir77_ambe_prba_sum34_vq[64][2] = {
+ { 0.7690f, 0.1548f },
+ { 0.3657f, 0.2974f },
+ { 0.4819f, -0.1167f },
+ { 0.2837f, 0.0547f },
+ { 0.5605f, 0.3843f },
+ { 0.2563f, 0.4556f },
+ { 0.3315f, 0.1514f },
+ { 0.0171f, 0.1743f },
+ { 0.6904f, -0.1558f },
+ { 0.3452f, -0.0488f },
+ { 0.4956f, -0.3496f },
+ { 0.2017f, -0.2012f },
+ { 0.4170f, 0.0449f },
+ { 0.2085f, 0.1289f },
+ { 0.2598f, -0.1104f },
+ { -0.0957f, -0.0425f },
+ { 0.4995f, 0.1812f },
+ { 0.1172f, 0.2080f },
+ { 0.2231f, -0.0186f },
+ { -0.0493f, 0.0181f },
+ { 0.1245f, 0.3232f },
+ { -0.0117f, 0.4590f },
+ { 0.0073f, 0.0815f },
+ { -0.1665f, 0.2837f },
+ { 0.3633f, -0.1968f },
+ { 0.0640f, -0.0786f },
+ { 0.1094f, -0.2900f },
+ { -0.1592f, -0.2900f },
+ { 0.0791f, 0.0513f },
+ { -0.0723f, 0.0996f },
+ { -0.0078f, -0.1392f },
+ { -0.4541f, -0.0605f },
+ { 0.5718f, 0.0234f },
+ { 0.0967f, 0.1221f },
+ { 0.1611f, -0.0962f },
+ { -0.0205f, -0.0601f },
+ { 0.2334f, 0.2417f },
+ { -0.0122f, 0.2778f },
+ { 0.0322f, -0.0034f },
+ { -0.3062f, 0.1792f },
+ { 0.2817f, -0.3203f },
+ { 0.0967f, -0.1621f },
+ { 0.1450f, -0.4668f },
+ { -0.0322f, -0.3652f },
+ { 0.1206f, -0.0156f },
+ { -0.1450f, 0.0322f },
+ { -0.0806f, -0.2246f },
+ { -0.4351f, -0.2217f },
+ { 0.1660f, 0.0557f },
+ { -0.1880f, 0.1260f },
+ { -0.0991f, -0.1270f },
+ { -0.3154f, -0.1235f },
+ { -0.0889f, 0.1855f },
+ { -0.3115f, 0.4067f },
+ { -0.2407f, -0.0005f },
+ { -0.5278f, 0.1504f },
+ { 0.0244f, -0.2319f },
+ { -0.2021f, -0.1865f },
+ { -0.2124f, -0.4775f },
+ { -0.5098f, -0.4111f },
+ { -0.1880f, -0.0845f },
+ { -0.3506f, 0.0313f },
+ { -0.3081f, -0.2881f },
+ { -0.7222f, -0.1060f },
+};
+
+/*! \brief PRBA[5:7] Sum vector quantization table */
+const float ir77_ambe_prba_sum57_vq[128][3] = {
+ { -0.0352f, -0.0244f, -0.1870f },
+ { -0.1187f, -0.0645f, -0.2529f },
+ { 0.0903f, -0.0566f, -0.0991f },
+ { 0.0205f, -0.0483f, -0.1104f },
+ { -0.2021f, -0.0806f, -0.1431f },
+ { -0.2993f, -0.1128f, -0.1104f },
+ { -0.0562f, -0.0083f, 0.0215f },
+ { -0.0840f, -0.0645f, -0.0005f },
+ { -0.0142f, 0.1045f, -0.1543f },
+ { 0.0137f, 0.0400f, -0.1211f },
+ { 0.1387f, 0.0806f, -0.0332f },
+ { 0.1182f, 0.0322f, -0.0884f },
+ { -0.1396f, 0.1289f, -0.0552f },
+ { -0.1675f, 0.0322f, -0.0444f },
+ { 0.0205f, 0.1128f, 0.0767f },
+ { -0.0073f, 0.0483f, 0.0435f },
+ { -0.1235f, 0.1519f, -0.1816f },
+ { -0.1157f, 0.0474f, -0.1377f },
+ { 0.0610f, 0.1235f, -0.0825f },
+ { 0.0303f, 0.0664f, -0.0386f },
+ { -0.2539f, 0.0757f, -0.1484f },
+ { -0.3154f, 0.0947f, -0.0278f },
+ { -0.0850f, 0.1328f, 0.0601f },
+ { -0.1001f, 0.0474f, 0.0601f },
+ { 0.0381f, 0.2568f, -0.1924f },
+ { -0.0313f, 0.1899f, -0.0605f },
+ { 0.1611f, 0.3423f, -0.0278f },
+ { 0.1074f, 0.2188f, -0.0386f },
+ { -0.1157f, 0.3042f, -0.0605f },
+ { -0.1924f, 0.2378f, 0.0493f },
+ { 0.0229f, 0.2949f, 0.1479f },
+ { -0.0156f, 0.2188f, 0.0601f },
+ { 0.0723f, -0.1597f, -0.2695f },
+ { 0.0562f, -0.1313f, -0.1738f },
+ { 0.2573f, -0.1807f, -0.1860f },
+ { 0.2495f, -0.1240f, -0.0542f },
+ { -0.0649f, -0.0957f, -0.1260f },
+ { -0.1211f, -0.1665f, -0.0903f },
+ { 0.0400f, -0.0674f, -0.0186f },
+ { 0.0400f, -0.1382f, -0.0063f },
+ { 0.2334f, -0.0039f, -0.2339f },
+ { 0.1768f, -0.0674f, -0.1382f },
+ { 0.3784f, -0.0107f, -0.1260f },
+ { 0.3140f, 0.0034f, 0.0054f },
+ { 0.0479f, 0.0034f, -0.0542f },
+ { -0.0005f, 0.0103f, -0.0186f },
+ { 0.2012f, 0.0317f, 0.0415f },
+ { 0.1123f, -0.0107f, 0.1011f },
+ { 0.0703f, 0.0977f, -0.2432f },
+ { 0.0845f, 0.0039f, -0.1934f },
+ { 0.2476f, 0.0635f, -0.0688f },
+ { 0.2051f, -0.0132f, -0.0439f },
+ { -0.0498f, 0.0039f, -0.0815f },
+ { -0.0781f, 0.0039f, -0.0317f },
+ { 0.0776f, 0.0552f, 0.0181f },
+ { 0.0493f, 0.0039f, 0.0308f },
+ { 0.2402f, 0.2090f, -0.1685f },
+ { 0.1694f, 0.1064f, -0.1313f },
+ { 0.3608f, 0.2002f, -0.0068f },
+ { 0.2192f, 0.1489f, 0.0181f },
+ { 0.0845f, 0.1489f, 0.0181f },
+ { -0.0005f, 0.1318f, 0.0059f },
+ { 0.1978f, 0.2432f, 0.1426f },
+ { 0.0986f, 0.1577f, 0.1426f },
+ { -0.0684f, -0.1797f, -0.1621f },
+ { -0.1973f, -0.2529f, -0.1621f },
+ { 0.0298f, -0.2310f, 0.0122f },
+ { -0.0459f, -0.1870f, 0.0122f },
+ { -0.2349f, -0.2017f, -0.0127f },
+ { -0.3711f, -0.2456f, -0.0376f },
+ { -0.1367f, -0.2017f, 0.0991f },
+ { -0.2651f, -0.2603f, 0.1489f },
+ { -0.0308f, -0.0479f, -0.0503f },
+ { -0.0459f, -0.1138f, -0.0503f },
+ { 0.0981f, -0.0698f, 0.0371f },
+ { 0.0449f, -0.0845f, 0.0620f },
+ { -0.1440f, -0.0332f, 0.0244f },
+ { -0.2046f, -0.1064f, 0.0742f },
+ { -0.0762f, -0.0405f, 0.1616f },
+ { -0.1138f, -0.1357f, 0.2114f },
+ { -0.1118f, -0.0513f, -0.0820f },
+ { -0.1714f, -0.0854f, -0.0410f },
+ { -0.0005f, -0.0376f, 0.0308f },
+ { -0.0522f, -0.0444f, 0.0718f },
+ { -0.2534f, -0.0376f, 0.0000f },
+ { -0.3203f, -0.0786f, 0.1128f },
+ { -0.1567f, -0.0239f, 0.1128f },
+ { -0.2012f, -0.0171f, 0.2256f },
+ { -0.0522f, 0.0854f, -0.0718f },
+ { -0.0674f, 0.0649f, -0.0103f },
+ { 0.1411f, 0.0854f, 0.0923f },
+ { 0.0591f, 0.0513f, 0.1025f },
+ { -0.1865f, 0.0649f, 0.0513f },
+ { -0.2759f, 0.0991f, 0.1436f },
+ { -0.0078f, 0.1196f, 0.1948f },
+ { -0.1196f, 0.0786f, 0.1743f },
+ { 0.0732f, -0.2876f, -0.1118f },
+ { -0.0332f, -0.3340f, -0.2012f },
+ { 0.2451f, -0.2876f, -0.0225f },
+ { 0.1060f, -0.3525f, 0.0669f },
+ { -0.0903f, -0.2783f, -0.0225f },
+ { -0.1719f, -0.3804f, 0.0220f },
+ { 0.0649f, -0.2134f, 0.1265f },
+ { -0.0410f, -0.2876f, 0.1563f },
+ { 0.1226f, -0.1021f, -0.0376f },
+ { 0.1226f, -0.1855f, -0.0674f },
+ { 0.3350f, -0.1299f, 0.0815f },
+ { 0.2124f, -0.1855f, 0.1113f },
+ { -0.0249f, -0.1021f, 0.0371f },
+ { 0.0078f, -0.1577f, 0.0669f },
+ { 0.1226f, -0.1021f, 0.1411f },
+ { 0.0898f, -0.1577f, 0.2603f },
+ { 0.0273f, -0.1265f, -0.0791f },
+ { -0.0137f, -0.1987f, -0.0791f },
+ { 0.1846f, -0.0723f, 0.0469f },
+ { 0.1299f, -0.1626f, 0.0361f },
+ { -0.0957f, -0.1177f, 0.0679f },
+ { -0.1230f, -0.1538f, 0.0049f },
+ { 0.0205f, -0.0903f, 0.1411f },
+ { -0.0410f, -0.1265f, 0.1309f },
+ { 0.1299f, 0.0088f, 0.0151f },
+ { 0.1025f, -0.0273f, -0.0269f },
+ { 0.3076f, 0.0811f, 0.1621f },
+ { 0.2188f, -0.0273f, 0.1411f },
+ { 0.0205f, -0.0093f, 0.1099f },
+ { -0.0410f, 0.0361f, 0.1099f },
+ { 0.1299f, 0.0449f, 0.2358f },
+ { 0.0205f, -0.0093f, 0.2358f },
+};
+
+/*! \brief PRBA[1:3] Difference vector quantization table */
+const float ir77_ambe_prba_dif13_vq[256][3] = {
+ { -0.0952f, 0.0181f, 0.0547f },
+ { -0.2441f, -0.0371f, 0.0547f },
+ { -0.2983f, -0.1104f, 0.1401f },
+ { -0.6504f, -0.2017f, 0.0303f },
+ { -0.2036f, 0.0181f, -0.1162f },
+ { -0.4746f, 0.0361f, -0.1650f },
+ { -0.5962f, -0.0552f, -0.0918f },
+ { -0.8130f, -0.2017f, -0.1650f },
+ { 0.0269f, -0.0552f, 0.0059f },
+ { -0.1357f, -0.0918f, -0.0430f },
+ { -0.0815f, -0.2202f, 0.0791f },
+ { -0.3252f, -0.2568f, -0.0430f },
+ { -0.0679f, -0.0552f, -0.0796f },
+ { -0.2983f, -0.1470f, -0.2383f },
+ { -0.3389f, -0.2935f, -0.1772f },
+ { -0.5830f, -0.5313f, -0.2139f },
+ { -0.0640f, 0.1646f, 0.0581f },
+ { -0.1914f, 0.1523f, 0.0400f },
+ { -0.1489f, 0.0791f, 0.0674f },
+ { -0.4995f, 0.0791f, 0.0220f },
+ { -0.1382f, 0.1768f, -0.0591f },
+ { -0.3823f, 0.2622f, -0.1494f },
+ { -0.3506f, 0.1279f, -0.0591f },
+ { -0.5947f, 0.1890f, -0.1313f },
+ { 0.0635f, 0.0303f, 0.0132f },
+ { -0.0215f, 0.0059f, -0.0229f },
+ { -0.0107f, -0.0308f, 0.0400f },
+ { -0.1807f, -0.0552f, -0.0049f },
+ { 0.0210f, 0.0547f, -0.0771f },
+ { -0.1489f, 0.0791f, -0.1855f },
+ { -0.1274f, -0.0063f, -0.0684f },
+ { -0.4146f, -0.1040f, -0.2036f },
+ { 0.0640f, 0.0166f, -0.0391f },
+ { -0.0771f, 0.0166f, -0.0498f },
+ { -0.0771f, -0.0845f, 0.0049f },
+ { -0.2949f, -0.1743f, -0.1157f },
+ { -0.0259f, 0.0391f, -0.0718f },
+ { -0.3081f, 0.0391f, -0.1709f },
+ { -0.2695f, -0.0845f, -0.1489f },
+ { -0.6025f, -0.1294f, -0.3354f },
+ { 0.1919f, -0.0620f, -0.0718f },
+ { -0.0005f, -0.0732f, -0.1050f },
+ { 0.1152f, -0.1631f, -0.0278f },
+ { -0.1924f, -0.2305f, -0.0938f },
+ { 0.0640f, -0.0508f, -0.1270f },
+ { -0.0898f, -0.1743f, -0.2915f },
+ { -0.0645f, -0.1069f, -0.1377f },
+ { -0.4106f, -0.2979f, -0.3354f },
+ { 0.1538f, 0.1621f, -0.0771f },
+ { -0.0122f, 0.1157f, -0.0659f },
+ { -0.0239f, 0.0415f, 0.0107f },
+ { -0.1304f, 0.0693f, -0.0771f },
+ { -0.0356f, 0.2085f, -0.1318f },
+ { -0.2251f, 0.1714f, -0.1978f },
+ { -0.0596f, 0.1250f, -0.1099f },
+ { -0.2251f, -0.0049f, -0.3296f },
+ { 0.5088f, 0.1343f, -0.0991f },
+ { 0.0942f, 0.0415f, -0.1099f },
+ { 0.1416f, -0.0234f, -0.0332f },
+ { -0.0239f, -0.0234f, -0.0659f },
+ { 0.2363f, 0.0415f, -0.2856f },
+ { -0.0239f, 0.0322f, -0.2856f },
+ { 0.1299f, -0.0049f, -0.1978f },
+ { -0.1777f, -0.0698f, -0.2090f },
+ { 0.0327f, -0.0645f, 0.0557f },
+ { -0.0991f, -0.1289f, 0.0557f },
+ { -0.0552f, -0.1450f, 0.1528f },
+ { -0.3955f, -0.2900f, 0.1670f },
+ { -0.0659f, -0.0483f, -0.0278f },
+ { -0.2310f, -0.0806f, -0.0698f },
+ { -0.3076f, -0.1450f, 0.0000f },
+ { -0.5054f, -0.2739f, -0.1113f },
+ { 0.1758f, -0.2095f, 0.0557f },
+ { 0.0439f, -0.2095f, 0.0000f },
+ { 0.0547f, -0.3545f, 0.0835f },
+ { -0.2090f, -0.4028f, -0.0420f },
+ { 0.0767f, -0.0967f, -0.0835f },
+ { -0.0771f, -0.2256f, -0.1533f },
+ { -0.0659f, -0.2900f, -0.0142f },
+ { -0.2417f, -0.5317f, -0.2505f },
+ { 0.1348f, 0.0659f, 0.1279f },
+ { -0.0391f, 0.0132f, 0.0337f },
+ { 0.0190f, -0.0132f, 0.0767f },
+ { -0.1353f, -0.0483f, 0.0679f },
+ { 0.0288f, 0.0659f, -0.0259f },
+ { -0.2222f, 0.1011f, -0.0688f },
+ { -0.0581f, 0.0044f, -0.0088f },
+ { -0.3184f, -0.0220f, -0.0771f },
+ { 0.2891f, -0.0308f, -0.0347f },
+ { 0.0767f, -0.0659f, -0.0005f },
+ { 0.0576f, -0.1099f, 0.0425f },
+ { -0.0391f, -0.1626f, -0.0176f },
+ { 0.2217f, 0.0044f, -0.1113f },
+ { 0.0288f, -0.0044f, -0.0859f },
+ { -0.0098f, -0.1099f, -0.0518f },
+ { -0.1548f, -0.1450f, -0.1284f },
+ { 0.2119f, -0.0366f, 0.0127f },
+ { 0.0381f, -0.0610f, -0.0522f },
+ { 0.0576f, -0.1221f, -0.0132f },
+ { -0.1162f, -0.1831f, -0.0264f },
+ { 0.0864f, -0.0244f, -0.0522f },
+ { -0.0581f, -0.0366f, -0.1816f },
+ { -0.0776f, -0.1221f, -0.0649f },
+ { -0.2026f, -0.2441f, -0.2334f },
+ { 0.3950f, -0.2686f, -0.1040f },
+ { 0.1445f, -0.1587f, -0.1167f },
+ { 0.1924f, -0.2686f, -0.0522f },
+ { -0.0005f, -0.4028f, -0.1558f },
+ { 0.2407f, -0.2319f, -0.2202f },
+ { 0.0962f, -0.1343f, -0.3110f },
+ { 0.0767f, -0.2686f, -0.1816f },
+ { 0.0288f, -0.3784f, -0.3755f },
+ { 0.4521f, 0.1436f, 0.0801f },
+ { 0.0879f, 0.0601f, -0.0103f },
+ { 0.1504f, 0.0137f, 0.0200f },
+ { -0.0005f, -0.0142f, 0.0000f },
+ { 0.1758f, 0.0972f, -0.1304f },
+ { 0.0122f, 0.1064f, -0.1304f },
+ { 0.0122f, 0.0229f, -0.0400f },
+ { -0.0630f, 0.0322f, -0.1201f },
+ { 0.7163f, -0.0513f, -0.0400f },
+ { 0.3140f, 0.0601f, -0.1001f },
+ { 0.2510f, -0.1348f, -0.0703f },
+ { 0.1255f, -0.0884f, -0.0400f },
+ { 0.5151f, -0.0327f, -0.2202f },
+ { 0.3140f, -0.0698f, -0.1904f },
+ { 0.1504f, -0.0791f, -0.1504f },
+ { 0.0249f, -0.1162f, -0.1802f },
+ { 0.0000f, 0.0762f, 0.1948f },
+ { -0.1685f, 0.0923f, 0.1831f },
+ { -0.0986f, -0.0044f, 0.2637f },
+ { -0.4917f, 0.0278f, 0.2061f },
+ { -0.1123f, 0.1162f, 0.0225f },
+ { -0.3369f, 0.1084f, 0.0571f },
+ { -0.3511f, 0.0117f, 0.1372f },
+ { -0.7300f, 0.0679f, 0.0913f },
+ { 0.1401f, -0.0288f, 0.0913f },
+ { -0.0562f, -0.0127f, 0.0801f },
+ { 0.0000f, -0.0366f, 0.1719f },
+ { -0.1826f, -0.1172f, 0.1260f },
+ { 0.0137f, 0.0195f, -0.0005f },
+ { -0.1548f, 0.0278f, -0.0234f },
+ { -0.1968f, -0.1333f, -0.0005f },
+ { -0.4355f, -0.1333f, -0.0806f },
+ { 0.0513f, 0.3936f, 0.2974f },
+ { -0.0308f, 0.2158f, 0.1641f },
+ { -0.0410f, 0.1650f, 0.2974f },
+ { -0.2871f, 0.1143f, 0.2256f },
+ { 0.0103f, 0.3301f, 0.0308f },
+ { -0.2256f, 0.3174f, 0.1333f },
+ { -0.2051f, 0.1777f, 0.1333f },
+ { -0.4204f, 0.2285f, 0.1128f },
+ { 0.2256f, 0.1523f, 0.1538f },
+ { 0.0308f, 0.1396f, 0.0615f },
+ { 0.0718f, 0.0000f, 0.1641f },
+ { -0.1128f, 0.0381f, 0.1128f },
+ { 0.0718f, 0.1396f, -0.0103f },
+ { -0.0718f, 0.1396f, -0.0205f },
+ { -0.0718f, 0.0762f, 0.0615f },
+ { -0.2563f, 0.0254f, 0.0000f },
+ { 0.1553f, 0.1582f, 0.0601f },
+ { -0.0132f, 0.0791f, 0.0415f },
+ { -0.0259f, 0.0352f, 0.0786f },
+ { -0.1943f, -0.0088f, 0.1436f },
+ { 0.0127f, 0.1143f, 0.0044f },
+ { -0.1426f, 0.1055f, -0.0234f },
+ { -0.0776f, 0.0527f, 0.0044f },
+ { -0.3882f, -0.0352f, 0.0044f },
+ { 0.4141f, 0.0264f, 0.0137f },
+ { 0.0903f, 0.0000f, 0.0044f },
+ { 0.1294f, -0.1143f, 0.0508f },
+ { -0.0259f, -0.0879f, 0.0229f },
+ { 0.1294f, 0.0439f, -0.0605f },
+ { 0.0127f, 0.0176f, -0.1440f },
+ { 0.0127f, -0.0176f, -0.0420f },
+ { -0.1426f, -0.0527f, -0.1348f },
+ { 0.3652f, 0.4199f, 0.2012f },
+ { 0.0752f, 0.2261f, 0.0620f },
+ { 0.0645f, 0.1484f, 0.1318f },
+ { -0.0859f, 0.1353f, 0.1318f },
+ { 0.1074f, 0.2778f, -0.0908f },
+ { -0.1611f, 0.3164f, -0.1465f },
+ { 0.0000f, 0.1743f, 0.0063f },
+ { -0.2363f, 0.2261f, -0.0073f },
+ { 0.4297f, 0.3555f, -0.0073f },
+ { 0.2686f, 0.1484f, 0.0063f },
+ { 0.2148f, 0.0576f, 0.0762f },
+ { 0.0000f, 0.0190f, 0.0342f },
+ { 0.2578f, 0.2905f, -0.2300f },
+ { 0.0752f, 0.1353f, -0.2163f },
+ { 0.0752f, 0.0967f, -0.0630f },
+ { -0.0645f, 0.0835f, -0.0493f },
+ { 0.1206f, -0.0054f, 0.2803f },
+ { -0.0005f, 0.0244f, 0.1187f },
+ { 0.0117f, -0.1255f, 0.2520f },
+ { -0.2422f, -0.0654f, 0.2710f },
+ { 0.0479f, 0.0347f, 0.0615f },
+ { -0.1694f, 0.0244f, 0.0327f },
+ { -0.0972f, -0.0454f, 0.1470f },
+ { -0.4473f, -0.1455f, 0.0708f },
+ { 0.3018f, -0.1157f, 0.2329f },
+ { 0.1084f, -0.1055f, 0.1567f },
+ { 0.1206f, -0.2456f, 0.1851f },
+ { -0.1572f, -0.2656f, 0.2041f },
+ { 0.1328f, -0.0557f, 0.0234f },
+ { -0.0122f, -0.0654f, -0.0146f },
+ { -0.0122f, -0.1357f, 0.0708f },
+ { -0.2300f, -0.2358f, 0.0518f },
+ { 0.2588f, 0.2451f, 0.3184f },
+ { 0.1294f, 0.1494f, 0.2231f },
+ { 0.2588f, 0.1016f, 0.2900f },
+ { -0.0581f, 0.0415f, 0.1567f },
+ { 0.1724f, 0.2930f, 0.1377f },
+ { -0.1157f, 0.2451f, 0.0234f },
+ { -0.0005f, 0.1016f, 0.0996f },
+ { -0.2163f, 0.0654f, 0.0996f },
+ { 0.6768f, 0.0654f, 0.2422f },
+ { 0.2158f, 0.0059f, 0.1470f },
+ { 0.3022f, 0.0537f, 0.1758f },
+ { 0.0571f, -0.0659f, 0.1089f },
+ { 0.3164f, 0.0776f, 0.0518f },
+ { 0.0430f, 0.0654f, 0.0234f },
+ { 0.0859f, -0.0181f, 0.0615f },
+ { -0.0581f, -0.0420f, 0.0327f },
+ { 0.4556f, 0.0659f, 0.2202f },
+ { 0.1211f, 0.0396f, 0.0562f },
+ { 0.2124f, -0.1187f, 0.1279f },
+ { -0.0308f, -0.0659f, 0.0869f },
+ { 0.1514f, 0.1055f, -0.0054f },
+ { -0.0205f, 0.0527f, -0.0259f },
+ { 0.0400f, -0.0132f, 0.0356f },
+ { -0.1016f, -0.0132f, -0.0054f },
+ { 0.5264f, -0.2637f, 0.0562f },
+ { 0.3340f, -0.1582f, 0.0459f },
+ { 0.3135f, -0.3032f, 0.1074f },
+ { 0.0605f, -0.1714f, 0.0972f },
+ { 0.4253f, -0.0791f, -0.0771f },
+ { 0.1211f, -0.0264f, -0.0977f },
+ { 0.1919f, -0.1187f, 0.0049f },
+ { 0.0200f, -0.1714f, -0.0977f },
+ { 0.6699f, 0.3623f, 0.1587f },
+ { 0.4766f, 0.2549f, 0.2202f },
+ { 0.3276f, 0.2280f, 0.1382f },
+ { 0.0596f, 0.0532f, 0.1074f },
+ { 0.2231f, 0.2549f, 0.0049f },
+ { 0.0298f, 0.1875f, -0.0669f },
+ { 0.0894f, 0.0938f, 0.0459f },
+ { -0.0298f, 0.0938f, 0.0049f },
+ { 0.8936f, 0.1206f, -0.0156f },
+ { 0.6255f, 0.1475f, 0.0767f },
+ { 0.4912f, -0.0405f, 0.0869f },
+ { 0.2979f, -0.0405f, 0.0767f },
+ { 0.6553f, 0.2817f, -0.0874f },
+ { 0.3276f, 0.1606f, -0.0977f },
+ { 0.2085f, 0.0400f, -0.0259f },
+ { 0.0444f, -0.0273f, -0.0054f },
+};
+
+/*! \brief PRBA[4:7] Difference vector quantization table */
+const float ir77_ambe_prba_dif47_vq[64][4] = {
+ { 0.0044f, 0.0229f, 0.0151f, -0.0024f },
+ { 0.0044f, -0.0298f, 0.0239f, 0.0142f },
+ { -0.0308f, 0.0757f, -0.0815f, -0.0356f },
+ { -0.0483f, -0.0298f, -0.0464f, -0.0107f },
+ { 0.0747f, 0.0098f, 0.0151f, -0.0439f },
+ { 0.1099f, -0.0825f, 0.0327f, -0.0605f },
+ { 0.0747f, 0.0361f, -0.0640f, -0.0938f },
+ { 0.0396f, -0.0562f, -0.0376f, -0.0605f },
+ { -0.0659f, -0.0166f, 0.0327f, 0.0059f },
+ { -0.0835f, -0.1089f, 0.0151f, 0.0225f },
+ { -0.1362f, -0.0034f, -0.0903f, -0.0356f },
+ { -0.1538f, -0.1221f, -0.0991f, -0.0356f },
+ { -0.0132f, -0.0298f, 0.0151f, -0.0356f },
+ { 0.0044f, -0.1089f, 0.0151f, -0.0273f },
+ { -0.0308f, -0.0298f, -0.0991f, -0.0938f },
+ { -0.0483f, -0.1221f, -0.0728f, -0.0522f },
+ { -0.0127f, 0.0991f, 0.0933f, -0.0137f },
+ { -0.0293f, 0.0142f, 0.0767f, 0.0000f },
+ { -0.0791f, 0.1416f, -0.0063f, -0.0137f },
+ { -0.0625f, 0.0425f, 0.0020f, 0.0000f },
+ { 0.0703f, 0.0566f, 0.0850f, -0.0820f },
+ { 0.0371f, -0.0142f, 0.0767f, -0.0615f },
+ { 0.0039f, 0.1133f, 0.0103f, -0.0889f },
+ { 0.0039f, 0.0142f, -0.0063f, -0.0615f },
+ { -0.1289f, 0.0708f, 0.1016f, 0.0137f },
+ { -0.1289f, -0.0425f, 0.1099f, 0.0000f },
+ { -0.1787f, 0.0708f, 0.0186f, -0.0410f },
+ { -0.1787f, -0.0425f, 0.0020f, 0.0068f },
+ { -0.0625f, 0.0283f, 0.0684f, -0.0752f },
+ { -0.0459f, -0.0708f, 0.1016f, -0.0615f },
+ { -0.0791f, 0.0425f, -0.0146f, -0.0820f },
+ { -0.0791f, -0.0566f, 0.0020f, -0.0684f },
+ { 0.0981f, 0.0474f, -0.0029f, 0.0791f },
+ { 0.0640f, -0.0288f, 0.0186f, 0.0688f },
+ { 0.0640f, 0.0601f, -0.0996f, 0.0483f },
+ { 0.0298f, -0.0288f, -0.0674f, 0.0688f },
+ { 0.1836f, 0.0093f, -0.0029f, -0.0234f },
+ { 0.1665f, -0.0796f, 0.0186f, 0.0483f },
+ { 0.1494f, 0.0347f, -0.1104f, -0.0439f },
+ { 0.1152f, -0.0542f, -0.0781f, 0.0278f },
+ { -0.0044f, -0.0161f, 0.0078f, 0.0791f },
+ { -0.0044f, -0.1050f, -0.0029f, 0.1099f },
+ { -0.0386f, 0.0220f, -0.0996f, 0.0483f },
+ { -0.0728f, -0.0923f, -0.1211f, 0.0483f },
+ { 0.0640f, -0.0415f, 0.0078f, -0.0029f },
+ { 0.0640f, -0.1304f, 0.0400f, 0.0278f },
+ { 0.0298f, -0.0161f, -0.0996f, -0.0132f },
+ { 0.0469f, -0.1304f, -0.0996f, 0.0073f },
+ { 0.0684f, 0.1128f, 0.0811f, 0.0586f },
+ { 0.0171f, 0.0151f, 0.0996f, 0.0732f },
+ { 0.0000f, 0.1128f, -0.0396f, 0.0586f },
+ { 0.0000f, 0.0273f, -0.0117f, 0.0513f },
+ { 0.1538f, 0.1250f, 0.0625f, 0.0000f },
+ { 0.1196f, 0.0029f, 0.0903f, 0.0146f },
+ { 0.0684f, 0.1128f, -0.0303f, -0.0146f },
+ { 0.0684f, 0.0151f, -0.0303f, 0.0073f },
+ { -0.0513f, 0.0640f, 0.0439f, 0.0732f },
+ { -0.0854f, -0.0337f, 0.0811f, 0.0952f },
+ { -0.1025f, 0.0640f, -0.0303f, 0.0586f },
+ { -0.0854f, -0.0215f, -0.0210f, 0.0659f },
+ { 0.0342f, 0.0518f, 0.0439f, 0.0073f },
+ { 0.0342f, -0.0581f, 0.0811f, 0.0220f },
+ { 0.0000f, 0.0396f, -0.0396f, -0.0073f },
+ { 0.0000f, -0.0337f, -0.0210f, 0.0146f },
+};
+
+/*! \brief HOC 1st block Sum vector quantization table */
+const float ir77_ambe_hoc0_sum_vq[128][4] = {
+ { -0.1294f, 0.0190f, 0.0112f, -0.0073f },
+ { -0.2329f, 0.0698f, 0.0562f, -0.0630f },
+ { -0.1812f, 0.0952f, 0.0562f, 0.1597f },
+ { -0.3105f, 0.2476f, 0.1909f, 0.0762f },
+ { -0.0259f, 0.0190f, -0.0337f, -0.0073f },
+ { -0.1294f, 0.1206f, -0.0337f, -0.0630f },
+ { -0.0518f, 0.0698f, -0.1011f, 0.0205f },
+ { -0.1035f, 0.2983f, 0.0337f, 0.1040f },
+ { -0.0518f, 0.0698f, 0.0337f, -0.1187f },
+ { -0.1553f, 0.1460f, 0.1011f, -0.1743f },
+ { -0.1035f, 0.1460f, 0.1011f, -0.0073f },
+ { -0.1035f, 0.3491f, 0.2358f, -0.0352f },
+ { 0.0776f, -0.0317f, -0.1011f, -0.1187f },
+ { 0.0518f, 0.1206f, -0.0562f, -0.2578f },
+ { 0.0000f, 0.1460f, -0.0562f, -0.0630f },
+ { 0.0518f, 0.2983f, 0.0112f, -0.1187f },
+ { -0.1416f, 0.0151f, -0.0747f, 0.0493f },
+ { -0.2905f, 0.1665f, 0.0000f, -0.0356f },
+ { -0.2012f, 0.1060f, -0.1245f, 0.1060f },
+ { -0.3799f, 0.2573f, -0.0747f, 0.1060f },
+ { -0.1118f, -0.0757f, -0.2241f, 0.0210f },
+ { -0.2310f, 0.0454f, -0.1245f, -0.0640f },
+ { -0.0225f, 0.0454f, -0.1992f, 0.1626f },
+ { -0.2012f, 0.1968f, -0.2490f, 0.0493f },
+ { -0.0820f, -0.0151f, -0.0996f, -0.0923f },
+ { -0.1714f, 0.1968f, -0.0996f, -0.1772f },
+ { -0.1118f, 0.2271f, -0.0996f, -0.0356f },
+ { -0.2607f, 0.3784f, 0.0000f, -0.1206f },
+ { 0.0669f, -0.0757f, -0.3735f, -0.0640f },
+ { -0.1416f, -0.0151f, -0.2739f, -0.2622f },
+ { 0.0073f, 0.1060f, -0.1992f, -0.0356f },
+ { 0.0073f, 0.3179f, -0.1992f, -0.0356f },
+ { 0.1543f, -0.0957f, 0.1250f, 0.0732f },
+ { 0.0771f, 0.0479f, 0.1250f, 0.0000f },
+ { 0.1929f, 0.0479f, 0.2549f, 0.1709f },
+ { 0.0000f, 0.1914f, 0.2363f, 0.1221f },
+ { 0.2700f, -0.2871f, 0.0137f, 0.1221f },
+ { 0.1929f, 0.0000f, -0.0234f, 0.0244f },
+ { 0.4629f, 0.1436f, 0.0508f, 0.1465f },
+ { 0.1543f, 0.2393f, 0.0508f, 0.2441f },
+ { 0.3086f, 0.0957f, 0.1807f, -0.0244f },
+ { 0.1157f, 0.1436f, 0.1992f, -0.1221f },
+ { 0.3472f, 0.2393f, 0.1992f, 0.1221f },
+ { 0.1929f, 0.3350f, 0.2178f, 0.0244f },
+ { 0.3857f, -0.0957f, 0.0322f, 0.0488f },
+ { 0.3086f, 0.2393f, 0.0322f, -0.1221f },
+ { 0.5786f, 0.2871f, 0.1621f, 0.0488f },
+ { 0.2314f, 0.4307f, -0.0049f, 0.0732f },
+ { 0.1245f, -0.1230f, -0.0464f, 0.0410f },
+ { 0.0532f, -0.0137f, -0.0669f, 0.0410f },
+ { 0.1958f, 0.0137f, -0.0259f, 0.2051f },
+ { 0.0176f, 0.0957f, 0.0356f, 0.1348f },
+ { 0.2671f, -0.1504f, -0.1284f, 0.0176f },
+ { 0.1245f, -0.0137f, -0.1489f, 0.0410f },
+ { 0.3027f, 0.0137f, -0.2104f, 0.1113f },
+ { 0.0889f, 0.1504f, -0.1694f, 0.0879f },
+ { 0.1958f, -0.0410f, 0.0151f, -0.1230f },
+ { 0.1245f, 0.0957f, -0.0464f, -0.0762f },
+ { 0.3027f, 0.1230f, -0.0259f, 0.0176f },
+ { 0.1245f, 0.2051f, 0.0767f, 0.0176f },
+ { 0.4810f, -0.1777f, -0.1899f, -0.0293f },
+ { 0.3027f, -0.0137f, -0.1694f, -0.1465f },
+ { 0.5522f, 0.1230f, -0.0669f, -0.0762f },
+ { 0.2671f, 0.2324f, -0.2310f, -0.0059f },
+ { -0.5029f, -0.1719f, 0.1777f, -0.0068f },
+ { -0.7456f, -0.0996f, 0.0986f, 0.0195f },
+ { -0.4336f, 0.0088f, 0.2041f, 0.1514f },
+ { -0.6763f, 0.2256f, 0.2305f, -0.0068f },
+ { -0.3643f, -0.3164f, -0.0068f, -0.0859f },
+ { -0.5723f, -0.1357f, -0.0596f, -0.0859f },
+ { -0.3643f, 0.0088f, -0.0332f, 0.1250f },
+ { -0.5029f, 0.0811f, 0.0459f, 0.0195f },
+ { -0.3643f, -0.0996f, 0.0723f, -0.1650f },
+ { -0.5723f, 0.0449f, 0.0459f, -0.1914f },
+ { -0.3643f, 0.0088f, 0.1250f, -0.0332f },
+ { -0.3989f, 0.1533f, 0.1514f, -0.1650f },
+ { -0.2603f, -0.2080f, -0.1650f, -0.1650f },
+ { -0.2603f, -0.0273f, -0.0859f, -0.2441f },
+ { -0.2256f, -0.1357f, -0.1387f, -0.0068f },
+ { -0.3643f, 0.0811f, -0.0332f, -0.1650f },
+ { -0.6401f, -0.4102f, -0.0518f, 0.0444f },
+ { -0.9185f, -0.2461f, -0.1035f, -0.1079f },
+ { -0.4731f, -0.1914f, 0.0000f, 0.1460f },
+ { -0.6958f, 0.0273f, -0.1294f, 0.0190f },
+ { -0.3618f, -0.5195f, -0.2847f, -0.1333f },
+ { -0.6401f, -0.3008f, -0.3364f, -0.0825f },
+ { -0.4175f, -0.2461f, -0.1812f, 0.0190f },
+ { -0.4175f, -0.0273f, -0.2070f, 0.0444f },
+ { -0.5288f, -0.3008f, -0.1035f, -0.2349f },
+ { -0.7515f, -0.0273f, -0.1812f, -0.2095f },
+ { -0.3618f, -0.0820f, -0.0518f, -0.0571f },
+ { -0.5288f, 0.3008f, -0.0776f, -0.0825f },
+ { -0.0835f, -0.4102f, -0.3882f, -0.2349f },
+ { -0.4175f, -0.1914f, -0.2847f, -0.2095f },
+ { -0.2505f, -0.1367f, -0.3623f, -0.0825f },
+ { -0.4175f, 0.0820f, -0.2329f, -0.1333f },
+ { -0.1489f, -0.2637f, 0.1646f, 0.0000f },
+ { -0.2681f, -0.1230f, 0.2231f, -0.0864f },
+ { -0.1489f, -0.0527f, 0.2378f, 0.2305f },
+ { -0.2085f, 0.0645f, 0.2378f, 0.0576f },
+ { 0.0298f, -0.2871f, 0.0620f, 0.0576f },
+ { -0.0298f, -0.1465f, 0.0913f, -0.0576f },
+ { 0.0298f, -0.0996f, 0.0474f, 0.1729f },
+ { -0.0894f, -0.0293f, 0.0474f, 0.0864f },
+ { 0.0596f, -0.2637f, 0.2085f, -0.1152f },
+ { -0.1191f, -0.0527f, 0.1792f, -0.2017f },
+ { -0.0298f, -0.0762f, 0.1938f, 0.0288f },
+ { -0.1489f, -0.0059f, 0.0913f, -0.0864f },
+ { 0.1787f, -0.1934f, 0.0474f, -0.0864f },
+ { 0.0000f, -0.0996f, 0.0327f, -0.2017f },
+ { 0.0596f, -0.0762f, 0.0181f, 0.0000f },
+ { -0.0298f, -0.0293f, 0.0474f, -0.0576f },
+ { -0.2231f, -0.4468f, 0.0298f, 0.1191f },
+ { -0.2847f, -0.1587f, 0.0898f, 0.0894f },
+ { -0.2539f, -0.1299f, -0.0103f, 0.2383f },
+ { -0.2231f, -0.0146f, 0.0098f, 0.0596f },
+ { 0.1460f, -0.4468f, -0.1904f, 0.0298f },
+ { -0.1924f, -0.3027f, -0.1704f, 0.0298f },
+ { 0.0229f, -0.1875f, -0.1304f, 0.2085f },
+ { -0.1001f, -0.1011f, -0.0503f, 0.1191f },
+ { -0.0693f, -0.3315f, -0.0503f, -0.1191f },
+ { -0.1924f, -0.1587f, 0.0098f, -0.0894f },
+ { -0.1001f, -0.1875f, 0.0498f, 0.0894f },
+ { -0.1924f, -0.0723f, 0.1099f, 0.0000f },
+ { 0.1768f, -0.2451f, -0.1904f, -0.2085f },
+ { -0.0693f, -0.1875f, -0.1904f, -0.2085f },
+ { -0.0078f, -0.1587f, -0.1304f, -0.0298f },
+ { -0.0693f, -0.0723f, -0.0103f, 0.0000f },
+};
+
+/*! \brief HOC 1st block Difference vector quantization table */
+const float ir77_ambe_hoc0_dif_vq[8][4] = {
+ { -0.0303f, -0.1313f, 0.0117f, 0.0107f },
+ { -0.2422f, -0.0771f, -0.0508f, -0.0166f },
+ { 0.1211f, -0.0771f, -0.0352f, 0.0107f },
+ { 0.0000f, 0.0132f, -0.0742f, 0.0264f },
+ { 0.0000f, -0.0049f, 0.0352f, -0.0166f },
+ { -0.1211f, 0.0493f, 0.0430f, -0.0049f },
+ { 0.2119f, 0.0854f, 0.0195f, 0.0146f },
+ { 0.0303f, 0.1396f, 0.0039f, -0.0283f },
+};
+
+/*! \brief HOC 2nd block Sum vector quantization table */
+const float ir77_ambe_hoc1_sum_vq[128][4] = {
+ { 0.4424f, -0.0303f, 0.0767f, 0.1050f },
+ { 0.2607f, 0.1816f, 0.1997f, 0.0649f },
+ { 0.1699f, 0.0000f, 0.0767f, -0.0151f },
+ { 0.0791f, 0.1211f, 0.1997f, -0.0552f },
+ { 0.2153f, -0.0605f, -0.1079f, 0.0249f },
+ { 0.0791f, 0.1816f, -0.0259f, -0.0752f },
+ { -0.0117f, -0.0303f, -0.0054f, -0.0151f },
+ { -0.1025f, 0.1514f, 0.0972f, -0.1152f },
+ { 0.1245f, 0.1211f, 0.0767f, 0.1851f },
+ { 0.0791f, 0.2725f, 0.1587f, 0.1050f },
+ { -0.0117f, 0.1211f, 0.0767f, 0.0249f },
+ { -0.1025f, 0.3027f, 0.1997f, -0.0752f },
+ { 0.0337f, 0.0605f, -0.0464f, 0.0850f },
+ { -0.0117f, 0.3936f, -0.0259f, 0.0449f },
+ { -0.1479f, 0.0908f, -0.0669f, -0.0552f },
+ { -0.2388f, 0.3027f, -0.0054f, -0.0952f },
+ { 0.3013f, -0.2007f, 0.1489f, 0.0947f },
+ { 0.1621f, -0.0195f, 0.2212f, 0.0547f },
+ { 0.1157f, -0.2266f, 0.2031f, -0.0854f },
+ { -0.0234f, -0.0195f, 0.2754f, -0.0854f },
+ { 0.1621f, -0.2007f, 0.0405f, 0.0146f },
+ { 0.0229f, -0.0195f, 0.1309f, -0.0054f },
+ { -0.1162f, -0.2266f, 0.1128f, -0.1255f },
+ { -0.2090f, -0.0195f, 0.1670f, -0.1255f },
+ { 0.1157f, -0.0713f, 0.1489f, 0.1748f },
+ { -0.0234f, 0.0840f, 0.2031f, 0.1147f },
+ { -0.1162f, -0.0972f, 0.1489f, 0.0347f },
+ { -0.2090f, 0.0840f, 0.2031f, -0.0054f },
+ { -0.0698f, -0.0713f, 0.0044f, 0.0547f },
+ { -0.1626f, 0.1099f, 0.0405f, 0.0146f },
+ { -0.3018f, -0.1230f, 0.0225f, -0.0054f },
+ { -0.3945f, 0.1616f, 0.1309f, -0.1255f },
+ { 0.1816f, -0.0063f, 0.0088f, 0.1206f },
+ { 0.0908f, 0.0654f, 0.1143f, 0.0576f },
+ { 0.0000f, -0.1260f, 0.0439f, 0.0366f },
+ { -0.0908f, 0.0176f, 0.0967f, -0.0054f },
+ { 0.0000f, -0.1021f, -0.0615f, 0.0996f },
+ { -0.0454f, 0.0415f, -0.0088f, 0.0366f },
+ { -0.1362f, -0.1260f, -0.0439f, -0.0474f },
+ { -0.3179f, 0.0894f, -0.0264f, -0.0474f },
+ { 0.0000f, 0.0415f, -0.0615f, 0.2676f },
+ { -0.0908f, 0.1851f, 0.0264f, 0.1626f },
+ { -0.1362f, 0.0176f, 0.0264f, 0.0996f },
+ { -0.2725f, 0.2329f, 0.1143f, 0.0786f },
+ { -0.1362f, 0.0415f, -0.1143f, 0.1416f },
+ { -0.2725f, 0.1851f, -0.0967f, 0.0996f },
+ { -0.3179f, -0.0303f, -0.1494f, 0.0786f },
+ { -0.4995f, 0.2329f, -0.0439f, 0.0156f },
+ { 0.0820f, -0.2373f, 0.0322f, 0.1699f },
+ { -0.0117f, -0.1582f, 0.1826f, 0.0820f },
+ { -0.0586f, -0.3428f, 0.1182f, 0.0820f },
+ { -0.1992f, -0.1846f, 0.2686f, -0.0498f },
+ { -0.1055f, -0.2637f, -0.0537f, 0.1699f },
+ { -0.1523f, -0.1582f, 0.0322f, 0.0381f },
+ { -0.2930f, -0.3691f, -0.0322f, -0.0059f },
+ { -0.3867f, -0.1582f, 0.1182f, -0.0718f },
+ { -0.1055f, -0.1318f, 0.0752f, 0.2578f },
+ { -0.1992f, 0.0264f, 0.1396f, 0.1699f },
+ { -0.2930f, -0.2637f, 0.1396f, 0.1040f },
+ { -0.3398f, 0.0000f, 0.2256f, 0.1040f },
+ { -0.2461f, -0.1318f, -0.0322f, 0.1479f },
+ { -0.3398f, 0.0000f, 0.0537f, 0.0601f },
+ { -0.4805f, -0.2109f, -0.0322f, 0.0820f },
+ { -0.6211f, -0.0527f, 0.0967f, -0.0059f },
+ { 0.7163f, 0.0000f, -0.0718f, 0.0054f },
+ { 0.4648f, 0.1777f, 0.0161f, -0.0161f },
+ { 0.2134f, -0.0508f, -0.0278f, -0.0806f },
+ { 0.2637f, 0.1523f, 0.0820f, -0.1235f },
+ { 0.4146f, -0.0254f, -0.1816f, -0.0806f },
+ { 0.2637f, 0.1270f, -0.1377f, -0.1450f },
+ { 0.1631f, -0.0508f, -0.1816f, -0.1880f },
+ { 0.0122f, 0.1523f, -0.0498f, -0.2310f },
+ { 0.3643f, 0.1270f, -0.1157f, 0.0913f },
+ { 0.3140f, 0.3301f, 0.0381f, 0.0269f },
+ { 0.1631f, 0.0762f, -0.0718f, -0.0161f },
+ { 0.1128f, 0.2793f, 0.0601f, -0.0806f },
+ { 0.2134f, 0.1270f, -0.2476f, 0.0269f },
+ { 0.1631f, 0.3047f, -0.1597f, -0.0806f },
+ { 0.0625f, 0.1016f, -0.2256f, -0.1021f },
+ { -0.0381f, 0.2539f, -0.1157f, -0.0806f },
+ { 0.5156f, -0.2051f, 0.0176f, -0.0054f },
+ { 0.3281f, -0.0371f, 0.1230f, -0.0698f },
+ { 0.2813f, -0.2051f, 0.0352f, -0.1558f },
+ { 0.1406f, -0.0161f, 0.1582f, -0.1558f },
+ { 0.2344f, -0.2051f, -0.1055f, -0.0698f },
+ { 0.0938f, 0.0049f, -0.0176f, -0.1343f },
+ { 0.0938f, -0.1841f, -0.0703f, -0.1558f },
+ { -0.0469f, -0.0791f, 0.0703f, -0.2632f },
+ { 0.2813f, -0.1001f, 0.0176f, 0.0591f },
+ { 0.1406f, 0.1099f, 0.0352f, 0.0161f },
+ { 0.0938f, -0.1001f, 0.0352f, -0.0698f },
+ { 0.0000f, 0.0259f, 0.0527f, -0.1128f },
+ { 0.0938f, -0.0371f, -0.0527f, 0.0161f },
+ { 0.0000f, 0.0889f, -0.0352f, -0.0483f },
+ { -0.0938f, -0.0581f, -0.0527f, -0.1128f },
+ { -0.1875f, 0.0889f, 0.0176f, -0.1772f },
+ { 0.3848f, -0.0942f, -0.1001f, 0.1318f },
+ { 0.3037f, 0.0938f, 0.0259f, 0.0220f },
+ { 0.1011f, -0.1479f, -0.1001f, 0.0000f },
+ { 0.0605f, 0.0132f, 0.0259f, 0.0000f },
+ { 0.2227f, -0.1479f, -0.2891f, 0.0000f },
+ { 0.0605f, -0.0137f, -0.1211f, -0.0659f },
+ { 0.0200f, -0.1211f, -0.2051f, -0.0659f },
+ { -0.1016f, -0.0137f, -0.1631f, -0.1978f },
+ { 0.1416f, 0.0132f, -0.1421f, 0.1099f },
+ { 0.1416f, 0.2012f, -0.0791f, 0.0879f },
+ { -0.0205f, -0.0137f, -0.1001f, 0.0220f },
+ { -0.0610f, 0.2012f, -0.0161f, 0.0220f },
+ { 0.0200f, -0.0405f, -0.2681f, 0.0659f },
+ { -0.0205f, 0.1475f, -0.1841f, 0.0879f },
+ { -0.1421f, 0.0400f, -0.2051f, -0.0220f },
+ { -0.2231f, 0.2549f, -0.2051f, -0.0220f },
+ { 0.3267f, -0.3203f, -0.0557f, 0.0479f },
+ { 0.1255f, -0.0957f, 0.0557f, 0.0479f },
+ { 0.0752f, -0.3428f, 0.0186f, -0.0718f },
+ { -0.0254f, -0.1182f, 0.0742f, -0.0957f },
+ { 0.0752f, -0.3428f, -0.1484f, 0.0479f },
+ { -0.0254f, -0.1406f, -0.0742f, -0.0239f },
+ { -0.0757f, -0.2979f, -0.2041f, -0.0718f },
+ { -0.2266f, -0.1631f, -0.0186f, -0.1675f },
+ { 0.1758f, -0.1855f, -0.0928f, 0.1914f },
+ { -0.0254f, -0.0059f, 0.0557f, 0.1196f },
+ { -0.0757f, -0.2529f, -0.0371f, -0.0239f },
+ { -0.1763f, -0.0059f, 0.0186f, -0.0479f },
+ { -0.0757f, -0.1631f, -0.1484f, 0.0718f },
+ { -0.1763f, -0.0283f, -0.0742f, 0.0239f },
+ { -0.2769f, -0.1855f, -0.1484f, -0.0479f },
+ { -0.4277f, -0.0508f, -0.0928f, -0.0957f },
+};
+
+/*! \brief HOC 2nd block Difference vector quantization table */
+const float ir77_ambe_hoc1_dif_vq[8][4] = {
+ { -0.0122f, 0.1094f, 0.0498f, -0.0337f },
+ { 0.1313f, 0.0957f, -0.0415f, -0.0122f },
+ { 0.0356f, -0.0137f, 0.0581f, 0.0200f },
+ { 0.1792f, -0.0684f, 0.0000f, 0.0093f },
+ { -0.1797f, 0.0547f, 0.0083f, -0.0068f },
+ { -0.0361f, 0.0273f, -0.0664f, 0.0308f },
+ { -0.1079f, -0.0957f, 0.0332f, 0.0146f },
+ { 0.0117f, -0.0820f, -0.0581f, -0.0444f },
+};
+
+/*! \brief HOC 3rd block Sum vector quantization table */
+const float ir77_ambe_hoc2_sum_vq[128][4] = {
+ { -0.0093f, 0.1221f, 0.0742f, -0.0044f },
+ { 0.1021f, 0.3101f, 0.1025f, -0.0044f },
+ { 0.1021f, -0.0283f, 0.0317f, -0.0210f },
+ { 0.1763f, 0.0845f, 0.0601f, 0.0039f },
+ { 0.1392f, 0.0093f, 0.1733f, -0.0542f },
+ { 0.2505f, 0.1973f, 0.1592f, -0.0210f },
+ { 0.2876f, -0.1787f, 0.1450f, -0.0542f },
+ { 0.3989f, 0.0093f, 0.1309f, -0.0376f },
+ { -0.1577f, 0.1221f, -0.0107f, 0.0288f },
+ { -0.0835f, 0.3853f, -0.0107f, 0.0039f },
+ { -0.0464f, -0.0659f, -0.0391f, 0.0371f },
+ { 0.0278f, 0.1221f, -0.0391f, 0.0620f },
+ { -0.0093f, -0.0283f, 0.0601f, 0.0288f },
+ { 0.1021f, 0.1597f, 0.0317f, 0.0039f },
+ { 0.1021f, -0.1787f, -0.0107f, -0.0127f },
+ { 0.1763f, -0.0283f, 0.0034f, 0.0205f },
+ { 0.1479f, 0.0952f, -0.0601f, -0.0195f },
+ { 0.2271f, 0.3379f, -0.0771f, 0.0195f },
+ { 0.2271f, -0.0435f, -0.0771f, -0.0039f },
+ { 0.3457f, 0.1299f, -0.0942f, -0.0273f },
+ { 0.2666f, 0.0259f, 0.0083f, 0.0039f },
+ { 0.4248f, 0.2686f, 0.0596f, 0.0273f },
+ { 0.4644f, -0.1821f, -0.0088f, -0.0039f },
+ { 0.5830f, 0.0605f, -0.0430f, -0.0195f },
+ { -0.0103f, 0.0952f, -0.1455f, 0.0430f },
+ { 0.0688f, 0.2339f, -0.1284f, 0.0508f },
+ { 0.0688f, -0.0781f, -0.1968f, 0.0742f },
+ { 0.1875f, 0.0605f, -0.1968f, 0.0898f },
+ { 0.1084f, -0.0088f, -0.0942f, 0.0586f },
+ { 0.2271f, 0.1646f, -0.0601f, 0.0742f },
+ { 0.2271f, -0.1821f, -0.1797f, 0.0352f },
+ { 0.3853f, -0.0088f, -0.1626f, 0.0820f },
+ { -0.1245f, 0.0571f, 0.0742f, -0.1616f },
+ { -0.0581f, 0.2534f, 0.0742f, -0.1206f },
+ { -0.0581f, -0.0737f, -0.0107f, -0.1821f },
+ { 0.0083f, 0.0571f, 0.0034f, -0.1001f },
+ { 0.0083f, -0.0410f, 0.1167f, -0.1309f },
+ { 0.0747f, 0.1226f, 0.1025f, -0.1411f },
+ { 0.1079f, -0.1719f, 0.0742f, -0.1616f },
+ { 0.2075f, -0.0083f, 0.0459f, -0.1309f },
+ { -0.2905f, 0.0571f, 0.0176f, -0.1001f },
+ { -0.2241f, 0.2207f, -0.0391f, -0.0796f },
+ { -0.2241f, -0.1064f, -0.0957f, -0.1104f },
+ { -0.0913f, 0.0898f, -0.0815f, -0.0386f },
+ { -0.1245f, -0.0410f, 0.0459f, -0.0591f },
+ { -0.0581f, 0.1226f, 0.0034f, -0.0693f },
+ { -0.0581f, -0.2373f, -0.0532f, -0.1104f },
+ { 0.0083f, -0.0410f, -0.0107f, -0.0283f },
+ { -0.0435f, 0.0869f, -0.0903f, -0.1709f },
+ { 0.0259f, 0.2456f, -0.0723f, -0.1343f },
+ { 0.0952f, -0.0718f, -0.1084f, -0.1709f },
+ { 0.1646f, 0.0869f, -0.1445f, -0.1221f },
+ { 0.1299f, -0.0083f, -0.0361f, -0.0732f },
+ { 0.2339f, 0.1504f, 0.0181f, -0.1099f },
+ { 0.2339f, -0.1987f, -0.0542f, -0.1343f },
+ { 0.3379f, -0.0083f, -0.1265f, -0.1343f },
+ { -0.1821f, 0.0552f, -0.1626f, -0.0732f },
+ { -0.1128f, 0.2139f, -0.2168f, 0.0000f },
+ { -0.0781f, -0.1035f, -0.2168f, -0.0854f },
+ { 0.0259f, 0.0552f, -0.2529f, -0.0610f },
+ { -0.0088f, -0.0083f, -0.1084f, -0.0366f },
+ { 0.0605f, 0.0869f, -0.1084f, -0.0244f },
+ { 0.0952f, -0.2305f, -0.1987f, -0.0854f },
+ { 0.1299f, -0.0718f, -0.1445f, -0.0366f },
+ { -0.1445f, 0.0757f, 0.1685f, 0.0718f },
+ { -0.0361f, 0.2441f, 0.1538f, 0.0718f },
+ { -0.0361f, -0.1265f, 0.0806f, 0.0308f },
+ { 0.0361f, 0.0757f, 0.0952f, 0.0615f },
+ { 0.0000f, -0.0254f, 0.1978f, 0.0410f },
+ { 0.1084f, 0.1431f, 0.2271f, 0.0718f },
+ { 0.1084f, -0.1938f, 0.1392f, 0.0103f },
+ { 0.2168f, -0.0254f, 0.1538f, 0.0718f },
+ { -0.3252f, 0.0083f, 0.1099f, 0.1230f },
+ { -0.2168f, 0.2104f, 0.0513f, 0.1128f },
+ { -0.2529f, -0.1938f, 0.0073f, 0.1538f },
+ { -0.1084f, 0.0083f, 0.0220f, 0.1128f },
+ { -0.1084f, -0.0928f, 0.1245f, 0.1333f },
+ { -0.0361f, 0.0757f, 0.0952f, 0.1641f },
+ { -0.0361f, -0.2612f, 0.0513f, 0.1128f },
+ { 0.0723f, -0.1265f, 0.0806f, 0.1436f },
+ { 0.0171f, 0.0078f, -0.0039f, 0.0767f },
+ { 0.0864f, 0.2300f, 0.0107f, 0.1484f },
+ { 0.0864f, -0.0874f, -0.0186f, 0.0459f },
+ { 0.1558f, 0.0713f, -0.0332f, 0.0767f },
+ { 0.1211f, -0.0239f, 0.0547f, 0.0869f },
+ { 0.2251f, 0.1348f, 0.0986f, 0.1382f },
+ { 0.2251f, -0.2144f, -0.0039f, 0.0664f },
+ { 0.3638f, -0.0239f, 0.0400f, 0.1177f },
+ { -0.1563f, 0.0396f, -0.0918f, 0.1587f },
+ { -0.0869f, 0.1665f, -0.1064f, 0.1382f },
+ { -0.0869f, -0.1509f, -0.1211f, 0.1279f },
+ { 0.0171f, 0.0396f, -0.1211f, 0.1587f },
+ { 0.0171f, -0.0874f, -0.0186f, 0.1484f },
+ { 0.0864f, 0.0713f, -0.0039f, 0.1997f },
+ { 0.0864f, -0.2461f, -0.1064f, 0.1484f },
+ { 0.1904f, -0.0557f, -0.0625f, 0.1792f },
+ { -0.3115f, 0.0615f, 0.1914f, -0.0586f },
+ { -0.2256f, 0.2256f, 0.1445f, -0.0352f },
+ { -0.2256f, -0.1436f, 0.0508f, -0.0820f },
+ { -0.0537f, 0.0205f, 0.0508f, -0.0273f },
+ { -0.1396f, -0.1025f, 0.2070f, -0.0664f },
+ { -0.0537f, 0.0615f, 0.1758f, -0.0586f },
+ { -0.0537f, -0.2256f, 0.1602f, -0.0508f },
+ { 0.0752f, -0.0615f, 0.0977f, -0.0273f },
+ { -0.5693f, -0.0205f, 0.1133f, 0.0273f },
+ { -0.4404f, 0.1846f, 0.0195f, -0.0117f },
+ { -0.4404f, -0.2666f, -0.0273f, 0.0117f },
+ { -0.2686f, -0.0205f, -0.0117f, 0.0352f },
+ { -0.3115f, -0.1436f, 0.1445f, 0.0352f },
+ { -0.1826f, 0.0205f, 0.0820f, -0.0039f },
+ { -0.2256f, -0.3896f, 0.0352f, 0.0117f },
+ { -0.1396f, -0.1436f, 0.0352f, 0.0195f },
+ { -0.1353f, 0.0176f, -0.0405f, -0.0552f },
+ { -0.0522f, 0.1958f, -0.0244f, 0.0063f },
+ { -0.0522f, -0.1250f, -0.0728f, -0.0464f },
+ { 0.0308f, 0.0176f, -0.0405f, -0.0024f },
+ { 0.0308f, -0.1250f, 0.0239f, -0.0640f },
+ { 0.0723f, 0.0532f, 0.0562f, -0.0288f },
+ { 0.1138f, -0.3389f, -0.0083f, -0.0376f },
+ { 0.2383f, -0.0894f, 0.0400f, -0.0112f },
+ { -0.3843f, -0.0181f, -0.1050f, 0.0063f },
+ { -0.3013f, 0.1958f, -0.1372f, 0.0679f },
+ { -0.2598f, -0.2319f, -0.1855f, -0.0200f },
+ { -0.1353f, -0.0181f, -0.1694f, 0.0415f },
+ { -0.1768f, -0.1250f, -0.0566f, 0.0327f },
+ { -0.0522f, 0.0532f, -0.0244f, 0.0503f },
+ { -0.0522f, -0.3389f, -0.1372f, 0.0239f },
+ { 0.0308f, -0.1250f, -0.0728f, 0.0327f },
+};
+
+/*! \brief HOC 3rd block Difference vector quantization table */
+const float ir77_ambe_hoc2_dif_vq[8][4] = {
+ { 0.0112f, 0.0884f, 0.0020f, 0.0527f },
+ { -0.1265f, 0.0884f, 0.0283f, -0.0020f },
+ { 0.1719f, 0.0762f, -0.0156f, -0.0156f },
+ { 0.0112f, 0.0029f, 0.0547f, -0.0430f },
+ { -0.0117f, -0.0093f, -0.0771f, -0.0156f },
+ { -0.1724f, -0.0581f, -0.0068f, -0.0156f },
+ { 0.1260f, -0.0947f, -0.0156f, 0.0049f },
+ { -0.0347f, -0.0947f, 0.0459f, 0.0391f },
+};
+
+/*! \brief HOC 4th block Sum vector quantization table */
+const float ir77_ambe_hoc3_sum_vq[128][4] = {
+ { -0.0532f, 0.0049f, -0.1143f, -0.0688f },
+ { 0.0317f, 0.1650f, -0.1396f, -0.1147f },
+ { 0.0742f, -0.0151f, -0.1016f, 0.0688f },
+ { 0.2441f, 0.1450f, -0.1904f, -0.0688f },
+ { -0.2231f, 0.0649f, -0.2412f, 0.0918f },
+ { -0.0957f, 0.2051f, -0.2412f, -0.0229f },
+ { -0.0107f, 0.0049f, -0.1904f, 0.1836f },
+ { 0.0317f, 0.1851f, -0.2285f, 0.0918f },
+ { -0.2231f, -0.0552f, -0.0762f, -0.1606f },
+ { -0.1382f, 0.0850f, -0.0889f, -0.1377f },
+ { -0.0532f, -0.0952f, -0.0508f, 0.0229f },
+ { 0.0317f, 0.0850f, -0.0762f, -0.0229f },
+ { -0.3931f, -0.0552f, -0.1777f, 0.0229f },
+ { -0.3081f, 0.1050f, -0.1523f, -0.0688f },
+ { -0.2231f, -0.0952f, -0.1523f, 0.1377f },
+ { -0.0957f, 0.1050f, -0.1523f, 0.0229f },
+ { 0.0698f, -0.1812f, -0.1880f, -0.0859f },
+ { 0.1499f, -0.0259f, -0.1470f, -0.1289f },
+ { 0.2300f, -0.2588f, -0.1196f, 0.0645f },
+ { 0.3501f, -0.0518f, -0.1743f, -0.0215f },
+ { -0.0903f, -0.1553f, -0.2427f, -0.0215f },
+ { -0.0103f, 0.0259f, -0.2427f, -0.0430f },
+ { 0.0698f, -0.1553f, -0.1743f, 0.1289f },
+ { 0.1499f, -0.0259f, -0.2427f, 0.0430f },
+ { -0.0903f, -0.2329f, -0.0513f, -0.1289f },
+ { -0.0503f, -0.0518f, -0.0923f, -0.1934f },
+ { -0.0103f, -0.3623f, -0.0513f, 0.0000f },
+ { 0.0698f, -0.1553f, -0.0376f, -0.0645f },
+ { -0.2505f, -0.2329f, -0.1606f, -0.0430f },
+ { -0.1704f, 0.0000f, -0.1606f, -0.0430f },
+ { -0.0903f, -0.2070f, -0.0923f, 0.0859f },
+ { -0.0503f, -0.0518f, -0.1333f, 0.0430f },
+ { 0.1011f, 0.0479f, -0.0063f, -0.0718f },
+ { 0.1416f, 0.2632f, -0.0190f, -0.1333f },
+ { 0.2227f, 0.0239f, 0.0063f, 0.0513f },
+ { 0.3848f, 0.2632f, 0.0317f, 0.0103f },
+ { -0.0610f, 0.1196f, -0.0571f, 0.0513f },
+ { 0.0200f, 0.3589f, -0.1206f, -0.0103f },
+ { 0.1011f, 0.0957f, -0.0825f, 0.1743f },
+ { 0.1821f, 0.2632f, -0.0825f, 0.0923f },
+ { -0.1016f, 0.0000f, 0.0698f, -0.0923f },
+ { -0.0205f, 0.1675f, 0.0317f, -0.1333f },
+ { 0.0605f, 0.0000f, 0.0571f, 0.0103f },
+ { 0.1821f, 0.1436f, 0.0190f, -0.0103f },
+ { -0.2231f, 0.0479f, -0.0063f, -0.0103f },
+ { -0.1826f, 0.2393f, -0.0444f, -0.0923f },
+ { -0.1016f, 0.0718f, 0.0063f, 0.1128f },
+ { 0.0200f, 0.1914f, -0.0698f, 0.0308f },
+ { 0.1885f, -0.1538f, -0.0352f, -0.1313f },
+ { 0.3218f, 0.0718f, -0.0195f, -0.1313f },
+ { 0.3662f, -0.1743f, 0.0742f, -0.0054f },
+ { 0.5439f, 0.0103f, -0.0039f, -0.0054f },
+ { 0.0552f, -0.0513f, -0.0508f, -0.0054f },
+ { 0.0996f, 0.0923f, -0.1133f, -0.0054f },
+ { 0.2329f, -0.0923f, -0.0664f, 0.1206f },
+ { 0.2773f, 0.0923f, -0.1133f, 0.0996f },
+ { 0.0107f, -0.1743f, 0.1211f, -0.1313f },
+ { 0.0996f, -0.0103f, 0.0430f, -0.1943f },
+ { 0.1440f, -0.2153f, 0.1211f, -0.0474f },
+ { 0.2329f, -0.0513f, 0.0586f, -0.0474f },
+ { -0.1226f, -0.1128f, 0.0273f, 0.0156f },
+ { -0.0781f, 0.0513f, -0.0195f, -0.0474f },
+ { 0.0107f, -0.0718f, 0.0273f, 0.0786f },
+ { 0.0552f, 0.0513f, -0.0039f, 0.0576f },
+ { -0.1504f, 0.0000f, -0.0293f, -0.0054f },
+ { -0.0645f, 0.2021f, -0.0293f, -0.0264f },
+ { -0.0215f, 0.0000f, -0.0146f, 0.0366f },
+ { 0.0645f, 0.1348f, 0.0146f, 0.0366f },
+ { -0.3223f, 0.0898f, -0.1172f, 0.1206f },
+ { -0.2363f, 0.2920f, -0.1611f, 0.0576f },
+ { -0.1504f, 0.0449f, -0.0439f, 0.2256f },
+ { -0.1074f, 0.2021f, -0.1025f, 0.1416f },
+ { -0.3652f, -0.0449f, 0.0146f, -0.0684f },
+ { -0.3223f, 0.1348f, 0.0146f, -0.0894f },
+ { -0.2363f, -0.0449f, 0.0586f, 0.0576f },
+ { -0.1074f, 0.0898f, 0.0439f, -0.0264f },
+ { -0.5801f, -0.0225f, 0.0000f, 0.0576f },
+ { -0.4941f, 0.2246f, -0.0879f, 0.0156f },
+ { -0.3652f, 0.0000f, 0.0146f, 0.1626f },
+ { -0.2793f, 0.1797f, -0.0293f, 0.0996f },
+ { -0.1074f, -0.1187f, -0.0552f, -0.0703f },
+ { 0.0098f, 0.0059f, -0.0186f, -0.0879f },
+ { 0.0879f, -0.1934f, 0.0059f, 0.0703f },
+ { 0.1660f, -0.0439f, -0.0430f, 0.0000f },
+ { -0.2246f, -0.0938f, -0.0674f, 0.0352f },
+ { -0.1855f, 0.1304f, -0.0918f, 0.0352f },
+ { -0.0684f, -0.0938f, -0.0186f, 0.1758f },
+ { 0.0098f, 0.0557f, -0.0796f, 0.1055f },
+ { -0.2637f, -0.2432f, 0.0547f, -0.0352f },
+ { -0.1855f, -0.0190f, 0.0303f, -0.0879f },
+ { -0.0684f, -0.2432f, 0.0913f, 0.0527f },
+ { -0.0293f, -0.0688f, 0.0303f, -0.0176f },
+ { -0.4199f, -0.2432f, -0.0063f, 0.0703f },
+ { -0.3418f, 0.0308f, -0.0430f, 0.0176f },
+ { -0.2246f, -0.1934f, 0.0181f, 0.1758f },
+ { -0.1465f, 0.0059f, -0.0674f, 0.0879f },
+ { -0.0210f, 0.0483f, 0.0996f, -0.0254f },
+ { 0.0210f, 0.3276f, 0.0830f, -0.0454f },
+ { 0.0630f, 0.0913f, 0.1328f, 0.0947f },
+ { 0.1890f, 0.2417f, 0.1494f, 0.0747f },
+ { -0.1890f, 0.1558f, 0.0332f, 0.0547f },
+ { -0.1470f, 0.3491f, -0.0166f, 0.0747f },
+ { -0.0210f, 0.1128f, 0.0664f, 0.2148f },
+ { 0.0630f, 0.2632f, 0.0166f, 0.1348f },
+ { -0.2729f, 0.0269f, 0.1992f, -0.0654f },
+ { -0.1470f, 0.1987f, 0.1328f, -0.0854f },
+ { -0.1050f, 0.0483f, 0.2324f, 0.0547f },
+ { 0.0210f, 0.1772f, 0.1826f, 0.0146f },
+ { -0.4409f, 0.0913f, 0.1494f, -0.0054f },
+ { -0.3569f, 0.3062f, 0.0996f, 0.0146f },
+ { -0.2729f, 0.1128f, 0.1328f, 0.1348f },
+ { -0.1050f, 0.2202f, 0.0996f, 0.0947f },
+ { 0.0767f, -0.0728f, 0.0762f, -0.0498f },
+ { 0.1206f, 0.1206f, 0.1230f, -0.0996f },
+ { 0.2085f, -0.1050f, 0.1113f, 0.0996f },
+ { 0.3403f, 0.0400f, 0.1230f, 0.0498f },
+ { -0.0991f, -0.0083f, 0.0645f, 0.0498f },
+ { -0.0552f, 0.1206f, 0.0293f, 0.0249f },
+ { 0.0767f, -0.0405f, 0.0410f, 0.1992f },
+ { 0.1646f, 0.1045f, 0.0410f, 0.1245f },
+ { -0.1431f, -0.1211f, 0.1699f, -0.0498f },
+ { -0.0991f, 0.0400f, 0.1582f, -0.1743f },
+ { 0.0327f, -0.1050f, 0.2051f, 0.0498f },
+ { 0.1646f, -0.0083f, 0.1934f, -0.0249f },
+ { -0.3188f, -0.1050f, 0.1699f, 0.0747f },
+ { -0.1870f, 0.0562f, 0.0996f, 0.0000f },
+ { -0.0991f, -0.0566f, 0.1465f, 0.1743f },
+ { -0.0112f, 0.0562f, 0.0762f, 0.0996f },
+};
+
+/*! \brief HOC 4th block Difference vector quantization table */
+const float ir77_ambe_hoc3_dif_vq[8][4] = {
+ { 0.1914f, -0.0171f, 0.0103f, 0.0044f },
+ { 0.0479f, -0.0718f, -0.0645f, 0.0220f },
+ { 0.0239f, -0.0444f, 0.0601f, -0.0366f },
+ { -0.0957f, -0.0991f, -0.0063f, 0.0044f },
+ { 0.0718f, 0.1060f, -0.0063f, -0.0073f },
+ { -0.0479f, 0.0376f, -0.0645f, -0.0190f },
+ { -0.0239f, 0.0513f, 0.0601f, 0.0513f },
+ { -0.1675f, 0.0376f, 0.0103f, -0.0015f },
+};
+
+/*! @} */
diff --git a/codec/tone.c b/codec/tone.c
new file mode 100644
index 0000000..601082f
--- /dev/null
+++ b/codec/tone.c
@@ -0,0 +1,175 @@
+/* Iridium AMBE vocoder - Tone frames */
+
+/* (C) 2015 by Sylvain Munaut <tnt@246tNt.com>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*! \addtogroup codec_private
+ * @{
+ */
+
+/*! \file codec/tone.c
+ * \brief Iridium AMBE vocoder tone frames handling
+ */
+
+#include <errno.h>
+#include <math.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "private.h"
+
+
+/*! \brief Structure describing a dual-frequency tone */
+struct tone_desc {
+ char *name; /*!< \brief Tone description */
+ int f1; /*!< \brief Frequency 1 (Hz) */
+ int f2; /*!< \brief Frequency 2 (Hz) */
+};
+
+/*! \brief DTMF tones descriptions */
+static const struct tone_desc dtmf_tones[] = {
+ { "0", 1336, 941 },
+ { "1", 1209, 697 },
+ { "2", 1336, 697 },
+ { "3", 1477, 697 },
+ { "4", 1209, 770 },
+ { "5", 1336, 770 },
+ { "6", 1477, 770 },
+ { "7", 1209, 852 },
+ { "8", 1336, 852 },
+ { "9", 1477, 852 },
+ { "A", 1633, 697 },
+ { "B", 1633, 770 },
+ { "C", 1633, 852 },
+ { "D", 1633, 941 },
+ { "#", 1477, 941 },
+ { "*", 1209, 941 },
+};
+
+/*! \brief Call progress tones descriptions */
+static const struct tone_desc call_progress_tones[] = {
+ { "Dial", 440, 350 },
+ { "Ring", 480, 440 },
+ { "Busy", 630, 480 },
+ { "????", 490, 350 },
+};
+
+
+/*! \brief Synthesize and add a tone to a given audio buffer
+ * \param[out] audio Audio buffer to mix the tone into
+ * \param[in] N number of audio samples to generate
+ * \param[in] ampl Tone amplitude
+ * \param[in] freq_hz Tone frequency in Hertz
+ * \param[inout] phase_p Pointer to phase variable to use
+ */
+static void
+tone_gen(int16_t *audio, int N, int ampl, int freq_hz, float *phase_p)
+{
+ float phase, phase_step;
+ int i;
+
+ phase = *phase_p;
+ phase_step = (2.0f * M_PIf * freq_hz) / AMBE_RATE;
+
+ for (i=0; i<N; i++)
+ {
+ audio[i] += (int16_t)(ampl * cosf(phase));
+ phase += phase_step;
+ }
+
+ *phase_p = phase;
+}
+
+
+/*! \brief Decodes an AMBE tone frame
+ * \param[in] dec AMBE decoder state
+ * \param[out] audio Output audio buffer
+ * \param[in] N number of audio samples to produce (152..168)
+ * \param[in] frame Frame data (as de-prioritized 103 ubits). Must be tone !
+ * \returns 0 for success. -EINVAL if frame was invalid.
+ */
+int
+ir77_ambe_decode_tone(struct ir77_ambe_decoder *dec,
+ int16_t *audio, int N, const ubit_t *frame)
+{
+ int p_log_ampl, p_freq;
+ int i, j, cnt;
+ int amplitude;
+
+ /* Decode parameters */
+ p_log_ampl =
+ (frame[10] << 7) |
+ (frame[11] << 6) |
+ (frame[12] << 5) |
+ (frame[15] << 4) |
+ (frame[16] << 3) |
+ (frame[17] << 2) |
+ (frame[18] << 1) |
+ (frame[19] << 0);
+
+ p_freq = 0;
+ for (i=0; i<8; i++) {
+ cnt = 0;
+ for (j=0; j<10; j++)
+ cnt += frame[20+(j<<3)+i];
+ p_freq = (p_freq << 1) | (cnt >= 5);
+ }
+
+ /* Clear audio */
+ memset(audio, 0x00, sizeof(int16_t) * N);
+
+ /* Compute amplitude */
+ amplitude = (int)(32767.0f * exp2f(((float)p_log_ampl-255.0f)/17.0f));
+
+ /* Interpret frequency code */
+ if (p_freq < 0x10)
+ {
+ /* DTMF tone */
+ int di = p_freq & 0xf;
+
+ tone_gen(audio, N, amplitude >> 1,
+ dtmf_tones[di].f1, &dec->tone_phase_f1);
+ tone_gen(audio, N, amplitude >> 1,
+ dtmf_tones[di].f2, &dec->tone_phase_f2);
+ }
+ else if ((p_freq >= 0x15) && (p_freq <= 0x8a))
+ {
+ int freq_hz = ((p_freq - 0x10) * 125) >> 2; /* 31.25 Hz increments */
+
+ tone_gen(audio, N, amplitude,
+ freq_hz, &dec->tone_phase_f1);
+ }
+ else if ((p_freq >= 0x90) && (p_freq <= 0x94))
+ {
+ /* Call progress tone */
+ int cpi = p_freq & 0xf;
+
+ tone_gen(audio, N, amplitude >> 1,
+ call_progress_tones[cpi].f1, &dec->tone_phase_f1);
+ tone_gen(audio, N, amplitude >> 1,
+ call_progress_tones[cpi].f2, &dec->tone_phase_f2);
+ }
+ else
+ {
+ /* Invalid */
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*! @} */