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

📄 openlpc.fixed.c

📁 LPC10 2.4Kpbs 语音压缩定点运算C语言源程序OPENLPC
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
  Fixed point OpenLPC codec
  Copyright (C) 2003-2005 Phil Frisbie, Jr. (phil@hawksoft.com)

  This is a major rewrite of the orginal floating point OpenLPC
  code from Future Dynamics. As such, a copywrite notice is not
  required to credit Future Dynamics.

  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
*/
/************************************************************************\

  Low bitrate LPC CODEC derived from the public domain implementation 
  of Ron Frederick.
  
  The basic design is preserved, except for several bug fixes and
  the following modifications:
    
  1. The pitch detector operates on the (downsampled) signal, not on 
  the residue. This appears to yield better performances, and it
  lowers the processing load.
  2. Each frame is elongated by 50% prefixing it with the last half
  of the previous frame. This design, inherited from the original
  code for windowing purposes, is exploited in order to provide 
  two independent pitch analyses: on the first 2/3, and on the 
  second 2/3 of the elongated frame (of course, they overlap by 
  half):
      
  last half old frame	            new frame
  --------------------========================================
  <--------- first pitch region --------->
                      <--------- second pitch region  ------->
        
  Two voiced/unvoiced flags define the voicing status of each
  region; only one value for the period is retained (if both
  halves are voiced, the average is used).
  The two flags are used by the synthesizer for the halves of
  each frame to play back. Of course, this is non optimal but
  is good enough (a half-frame would be too short for measuring
  low pitches)
  3. The parameters (one float for the period (pitch), one for the
  gain, and ten for the LPC-10 filter) are quantized according 
  this procedure:
  - the period is logarithmically compressed, then quantized 
  as 8-bit unsigned int (6 would actually suffice)
  - the gain is logarithmically compressed (using a different
  formula), then quantized at 6-bit unsigned int. The two
  remaining bits are used for the voicing flags.
  - the first two LPC parameters (k[1] and k[2]) are multiplied
  by PI/2, and the arcsine of the result is quantized as
  6 and 5 bit signed integers. This has proved more effective
  than the log-area compression used by LPC-10.
  - the remaining eight LPC parameters (k[3]...k[10]) are
  quantized as, respectively, 5,4,4,3,3,3,3 and 2 bit signed
  integers.
  Finally, period and gain plus voicing flags are stored in the
  first two bytes of the 7-byte parameters block, and the quantized
  LPC parameters are packed into the remaining 5 bytes. Two bits
  remain unassigned, and can be used for error detection or other
  purposes.

  The frame lenght is actually variable, and is simply passed as 
  initialization parameter to lpc_init(): this allows to experiment
  with various frame lengths. Long frames reduce the bitrate, but
  exceeding 320 samples (i.e. 40 ms, at 8000 samples/s) tend to
  deteriorate the speech, that sounds like spoken by a person 
  affected by a stroke: the LPC parameters (modeling the vocal 
  tract) can't change fast enough for a natural-sounding synthesis.
  25 ms per frame already yields a quite tight compression, corresponding
  to 1000/40 * 7 * 8 = 1400 bps. The quality improves little with 
  frames shorter than 250 samples (32 frames/s), so this is a recommended
  compromise. The bitrate is 32 * 7 * 8 = 1792 bps.
  
  The synthesizer has been modified as well. For voiced subframes it 
  now uses a sawtooth excitation, instead of the original pulse train.
  This idea, copied from MELP, reduces the buzzing-noise artifacts.
  In order to compensate the non-white spectrum of the sawtooth, a 
  pre-emphasis is applied to the signal before the Durbin calculation.
  The filter has (in s-space) two zeroes at (640, 0) Hz and two poles 
  at (3200, 0) Hz. These filters have been handoded, and may not be 
  optimal. Two other filters (anti-hum high-pass with corner at 100 Hz,
  and pre-downsampling lowpass with corner at 300 Hz) are Butterworth
  designs produced by the MkFilter package by A.J. Fisher
  (http://www.cs.york.ac.uk/~fisher/mkfilter/).

\************************************************************************/

#ifdef _MSC_VER
#pragma warning (disable:4711) /* to disable automatic inline warning */
  #define M_PI (3.1415926535897932384626433832795)
#endif

#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <math.h>
#include "openlpc.h"

#define fixed32         long

#if defined WIN32 || defined WIN64 || defined (_WIN32_WCE)
#define fixed64         __int64
#else
#define fixed64         long long
#endif

/* These are for development and debugging and should not be changed unless
you REALLY know what you are doing ;) */
#define IGNORE_OVERFLOW
#define FAST_FILTERS
#define PRECISION       20

#define ftofix32(x)       ((fixed32)((x) * (float)(1 << PRECISION) + ((x) < 0 ? -0.5 : 0.5)))
#define itofix32(x)       ((x) << PRECISION)
#define fixtoi32(x)       ((x) >> PRECISION)
#define fixtof32(x)       (float)((float)(x) / (float)(1 << PRECISION))

static fixed32 fixmul32(fixed32 x, fixed32 y)
{
    fixed64 temp;
    
    temp = x;
    temp *= y;
    temp >>= PRECISION;
#ifndef IGNORE_OVERFLOW
    if(temp > 0x7fffffff)
    {
        return 0x7fffffff;
    }
    else if(temp < -0x7ffffffe)
    {
        return -0x7ffffffe;
    }
#endif
    return (fixed32)temp;
}

static fixed32 fixdiv32(fixed32 x, fixed32 y)
{
    fixed64 temp;
    
    if(x == 0)
        return 0;
    if(y == 0)
        return 0x7fffffff;
    temp = x;
    temp <<= PRECISION;
    return (fixed32)(temp / y);
}

static fixed32 fixsqrt32(fixed32 x)
{
    
    unsigned long r = 0, s, v = (unsigned long)x;
    
#define STEP(k) s = r + (1 << k * 2); r >>= 1; \
    if (s <= v) { v -= s; r |= (1 << k * 2); }
    
    STEP(15);
    STEP(14);
    STEP(13);
    STEP(12);
    STEP(11);
    STEP(10);
    STEP(9);
    STEP(8);
    STEP(7);
    STEP(6);
    STEP(5);
    STEP(4);
    STEP(3);
    STEP(2);
    STEP(1);
    STEP(0);
    
    return (fixed32)(r << (PRECISION / 2));
}

__inline static fixed32 fixexp32(fixed32 x)
{
    fixed64 result = ftofix32(1.f);
    fixed64 temp;
    int     sign = 1;

    /* reduce range to 0.0 to 1.0 */
    if(x < 0)
    {
        x = (fixed32)-x;
        sign = -1;
    }
    while(x > itofix32(1))
    {
        x -= itofix32(1);
        result *= ftofix32(2.718282f);
        result >>= PRECISION;
    }
    /* reduce range to 0.0 to 0.5 */
    if(x > ftofix32(0.5f))
    {
        x -= ftofix32(0.5f);
        result *= ftofix32(1.648721f);
        result >>= PRECISION;
    }
    if(result > 0x7fffffff)
    {
        return 0x7fffffff;
    }
    temp = ftofix32(0.00138888f) * x;
    temp >>= PRECISION;
    temp = (temp + ftofix32(0.00833333f)) * x;
    temp >>= PRECISION;
    temp = (temp + ftofix32(0.04166666f)) * x;
    temp >>= PRECISION;
    temp = (temp + ftofix32(0.16666666f)) * x;
    temp >>= PRECISION;
    temp = (temp + ftofix32(0.5f)) * x;
    temp >>= PRECISION;
    temp = (temp + ftofix32(1.0f)) * x;
    temp >>= PRECISION;
    result *= (temp + ftofix32(1.f));
    result >>= PRECISION;
    if(sign == -1)
    {
        temp = 1;
        result = (temp << (PRECISION * 2)) / result;
    }
    if(result > 0x7fffffff)
    {
        return 0x7fffffff;
    }
    return (fixed32)result;
}

__inline static fixed32 fixlog32(fixed32 x)
{
    fixed64 result = 0;
    fixed64 temp;

    if(x == 0)
    {
        return -0x7ffffffe;
    }
    else if(x < 0)
    {
        return 0;
    }
    while(x > itofix32(2))
    {
        result += ftofix32(0.693147f);
        x /= 2;
    }
    while(x < itofix32(1))
    {
        result -= ftofix32(0.693147f);
        x *= 2;
    }
    x -= itofix32(1);
    temp = ftofix32(-.0064535442f) * x;
    temp >>= PRECISION;
    temp = (temp + ftofix32(.0360884937f)) * x;
    temp >>= PRECISION;
    temp = (temp - ftofix32(.0953293897f)) * x;
    temp >>= PRECISION;
    temp = (temp + ftofix32(.1676540711f)) * x;
    temp >>= PRECISION;
    temp = (temp - ftofix32(.2407338084f)) * x;
    temp >>= PRECISION;
    temp = (temp + ftofix32(.3317990258f)) * x;
    temp >>= PRECISION;
    temp = (temp - ftofix32(.4998741238f)) * x;
    temp >>= PRECISION;
    temp = (temp + ftofix32(.9999964239f)) * x;
    temp >>= PRECISION;
    result += temp;

    return (fixed32)result;
}

__inline fixed32 fixsin32(fixed32 x)
{
    fixed64 x2, temp;
    int     sign = 1;

    if(x < 0)
    {
        sign = -1;
        x = -x;
    }
    while(x > ftofix32(M_PI))
    {
        x -= ftofix32(M_PI);
        sign = -sign;
    }
    if(x > ftofix32(M_PI/2))
    {
        x = ftofix32(M_PI) - x;
    }
    x2 = (fixed64)x * x;
    x2 >>= PRECISION;
    if(sign != 1)
    {
        x = -x;
    }
    temp = ftofix32(-.0000000239f) * x2;
    temp >>= PRECISION;
    temp = (temp + ftofix32(.0000027526f)) * x2;
    temp >>= PRECISION;
    temp = (temp - ftofix32(.0001984090f)) * x2;
    temp >>= PRECISION;
    temp = (temp + ftofix32(.0083333315f)) * x2;
    temp >>= PRECISION;
    temp = (temp - ftofix32(.1666666664f)) * x2;
    temp >>= PRECISION;
    temp += itofix32(1);
    temp = temp * x;
    temp >>= PRECISION;

    return  (fixed32)(temp);
}

__inline fixed32 fixasin32(fixed32 x)
{
    fixed64 temp;
    int     sign = 1;

    if(x > itofix32(1) || x < itofix32(-1))
    {
        return 0;
    }
    if(x < 0)
    {
        sign = -1;
        x = -x;
    }
    temp = 0;
    temp = ftofix32(-.0012624911f) * (fixed64)x;
    temp >>= PRECISION;
    temp = (temp + ftofix32(.0066700901f)) * x;

⌨️ 快捷键说明

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