#include "G721.h"
/*****************************************************
*
* G.721 Encoder
*
******************************************************/
#include "G721.h"
/*****************************************************
*
* G.721 Encoder
*
******************************************************/
void G721Encoder(INT16S *Indata_P16s, INT8U *Outdata_P8u, INT16S FrameLen_16u, AdpcmState_ST *State_ST)
{
// INT16S *In_P16s; /* Input buffer pointer */
INT8S *Out_P16u; /* output buffer pointer */
INT16S Sign_b; /* Current adpcm sign bit */
INT16S CurIn_16s; /* Current input sample value */
INT16S Diff_16s; /* Difference between val and valprev */
INT16S ValuePred_16s; /* Predicted output value */
INT16S Index_16s; /* Current step change index */ //zgx
INT16S BufStep_16s; /* toggle between OutBuf_16u/output */
INT16S CurOut_16u; /* Current adpcm output value */
INT16S Step_16u; /* Stepsize */
INT16S VP_Diff_16u; /* Current change to ValuePred_16s */
INT16S OutBuf_16u; /* place to keep previous 4-bit value */
Out_P16u = (INT8S *) Outdata_P8u;
ValuePred_16s = State_ST->PreValue_16s;
Index_16s = (INT16S)State_ST->Index_8u;
Step_16u = StepSizeTable_16u[Index_16s];
BufStep_16s = 1;
while (FrameLen_16u-- > 0 ) {
CurIn_16s = *Indata_P16s++;
/* Step 1 - compute difference with previous value */
Diff_16s = CurIn_16s - ValuePred_16s;
if(Diff_16s < 0) {
Sign_b = 8;
Diff_16s = -Diff_16s;
}
else
Sign_b = 0;
/* Step_16u 2 - Divide and clamp */
/* Note:
** This code *approximately* computes:
** CurOut_16u = Diff_16s*4/Step_16u;
** VP_Diff_16u = (CurOut_16u+0.5)*Step_16u/4;
** but in shift Step_16u bits are dropped. The net result of this is
** that even if you have fast mul/div hardware you cannot put it to
** good use since the fixup would be too expensive.
*/
CurOut_16u = 0;
VP_Diff_16u = Step_16u >> 3;
if (Diff_16s >= Step_16u) {
CurOut_16u = 4;
Diff_16s -= Step_16u;
VP_Diff_16u += Step_16u;
}
Step_16u >>= 1;
if (Diff_16s >= Step_16u) {
CurOut_16u |= 2;
Diff_16s -= Step_16u;
VP_Diff_16u += Step_16u;
}
Step_16u >>= 1;
if (Diff_16s >= Step_16u) {
CurOut_16u |= 1;
VP_Diff_16u += Step_16u;
}
/* Step 3 - Update previous value */
if (Sign_b)
ValuePred_16s -= VP_Diff_16u;
else
ValuePred_16s += VP_Diff_16u;
/* Step 4 - Clamp previous value to 16 bits */
if ( ValuePred_16s < -32768 )
ValuePred_16s = -32768;
else if( ValuePred_16s > 32767 )
ValuePred_16s = 32767;
/* Step 5 - Assemble value, update Index_16s and Step_16u values */
CurOut_16u |= Sign_b;
Index_16s += IndexTable_8s[CurOut_16u];
if (Index_16s < 0) Index_16s = 0;
if (Index_16s > 88) Index_16s = 88;
Step_16u = StepSizeTable_16u[Index_16s];
/* Step 6 - Output value */
if (BufStep_16s != 0) {
OutBuf_16u = (CurOut_16u << 4) & 0xf0;
} else
*Out_P16u++ = (CurOut_16u & 0x0f) | OutBuf_16u;
BufStep_16s = !BufStep_16s;
}//while (FrameLen_16u-- > 0 )
/* Output last step, if needed */
if ( BufStep_16s == 0 )
*Out_P16u++ = (INT8U)OutBuf_16u;
State_ST->PreValue_16s = (INT16S)ValuePred_16s;
State_ST->Index_8u = (INT8U)Index_16s;
}
/*****************************************************
*
* G.721 Decoder
*
******************************************************/
void G721Decoder(INT8U *Indata_P8u, INT16S *Outdata_P16s, INT16S FrameLen_16u, AdpcmState_ST *State_ST)
{
INT8S *Indata_P8s; /* Input buffer pointer */
//short *outp; /* output buffer pointer */
INT16S Sign_16s; /* Current adpcm sign bit */
INT16S CurOut_16s; /* Current adpcm output value */
INT16S Step_16s; /* Stepsize */
INT16S ValuePred_16s; /* Predicted value */
INT16S VP_Diff_16s; /* Current change to ValuePred_16s */
INT16S Index_16s; /* Current step change Index_16s */
INT16S InBuf_16s; /* place to keep next 4-bit value */
INT16S bufferstep; /* toggle between inputbuffer/input */
Indata_P8s = (INT8S *) Indata_P8u;
ValuePred_16s = State_ST->PreValue_16s;
Index_16s = State_ST->Index_8u;
Step_16s = StepSizeTable_16u[Index_16s];
bufferstep = 0;
while (FrameLen_16u-- >0) {
/* Step 1 - get the CurOut_16s value */
if ( bufferstep ) {
CurOut_16s = InBuf_16s & 0xf;
} else {
InBuf_16s = *Indata_P8s++;
CurOut_16s = (InBuf_16s >> 4) & 0xf;
}
bufferstep = !bufferstep;
/* Step 2 - Find new Index_16s value (for later) */
Index_16s += IndexTable_8s[CurOut_16s];
if ( Index_16s < 0 ) Index_16s = 0;
if ( Index_16s > 88 ) Index_16s = 88;
/* Step 3 - Separate Sign_16s and magnitude */
Sign_16s = CurOut_16s & 8;
CurOut_16s = CurOut_16s & 7;
/* Step 4 - Compute difference and new predicted value */
/*
** Computes 'VP_Diff_16s = (CurOut_16s+0.5)*Step_16s/4', but see comment
** in adpcm_coder.
*/
VP_Diff_16s = Step_16s >> 3;
if ( CurOut_16s & 4 ) VP_Diff_16s += Step_16s;
if ( CurOut_16s & 2 ) VP_Diff_16s += Step_16s>>1;
if ( CurOut_16s & 1 ) VP_Diff_16s += Step_16s>>2;
if ( Sign_16s )
ValuePred_16s -= VP_Diff_16s;
else
ValuePred_16s += VP_Diff_16s;
/* Step 5 - clamp output value */
if ( ValuePred_16s > 32767 )
ValuePred_16s = 32767;
else if ( ValuePred_16s < -32768 )
ValuePred_16s = -32768;
/* Step 6 - Update Step_16s value */
Step_16s = StepSizeTable_16u[Index_16s];
/* Step 7 - Output value */
*Outdata_P16s++ = ValuePred_16s;
}//while (FrameLen_16u-- >0)
State_ST->PreValue_16s = ValuePred_16s;
State_ST->Index_8u = Index_16s;
}