diff spandsp-0.0.6pre17/src/lpc10_placev.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spandsp-0.0.6pre17/src/lpc10_placev.c	Fri Jun 25 15:50:58 2010 +0200
@@ -0,0 +1,336 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * lpc10_placev.c - LPC10 low bit rate speech codec.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2006 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This code is based on the U.S. Department of Defense reference
+ * implementation of the LPC-10 2400 bps Voice Coder. They do not
+ * exert copyright claims on their code, and it may be freely used.
+ *
+ * $Id: lpc10_placev.c,v 1.19 2009/01/28 03:41:27 steveu Exp $
+ */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <memory.h>
+#if defined(HAVE_TGMATH_H)
+#include <tgmath.h>
+#endif
+#if defined(HAVE_MATH_H)
+#include <math.h>
+#endif
+#include "floating_fudge.h"
+
+#include "spandsp/telephony.h"
+#include "spandsp/dc_restore.h"
+#include "spandsp/lpc10.h"
+
+#include "lpc10_encdecs.h"
+
+#define subsc(x,y) (((x) << 1) + (y))
+
+void lpc10_placea(int32_t *ipitch,
+                  int32_t voibuf[3][2],
+                  int32_t *obound,
+                  int32_t af,
+                  int32_t vwin[3][2],
+                  int32_t awin[3][2],
+                  int32_t ewin[3][2], 
+                  int32_t lframe,
+                  int32_t maxwin)
+{
+    int allv;
+    int winv;
+    int32_t i;
+    int32_t j;
+    int32_t k;
+    int32_t l;
+    int32_t hrange;
+    int ephase;
+    int32_t lrange;
+    
+    lrange = (af - 2)*lframe + 1;
+    hrange = af*lframe;
+
+    /* Place the analysis window based on the voicing window placement,
+       onsets, tentative voicing decision, and pitch. */
+
+    /* Case 1:  Sustained voiced speech
+       If the five most recent voicing decisions are
+       voiced, then the window is placed phase-synchronously with the
+       previous window, as close to the present voicing window if possible.
+       If onsets bound the voicing window, then preference is given to
+       a phase-synchronous placement which does not overlap these onsets. */
+
+    /* Case 2:  Voiced transition
+       If at least one voicing decision in AF is voicied, and there are no
+       onsets, then the window is placed as in case 1. */
+
+    /* Case 3:  Unvoiced speech or onsets
+       If both voicing decisions in AF are unvoiced, or there are onsets
+       then the window is placed coincident with the voicing window. */
+
+    /* Note:  During phase-synchronous placement of windows, the length
+       is not altered from MAXWIN, since this would defeat the purpose
+       of phase-synchronous placement. */
+
+    /* Check for case 1 and case 2 */
+    allv = voibuf[af - 2][1] == 1
+           &&
+           voibuf[af - 1][0] == 1
+           &&
+           voibuf[af - 1][1] == 1
+           &&
+           voibuf[af][0] == 1
+           &&
+           voibuf[af][1] == 1;
+    winv = voibuf[af][0] == 1  ||  voibuf[af][1] == 1;
+    if (allv  ||  (winv  &&  *obound == 0))
+    {
+        /* APHASE:  Phase synchronous window placement. */
+        /* Get minimum lower index of the window. */
+        i = (lrange + *ipitch - 1 - awin[af - 2][0]) / *ipitch;
+        i *= *ipitch;
+        i += awin[af - 2][0];
+        /* l = the actual length of this frame's analysis window. */
+        l = maxwin;
+        /* Calculate the location where a perfectly centered window would start. */
+        k = (vwin[af - 1][0] + vwin[af - 1][1] + 1 - l)/2;
+        /* Choose the actual location to be the pitch multiple closest to this */
+        awin[af - 1][0] = i + ((int) floorf((float) (k - i)/(float) *ipitch + 0.5f))*(*ipitch);
+        awin[af - 1][1] = awin[af - 1][0] + l - 1;
+        /* If there is an onset bounding the right of the voicing window and the
+           analysis window overlaps that, then move the analysis window backward
+           to avoid this onset. */
+        if (*obound >= 2  &&  awin[af - 1][1] > vwin[af - 1][1])
+        {
+            awin[af - 1][0] -= *ipitch;
+            awin[af - 1][1] -= *ipitch;
+        }
+        /* Similarly for the left of the voicing window. */
+        if ((*obound == 1  ||  *obound == 3)  &&  awin[af - 1][0] < vwin[af - 1][0])
+        {
+            awin[af - 1][0] += *ipitch;
+            awin[af - 1][1] += *ipitch;
+        }
+        /* If this placement puts the analysis window above HRANGE, then
+           move it backward an integer number of pitch periods. */
+        while (awin[af - 1][1] > hrange)
+        {
+            awin[af - 1][0] -= *ipitch;
+            awin[af - 1][1] -= *ipitch;
+        }
+        /* Similarly if the placement puts the analysis window below LRANGE. */
+        while (awin[af - 1][0] < lrange)
+        {
+            awin[af - 1][0] += *ipitch;
+            awin[af - 1][1] += *ipitch;
+        }
+        /* Make energy window be phase-synchronous. */
+        ephase = TRUE;
+    }
+    else
+    {
+        /* Case 3 */
+        awin[af - 1][0] = vwin[af - 1][0];
+        awin[af - 1][1] = vwin[af - 1][1];
+        ephase = FALSE;
+    }
+    /* RMS is computed over an integer number of pitch periods in the analysis
+       window.  When it is not placed phase-synchronously, it is placed as close
+       as possible to onsets. */
+    j = (awin[af - 1][1] - awin[af - 1][0] + 1) / *ipitch * *ipitch;
+    if (j == 0  ||  !winv)
+    {
+        ewin[af - 1][0] = vwin[af - 1][0];
+        ewin[af - 1][1] = vwin[af - 1][1];
+    }
+    else if (!ephase  &&  *obound == 2)
+    {
+        ewin[af - 1][0] = awin[af - 1][1] - j + 1;
+        ewin[af - 1][1] = awin[af - 1][1];
+    }
+    else
+    {
+        ewin[af - 1][0] = awin[af - 1][0];
+        ewin[af - 1][1] = awin[af - 1][0] + j - 1;
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+void lpc10_placev(int32_t *osbuf,
+                  int32_t *osptr,
+                  int32_t oslen, 
+                  int32_t *obound,
+                  int32_t vwin[3][2],
+                  int32_t af,
+                  int32_t lframe,
+                  int32_t minwin,
+                  int32_t maxwin,
+                  int32_t dvwinl,
+                  int32_t dvwinh)
+{
+    int32_t i1;
+    int32_t i2;
+    int crit;
+    int32_t q;
+    int32_t osptr1;
+    int32_t hrange;
+    int32_t lrange;
+    int i;
+
+    /* Voicing window placement */
+
+    /*         __________________ __________________ ______________ */
+    /*        |                  |                  |               */
+    /*        |        1F        |        2F        |        3F ... */
+    /*        |__________________|__________________|______________ */
+
+    /*    Previous | */
+    /*      Window | */
+    /*  ...________| */
+
+    /*             |                                | */
+    /*      ------>| This window's placement range  |<------ */
+    /*             |                                | */
+
+    /* There are three cases.  Note these are different from those
+       given in the LPC-10e phase 1 report. */
+
+    /* 1.  If there are no onsets in this range, then the voicing window
+       is centered in the pitch window.  If such a placement is not within
+       the window's placement range, then the window is placed in the left-most
+       portion of the placement range.  Its length is always MAXWIN. */
+
+    /* 2.  If the first onset is in 2F and there is sufficient room to place
+       the window immediately before this onset, then the window is placed
+       there, and its length is set to the maximum possible under these
+       constraints. */
+
+    /* "Critical Region Exception":  If there is another onset in 2F
+       such that a window can be placed between the two onsets, the
+       window is placed there (ie, as in case 3). */
+
+    /* 3.  Otherwise, the window is placed immediately after the onset.  The
+       window's length is the longest length that can fit in the range under these
+       constraints, except that the window may be shortened even further to avoid
+       overlapping other onsets in the placement range.  In any case, the window's
+       length is at least MINWIN. */
+
+    /* Note that the values of MINWIN and LFRAME must be chosen such
+       that case 2 = false implies case 3 = true.   This means that
+       MINWIN <= LFRAME/2.  If this were not the case, then a fourth case
+       would have to be added for when the window cannot fit either before
+       or after the onset. */
+
+    /* Note also that onsets which weren't in 2F last time may be in 1F this
+       time, due to the filter delays in computing onsets.  The result is that
+       occasionally a voicing window will overlap that onset.  The only way
+       to circumvent this problem is to add more delay in processing input
+       speech.  In the trade-off between delay and window-placement, window
+       placement lost. */
+
+    /* Compute the placement range */
+
+    /* Computing MAX */
+    i1 = vwin[af - 2][1] + 1;
+    i2 = (af - 2)*lframe + 1;
+    lrange = max(i1, i2);
+    hrange = af*lframe;
+    /* Compute OSPTR1, so the following code only looks at relevant onsets. */
+    for (osptr1 = *osptr - 1;  osptr1 >= 1;  osptr1--)
+    {
+        if (osbuf[osptr1 - 1] <= hrange)
+            break;
+    }
+    osptr1++;
+    /* Check for case 1 first (fast case) */
+    if (osptr1 <= 1  ||  osbuf[osptr1 - 2] < lrange)
+    {
+        /* Compute max */
+        i1 = vwin[af - 2][1] + 1;
+        vwin[af - 1][0] = max(i1, dvwinl);
+        vwin[af - 1][1] = vwin[af - 1][0] + maxwin - 1;
+        *obound = 0;
+    }
+    else
+    {
+        /* Search backward in OSBUF for first onset in range. */
+        /* This code relies on the above check being performed first. */
+        for (q = osptr1 - 1;  q >= 1;  q--)
+        {
+            if (osbuf[q - 1] < lrange)
+                break;
+        }
+        q++;
+        /* Check for case 2 (placement before onset): */
+        /* Check for critical region exception: */
+        crit = FALSE;
+        for (i = q + 1;  i < osptr1;  i++)
+        {
+            if (osbuf[i - 1] - osbuf[q - 1] >= minwin)
+            {
+                crit = TRUE;
+                break;
+            }
+        }
+        /* Compute max */
+        i1 = (af - 1)*lframe;
+        i2 = lrange + minwin - 1;
+        if (!crit  &&  osbuf[q - 1] > max(i1, i2))
+        {
+            vwin[af - 1][1] = osbuf[q - 1] - 1;
+            /* Compute max */
+            i2 = vwin[af - 1][1] - maxwin + 1;
+            vwin[af - 1][0] = max(lrange, i2);
+            *obound = 2;
+        }
+        else
+        {
+            /* Case 3 (placement after onset) */
+            vwin[af - 1][0] = osbuf[q - 1];
+            do
+            {
+                if (++q >= osptr1
+                    ||
+                    osbuf[q - 1] > vwin[af - 1][0] + maxwin)
+                {
+                    /* Compute min */
+                    i1 = vwin[af - 1][0] + maxwin - 1;
+                    vwin[af - 1][1] = min(i1, hrange);
+                    *obound = 1;
+                    return;
+                }
+            }
+            while (osbuf[q - 1] < vwin[af - 1][0] + minwin);
+            vwin[af - 1][1] = osbuf[q - 1] - 1;
+            *obound = 3;
+        }
+    }
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.