📄 g72x.c
字号:
/*
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* g72x.c
*
* Common routines for G.721 and G.723 conversions.
*/
//#include <audiofmt/st.h>
#include "g72x.h"
//#include <audiofmt/libst.h>
//#include <math.h>
static int power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000};
static int abs(int d)
{
if(d>0)
{
return d;
}
else
{
return -d;
}
}
/*
* g72x_init_state()
*
* This routine initializes and/or resets the g72x_state structure
* pointed to by 'state_ptr'.
* All the initial state values are specified in the CCITT G.721 document.
*/
void
g72x_init_state(struct g72x_state* state_ptr)
{
asm
{
move.l state_ptr,a4
move.l #34816,(a4)+ //yl
move.l #544,(a4)+ //yu
move.l #0,(a4)+ //dms
move.l #0,(a4)+ //dml
move.l #0,(a4)+ //ap
move.l #0,(a4)+ //a
move.l #0,(a4)+
move.l #0,(a4)+ //b
move.l #0,(a4)+
move.l #0,(a4)+
move.l #0,(a4)+
move.l #0,(a4)+
move.l #0,(a4)+
move.l #0,(a4)+ //pk
move.l #0,(a4)+
move.w #32,(a4)+ //dq
move.w #32,(a4)+
move.w #32,(a4)+
move.w #32,(a4)+
move.w #32,(a4)+
move.w #32,(a4)+
move.l #32,(a4)+ //sr
move.l #32,(a4)+
move.l #0,(a4) //td
}
/* int cnta;
state_ptr->yl = 34816;
state_ptr->yu = 544;
state_ptr->dms = 0;
state_ptr->dml = 0;
state_ptr->ap = 0;
for (cnta = 0; cnta < 2; cnta++) {
state_ptr->a[cnta] = 0;
state_ptr->pk[cnta] = 0;
state_ptr->sr[cnta] = 32;
}
for (cnta = 0; cnta < 6; cnta++) {
state_ptr->b[cnta] = 0;
state_ptr->dq[cnta] = 32;//short
}
state_ptr->td = 0;*/
}
/*
* predictor_zero()
*
* computes the estimated signal from 6-zero predictor.
*
*/
/*int
predictor_zero(struct g72x_state* state_ptr)
{
int i;
int sezi;
sezi = state_ptr->b[0] * state_ptr->dq[0];
for (i = 1; i < 6; i++) /* ACCUM */
/* sezi += state_ptr->b[i] * state_ptr->dq[i];
return (sezi >>13);*/
/* sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]);
for (i = 1; i < 6; i++)
sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]);
return (sezi);
}
*/
/*
* predictor_pole()
*
* computes the estimated signal from 2-pole predictor.
*
*/
/*int
predictor_pole( struct g72x_state* state_ptr )
{
return((state_ptr->a[1] * state_ptr->sr[1] +
state_ptr->a[0] * state_ptr->sr[0]) >> 13);*/
/* return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) +
fmult(state_ptr->a[0] >> 2, state_ptr->sr[0]));
}
*/
/*
* step_size()
*
* computes the quantization step size of the adaptive quantizer.
*
*/
int
step_size(struct g72x_state *state_ptr)
{
asm
{
move.l state_ptr,a0
add.l #16,a0
move.l (a0),d0
sub.l #12,a0
move.l (a0),d1
cmp.l #256,d0
ble else1
move.l d1,d0
jmp exit
else1:
sub.l #4,a0
move.l (a0),d2
asr.l #6,d2 //y,d2
sub.l d2,d1 //dif,d1
asr.l #2,d0 //al,d0
cmp.l #0,d1
bgt gt1
cmp.l #0,d1
blt lt1
move.l d2,d0
jmp exit
gt1:
muls.l d1,d0
asr.l #6,d0
add.l d2,d0
jmp exit
lt1:
muls.l d1,d0
add.l #0x3F,d0
asr.l #6,d0
add.l d2,d0
exit:
}
/* int y;
int dif;
int al;
if (state_ptr->ap >= 256)
return (state_ptr->yu);
else {
y = state_ptr->yl >> 6;
dif = state_ptr->yu - y;
al = state_ptr->ap >> 2;
if (dif > 0)
y += (dif * al) >> 6;
else if (dif < 0)
y += (dif * al + 0x3F) >> 6;
return (y);
}*/
}
/*
* quantize()
*
* 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.
*/
int
quantize(
int d, // Raw difference signal sample
int y, // Step size multiplier
int * table, // quantization table
int size // table size of short integers
)
{
// short dqm; /* Magnitude of 'd' */
// short exp; /* Integer part of base 2 log of 'd' */
// short mant; /* Fractional part of base 2 log */
// short dl; /* Log of magnitude of 'd' */
// short dln; /* Step size scale factor normalized log */
// int i;
/*
* LOG
*
* Compute base 2 log of 'd', and store in 'dl'.
*/
// dqm = abs(d);
/* if(d>=0)
{
dqm = d;
}
else
{
dqm = -d;
}
exp = quan(dqm >> 1, power2, 15);
mant = ((dqm << 7) >> exp) & 0x7F; // Fractional portion.
dl = (exp << 7) + mant;*/
asm
{
move.l d,d3
move.l d3,d5 //d5--d
cmp.l #0,d3
bge good_d
neg.l d3
good_d:
move.l d3,d1 //d1 dqm
move.l #0,d0
move.l #15,d2
asr.l #1,d3
lea power2,a1
next_q3:
move.l (a1)+,d4
cmp.l d4,d3
blt exit_q3
addi.l #1,d0
cmp.l d2,d0
blt next_q3
exit_q3:
asl.l #7,d1
asr.l d0,d1
and.l #0x7f,d1 //d1 mant
asl.l #7,d0
add.l d1,d0 //d0--dl
move.l y,d1
asr.l #2,d1
sub.l d1,d0 //d0--dln
/*
* SUBTB
*
* "Divide" by step size multiplier.
*/
// dln = dl - (y >> 2);
move.l #0,d1
move.l size,d2
move.l d0,d3
move.l table,a1
next_q:
move.l (a1)+,d4
ext.l d4
cmp.l d4,d3
blt exit_q
addi.l #1,d1
cmp.l d2,d1
blt next_q
exit_q: //d1--i
cmp.l #0,d5
blt end_d
cmp.l #0,d1
bne end_all
move.l #0,d1
end_d:
asl.l #1,d2
add.l #1,d2
sub.l d1,d2
move.l d2,d1
end_all:
move.l d1,d0
}
/*
* QUAN
*
* Obtain codword i for 'd'.
*/
/* 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);*/
}
/*
* 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(int sign, int dqln, int y)
{
/* 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 = (dql >> 7) & 15;
dqt = 128 + (dql & 127);
dq = (dqt << 7) >> (14 - dex);
return ((sign) ? (dq - 0x8000) : dq);
}*/
asm
{
move.l y,d1
asr.l #2,d1
move.l dqln,d2
add.l d2,d1 //d1--dql
cmp.l #0,d1
bge next_dql
move.l sign,d3
cmp.l #0,d3
beq retu_0
move.l #0x8000,d0
neg.l d0
bra end_re
retu_0:
move.l #0,d0
bra end_re
next_dql:
move.l sign,d3
move.l d1,d4
asr.l #7,d4
and.l #15,d4 //d4 dex
and.l #127,d1
add.l #128,d1 //d1 dqt
asl.l #7,d1
move.l #14,d2
sub.l d4,d2
asr.l d2,d1 //d1--dq
ext.l d1
cmp.l #0,d3
beq next_n0
move.l #0x8000,d2
sub.l d2,d1
next_n0:
move.l d1,d0
end_re:
}
}
/*
* update()
*
* updates the state variables for each output code
*/
void
update(int y, int wi, int fi, int dq, int sr, int dqsez, struct g72x_state* state_ptr)
{
int cnt;
int mag, exp, mant; /* Adaptive predictor, cbFLOAT A */
int a2p = 0; /* LIMC */
int a1ul; /* UPA1 */
int ua2, pks1; /* UPA2 */
int uga2a, fa1;
int uga2b;
int tr; /* tone/transition detector */
int ylint, thr2, dqthr;
int ylfrac, thr1;
int pk0;
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 + 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 + ((wi - y) >> 5);
/* LIMB */
if (state_ptr->yu < 544) /* 544 <= yu <= 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++) {
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;
}
}
}*/
asm
{
move.l state_ptr,a0
add.l #28,a0
move.l (a0),d1
move.l d1,d2
asr.l #8,d2
sub.l d2,d1
move.l d1,(a0)+
move.l (a0),d1
move.l d1,d2
asr.l #8,d2
sub.l d2,d1
move.l d1,(a0)+
move.l (a0),d1
move.l d1,d2
asr.l #8,d2
sub.l d2,d1
move.l d1,(a0)+
move.l (a0),d1
move.l d1,d2
asr.l #8,d2
sub.l d2,d1
move.l d1,(a0)+
move.l (a0),d1
move.l d1,d2
asr.l #8,d2
sub.l d2,d1
move.l d1,(a0)+
move.l (a0),d1
move.l d1,d2
asr.l #8,d2
sub.l d2,d1
move.l d1,(a0)+
check2:
move.l dq,d3
andi.l #0x7fff,d3
cmp.l #0,d3
beq exit1
move.l state_ptr,a0
add.l #28,a0
move.l a0,a1
add.l #32,a1
move.l dq,d2
move.l (a0),d3
move.w (a1)+,d4
ext.l d4
eor.l d2,d4
cmp.l #0,d4
blt else2
add.l #128,d3
move.l d3,(a0)+
jmp next2
else2:
sub.l #128,d3
move.l d3,(a0)+
next2:
move.l (a0),d3
move.w (a1)+,d4
ext.l d4
eor.l d2,d4
cmp.l #0,d4
blt else3
add.l #128,d3
move.l d3,(a0)+
jmp next3
else3:
sub.l #128,d3
move.l d3,(a0)+
next3:
move.l (a0),d3
move.w (a1)+,d4
ext.l d4
eor.l d2,d4
cmp.l #0,d4
blt else4
add.l #128,d3
move.l d3,(a0)+
jmp next4
else4:
sub.l #128,d3
move.l d3,(a0)+
next4:
move.l (a0),d3
move.w (a1)+,d4
ext.l d4
eor.l d2,d4
cmp.l #0,d4
blt else5
add.l #128,d3
move.l d3,(a0)+
jmp next5
else5:
sub.l #128,d3
move.l d3,(a0)+
next5:
move.l (a0),d3
move.w (a1)+,d4
ext.l d4
eor.l d2,d4
cmp.l #0,d4
blt else6
add.l #128,d3
move.l d3,(a0)+
jmp next6
else6:
sub.l #128,d3
move.l d3,(a0)+
next6:
move.l (a0),d3
move.w (a1)+,d4
ext.l d4
eor.l d2,d4
cmp.l #0,d4
blt else7
add.l #128,d3
move.l d3,(a0)+
jmp next7
else7:
sub.l #128,d3
move.l d3,(a0)+
next7:
exit1:
}
}
asm
{
move.l state_ptr,a0
add.l #70,a0
move.l a0,a1
add.l #2,a1
move.w -(a0),d0
move.w d0,-(a1)
move.w -(a0),d0
move.w d0,-(a1)
move.w -(a0),d0
move.w d0,-(a1)
move.w -(a0),d0
move.w d0,-(a1)
move.w -(a0),d0
move.w d0,-(a1)
}
/* for (cnt = 5; cnt > 0; cnt--)
state_ptr->dq[cnt] = state_ptr->dq[cnt-1];*/
if(dq < 0){
dq = 32768 + dq;
dq = -dq;
}
state_ptr->dq[0] = dq;
state_ptr->sr[1] = state_ptr->sr[0];
state_ptr->sr[0] = sr;
/* 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -