summaryrefslogtreecommitdiff
path: root/protocols/Tlen/codec
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Tlen/codec')
-rw-r--r--protocols/Tlen/codec/gsm.h65
-rw-r--r--protocols/Tlen/codec/gsm_codec.c283
-rw-r--r--protocols/Tlen/codec/gsm_long.c183
-rw-r--r--protocols/Tlen/codec/gsm_lpc.c208
-rw-r--r--protocols/Tlen/codec/gsm_preprocess.c103
-rw-r--r--protocols/Tlen/codec/gsm_rpe.c248
-rw-r--r--protocols/Tlen/codec/gsm_short.c211
7 files changed, 1301 insertions, 0 deletions
diff --git a/protocols/Tlen/codec/gsm.h b/protocols/Tlen/codec/gsm.h
new file mode 100644
index 0000000000..fba1bcb1ac
--- /dev/null
+++ b/protocols/Tlen/codec/gsm.h
@@ -0,0 +1,65 @@
+/*
+
+Tlen Protocol Plugin for Miranda IM
+Copyright (C) 2004 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include <windows.h>
+
+#define P_MAX 8 /* order p of LPC analysis, typically 8..14 */
+
+typedef struct {
+ int LARpp[2][8]; /* LAR coefficients for previous and current frame */
+ int j; /* current frame index in LARpp[j][] */
+ int qLARs[8]; /* quantized LARs for current frame */
+ int u[8]; /* used by short term analysis filter */
+ int v[9]; /* used by short term synthesis filter */
+ int subframe; /* subframe index (0..3)*/
+ short dp0[ 280 ]; /* previous short-term filter output/prediction, used by long term analysis*/
+ int e[160]; /* errors (residuals) */
+ int nrp; /* long term synthesis */
+ int Nc[4], bc[4]; /* long-term lag and gain for current frame */
+ int Mc[4]; /* RPE grid index (0..3) */
+ int xMaxc[4]; /* RPE maximum error quantized and encoded (mantissa + exp) */
+ int xMc[52]; /* quantized residuals (errors) 4 * 13 */
+
+ int z1; /* preprocessing.c, Offset_com. */
+ int z2; /* Offset_com. */
+ int mp; /* Preemphasis */
+ int msr; /* decoder.c, Postprocessing */
+
+ unsigned char gsmFrame[33];
+}gsm_state;
+
+extern gsm_state * gsm_create() ;
+extern void gsm_release(gsm_state *ptr);
+extern void gsm_encode(gsm_state *state, short *in);
+extern void gsm_decode(gsm_state *state, short *out);
+
+extern void gsm_preprocessing( gsm_state *state, short *in, short *out);
+extern void shortTermAnalysis(gsm_state *state, short *in);
+extern void longTermAnalysis(gsm_state *state, short *in);
+extern void encodeRPE(gsm_state *state);
+extern void decodeRPE(gsm_state *state);
+extern void longTermSynthesis(gsm_state *state);
+extern void shortTermSynthesis(gsm_state *state, short *in, short *out);
+extern void gsm_postprocessing( gsm_state *state, short *in, short *out);
diff --git a/protocols/Tlen/codec/gsm_codec.c b/protocols/Tlen/codec/gsm_codec.c
new file mode 100644
index 0000000000..1d0a08a41e
--- /dev/null
+++ b/protocols/Tlen/codec/gsm_codec.c
@@ -0,0 +1,283 @@
+/*
+
+Tlen Protocol Plugin for Miranda IM
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "gsm.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define GSM_MAGIC 0xD
+
+gsm_state * gsm_create()
+{
+ gsm_state * state = (gsm_state *)malloc(sizeof(gsm_state));
+ memset(state, 0, sizeof(gsm_state));
+ state->nrp = 40;
+ return state;
+}
+
+void gsm_release(gsm_state *ptr)
+{
+ free(ptr);
+}
+
+void gsm_encode(gsm_state *state, short *in)
+{ int i, j;
+ unsigned char *c = state->gsmFrame;
+ short temp_in[160];
+
+ gsm_preprocessing(state, in, temp_in);
+ shortTermAnalysis(state, temp_in);
+ for (i = 0; i < 4; i++) {
+ state->subframe = i;
+ longTermAnalysis(state, temp_in + 40 * i);
+ encodeRPE(state);
+ for (j = 0; j < 40; j++) {
+ int ii = (int) state->dp0[120 + i * 40 + j] + state->e[i * 40 + j];
+ if (ii<-32768) ii = -32768;
+ else if (ii>32767) ii=32767;
+ state->dp0[120 + i * 40 + j] = ii;
+ }
+ }
+ memcpy(state->dp0, state->dp0 + 160, 120 * sizeof(short));
+ state->j ^= 1;
+ *c++ = ((GSM_MAGIC & 0xF) << 4)
+ | ((state->qLARs[0] >> 2) & 0xF);
+ *c++ = ((state->qLARs[0] & 0x3) << 6)
+ | (state->qLARs[1] & 0x3F);
+ *c++ = ((state->qLARs[2] & 0x1F) << 3)
+ | ((state->qLARs[3] >> 2) & 0x7);
+ *c++ = ((state->qLARs[3] & 0x3) << 6)
+ | ((state->qLARs[4] & 0xF) << 2)
+ | ((state->qLARs[5] >> 2) & 0x3);
+ *c++ = ((state->qLARs[5] & 0x3) << 6)
+ | ((state->qLARs[6] & 0x7) << 3)
+ | (state->qLARs[7] & 0x7);
+ *c++ = ((state->Nc[0] & 0x7F) << 1)
+ | ((state->bc[0] >> 1) & 0x1);
+ *c++ = ((state->bc[0] & 0x1) << 7)
+ | ((state->Mc[0] & 0x3) << 5)
+ | ((state->xMaxc[0] >> 1) & 0x1F);
+ *c++ = ((state->xMaxc[0] & 0x1) << 7)
+ | ((state->xMc[0] & 0x7) << 4)
+ | ((state->xMc[1] & 0x7) << 1)
+ | ((state->xMc[2] >> 2) & 0x1);
+ *c++ = ((state->xMc[2] & 0x3) << 6)
+ | ((state->xMc[3] & 0x7) << 3)
+ | (state->xMc[4] & 0x7);
+ *c++ = ((state->xMc[5] & 0x7) << 5)
+ | ((state->xMc[6] & 0x7) << 2)
+ | ((state->xMc[7] >> 1) & 0x3);
+ *c++ = ((state->xMc[7] & 0x1) << 7)
+ | ((state->xMc[8] & 0x7) << 4)
+ | ((state->xMc[9] & 0x7) << 1)
+ | ((state->xMc[10] >> 2) & 0x1);
+ *c++ = ((state->xMc[10] & 0x3) << 6)
+ | ((state->xMc[11] & 0x7) << 3)
+ | (state->xMc[12] & 0x7);
+ *c++ = ((state->Nc[1] & 0x7F) << 1)
+ | ((state->bc[1] >> 1) & 0x1);
+ *c++ = ((state->bc[1] & 0x1) << 7)
+ | ((state->Mc[1] & 0x3) << 5)
+ | ((state->xMaxc[1] >> 1) & 0x1F);
+ *c++ = ((state->xMaxc[1] & 0x1) << 7)
+ | ((state->xMc[13] & 0x7) << 4)
+ | ((state->xMc[14] & 0x7) << 1)
+ | ((state->xMc[15] >> 2) & 0x1);
+ *c++ = ((state->xMc[15] & 0x3) << 6)
+ | ((state->xMc[16] & 0x7) << 3)
+ | (state->xMc[17] & 0x7);
+ *c++ = ((state->xMc[18] & 0x7) << 5)
+ | ((state->xMc[19] & 0x7) << 2)
+ | ((state->xMc[20] >> 1) & 0x3);
+ *c++ = ((state->xMc[20] & 0x1) << 7)
+ | ((state->xMc[21] & 0x7) << 4)
+ | ((state->xMc[22] & 0x7) << 1)
+ | ((state->xMc[23] >> 2) & 0x1);
+ *c++ = ((state->xMc[23] & 0x3) << 6)
+ | ((state->xMc[24] & 0x7) << 3)
+ | (state->xMc[25] & 0x7);
+ *c++ = ((state->Nc[2] & 0x7F) << 1)
+ | ((state->bc[2] >> 1) & 0x1);
+ *c++ = ((state->bc[2] & 0x1) << 7)
+ | ((state->Mc[2] & 0x3) << 5)
+ | ((state->xMaxc[2] >> 1) & 0x1F);
+ *c++ = ((state->xMaxc[2] & 0x1) << 7)
+ | ((state->xMc[26] & 0x7) << 4)
+ | ((state->xMc[27] & 0x7) << 1)
+ | ((state->xMc[28] >> 2) & 0x1);
+ *c++ = ((state->xMc[28] & 0x3) << 6)
+ | ((state->xMc[29] & 0x7) << 3)
+ | (state->xMc[30] & 0x7);
+ *c++ = ((state->xMc[31] & 0x7) << 5)
+ | ((state->xMc[32] & 0x7) << 2)
+ | ((state->xMc[33] >> 1) & 0x3);
+ *c++ = ((state->xMc[33] & 0x1) << 7)
+ | ((state->xMc[34] & 0x7) << 4)
+ | ((state->xMc[35] & 0x7) << 1)
+ | ((state->xMc[36] >> 2) & 0x1);
+ *c++ = ((state->xMc[36] & 0x3) << 6)
+ | ((state->xMc[37] & 0x7) << 3)
+ | (state->xMc[38] & 0x7);
+ *c++ = ((state->Nc[3] & 0x7F) << 1)
+ | ((state->bc[3] >> 1) & 0x1);
+ *c++ = ((state->bc[3] & 0x1) << 7)
+ | ((state->Mc[3] & 0x3) << 5)
+ | ((state->xMaxc[3] >> 1) & 0x1F);
+ *c++ = ((state->xMaxc[3] & 0x1) << 7)
+ | ((state->xMc[39] & 0x7) << 4)
+ | ((state->xMc[40] & 0x7) << 1)
+ | ((state->xMc[41] >> 2) & 0x1);
+ *c++ = ((state->xMc[41] & 0x3) << 6)
+ | ((state->xMc[42] & 0x7) << 3)
+ | (state->xMc[43] & 0x7);
+ *c++ = ((state->xMc[44] & 0x7) << 5)
+ | ((state->xMc[45] & 0x7) << 2)
+ | ((state->xMc[46] >> 1) & 0x3);
+ *c++ = ((state->xMc[46] & 0x1) << 7)
+ | ((state->xMc[47] & 0x7) << 4)
+ | ((state->xMc[48] & 0x7) << 1)
+ | ((state->xMc[49] >> 2) & 0x1);
+ *c++ = ((state->xMc[49] & 0x3) << 6)
+ | ((state->xMc[50] & 0x7) << 3)
+ | (state->xMc[51] & 0x7);
+}
+
+void gsm_decode(gsm_state *state, short *out)
+{
+ int i;
+ unsigned char *c = state->gsmFrame;
+
+ if (((*c >> 4) & 0x0F) != GSM_MAGIC) return ;
+ state->qLARs[0] = (*c++ & 0xF) << 2;
+ state->qLARs[0] |= (*c >> 6) & 0x3;
+ state->qLARs[1] = *c++ & 0x3F;
+ state->qLARs[2] = (*c >> 3) & 0x1F;
+ state->qLARs[3] = (*c++ & 0x7) << 2;
+ state->qLARs[3] |= (*c >> 6) & 0x3;
+ state->qLARs[4] = (*c >> 2) & 0xF;
+ state->qLARs[5] = (*c++ & 0x3) << 2;
+ state->qLARs[5] |= (*c >> 6) & 0x3;
+ state->qLARs[6] = (*c >> 3) & 0x7;
+ state->qLARs[7] = *c++ & 0x7;
+ state->Nc[0] = (*c >> 1) & 0x7F;
+ state->bc[0] = (*c++ & 0x1) << 1;
+ state->bc[0] |= (*c >> 7) & 0x1;
+ state->Mc[0] = (*c >> 5) & 0x3;
+ state->xMaxc[0] = (*c++ & 0x1F) << 1;
+ state->xMaxc[0] |= (*c >> 7) & 0x1;
+ state->xMc[0] = (*c >> 4) & 0x7;
+ state->xMc[1] = (*c >> 1) & 0x7;
+ state->xMc[2] = (*c++ & 0x1) << 2;
+ state->xMc[2] |= (*c >> 6) & 0x3;
+ state->xMc[3] = (*c >> 3) & 0x7;
+ state->xMc[4] = *c++ & 0x7;
+ state->xMc[5] = (*c >> 5) & 0x7;
+ state->xMc[6] = (*c >> 2) & 0x7;
+ state->xMc[7] = (*c++ & 0x3) << 1;
+ state->xMc[7] |= (*c >> 7) & 0x1;
+ state->xMc[8] = (*c >> 4) & 0x7;
+ state->xMc[9] = (*c >> 1) & 0x7;
+ state->xMc[10] = (*c++ & 0x1) << 2;
+ state->xMc[10] |= (*c >> 6) & 0x3;
+ state->xMc[11] = (*c >> 3) & 0x7;
+ state->xMc[12] = *c++ & 0x7;
+ state->Nc[1] = (*c >> 1) & 0x7F;
+ state->bc[1] = (*c++ & 0x1) << 1;
+ state->bc[1] |= (*c >> 7) & 0x1;
+ state->Mc[1] = (*c >> 5) & 0x3;
+ state->xMaxc[1] = (*c++ & 0x1F) << 1;
+ state->xMaxc[1] |= (*c >> 7) & 0x1;
+ state->xMc[13] = (*c >> 4) & 0x7;
+ state->xMc[14] = (*c >> 1) & 0x7;
+ state->xMc[15] = (*c++ & 0x1) << 2;
+ state->xMc[15] |= (*c >> 6) & 0x3;
+ state->xMc[16] = (*c >> 3) & 0x7;
+ state->xMc[17] = *c++ & 0x7;
+ state->xMc[18] = (*c >> 5) & 0x7;
+ state->xMc[19] = (*c >> 2) & 0x7;
+ state->xMc[20] = (*c++ & 0x3) << 1;
+ state->xMc[20] |= (*c >> 7) & 0x1;
+ state->xMc[21] = (*c >> 4) & 0x7;
+ state->xMc[22] = (*c >> 1) & 0x7;
+ state->xMc[23] = (*c++ & 0x1) << 2;
+ state->xMc[23] |= (*c >> 6) & 0x3;
+ state->xMc[24] = (*c >> 3) & 0x7;
+ state->xMc[25] = *c++ & 0x7;
+ state->Nc[2] = (*c >> 1) & 0x7F;
+ state->bc[2] = (*c++ & 0x1) << 1;
+ state->bc[2] |= (*c >> 7) & 0x1;
+ state->Mc[2] = (*c >> 5) & 0x3;
+ state->xMaxc[2] = (*c++ & 0x1F) << 1;
+ state->xMaxc[2] |= (*c >> 7) & 0x1;
+ state->xMc[26] = (*c >> 4) & 0x7;
+ state->xMc[27] = (*c >> 1) & 0x7;
+ state->xMc[28] = (*c++ & 0x1) << 2;
+ state->xMc[28] |= (*c >> 6) & 0x3;
+ state->xMc[29] = (*c >> 3) & 0x7;
+ state->xMc[30] = *c++ & 0x7;
+ state->xMc[31] = (*c >> 5) & 0x7;
+ state->xMc[32] = (*c >> 2) & 0x7;
+ state->xMc[33] = (*c++ & 0x3) << 1;
+ state->xMc[33] |= (*c >> 7) & 0x1;
+ state->xMc[34] = (*c >> 4) & 0x7;
+ state->xMc[35] = (*c >> 1) & 0x7;
+ state->xMc[36] = (*c++ & 0x1) << 2;
+ state->xMc[36] |= (*c >> 6) & 0x3;
+ state->xMc[37] = (*c >> 3) & 0x7;
+ state->xMc[38] = *c++ & 0x7;
+ state->Nc[3] = (*c >> 1) & 0x7F;
+ state->bc[3] = (*c++ & 0x1) << 1;
+ state->bc[3] |= (*c >> 7) & 0x1;
+ state->Mc[3] = (*c >> 5) & 0x3;
+ state->xMaxc[3] = (*c++ & 0x1F) << 1;
+ state->xMaxc[3] |= (*c >> 7) & 0x1;
+ state->xMc[39] = (*c >> 4) & 0x7;
+ state->xMc[40] = (*c >> 1) & 0x7;
+ state->xMc[41] = (*c++ & 0x1) << 2;
+ state->xMc[41] |= (*c >> 6) & 0x3;
+ state->xMc[42] = (*c >> 3) & 0x7;
+ state->xMc[43] = *c++ & 0x7;
+ state->xMc[44] = (*c >> 5) & 0x7;
+ state->xMc[45] = (*c >> 2) & 0x7;
+ state->xMc[46] = (*c++ & 0x3) << 1;
+ state->xMc[46] |= (*c >> 7) & 0x1;
+ state->xMc[47] = (*c >> 4) & 0x7;
+ state->xMc[48] = (*c >> 1) & 0x7;
+ state->xMc[49] = (*c++ & 0x1) << 2;
+ state->xMc[49] |= (*c >> 6) & 0x3;
+ state->xMc[50] = (*c >> 3) & 0x7;
+ state->xMc[51] = *c & 0x7;
+
+ for (i = 0; i < 4; i++) {
+ state->subframe = i;
+ decodeRPE(state);
+ longTermSynthesis(state);
+ }
+ memcpy(state->dp0, state->dp0 + 160, 120 * sizeof(short));
+ shortTermSynthesis(state, &state->dp0[120], out);
+ gsm_postprocessing(state, out, out);
+ state->j ^= 1;
+}
diff --git a/protocols/Tlen/codec/gsm_long.c b/protocols/Tlen/codec/gsm_long.c
new file mode 100644
index 0000000000..7d9148061c
--- /dev/null
+++ b/protocols/Tlen/codec/gsm_long.c
@@ -0,0 +1,183 @@
+/*
+
+Tlen Protocol Plugin for Miranda IM
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "gsm.h"
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+/* Decision levels */
+const static int gsm_DLB[4] = { 6554, 16384, 26214, 32767 };
+/* Quantization levels */
+const static int gsm_QLB[4] = { 3277, 11469, 21299, 32767 };
+
+/*
+ * Long term parameters calculation - lag (Nc) and gain (bc).
+ */
+static void longTermLTPCalculation(gsm_state *state, short *in, short *in_1)
+{
+ int k, lambda;
+ int Nc, bc;
+ float in_1_float_base[120], * in_1_float = in_1_float_base + 120;
+ float in_float[40];
+ float L_result, L_max, L_power;
+
+ for (k = -120; k < 0; k++) in_1_float[k] = (float)in_1[k];
+ for (k = 0; k < 40; k++) in_float[k] = (float)in[k];
+
+ /* Search for the maximum cross-correlation and coding of the LTP lag */
+
+ L_max = 0;
+ Nc = 40; /* index for the maximum cross-correlation */
+
+ for (lambda = 40; lambda < 121; lambda++) {
+ for (L_result = 0, L_power = 0, k = 0; k < 40; k++) {
+ L_result += in_float[k] * in_1_float[k - lambda];
+// L_power += in_1_float[k - lambda] * in_1_float[k - lambda];
+ }
+// L_result = L_result / L_power;
+ if (L_result > L_max) {
+ Nc = lambda;
+ L_max = L_result;
+ }
+ }
+ state->Nc[state->subframe] = Nc;
+ if (L_max <= 0.) {
+ state->bc[state->subframe] = 0;
+ return;
+ }
+ /* Compute the power of the reconstructed short term residual signal dp[..] */
+ in_1_float -= Nc;
+ L_power = 0;
+ for (k = 0; k < 40; k++) {
+ float f = in_1_float[k];
+ L_power += f * f;
+ }
+ if (L_max >= L_power) { //1.0
+ state->bc[state->subframe] = 3;
+ return;
+ }
+ /* Coding of the LTP gain
+ * Table gsm_DLB must be used to obtain the level DLB[i] for the
+ * quantization of the LTP gain b to get the coded version bc.
+ */
+// lambda = L_max * 32768.;
+ lambda = (int)(L_max * 32768. / L_power);
+ for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break;
+ state->bc[state->subframe] = bc;
+}
+
+/*
+ * Here we decode the bc parameter and compute samples of the estimate out[0..39].
+ * The decoding of bc needs the gsm_QLB table.
+ * The long term residual signal e[0..39] is then calculated to be fed to the
+ * RPE encoding section.
+ */
+static void longTermAnalysisFilter(int Nc, int bc, short *in, short *in_1, short *out, int *e)
+{
+ int gain, k, l;
+ gain = gsm_QLB[bc];
+ for (k = 0; k < 40; k++) {
+ l = (gain * (int)in_1[k - Nc] + 16384) >> 15;
+ if (l < -32768) l = -32768;
+ else if (l > 32767) l = 32767;
+ out[k] = l;
+ e[k] = in[k] - l;
+ }
+}
+
+/*
+ * This procedure uses the bcr and Ncr parameter to realize the
+ * long term synthesis filtering. The decoding of bcr needs table gsm_QLB.
+ */
+static void longTermSynthesisFilter(gsm_state * state, int Ncr, int bcr, int *e, short *out)
+{
+ int k;
+ int brp, Nr;
+
+ /* Check the limits of Nr. */
+ Nr = Ncr < 40 || Ncr > 120 ? state->nrp : Ncr;
+ state->nrp = Nr;
+ /* Decoding of the LTP gain bcr */
+ brp = gsm_QLB[ bcr ];
+
+ /* Computation of the reconstructed short term residual
+ * signal drp[0..39]
+ */
+ for (k = 0; k < 40; k++) {
+ int temp = (brp * (int)out[ k-Nr ] + 16384) >> 15;
+ out[k] = e[k] + temp;
+ }
+}
+
+/*
+ * This procedure performs long term analysis.
+ */
+void longTermAnalysis(gsm_state *state, short *in)
+{
+ short *in_1 = state->dp0 + 120 + state->subframe * 40;
+ short *out = state->dp0 + 120 + state->subframe * 40;
+ int *e = state->e + state->subframe * 40;
+/*
+
+ int i;
+ printf("Long-term in: \n");
+ for (i=0;i<40;i++) {
+ printf("%7d ", in[i]);
+ }
+ printf("\n");
+ */
+ longTermLTPCalculation(state, in, in_1);
+ /* printf("Nc: %d, bc: %d \n", state->Nc[state->subframe], state->bc[state->subframe]);
+ */
+ longTermAnalysisFilter(state->Nc[state->subframe], state->bc[state->subframe], in, in_1, out, e);
+/*
+ printf("Long-term out: \n");
+ for (i=0;i<40;i++) {
+ printf("%7d ", out[i]);
+ }
+ printf("\n");
+ */
+}
+
+/*
+ * This procedure performs long term synthesis.
+ */
+void longTermSynthesis(gsm_state *state)
+{
+ int Nc = state->Nc[state->subframe];
+ int bc = state->bc[state->subframe];
+ int *e = state->e + state->subframe * 40;
+ short *out = state->dp0 + 120 + state->subframe * 40;
+ //int i;
+ longTermSynthesisFilter(state, Nc, bc, e, out);
+ /*
+ printf("Long-term reconstructed: \n");
+ for (i=0;i<160;i++) {
+ printf("%7d ", state->dp0[i]);
+ }
+ printf("\n");
+ */
+}
diff --git a/protocols/Tlen/codec/gsm_lpc.c b/protocols/Tlen/codec/gsm_lpc.c
new file mode 100644
index 0000000000..519612baff
--- /dev/null
+++ b/protocols/Tlen/codec/gsm_lpc.c
@@ -0,0 +1,208 @@
+/*
+
+Tlen Protocol Plugin for Miranda IM
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/* LPC- and Reflection Coefficients
+ * The next two functions calculate linear prediction coefficients
+ * and/or the related reflection coefficients from the first P_MAX+1
+ * values of the autocorrelation function.
+ */
+#include "gsm.h" /* for P_MAX */
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Compute the autocorrelation
+ * ,--,
+ * ac(l) = > x(i) * x(i-l) for all i
+ * `--'
+ * for lags l between 0 and lag-1, and x(i) == 0 for i < 0 or i >= n
+ * @param n: number of samples
+ * @param lax: max lag (order)
+ * @param in: [0...n-1] samples x
+ * @param out: [0...lag-1] autocorrelation
+ */
+static void autocorrelation(int n, float const *x, int lag, float *ac)
+{
+ float d;
+ int i, j;
+ for (j = 0; j < lag; j++) {
+ for (i = j, d = 0; i < n; i++) d += x[i] * x[i-j];
+ ac[j] = d;
+ }
+ d = (float)fabs(ac[0]);
+ if (d != 0) {
+ for (j = 0; j < lag; j++) ac[j] /= d;
+ }
+}
+
+/* The Levinson-Durbin algorithm was invented by N. Levinson in 1947
+ * and modified by J. Durbin in 1959.
+ * @param in: [0...p] autocorrelation values
+ * @param out: [0...p-1] reflection coefficients
+ * @param lpc: [0...p-1] LPC coefficients
+ * @return minimum mean square error
+ */
+/*
+static float levinson_durbin (float const *ac, float *ref, float *lpc)
+{
+ int i, j;
+ float r, error = ac[0];
+
+ if (ac[0] == 0) {
+ for (i = 0; i < P_MAX; i++) ref[i] = 0;
+ return 0;
+ }
+
+ for (i = 0; i < P_MAX; i++) {
+
+ r = -ac[i + 1];
+ for (j = 0; j < i; j++) r -= lpc[j] * ac[i - j];
+ ref[i] = r /= error;
+
+ // Update LPC coefficients and total error.
+ lpc[i] = r;
+ for (j = 0; j < i / 2; j++) {
+ float tmp = lpc[j];
+ lpc[j] = r * lpc[i - 1 - j];
+ lpc[i - 1 - j] += r * tmp;
+ }
+ if (i % 2) lpc[j] += lpc[j] * r;
+
+ error *= 1 - r * r;
+ }
+ return error;
+}
+*/
+/* I. Schur's recursion from 1917 is related to the Levinson-Durbin method,
+ * but faster on parallel architectures; where Levinson-Durbin would take time
+ * proportional to p * log(p), Schur only requires time proportional to p. The
+ * GSM coder uses an integer version of the Schur recursion.
+ * @param in: [0...p] autocorrelation values
+ * @param out: [0...p-1] reflection coefficients
+ * @return the minimum mean square error
+ */
+static float schur(float const *ac, float *ref)
+{
+ int i, m;
+ float error=ac[0], r, G[2][P_MAX];
+
+ if (ac[0] == 0.0) {
+ for (i = 0; i < P_MAX; i++) ref[i] = 0;
+ return 0;
+ }
+
+ /* Initialize the rows of the generator matrix G to ac[1...p]. */
+ for (i = 0; i < P_MAX; i++) G[0][i] = G[1][i] = ac[i + 1];
+
+ for (i = 0;;) {
+ /* Calculate this iteration's reflection coefficient and error. */
+ ref[i] = r = -G[1][0] / error;
+ error += G[1][0] * r;
+
+ if (++i >= P_MAX) return error;
+
+ /* Update the generator matrix. Unlike Levinson-Durbin's summing of
+ * reflection coefficients, this loop could be executed in parallel
+ * by p processors in constant time.
+ */
+ for (m = 0; m < P_MAX - i; m++) {
+ G[1][m] = G[1][m + 1] + r * G[0][m];
+ G[0][m] = G[1][m + 1] * r + G[0][m];
+ }
+ }
+}
+
+
+ /* 0..7 IN/OUT */
+static void rToLAR(int *r)
+/*
+ * The following scaling for r[..] and LAR[..] has been used:
+ *
+ * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1.
+ * LAR[..] = integer( real_LAR[..] * 16384 );
+ * with -1.625 <= real_LAR <= 1.625
+ */
+{
+ int temp;
+ int i;
+
+ /* Computation of the LAR[0..7] from the r[0..7]
+ */
+ for (i = 0; i < 8; i++) {
+ temp = abs(r[i]); //GSM_ABS(temp);
+ if (temp < 22118) {
+ temp >>= 1;
+ } else if (temp < 31130) {
+ temp -= 11059;
+ } else {
+ temp -= 26112;
+ temp <<= 2;
+ }
+ r[i] = r[i] < 0 ? -temp : temp;
+ }
+}
+
+static void quantizeLARs(int *LARs, int *qLARs)
+{ int qA[]={20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036};
+ int qB[]={0, 0, 2048, -2560, 94, -1792, -341, -1144};
+ int qMin[]={-32, -32, -16, -16, -8, -8, -4, -4};
+ int qMax[]={31, 31, 15, 15, 7, 7, 3, 3};
+ int i;
+ for (i = 0; i < 8; i++) {
+ int temp;
+ temp = (((LARs[i] * qA[i]) >> 15) + qB[i] + 256) >> 9;
+ if (temp < qMin[i]) temp = 0;
+ else if (temp > qMax[i]) temp = qMax[i] - qMin[i];
+ else temp = temp - qMin[i];
+ qLARs[i] = temp;
+ }
+}
+
+void lpcAnalysis(gsm_state *state, short *in)
+{ float error;
+ float samples[160];
+ float ac[9];
+ float ref[8];
+ int i;
+ int * qLARs = state->qLARs;
+ for (i = 0; i < 160; i++) {
+ samples[i] = in[i];
+ }
+ autocorrelation(160, samples, 9, ac);
+ error=schur(ac, ref);
+ /*
+ printf("reff: ");
+ for (i=0;i<8;i++) {
+ printf("%5.5f ", ref[i]);//((float)i_lpc[i])/32768.0f);
+ }
+ printf("\n");
+ */
+ for (i = 0; i < 8; i++) {
+ qLARs[i] = (int) (32768 * ref[i]);
+ }
+ rToLAR(qLARs);
+ quantizeLARs(qLARs, qLARs);
+}
diff --git a/protocols/Tlen/codec/gsm_preprocess.c b/protocols/Tlen/codec/gsm_preprocess.c
new file mode 100644
index 0000000000..b3d11bb7b1
--- /dev/null
+++ b/protocols/Tlen/codec/gsm_preprocess.c
@@ -0,0 +1,103 @@
+/*
+
+Tlen Protocol Plugin for Miranda IM
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "gsm.h"
+#include <stdio.h>
+
+/* 4.2.0 .. 4.2.3 PREPROCESSING SECTION
+ *
+ * After A-law to linear conversion (or directly from the
+ * Ato D converter) the following scaling is assumed for
+ * input to the RPE-LTP algorithm:
+ *
+ *
+ * Where S is the sign bit, v a valid bit, and * a "don't care" bit.
+ * The original signal is called sop[..]
+ *
+ */
+
+
+void gsm_preprocessing( gsm_state *state, short *in, short *out)
+{
+ int z1 = state->z1;
+ int z2 = state->z2;
+ int mp = state->mp;
+ int so, s1;
+ int msp, lsp;
+
+ int k = 160;
+
+ while (k--) {
+ /* Downscaling of the input signal
+ * in: 0.1.....................12
+ * S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.*
+ * out: 0.1................... 12
+ * S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0
+ */
+ so = (*in >> 3) << 2;
+ in++;
+ /* 4.2.2 Offset compensation
+ *
+ * This part implements a high-pass filter and requires extended
+ * arithmetic precision for the recursive part of this filter.
+ * The input of this procedure is the array so[0...159] and the
+ * output the array sof[ 0...159 ].
+ */
+ /* Compute the non-recursive part
+ */
+ s1 = (so - z1) << 15;
+ z1 = so;
+ msp = z2 >> 15;
+ lsp = z2 - (msp << 15);
+ s1 += ((lsp * 32735) + 16384) >> 15;
+ z2 = msp * 32735 + s1;
+ /* 4.2.3 Preemphasis
+ */
+ msp = (-28180 * mp + 16384) >> 15;
+ mp = (z2 + 16384) >> 15;
+ *out++ = mp + msp;
+ }
+ state->z1 = z1;
+ state->z2 = z2;
+ state->mp = mp;
+/*
+ printf("preprocessed: \n");
+ for (k=0;k<160;k++) {
+ printf("%7d ", out[k]);//((float)i_lpc[i])/32768.0f);
+ }
+ printf("\n");
+ */
+}
+
+void gsm_postprocessing( gsm_state *state, short *in, short *out)
+{
+ int k;
+ int msr = state->msr;
+ for (k = 160; k--; in++, out++) {
+ msr = *in + ((msr * 28180 + 16384) >>15); /* Deemphasis */
+ *out = (msr + msr ) & 0xFFF8; /* Truncation & Upscaling */
+ }
+ state->msr = msr;
+}
diff --git a/protocols/Tlen/codec/gsm_rpe.c b/protocols/Tlen/codec/gsm_rpe.c
new file mode 100644
index 0000000000..ad7234e606
--- /dev/null
+++ b/protocols/Tlen/codec/gsm_rpe.c
@@ -0,0 +1,248 @@
+/*
+
+Tlen Protocol Plugin for Miranda IM
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "gsm.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static const int gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 };
+static const int gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 };
+static const int gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 };
+/*
+ * The coefficients of the weighting filter are stored in the gsm_H table.
+ * The following scaling is used:
+ *
+ * gsm_H[0..10] = integer( real_H[ 0..10] * 8192 );
+ */
+static void weightingFilter (int *e, int *x)
+{
+ int L_result;
+ int k, i;
+ for (k = 0; k < 40; k++) {
+ L_result = 4096;
+ for (i = 0; i < 11; i++) {
+ int ix = i + k;
+ if (ix>4 && ix<45) L_result += e[ix - 5] * gsm_H[i];
+ }
+ L_result >>= 13;
+ x[k] = (L_result < -32768 ? -32768 : (L_result > 32767 ? 32767 : L_result));
+ }
+}
+
+/*
+ * The signal x[0..39] is used to select the RPE grid which is
+ * represented by Mc.
+ */
+static void gridSelection( int *x, int *xM, int *Mc_out)
+{
+ int m, i;
+ int L_result, L_temp;
+ int EM, Mc;
+
+ EM = 0;
+ Mc = 0;
+
+ for (m = 0; m < 4; m++) {
+ L_result = 0;
+ for (i = 0; i < 13; i++) {
+ int temp = x[m + 3*i] >> 2;
+ L_temp = temp * temp << 1;
+ L_result += L_temp;
+ }
+ if (L_result > EM) {
+ Mc = m;
+ EM = L_result;
+ }
+ }
+ /* Down-sampling by a factor 3 to get the selected xM[0..12]
+ * RPE sequence.
+ */
+ for (i = 0; i < 13; i ++) xM[i] = x[Mc + 3*i];
+ *Mc_out = Mc;
+}
+
+/*
+ * This procedure computes the reconstructed long term residual signal
+ * ep[0..39] for the LTP analysis filter. The inputs are the Mc
+ * which is the grid position selection and the xMp[0..12] decoded
+ * RPE samples which are upsampled by a factor of 3 by inserting zero
+ * values.
+ */
+static void gridPositioning (int Mc, int *xMp, int *ep)
+{
+ int i, k;
+ for (k = 0; k < 40; k++) ep[k] = 0;
+ for (i = 0; i < 13; i++) {
+ ep[ Mc + (3*i) ] = xMp[i];
+ }
+}
+
+static void APCMXmaxcToExpMant (int xmaxc, int *exp_out, int *mant_out )
+{
+ int exp, mant;
+ /* Compute exponent and mantissa of the decoded version of xmaxc
+ */
+ exp = 0;
+ if (xmaxc > 15) exp = (xmaxc >> 3) - 1;
+ mant = xmaxc - (exp << 3);
+
+ if (mant == 0) {
+ exp = -4;
+ mant = 7;
+ }
+ else {
+ while (mant < 8) {
+ mant = mant << 1 | 1;
+ exp--;
+ }
+ mant -= 8;
+ }
+
+ *exp_out = exp;
+ *mant_out = mant;
+}
+
+static void APCMQuantization (int *xM, int *xMc, int *mant_out, int *exp_out, int *xmaxc_out)
+{
+ int i, itest;
+ int xmax, xmaxc, temp, temp1, temp2;
+ int exp, mant;
+
+
+ /* Find the maximum absolute value xmax of xM[0..12].
+ */
+
+ xmax = 0;
+ for (i = 0; i < 13; i++) {
+ temp = abs(xM[i]);
+ if (temp > xmax) xmax = temp;
+ }
+ if (xmax > 32767) xmax = 32767;
+ /* Qantizing and coding of xmax to get xmaxc.
+ */
+
+ exp = 0;
+ temp = xmax >> 9;
+ itest = 0;
+
+ for (i = 0; i < 6; i++) {
+ if (temp != 0) exp++;
+ temp = temp >> 1;
+ }
+
+ temp = exp + 5;
+
+ xmaxc = (xmax >> temp) + (exp << 3);
+
+ /* Quantizing and coding of the xM[0..12] RPE sequence
+ * to get the xMc[0..12]
+ */
+ APCMXmaxcToExpMant( xmaxc, &exp, &mant );
+
+ /* This computation uses the fact that the decoded version of xmaxc
+ * can be calculated by using the exponent and the mantissa part of
+ * xmaxc (logarithmic table).
+ * So, this method avoids any division and uses only a scaling
+ * of the RPE samples by a function of the exponent. A direct
+ * multiplication by the inverse of the mantissa (NRFAC[0..7]
+ * found in table 4.5) gives the 3 bit coded version xMc[0..12]
+ * of the RPE samples.
+ */
+
+ /* Direct computation of xMc[0..12] using table 4.5
+ */
+ temp = (mant|8)<<(5+exp);
+ temp1 = 6 - exp;
+ temp2 = gsm_NRFAC[ mant ];
+ for (i = 0; i < 13; i++) {
+ xMc[i] = ((xM[i] << temp1) * temp2 >> 27) + 4;
+ }
+
+ /* NOTE: This equation is used to make all the xMc[i] positive.
+ */
+
+ *mant_out = mant;
+ *exp_out = exp;
+ *xmaxc_out = xmaxc;
+}
+
+static void APCMDequantization (int *xMc, int mant, int exp, int *xMp)
+{
+ int i, temp1, temp2, temp3;
+ temp1 = gsm_FAC[ mant ];
+ temp2 = 6 - exp;
+ if (temp2 <= 0) {
+ temp3 = 1 >> (1 - temp2);
+ } else {
+ temp3 = 1 << (temp2 - 1);
+ }
+ for (i = 0; i < 13; i++) {
+ xMp[i] = ((((((xMc[i]<<1)-7)<<12)*temp1+16384)>>15)+temp3)>>temp2;
+ }
+}
+
+void encodeRPE(gsm_state *state)
+{ int x[40];
+ int xM[13], xMp[13];
+ int mant, exp;
+ int *Mc = state->Mc + state->subframe;
+ int *xMaxc = state->xMaxc + state->subframe;
+ int *xMc = state->xMc + state->subframe * 13;
+ int *e = state->e + state->subframe * 40;
+ //int i;
+ /*
+ printf("RPE in: \n");
+ for (i=0;i<40;i++) {
+ printf("%7d ", e[i]);
+ }
+ printf("\n");
+ */
+ weightingFilter(e, x);
+ /*
+ printf("RPE weighting filter: \n");
+ for (i=0;i<40;i++) {
+ printf("%7d ", x[i]);
+ }
+ printf("\n");
+ */
+ gridSelection(x, xM, Mc);
+ APCMQuantization(xM, xMc, &mant, &exp, xMaxc);
+ /* printf("RPE Mc(grid #)=%d xmaxc=%d mant=%d exp=%d \n", *Mc, *xMaxc, mant, exp); */
+ APCMDequantization(xMc, mant, exp, xMp);
+ gridPositioning(*Mc, xMp, e);
+}
+
+void decodeRPE(gsm_state *state)
+{
+ int exp, mant;
+ int xMp[ 13 ];
+ int *xMc = state->xMc + state->subframe * 13;
+ int *e = state->e + state->subframe * 40;
+
+ APCMXmaxcToExpMant(state->xMaxc[state->subframe], &exp, &mant);
+ APCMDequantization(xMc, mant, exp, xMp);
+ gridPositioning(state->Mc[state->subframe], xMp, e);
+}
diff --git a/protocols/Tlen/codec/gsm_short.c b/protocols/Tlen/codec/gsm_short.c
new file mode 100644
index 0000000000..c461484639
--- /dev/null
+++ b/protocols/Tlen/codec/gsm_short.c
@@ -0,0 +1,211 @@
+/*
+
+Tlen Protocol Plugin for Miranda IM
+Copyright (C) 2004-2007 Piotr Piastucki
+
+This program is based on GSM 06.10 source code developed by
+Jutta Degener and Carsten Bormann,
+Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+Technische Universitaet Berlin
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "gsm.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+extern void lpcAnalysis(gsm_state *state, short *in);
+
+/*
+ * Dequantize LAR coefficients
+ */
+static void dequantizeLARs(int *qLARs, int *LARs)
+{
+ int dqA[]={13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708};
+ int dqB[]={0, 0, 2048, -2560, 94, -1792, -341, -1144};
+ int dqMin[]={-32, -32, -16, -16, -8, -8, -4, -4};
+ int i;
+ for (i = 0; i < 8; i++) {
+ int temp;
+ temp = ((((qLARs[i] + dqMin[i]) << 10) - (dqB[i] << 1)) * dqA[i] + 16384) >> 15;
+ LARs[i] = temp + temp;
+ }
+}
+/*
+ * Interpolate LAR coefficients (samples 0..12)
+ */
+static void interpolateLARs_0_12 (int *LARpp_j_1, int *LARpp_j, int *LARp)
+{ int i;
+ for (i = 0; i < 8; i++) {
+ LARp[i] = (LARpp_j_1[i] >> 1) + (LARpp_j_1[i] >> 2) + (LARpp_j[i] >> 2);
+ }
+}
+/*
+ * Interpolate LAR coefficients (samples 13..26)
+ */
+static void interpolateLARs_13_26 (int *LARpp_j_1, int *LARpp_j, int *LARp)
+{ int i;
+ for (i = 0; i < 8; i++) {
+ LARp[i] = (LARpp_j_1[i] >> 1) + (LARpp_j[i] >> 1);
+ }
+}
+/*
+ * Interpolate LAR coefficients (samples 27..39)
+ */
+static void interpolateLARs_27_39 (int *LARpp_j_1, int *LARpp_j, int *LARp)
+{ int i;
+ for (i = 0; i < 8; i++) {
+ LARp[i] = (LARpp_j[i] >> 1) + (LARpp_j_1[i] >> 2) + (LARpp_j[i] >> 2);
+ }
+}
+/*
+ * Interpolate LAR coefficients (samples 40..159)
+ */
+static void interpolateLARs_40_159 (int *LARpp_j_1, int *LARpp_j, int *LARp)
+{ int i;
+ for (i = 0; i < 8; i++) {
+ LARp[i] = LARpp_j[i];
+ }
+}
+/*
+ * Convert LAR coefficients to reflection coefficients
+ */
+static void LARToR( int * LARp)
+{
+ int i;
+ int temp;
+ for (i = 0; i < 8; i++) {
+ temp = abs(LARp[i]);
+ if (temp < 11059) temp <<= 1;
+ else if (temp < 20070) temp += 11059;
+ else temp = (temp >> 2) + 26112;
+ LARp[i] = LARp[i] < 0 ? -temp : temp;
+ }
+}
+
+/*
+ * This procedure computes the short term residual signal d[..] to be fed
+ * to the RPE-LTP loop from the s[..] signal and from the local rp[..]
+ * array (quantized reflection coefficients). As the call of this
+ * procedure can be done in many ways (see the interpolation of the LAR
+ * coefficient), it is assumed that the computation begins with index
+ * k_start (for arrays d[..] and s[..]) and stops with index k_end
+ * (k_start and k_end are defined in 4.2.9.1). This procedure also
+ * needs to keep the array u[0..7] in memory for each call.
+ */
+static void shortTermAnalysisFilter (gsm_state * state, int * rp, int len, short * in)
+{
+ int * u = state->u;
+ int i;
+ int di, ui, sav, rpi;
+ for (; len--; in++) {
+ di = sav = *in;
+ for (i = 0; i < 8; i++) {
+ ui = u[i];
+ rpi = rp[i];
+ u[i] = sav;
+ sav = ui + ((rpi * di + 16384) >> 15);
+ di = di + ((rpi * ui + 16384) >> 15);
+ }
+ *in = di;
+ }
+}
+
+static void shortTermSynthesisFilter(gsm_state * state, int * rrp, int len, short * in, short *out)
+{
+ int * v = state->v;
+ int i;
+ int sri;
+ for (; len--; in++, out++) {
+ sri = *in;
+ for (i = 8; i--;) {
+ sri -= (rrp[i] * v[i] + 16384) >> 15;
+ if (sri < -32768) sri = -32768;
+ else if (sri > 32767) sri = 32767;
+ v[i+1] = v[i] + ((rrp[i] * sri + 16384) >> 15);
+ if (v[i+1] < -32768) v[i+1] = -32768;
+ else if (v[i+1] > 32767) v[i+1] = 32767;
+ }
+ *out = v[0] = sri;
+ }
+}
+
+void shortTermAnalysis(gsm_state *state, short *in)
+{
+ int * qLARs = state->qLARs;
+ int * LARpp_j = state->LARpp[state->j];
+ int * LARpp_j_1 = state->LARpp[state->j ^1];
+ int LARp[8];
+// int i;
+
+ lpcAnalysis(state, in);//i_samples);
+/*
+ printf("short term in: \n");
+ for (i=0;i<160;i++) {
+ printf("%7d ", in[i]);//((float)i_lpc[i])/32768.0f);
+ }
+ printf("\n");
+ */
+ dequantizeLARs(qLARs, LARpp_j);
+ interpolateLARs_0_12(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermAnalysisFilter(state, LARp, 13, in);
+ interpolateLARs_13_26(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermAnalysisFilter(state, LARp, 14, in+13);
+ interpolateLARs_27_39(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermAnalysisFilter(state, LARp, 13, in+27);
+ interpolateLARs_40_159(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermAnalysisFilter(state, LARp, 120, in+40);
+ /*
+ printf("short-term residuals: \n");
+ for (i=0;i<160;i++) {
+ printf("%7d ", in[i]);//((float)i_lpc[i])/32768.0f);
+ }
+ printf("\n");
+ */
+}
+
+void shortTermSynthesis(gsm_state *state, short *in, short *out)
+{
+ int * qLARs = state->qLARs;
+ int * LARpp_j = state->LARpp[state->j];
+ int * LARpp_j_1 = state->LARpp[state->j ^1];
+ int LARp[8];
+// int i;
+
+ dequantizeLARs(qLARs, LARpp_j);
+ interpolateLARs_0_12(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermSynthesisFilter(state, LARp, 13, in, out);
+ interpolateLARs_13_26(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermSynthesisFilter(state, LARp, 14, in+13, out+13);
+ interpolateLARs_27_39(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermSynthesisFilter(state, LARp, 13, in+27, out+27);
+ interpolateLARs_40_159(LARpp_j_1, LARpp_j, LARp);
+ LARToR(LARp);
+ shortTermSynthesisFilter(state, LARp, 120, in+40, out+40);
+ /*
+ printf("samples[reconstructed]: \n");
+ for (i=0;i<160;i++) {
+ printf("%7d ", out[i]);
+ }
+ */
+}