diff spandsp-0.0.3/spandsp-0.0.3/src/gsm0610_encode.c @ 5:f762bf195c4b

import spandsp-0.0.3
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 16:00:21 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spandsp-0.0.3/spandsp-0.0.3/src/gsm0610_encode.c	Fri Jun 25 16:00:21 2010 +0200
@@ -0,0 +1,332 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * gsm0610_encode.c - GSM 06.10 full 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 General Public License version 2, 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 widely used GSM 06.10 code available from
+ * http://kbs.cs.tu-berlin.de/~jutta/toast.html
+ *
+ * $Id: gsm0610_encode.c,v 1.12 2006/11/30 15:41:47 steveu Exp $
+ */
+
+/*! \file */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <inttypes.h>
+#if defined(HAVE_TGMATH_H)
+#include <tgmath.h>
+#endif
+#if defined(HAVE_MATH_H)
+#include <math.h>
+#endif
+#include <stdlib.h>
+#include <memory.h>
+
+#include "spandsp/telephony.h"
+#include "spandsp/dc_restore.h"
+#include "spandsp/bitstream.h"
+#include "spandsp/gsm0610.h"
+
+#include "gsm0610_local.h"
+
+/* 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER */
+
+/* The RPE-LTD coder works on a frame by frame basis.  The length of
+   the frame is equal to 160 samples.  Some computations are done
+   once per frame to produce at the output of the coder the
+   LARc[1..8] parameters which are the coded LAR coefficients and 
+   also to realize the inverse filtering operation for the entire
+   frame (160 samples of signal d[0..159]).  These parts produce at
+   the output of the coder:
+
+   Procedure 4.2.11 to 4.2.18 are to be executed four times per
+   frame.  That means once for each sub-segment RPE-LTP analysis of
+   40 samples.  These parts produce at the output of the coder.
+*/
+static void encode_a_frame(gsm0610_state_t *s, const int16_t amp[], gsm0610_frame_t *f)
+{
+    int k;
+    int16_t *dp;
+    int16_t *dpp;
+    int16_t so[GSM0610_FRAME_LEN];
+    int i;
+
+    dp = s->dp0 + 120;
+    dpp = dp;
+    gsm0610_preprocess(s, amp, so);
+    gsm0610_lpc_analysis(s, so, f->LARc);
+    gsm0610_short_term_analysis_filter(s, f->LARc, so);
+
+    for (k = 0;  k < 4;  k++)
+    {
+        gsm0610_long_term_predictor(s,
+                                    so + k*40,
+                                    dp,
+                                    s->e + 5,
+                                    dpp,
+                                    &f->Nc[k],
+                                    &f->bc[k]);
+        gsm0610_rpe_encoding(s, s->e + 5, &f->xmaxc[k], &f->Mc[k], f->xMc[k]);
+
+        for (i = 0;  i < 40;  i++)
+            dp[i] = gsm_add(s->e[5 + i], dpp[i]);
+        /*endfor*/
+        dp += 40;
+        dpp += 40;
+    }
+    /*endfor*/
+    memcpy ((char *) s->dp0,
+            (char *) (s->dp0 + GSM0610_FRAME_LEN),
+            120*sizeof(*s->dp0));
+}
+/*- End of function --------------------------------------------------------*/
+
+gsm0610_state_t *gsm0610_init(gsm0610_state_t *s, int packing)
+{
+    if (s == NULL)
+    {
+        s = (gsm0610_state_t *) malloc(sizeof (gsm0610_state_t));
+        if (s == NULL)
+            return  NULL;
+        /*endif*/
+    }
+    /*endif*/
+    memset((char *) s, '\0', sizeof (gsm0610_state_t));
+    s->nrp = 40;
+    s->packing = packing;
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+int gsm0610_release(gsm0610_state_t *s)
+{
+    if (s)
+        free(s);
+    /*endif*/
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+int gsm0610_pack_none(uint8_t c[], gsm0610_frame_t *s)
+{
+    int i;
+    int j;
+    int k;
+    
+    i = 0;
+    for (j = 0;  j < 8;  j++)
+        c[i++] = (uint8_t) s->LARc[j];
+    for (j = 0;  j < 4;  j++)
+    {
+        c[i++] = (uint8_t) s->Nc[j];
+        c[i++] = (uint8_t) s->bc[j];
+        c[i++] = (uint8_t) s->Mc[j];
+        c[i++] = (uint8_t) s->xmaxc[j];
+        for (k = 0;  k < 13;  k++)
+            c[i++] = (uint8_t) s->xMc[j][k];
+    }
+    return 76;
+}
+/*- End of function --------------------------------------------------------*/
+
+int gsm0610_pack_wav49(uint8_t code[], gsm0610_frame_t *s, int half)
+{
+    int i;
+    int j;
+    uint8_t *c;
+    bitstream_state_t bs;
+
+    c = code;
+    if (half)
+        bitstream_init(&bs);
+    bitstream_put(&bs, &c, s->LARc[0], 6);
+    bitstream_put(&bs, &c, s->LARc[1], 6);
+    bitstream_put(&bs, &c, s->LARc[2], 5);
+    bitstream_put(&bs, &c, s->LARc[3], 5);
+    bitstream_put(&bs, &c, s->LARc[4], 4);
+    bitstream_put(&bs, &c, s->LARc[5], 4);
+    bitstream_put(&bs, &c, s->LARc[6], 3);
+    bitstream_put(&bs, &c, s->LARc[7], 3);
+    for (i = 0;  i < 4;  i++)
+    {
+        bitstream_put(&bs, &c, s->Nc[i], 7);
+        bitstream_put(&bs, &c, s->bc[i], 2);
+        bitstream_put(&bs, &c, s->Mc[i], 2);
+        bitstream_put(&bs, &c, s->xmaxc[i], 6);
+        for (j = 0;  j < 13;  j++)
+            bitstream_put(&bs, &c, s->xMc[i][j], 3);
+    }
+    return (half)  ?  32  :  33;
+}
+/*- End of function --------------------------------------------------------*/
+
+int gsm0610_pack_voip(uint8_t code[], gsm0610_frame_t *s)
+{
+    int i;
+    int j;
+    uint8_t *c;
+    bitstream_state_t bs;
+
+    c = code;
+    bitstream_init(&bs);
+    bitstream_put2(&bs, &c, GSM0610_MAGIC, 4);
+    bitstream_put2(&bs, &c, s->LARc[0], 6);
+    bitstream_put2(&bs, &c, s->LARc[1], 6);
+    bitstream_put2(&bs, &c, s->LARc[2], 5);
+    bitstream_put2(&bs, &c, s->LARc[3], 5);
+    bitstream_put2(&bs, &c, s->LARc[4], 4);
+    bitstream_put2(&bs, &c, s->LARc[5], 4);
+    bitstream_put2(&bs, &c, s->LARc[6], 3);
+    bitstream_put2(&bs, &c, s->LARc[7], 3);
+    for (i = 0;  i < 4;  i++)
+    {
+        bitstream_put2(&bs, &c, s->Nc[i], 7);
+        bitstream_put2(&bs, &c, s->bc[i], 2);
+        bitstream_put2(&bs, &c, s->Mc[i], 2);
+        bitstream_put2(&bs, &c, s->xmaxc[i], 6);
+        for (j = 0;  j < 13;  j++)
+            bitstream_put2(&bs, &c, s->xMc[i][j], 3);
+    }
+    return 33;
+}
+/*- End of function --------------------------------------------------------*/
+
+int gsm0610_encode(gsm0610_state_t *s, uint8_t code[], const int16_t amp[], int quant)
+{
+    gsm0610_frame_t frame;
+    uint8_t *c;
+    int i;
+
+    c = code;
+    if (s->packing == GSM0610_PACKING_WAV49)
+        quant <<= 1;
+    for (i = 0;  i < quant;  i++)
+    {
+        encode_a_frame(s, &amp[i*GSM0610_FRAME_LEN], &frame);
+        /*  variable    size
+
+            LARc[0]     6
+            LARc[1]     6
+            LARc[2]     5
+            LARc[3]     5
+            LARc[4]     4
+            LARc[5]     4
+            LARc[6]     3
+            LARc[7]     3
+    
+            Nc[0]       7
+            bc[0]       2
+            Mc[0]       2
+            xmaxc[0]    6
+            xMc[0]      3
+            xMc[1]      3
+            xMc[2]      3
+            xMc[3]      3
+            xMc[4]      3
+            xMc[5]      3
+            xMc[6]      3
+            xMc[7]      3
+            xMc[8]      3
+            xMc[9]      3
+            xMc[10]     3
+            xMc[11]     3
+            xMc[12]     3
+
+            Nc[1]       7
+            bc[1]       2
+            Mc[1]       2
+            xmaxc[1]    6
+            xMc[13]     3
+            xMc[14]     3
+            xMc[15]     3
+            xMc[16]     3
+            xMc[17]     3
+            xMc[18]     3
+            xMc[19]     3
+            xMc[20]     3
+            xMc[21]     3
+            xMc[22]     3
+            xMc[23]     3
+            xMc[24]     3
+            xMc[25]     3
+
+            Nc[2]       7
+            bc[2]       2
+            Mc[2]       2
+            xmaxc[2]    6
+            xMc[26]     3
+            xMc[27]     3
+            xMc[28]     3
+            xMc[29]     3
+            xMc[30]     3
+            xMc[31]     3
+            xMc[32]     3
+            xMc[33]     3
+            xMc[34]     3
+            xMc[35]     3
+            xMc[36]     3
+            xMc[37]     3
+            xMc[38]     3
+
+            Nc[3]       7
+            bc[3]       2
+            Mc[3]       2
+            xmaxc[3]    6
+            xMc[39]     3
+            xMc[40]     3
+            xMc[41]     3
+            xMc[42]     3
+            xMc[43]     3
+            xMc[44]     3
+            xMc[45]     3
+            xMc[46]     3
+            xMc[47]     3
+            xMc[48]     3
+            xMc[49]     3
+            xMc[50]     3
+            xMc[51]     3
+        */
+
+        switch (s->packing)
+        {
+        case GSM0610_PACKING_NONE:
+            c += gsm0610_pack_none(c, &frame);
+            break;
+        case GSM0610_PACKING_WAV49:
+            s->frame_index = !s->frame_index;
+            c += gsm0610_pack_wav49(c, &frame, s->frame_index);
+            break;
+        case GSM0610_PACKING_VOIP:
+            c += gsm0610_pack_voip(c, &frame);
+            break;
+        }
+        /*endswitch*/
+    }
+    /*endwhile*/
+    return (int) (c - code);
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/

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