// $Id: GSMDecoder.java,v 1.1 2000/08/10 17:47:08 pfisterer Exp $
// This file is part of the GSM 6.10 audio decoder library for Java
// Copyright (C) 1998 Steven Pickles (pix@test.at)
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This library 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
// Library General Public License for more details.
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// This software is a port of the GSM Library provided by
// Jutta Degener (jutta@cs.tu-berlin.de) and
// Carsten Bormann (cabo@cs.tu-berlin.de),
// Technische Universitaet Berlin
package javaforce.codec.gsm;
public final class GSMDecoder {
private static final byte GSM_MAGIC = 0x0d;
private static final int[] FAC = {18431, 20479, 22527, 24575,
26623, 28671, 30719, 32767};
private static final int[] QLB = {3277, 11469, 21299, 32767};
// TODO: can be replaced by Short.MIN_VALUE and Short.MAX_VALUE ?
private static final int MIN_WORD = -32767 - 1;
private static final int MAX_WORD = 32767;
private int dp0[] = new int[280];
private int u[] = new int[8];
private int LARpp[][] = new int[2][8];
private int j;
private int nrp;
private int v[] = new int[9];
private int msr;
public void GSM() {
nrp = 40;
}
public final int[] decode(byte c[])
throws InvalidGSMFrameException {
if (c.length != 33) {
throw new InvalidGSMFrameException();
}
int i = 0;
if (((c[i] >> 4) & 0xf) != GSM_MAGIC) {
throw new InvalidGSMFrameException();
}
int LARc[] = new int[8];
int Nc[] = new int[4];
int Mc[] = new int[4];
int bc[] = new int[4];
int xmaxc[] = new int[4];
int xmc[] = new int[13 * 4];
LARc[0] = ((c[i++] & 0xF) << 2);
/* 1 */
LARc[0] |= ((c[i] >> 6) & 0x3);
LARc[1] = (c[i++] & 0x3F);
LARc[2] = ((c[i] >> 3) & 0x1F);
LARc[3] = ((c[i++] & 0x7) << 2);
LARc[3] |= ((c[i] >> 6) & 0x3);
LARc[4] = ((c[i] >> 2) & 0xF);
LARc[5] = ((c[i++] & 0x3) << 2);
LARc[5] |= ((c[i] >> 6) & 0x3);
LARc[6] = ((c[i] >> 3) & 0x7);
LARc[7] = (c[i++] & 0x7);
Nc[0] = ((c[i] >> 1) & 0x7F);
bc[0] = ((c[i++] & 0x1) << 1);
bc[0] |= ((c[i] >> 7) & 0x1);
Mc[0] = ((c[i] >> 5) & 0x3);
xmaxc[0] = ((c[i++] & 0x1F) << 1);
xmaxc[0] |= ((c[i] >> 7) & 0x1);
xmc[0] = ((c[i] >> 4) & 0x7);
xmc[1] = ((c[i] >> 1) & 0x7);
xmc[2] = ((c[i++] & 0x1) << 2);
xmc[2] |= ((c[i] >> 6) & 0x3);
xmc[3] = ((c[i] >> 3) & 0x7);
xmc[4] = (c[i++] & 0x7);
xmc[5] = ((c[i] >> 5) & 0x7);
xmc[6] = ((c[i] >> 2) & 0x7);
xmc[7] = ((c[i++] & 0x3) << 1);
/* 10 */
xmc[7] |= ((c[i] >> 7) & 0x1);
xmc[8] = ((c[i] >> 4) & 0x7);
xmc[9] = ((c[i] >> 1) & 0x7);
xmc[10] = ((c[i++] & 0x1) << 2);
xmc[10] |= ((c[i] >> 6) & 0x3);
xmc[11] = ((c[i] >> 3) & 0x7);
xmc[12] = (c[i++] & 0x7);
Nc[1] = ((c[i] >> 1) & 0x7F);
bc[1] = ((c[i++] & 0x1) << 1);
bc[1] |= ((c[i] >> 7) & 0x1);
Mc[1] = ((c[i] >> 5) & 0x3);
xmaxc[1] = ((c[i++] & 0x1F) << 1);
xmaxc[1] |= ((c[i] >> 7) & 0x1);
xmc[13] = ((c[i] >> 4) & 0x7);
xmc[14] = ((c[i] >> 1) & 0x7);
xmc[15] = ((c[i++] & 0x1) << 2);
xmc[15] |= ((c[i] >> 6) & 0x3);
xmc[16] = ((c[i] >> 3) & 0x7);
xmc[17] = (c[i++] & 0x7);
xmc[18] = ((c[i] >> 5) & 0x7);
xmc[19] = ((c[i] >> 2) & 0x7);
xmc[20] = ((c[i++] & 0x3) << 1);
xmc[20] |= ((c[i] >> 7) & 0x1);
xmc[21] = ((c[i] >> 4) & 0x7);
xmc[22] = ((c[i] >> 1) & 0x7);
xmc[23] = ((c[i++] & 0x1) << 2);
xmc[23] |= ((c[i] >> 6) & 0x3);
xmc[24] = ((c[i] >> 3) & 0x7);
xmc[25] = (c[i++] & 0x7);
Nc[2] = ((c[i] >> 1) & 0x7F);
bc[2] = ((c[i++] & 0x1) << 1);
/* 20 */
bc[2] |= ((c[i] >> 7) & 0x1);
Mc[2] = ((c[i] >> 5) & 0x3);
xmaxc[2] = ((c[i++] & 0x1F) << 1);
xmaxc[2] |= ((c[i] >> 7) & 0x1);
xmc[26] = ((c[i] >> 4) & 0x7);
xmc[27] = ((c[i] >> 1) & 0x7);
xmc[28] = ((c[i++] & 0x1) << 2);
xmc[28] |= ((c[i] >> 6) & 0x3);
xmc[29] = ((c[i] >> 3) & 0x7);
xmc[30] = (c[i++] & 0x7);
xmc[31] = ((c[i] >> 5) & 0x7);
xmc[32] = ((c[i] >> 2) & 0x7);
xmc[33] = ((c[i++] & 0x3) << 1);
xmc[33] |= ((c[i] >> 7) & 0x1);
xmc[34] = ((c[i] >> 4) & 0x7);
xmc[35] = ((c[i] >> 1) & 0x7);
xmc[36] = ((c[i++] & 0x1) << 2);
xmc[36] |= ((c[i] >> 6) & 0x3);
xmc[37] = ((c[i] >> 3) & 0x7);
xmc[38] = (c[i++] & 0x7);
Nc[3] = ((c[i] >> 1) & 0x7F);
bc[3] = ((c[i++] & 0x1) << 1);
bc[3] |= ((c[i] >> 7) & 0x1);
Mc[3] = ((c[i] >> 5) & 0x3);
xmaxc[3] = ((c[i++] & 0x1F) << 1);
xmaxc[3] |= ((c[i] >> 7) & 0x1);
xmc[39] = ((c[i] >> 4) & 0x7);
xmc[40] = ((c[i] >> 1) & 0x7);
xmc[41] = ((c[i++] & 0x1) << 2);
xmc[41] |= ((c[i] >> 6) & 0x3);
xmc[42] = ((c[i] >> 3) & 0x7);
xmc[43] = (c[i++] & 0x7);
/* 30 */
xmc[44] = ((c[i] >> 5) & 0x7);
xmc[45] = ((c[i] >> 2) & 0x7);
xmc[46] = ((c[i++] & 0x3) << 1);
xmc[46] |= ((c[i] >> 7) & 0x1);
xmc[47] = ((c[i] >> 4) & 0x7);
xmc[48] = ((c[i] >> 1) & 0x7);
xmc[49] = ((c[i++] & 0x1) << 2);
xmc[49] |= ((c[i] >> 6) & 0x3);
xmc[50] = ((c[i] >> 3) & 0x7);
xmc[51] = (c[i] & 0x7);
/* 33 */
return decoder(LARc, Nc, bc, Mc, xmaxc, xmc);
}
public final static void print(String name, int data[]) {
System.out.print("[" + name + ":");
for (int i = 0; i < data.length; i++) {
System.out.print("" + data[i]);
if (i < data.length - 1) {
System.out.print(",");
} else {
System.out.println("]");
}
}
}
public final static void print(String name, int data) {
System.out.println("[" + name + ":" + data + "]");
}
private final int[] decoder(int LARcr[],
int Ncr[],
int bcr[],
int Mcr[],
int xmaxcr[],
int xMcr[]) {
int j, k;
int erp[] = new int[40];
int wt[] = new int[160];
// drp is just dp0+120
//print("LARcr",LARcr);
//print("Ncr",Ncr);
//print("bcr",bcr);
//print("Mcr",Mcr);
//print("xmaxcr",xmaxcr);
//print("xMcr",xMcr);
for (j = 0; j < 4; j++) {
// find out what is done with xMcr
RPEDecoding(xmaxcr[j], Mcr[j], xMcr, j * 13, erp);
//print("erp",erp);
longTermSynthesisFiltering(Ncr[j], bcr[j], erp, dp0);
for (k = 0; k < 40; k++) {
wt[j * 40 + k] = dp0[120 + k];
}
}
//print("LARcr",LARcr);
//print("wt",wt);
int s[] = shortTermSynthesisFilter(LARcr, wt);
//print("s",s);
postprocessing(s);
return s;
}
private final void RPEDecoding(int xmaxcr,
int Mcr,
int xMcr[],
int xMcrOffset,
int erp[]) {
int expAndMant[];
int xMp[] = new int[13];
expAndMant = xmaxcToExpAndMant(xmaxcr);
//System.out.println("[e&m:"+expAndMant[0]+","+expAndMant[1]+"]");
APCMInverseQuantization(xMcr, xMcrOffset, expAndMant[0], expAndMant[1], xMp);
//print("xMp",xMp);
RPE_grid_positioning(Mcr, xMp, erp);
}
private final int[] xmaxcToExpAndMant(int xmaxc) {
int exp, mant;
exp = 0;
if (xmaxc > 15) {
exp = ((xmaxc >> 3) - 1);
}
mant = (xmaxc - (exp << 3));
if (mant == 0) {
exp = -4;
mant = 7;
} else {
while (mant <= 7) {
mant = (mant << 1 | 1);
exp--;
}
mant -= 8;
}
//assert(exp>=-4 && exp <= 6);
//assert(mant>=0 && mant<=7);
int result[] = new int[2];
result[0] = exp;
result[1] = mant;
return result;
}
//private void assert(boolean test) {
// if (!test) {
// System.out.println("assertion error");
// }
//}
private final void APCMInverseQuantization(int xMc[],
int xMcOffset,
int exp,
int mant,
int xMp[]) {
int i, p;
int temp, temp1, temp2, temp3;
int ltmp;
//assert(mant >0 && mant <= 7 );
temp1 = FAC[mant];
temp2 = sub(6, exp);
temp3 = asl(1, sub(temp2, 1));
//System.out.println("temp1="+temp1);
//System.out.println("temp2="+temp2);
//System.out.println("temp3="+temp3);
p = 0;
for (i = 13; i-- > 0;) {
//assert(xMc[xMcOffset] <= 7 && xMc[xMcOffset] >= 0);
temp = ((xMc[xMcOffset++] << 1) - 7);
//System.out.println("s1:temp="+temp);
//assert(temp<=7 && temp >= -7);
temp = (temp << 12);//&0xffff;
//System.out.println("s2:temp="+temp);
temp = mult_r(temp1, temp);
//System.out.println("s3:temp="+temp);
temp = add(temp, temp3);
//System.out.println("s4:temp="+temp);
xMp[p++] = asr(temp, temp2);
}
}
private final static int saturate(int x) {
return (x < MIN_WORD ? MIN_WORD : (x > MAX_WORD ? MAX_WORD : x));
}
private final static int sub(int a, int b) {
int diff = a - b;
return saturate(diff);
}
private final static int add(int a, int b) {
int sum = a + b;
return saturate(sum);
}
private final static int asl(int a, int n) {
if (n >= 16) {
return 0;
}
if (n <= -16) {
return (a < 0 ? -1 : 0);
}
if (n < 0) {
return asr(a, -n);
}
return (a << n);
}
private final static int asr(int a, int n) {
if (n >= 16) {
return (a < 0 ? -1 : 0);
}
if (n <= -16) {
return 0;
}
if (n < 0) {
return (a << -n);//&0xffff;
}
return (a >> n);
}
private final static int mult_r(int a, int b) {
if (b == MIN_WORD && a == MIN_WORD) {
return MAX_WORD;
} else {
int prod = a * b + 16384;
//prod >>= 15;
return saturate(prod >> 15);//&0xffff;
//return (prod & 0xffff);
}
}
private final void longTermSynthesisFiltering(int Ncr,
int bcr,
int erp[],
int dp0[]) {
int ltmp;
int k;
int brp, drpp, Nr;
Nr = Ncr < 40 || Ncr > 120 ? nrp : Ncr;
nrp = Nr;
brp = QLB[bcr];
for (k = 0; k <= 39; k++) {
drpp = mult_r(brp, dp0[120 + (k - Nr)]);
dp0[120 + k] = add(erp[k], drpp);
}
for (k = 0; k <= 119; k++) {
dp0[k] = dp0[40 + k];
}
}
private final int[] shortTermSynthesisFilter(int LARcr[],
int wt[]) {
//print("wt",wt);
int LARpp_j[] = LARpp[j];
int LARpp_j_1[] = LARpp[j ^= 1];
int LARp[] = new int[8];
int s[] = new int[160];
decodingOfTheCodedLogAreaRatios(LARcr, LARpp_j);
//print("LARpp_j",LARpp_j);
Coefficients_0_12(LARpp_j_1, LARpp_j, LARp);
LARp_to_rp(LARp);
shortTermSynthesisFiltering(LARp, 13, wt, s, 0);
Coefficients_13_26(LARpp_j_1, LARpp_j, LARp);
LARp_to_rp(LARp);
shortTermSynthesisFiltering(LARp, 14, wt, s, 13);
Coefficients_27_39(LARpp_j_1, LARpp_j, LARp);
LARp_to_rp(LARp);
shortTermSynthesisFiltering(LARp, 13, wt, s, 27);
Coefficients_40_159(LARpp_j, LARp);
LARp_to_rp(LARp);
shortTermSynthesisFiltering(LARp, 120, wt, s, 40);
return s;
}
public final static void decodingOfTheCodedLogAreaRatios(int LARc[],
int LARpp[]) {
int temp1;
int ltmp;
// STEP( 0, -32, 13107 );
temp1 = (add(LARc[0], -32) << 10);
//temp1 = (sub(temp1, 0));
temp1 = (mult_r(13107, temp1));
LARpp[0] = (add(temp1, temp1));
// STEP( 0, -32, 13107 );
temp1 = (add(LARc[1], -32) << 10);
//temp1 = (sub(temp1, 0));
temp1 = (mult_r(13107, temp1));
LARpp[1] = (add(temp1, temp1));
// STEP( 2048, -16, 13107 );
temp1 = (add(LARc[2], -16) << 10);
temp1 = (sub(temp1, 4096));
temp1 = (mult_r(13107, temp1));
LARpp[2] = (add(temp1, temp1));
// STEP( -2560, -16, 13107 );
temp1 = (add(LARc[3], (-16)) << 10);
temp1 = (sub(temp1, -5120));
temp1 = (mult_r(13107, temp1));
LARpp[3] = (add(temp1, temp1));
// STEP( 94, -8, 19223 );
temp1 = (add(LARc[4], -8) << 10);
temp1 = (sub(temp1, 188));
temp1 = (mult_r(19223, temp1));
LARpp[4] = (add(temp1, temp1));
// STEP( -1792, -8, 17476 );
temp1 = (add(LARc[5], (-8)) << 10);
temp1 = (sub(temp1, -3584));
temp1 = (mult_r(17476, temp1));
LARpp[5] = (add(temp1, temp1));
// STEP( -341, -4, 31454 );
temp1 = (add(LARc[6], (-4)) << 10);
temp1 = (sub(temp1, -682));
temp1 = (mult_r(31454, temp1));
LARpp[6] = (add(temp1, temp1));
// STEP( -1144, -4, 29708 );
temp1 = (add(LARc[7], -4) << 10);
temp1 = (sub(temp1, -2288));
temp1 = (mult_r(29708, temp1));
LARpp[7] = (add(temp1, temp1));
}
private final static void Coefficients_0_12(int LARpp_j_1[],
int LARpp_j[],
int LARp[]) {
int i;
int ltmp;
for (i = 0; i < 8; i++) {
LARp[i] = add((LARpp_j_1[i] >> 2), (LARpp_j[i] >> 2));
LARp[i] = add(LARp[i], (LARpp_j_1[i] >> 1));
}
}
private final static void Coefficients_13_26(int LARpp_j_1[],
int LARpp_j[],
int LARp[]) {
int i;
int ltmp;
for (i = 0; i < 8; i++) {
LARp[i] = add((LARpp_j_1[i] >> 1), (LARpp_j[i] >> 1));
}
}
private final static void Coefficients_27_39(int LARpp_j_1[],
int LARpp_j[],
int LARp[]) {
int i;
int ltmp;
for (i = 0; i < 8; i++) {
LARp[i] = add((LARpp_j_1[i] >> 2), (LARpp_j[i] >> 2));
LARp[i] = add(LARp[i], (LARpp_j[i] >> 1));
}
}
private final static void Coefficients_40_159(int LARpp_j[],
int LARp[]) {
int i;
int ltmp;
for (i = 0; i < 8; i++) {
LARp[i] = LARpp_j[i];
}
}
private final static void LARp_to_rp(int LARp[]) {
int i;
int temp;
for (i = 0; i < 8; i++) {
if (LARp[i] < 0) {
temp = ((LARp[i] == MIN_WORD) ? MAX_WORD : -LARp[i]);
LARp[i] = (-((temp < 11059) ? temp << 1
: ((temp < 20070) ? temp + 11059
: add((temp >> 2), 26112))));
} else {
temp = LARp[i];
LARp[i] = ((temp < 11059) ? temp << 1
: ((temp < 20070) ? temp + 11059
: add((temp >> 2), 26112)));
}
}
}
// shortTermSynthesisFiltering(LARp,13,wt,s,0);
private final void shortTermSynthesisFiltering(int rrp[],
int k,
int wt[],
int sr[],
int off) {
int i;
int sri, tmp1, tmp2;
int woff = off;
int soff = off;
while (k-- > 0) {
sri = wt[woff++];
for (i = 8; i-- > 0;) {
tmp1 = rrp[i];
tmp2 = v[i];
tmp2 = ((tmp1 == MIN_WORD && tmp2 == MIN_WORD
? MAX_WORD
: saturate((tmp1 * tmp2 + 16384) >> 15)));
sri = sub(sri, tmp2);
tmp1 = ((tmp1 == MIN_WORD && sri == MIN_WORD
? MAX_WORD
: saturate((tmp1 * sri + 16384) >> 15)));
v[i + 1] = add(v[i], tmp1);
}
sr[soff++] = v[0] = sri;
}
}
private final void postprocessing(int s[]) {
int k, soff = 0;
int tmp;
for (k = 160; k-- > 0; soff++) {
tmp = mult_r(msr, (28180));
msr = add(s[soff], tmp);
//s[soff]=(add(msr,msr) & 0xfff8);
s[soff] = saturate(add(msr, msr) & ~0x7);
}
}
private final static void RPE_grid_positioning(int Mc,
int xMp[],
int ep[]) {
int i = 13;
int epo = 0;
int po = 0;
switch (Mc) {
case 3:
ep[epo++] = 0;
case 2:
ep[epo++] = 0;
case 1:
ep[epo++] = 0;
case 0:
ep[epo++] = xMp[po++];
i--;
};
do {
ep[epo++] = 0;
ep[epo++] = 0;
ep[epo++] = xMp[po++];
} while (--i > 0);
while (++Mc < 4) {
ep[epo++] = 0;
}
}
}
/**
* * GSMDecoder.java **
*/