⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpc10enc.c

📁 由HawK提供的语音压缩软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
  LPC-10 voice codec, part of the HawkVoice Direct Interface (HVDI)
  cross platform network voice library
  Copyright (C) 2001-2003 Phil Frisbie, Jr. (phil@hawksoft.com)

  The VBR algorithm was contributed by
  Ben Appleton <appleton@bigpond.net.au>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.
    
  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  Boston, MA  02111-1307, USA.
      
  Or go to http://www.gnu.org/copyleft/lgpl.html
*/

#ifndef MACOSX
#include <malloc.h>
#endif
#include <stdlib.h>
#include <memory.h>
#ifdef _MSC_VER

#pragma warning (disable:4711) /* to disable automatic inline warning */
#endif
#include <math.h>
#include "ftol.h"
#include "lpc10.h"

#define LPC10_BITS_IN_COMPRESSED_FRAME 54

#ifndef TRUE
#define TRUE (1)
#define FALSE (0)
#endif

#ifndef min
#define min(a,b) ((a) <= (b) ? (a) : (b))
#define max(a,b) ((a) >= (b) ? (a) : (b))
#endif

typedef struct lpc10_e_state {
    /* State used only by function hp100 */
    float z11;
    float z21;
    float z12;
    float z22;
    
    /* State used by function analys */
    float inbuf[540], pebuf[540];
    float lpbuf[696], ivbuf[312];
    float bias;
    long osbuf[10];  /* no initial value necessary */
    long osptr;     /* initial value 1 */
    long obound[3];
    long vwin[6]	/* was [2][3] */;   /* initial value vwin[4] = 307; vwin[5] = 462; */
    long awin[6]	/* was [2][3] */;   /* initial value awin[4] = 307; awin[5] = 462; */
    long voibuf[8]	/* was [2][4] */;
    float rmsbuf[3];
    float rcbuf[30]	/* was [10][3] */;
    float zpre;


    /* State used by function onset */
    float n;
    float d;   /* initial value 1.f */
    float fpc;   /* no initial value necessary */
    float l2buf[16];
    float l2sum1;
    long l2ptr1;   /* initial value 1 */
    long l2ptr2;   /* initial value 9 */
    long lasti;    /* no initial value necessary */
    int hyst;   /* initial value FALSE_ */

    /* State used by function voicin */
    float dither;   /* initial value 20.f */
    float snr;
    float maxmin;
    float voice[6]	/* was [2][3] */;   /* initial value is probably unnecessary */
    long lbve, lbue, fbve, fbue;
    long ofbue, sfbue;
    long olbue, slbue;

    /* State used by function dyptrk */
    float s[60];
    long p[120]	/* was [60][2] */;
    long ipoint;
    float alphax;

    /* State used by function chanwr */
    long isync;

} lpc10_e_state_t;

/* Table of constant values */
long lpcbits[10] = { 5,5,5,5,4,4,4,4,3,3 };

static long entau[60] = { 19,11,27,25,29,21,23,22,30,14,15,7,39,38,46,
	    42,43,41,45,37,53,49,51,50,54,52,60,56,58,26,90,88,92,84,86,82,83,
	    81,85,69,77,73,75,74,78,70,71,67,99,97,113,112,114,98,106,104,108,
	    100,101,76 };
static long enadd[8] = { 1920,-768,2432,1280,3584,1536,2816,-1152 };
static float enscl[8] = { .0204f,.0167f,.0145f,.0147f,.0143f,.0135f,.0125f,.0112f };
static long enbits[8] = { 6,5,4,4,4,4,3,3 };
static long entab6[64] = { 0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,
	    3,3,3,3,3,4,4,4,4,4,4,4,5,5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,9,9,
	    9,10,10,11,11,12,13,14,15 };
static long rmst[64] = { 1024,936,856,784,718,656,600,550,502,460,420,
	    384,352,328,294,270,246,226,206,188,172,158,144,132,120,110,102,
	    92,84,78,70,64,60,54,50,46,42,38,34,32,30,26,24,22,20,18,17,16,15,
	    14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 };

