📄 g726.cpp
字号:
@brief UPA2 function from %G726 Section 4.2.6 - Adaptative predictor and reconstructed signal calculator
*/
inline static void UPA2(int PK0,int PK1,int PK2,int A1,int A2,uint SIGPK,int& A2T)
{
CHECK_TC(PK0,1);
CHECK_TC(PK1,1);
CHECK_TC(PK2,1);
CHECK_TC(A1,16);
CHECK_TC(A2,16);
CHECK_UNSIGNED(SIGPK,1);
uint UGA2;
if(SIGPK==0)
{
int UGA2A = (PK0^PK2) ? -16384 : 16384;
int FA1;
if(A1<-8191) FA1 = -8191<<2;
else if(A1>8191) FA1 = 8191<<2;
else FA1 = A1<<2;
int FA = (PK0^PK1) ? FA1 : -FA1;
UGA2 = (UGA2A+FA) >> 7;
}
else
UGA2 = 0;
A2T = (int16)(A2+UGA2-(A2>>7));
CHECK_TC(A2T,16);
}
/**
@brief UPB function from %G726 Section 4.2.6 - Adaptative predictor and reconstructed signal calculator
*/
inline static void UPB(uint RATE,int Un,int Bn,uint DQ,int& BnP)
{
CHECK_TC(Un,1);
CHECK_TC(Bn,16);
CHECK_SM(DQ,16);
int UGBn;
if(DQ&32767)
UGBn = Un ? -128 : 128;
else
UGBn = 0;
int ULBn = (RATE==5) ? Bn>>9 : Bn>>8;
BnP = (int16)(Bn+UGBn-ULBn);
CHECK_TC(BnP,16);
}
/**
@brief XOR function from %G726 Section 4.2.6 - Adaptative predictor and reconstructed signal calculator
*/
inline static void XOR(uint DQn,uint DQ,int& Un)
{
CHECK_FL(DQn,11);
CHECK_SM(DQ,16);
Un = -(int)((DQn>>10)^(DQ>>15));
CHECK_TC(Un,1);
}
/**
@brief TONE function from %G726 Section 4.2.7 - Tone and transition detector
*/
inline static void TONE(int A2P,uint& TDP)
{
CHECK_TC(A2P,16);
TDP = A2P<(53760-65536);
CHECK_UNSIGNED(TDP,1);
}
/**
@brief TRANS function from %G726 Section 4.2.7 - Tone and transition detector
*/
inline static void TRANS(uint TD,uint YL,uint DQ,uint& TR)
{
CHECK_UNSIGNED(TD,1);
CHECK_UM(YL,19);
CHECK_SM(DQ,16);
uint DQMAG = DQ&32767;
uint YLINT = YL>>15;
uint YLFRAC = (YL>>10) & 31;
uint THR1 = (32+YLFRAC)<<YLINT;
uint THR2;
if(YLINT>9)
THR2 = 31<<10;
else
THR2 = THR1;
uint DQTHR = (THR2+(THR2>>1)) >> 1;
TR = DQMAG>DQTHR && TD;
CHECK_UNSIGNED(TR,1);
}
/**
@brief COMPRESS function from %G726 Section 4.2.8 - Output PCM format conversion and synchronous coding adjustment
*/
inline static void COMPRESS(int SR,uint LAW,uint& SP)
{
CHECK_TC(SR,16);
CHECK_UNSIGNED(LAW,1);
int x = SR;
#ifdef IMPLEMENT_G191_BUGS
// reproduce bugs in G191 reference implementation...
if(x==-0x8000)
x=-1;
else
if(!LAW && x<0) x--;
#endif
// Clamp to 14 bits...
if(x>=(1<<13))
x = (1<<13)-1;
else if(x<-(1<<13))
x = -(1<<13);
if(LAW)
SP = G711::ALawEncode(x<<2);
else
SP = G711::ULawEncode(x<<2);
CHECK_UNSIGNED(SP,8);
}
/**
@brief SYNC function from %G726 Section 4.2.8 - Output PCM format conversion and synchronous coding adjustment
*/
inline static void SYNC(uint RATE,uint I,uint SP,int DLNX,int DSX,uint LAW,uint& SD)
{
CHECK_UNSIGNED(SP,8);
CHECK_TC(DLNX,12);
CHECK_TC(DSX,1);
CHECK_UNSIGNED(LAW,1);
uint ID;
uint IM;
QUAN(RATE,DLNX,DSX,ID);
uint signMask = 1<<(RATE-1);
ID = ID^signMask;
IM = I^signMask;
uint s;
if(LAW)
{
s = SP^0x55;
if(!(s&0x80))
s = s^0x7f;
}
else
{
s = SP;
if(s&0x80)
s = s^0x7f;
}
// s = ALAW/uLAW code converted to range 0x00..0xff
// where 0x00 is most-negative and 0xff is most-positive
if(ID<IM)
{
if(s<0xff)
++s;
}
else if(ID>IM)
{
if(s>0x00)
{
--s;
if(s==0x7f && !LAW) --s; // TABLE 20/G.726 says uLaw 0xFF decrements to 0x7e and not 0x7f (!?)
}
}
// convert s back to ALAW/uLAW code
if(LAW)
{
if(!(s&0x80))
s = s^0x7f;
s = s^0x55;
}
else
{
if(s&0x80)
s = s^0x7f;
}
SD = s;
CHECK_UNSIGNED(SD,8);
}
/**
@brief LIMO function from %G726 Section A.3.5 - Output limiting (decoder only)
*/
inline static void LIMO(int SR,int& SO)
{
CHECK_TC(SR,16);
if(SR>=(1<<13))
SO = (1<<13)-1;
else if(SR<-(1<<13))
SO = -(1<<13);
else
SO = SR;
CHECK_TC(SO,14);
}
/** @} */ // End of group
/**
@defgroup g726_section4B Internal - Functional blocks from Section 4 of G726
@ingroup g726
Some of these have been broken into two parts, the first of which can generate
it's outputs using only the saved internal state from the previous itteration
of the algorithm.
@{
*/
/**
@brief FIGURE 4/G.726 from Section 4.2.1 - Input PCM format conversion and difference signal computation
*/
inline void G726::InputPCMFormatConversionAndDifferenceSignalComputation(uint S,int SE,int& D)
{
int SL;
EXPAND(S,LAW,SL);
SUBTA(SL,SE,D);
}
/**
@brief FIGURE 5/G.726 from Section 4.2.2 - Adaptive quantizer
*/
inline void G726::AdaptiveQuantizer(int D,uint Y,uint& I)
{
uint DL;
int DS;
LOG(D,DL,DS);
int DLN;
SUBTB(DL,Y,DLN);
QUAN(RATE,DLN,DS,I);
}
/**
@brief FIGURE 6/G.726 from Section 4.2.3 - Inverse adaptive quantizer
*/
inline void G726::InverseAdaptiveQuantizer(uint I,uint Y,uint& DQ)
{
int DQLN;
int DQS;
RECONST(RATE,I,DQLN,DQS);
int DQL;
ADDA(DQLN,Y,DQL);
ANTILOG(DQL,DQS,DQ);
}
/**
@brief FIGURE 7/G.726 (Part 1) from Section 4.2.4 - Quantizer scale factor adaptation
*/
inline void G726::QuantizerScaleFactorAdaptation1(uint AL,uint& Y)
{
MIX(AL,YU,YL,Y);
}
/**
@brief FIGURE 7/G.726 (Part 2) from Section 4.2.4 - Quantizer scale factor adaptation
*/
inline void G726::QuantizerScaleFactorAdaptation2(uint I,uint Y)
{
int WI;
FUNCTW(RATE,I,WI);
uint YUT;
FILTD(WI,Y,YUT);
uint YUP;
LIMB(YUT,YUP);
uint YLP;
FILTE(YUP,YL,YLP);
YU = YUP; // Delay
YL = YLP; // Delay
}
/**
@brief FIGURE 8/G.726 (Part 1) from Section 4.2.5 - Adaptation speed control
*/
inline void G726::AdaptationSpeedControl1(uint& AL)
{
LIMA(AP,AL);
}
/**
@brief FIGURE 8/G.726 (Part 2) from Section 4.2.5 - Adaptation speed control
*/
inline void G726::AdaptationSpeedControl2(uint I,uint Y,uint TDP,uint TR)
{
uint FI;
FUNCTF(RATE,I,FI);
FILTA(FI,DMS,DMS); // Result 'DMSP' straight to delay storage 'DMS'
FILTB(FI,DML,DML); // Result 'DMSP' straight to delay storage 'DMS'
uint AX;
SUBTC(DMS,DML,TDP,Y,AX); // DMSP and DMLP are read from delay storage 'DMS' and 'DML'
uint APP;
FILTC(AX,AP,APP);
TRIGA(TR,APP,AP); // Result 'APR' straight to delay storage 'AP'
}
/**
@brief FIGURE 9/G.726 (Part1) from Section 4.2.6 - Adaptative predictor and reconstructed signal calculator
*/
inline void G726::AdaptativePredictorAndReconstructedSignalCalculator1(int& SE,int& SEZ)
{
int WBn[6];
for(int i=0; i<6; i++)
FMULT(Bn[i],DQn[i],WBn[i]);
int WAn[2];
FMULT(A1,SR1,WAn[0]);
FMULT(A2,SR2,WAn[1]);
ACCUM(WAn,WBn,SE,SEZ);
}
/**
@brief FIGURE 9/G.726 (Part2) from Section 4.2.6 - Adaptative predictor and reconstructed signal calculator
*/
inline void G726::AdaptativePredictorAndReconstructedSignalCalculator2(uint DQ,uint TR,int SE,int SEZ,int& SR,int& A2P)
{
int PK0;
uint SIGPK;
ADDC(DQ,SEZ,PK0,SIGPK);
ADDB(DQ,SE,SR);
SR2 = SR1; // Delay
FLOATB(SR,SR1); // Result 'SR0' straight to delay storage 'SR1'
uint DQ0;
FLOATA(DQ,DQ0);
int i;
for(i=0; i<6; i++)
{
int Un;
XOR(DQn[i],DQ,Un);
int BnP;
UPB(RATE,Un,Bn[i],DQ,BnP);
TRIGB(TR,BnP,Bn[i]); // Result 'BnR' straight to delay storage 'Bn'
}
int A2T;
UPA2(PK0,PK1,PK2,A1,A2,SIGPK,A2T);
LIMC(A2T,A2P);
TRIGB(TR,A2P,A2); // Result 'A2R' straight to delay storage 'A2'
int A1T;
UPA1(PK0,PK1,A1,SIGPK,A1T);
int A1P;
LIMD(A1T,A2P,A1P);
TRIGB(TR,A1P,A1); // Result 'A1R' straight to delay storage 'A1'
PK2 = PK1; // Delay
PK1 = PK0; // Delay
for(i=5; i>0; i--)
DQn[i] = DQn[i-1]; // Delay
DQn[0] = DQ0; // Delay
}
/**
@brief FIGURE 10/G.726 (Part 1) from Section 4.2.7 - Tone and transition detector
*/
inline void G726::ToneAndTransitionDetector1(uint DQ,uint& TR)
{
TRANS(TD,YL,DQ,TR);
}
/**
@brief FIGURE 10/G.726 (Part 2) from Section 4.2.7 - Tone and transition detector
*/
inline void G726::ToneAndTransitionDetector2(int A2P,uint TR,uint& TDP)
{
TONE(A2P,TDP);
TRIGB(TR,TDP,(int&)TD); // Result 'TDR' straight to delay storage 'TD'
}
/**
@brief FIGURE 11/G.726 from Section 4.2.8 - Output PCM format conversion and synchronous coding adjustment
*/
inline void G726::OutputPCMFormatConversionAndSynchronousCodingAdjustment(int SR,int SE,uint Y,uint I,uint& SD)
{
uint SP;
COMPRESS(SR,LAW,SP);
int SLX;
EXPAND(SP,LAW,SLX);
int DX;
SUBTA(SLX,SE,DX);
uint DLX;
int DSX;
LOG(DX,DLX,DSX);
int DLNX;
SUBTB(DLX,Y,DLNX);
SYNC(RATE,I,SP,DLNX,DSX,LAW,SD);
}
/**
@brief FIGURE A.4/G.726 from Section A.3.3 - Difference signal computation
*/
inline void G726::DifferenceSignalComputation(int SL,int SE,int& D)
{
SUBTA(SL,SE,D);
}
/**
@brief FIGURE A.5/G.726 from Section A.3.5 - Output limiting (decoder only)
*/
inline void G726::OutputLimiting(int SR,int& SO)
{
LIMO(SR,SO);
}
/** @} */ // End of group
/**
@brief The top level method which implements the complete algorithm for both
encoding and decoding.
@param input Either the PCM input to the encoder or the ADPCM input to the decoder.
@param encode A flag which if true makes this method perform the encode function.
If the flag is false then the decode function is performed.
@return Either the ADPCM output to the encoder or the PCM output to the decoder.
*/
uint G726::EncodeDecode(uint input,bool encode)
{
uint AL;
AdaptationSpeedControl1(AL);
uint Y;
QuantizerScaleFactorAdaptation1(AL,Y);
int SE;
int SEZ;
AdaptativePredictorAndReconstructedSignalCalculator1(SE,SEZ);
uint I;
if(encode)
{
int D;
if(LAW==G726::PCM16)
{
int SL = (int16)input;
SL >>= 2; // Convert input from 16bit to 14bit
DifferenceSignalComputation(SL,SE,D);
}
else
InputPCMFormatConversionAndDifferenceSignalComputation(input,SE,D);
AdaptiveQuantizer(D,Y,I);
}
else
I = input;
uint DQ;
InverseAdaptiveQuantizer(I,Y,DQ);
uint TR;
ToneAndTransitionDetector1(DQ,TR);
int SR;
int A2P;
AdaptativePredictorAndReconstructedSignalCalculator2(DQ,TR,SE,SEZ,SR,A2P);
uint TDP;
ToneAndTransitionDetector2(A2P,TR,TDP);
AdaptationSpeedControl2(I,Y,TDP,TR);
QuantizerScaleFactorAdaptation2(I,Y);
if(encode)
return I;
if(LAW==G726::PCM16)
{
int SO;
OutputLimiting(SR,SO);
return SO<<2; // Convert result from 14bit to 16 bit
}
else
{
uint SD;
OutputPCMFormatConversionAndSynchronousCodingAdjustment(SR,SE,Y,I,SD);
return SD;
}
}
/*
Public members of class G726
*/
EXPORT void G726::Reset()
{
int i;
for(i=0; i<6; i++)
{
Bn[i] = 0;
DQn[i] = 32;
}
A1 = 0;
A2 = 0;
AP = 0;
DML = 0;
DMS = 0;
PK1 = 0;
PK2 = 0;
SR1 = 32;
SR2 = 32;
TD = 0;
YL = 34816;
YU = 544;
}
EXPORT void G726::SetLaw(Law law)
{
ASSERT_DEBUG((uint)law<=PCM16);
LAW = law;
}
EXPORT void G726::SetRate(Rate rate)
{
ASSERT_DEBUG((uint)(rate-Rate16kBits)<=(uint)(Rate40kBits-Rate16kBits));
RATE = rate;
}
EXPORT uint G726::Encode(uint S)
{
return EncodeDecode(S,true);
}
EXPORT uint G726::Decode(uint I)
{
I &= (1<<RATE)-1; // Mask off un-needed bits
return EncodeDecode(I,false);
}
EXPORT uint G726::Encode(void* dst, int dstOffset, const void* src, uint srcSize)
{
// convert pointers into more useful types
uint8* out = (uint8*)dst;
const uint8* in = (const uint8*)src;
// use given bit offset
out += dstOffset>>3;
uint bitOffset = dstOffset&7;
uint bits = RATE; // bits per adpcm sample
uint mask = (1<<bits)-1; // bitmask for an adpcm sample
// calculate number of bits to be written
uint outBits;
if(LAW!=PCM16)
outBits = bits*srcSize;
else
{
outBits = bits*(srcSize>>1);
srcSize &= ~1; // make sure srcSize represents a whole number of samples
}
// calculate end of input buffer
const uint8* end = in+srcSize;
while(in<end)
{
// read a single PCM value from input
uint pcm;
if(LAW==PCM16)
pcm = *((int16*&)in)++;
else
pcm = *in++;
// encode the pcm value as an adpcm value
uint adpcm = Encode(pcm);
// shift it to the required output position
adpcm <<= bitOffset;
// write adpcm value to buffer...
uint b = *out; // get byte from ouput
b &= ~(mask<<bitOffset); // clear bits which we want to write to
b |= adpcm; // or in adpcm value
*out = (uint8)b; // write value back to output
// update bitOffset for next adpcm value
bitOffset += bits;
// loop if not moved on to next byte
if(bitOffset<8)
continue;
// move pointers on to next byte
++out;
bitOffset &= 7;
// write any left-over bits from the last adpcm value
if(bitOffset)
*out = (uint8)(adpcm>>8);
}
// return number bits written to dst
return outBits;
}
EXPORT uint G726::Decode(void* dst, const void* src, int srcOffset, uint srcSize)
{
// convert pointers into more useful types
uint8* out = (uint8*)dst;
const uint8* in = (const uint8*)src;
// use given bit offset
in += srcOffset>>3;
uint bitOffset = srcOffset&7;
uint bits = RATE; // bits per adpcm sample
while(srcSize>=bits)
{
// read adpcm value from input
uint adpcm = *in;
if(bitOffset+bits>8)
adpcm |= in[1]<<8; // need bits from next byte as well
// allign adpcm value to bit 0
adpcm >>= bitOffset;
// decode the adpcm value into a pcm value
uint pcm = Decode(adpcm);
// write pcm value to output
if(LAW==PCM16)
*((int16*&)out)++ = (int16)pcm;
else
*out++ = (uint8)pcm;
// update bit values for next adpcm value
bitOffset += bits;
srcSize -= bits;
// move on to next byte of input if required
if(bitOffset>=8)
{
bitOffset &= 7;
++in;
}
}
// return number of bytes written to dst
return out-(uint8*)dst;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -