Mercurial > hg > audiostuff
diff intercom/g726/g726.c @ 2:13be24d74cd2
import intercom-0.4.1
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 09:57:52 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/intercom/g726/g726.c Fri Jun 25 09:57:52 2010 +0200 @@ -0,0 +1,3387 @@ +/* v2.0 24.Jan.2000 +============================================================================= + + U U GGG SSSS TTTTT + U U G S T + U U G GG SSSS T + U U G G S T + UUU GG SSS T + + ======================================== + ITU-T - USER'S GROUP ON SOFTWARE TOOLS + ======================================== + + + ============================================================= + COPYRIGHT NOTE: This source code, and all of its derivations, + is subject to the "ITU-T General Public License". Please have + it read in the distribution disk, or in the ITU-T + Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO + CODING STANDARDS". + ============================================================= + + +MODULE: G726.C ADPCM AT 40, 32, 24, AND 16 KBIT/S MODULE + +ORIGINAL BY: + Jose' Sindi Yamamoto (Fortran version of the G.721) + <tdsindi@venus.cpqd.ansp.br> + Simao Ferraz de Campos Neto (C translation, adaptation&testing of the G.721) + <simao@venus.cpqd.ansp.br> + Fernando Tofolli Queiroz (Extension of the G.721 to the other rates=>G.726) + <tofolli@venus.cpqd.ansp.br> + Simao Ferraz de Campos Neto (Adaptation and testing of the G.726) + <simao@venus.cpqd.ansp.br> + +HISTORY: +28.Feb.1994 v1.0c Version 1.0 in C, by translating Fortran to C (f2c) +24.Jan.2000 v2.0 Corrected bug G726_compress() that caused incorrect + processing of test vector ri40fa. Corrected code + provided by Jayesh Patel <jayesh@dspse.com>. + Verified by <simao.campos@labs.comsat.com> + +FUNCTIONS: +Public: + G726_encode ..... G726 encoder function; + + G726_decode ..... G726 decoder function; + +Private: + G726_accum ...... addition of predictor outputs to form the partial + signal estimate (from the sixth order predictor) and + the signal estimate. + + G726_adda ....... addition of scale factor to logarithmic version of + quantized difference signal. + + G726_addb ....... addition of quantized difference signal and signal + estimate to form reconstructed signal. + + G726_addc....... obtain sign of addition of quantized difference signal + and partial signal estimate. + + G726_antilog .... convert quantized difference signal from the + logarithmic to the linear domain. + + G726_compress ... convert from uniform pcm to either a-law or u-law pcm. + + G726_delaya ..... memory block. + + G726_delayb ..... memory block. + + G726_delayc ..... memory block. + + G726_delayd ..... memory block. + + G726_expand ..... convert either a-law (law=1) or u-law (law=0) to + uniform pcm. + + G726_filta ...... update of short term average of f(i). + + G726_filtb ...... update of long term average of f(i). + + G726_filtc ...... low pass filter of speed control parameter. + + G726_filtd ...... update of fast quantizer scale factor. + + G726_filte ...... update of slow quantizer scale factor. + + G726_floata ..... convert 15-bit signed magnitude to floating point. + + G726_floatb ..... convert 16-bit two's complement to floating point. + + G726_fmult ...... multiply predictor coefficients with corresponding + quantized difference signal or reconstructed signal. + Multiplication is done in floating point format. + + G726_functf ..... map quantizer output into the f(i) function. + + G726_functw ..... map quantizer output into logarithmic version of scale + factor multiplier. + + G726_lima ....... limit speed control parameter. + + G726_limb ....... limit quantizer scale factor. + + G726_limc ....... limits on a2 coefficient of second order predictor. + + G726_limd ....... limits on a1 coefficient of second order predictor. + + G726_log ........ convert difference signal from linear to the + logarithmic domain. + + G726_mix ........ form linear combination of fast and slow quantizer + scale factors. + + G726_quan ....... quantize difference signal in logarithmic domain. + + G726_reconst .... reconstruction of quantized difference signal in the + logarithmic domain. + + G726_subta ...... compute difference signal by subtracting signal + estimate from input signal (or quantized reconstructed + signal in decoder). + + G726_subtb ...... scale logarithmic version of difference signal by + subtracting scale factor. + + G726_subtc ...... compute magnitude of the difference of short and + long-term function of quantizer output sequence and + then perform threshold comparison for quantizing speed + control parameter. + + G726_sync ....... re-encode output pcm sample in decoder for synchronous + tandem coding. + + G726_tone ....... partial band signal detection. + + G726_trans ...... transition detector. + + G726_triga ...... speed control trigger block. + + G726_trigb ...... predictor trigger block. + + G726_upa1 ....... update a1 coefficient of second order predictor. + + G726_upa2 ....... update a2 coefficient of second order predictor. + + G726_upb ........ update for coefficients of sixth order predictor. + + G726_xor ........ one bit "exclusive or" of sign of difference signal + and sign of delayed difference signal. + +============================================================================= +*/ + +/* + * .................. INCLUDES .................. + */ +#include "g726.h" + + +/* + * .................. FUNCTIONS .................. + */ + +/* + ---------------------------------------------------------------------------- + + void G726_encode (short *inp_buf, short *out_buf, long smpno, + ~~~~~~~~~~~~~~~~ char *law, short rate, short r, G726_state *state); + + Description: + ~~~~~~~~~~~~ + + Simulation of the ITU-T G.726 ADPCM encoder. Takes the A or mu + law input array of shorts `inp_buf' (16 bit, right- justified, + without sign extension) of length `smpno', and saves the + encoded samples in the array of shorts `out_buf', with the + same number of samples and right-justified. + + The state variables are saved in the structure `state', and the + reset can be stablished by making r equal to 1. The law is A if + `law'=='1', and mu law if `law'=='0'. + + + Return value: + ~~~~~~~~~~~~~ + None. + + Prototype: in file g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Version 1.0 in Fortran + <tdsindi@venus.cpqd.ansp.br> + 05.Feb.92 v1.0c Version 1.0 in C, by translating Fortran to C (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------------- +*/ +void G726_encode(inp_buf, out_buf, smpno, law, rate, r, state) +unsigned char *inp_buf; +short *out_buf; +long smpno; +char *law; +short r; +short rate; +G726_state *state; +{ + short s; + short d, i; + short y; + short sigpk; + short sr, tr; + short yu; + short al, fi, dl, ap, dq, ds, se, ax, td, sl, wi; + short u1, u2, u3, u4, u5, u6; + short a1, a2, b1, b2, b3, b4, b5, b6; + short dqln; + short a1p, a2p, a1t, a2t, b1p, b2p, b3p, b4p, b5p, b6p, dq6, pk2, + sr2, wa1, wa2, wb1, wb2, wb3, wb4, wb5, wb6; + short dml, dln, app, dql, dms; + short dqs, tdp; + short sez; + short yut; + long yl; + + long j; + + /* Invert even bits if A law */ + if (*law == '1') { + for (j = 0; j < smpno; j++) + inp_buf[j] ^= 85; + } + + /* Process all desired samples in inp_buf to out_buf; The comments about + * general blocks are given as in G.726, and refer to: 4.1.1 Input PCM + * format conversion and difference signal computation 4.1.2 Adaptive + * quantizer 4.1.3 Inverse adaptive quantizer 4.1.4 Quantizer scale factor + * adaptation 4.1.5 Adaptation speed control 4.1.6 Adaptive predictor and + * reconstructed signal calculator 4.1.7 Tone and transition detector 4.1.8 + * (Only in the decoder) */ + for (j = 0; j < smpno; j++, r = 0) { + s = inp_buf[j]; + + /* Process `known-state' part of 4.2.6 */ + G726_delayd(&r, &state->sr1, &sr2); + G726_delayd(&r, &state->sr0, &state->sr1); + G726_delaya(&r, &state->a2r, &a2); + G726_delaya(&r, &state->a1r, &a1); + G726_fmult(&a2, &sr2, &wa2); + G726_fmult(&a1, &state->sr1, &wa1); + + G726_delayd(&r, &state->dq5, &dq6); + G726_delayd(&r, &state->dq4, &state->dq5); + G726_delayd(&r, &state->dq3, &state->dq4); + G726_delayd(&r, &state->dq2, &state->dq3); + G726_delayd(&r, &state->dq1, &state->dq2); + G726_delayd(&r, &state->dq0, &state->dq1); + + G726_delaya(&r, &state->b1r, &b1); + G726_delaya(&r, &state->b2r, &b2); + G726_delaya(&r, &state->b3r, &b3); + G726_delaya(&r, &state->b4r, &b4); + G726_delaya(&r, &state->b5r, &b5); + G726_delaya(&r, &state->b6r, &b6); + + G726_fmult(&b1, &state->dq1, &wb1); + G726_fmult(&b2, &state->dq2, &wb2); + G726_fmult(&b3, &state->dq3, &wb3); + G726_fmult(&b4, &state->dq4, &wb4); + G726_fmult(&b5, &state->dq5, &wb5); + G726_fmult(&b6, &dq6, &wb6); + + G726_accum(&wa1, &wa2, &wb1, &wb2, &wb3, &wb4, &wb5, &wb6, &se, + &sez); + + /* Process 4.2.1 */ + G726_expand(&s, law, &sl); + G726_subta(&sl, &se, &d); + + /* Process delays and `know-state' part of 4.2.5 */ + G726_delaya(&r, &state->dmsp, &dms); + G726_delaya(&r, &state->dmlp, &dml); + G726_delaya(&r, &state->apr, &ap); + G726_lima(&ap, &al); + + /* Process `know-state' parts of 4.2.4 */ + G726_delayb(&r, &state->yup, &yu); + G726_delayc(&r, &state->ylp, &yl); + G726_mix(&al, &yu, &yl, &y); + + /* Process 4.2.2 */ + G726_log(&d, &dl, &ds); + G726_subtb(&dl, &y, &dln); + G726_quan(rate, &dln, &ds, &i); + + /* Save ADPCM quantized sample into output buffer */ + out_buf[j] = i; + + /* Process 4.2.3 */ + G726_reconst(rate, &i, &dqln, &dqs); + G726_adda(&dqln, &y, &dql); + G726_antilog(&dql, &dqs, &dq); + + /* Part of 4.2.5 */ + G726_functf(rate, &i, &fi); + G726_filta(&fi, &dms, &state->dmsp); + G726_filtb(&fi, &dml, &state->dmlp); + + /* Remaining part of 4.2.4 */ + G726_functw(rate, &i, &wi); + G726_filtd(&wi, &y, &yut); + G726_limb(&yut, &state->yup); + G726_filte(&state->yup, &yl, &state->ylp); + + /* Process `known-state' part of 4.2.7 */ + G726_delaya(&r, &state->tdr, &td); + G726_trans(&td, &yl, &dq, &tr); + + /* More `known-state' parts of 4.2.6: update of `pk's */ + G726_delaya(&r, &state->pk1, &pk2); + G726_delaya(&r, &state->pk0, &state->pk1); + G726_addc(&dq, &sez, &state->pk0, &sigpk); + + /* 4.2.6: find sr0 */ + G726_addb(&dq, &se, &sr); + G726_floatb(&sr, &state->sr0); + + /* 4.2.6: find dq0 */ + G726_floata(&dq, &state->dq0); + + /* 4.2.6: prepar a2(r) */ + G726_upa2(&state->pk0, &state->pk1, &pk2, &a2, &a1, &sigpk, &a2t); + G726_limc(&a2t, &a2p); + G726_trigb(&tr, &a2p, &state->a2r); + + /* 4.2.6: prepar a1(r) */ + G726_upa1(&state->pk0, &state->pk1, &a1, &sigpk, &a1t); + G726_limd(&a1t, &a2p, &a1p); + G726_trigb(&tr, &a1p, &state->a1r); + + /* Remaining of 4.2.7 */ + G726_tone(&a2p, &tdp); + G726_trigb(&tr, &tdp, &state->tdr); + + /* Remaining of 4.2.5 */ + G726_subtc(&state->dmsp, &state->dmlp, &tdp, &y, &ax); + G726_filtc(&ax, &ap, &app); + G726_triga(&tr, &app, &state->apr); + + /* Remaining of 4.2.6: update of all `b's */ + G726_xor(&state->dq1, &dq, &u1); /* Here, b1 */ + G726_upb(rate, &u1, &b1, &dq, &b1p); + G726_trigb(&tr, &b1p, &state->b1r); + + G726_xor(&state->dq2, &dq, &u2); /* Here, b2 */ + G726_upb(rate, &u2, &b2, &dq, &b2p); + G726_trigb(&tr, &b2p, &state->b2r); + + G726_xor(&state->dq3, &dq, &u3); /* Here, b3 */ + G726_upb(rate, &u3, &b3, &dq, &b3p); + G726_trigb(&tr, &b3p, &state->b3r); + + G726_xor(&state->dq4, &dq, &u4); /* Here, b4 */ + G726_upb(rate, &u4, &b4, &dq, &b4p); + G726_trigb(&tr, &b4p, &state->b4r); + + G726_xor(&state->dq5, &dq, &u5); /* Here, b5 */ + G726_upb(rate, &u5, &b5, &dq, &b5p); + G726_trigb(&tr, &b5p, &state->b5r); + + G726_xor(&dq6, &dq, &u6); /* At last, b6 */ + G726_upb(rate, &u6, &b6, &dq, &b6p); + G726_trigb(&tr, &b6p, &state->b6r); + } +} + +/* ........................ end of G726_encode() ....................... */ + + +/* + ---------------------------------------------------------------------------- + + void G726_decode (short *inp_buf, short *out_buf, long smpno, + ~~~~~~~~~~~~~~~~ char *law, short rate, short r, G726_state *state); + + Description: + ~~~~~~~~~~~~ + + Simulation of the ITU-T G.726 ADPCM decoder. Takes the ADPCM + input array of shorts `inp_buf' (16 bit, right- justified, + without sign extension) of length `smpno', and saves the + decoded samples (A or mu law) in the array of shorts + `out_buf', with the same number of samples and + right-justified. + + The state variables are saved in the structure `state', and the + reset can be stablished by making r equal to 1. The law is A if + `law'=='1', and mu law if `law'=='0'. + + + Return value: + ~~~~~~~~~~~~~ + None. + + Prototype: in file g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Version 1.0 in Fortran + <tdsindi@venus.cpqd.ansp.br> + 05.Feb.92 v1.0c Version 1.0 in C, by translating Fortran to C (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------------- +*/ +void G726_decode(inp_buf, out_buf, smpno, law, rate, r, state) +short *inp_buf; +unsigned char *out_buf; +long smpno; +char *law; +short r; +short rate; +G726_state *state; +{ + short i; + short y; + short sigpk; + short sr, tr; + short sp, dlnx, dsx, sd, slx, dlx, dx; /* these are unique to + * the decoder */ + long yl; + short yu; + short al, fi, ap, dq, se, ax, td, wi; + short u1, u2, u3, u4, u5, u6; + short a1, a2, b1, b2, b3, b4, b5, b6; + short dqln; + short a1p, a2p, a1t, a2t, b1p, b2p, b3p, b4p, b5p, b6p, dq6, pk2, + sr2, wa1, wa2, wb1, wb2, wb3, wb4, wb5, wb6; + short dml, app, dql, dms; + short dqs, tdp; + short sez; + short yut; + long j; + + /* Process all desired samples in inp_buf to out_buf; The comments about + * general blocks are given as in G.726, and refer to: 4.1.1 Input PCM + * format conversion and difference signal computation 4.1.2 Adaptive + * quantizer 4.1.3 Inverse adaptive quantizer 4.1.4 Quantizer scale factor + * adaptation 4.1.5 Adaptation speed control 4.1.6 Adaptive predictor and + * reconstructed signal calculator 4.1.7 Tone and transition detector 4.1.8 + * Output PCM format conversion and synchronous coding adjustment */ + for (j = 0; j < smpno; j++, r = 0) { + /* Process `known-state' part of 4.2.6 */ + G726_delayd(&r, &state->sr1, &sr2); + G726_delayd(&r, &state->sr0, &state->sr1); + G726_delaya(&r, &state->a2r, &a2); + G726_delaya(&r, &state->a1r, &a1); + G726_fmult(&a2, &sr2, &wa2); + G726_fmult(&a1, &state->sr1, &wa1); + + G726_delayd(&r, &state->dq5, &dq6); + G726_delayd(&r, &state->dq4, &state->dq5); + G726_delayd(&r, &state->dq3, &state->dq4); + G726_delayd(&r, &state->dq2, &state->dq3); + G726_delayd(&r, &state->dq1, &state->dq2); + G726_delayd(&r, &state->dq0, &state->dq1); + + G726_delaya(&r, &state->b1r, &b1); + G726_delaya(&r, &state->b2r, &b2); + G726_delaya(&r, &state->b3r, &b3); + G726_delaya(&r, &state->b4r, &b4); + G726_delaya(&r, &state->b5r, &b5); + G726_delaya(&r, &state->b6r, &b6); + + G726_fmult(&b1, &state->dq1, &wb1); + G726_fmult(&b2, &state->dq2, &wb2); + G726_fmult(&b3, &state->dq3, &wb3); + G726_fmult(&b4, &state->dq4, &wb4); + G726_fmult(&b5, &state->dq5, &wb5); + G726_fmult(&b6, &dq6, &wb6); + + G726_accum(&wa1, &wa2, &wb1, &wb2, &wb3, &wb4, &wb5, &wb6, &se, + &sez); + + /* Process delays and `know-state' part of 4.2.5 */ + G726_delaya(&r, &state->dmsp, &dms); + G726_delaya(&r, &state->dmlp, &dml); + G726_delaya(&r, &state->apr, &ap); + G726_lima(&ap, &al); + + /* Process `know-state' parts of 4.2.4 */ + G726_delayb(&r, &state->yup, &yu); + G726_delayc(&r, &state->ylp, &yl); + G726_mix(&al, &yu, &yl, &y); + + /* Retrieve ADPCM sample from input buffer */ + i = inp_buf[j]; + + /* Process 4.2.3 */ + G726_reconst(rate, &i, &dqln, &dqs); + G726_adda(&dqln, &y, &dql); + G726_antilog(&dql, &dqs, &dq); + + /* Process `known-state' part of 4.2.7 */ + G726_delaya(&r, &state->tdr, &td); + G726_trans(&td, &yl, &dq, &tr); + + /* Part of 4.2.5 */ + G726_functf(rate, &i, &fi); + G726_filta(&fi, &dms, &state->dmsp); + G726_filtb(&fi, &dml, &state->dmlp); + + /* Remaining part of 4.2.4 */ + G726_functw(rate, &i, &wi); + G726_filtd(&wi, &y, &yut); + G726_limb(&yut, &state->yup); + G726_filte(&state->yup, &yl, &state->ylp); + + /* More `known-state' parts of 4.2.6: update of `pk's */ + G726_delaya(&r, &state->pk1, &pk2); + G726_delaya(&r, &state->pk0, &state->pk1); + G726_addc(&dq, &sez, &state->pk0, &sigpk); + + /* 4.2.6: find sr0 */ + G726_addb(&dq, &se, &sr); + G726_floatb(&sr, &state->sr0); + + /* 4.2.6: find dq0 */ + G726_floata(&dq, &state->dq0); + + /* Process 4.2.8 */ + G726_compress(&sr, law, &sp); + G726_expand(&sp, law, &slx); + G726_subta(&slx, &se, &dx); + G726_log(&dx, &dlx, &dsx); + G726_subtb(&dlx, &y, &dlnx); + G726_sync(rate, &i, &sp, &dlnx, &dsx, law, &sd); + + /* Save output PCM word in output buffer */ + out_buf[j] = sd; + + /* 4.2.6: prepar a2(r) */ + G726_upa2(&state->pk0, &state->pk1, &pk2, &a2, &a1, &sigpk, &a2t); + G726_limc(&a2t, &a2p); + G726_trigb(&tr, &a2p, &state->a2r); + + /* 4.2.6: prepar a1(r) */ + G726_upa1(&state->pk0, &state->pk1, &a1, &sigpk, &a1t); + G726_limd(&a1t, &a2p, &a1p); + G726_trigb(&tr, &a1p, &state->a1r); + + /* Remaining of 4.2.7 */ + G726_tone(&a2p, &tdp); + G726_trigb(&tr, &tdp, &state->tdr); + + /* Remaining of 4.2.5 */ + G726_subtc(&state->dmsp, &state->dmlp, &tdp, &y, &ax); + G726_filtc(&ax, &ap, &app); + G726_triga(&tr, &app, &state->apr); + + /* Remaining of 4.2.6: update of all `b's */ + G726_xor(&state->dq1, &dq, &u1); /* Here, b1 */ + G726_upb(rate, &u1, &b1, &dq, &b1p); + G726_trigb(&tr, &b1p, &state->b1r); + + G726_xor(&state->dq2, &dq, &u2); /* Here, b2 */ + G726_upb(rate, &u2, &b2, &dq, &b2p); + G726_trigb(&tr, &b2p, &state->b2r); + + G726_xor(&state->dq3, &dq, &u3); /* Here, b3 */ + G726_upb(rate, &u3, &b3, &dq, &b3p); + G726_trigb(&tr, &b3p, &state->b3r); + + G726_xor(&state->dq4, &dq, &u4); /* Here, b4 */ + G726_upb(rate, &u4, &b4, &dq, &b4p); + G726_trigb(&tr, &b4p, &state->b4r); + + G726_xor(&state->dq5, &dq, &u5); /* Here, b5 */ + G726_upb(rate, &u5, &b5, &dq, &b5p); + G726_trigb(&tr, &b5p, &state->b5r); + + G726_xor(&dq6, &dq, &u6); /* At last, b6 */ + G726_upb(rate, &u6, &b6, &dq, &b6p); + G726_trigb(&tr, &b6p, &state->b6r); + } + + /* Invert even bits if A law */ + if (*law == '1') { + for (j = 0; j < smpno; j++) + out_buf[j] ^= 85; + } + +} + +/* ...................... end of G726_decode() ...................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_expand (short *s, char *law, short *sl); + ~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Convert either a-law (law=1) or u-law (law=0) to uniform pcm. + + Inputs: s (sp in decoder), law + Output: sl (slx in decoder) + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_expand(s, law, sl) +short *s; +char *law; +short *sl; +{ + long mant, iexp; + short s1, ss, sig, ssm, ssq, sss; + + s1 = *s; + + if (*law == '1') { + /* Invert sign bit */ + s1 ^= 128; + if (s1 >= 128) { + s1 += -128; + sig = 4096; + } else { + sig = 0; + + } + iexp = s1 / 16; + + mant = s1 - (iexp << 4); + ss = (iexp == 0) ? + ((mant << 1) + 1 + sig) : + ((1 << (iexp - 1)) * ((mant << 1) + 33) + sig); + + sss = ss / 4096; + ssm = ss & 4095; + ssq = ssm << 1; + } else { + /* Invert sign bit */ + s1 ^= 128; + if (s1 >= 128) { + s1 += -128; + s1 ^= 127; + sig = 8192; + } else { + sig = 0; + s1 ^= 127; + } + iexp = s1 / 16; + + mant = s1 - (iexp << 4); + + ss = (iexp == 0) ? + ((mant << 1) + sig) : + ((1 << iexp) * ((mant << 1) + 33) - 33 + sig); + + sss = ss / 8192; + ssq = ss & 8191; + } + + *sl = (sss == 0) ? ssq : ((16384 - ssq) & 16383); + +} + +/* ...................... end of G726_expand() ...................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_subta (short *sl, short *se, short *d); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Compute difference signal by subtracting signal estimate from + input signal (or quantized reconstructed signal in decoder). + + Inputs: sl (slx in decoder), se + Output: d (dx in decoder) + + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + + ---------------------------------------------------------------------- +*/ +void G726_subta(sl, se, d) +short *sl, *se, *d; +{ + long se1; + long sl1, sei, sli; + short ses, sls; + + sls = (*sl >> 13); + + sl1 = *sl; + se1 = *se; + + /* Sign extension */ + sli = (sls == 0) ? sl1 : (sl1 + 49152); + + ses = (*se >> 14); + + /* Sign extension */ + sei = (ses == 0) ? se1 : (se1 + 32768); + + /* 16 bit TC */ + *d = (short) ((sli + 65536 - sei) & 65535); + +} + +/* ......................... end of G726_subta() ......................... */ + + +/* + -------------------------------------------------------------------------- + + void G726_log (short *d, short *dl, short *ds); + ~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Convert difference signal from linear to the logarithmic domain. + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f 1st release to UGST, in Fortran. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c release of 1st version, in C. + <tdsimao@venus.cpqd.ansp.br> + + -------------------------------------------------------------------------- +*/ +void G726_log(d, dl, ds) +short *d, *dl, *ds; +{ + long mant; + long d1; + long dqm, exp_; + + *ds = (*d >> 15); + + d1 = *d; + + /* Convert from 2-complement to signed magnitude */ + dqm = (*ds) ? ((65536 - d1) & 32767) : d1; + + /* Compute exponent */ + if (dqm >= 16384) + exp_ = 14; + else if (dqm >= 8192) + exp_ = 13; + else if (dqm >= 4096) + exp_ = 12; + else if (dqm >= 2048) + exp_ = 11; + else if (dqm >= 1024) + exp_ = 10; + else if (dqm >= 512) + exp_ = 9; + else if (dqm >= 256) + exp_ = 8; + else if (dqm >= 128) + exp_ = 7; + else if (dqm >= 64) + exp_ = 6; + else if (dqm >= 32) + exp_ = 5; + else if (dqm >= 16) + exp_ = 4; + else if (dqm >= 8) + exp_ = 3; + else if (dqm >= 4) + exp_ = 2; + else if (dqm >= 2) + exp_ = 1; + else + exp_ = 0; + + /* Compute approximation log2(1+x) = x */ + mant = ((dqm << 7) >> exp_) & 127; + + /* Combine mantissa and exponent (7 and 4) bits into a 11-bit word */ + *dl = (short) ((exp_ << 7) + mant); + +} + +/* ........................ end of G726_log() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_quan (short rate, short *dln, short *ds, short *i); + ~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Quantize difference signal in logarithmic + domain. + + Inputs: dln, ds, rate + Output: i + + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_quan(rate, dln, ds, i) +short *dln, *ds, *i; +short rate; +{ + if (rate == 4) { + if (*dln >= 3972) + *i = 1; + else if (*dln >= 2048) + *i = 15; + else if (*dln >= 400) + *i = 7; + else if (*dln >= 349) + *i = 6; + else if (*dln >= 300) + *i = 5; + else if (*dln >= 246) + *i = 4; + else if (*dln >= 178) + *i = 3; + else if (*dln >= 80) + *i = 2; + else + *i = 1; + + /* Adjust for sign */ + if (*ds) + *i = 15 - *i; + + if (*i == 0) + *i = 15; + } + + /* ......... end of 32 kbit part ........... */ + else if (rate == 3) { + if (*dln >= 2048) + *i = 7; + else if (*dln >= 331) + *i = 3; + else if (*dln >= 218) + *i = 2; + else if (*dln >= 8) + *i = 1; + else if (*dln >= 0) + *i = 7; + + /* Adjust for sign */ + if (*ds) + *i = 7 - *i; + + if (*i == 0) + *i = 7; + } + /* ......... end of 24 kbit part ........... */ + else if (rate == 2) { + if (*dln >= 2048) + *i = 0; + else if (*dln >= 261) + *i = 1; + else + *i = 0; + + /* Adjust for sign */ + if (*ds) + *i = 3 - *i; + } + /* ......... end of 16 kbit part ........... */ + else { + if (*dln >= 4080) + *i = 2; + else if (*dln >= 3974) + *i = 1; + else if (*dln >= 2048) + *i = 31; + else if (*dln >= 553) + *i = 15; + else if (*dln >= 528) + *i = 14; + else if (*dln >= 502) + *i = 13; + else if (*dln >= 475) + *i = 12; + else if (*dln >= 445) + *i = 11; + else if (*dln >= 413) + *i = 10; + else if (*dln >= 378) + *i = 9; + else if (*dln >= 339) + *i = 8; + else if (*dln >= 298) + *i = 7; + else if (*dln >= 250) + *i = 6; + else if (*dln >= 198) + *i = 5; + else if (*dln >= 139) + *i = 4; + else if (*dln >= 68) + *i = 3; + else if (*dln >= 0) + *i = 2; + + if (*ds) + *i = 31 - *i; + + if (*i == 0) + *i = 31; + + } /* ......... end of 40 kbit part ........... */ + +} + +/* ........................ end of G726_quan() ........................ */ + + +/* + ---------------------------------------------------------------------- + + void G726_subtb (short *dl, short *y, short *dln); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Scale logarithmic version of difference signal by subtracting + scale factor. + + Inputs: dl (dlx no decodificador), y + Output: dln (dlnx no decodificador) + + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_subtb(dl, y, dln) +short *dl, *y, *dln; +{ + *dln = (*dl + 4096 - (*y >> 2)) & 4095; + +} + +/* ........................ end of G726_subtb() ........................ */ + + +/* + ---------------------------------------------------------------------- + + void G726_adda (short *dqln, short *y, short *dql); + ~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Addition of scale factor to logarithmic version of quantized + difference signal. + + Inputs: dqln, y + Output: dql + + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_adda(dqln, y, dql) +short *dqln, *y, *dql; +{ + *dql = (*dqln + (*y >> 2)) & 4095; + +} + +/* ....................... end of G726_adda() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_antilog (short *dql, short *dqs, short *dq); + ~~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Convert quantized difference signal from the logarithmic to + the linear domain. + + Inputs: dql, dqs + Output: dq + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_antilog(dql, dqs, dq) +short *dql, *dqs, *dq; +{ + long dqmag; + long ds, dmn, dex, dqt; + + /* Extract 4-bit exponent */ + ds = (*dql >> 11); + dex = (*dql >> 7) & 15; + + /* Extract 7-bit mantissa */ + dmn = *dql & 127; + + dqt = dmn + 128; + + /* Convert mantissa to linear using the approx. 2**x = 1+x */ + dqmag = ds ? 0 : ((dqt << 7) >> (14 - dex)); + + /* Attach sign bit to signed mag. word */ + *dq = (short) (*dqs << 15) + dqmag; +} + +/* ..................... end of G726_antilog() ..................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_reconst (short rate, short *i, short *dqln, short *dqs); + ~~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Reconstruction of quantized difference signal in the + logarithmic domain. + + Inputs: i, rate + Outputs: dqln, dqs + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_reconst(rate, i, dqln, dqs) +short *i, *dqln, *dqs; +short rate; +{ + if (rate == 4) { + /* Initialized data */ + static short tab[16] = { 2048, 4, 135, 213, 273, 323, 373, 425, + 425, 373, 323, 273, 213, 135, 4, 2048 + }; + + /* Extract sign */ + *dqs = (*i >> 3); + + /* Table look-up */ + *dqln = tab[*i]; + } + /* ............... end of 32 kbit part + * ................. */ + else if (rate == 3) { + /* Initialized data */ + static short tab[8] = { 2048, 135, 273, 373, 373, 273, 135, 2048 }; + + *dqs = (*i >> 2); + + /* Table look-up */ + *dqln = tab[*i]; + + } + + /* ............... end of 24 kbit part + * ................. */ + else if (rate == 2) { + /* Initialized data */ + static short tab[4] = { 116, 365, 365, 116 }; + + *dqs = (*i >> 1); + + /* Table look-up */ + *dqln = tab[*i]; + + } /* ............... end of 16 kbit part + * ................. */ + else { + /* Initialized data */ + static short tab[32] = + { 2048, 4030, 28, 104, 169, 224, 274, 318, 358, 395, 429, + 459, 488, 514, 539, 566, 566, 539, 514, 488, 459, 429, 395, 358, + 318, 274, 224, + 169, 104, 28, 4030, 2048 + }; + + *dqs = (*i >> 4); + + /* Table look-up */ + *dqln = tab[*i]; + + } /* ................ end of 40 kbit part + * ................... */ + + +} + +/* ....................... end of G726_reconst() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_delaya (short *r, short *x, short *y); + ~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Memory block. + + Inputs: r, x + Output: y + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_delaya(r, x, y) +short *r, *x, *y; +{ + *y = (*r == 0) ? *x : 0; + +} + +/* ....................... end of G726_delaya() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_delayb (short *r, short *x, short *y); + ~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Memory block. + + Inputs: r, x + Output: y + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_delayb(r, x, y) +short *r, *x, *y; +{ + *y = (*r == 0) ? *x : 544; + +} + +/* ....................... end of G726_delayb() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_delayc (short *r, long *x, long *y); + ~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Memory block. + + Inputs: r, x + Output: y + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_delayc(r, x, y) +short *r; +long *x, *y; +{ + *y = (*r == 0) ? *x : 34816; + +} + +/* ....................... end of G726_delayc() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_delayd (short *r, short *x, short *y); + ~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Memory block + + Inputs: r, x + Output: y + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_delayd(r, x, y) +short *r, *x, *y; +{ + *y = (*r == 0) ? *x : 32; + +} + +/* ....................... end of G726_delayd() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_filtd (short *wi, short *y, short *yut); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Update of fast quantizer scale factor. + + Inputs: wi, y + Output: yut + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_filtd(wi, y, yut) +short *wi, *y, *yut; +{ + long difs, difsx; + long y1; + long wi1, dif; + + /* Compute difference */ + wi1 = *wi; + y1 = *y; + dif = ((wi1 << 5) + 131072 - y1) & 131071; + difs = (dif >> 16); + + /* Time constant is 1/32; sign extension */ + difsx = (difs == 0) ? (dif >> 5) : ((dif >> 5) + 4096); + + *yut = (short) ((y1 + difsx) & 8191); + +} + +/* ....................... end of G726_filte() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_filte (short *yup, long *yl, long *ylp); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Update of slow quantizer scale factor. + + + Inputs: yup, yl + Output: ylp + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_filte(yup, yl, ylp) +short *yup; +long *yl, *ylp; +{ + long difs, difsx; + long dif, dif1, yup1; + + /* Compute difference */ + yup1 = *yup; + dif1 = 1048576 - *yl; + dif = (yup1 + (dif1 >> 6)) & 16383; + difs = (dif >> 13); + + /* Sign extension */ + difsx = (difs == 0) ? dif : (dif + 507904); + + *ylp = (*yl + difsx) & 524287; + +} + +/* ....................... end of G726_filte() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_functw (short rate, short *i, short *wi); + ~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Map quantizer output into logarithmic version of scale factor + multiplier. + + Inputs: i, rate + Output: wi + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_functw(rate, i, wi) +short *i, *wi; +short rate; +{ + if (rate == 4) { + /* Initialized data */ + static short tab[8] = { 4084, 18, 41, 64, 112, 198, 355, 1122 }; + short im, is; + + is = (*i >> 3); + + im = (is == 0) ? (*i & 7) : ((15 - *i) & 7); + + /* Scale factor multiplier */ + *wi = tab[im]; + + + } + + + + + /* ................. end of 32 kbit part + * .............. */ + else if (rate == 3) { + + /* Initialized data */ + static short tab[4] = { 4092, 30, 137, 582 }; + short im, is; + + + is = (*i >> 2); + + im = (is == 0) ? (*i & 3) : ((7 - *i) & 3); + + *wi = tab[im]; + + + + } + + + + + /* ................. end of 24 kbit part + * .............. */ + else if (rate == 2) { + /* Initialized data */ + static short tab[2] = { 4074, 439 }; + short im, is; + + + is = (*i >> 1); + + im = (is == 0) ? (*i & 1) : ((3 - *i) & 1); + + *wi = tab[im]; + + } + + + + + /* ................. end of 16 kbit part + * .............. */ + else { + /* Initialized data */ + static short tab[16] = + { 14, 14, 24, 39, 40, 41, 58, 100, 141, 179, 219, 280, 358, + 440, 529, 696 + }; + short im, is; + + is = (*i >> 4); + + im = (is == 0) ? (*i & 15) : ((31 - *i) & 15); + + *wi = tab[im]; + } /* ................. end of 40 kbit part + * .............. */ +} + +/* ....................... end of G726_functw() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_limb (short *yut, short *yup); + ~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Limit quantizer scale factor. + + Inputs: yut + Output: yup + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_limb(yut, yup) +short *yut, *yup; +{ + short gell, geul; + + geul = ((*yut + 11264) & 16383) >> 13; + gell = ((*yut + 15840) & 16383) >> 13; + + if (gell == 1) + *yup = 544; /* Lower limit is 1.06 */ + else if (geul == 0) + *yup = 5120; /* Upper limit is 10.0 */ + else + *yup = *yut; + +} + +/* ....................... end of G726_limb() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_mix (short *al, short *yu, long *yl, short *y); + ~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Form linear combination of fast and slow quantizer scale + factors. + + Inputs: al, yu, yl + Output: y + + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_mix(al, yu, yl, y) +short *al, *yu; +long *yl; +short *y; +{ + long difm, difs, prod; + long prodm, al1; + long yu1, dif; + + /* Preamble */ + al1 = *al; + yu1 = *yu; + + /* Compute difference */ + dif = (yu1 + 16384 - (*yl >> 6)) & 16383; + difs = (dif >> 13); + + /* Compute magnitude of difference */ + difm = (difs == 0) ? dif : ((16384 - dif) & 8191); + + /* Compute magnitude of product */ + prodm = ((difm * al1) >> 6); + + /* Convert magnitude to two's complement */ + prod = (difs == 0) ? prodm : ((16384 - prodm) & 16383); + + *y = (short) (((*yl >> 6) + prod) & 8191); + +} + +/* ....................... end of G726_mix() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_filta (short *fi, short *dms, short *dmsp); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Update of short term average of f(i). + + Inputs: fi, dms + Output: dmsp + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_filta(fi, dms, dmsp) +short *fi, *dms, *dmsp; +{ + short difs, difsx; + short dif; + + /* Compute difference */ + dif = ((*fi << 9) + 8192 - *dms) & 8191; + difs = (dif >> 12); + + /* Time constant is 1/32, sign extension */ + difsx = (difs == 0) ? (dif >> 5) : ((dif >> 5) + 3840); + + *dmsp = (difsx + *dms) & 4095; + +} + +/* ....................... end of G726_filta() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_filtb (short *fi, short *dml, short *dmlp); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Update of long term average of f(i). + + Inputs: fi, dml + Output: dmlp + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_filtb(fi, dml, dmlp) +short *fi, *dml, *dmlp; +{ + long difs, difsx; + long fi1; + long dif, dml1; + + /* Preamble */ + fi1 = *fi; + dml1 = *dml; + + /* Compute difference */ + dif = ((fi1 << 11) + 32768 - dml1) & 32767; + difs = (dif >> 14); + + /* Time constant is 1/28, sign extension */ + difsx = (difs == 0) ? (dif >> 7) : ((dif >> 7) + 16128); + + *dmlp = (short) ((difsx + dml1) & 16383); + +} + +/* ....................... end of G726_filtb() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_filtc (short *ax, short *ap, short *app); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Low pass filter of speed control parameter. + + Inputs: ax, ap + Output: app + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_filtc(ax, ap, app) +short *ax, *ap, *app; +{ + short difs, difsx; + short dif; + + /* Compute difference */ + dif = ((*ax << 9) + 2048 - *ap) & 2047; + difs = (dif >> 10); + + /* Time constant is 1/16, sign extension */ + difsx = (difs == 0) ? (dif >> 4) : ((dif >> 4) + 896); + + *app = (difsx + *ap) & 1023; + +} + +/* .................... end of G726_filtc() .................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_functf (short rate, short *i, short *fi); + ~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Map quantizer output into the f(i) function. + + Inputs: i, rate + Output: fi + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_functf(rate, i, fi) +short *i, *fi; +short rate; + +{ + short im, is; + + if (rate == 4) { + /* Initialized data */ + static short tab[8] = { 0, 0, 0, 1, 1, 1, 3, 7 }; + + is = (*i >> 3); + + im = (is == 0) ? (*i & 7) : ((15 - *i) & 7); + + *fi = tab[im]; + } + /* ................ end of 32 kbit part + * ................. */ + else if (rate == 3) { + /* Initialized data */ + static short tab[4] = { 0, 1, 2, 7 }; + + is = (*i >> 2); + + im = (is == 0) ? (*i & 3) : ((7 - *i) & 3); + + *fi = tab[im]; + + } /* ................ end of 24 kbit part + * ................. */ + else if (rate == 2) { + /* Initialized data */ + static short tab[2] = { 0, 7 }; + + + is = (*i >> 1); + + im = (is == 0) ? (*i & 1) : ((3 - *i) & 1); + + *fi = tab[im]; + + } + /* ................ end of 16 kbit part + * ................. */ + else { + /* Initialized data */ + static short tab[16] = + { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 6 }; + + + is = (*i >> 4); + + im = (is == 0) ? (*i & 15) : ((31 - *i) & 15); + + *fi = tab[im]; + + } /* ................ end of 40 kbit part + * ................. */ +} + +/* ...................... end of G726_functf() ...................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_lima (short *ap, short *al); + ~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Limit speed control parameter. + + Inputs: ap + Output: al + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_lima(ap, al) +short *ap, *al; +{ + *al = (*ap >= 256) ? 64 : (*ap >> 2); + +} + +/* ....................... end of G726_lima() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_subtc (short *dmsp, short *dmlp, short *tdp, + ~~~~~~~~~~~~~~~ short *y, short *ax); + + Description: + ~~~~~~~~~~~~ + + Functions of quantizer output sequence and then perform + threshold comparison for quantizing speed control parameter. + compute magnitude of the difference of short and long-term + + Inputs: dmsp, dmlp, tdp, y + Output: ax + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_subtc(dmsp, dmlp, tdp, y, ax) +short *dmsp, *dmlp, *tdp, *y, *ax; +{ + long difm, difs, dthr, dmlp1, dmsp1; + long dif; + + /* Preamble */ + dmsp1 = *dmsp; + dmlp1 = *dmlp; + + /* Compute difference */ + dif = ((dmsp1 << 2) + 32768 - dmlp1) & 32767; + difs = (dif >> 14); + + /* Compute magnitude of difference */ + difm = (difs == 0) ? dif : ((32768 - dif) & 16383); + + /* Compute threshold */ + dthr = (dmlp1 >> 3); + + /* Quantize speed control parameter */ + *ax = (*y >= 1536 && difm < dthr && *tdp == 0) ? 0 : 1; + +} + +/* ....................... end of G726_subtc() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_triga (short *tr, short *app, short *apr); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Speed control trigger block. + + Inputs: tr, app + Output: apr + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_triga(tr, app, apr) +short *tr, *app, *apr; +{ + *apr = (*tr == 0) ? (*app) : 256; + +} + +/* ....................... end of G726_triga() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_accum (short *wa1, short *wa2, short *wb1, + ~~~~~~~~~~~~~~~ short *wb2, short *wb3, short *wb4, + short *wb5, short *wb6, short *se, short *sez); + + Description: + ~~~~~~~~~~~~ + + Addition of predictor outputs to form the partial signal + estimate (from the sixth order predictor) and the signal + estimate. + + Inputs: wa1, wa2, wb1, wb2, wb3, wb4, wb5, wb6 + Output: se, sez + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_accum(wa1, wa2, wb1, wb2, wb3, wb4, wb5, wb6, se, sez) +short *wa1, *wa2, *wb1, *wb2, *wb3, *wb4, *wb5, *wb6, *se, *sez; +{ + unsigned long sezi; + unsigned long wa11, wa21, wb11, wb21, wb31, wb41, wb51, wb61, sei; + + /* Preamble */ + wa11 = *wa1; + wa21 = *wa2; + wb11 = *wb1; + wb21 = *wb2; + wb31 = *wb3; + wb41 = *wb4; + wb51 = *wb5; + wb61 = *wb6; + + /* Sum of partial signal estimate */ + sezi = (((((((((wb11 + wb21) & 65535) + wb31) & 65535) + + wb41) & 65535) + wb51) & 65535) + wb61) & 65535; + + /* Complete sum for signal estimate */ + sei = (((sezi + wa21) & 65535) + wa11) & 65535; + + *sez = (short) (sezi >> 1); + *se = (short) (sei >> 1); + +} + +/* ....................... end of G726_accum() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_addb (short *dq, short *se, short *sr); + ~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Addition of quantized difference signal and signal estimate + to form reconstructed signal. + + Inputs: dq, se + Output: sr + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_addb(dq, se, sr) +short *dq, *se, *sr; +{ + unsigned long dq1, se1; + unsigned long dqi, sei; + short dqs, ses; + + /* Preamble */ + dq1 = *dq & 65535; + se1 = *se; + + /* Sign */ + dqs = (*dq >> 15) & 1; + + /* Convert signed magnitude to 2's complement */ + dqi = (dqs == 0) ? dq1 : ((65536 - (dq1 & 32767)) & 65535); + + ses = (*se >> 14); + + /* Sign extension */ + sei = (ses == 0) ? se1 : ((1 << 15) + se1); + + *sr = (short) ((dqi + sei) & 65535); + +} + +/* ....................... end of G726_addb() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_addc (short *dq, short *sez, short *pk0, + ~~~~~~~~~~~~~~ short *sigpk); + + Description: + ~~~~~~~~~~~~ + + Obtain sign of addition of quantized difference signal and + partial signal estimate. + + Inputs: dq, sez + Outputs: pk0, sigpk + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_addc(dq, sez, pk0, sigpk) +short *dq, *sez, *pk0, *sigpk; +{ + unsigned long sezi; + short sezs; + unsigned long dqsez, dq1; + unsigned long dqi; + short dqs; + unsigned long sez1; + + /* Preamble */ + dq1 = *dq & 65535; + sez1 = *sez; + + /* Get sign */ + dqs = (*dq >> 15) & 1; + + /* Convert signed magnitude to 2's compelemnent */ + dqi = (dqs == 0) ? dq1 : ((65536 - (dq1 & 32767)) & 65535); + + sezs = (*sez >> 14); + + /* Sign extension */ + sezi = (sezs == 0) ? sez1 : (sez1 + 32768); + + dqsez = (dqi + sezi) & 65535; + + *pk0 = (short) (dqsez >> 15); + *sigpk = (dqsez == 0) ? 1 : 0; + +} + +/* ....................... end of G726_addc() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_floata (short *dq, short *dq0); + ~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Convert 16-bit signed magnitude to floating point. + + Inputs: dq + Output: dq0 + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_floata(dq, dq0) +short *dq, *dq0; +{ + long mant; + long mag, exp_; + long dqs; + + dqs = (*dq >> 15) & 1; + + /* Compute magnitude */ + mag = *dq & 32767; + + /* Exponent */ + if (mag >= 16384) + exp_ = 15; + else if (mag >= 8192) + exp_ = 14; + else if (mag >= 4096) + exp_ = 13; + else if (mag >= 2048) + exp_ = 12; + else if (mag >= 1024) + exp_ = 11; + else if (mag >= 512) + exp_ = 10; + else if (mag >= 256) + exp_ = 9; + else if (mag >= 128) + exp_ = 8; + else if (mag >= 64) + exp_ = 7; + else if (mag >= 32) + exp_ = 6; + else if (mag >= 16) + exp_ = 5; + else if (mag >= 8) + exp_ = 4; + else if (mag >= 4) + exp_ = 3; + else if (mag >= 2) + exp_ = 2; + else if (mag == 1) + exp_ = 1; + else + exp_ = 0; + + /* Compute mantissa w/a 1 in the most sig. bit */ + mant = (mag == 0) ? (1 << 5) : ((mag << 6) >> exp_); + /* Combine sign, exponent and mantissa (1,4,6) bits in a word */ + *dq0 = (short) ((dqs << 10) + (exp_ << 6) + mant); + +} + +/* ....................... end of G726_floata() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_floatb (short *sr, short *sr0); + ~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Convert 16-bit two's complement to floating point. + + Inputs: sr + Output: sr0 + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_floatb(sr, sr0) +short *sr, *sr0; +{ + long mant; + long mag, exp_, srr, srs; + + /* Preamble */ + srr = *sr & 65535; + + /* Sign */ + srs = (srr >> 15); + + /* Compute magnitude */ + mag = (srs == 0) ? srr : ((65536 - srr) & 32767); + + /* Exponent */ + if (mag >= 16384) + exp_ = 15; + else if (mag >= 8192) + exp_ = 14; + else if (mag >= 4096) + exp_ = 13; + else if (mag >= 2048) + exp_ = 12; + else if (mag >= 1024) + exp_ = 11; + else if (mag >= 512) + exp_ = 10; + else if (mag >= 256) + exp_ = 9; + else if (mag >= 128) + exp_ = 8; + else if (mag >= 64) + exp_ = 7; + else if (mag >= 32) + exp_ = 6; + else if (mag >= 16) + exp_ = 5; + else if (mag >= 8) + exp_ = 4; + else if (mag >= 4) + exp_ = 3; + else if (mag >= 2) + exp_ = 2; + else if (mag == 1) + exp_ = 1; + else + exp_ = 0; + + /* Compute mantissa w/a 1 in the most sig. bit */ + mant = (mag == 0) ? (1 << 5) : ((mag << 6) >> exp_); + + /* Combine sign, exponent and mantissa (1,4,6) bits in a word */ + *sr0 = (short) ((srs << 10) + (exp_ << 6) + mant); + +} + +/* ....................... end of G726_floatb() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_fmult (short *a, short *srn, short *wa); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Multiply predictor coefficients with corresponding quantized + difference signal or reconstructed signal. multiplication is + done in floating piont format + + Inputs: a (or b), srn (or dqn) + Outputs: wa (or wb) + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_fmult(An, SRn, WAn) +short *An, *SRn, *WAn; +{ + long anmag, anexp, wanmag, anmant; + long wanexp, srnexp, an, ans, wanmant, srnmant; + long wan, wans, srns, srn1; + + /* Preamble */ + an = *An & 65535; + srn1 = *SRn & 65535; + + /* Sign */ + ans = an & 32768; + ans = (ans >> 15); + + /* Convert 2's complement to signed magnitude */ + anmag = (ans == 0) ? (an >> 2) : ((16384 - (an >> 2)) & 8191); + + /* Exponent */ + if (anmag >= 4096) + anexp = 13; + else if (anmag >= 2048) + anexp = 12; + else if (anmag >= 1024) + anexp = 11; + else if (anmag >= 512) + anexp = 10; + else if (anmag >= 256) + anexp = 9; + else if (anmag >= 128) + anexp = 8; + else if (anmag >= 64) + anexp = 7; + else if (anmag >= 32) + anexp = 6; + else if (anmag >= 16) + anexp = 5; + else if (anmag >= 8) + anexp = 4; + else if (anmag >= 4) + anexp = 3; + else if (anmag >= 2) + anexp = 2; + else if (anmag == 1) + anexp = 1; + else + anexp = 0; + + /* Compute mantissa w/a 1 in the most sig. bit */ + anmant = (anmag == 0) ? (1 << 5) : ((anmag << 6) >> anexp); + + /* Split floating point word into sign, exponent and mantissa */ + srns = (srn1 >> 10); + srnexp = (srn1 >> 6) & 15; + srnmant = srn1 & 63; + + /* Floating point multiplication */ + wans = srns ^ ans; + wanexp = srnexp + anexp; + wanmant = ((srnmant * anmant) + 48) >> 4; + + /* Convert floating point to magnitude */ + wanmag = (wanexp <= 26) ? + (wanmant << 7) >> (26 - wanexp) : + ((wanmant << 7) << (wanexp - 26)) & 32767; + + /* Convert mag. to 2's complement */ + wan = (wans == 0) ? wanmag : ((65536 - wanmag) & 65535); + + *WAn = (short) wan; + +} + +/* ....................... end of G726_fmult() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_limc (short *a2t, short *a2p); + ~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Limits on a2 coefficient of second order predictor. + + Inputs: a2t + Output: a2p + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ + +void G726_limc(a2t, a2p) +short *a2t, *a2p; +{ + long a2p1, a2t1, a2ll, a2ul; + + a2t1 = *a2t & 65535; + + a2ul = 12288; /* Upper limit of +.75 */ + a2ll = 53248; /* Lower limit of -.75 */ + + if (a2t1 >= 32768 && a2t1 <= a2ll) + a2p1 = a2ll; + else if (a2t1 >= a2ul && a2t1 <= 32767) + a2p1 = a2ul; + else + a2p1 = a2t1; + + *a2p = (short) a2p1; + +} + +/* ....................... end of G726_limc() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_limd (short *a1t, short *a2p, short *a1p); + ~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Limits on a1 coefficient of second order predictor. + + Inputs: a1t, a2p + Output: a1p + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_limd(a1t, a2p, a1p) +short *a1t, *a2p, *a1p; +{ + long a1p1, a2p1, a1t1, ome, a1ll, a1ul; + + /* Preamble */ + a1t1 = *a1t & 65535; + a2p1 = *a2p & 65535; + + /* (1-epsilon), where epsilon = (1/16) */ + ome = 15360; + + /* Compute upper limit */ + a1ul = (ome + 65536 - a2p1) & 65535; + + /* Compute lower limit */ + a1ll = (a2p1 + 65536 - ome) & 65535; + + if (a1t1 >= 32768 && a1t1 <= a1ll) + a1p1 = a1ll; + else if (a1t1 >= a1ul && a1t1 <= 32767) + a1p1 = a1ul; + else + a1p1 = a1t1; + + *a1p = (short) a1p1; + +} + +/* ....................... end of G726_limd() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_trigb (short *tr, short *ap, short *ar); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Predictor trigger block. + + Inputs: tr, ap (ou bp ou tdp) + Output: ar (ou br ou tdr) + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_trigb(tr, ap, ar) +short *tr, *ap, *ar; +{ + *ar = (*tr == 0) ? *ap : 0; + +} + +/* ....................... end of G726_trigb() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_upa1 (short *pk0, short *pk1, short *a1, + ~~~~~~~~~~~~~~ short *sigpk, short *a1t); + + Description: + ~~~~~~~~~~~~ + + Update a1 coefficient of second order predictor. + + Inputs: pk0, pk1, a1, sigpk + Output: a1t + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_upa1(pk0, pk1, a1, sigpk, a1t) +short *pk0, *pk1, *a1, *sigpk, *a1t; +{ + long a11, a1s, ua1; + long ash; + short pks; + long uga1, ula1; + + /* Preamble */ + a11 = *a1 & 65535; + + pks = (*pk0) ^ (*pk1); + + /* Gain is +/- (3/256) */ + uga1 = (*sigpk == 1) ? 0 : ((pks == 0) ? 192 : 65344); + + a1s = (a11 >> 15); + + /* Leak factor is (1/256) */ + ash = (a11 >> 8); + ula1 = ((a1s == 0) ? (65536 - ash) : (65536 - (ash + 65280))) & 65535; + + /* Compute update */ + ua1 = (uga1 + ula1) & 65535; + *a1t = (short) ((a11 + ua1) & 65535); + +} + +/* ....................... end of G726_upa1() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_upa2 (short *pk0, short *pk1, short *pk2, + ~~~~~~~~~~~~~~ short *a2, short *a1, short *sigpk, short *a2t); + + Description: + ~~~~~~~~~~~~ + + Update a2 coefficient of second order predictor. + + Inputs: pk0, pk1, pk2, a2, a1, sigpk + Output: a2t + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_upa2(pk0, pk1, pk2, a2, a1, sigpk, a2t) +short *pk0, *pk1, *pk2, *a2, *a1, *sigpk, *a2t; +{ + long uga2a, uga2b, uga2s; + long a11, a21, fa, fa1; + short a1s, a2s; + long ua2; + long uga2, ula2; + short pks1, pks2; + + /* Preamble */ + a11 = *a1 & 65535; + a21 = *a2 & 65535; + + /* 1 bit xors */ + pks1 = (*pk0 ^ *pk1); + pks2 = (*pk0 ^ *pk2); + + uga2a = (pks2 == 0) ? 16384 : 114688; + + a1s = (*a1 >> 15); + + /* Implement f(a1) w/ limiting at +/-(1/2) */ + if (a1s == 0) + fa1 = (a11 <= 8191) ? (a11 << 2) : (8191 << 2); + else + fa1 = (a11 >= 57345) ? ((a11 << 2) & 131071) : (24577 << 2); + + /* Attach sign to the result of f(a1) */ + fa = (pks1) ? fa1 : ((131072 - fa1) & 131071); + + uga2b = (uga2a + fa) & 131071; + uga2s = (uga2b >> 16); + + uga2 = (*sigpk == 1) ? 0 : + ((uga2s) ? ((uga2b >> 7) + 64512) : (uga2b >> 7)); + + a2s = (*a2 >> 15); + + ula2 = (a2s == 0) ? (65536 - (a21 >> 7)) & 65535 : + (65536 - ((a21 >> 7) + 65024)) & 65535; + + /* Compute update */ + ua2 = (uga2 + ula2) & 65535; + *a2t = (short) ((a21 + ua2) & 65535); + +} + +/* ....................... end of G726_upa2() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_upb (short rate, short *u, short *b, short *dq, short *bp); + ~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Update for coefficients of sixth order predictor. + + Inputs: u, b, dq, rate + Output: bp + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_upb(rate, u, b, dq, bp) +short *u, *b, *dq, *bp; +short rate; +{ + short dqmag; + long bb, bs, ub; + long ugb, ulb; + short param; + short leak; + + /* Preamble */ + bb = *b & 65535; + + dqmag = *dq & 32767; + if (rate != 5) { + leak = 8; + param = 65280; + } else { + leak = 9; + param = 65408; + } + /* gain is 0 or +/- (1/128) */ + ugb = (dqmag == 0) ? 0 : ((*u == 0) ? 128 : 65408); + + bs = (bb >> 15); + + /* Leak factor is (1/256 or 1/512 for 40 kbit/s) */ + + ulb = (bs == 0) ? + ((65536 - (bb >> leak)) & 65535) : + ((65536 - ((bb >> leak) + param)) & 65535); + + /* Compute update */ + ub = (ugb + ulb) & 65535; +/* aux = bb + ub;*/ + + *bp = (short) ((bb + ub) & 65535); + +} + +/* ....................... end of G726_upb() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_xor (short *dqn, short *dq, short *u); + ~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + One bit "exclusive or" of sign of difference signal and sign + of delayed difference signal. + + Inputs: dqn, dq + Output: u + + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_xor(dqn, dq, u) +short *dqn, *dq, *u; +{ + short dqns; + short dqs; + + dqs = (*dq >> 15) & 1; + + dqns = (*dqn >> 10); + + *u = (dqs ^ dqns); + +} + +/* ....................... end of G726_xor() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_tone (short *a2p, short *tdp); + ~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Partial band signal detection. + + Inputs: a2p + Output: tdp + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_tone(a2p, tdp) +short *a2p, *tdp; +{ + long a2p1; + + a2p1 = *a2p & 65535; + + *tdp = (a2p1 >= 32768 && a2p1 < 53760) ? 1 : 0; + +} + +/* ....................... end of G726_tone() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_trans (short *td, long *yl, short *dq, short *tr); + ~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Transition detector. + + Inputs: td, yl, dq + Output: tr + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_trans(td, yl, dq, tr) +short *td; +long *yl; +short *dq, *tr; +{ + short dqmag; + long dqthr; + short ylint; + long dqmag1; + short ylfrac; + long thr1, thr2; + + dqmag = *dq & 32767; + + ylint = (*yl >> 15); + + ylfrac = (*yl >> 10) & 31; + + thr1 = (ylfrac + 32) << ylint; + + thr2 = (ylint > 9) ? 31744 : thr1; + + dqthr = (thr2 + (thr2 >> 1)) >> 1; + + dqmag1 = dqmag; + + *tr = (dqmag1 > dqthr && *td == 1) ? 1 : 0; + +} + +/* ....................... end of G726_trans() ....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_compress (short *sr, char *law, short *sp); + ~~~~~~~~~~~~~~~~~~ + + Description: + ~~~~~~~~~~~~ + + Convert from uniform pcm to either a-law or u-law pcm + + Inputs: sr, law + Output: sp + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + 24.Jan.00 v2.0 Corrected im calculation that caused incorrect + processing of test vector ri40fa. Corrected + code provided by Jayesh Patel <jayesh@dspse.com>. + Verified by <simao.campos@labs.comsat.com> + ---------------------------------------------------------------------- +*/ +void G726_compress(sr, law, sp) +short *sr; +char *law; +short *sp; +{ + short imag, iesp, ofst; + short ofst1; + long i; + long im; + short is; + long srr; + + is = (*sr >> 15); + srr = (*sr & 65535); + + /* Convert 2-complement to signed magnitude */ + im = (is == 0) ? srr : ((65536 - srr) & 32767); + + /* Compress ... */ + if (*law == '1') { + + /* Next line added by J.Patel to fix a with test vector ri40fa.o */ + im = (*sr == -32768) ? 2 : im; /* *** */ + + imag = (is == 0) ? (im >> 1) : ((im + 1) >> 1); + + if (is) + --imag; + + /* Saturation */ + if (imag > 4095) + imag = 4095; + + iesp = 7; + for (i = 1; i <= 7; ++i) { + imag += imag; + if (imag >= 4096) + break; + iesp = 7 - i; + } + + imag &= 4095; + + imag = (imag >> 8); + *sp = (is == 0) ? imag + (iesp << 4) : imag + (iesp << 4) + 128; + + /* Sign bit inversion */ + *sp ^= 128; + } else { + imag = im; + + if (imag > 8158) + imag = 8158; /* Saturation */ + + ++imag; + iesp = 0; + ofst = 31; + + if (imag > ofst) { + for (iesp = 1; iesp <= 8; ++iesp) { + ofst1 = ofst; + ofst += (1 << (iesp + 5)); + if (imag <= ofst) + break; + } + imag -= ofst1 + 1; + } + + imag /= (1 << (iesp + 1)); + + *sp = (is == 0) ? (imag + (iesp << 4)) : (imag + (iesp << 4) + 128); + + /* Sign bit inversion */ + *sp ^= 128; + *sp ^= 127; + } + +} + +/* ....................... end of G726_compress()....................... */ + + +/* + ---------------------------------------------------------------------- + + void G726_sync (short rate, short *i, short *sp, short *dlnx, + ~~~~~~~~~~~~~~ short *dsx, char *law, short *sd); + + Description: + ~~~~~~~~~~~~ + + Re-encode output pcm sample in decoder for synchronous tandem + coding. + + Inputs: i, sp, dlnx, dsx, law, rate + Output: sd + + Return value: none. + ~~~~~~~~~~~~~ + + Prototype: in g726.h + ~~~~~~~~~~ + + History: + ~~~~~~~~ + 31.Jan.91 v1.0f Release of 1st Fortran version to UGST. + <tdsindi@venus.cpqd.ansp.br> + 13.Feb.92 v1.0c 1st version in C translated from Fortran (f2c) + <tdsimao@venus.cpqd.ansp.br> + + ---------------------------------------------------------------------- +*/ +void G726_sync(rate, i, sp, dlnx, dsx, law, sd) +short *i, *sp, *dlnx, *dsx; +char *law; +short *sd; +short rate; +{ + short mask, id, im, is, ss; + + if (rate == 4) { + is = (*i >> 3); + + im = (is == 0) ? (*i + 8) : (*i & 7); + + /* Find value of `id' as in Table 17/G.726 */ + if (*dlnx >= 3972) + id = 9; + else if (*dlnx >= 2048) + id = 7; + else if (*dlnx >= 400) + id = 15; + else if (*dlnx >= 349) + id = 14; + else if (*dlnx >= 300) + id = 13; + else if (*dlnx >= 246) + id = 12; + else if (*dlnx >= 178) + id = 11; + else if (*dlnx >= 80) + id = 10; + else + id = 9; + + /* Account for the negative part of the table */ + if (*dsx) + id = 15 - id; + + if (id == 8) + id = 7; + } /* ............... end of 32 kbit part + * ................. */ + else if (rate == 3) { + is = (*i >> 2); + + im = (is == 0) ? (*i + 4) : (*i & 3); + + /* Find value of `id' as in the Table 18/G.726 */ + if (*dlnx >= 2048) + id = 3; + else if (*dlnx >= 331) + id = 7; + else if (*dlnx >= 218) + id = 6; + else if (*dlnx >= 8) + id = 5; + else if (*dlnx >= 0) + id = 3; + + + if (*dsx) + id = 7 - id; + + if (id == 4) + id = 3; + } /* ............... end of 24 kbit part + * ................. */ + else if (rate == 2) { + is = (*i >> 1); + + im = (is == 0) ? (*i + 2) : (*i & 1); + + /* Find value of `id' as in the Table 19/G.726 */ + if (*dlnx >= 2048) + id = 2; + else if (*dlnx >= 261) + id = 3; + else if (*dlnx >= 0) + id = 2; + + if (*dsx) + id = 3 - id; + + } /* ............... end of 16 kbit part + * ................. */ + else { + is = (*i >> 4); + + im = (is == 0) ? (*i + 16) : (*i & 15); + + /* Find value of `id' as in the Table 16/G.726 */ + + if (*dlnx >= 4080) + id = 18; + else if (*dlnx >= 3974) + id = 17; + else if (*dlnx >= 2048) + id = 15; + else if (*dlnx >= 553) + id = 31; + else if (*dlnx >= 528) + id = 30; + else if (*dlnx >= 502) + id = 29; + else if (*dlnx >= 475) + id = 28; + else if (*dlnx >= 445) + id = 27; + else if (*dlnx >= 413) + id = 26; + else if (*dlnx >= 378) + id = 25; + else if (*dlnx >= 339) + id = 24; + else if (*dlnx >= 298) + id = 23; + else if (*dlnx >= 250) + id = 22; + else if (*dlnx >= 198) + id = 21; + else if (*dlnx >= 139) + id = 20; + else if (*dlnx >= 68) + id = 19; + else if (*dlnx >= 0) + id = 18; + + if (*dsx) + id = 31 - id; + + if (id == 16) + id = 15; + + } /* ............... end of 40 kbit part + * ................. */ + + /* Choose sd as sp, sp+ or sp- */ + + ss = (*sp & 128) >> 7; + mask = (*sp & 127); + + if (*law == '1') { /* ......... A-law */ + if (id > im && ss == 1 && mask == 0) + ss = 0; + else if (id > im && ss == 1 && mask != 0) + mask--; + else if (id > im && ss == 0 && mask != 127) + mask++; + else if (id < im && ss == 1 && mask != 127) + mask++; + else if (id < im && ss == 0 && mask == 0) + ss = 1; + else if (id < im && ss == 0 && mask != 0) + mask--; + } else { /* ......... u-law */ + if (id > im && ss == 1 && mask == 127) { + ss = 0; + mask--; + } else if (id > im && ss == 1 && mask != 127) + mask++; + else if (id > im && ss == 0 && mask != 0) + mask--; + else if (id < im && ss == 1 && mask != 0) + mask--; + else if (id < im && ss == 0 && mask == 127) + ss = 1; + else if (id < im && ss == 0 && mask != 127) + mask++; + } + + *sd = mask + (ss << 7); + +} + +/* ........................ end of G726_sync() ........................ */ + +/* ************************* END OF G726.C ************************* */