📄 adpcm.c
字号:
/*
* reconstruct()
*
* 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.
*/
int
reconstruct( sign, dqln, y )
int sign; /* 0 for non-negative value */
long dqln; /* G.72x codeword */
int y; /* Step size multiplier */
{
short dql; /* Log of 'dq' magnitude */
short dex; /* Integer part of log */
short dqt;
short dq; /* Reconstructed difference signal sample */
dql = dqln + (y >> 2); /* ADDA */
if (dql < 0) {
return ((sign) ? -0x8000 : 0);
} else { /* ANTILOG */
dex = ((long)dql >> 7) & 15;
dqt = 128 + (dql & 127);
dq = ((long)dqt << 7) >> (14 - dex);
return ((sign) ? (dq - 0x8000) : dq);
}
}
/*
* update()
*
* updates the state variables for each output code
*/
void
update( code_size, y, wi, fi, dq, sr, dqsez, state_ptr)
int code_size; /* distinguish 723_40 with others */
int y; /* quantizer step size */
long wi; /* scale factor multiplier */
int fi; /* for long/short term energies */
int dq; /* quantized prediction difference */
int sr; /* reconstructed signal */
int dqsez; /* difference from 2-pole predictor */
struct g72x_state *state_ptr; /* coder state pointer */
{
int cnt;
short mant; /* Adaptive predictor, FLOAT A */
short exp, mag;
short a2p; /* LIMC */
short a1ul; /* UPA1 */
short ua2, pks1; /* UPA2 */
short uga2a, fa1;
short uga2b;
char tr; /* tone/transition detector */
short ylint, thr2, dqthr;
short ylfrac, thr1;
short pk0;
int aprin;
pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */
mag = dq & 0x7FFF; /* prediction difference magnitude */
/* TRANS */
ylint = state_ptr->yl >> 15; /* exponent part of yl */
ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */
thr1 = (32 + (long)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_ptr->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_ptr->yu = y + ((long)(wi - y) >> 5);
/* LIMB */
if (state_ptr->yu < 544) /* 544 <= <= 5120 */
state_ptr->yu = 544;
else if (state_ptr->yu > 5120)
state_ptr->yu = 5120;
/* FILTE & DELAY */
/* update steady state step size multiplier */
state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6);
/*
* Adaptive predictor coefficients.
*/
if (tr == 1) { /* reset a's and b's for modem signal */
state_ptr->a[0] = 0;
state_ptr->a[1] = 0;
state_ptr->b[0] = 0;
state_ptr->b[1] = 0;
state_ptr->b[2] = 0;
state_ptr->b[3] = 0;
state_ptr->b[4] = 0;
state_ptr->b[5] = 0;
} else { /* update a's and b's */
pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */
/* update predictor pole a[1] */
a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7);
if (dqsez != 0) {
fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0];
if (fa1 < -8191) /* a2p = function of fa1 */
a2p -= 0x100;
else if (fa1 > 8191)
a2p += 0xFF;
else
a2p += fa1 >> 5;
if (pk0 ^ state_ptr->pk[1])
/* 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_ptr->a[1] = a2p;
/* UPA1 */
/* update predictor pole a[0] */
state_ptr->a[0] -= state_ptr->a[0] >> 8;
if (dqsez != 0)
if (pks1 == 0)
state_ptr->a[0] += 192;
else
state_ptr->a[0] -= 192;
/* LIMD */
a1ul = 15360 - a2p;
if (state_ptr->a[0] < -a1ul)
state_ptr->a[0] = -a1ul;
else if (state_ptr->a[0] > a1ul)
state_ptr->a[0] = a1ul;
/* UPB : update predictor zeros b[6] */
for (cnt = 0; cnt < 6; cnt++) {
if (code_size == 5) /* for 40Kbps G.723 */
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9;
else /* for G.721 and 24Kbps G.723 */
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8;
if (dq & 0x7FFF) { /* XOR */
if ((dq ^ state_ptr->dq[cnt]) >= 0)
state_ptr->b[cnt] += 128;
else
state_ptr->b[cnt] -= 128;
}
}
}
for (cnt = 5; cnt > 0; cnt--)
state_ptr->dq[cnt] = state_ptr->dq[cnt-1];
/* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */
if (mag == 0) {
state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20;
} else {
exp = quan(mag, power2, 15);
state_ptr->dq[0] = (dq >= 0) ?
((long)exp << 6) + (((long)mag << 6) >> exp) :
((long)exp << 6) + (((long)mag << 6) >> exp) - 0x400;
}
state_ptr->sr[1] = state_ptr->sr[0];
/* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */
if (sr == 0) {
state_ptr->sr[0] = 0x20;
} else if (sr > 0) {
exp = quan(sr, power2, 15);
state_ptr->sr[0] = ((long)exp << 6) + (((long)sr << 6) >> exp);
} else if (sr > -32768) {
mag = -sr;
exp = quan(mag, power2, 15);
state_ptr->sr[0] = ((long)exp << 6) + (((long)mag << 6) >> exp) - 0x400;
} else
state_ptr->sr[0] = 0xFC20;
/* DELAY A */
state_ptr->pk[1] = state_ptr->pk[0];
state_ptr->pk[0] = pk0;
/* TONE */
if (tr == 1) /* this sample has been treated as data */
state_ptr->td = 0; /* next one will be treated as voice */
else if (a2p < -11776) /* small sample-to-sample correlation */
state_ptr->td = 1; /* signal may be data */
else /* signal is voice */
state_ptr->td = 0;
/*
* Adaptation speed control.
*/
state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */
state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */
if (tr == 1)
state_ptr->ap = 256;
else if (y < 1536) /* SUBTC */
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else if (state_ptr->td == 1)
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else if (abs((state_ptr->dms << 2) - state_ptr->dml) >=
(state_ptr->dml >> 3))
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else
state_ptr->ap += (-state_ptr->ap) >> 4;
}
/*
* Pack output codes into bytes and write them to stdout.
* Returns 1 if there is residual output, else returns 0.
*/
int
pack_output( code, fpw )
unsigned code;
FILE *fpw;
{
static unsigned int out_buffer = 0;
static int out_bits = 0;
unsigned char out_byte;
out_buffer |= (code << out_bits);
out_bits += 4;
if (out_bits >= 8) {
out_byte = out_buffer & 0xff;
out_bits -= 8;
out_buffer >>= 8;
fwrite(&out_byte, sizeof (char), 1, fpw);
}
return (out_bits > 0);
}
int
unpack_input(code, fpr)
unsigned char *code;
FILE *fpr;
{
static unsigned int in_buffer = 0;
static int in_bits = 0;
unsigned char in_byte;
if (in_bits < 4) {
if (fread(&in_byte, sizeof (char), 1, fpr) != 1) {
*code = 0;
return (-1);
}
in_buffer |= (in_byte << in_bits);
in_bits += 8;
}
*code = in_buffer & ((1 << 4) - 1);
in_buffer >>= 4;
in_bits -= 4;
return (in_bits > 0);
}
main( argc, argv )
int argc;
char **argv;
{
struct g72x_state state_enc;
struct g72x_state state_dec;
unsigned char code;
double org;
double dec;
double dif;
double x;
float snr;
short sample;
int al;
int resid;
int in_size;
int count;
short in_buf;
FILE *fpr, *fpw1, *fpw2, *fpw3, *fopen();
org = 0;
dec = 0;
if ((fpr = fopen(argv[1], "rb")) == NULL ) {
fprintf(stderr, "Cannot open input_file : source\n");
// fprintf(stderr, "Usage : adpcm sample_file dec_file > result\n");
}
if ((fpw1 = fopen(argv[2], "wb")) == NULL ) {
fprintf(stderr, "Cannot open output_file : enc\n");
// fprintf(stderr, "Usage : adpcm sample_file dec_file > result\n");
}
if ((fpw2 = fopen(argv[3], "wb")) == NULL ) {
fprintf(stderr, "Cannot open output_file : dec\n");
// fprintf(stderr, "Usage : adpcm sample_file dec_file > result\n");
}
/* if ((fpw3 = fopen(argv[4], "w")) == NULL ) {
fprintf(stderr, "Cannot open output_file : out\n");
fprintf(stderr, "Usage : adpcm sample_file dec_file > result\n");
}
*/
g72x_init_state(&state_enc);
g72x_init_state(&state_dec);
while (fread(&in_buf, sizeof(short), 1, fpr) == 1) {
code = g721_encoder(in_buf, &state_enc, al, fpw3);
resid = pack_output(code, fpw1);
sample = g721_decoder(code, &state_dec, al);
fwrite(&sample, sizeof(short), 1, fpw2);
org += (double)in_buf*(double)in_buf;
dif = in_buf - sample;
dec += (double)dif*(double)dif;
// printf("%d, %x, %d\n", in_buf, code, sample);
}
fclose(fpr);
fclose(fpw1);
fclose(fpw2);
snr = 10*log10(org / dec); // SNR=10*log10(org^2/(org-dec)^2)
fclose(fpr);
fclose(fpw1);
fclose(fpw2);
printf(" %s with org ADPCM : %lf\n", argv[1], snr);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -