/*----------------------------------------------------------------* * main decoder function *---------------------------------------------------------------*/ void iLBC_decode( float[] decblock, /* (o) decoded signal block */ bitstream bytes, /* (i) encoded signal bits */ int mode) /* (i) 0: bad packet, PLC, 1: normal */ { float[] data = new float[ilbc_constants.BLOCKL_MAX]; float[] lsfdeq = new float[ilbc_constants.LPC_FILTERORDER * ilbc_constants.LPC_N_MAX]; float[] PLCresidual = new float[ilbc_constants.BLOCKL_MAX]; float[] PLClpc = new float[ilbc_constants.LPC_FILTERORDER + 1]; float[] zeros = new float[ilbc_constants.BLOCKL_MAX]; float[] one = new float[ilbc_constants.LPC_FILTERORDER + 1]; int k, i, start, idxForMax, /*pos,*/ lastpart, ulp; int lag, ilag; float cc, maxcc; int[] idxVec = new int[ilbc_constants.STATE_LEN]; // int check; int[] gain_index = new int[ilbc_constants.NASUB_MAX * ilbc_constants.CB_NSTAGES]; int[] extra_gain_index = new int[ilbc_constants.CB_NSTAGES]; int[] cb_index = new int[ilbc_constants.CB_NSTAGES * ilbc_constants.NASUB_MAX]; int[] extra_cb_index = new int[ilbc_constants.CB_NSTAGES]; int[] lsf_i = new int[ilbc_constants.LSF_NSPLIT * ilbc_constants.LPC_N_MAX]; int state_first; int last_bit; // unsigned char *pbytes; float[] weightdenum = new float[(ilbc_constants.LPC_FILTERORDER + 1) * ilbc_constants.NSUB_MAX]; int order_plus_one; float[] syntdenum = new float[ilbc_constants.NSUB_MAX * (ilbc_constants.LPC_FILTERORDER + 1)]; float[] decresidual = new float[ilbc_constants.BLOCKL_MAX]; if (mode > 0) { /* the data are good */ /* decode data */ // pbytes=bytes; // pos=0; /* Set everything to zero before decoding */ for (k = 0;k < ilbc_constants.LSF_NSPLIT * ilbc_constants.LPC_N_MAX;k++) { lsf_i[k] = 0; } start = 0; state_first = 0; idxForMax = 0; for (k = 0;k < this.ULP_inst.state_short_len;k++) { idxVec[k] = 0; } for (k = 0;k < ilbc_constants.CB_NSTAGES;k++) { extra_cb_index[k] = 0; } for (k = 0;k < ilbc_constants.CB_NSTAGES;k++) { extra_gain_index[k] = 0; } for (i = 0;i < this.ULP_inst.nasub;i++) { for (k = 0;k < ilbc_constants.CB_NSTAGES;k++) { cb_index[i * ilbc_constants.CB_NSTAGES + k] = 0; } } for (i = 0;i < this.ULP_inst.nasub;i++) { for (k = 0;k < ilbc_constants.CB_NSTAGES;k++) { gain_index[i * ilbc_constants.CB_NSTAGES + k] = 0; } } /* loop over ULP classes */ for (ulp = 0;ulp < 3;ulp++) { /* LSF */ for (k = 0;k < ilbc_constants.LSF_NSPLIT * this.ULP_inst.lpc_n;k++) { lastpart = bytes.unpack(this.ULP_inst.lsf_bits[k, ulp]); // unpack( &pbytes, &lastpart, // this.ULP_inst.lsf_bits[k,ulp], &pos); lsf_i[k] = bytes.packcombine(lsf_i[k], lastpart, this.ULP_inst.lsf_bits[k, ulp]); // System.out.println("lsf_i["+k+"] = " + lsf_i[k]); // packcombine(&lsf_i[k], lastpart, // this.ULP_inst.lsf_bits[k,ulp]); } /* Start block info */ lastpart = bytes.unpack(this.ULP_inst.start_bits[ulp]); // unpack( &pbytes, &lastpart, // this.ULP_inst.start_bits[ulp], &pos); start = bytes.packcombine(start, lastpart, this.ULP_inst.start_bits[ulp]); // System.out.println("start = " + start); // packcombine(&start, lastpart, // this.ULP_inst.start_bits[ulp]); lastpart = bytes.unpack(this.ULP_inst.startfirst_bits[ulp]); // unpack( &pbytes, &lastpart, // this.ULP_inst.startfirst_bits[ulp], &pos); state_first = bytes.packcombine(state_first, lastpart, this.ULP_inst.startfirst_bits[ulp]); // System.out.println("state_first = " + state_first); // packcombine(&state_first, lastpart, // this.ULP_inst.startfirst_bits[ulp]); lastpart = bytes.unpack(this.ULP_inst.scale_bits[ulp]); // unpack( &pbytes, &lastpart, // this.ULP_inst.scale_bits[ulp], &pos); idxForMax = bytes.packcombine(idxForMax, lastpart, this.ULP_inst.scale_bits[ulp]); // System.out.println("idxForMax = " + idxForMax); // packcombine(&idxForMax, lastpart, // this.ULP_inst.scale_bits[ulp]); for (k = 0;k < this.ULP_inst.state_short_len;k++) { lastpart = bytes.unpack(this.ULP_inst.state_bits[ulp]); // unpack( &pbytes, &lastpart, // this.ULP_inst.state_bits[ulp], &pos); idxVec[k] = bytes.packcombine(idxVec[k], lastpart, this.ULP_inst.state_bits[ulp]); // System.out.println("idxVec["+k+"] = " + idxVec[k]); // packcombine(idxVec+k, lastpart, // this.ULP_inst.state_bits[ulp]); } /* 23/22 (20ms/30ms) sample block */ for (k = 0;k < ilbc_constants.CB_NSTAGES;k++) { lastpart = bytes.unpack(this.ULP_inst.extra_cb_index[k, ulp]); // unpack( &pbytes, &lastpart, // this.ULP_inst.extra_cb_index[k,ulp], // &pos); extra_cb_index[k] = bytes.packcombine(extra_cb_index[k], lastpart, this.ULP_inst.extra_cb_index[k, ulp]); // System.out.println("extra_cb_index["+k+"] = " + extra_cb_index[k]); // packcombine(extra_cb_index+k, lastpart, // this.ULP_inst.extra_cb_index[k,ulp]); } for (k = 0;k < ilbc_constants.CB_NSTAGES;k++) { lastpart = bytes.unpack(this.ULP_inst.extra_cb_gain[k, ulp]); // unpack( &pbytes, &lastpart, // this.ULP_inst.extra_cb_gain[k,ulp], // &pos); extra_gain_index[k] = bytes.packcombine(extra_gain_index[k], lastpart, this.ULP_inst.extra_cb_gain[k, ulp]); // System.out.println("extra_gain_index["+k+"] = " + extra_gain_index[k]); // packcombine(extra_gain_index+k, lastpart, // this.ULP_inst.extra_cb_gain[k,ulp]); } /* The two/four (20ms/30ms) 40 sample sub-blocks */ for (i = 0;i < this.ULP_inst.nasub;i++) { for (k = 0;k < ilbc_constants.CB_NSTAGES;k++) { lastpart = bytes.unpack(this.ULP_inst.cb_index[i, k, ulp]); // unpack( &pbytes, &lastpart, // this.ULP_inst.cb_index[i,k,ulp], // &pos); cb_index[i * ilbc_constants.CB_NSTAGES + k] = bytes.packcombine(cb_index[i * ilbc_constants.CB_NSTAGES + k], lastpart, this.ULP_inst.cb_index[i, k, ulp]); // System.out.println("cb_index["+(i*ilbc_constants.CB_NSTAGES+k)+"] = " + cb_index[(i*ilbc_constants.CB_NSTAGES+k)]); // packcombine(cb_index+i*CB_NSTAGES+k, lastpart, // this.ULP_inst.cb_index[i,k,ulp]); } } for (i = 0;i < this.ULP_inst.nasub;i++) { for (k = 0;k < ilbc_constants.CB_NSTAGES;k++) { lastpart = bytes.unpack(this.ULP_inst.cb_gain[i, k, ulp]); gain_index[i * ilbc_constants.CB_NSTAGES + k] = bytes.packcombine(gain_index[i * ilbc_constants.CB_NSTAGES + k], lastpart, this.ULP_inst.cb_gain[i, k, ulp]); // System.out.println("gain_index["+(i*ilbc_constants.CB_NSTAGES+k)+"] = " + gain_index[(i*ilbc_constants.CB_NSTAGES+k)]); } } } /* Extract last bit. If it is 1 this indicates an empty/lost frame */ last_bit = bytes.unpack(1); // System.out.println("last_bit = " + last_bit); /* Check for bit errors or empty/lost frames */ if (start < 1) mode = 0; if (this.ULP_inst.mode == 20 && start > 3) mode = 0; if (this.ULP_inst.mode == 30 && start > 5) mode = 0; if (last_bit == 1) mode = 0; if (mode == 1) { /* No bit errors was detected, continue decoding */ /* adjust index */ index_conv_dec(cb_index); // for (int li = 0; li < cb_index.Length; li++) // System.out.println("cb_index["+li+"] = " + cb_index[li]); /* decode the lsf */ SimplelsfDEQ(lsfdeq, lsf_i, this.ULP_inst.lpc_n); // for (int li = 0; li < lsfdeq.Length; li++) // System.out.println("lsfdeq["+li+"] = " + lsfdeq[li]); ilbc_common.LSF_check(lsfdeq, ilbc_constants.LPC_FILTERORDER, this.ULP_inst.lpc_n); // check=ilbc_common.LSF_check(lsfdeq, ilbc_constants.LPC_FILTERORDER, // this.ULP_inst.lpc_n); // System.out.println("check returns " + check); DecoderInterpolateLSF(syntdenum, weightdenum, lsfdeq, ilbc_constants.LPC_FILTERORDER); // for (int li = 0; li < syntdenum.Length; li++) // System.out.println("syntdenum[" + li + "] = " + syntdenum[li]); // for (int li = 0; li < weightdenum.Length; li++) // System.out.println("weightdenum[" + li + "] = " + weightdenum[li]); Decode(decresidual, start, idxForMax, idxVec, syntdenum, cb_index, gain_index, extra_cb_index, extra_gain_index, state_first); // for (int li = 0; li < decresidual.Length; li++) // System.out.println("decresidual[" + li + "] = " + decresidual[li]); /* preparing the plc for a future loss! */ doThePLC(PLCresidual, PLClpc, 0, decresidual, syntdenum, (ilbc_constants.LPC_FILTERORDER + 1) * (this.ULP_inst.nsub - 1), last_lag); System.Array.Copy(PLCresidual, 0, decresidual, 0, this.ULP_inst.blockl); // for (int li = 0; li < decresidual.Length; li++) // System.out.println("decresidual[" + li + "] = " + decresidual[li]); // memcpy(decresidual, PLCresidual, // this.ULP_inst.blockl*sizeof(float)); } } if (mode == 0) { /* the data is bad (either a PLC call * was made or a severe bit error was detected) */ /* packet loss conceal */ for (int li = 0;li < ilbc_constants.BLOCKL_MAX;li++) zeros[li] = 0.0f; // memset(zeros, 0, BLOCKL_MAX*sizeof(float)); one[0] = 1; for (int li = 0;li < ilbc_constants.LPC_FILTERORDER;li++) one[li + 1] = 0.0f; // memset(one+1, 0, LPC_FILTERORDER*sizeof(float)); start = 0; doThePLC(PLCresidual, PLClpc, 1, zeros, one, 0, last_lag); System.Array.Copy(PLCresidual, 0, decresidual, 0, this.ULP_inst.blockl); // memcpy(decresidual, PLCresidual, // this.ULP_inst.blockl*sizeof(float)); order_plus_one = ilbc_constants.LPC_FILTERORDER + 1; for (i = 0;i < this.ULP_inst.nsub;i++) { System.Array.Copy(PLClpc, 0, syntdenum, (i * order_plus_one), order_plus_one); // memcpy(syntdenum+(i*order_plus_one), PLClpc, // order_plus_one*sizeof(float)); } } if (this.use_enhancer == 1) { /* post filtering */ this.last_lag = enhancerInterface(data, decresidual); // System.out.println("last_lag : " + this.last_lag); // for (int li = 0; li < data.Length; li++) // System.out.println("data["+li+"] = " + data[li]); // for (li = 0; li < /* synthesis filtering */ if (this.ULP_inst.mode == 20) { /* Enhancer has 40 samples delay */ i = 0; // System.out.println("run 1"); syntFilter(data, i * ilbc_constants.SUBL, this.old_syntdenum, (i + this.ULP_inst.nsub - 1) * (ilbc_constants.LPC_FILTERORDER + 1), ilbc_constants.SUBL, this.syntMem); // System.out.println("runs 2"); for (i = 1;i < this.ULP_inst.nsub;i++) { // System.out.println("pass " + i); syntFilter(data, i * ilbc_constants.SUBL, syntdenum, (i - 1) * (ilbc_constants.LPC_FILTERORDER + 1), ilbc_constants.SUBL, this.syntMem); // System.out.println("pass " + i + " ends"); } // for (int li = 0; li < data.Length; li++) // System.out.println("psdata["+li+"] = " + data[li]); } else if (this.ULP_inst.mode == 30) { /* Enhancer has 80 samples delay */ // System.out.println("runs 3"); for (i = 0;i < 2;i++) { syntFilter(data, i * ilbc_constants.SUBL, this.old_syntdenum, (i + this.ULP_inst.nsub - 2) * (ilbc_constants.LPC_FILTERORDER + 1), ilbc_constants.SUBL, this.syntMem); } for (i = 2;i < this.ULP_inst.nsub;i++) { // System.out.println("runs 4"); syntFilter(data, i * ilbc_constants.SUBL, syntdenum, (i - 2) * (ilbc_constants.LPC_FILTERORDER + 1), ilbc_constants.SUBL, this.syntMem); } } } else { /* Find last lag */ lag = 20; maxcc = xCorrCoef(decresidual, ilbc_constants.BLOCKL_MAX - ilbc_constants.ENH_BLOCKL, decresidual, ilbc_constants.BLOCKL_MAX - ilbc_constants.ENH_BLOCKL - lag, ilbc_constants.ENH_BLOCKL); for (ilag = 21;ilag < 120;ilag++) { cc = xCorrCoef(decresidual, ilbc_constants.BLOCKL_MAX - ilbc_constants.ENH_BLOCKL, decresidual, ilbc_constants.BLOCKL_MAX - ilbc_constants.ENH_BLOCKL - ilag, ilbc_constants.ENH_BLOCKL); if (cc > maxcc) { maxcc = cc; lag = ilag; } } this.last_lag = lag; /* copy data and run synthesis filter */ System.Array.Copy(decresidual, 0, data, 0, this.ULP_inst.blockl); // memcpy(data, decresidual, // this.ULP_inst.blockl*sizeof(float)); // System.out.println("runs 5"); for (i = 0;i < this.ULP_inst.nsub;i++) { syntFilter(data, i * ilbc_constants.SUBL, syntdenum, i * (ilbc_constants.LPC_FILTERORDER + 1), ilbc_constants.SUBL, this.syntMem); } } /* high pass filtering on output if desired, otherwise copy to out */ hpOutput(data, this.ULP_inst.blockl, decblock, this.hpomem); /* memcpy(decblock,data,iLBCdec_inst->blockl*sizeof(float));*/ System.Array.Copy(syntdenum, 0, this.old_syntdenum, 0, this.ULP_inst.nsub * (ilbc_constants.LPC_FILTERORDER + 1)); // memcpy(this.old_syntdenum, syntdenum, // this.ULP_inst.nsub*(LPC_FILTERORDER+1)*sizeof(float)); this.prev_enh_pl = 0; if (mode == 0) { /* PLC was used */ this.prev_enh_pl = 1; } }
// public int decode(short decoded_data[], short encoded_data[], int mode) // { // return this.ULP_inst.blockl; // } public short decode( /* (o) Number of decoded samples */ short[] decoded_data, /* (o) Decoded signal block*/ short[] encoded_data, /* (i) Encoded bytes */ short mode) /* (i) 0=PL, 1=Normal */ { int k; float[] decblock = new float[ilbc_constants.BLOCKL_MAX]; float dtmp; // char en_data[] = new char [this.ULP_inst.no_of_bytes]; bitstream en_data = new bitstream(this.ULP_inst.no_of_bytes); /* check if mode is valid */ if ((mode < 0) || (mode > 1)) { //System.Diagnostics.Debug.WriteLine("\nERROR - Wrong mode - 0, 1 allowed\n"); throw new System.ArgumentException("mode"); } /* do actual decoding of block */ for (k = 0;k < encoded_data.Length;k++) { en_data.buffer[2 * k + 1] = (byte) (encoded_data[k] >> 8); en_data.buffer[2 * k] = (byte) (encoded_data[k] & 0xff); // System.out.println("on decode " + (en_data.buffer[2*k]+0) + " et " + (en_data.buffer[2*k+1]+0)); } iLBC_decode(decblock, en_data, mode); /* convert to short */ for (k = 0;k < this.ULP_inst.blockl;k++) { dtmp = decblock[k]; // System.out.println("on a eu : " + dtmp); if (dtmp < ilbc_constants.MIN_SAMPLE) dtmp = ilbc_constants.MIN_SAMPLE; else if (dtmp > ilbc_constants.MAX_SAMPLE) dtmp = ilbc_constants.MAX_SAMPLE; decoded_data[k] = (short) dtmp; } return ((short) this.ULP_inst.blockl); }