|
package cn.org.hentai.jtt1078.codec.g726;
|
|
|
import cn.org.hentai.jtt1078.codec.G711Codec;
|
import cn.org.hentai.jtt1078.codec.G711UCodec;
|
|
/** Common routines for G.721 and G.723 conversions.
|
* <p>
|
* This implementation is based on the ANSI-C language reference implementations
|
* of the CCITT (International Telegraph and Telephone Consultative Committee)
|
* G.711, G.721 and G.723 voice compressions, provided by Sun Microsystems, Inc.
|
* <p>
|
* Acknowledgement to Sun Microsystems, Inc. for having released the original
|
* ANSI-C source code to the public domain.
|
*/
|
public abstract class G726 {
|
|
// ##### C-to-Java conversion: #####
|
// short becomes int
|
// char becomes int
|
// unsigned char becomes int
|
|
|
// *************************** STATIC ***************************
|
|
/** ISDN u-law */
|
public static final int AUDIO_ENCODING_ULAW=1;
|
|
/** ISDN A-law */
|
public static final int AUDIO_ENCODING_ALAW=2;
|
|
/** PCM 2's-complement (0-center) */
|
public static final int AUDIO_ENCODING_LINEAR=3;
|
|
|
|
/** The first 15 values, powers of 2. */
|
private static final /*short*/int[] power2 = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000 };
|
|
|
/** Quantizes the input val against the table of size short integers.
|
* It returns i if table[i-1]<=val<table[i].
|
* <p>
|
* Using linear search for simple coding. */
|
private static int quan(int val, /*short*/int[] table, int size) {
|
|
int i;
|
for (i=0; i<size; i++) if (val<table[i]) break;
|
return i;
|
}
|
|
|
/** Given a raw sample, 'd', of the difference signal and a
|
* quantization step size scale factor, 'y', this routine returns the
|
* ADPCM codeword to which that sample gets quantized. The step
|
* size scale factor division operation is done in the log base 2 domain
|
* as a subtraction.
|
* <br>
|
* @param d - Raw difference signal sample
|
* @param y - Step size multiplier
|
* @param table - Quantization table
|
* @param size - Table size of short integers
|
*/
|
protected static int quantize(int d, int y, /*short*/int[] table, int size) {
|
|
/* LOG
|
* Compute base 2 log of 'd', and store in 'dl'.
|
*/
|
/*short*/int dqm=Math.abs(d); /* Magnitude of 'd' */
|
|
/*short*/int exp=quan(dqm>>1, power2, 15); /* Integer part of base 2 log of 'd' */
|
|
/*short*/int mant=((dqm<<7)>>exp)&0x7F; /* Fractional part of base 2 log */
|
|
/*short*/int dl=(exp<<7)+mant; /* Log of magnitude of 'd' */
|
|
/* SUBTB
|
* "Divide" by step size multiplier.
|
*/
|
/* Step size scale factor normalized log */
|
/*short*/int dln=dl-(y>>2);
|
|
/* QUAN
|
* Obtain codword i for 'd'.
|
*/
|
int i=quan(dln, table, size);
|
if (d<0) /* take 1's complement of i */
|
return ((size<<1)+1-i);
|
else if (i==0) /* take 1's complement of 0 */
|
return ((size<<1)+1); /* new in 1988 */
|
else
|
return (i);
|
}
|
|
|
/** Returns reconstructed difference signal 'dq' obtained from
|
* codeword 'i' and quantization step size scale factor 'y'.
|
* Multiplication is performed in log base 2 domain as addition.
|
* @param sign - 0 for non-negative value
|
* @param dqln - G.72x codeword
|
* @param y - Step size multiplier
|
*/
|
protected static int reconstruct(int sign, int dqln, int y) {
|
|
/* Log of 'dq' magnitude */
|
/*short*/int dql=dqln+(y>>2); /* ADDA */
|
|
if (dql<0) {
|
return ((sign!=0)? -0x8000 : 0);
|
}
|
else {
|
/* ANTILOG */
|
/* Integer part of log */
|
/*short*/int dex=(dql>>7)&15;
|
/*short*/int dqt=128+(dql&127);
|
/* Reconstructed difference signal sample */
|
/*short*/int dq=(dqt<<7)>>(14-dex);
|
return ((sign!=0)? (dq-0x8000) : dq);
|
}
|
}
|
|
|
/** updates the state variables for each output code
|
* @param code_size - distinguish 723_40 with others
|
* @param y - quantizer step size
|
* @param wi - scale factor multiplier
|
* @param fi - for long/short term energies
|
* @param dq - quantized prediction difference
|
* @param sr - reconstructed signal
|
* @param dqsez - difference from 2-pole predictor
|
* @param state - coder state
|
*/
|
protected static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, G726State state) {
|
|
int cnt;
|
/*short*/int mag, exp, mant; /* Adaptive predictor, FLOAT A */
|
/*short*/int a2p; /* LIMC */
|
/*short*/int a1ul; /* UPA1 */
|
/*short*/int ua2, pks1; /* UPA2 */
|
/*short*/int uga2a, fa1;
|
/*short*/int uga2b;
|
/*char*/int tr; /* tone/transition detector */
|
/*short*/int ylint, thr2, dqthr;
|
/*short*/int ylfrac, thr1;
|
/*short*/int pk0;
|
|
// ##### C-to-Java conversion: #####
|
// init a2p
|
a2p=0;
|
|
pk0=(dqsez<0)? 1 : 0; /* needed in updating predictor poles */
|
|
mag=dq&0x7FFF; /* prediction difference magnitude */
|
/* TRANS */
|
ylint=state.yl>>15; /* exponent part of yl */
|
ylfrac=(state.yl>>10)&0x1F; /* fractional part of yl */
|
thr1=(32+ylfrac)<<ylint; /* threshold */
|
thr2=(ylint>9)? 31<<10 : thr1; /* limit thr2 to 31<<10 */
|
dqthr=(thr2+(thr2>>1))>>1; /* dqthr=0.75 * thr2 */
|
if (state.td==0) /* signal supposed voice */
|
tr=0;
|
else
|
if (mag<=dqthr) /* supposed data, but small mag */
|
tr=0; /* treated as voice */
|
else /* signal is data (modem) */
|
tr=1;
|
|
/* Quantizer scale factor adaptation. */
|
|
/* FUNCTW&FILTD&DELAY */
|
/* update non-steady state step size multiplier */
|
state.yu=y+((wi-y)>>5);
|
|
/* LIMB */
|
if (state.yu<544) /* 544<=yu<=5120 */
|
state.yu=544;
|
else
|
if (state.yu>5120)
|
state.yu=5120;
|
|
/* FILTE&DELAY */
|
/* update steady state step size multiplier */
|
state.yl+=state.yu+((-state.yl)>>6);
|
|
/*
|
* Adaptive predictor coefficients.
|
*/
|
if (tr==1) {
|
/* reset a's and b's for modem signal */
|
state.a[0]=0;
|
state.a[1]=0;
|
state.b[0]=0;
|
state.b[1]=0;
|
state.b[2]=0;
|
state.b[3]=0;
|
state.b[4]=0;
|
state.b[5]=0;
|
}
|
else {
|
/* update a's and b's */
|
pks1=pk0^state.pk[0]; /* UPA2 */
|
|
/* update predictor pole a[1] */
|
a2p=state.a[1]-(state.a[1]>>7);
|
if (dqsez != 0) {
|
fa1=(pks1!=0)? state.a[0] : -state.a[0];
|
if (fa1<-8191) /* a2p=function of fa1 */
|
a2p-=0x100;
|
else
|
if (fa1>8191)
|
a2p+=0xFF;
|
else
|
a2p+=fa1>>5;
|
|
if ((pk0^state.pk[1])!=0) {
|
/* LIMC */
|
if (a2p<=-12160)
|
a2p=-12288;
|
else
|
if (a2p>=12416)
|
a2p=12288;
|
else
|
a2p-=0x80;
|
}
|
else
|
if (a2p<=-12416)
|
a2p=-12288;
|
else
|
if (a2p>=12160)
|
a2p=12288;
|
else
|
a2p+=0x80;
|
}
|
|
/* TRIGB&DELAY */
|
state.a[1]=a2p;
|
|
/* UPA1 */
|
/* update predictor pole a[0] */
|
state.a[0] -= state.a[0]>>8;
|
if (dqsez != 0)
|
if (pks1==0)
|
state.a[0]+=192;
|
else
|
state.a[0] -= 192;
|
|
/* LIMD */
|
a1ul=15360-a2p;
|
if (state.a[0]<-a1ul)
|
state.a[0]=-a1ul;
|
else if (state.a[0]>a1ul)
|
state.a[0]=a1ul;
|
|
/* UPB : update predictor zeros b[6] */
|
for (cnt=0; cnt<6; cnt++) {
|
|
if (code_size==5) /* for 40Kbps G.723 */
|
state.b[cnt]-=state.b[cnt]>>9;
|
else /* for G.721 and 24Kbps G.723 */
|
state.b[cnt]-=state.b[cnt]>>8;
|
if ((dq&0x7FFF)!=0) {
|
/* XOR */
|
if ((dq^state.dq[cnt])>=0)
|
state.b[cnt]+=128;
|
else
|
state.b[cnt]-=128;
|
}
|
}
|
}
|
|
for (cnt=5; cnt>0; cnt--) state.dq[cnt]=state.dq[cnt-1];
|
/* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */
|
if (mag==0) {
|
state.dq[0]=(dq>=0)? 0x20 : 0xFC20;
|
}
|
else {
|
exp=quan(mag, power2, 15);
|
state.dq[0]=(dq>=0) ? (exp<<6)+((mag<<6)>>exp) : (exp<<6)+((mag<<6)>>exp)-0x400;
|
}
|
|
state.sr[1]=state.sr[0];
|
/* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */
|
if (sr==0) {
|
state.sr[0]=0x20;
|
}
|
else
|
if (sr>0) {
|
exp=quan(sr, power2, 15);
|
state.sr[0]=(exp<<6)+((sr<<6)>>exp);
|
}
|
else
|
if (sr>-32768) {
|
mag=-sr;
|
exp=quan(mag, power2, 15);
|
state.sr[0]=(exp<<6)+((mag<<6)>>exp)-0x400;
|
}
|
else
|
state.sr[0]=0xFC20;
|
|
/* DELAY A */
|
state.pk[1]=state.pk[0];
|
state.pk[0]=pk0;
|
|
/* TONE */
|
if (tr==1) /* this sample has been treated as data */
|
state.td=0; /* next one will be treated as voice */
|
else
|
if (a2p<-11776) /* small sample-to-sample correlation */
|
state.td=1; /* signal may be data */
|
else /* signal is voice */
|
state.td=0;
|
|
/*
|
* Adaptation speed control.
|
*/
|
state.dms+=(fi-state.dms)>>5; /* FILTA */
|
state.dml+=(((fi<<2)-state.dml)>>7); /* FILTB */
|
|
if (tr==1)
|
state.ap=256;
|
else
|
if (y<1536) /* SUBTC */
|
state.ap+=(0x200-state.ap)>>4;
|
else
|
if (state.td==1)
|
state.ap+=(0x200-state.ap)>>4;
|
else
|
if (Math.abs((state.dms<<2)-state.dml)>=(state.dml>>3))
|
state.ap+=(0x200-state.ap)>>4;
|
else
|
state.ap+=(-state.ap)>>4;
|
}
|
|
/** At the end of ADPCM decoding, it simulates an encoder which may be receiving
|
* the output of this decoder as a tandem process. If the output of the
|
* simulated encoder differs from the input to this decoder, the decoder output
|
* is adjusted by one level of A-law or u-law codes.
|
*
|
* @param sr - decoder output linear PCM sample,
|
* @param se - predictor estimate sample,
|
* @param y - quantizer step size,
|
* @param i - decoder input code,
|
* @param sign - sign bit of code i
|
*
|
* @return adjusted A-law or u-law compressed sample.
|
*/
|
protected static int tandem_adjust_alaw(int sr, int se, int y, int i, int sign, /*short*/int[] qtab) {
|
|
/*unsigned char*/int sp; /* A-law compressed 8-bit code */
|
/*short*/int dx; /* prediction error */
|
/*char*/int id; /* quantized prediction error */
|
int sd; /* adjusted A-law decoded sample value */
|
int im; /* biased magnitude of i */
|
int imx; /* biased magnitude of id */
|
|
if (sr<=-32768) sr=-1;
|
sp= G711Codec.linear2alaw((short)((sr>>1)<<3)); /* short to A-law compression */
|
dx=(G711Codec.alaw2linear((byte)sp)>>2)-se; /* 16-bit prediction error */
|
id=quantize(dx, y, qtab, sign-1);
|
|
if (id==i) {
|
/* no adjustment on sp */
|
return (sp);
|
}
|
else {
|
/* sp adjustment needed */
|
/* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */
|
im=i^sign; /* 2's complement to biased unsigned */
|
imx=id^sign;
|
|
if (imx>im) {
|
/* sp adjusted to next lower value */
|
if ((sp&0x80)!=0) {
|
sd=(sp==0xD5)? 0x55 : ((sp^0x55)-1)^0x55;
|
}
|
else {
|
sd=(sp==0x2A)? 0x2A : ((sp^0x55)+1)^0x55;
|
}
|
}
|
else {
|
/* sp adjusted to next higher value */
|
if ((sp&0x80)!=0)
|
sd=(sp==0xAA)? 0xAA : ((sp^0x55)+1)^0x55;
|
else
|
sd=(sp==0x55)? 0xD5 : ((sp^0x55)-1)^0x55;
|
}
|
return (sd);
|
}
|
}
|
|
/** @param sr - decoder output linear PCM sample
|
* @param se - predictor estimate sample
|
* @param y - quantizer step size
|
* @param i - decoder input code
|
* @param sign
|
* @param qtab
|
*/
|
protected static int tandem_adjust_ulaw(int sr, int se, int y, int i, int sign, /*short*/int[] qtab) {
|
|
/*unsigned char*/int sp; /* u-law compressed 8-bit code */
|
/*short*/int dx; /* prediction error */
|
/*char*/int id; /* quantized prediction error */
|
int sd; /* adjusted u-law decoded sample value */
|
int im; /* biased magnitude of i */
|
int imx; /* biased magnitude of id */
|
|
if (sr<=-32768) sr=0;
|
sp= G711UCodec.linear2ulaw((short)(sr<<2)); /* short to u-law compression */
|
dx=(G711UCodec.ulaw2linear((byte)sp)>>2)-se; /* 16-bit prediction error */
|
id=quantize(dx, y, qtab, sign-1);
|
if (id==i) {
|
return (sp);
|
}
|
else {
|
/* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */
|
im=i^sign; /* 2's complement to biased unsigned */
|
imx=id^sign;
|
if (imx>im) {
|
/* sp adjusted to next lower value */
|
if ((sp&0x80)!=0)
|
sd=(sp==0xFF)? 0x7E : sp+1;
|
else
|
sd=(sp==0)? 0 : sp-1;
|
|
}
|
else {
|
/* sp adjusted to next higher value */
|
if ((sp&0x80)!=0)
|
sd=(sp==0x80)? 0x80 : sp-1;
|
else
|
sd=(sp==0x7F)? 0xFE : sp+1;
|
}
|
return (sd);
|
}
|
}
|
|
|
// ##### C-to-Java conversion: #####
|
|
/** Converts a byte into an unsigned int. */
|
protected static int unsignedInt(byte b) {
|
return ((int)b+0x100)&0xFF;
|
}
|
|
// ##### 2 bytes to int conversion: #####
|
|
/** Converts 2 little-endian-bytes into an unsigned int. */
|
public static int unsignedIntLittleEndian(byte hi_b, byte lo_b) {
|
return (unsignedInt(hi_b)<<8) + unsignedInt(lo_b);
|
}
|
|
/** Converts 2 little-endian-bytes into a signed int. */
|
public static int signedIntLittleEndian(byte hi_b, byte lo_b) {
|
int sign_bit=hi_b>>7;
|
return (sign_bit==0)? (unsignedInt(hi_b)<<8) + unsignedInt(lo_b) : (-1^0x7FFF)^(((unsignedInt(hi_b)&0x7F)<<8) + unsignedInt(lo_b));
|
}
|
|
|
// ************************* NON-STATIC *************************
|
|
/** Encoding state */
|
G726State state;
|
|
int type;
|
|
/** Creates a new G726 processor, that can be used to encode from or decode do PCM audio data. */
|
public G726(int type) {
|
this.type = type;
|
state=new G726State();
|
}
|
|
public int getType() {
|
return type;
|
}
|
|
/** Encodes the input vale of linear PCM, A-law or u-law data sl and returns
|
* the resulting code. -1 is returned for unknown input coding value. */
|
public abstract int encode(int sl, int in_coding);
|
|
|
/** Encodes the input chunk in_buff of linear PCM, A-law or u-law data and returns
|
* the G726 encoded chuck into out_buff. <br>
|
* It returns the actual size of the output data, or -1 in case of unknown
|
* in_coding value. */
|
public abstract int encode(byte[] in_buff, int in_offset, int in_len, int in_coding, byte[] out_buff, int out_offset);
|
|
|
/** Decodes a 4-bit code of G.72x encoded data of i and
|
* returns the resulting linear PCM, A-law or u-law value.
|
* return -1 for unknown out_coding value. */
|
public abstract int decode(int i, int out_coding);
|
|
|
/** Decodes the input chunk in_buff of G726 encoded data and returns
|
* the linear PCM, A-law or u-law chunk into out_buff. <br>
|
* It returns the actual size of the output data, or -1 in case of unknown
|
* out_coding value. */
|
public abstract int decode(byte[] in_buff, int in_offset, int in_len, int out_coding, byte[] out_buff, int out_offset);
|
|
}
|