diff spandsp-0.0.6pre17/src/awgn.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/awgn.c	Fri Jun 25 15:50:58 2010 +0200
@@ -0,0 +1,180 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * awgn.c - An additive Gaussian white noise generator
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2001 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.
+ *
+ * $Id: awgn.c,v 1.22 2009/02/10 13:06:46 steveu Exp $
+ */
+
+/*! \file */
+
+/* This code is based on some demonstration code in a research
+   paper somewhere. I can't track down where I got the original from,
+   so that due recognition can be given. The original had no explicit
+   copyright notice, and I hope nobody objects to its use here.
+   
+   Having a reasonable Gaussian noise generator is pretty important for
+   telephony testing (in fact, pretty much any DSP testing), and this
+   one seems to have served me OK. Since the generation of Gaussian
+   noise is only for test purposes, and not a core system component,
+   I don't intend to worry excessively about copyright issues, unless
+   someone worries me.
+        
+   The non-core nature of this code also explains why it is unlikely
+   to ever be optimised. */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <inttypes.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/fast_convert.h"
+#include "spandsp/saturated.h"
+#include "spandsp/awgn.h"
+
+#include "spandsp/private/awgn.h"
+
+/* Gaussian noise generator constants */
+#define M1 259200
+#define IA1 7141
+#define IC1 54773
+#define RM1 (1.0/M1)
+#define M2 134456
+#define IA2 8121
+#define IC2 28411
+#define RM2 (1.0/M2)
+#define M3 243000
+#define IA3 4561
+#define IC3 51349
+
+static double ran1(awgn_state_t *s)
+{
+    double temp;
+    int j;
+
+    s->ix1 = (IA1*s->ix1 + IC1)%M1;
+    s->ix2 = (IA2*s->ix2 + IC2)%M2;
+    s->ix3 = (IA3*s->ix3 + IC3)%M3;
+    j = 1 + ((97*s->ix3)/M3);
+    if (j > 97  ||  j < 1)
+    {
+        /* Error */
+        return -1;
+    }
+    temp = s->r[j];
+    s->r[j] = (s->ix1 + s->ix2*RM2)*RM1;
+    return temp;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(awgn_state_t *) awgn_init_dbov(awgn_state_t *s, int idum, float level)
+{
+    int j;
+
+    if (s == NULL)
+    {
+        if ((s = (awgn_state_t *) malloc(sizeof(*s))) == NULL)
+            return  NULL;
+    }
+    if (idum < 0)
+        idum = -idum;
+
+    s->rms = pow(10.0, level/20.0)*32768.0;
+
+    s->ix1 = (IC1 + idum)%M1;
+    s->ix1 = (IA1*s->ix1 + IC1)%M1;
+    s->ix2 = s->ix1%M2;
+    s->ix1 = (IA1*s->ix1 + IC1)%M1;
+    s->ix3 = s->ix1%M3;
+    s->r[0] = 0.0;
+    for (j = 1;  j <= 97;  j++)
+    {
+        s->ix1 = (IA1*s->ix1 + IC1)%M1;
+        s->ix2 = (IA2*s->ix2 + IC2)%M2;
+        s->r[j] = (s->ix1 + s->ix2*RM2)*RM1;
+    }
+    s->gset = 0.0;
+    s->iset = 0;
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(awgn_state_t *) awgn_init_dbm0(awgn_state_t *s, int idum, float level)
+{
+    return awgn_init_dbov(s, idum, level - DBM0_MAX_POWER);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) awgn_release(awgn_state_t *s)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) awgn_free(awgn_state_t *s)
+{
+    free(s);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int16_t) awgn(awgn_state_t *s)
+{
+    double fac;
+    double r;
+    double v1;
+    double v2;
+    double amp;
+
+    if (s->iset == 0)
+    {
+        do
+        {
+            v1 = 2.0*ran1(s) - 1.0;
+            v2 = 2.0*ran1(s) - 1.0;
+            r = v1*v1 + v2*v2;
+        }
+        while (r >= 1.0);
+        fac = sqrt(-2.0*log(r)/r);
+        s->gset = v1*fac;
+        s->iset = 1;
+        amp = v2*fac*s->rms;
+    }
+    else
+    {
+        s->iset = 0;
+        amp = s->gset*s->rms;
+    }
+    return fsaturate(amp);
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/

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