static void vparms(long *vwin, float *inbuf, float *lpbuf, long half,
                   float *dither, long *mintau, long *zc, long *lbe,
                   long *fbe, float *qs, float *rc1, float *ar_b, float *ar_f)
{
    /* Local variables */
    float temp;
    long vlen, stop, i;
    float e_pre;
    long start;
    float ap_rms, e_0, oldsgn, lp_rms, e_b, e_f, r_b, r_f, e0ap;
    
    /* Parameter adjustments */
    lpbuf -= 25;
    inbuf -= 181;
    
    /* Function Body */
    lp_rms = 0.f;
    ap_rms = 0.f;
    e_pre = 0.f;
    e0ap = 0.f;
    *rc1 = 0.f;
    e_0 = 0.f;
    e_b = 0.f;
    e_f = 0.f;
    r_f = 0.f;
    r_b = 0.f;
    *zc = 0;
    vlen = vwin[1] - vwin[0] + 1;
    start = vwin[0] + (half - 1) * vlen / 2 + 1;
    stop = start + vlen / 2 - 1;
    
    oldsgn = ((inbuf[start - 1] - *dither)<0.0f)?-1.0f:1.0f;
    for (i = start; i <= stop; ++i) {
        if(lpbuf[i] < 0.0f)
            lp_rms -= lpbuf[i];
        else
            lp_rms += lpbuf[i];
        if(inbuf[i] < 0.0f)
            ap_rms -= inbuf[i];
        else
            ap_rms += inbuf[i];
        temp = inbuf[i] - inbuf[i - 1];
        if(temp < 0.0f)
            e_pre -= temp;
        else
            e_pre += temp;
        e0ap += inbuf[i] * inbuf[i];
        *rc1 += inbuf[i] * inbuf[i - 1];
        e_0 += lpbuf[i] * lpbuf[i];
        e_b += lpbuf[i - *mintau] * lpbuf[i - *mintau];
        e_f += lpbuf[i + *mintau] * lpbuf[i + *mintau];
        r_f += lpbuf[i] * lpbuf[i + *mintau];
        r_b += lpbuf[i] * lpbuf[i - *mintau];
        if ((((inbuf[i] + *dither)<0.0f)?-1.0f:1.0f) != oldsgn) {
            ++(*zc);
            oldsgn = -oldsgn;
        }
        *dither = -(*dither);
    }
    *rc1 /= max(e0ap,1.f);
    *qs = e_pre / max(ap_rms * 2.f, 1.f);
    *ar_b = r_b / max(e_b,1.f) * (r_b / max(e_0,1.f));
    *ar_f = r_f / max(e_f,1.f) * (r_f / max(e_0,1.f));
    *zc = lrintf((float) (*zc << 1) * (90.f / vlen));
    /* Computing MIN */
    *lbe = min(lrintf(lp_rms * 0.25f * (90.f / vlen)),32767);
    /* Computing MIN */
    *fbe = min(lrintf(ap_rms * 0.25f * (90.f / vlen)),32767);
} /* vparms_ */

static void voicin(long *vwin, float *inbuf, float *lpbuf, long half,
            float *minamd, float *maxamd, long *mintau, float *ivrc, long *obound,
            long *voibuf, lpc10_encoder_state *st)
{
    /* Initialized data */
    
    float *dither;
    static float vdc[100]	/* was [10][10] */ = { 0.f,1714.f,-110.f,
        334.f,-4096.f,-654.f,3752.f,3769.f,0.f,1181.f,0.f,874.f,-97.f,
        300.f,-4096.f,-1021.f,2451.f,2527.f,0.f,-500.f,0.f,510.f,-70.f,
        250.f,-4096.f,-1270.f,2194.f,2491.f,0.f,-1500.f,0.f,500.f,-10.f,
        200.f,-4096.f,-1300.f,2e3f,2e3f,0.f,-2e3f,0.f,500.f,0.f,0.f,
        -4096.f,-1300.f,2e3f,2e3f,0.f,-2500.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,
        0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,
        0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,
        0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f };
    static float vdcl[10] = { 600.f,450.f,300.f,200.f,0.f,0.f,0.f,0.f,0.f,0.f };
    
    /* Local variables */
    float ar_b, ar_f;
    long snrl, i;
    float *voice;
    float value[9];
    long zc;
    int ot;
    float qs;
    long vstate;
    float rc1;
    long fbe, lbe;
    float snr2;
    
    
    /*   Declare and initialize filters: */
    
    dither = (&st->dither);
    voice = (&st->voice[0]);
    
    /* Function Body */
    
    /*   Update linear discriminant function history each frame: */
    if (half == 1) {
        voice[0] = voice[2];
        voice[1] = voice[3];
        voice[2] = voice[4];
        voice[3] = voice[5];
        st->maxmin = *maxamd / max(*minamd, 1.f);
    }
    /*   Calculate voicing parameters twice per frame: */
    vparms(vwin, inbuf, lpbuf, half, dither, mintau,
        &zc, &lbe, &fbe, &qs, &rc1, &ar_b, &ar_f);
        /*   Estimate signal-to-noise ratio to select the appropriate VDC vector. */
    st->snr = (float) lrintf((st->snr + st->fbve / (float) max(st->fbue, 1)) * 63 / 64.f);
    snr2 = st->snr * st->fbue / max(st->lbue, 1);
    /*   Quantize SNR to SNRL according to VDCL thresholds. */
    for (snrl = 1; snrl <= 4; ++snrl) {
        if (snr2 > vdcl[snrl - 1]) {
            break;
        }
    }
    /*   Linear discriminant voicing parameters: */
    value[0] = st->maxmin;
    value[1] = (float) lbe / max(st->lbve, 1);
    value[2] = (float) zc;
    value[3] = rc1;
    value[4] = qs;
    value[5] = ivrc[1];
    value[6] = ar_b;
    value[7] = ar_f;
    /*   Evaluation of linear discriminant function: */
    voice[half + 3] = vdc[snrl * 10 - 1];
    for (i = 1; i <= 8; ++i) {
        voice[half + 3] += vdc[i + snrl * 10 - 11] * value[i - 1];
    }
    /*   Classify as voiced if discriminant > 0, otherwise unvoiced */
    /*   Voicing decision for current half-frame:  1 = Voiced; 0 = Unvoiced */
    if (voice[half + 3] > 0.f) {
        voibuf[half + 5] = 1;
    } else {
        voibuf[half + 5] = 0;
    }
    /*   Skip voicing decision smoothing in first half-frame: */
    vstate = -1;
    if (half != 1) {
        /*   Determine if there is an onset transition between P and 1F. */
        /*   OT (Onset Transition) is true if there is an onset between */
        /*   P and 1F but not after 1F. */
        ot = ((obound[0] & 2) != 0 || obound[1] == 1) && (obound[2] & 1) == 0;
        /*   Multi-way dispatch on voicing decision history: */
        vstate = (voibuf[2] << 3) + (voibuf[3] << 2) + (voibuf[4] << 1) + voibuf[5];
        
        switch (vstate + 1) {
        case 1:
            break;
        case 2:
            if (ot && voibuf[6] == 1) {
                voibuf[4] = 1;
            }
            break;
        case 3:
            if (voibuf[6] == 0 || voice[2] < -voice[3]) {
                voibuf[4] = 0;
            } else {
                voibuf[5] = 1;
            }
            break;
        case 4:
            break;
        case 5:
            voibuf[3] = 0;
            break;
        case 6:
            if (voice[1] < -voice[2]) {
                voibuf[3] = 0;
            } else {
                voibuf[4] = 1;
            }
            break;
        case 7:
            if (voibuf[0] == 1 || voibuf[6] == 1 || voice[3] > voice[0]) {
                voibuf[5] = 1;
            } else {
                voibuf[2] = 1;
            }
            break;
        case 8:
            if (ot) {
                voibuf[3] = 0;
            }
            break;
        case 9:
            if (ot) {
                voibuf[3] = 1;
            }
            break;
        case 10:
            break;
        case 11:
            if (voice[2] < -voice[1]) {
                voibuf[4] = 0;
            } else {
                voibuf[3] = 1;
            }
            break;
        case 12:
            voibuf[3] = 1;
            break;
        case 13:
            break;
        case 14:
            if (voibuf[6] == 0 && voice[3] < -voice[2]) {
                voibuf[5] = 0;
            } else {
                voibuf[4] = 1;
            }
            break;
        case 15:
            if (ot && voibuf[6] == 0) {
                voibuf[4] = 0;
            }
            break;
        case 16:
            break;
        }
    }
    /*   Now update parameters: */
    if (voibuf[half + 5] == 0) {
        /* Computing MIN */
        st->sfbue = lrintf((st->sfbue * 63 + (min(fbe, st->ofbue * 3) << 3)) / 64.f);
        st->fbue = st->sfbue / 8;
        st->ofbue = fbe;
        /* Computing MIN */
        st->slbue = lrintf((st->slbue * 63 + (min(lbe, st->olbue * 3) << 3)) / 64.f);
        st->lbue = st->slbue / 8;
        st->olbue = lbe;
    } else {
        st->lbve = lrintf((st->lbve * 63 + lbe) / 64.f);
        st->fbve = lrintf((st->fbve * 63 + fbe) / 64.f);
    }
    /*   Set dither threshold to yield proper zero crossing rates in the */
    /*   presence of low frequency noise and low level signal input. */
    *dither = min(max(((float)sqrt((float) (st->lbue * st->lbve)) * 64 / 3000), 1.f),20.f);
} /* voicin_ */

static void difmag(float *speech, long *tau, 
            long ltau, long maxlag, float *amdf,
            long *minptr, long *maxptr)
{
    /* Local variables */
    long i, j, n1, n2;
    long lmin, lmax;
    float sum;
    
    /* Function Body */
    lmin = 0;
    lmax = 0;

    for (i = 0; i < ltau; ++i) {
        long t = tau[i];

        n1 = (maxlag - t) / 2;
        n2 = n1 + 156;
        sum = 0.f;
        t += n1;
        for (j = n1; j < n2; j += 4, t += 4) {
            float temp = speech[j] - speech[t];

            if(temp < 0.0f)
            {
                sum -= temp;
            }
            else
            {
                sum += temp;
            }
        }
        if (sum < amdf[lmin]) {
            lmin = i;
        } else if (sum > amdf[lmax]) {
            lmax = i;
        }
        amdf[i] = sum;
    }
    *minptr = lmin + 1;
    *maxptr = lmax + 1;
} /* difmag_ */

static void tbdm(float *speech, long *tau, float *amdf, long *minptr, long *maxptr, long *mintau)
{
    /* Local variables */
    float amdf2[6];
    long minp2, ltau2, maxp2, i, j;
    long minamd, ptr, tau2[6];
    
    /*   Compute full AMDF using log spaced lags, find coarse minimum */
    /* Parameter adjustments */
    --amdf;
    --tau;
    
    /* Function Body */
    difmag(speech, &tau[1], 60, tau[60], &amdf[1], minptr, maxptr);
    *mintau = tau[*minptr];
    minamd = (long)amdf[*minptr];
    /*   Build table containing all lags within +/- 3 of the AMDF minimum */
    /*    excluding all that have already been computed */
    ltau2 = 0;
    ptr = *minptr - 2;
    /* Computing MIN */
    j = min(*mintau + 3, tau[60] - 1);
    /* Computing MAX */
    i = max(*mintau - 3, 41);
    for (; i <= j; ++i) {
        while(tau[ptr] < i) {
            ++ptr;
        }
        if (tau[ptr] != i) {
            ++ltau2;
            tau2[ltau2 - 1] = i;
        }
    }
    /*   Compute AMDF of the new lags, if there are any, and choose one */
    /*    if it is better than the coarse minimum */
    if (ltau2 > 0) {
        difmag(speech, tau2, ltau2, tau[60], amdf2, &minp2, &maxp2);
        if (amdf2[minp2 - 1] < (float) minamd) {
            *mintau = tau2[minp2 - 1];
            minamd = (long)amdf2[minp2 - 1];
        }
    }
    /*   Check one octave up, if there are any lags not yet computed */
    if (*mintau >= 80) {
        i = *mintau / 2;
        if ((i & 1) == 0) {
            ltau2 = 2;
            tau2[0] = i - 1;
            tau2[1] = i + 1;
        } else {
            ltau2 = 1;
            tau2[0] = i;
        }
        difmag(speech, tau2, ltau2, tau[60], amdf2, &minp2, &maxp2);
        if (amdf2[minp2 - 1] < (float) minamd) {
            *mintau = tau2[minp2 - 1];
            minamd = (long)amdf2[minp2 - 1];
            *minptr += -20;
        }
    }
    /*   Force minimum of the AMDF array to the high resolution minimum */
    amdf[*minptr] = (float) minamd;
    /*   Find maximum of AMDF within 1/2 octave of minimum */
    /* Computing MAX */
    *maxptr = max(*minptr - 5,1);
    /* Computing MIN */
    j = min(*minptr + 5, 60);
    for (i = *maxptr + 1; i <= j; ++i) {
        if (amdf[i] > amdf[*maxptr]) {
            *maxptr = i;
        }
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -