[Freeswitch-svn] [commit] r9345 - freeswitch/trunk/src/mod/applications/mod_stress

Freeswitch SVN anthm at freeswitch.org
Thu Aug 21 16:58:43 EDT 2008


Author: anthm
Date: Thu Aug 21 16:58:43 2008
New Revision: 9345

Added:
   freeswitch/trunk/src/mod/applications/mod_stress/
   freeswitch/trunk/src/mod/applications/mod_stress/FFTReal.cpp
   freeswitch/trunk/src/mod/applications/mod_stress/FFTReal.h
   freeswitch/trunk/src/mod/applications/mod_stress/Makefile
   freeswitch/trunk/src/mod/applications/mod_stress/mod_stress.cpp

Log:
add mod_stress (needs work)

Added: freeswitch/trunk/src/mod/applications/mod_stress/FFTReal.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_stress/FFTReal.cpp	Thu Aug 21 16:58:43 2008
@@ -0,0 +1,615 @@
+/*****************************************************************************
+*                                                                            *
+*       DIGITAL SIGNAL PROCESSING TOOLS                                      *
+*       Version 1.03, 2001/06/15                                             *
+*       (c) 1999 - Laurent de Soras                                          *
+*                                                                            *
+*       FFTReal.cpp                                                          *
+*       Fourier transformation of real number arrays.                        *
+*       Portable ISO C++                                                     *
+*                                                                            *
+* Tab = 3                                                                    *
+*****************************************************************************/
+
+
+
+/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
+
+#include	"FFTReal.h"
+
+#include	<cassert>
+#include	<cmath>
+
+
+
+#if defined (_MSC_VER)
+#pragma pack (push, 8)
+#endif	// _MSC_VER
+
+
+
+/*\\\ PUBLIC MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
+
+
+
+/*==========================================================================*/
+/*      Name: Constructor                                                   */
+/*      Input parameters:                                                   */
+/*        - length: length of the array on which we want to do a FFT.       */
+/*                  Range: power of 2 only, > 0.                            */
+/*      Throws: std::bad_alloc, anything                                    */
+/*==========================================================================*/
+
+FFTReal::FFTReal (const long length)
+:	_length (length)
+,	_nbr_bits (int (floor (log (length) / log (2) + 0.5)))
+,	_bit_rev_lut (int (floor (log (length) / log (2) + 0.5)))
+,	_trigo_lut (int (floor (log (length) / log (2) + 0.5)))
+,	_sqrt2_2 (flt_t (sqrt (2) * 0.5))
+{
+	assert ((1L << _nbr_bits) == length);
+
+	_buffer_ptr = 0;
+	if (_nbr_bits > 2)
+	{
+		_buffer_ptr = new flt_t [_length];
+	}
+}
+
+
+
+/*==========================================================================*/
+/*      Name: Destructor                                                    */
+/*==========================================================================*/
+
+FFTReal::~FFTReal (void)
+{
+	delete [] _buffer_ptr;
+	_buffer_ptr = 0;
+}
+
+
+
+/*==========================================================================*/
+/*      Name: do_fft                                                        */
+/*      Description: Compute the FFT of the array.                          */
+/*      Input parameters:                                                   */
+/*        - x: pointer on the source array (time).                          */
+/*      Output parameters:                                                  */
+/*        - f: pointer on the destination array (frequencies).              */
+/*             f [0...length(x)/2] = real values,                           */
+/*             f [length(x)/2+1...length(x)-1] = imaginary values of        */
+/*               coefficents 1...length(x)/2-1.                             */
+/*      Throws: Nothing                                                     */
+/*==========================================================================*/
+
+void	FFTReal::do_fft (flt_t f [], const flt_t x []) const
+{
+
+/*______________________________________________
+ *
+ * General case
+ *______________________________________________
+ */
+
+	if (_nbr_bits > 2)
+	{
+		flt_t *			sf;
+		flt_t *			df;
+
+		if (_nbr_bits & 1)
+		{
+			df = _buffer_ptr;
+			sf = f;
+		}
+		else
+		{
+			df = f;
+			sf = _buffer_ptr;
+		}
+
+		/* Do the transformation in several pass */
+		{
+			int		pass;
+			long		nbr_coef;
+			long		h_nbr_coef;
+			long		d_nbr_coef;
+			long		coef_index;
+
+			/* First and second pass at once */
+			{
+				const long * const	bit_rev_lut_ptr = _bit_rev_lut.get_ptr ();
+				coef_index = 0;
+				do
+				{
+					const long		rev_index_0 = bit_rev_lut_ptr [coef_index];
+					const long		rev_index_1 = bit_rev_lut_ptr [coef_index + 1];
+					const long		rev_index_2 = bit_rev_lut_ptr [coef_index + 2];
+					const long		rev_index_3 = bit_rev_lut_ptr [coef_index + 3];
+
+					flt_t	* const	df2 = df + coef_index;
+					df2 [1] = x [rev_index_0] - x [rev_index_1];
+					df2 [3] = x [rev_index_2] - x [rev_index_3];
+
+					const flt_t		sf_0 = x [rev_index_0] + x [rev_index_1];
+					const flt_t		sf_2 = x [rev_index_2] + x [rev_index_3];
+
+					df2 [0] = sf_0 + sf_2;
+					df2 [2] = sf_0 - sf_2;
+					
+					coef_index += 4;
+				}
+				while (coef_index < _length);
+			}
+
+			/* Third pass */
+			{
+				coef_index = 0;
+				const flt_t		sqrt2_2 = _sqrt2_2;
+				do
+				{
+					flt_t				v;
+
+					sf [coef_index] = df [coef_index] + df [coef_index + 4];
+					sf [coef_index + 4] = df [coef_index] - df [coef_index + 4];
+					sf [coef_index + 2] = df [coef_index + 2];
+					sf [coef_index + 6] = df [coef_index + 6];
+
+					v = (df [coef_index + 5] - df [coef_index + 7]) * sqrt2_2;
+					sf [coef_index + 1] = df [coef_index + 1] + v;
+					sf [coef_index + 3] = df [coef_index + 1] - v;
+
+					v = (df [coef_index + 5] + df [coef_index + 7]) * sqrt2_2;
+					sf [coef_index + 5] = v + df [coef_index + 3];
+					sf [coef_index + 7] = v - df [coef_index + 3];
+
+					coef_index += 8;
+				}
+				while (coef_index < _length);
+			}
+
+			/* Next pass */
+			for (pass = 3; pass < _nbr_bits; ++pass)
+			{
+				coef_index = 0;
+				nbr_coef = 1 << pass;
+				h_nbr_coef = nbr_coef >> 1;
+				d_nbr_coef = nbr_coef << 1;
+				const flt_t	* const	cos_ptr = _trigo_lut.get_ptr (pass);
+				do
+				{
+					long				i;
+					const flt_t	*	const sf1r = sf + coef_index;
+					const flt_t	*	const sf2r = sf1r + nbr_coef;
+					flt_t *			const dfr = df + coef_index;
+					flt_t *			const dfi = dfr + nbr_coef;
+
+					/* Extreme coefficients are always real */
+					dfr [0] = sf1r [0] + sf2r [0];
+					dfi [0] = sf1r [0] - sf2r [0];	// dfr [nbr_coef] =
+					dfr [h_nbr_coef] = sf1r [h_nbr_coef];
+					dfi [h_nbr_coef] = sf2r [h_nbr_coef];
+
+					/* Others are conjugate complex numbers */
+					const flt_t	* const	sf1i = sf1r + h_nbr_coef;
+					const flt_t	* const	sf2i = sf1i + nbr_coef;
+					for (i = 1; i < h_nbr_coef; ++ i)
+					{
+						const flt_t		c = cos_ptr [i];					// cos (i*PI/nbr_coef);
+						const flt_t		s = cos_ptr [h_nbr_coef - i];	// sin (i*PI/nbr_coef);
+						flt_t				v;
+
+						v = sf2r [i] * c - sf2i [i] * s;
+						dfr [i] = sf1r [i] + v;
+						dfi [-i] = sf1r [i] - v;	// dfr [nbr_coef - i] =
+
+						v = sf2r [i] * s + sf2i [i] * c;
+						dfi [i] = v + sf1i [i];
+						dfi [nbr_coef - i] = v - sf1i [i];
+					}
+
+					coef_index += d_nbr_coef;
+				}
+				while (coef_index < _length);
+
+				/* Prepare to the next pass */
+				{
+					flt_t	* const		temp_ptr = df;
+					df = sf;
+					sf = temp_ptr;
+				}
+			}
+		}
+	}
+
+/*______________________________________________
+ *
+ * Special cases
+ *______________________________________________
+ */
+
+	/* 4-point FFT */
+	else if (_nbr_bits == 2)
+	{
+		f [1] = x [0] - x [2];
+		f [3] = x [1] - x [3];
+
+		const flt_t			b_0 = x [0] + x [2];
+		const flt_t			b_2 = x [1] + x [3];
+		
+		f [0] = b_0 + b_2;
+		f [2] = b_0 - b_2;
+	}
+
+	/* 2-point FFT */
+	else if (_nbr_bits == 1)
+	{
+		f [0] = x [0] + x [1];
+		f [1] = x [0] - x [1];
+	}
+
+	/* 1-point FFT */
+	else
+	{
+		f [0] = x [0];
+	}
+}
+
+
+
+/*==========================================================================*/
+/*      Name: do_ifft                                                       */
+/*      Description: Compute the inverse FFT of the array. Notice that      */
+/*                   IFFT (FFT (x)) = x * length (x). Data must be          */
+/*                   post-scaled.                                           */
+/*      Input parameters:                                                   */
+/*        - f: pointer on the source array (frequencies).                   */
+/*             f [0...length(x)/2] = real values,                           */
+/*             f [length(x)/2+1...length(x)] = imaginary values of          */
+/*               coefficents 1...length(x)-1.                               */
+/*      Output parameters:                                                  */
+/*        - x: pointer on the destination array (time).                     */
+/*      Throws: Nothing                                                     */
+/*==========================================================================*/
+
+void	FFTReal::do_ifft (const flt_t f [], flt_t x []) const
+{
+
+/*______________________________________________
+ *
+ * General case
+ *______________________________________________
+ */
+
+	if (_nbr_bits > 2)
+	{
+		flt_t *			sf = const_cast <flt_t *> (f);
+		flt_t *			df;
+		flt_t *			df_temp;
+
+		if (_nbr_bits & 1)
+		{
+			df = _buffer_ptr;
+			df_temp = x;
+		}
+		else
+		{
+			df = x;
+			df_temp = _buffer_ptr;
+		}
+
+		/* Do the transformation in several pass */
+		{
+			int			pass;
+			long			nbr_coef;
+			long			h_nbr_coef;
+			long			d_nbr_coef;
+			long			coef_index;
+
+			/* First pass */
+			for (pass = _nbr_bits - 1; pass >= 3; --pass)
+			{
+				coef_index = 0;
+				nbr_coef = 1 << pass;
+				h_nbr_coef = nbr_coef >> 1;
+				d_nbr_coef = nbr_coef << 1;
+				const flt_t	*const cos_ptr = _trigo_lut.get_ptr (pass);
+				do
+				{
+					long				i;
+					const flt_t	*	const sfr = sf + coef_index;
+					const flt_t	*	const sfi = sfr + nbr_coef;
+					flt_t *			const df1r = df + coef_index;
+					flt_t *			const df2r = df1r + nbr_coef;
+
+					/* Extreme coefficients are always real */
+					df1r [0] = sfr [0] + sfi [0];		// + sfr [nbr_coef]
+					df2r [0] = sfr [0] - sfi [0];		// - sfr [nbr_coef]
+					df1r [h_nbr_coef] = sfr [h_nbr_coef] * 2;
+					df2r [h_nbr_coef] = sfi [h_nbr_coef] * 2;
+
+					/* Others are conjugate complex numbers */
+					flt_t * const	df1i = df1r + h_nbr_coef;
+					flt_t * const	df2i = df1i + nbr_coef;
+					for (i = 1; i < h_nbr_coef; ++ i)
+					{
+						df1r [i] = sfr [i] + sfi [-i];		// + sfr [nbr_coef - i]
+						df1i [i] = sfi [i] - sfi [nbr_coef - i];
+
+						const flt_t		c = cos_ptr [i];					// cos (i*PI/nbr_coef);
+						const flt_t		s = cos_ptr [h_nbr_coef - i];	// sin (i*PI/nbr_coef);
+						const flt_t		vr = sfr [i] - sfi [-i];		// - sfr [nbr_coef - i]
+						const flt_t		vi = sfi [i] + sfi [nbr_coef - i];
+
+						df2r [i] = vr * c + vi * s;
+						df2i [i] = vi * c - vr * s;
+					}
+
+					coef_index += d_nbr_coef;
+				}
+				while (coef_index < _length);
+
+				/* Prepare to the next pass */
+				if (pass < _nbr_bits - 1)
+				{
+					flt_t	* const	temp_ptr = df;
+					df = sf;
+					sf = temp_ptr;
+				}
+				else
+				{
+					sf = df;
+					df = df_temp;
+				}
+			}
+
+			/* Antepenultimate pass */
+			{
+				const flt_t		sqrt2_2 = _sqrt2_2;
+				coef_index = 0;
+				do
+				{
+					df [coef_index] = sf [coef_index] + sf [coef_index + 4];
+					df [coef_index + 4] = sf [coef_index] - sf [coef_index + 4];
+					df [coef_index + 2] = sf [coef_index + 2] * 2;
+					df [coef_index + 6] = sf [coef_index + 6] * 2;
+
+					df [coef_index + 1] = sf [coef_index + 1] + sf [coef_index + 3];
+					df [coef_index + 3] = sf [coef_index + 5] - sf [coef_index + 7];
+
+					const flt_t		vr = sf [coef_index + 1] - sf [coef_index + 3];
+					const flt_t		vi = sf [coef_index + 5] + sf [coef_index + 7];
+
+					df [coef_index + 5] = (vr + vi) * sqrt2_2;
+					df [coef_index + 7] = (vi - vr) * sqrt2_2;
+
+					coef_index += 8;
+				}
+				while (coef_index < _length);
+			}
+
+			/* Penultimate and last pass at once */
+			{
+				coef_index = 0;
+				const long *	bit_rev_lut_ptr = _bit_rev_lut.get_ptr ();
+				const flt_t	*	sf2 = df;
+				do
+				{
+					{
+						const flt_t		b_0 = sf2 [0] + sf2 [2];
+						const flt_t		b_2 = sf2 [0] - sf2 [2];
+						const flt_t		b_1 = sf2 [1] * 2;
+						const flt_t		b_3 = sf2 [3] * 2;
+
+						x [bit_rev_lut_ptr [0]] = b_0 + b_1;
+						x [bit_rev_lut_ptr [1]] = b_0 - b_1;
+						x [bit_rev_lut_ptr [2]] = b_2 + b_3;
+						x [bit_rev_lut_ptr [3]] = b_2 - b_3;
+					}
+					{
+						const flt_t		b_0 = sf2 [4] + sf2 [6];
+						const flt_t		b_2 = sf2 [4] - sf2 [6];
+						const flt_t		b_1 = sf2 [5] * 2;
+						const flt_t		b_3 = sf2 [7] * 2;
+
+						x [bit_rev_lut_ptr [4]] = b_0 + b_1;
+						x [bit_rev_lut_ptr [5]] = b_0 - b_1;
+						x [bit_rev_lut_ptr [6]] = b_2 + b_3;
+						x [bit_rev_lut_ptr [7]] = b_2 - b_3;
+					}
+
+					sf2 += 8;
+					coef_index += 8;
+					bit_rev_lut_ptr += 8;
+				}
+				while (coef_index < _length);
+			}
+		}
+	}
+
+/*______________________________________________
+ *
+ * Special cases
+ *______________________________________________
+ */
+
+	/* 4-point IFFT */
+	else if (_nbr_bits == 2)
+	{
+		const flt_t		b_0 = f [0] + f [2];
+		const flt_t		b_2 = f [0] - f [2];
+
+		x [0] = b_0 + f [1] * 2;
+		x [2] = b_0 - f [1] * 2;
+		x [1] = b_2 + f [3] * 2;
+		x [3] = b_2 - f [3] * 2;
+	}
+
+	/* 2-point IFFT */
+	else if (_nbr_bits == 1)
+	{
+		x [0] = f [0] + f [1];
+		x [1] = f [0] - f [1];
+	}
+
+	/* 1-point IFFT */
+	else
+	{
+		x [0] = f [0];
+	}
+}
+
+
+
+/*==========================================================================*/
+/*      Name: rescale                                                       */
+/*      Description: Scale an array by divide each element by its length.   */
+/*                   This function should be called after FFT + IFFT.       */
+/*      Input/Output parameters:                                            */
+/*        - x: pointer on array to rescale (time or frequency).             */
+/*      Throws: Nothing                                                     */
+/*==========================================================================*/
+
+void	FFTReal::rescale (flt_t x []) const
+{
+	const flt_t		mul = flt_t (1.0 / _length);
+	long				i = _length - 1;
+
+	do
+	{
+		x [i] *= mul;
+		--i;
+	}
+	while (i >= 0);
+}
+
+
+
+/*\\\ NESTED CLASS MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
+
+
+
+/*==========================================================================*/
+/*      Name: Constructor                                                   */
+/*      Input parameters:                                                   */
+/*        - nbr_bits: number of bits of the array on which we want to do a  */
+/*                    FFT. Range: > 0                                       */
+/*      Throws: std::bad_alloc                                              */
+/*==========================================================================*/
+
+FFTReal::BitReversedLUT::BitReversedLUT (const int nbr_bits)
+{
+	long				length;
+	long				cnt;
+	long				br_index;
+	long				bit;
+
+	length = 1L << nbr_bits;
+	_ptr = new long [length];
+
+	br_index = 0;
+	_ptr [0] = 0;
+	for (cnt = 1; cnt < length; ++cnt)
+	{
+		/* ++br_index (bit reversed) */
+		bit = length >> 1;
+		while (((br_index ^= bit) & bit) == 0)
+		{
+			bit >>= 1;
+		}
+
+		_ptr [cnt] = br_index;
+	}
+}
+
+
+
+/*==========================================================================*/
+/*      Name: Destructor                                                    */
+/*==========================================================================*/
+
+FFTReal::BitReversedLUT::~BitReversedLUT (void)
+{
+	delete [] _ptr;
+	_ptr = 0;
+}
+
+
+
+/*==========================================================================*/
+/*      Name: Constructor                                                   */
+/*      Input parameters:                                                   */
+/*        - nbr_bits: number of bits of the array on which we want to do a  */
+/*                    FFT. Range: > 0                                       */
+/*      Throws: std::bad_alloc, anything                                    */
+/*==========================================================================*/
+
+FFTReal::TrigoLUT::TrigoLUT (const int nbr_bits)
+{
+	long		total_len;
+
+	_ptr = 0;
+	if (nbr_bits > 3)
+	{
+		total_len = (1L << (nbr_bits - 1)) - 4;
+		_ptr = new flt_t [total_len];
+
+		const double	PI = atan (1) * 4;
+		for (int level = 3; level < nbr_bits; ++level)
+		{
+			const long		level_len = 1L << (level - 1);
+			flt_t	* const	level_ptr = const_cast<flt_t *> (get_ptr (level));
+			const double	mul = PI / (level_len << 1);
+
+			for (long i = 0; i < level_len; ++ i)
+			{
+				level_ptr [i] = (flt_t) cos (i * mul);
+			}
+		}
+	}
+}
+
+
+
+/*==========================================================================*/
+/*      Name: Destructor                                                    */
+/*==========================================================================*/
+
+FFTReal::TrigoLUT::~TrigoLUT (void)
+{
+	delete [] _ptr;
+	_ptr = 0;
+}
+
+
+
+#if defined (_MSC_VER)
+#pragma pack (pop)
+#endif	// _MSC_VER
+
+
+
+/*****************************************************************************
+
+	LEGAL
+
+	Source code may be freely used for any purpose, including commercial
+	applications. Programs must display in their "About" dialog-box (or
+	documentation) a text telling they use these routines by Laurent de Soras.
+	Modified source code can be distributed, but modifications must be clearly
+	indicated.
+
+	CONTACT
+
+	Laurent de Soras
+	92 avenue Albert 1er
+	92500 Rueil-Malmaison
+	France
+
+	ldesoras at club-internet.fr
+
+*****************************************************************************/
+
+
+
+/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

Added: freeswitch/trunk/src/mod/applications/mod_stress/FFTReal.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_stress/FFTReal.h	Thu Aug 21 16:58:43 2008
@@ -0,0 +1,139 @@
+/*****************************************************************************
+*                                                                            *
+*       DIGITAL SIGNAL PROCESSING TOOLS                                      *
+*       Version 1.03, 2001/06/15                                             *
+*       (c) 1999 - Laurent de Soras                                          *
+*                                                                            *
+*       FFTReal.h                                                            *
+*       Fourier transformation of real number arrays.                        *
+*       Portable ISO C++                                                     *
+*                                                                            *
+* Tab = 3                                                                    *
+*****************************************************************************/
+
+
+
+#if defined (FFTReal_CURRENT_HEADER)
+	#error Recursive inclusion of FFTReal header file.
+#endif
+#define	FFTReal_CURRENT_HEADER
+
+#if ! defined (FFTReal_HEADER_INCLUDED)
+#define	FFTReal_HEADER_INCLUDED
+
+
+
+#if defined (_MSC_VER)
+#pragma pack (push, 8)
+#endif	// _MSC_VER
+
+
+
+class	FFTReal
+{
+
+/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
+
+public:
+
+	/* Change this typedef to use a different floating point type in your FFTs
+		(i.e. float, double or long double). */
+	typedef float	flt_t;
+
+	explicit			FFTReal (const long length);
+						~FFTReal ();
+	void				do_fft (flt_t f [], const flt_t x []) const;
+	void				do_ifft (const flt_t f [], flt_t x []) const;
+	void				rescale (flt_t x []) const;
+
+
+
+/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
+
+private:
+
+	/* Bit-reversed look-up table nested class */
+	class BitReversedLUT
+	{
+	public:
+		explicit			BitReversedLUT (const int nbr_bits);
+							~BitReversedLUT ();
+		const long *	get_ptr () const
+		{
+			return (_ptr);
+		}
+	private:
+		long *			_ptr;
+	};
+
+	/* Trigonometric look-up table nested class */
+	class	TrigoLUT
+	{
+	public:
+		explicit			TrigoLUT (const int nbr_bits);
+							~TrigoLUT ();
+		const flt_t	*	get_ptr (const int level) const
+		{
+			return (_ptr + (1L << (level - 1)) - 4);
+		};
+	private:
+		flt_t	*			_ptr;
+	};
+
+	const BitReversedLUT	_bit_rev_lut;
+	const TrigoLUT	_trigo_lut;
+	const flt_t		_sqrt2_2;
+	const long		_length;
+	const int		_nbr_bits;
+	flt_t *			_buffer_ptr;
+
+
+
+/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
+
+private:
+
+						FFTReal (const FFTReal &other);
+	const FFTReal&	operator = (const FFTReal &other);
+	int				operator == (const FFTReal &other);
+	int				operator != (const FFTReal &other);
+};
+
+
+
+#if defined (_MSC_VER)
+#pragma pack (pop)
+#endif	// _MSC_VER
+
+
+
+#endif	// FFTReal_HEADER_INCLUDED
+
+#undef FFTReal_CURRENT_HEADER
+
+
+
+/*****************************************************************************
+
+	LEGAL
+
+	Source code may be freely used for any purpose, including commercial
+	applications. Programs must display in their "About" dialog-box (or
+	documentation) a text telling they use these routines by Laurent de Soras.
+	Modified source code can be distributed, but modifications must be clearly
+	indicated.
+
+	CONTACT
+
+	Laurent de Soras
+	92 avenue Albert 1er
+	92500 Rueil-Malmaison
+	France
+
+	ldesoras at club-internet.fr
+
+*****************************************************************************/
+
+
+
+/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

Added: freeswitch/trunk/src/mod/applications/mod_stress/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_stress/Makefile	Thu Aug 21 16:58:43 2008
@@ -0,0 +1,3 @@
+BASE=../../../..
+LOCAL_OBJS=FFTReal.o
+include $(BASE)/build/modmake.rules

Added: freeswitch/trunk/src/mod/applications/mod_stress/mod_stress.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/applications/mod_stress/mod_stress.cpp	Thu Aug 21 16:58:43 2008
@@ -0,0 +1,266 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct at yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * mod_stress.cpp -- Detect Voice Stress
+ *
+ */
+
+#include <stdexcept>
+#include <stdio.h>
+#include "FFTReal.h"
+using namespace std;
+
+#include <switch.h>
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_stress_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_stress_shutdown);
+SWITCH_MODULE_DEFINITION(mod_stress, mod_stress_load, mod_stress_shutdown, NULL);
+
+struct stress_helper {
+	switch_core_session_t *session;
+	int read;
+	uint32_t frame_size;
+    FFTReal *fft;
+    float *data;
+    float *result;
+    float *pow_spectrum;
+    float bind;
+    int start;
+    int end;
+    float avg_tremor_pwr;
+    float avg_total_pwr;
+    float total_pwr;
+    float tremor_ratio;
+    float stress;
+    uint32_t rate;
+    switch_buffer_t *audio_buffer;
+    int16_t *audio;
+};
+
+static switch_bool_t stress_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
+{
+	struct stress_helper *sth = (struct stress_helper *) user_data;
+
+	switch (type) {
+	case SWITCH_ABC_TYPE_INIT:
+		{
+			switch_codec_t *read_codec = switch_core_session_get_read_codec(sth->session);
+
+            sth->rate = read_codec->implementation->actual_samples_per_second;
+
+            if (sth->rate == 8000) {
+                sth->frame_size = 8192;
+            } else if (sth->rate == 16000) {
+                sth->frame_size = 16384;
+            } else if (sth->rate == 32000) {
+                sth->frame_size = 32768;
+            } else {
+                return SWITCH_FALSE;
+            }
+            
+            sth->data = (float *) switch_core_session_alloc(sth->session, sizeof(*sth->data) * sth->frame_size);
+            sth->result = (float *) switch_core_session_alloc(sth->session, sizeof(*sth->result) * sth->frame_size);
+            sth->pow_spectrum = (float *) switch_core_session_alloc(sth->session, sizeof(*sth->pow_spectrum) * sth->frame_size);
+            sth->audio = (int16_t *) switch_core_session_alloc(sth->session, sizeof(*sth->audio) * sth->frame_size);
+            
+            sth->fft = new FFTReal (sth->frame_size);
+            switch_buffer_create_dynamic(&sth->audio_buffer, sth->frame_size, sth->frame_size * 3, 0);
+
+            sth->bind = (float) sth->rate / sth->frame_size;
+            sth->start = (int) (8.0 / sth->bind);
+            sth->end = (int) (14.0 / sth->bind);
+            
+		}
+		break;
+	case SWITCH_ABC_TYPE_CLOSE:
+		{
+            switch_buffer_destroy(&sth->audio_buffer);
+            delete sth->fft;
+		}
+		break;
+	case SWITCH_ABC_TYPE_READ:
+	case SWITCH_ABC_TYPE_WRITE:
+		break;
+	case SWITCH_ABC_TYPE_READ_REPLACE:
+	case SWITCH_ABC_TYPE_WRITE_REPLACE:
+		{
+			switch_frame_t *frame;
+            
+			if (sth->read) {
+				frame = switch_core_media_bug_get_read_replace_frame(bug);
+			} else {
+				frame = switch_core_media_bug_get_write_replace_frame(bug);
+			}
+
+            if (!switch_test_flag(frame, SFF_CNG)) {
+                switch_buffer_write(sth->audio_buffer, frame->data, frame->datalen);
+            }
+            
+            sth->stress = 0.0;
+
+            if (switch_buffer_inuse(sth->audio_buffer) >= sth->frame_size * sizeof(int16_t)) {
+                switch_size_t bytes;
+                uint32_t samples, i;
+                const float threshold = 1.5;
+
+                bytes = switch_buffer_read(sth->audio_buffer, sth->audio, sth->frame_size * sizeof(int16_t));
+                samples = bytes / sizeof(int16_t);
+                
+                switch_short_to_float(sth->audio, sth->data, samples);
+                sth->fft->do_fft(sth->result, sth->data);
+
+                for (i = 0; i < samples; ++i) {
+                    sth->pow_spectrum[i] = pow(fabs(sth->result[i]), 2) / (float) samples;
+                }
+
+                sth->avg_tremor_pwr = 0.0;
+                sth->avg_total_pwr = 0.0;
+                sth->total_pwr = 0.0;
+                
+                for (i = sth->start; i <= sth->end; ++i) {
+                    sth->avg_tremor_pwr += sth->pow_spectrum[i];
+                }
+                sth->avg_tremor_pwr /= ((sth->end - sth->start) + 1);
+
+                for (i = 0; i < samples; ++i) {
+                    sth->total_pwr += sth->pow_spectrum[i];
+                }
+                sth->avg_total_pwr = sth->total_pwr / samples;
+                
+                if (sth->total_pwr < threshold) {
+                    sth->tremor_ratio = 0.0;
+                } else {
+                    sth->tremor_ratio = sth->avg_tremor_pwr / sth->avg_total_pwr;
+                }
+
+                if (sth->total_pwr >= 1.0) {
+                    float d = pow(sth->tremor_ratio, 4);
+                    if (d > 0.0) {
+                        sth->stress = (10.0 / d) / 10000;
+                        if (sth->stress >= 20000.0) {
+                            sth->stress = 20000.0;
+                        }
+                    }
+                }
+            }
+
+            if (sth->stress) {
+                switch_event_t *event, *dup;
+                
+                if (switch_event_create(&event, SWITCH_EVENT_DETECTED_SPEECH) == SWITCH_STATUS_SUCCESS) {
+                    switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Speech-Type", "stress-level");
+                    switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Stress-Level", "%02f", sth->stress);
+                    if (switch_event_dup(&dup, event) == SWITCH_STATUS_SUCCESS) {
+                        switch_event_fire(&dup);
+                    }
+                    if (switch_core_session_queue_event(sth->session, &event) != SWITCH_STATUS_SUCCESS) {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Event queue failed!\n");
+                        switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
+                        switch_event_fire(&event);
+                    }
+                }
+            }
+		}
+	default:
+		break;
+	}
+
+	return SWITCH_TRUE;
+}
+
+SWITCH_STANDARD_APP(stress_start_function)
+{
+	switch_media_bug_t *bug;
+	switch_status_t status;
+	switch_channel_t *channel = switch_core_session_get_channel(session);
+	struct stress_helper *sth;
+	char *argv[6];
+	int argc;
+	char *lbuf = NULL;
+	int x = 0;
+
+	if ((bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_stress_"))) {
+		if (!switch_strlen_zero(data) && !strcasecmp(data, "stop")) {
+			switch_channel_set_private(channel, "_stress_", NULL);
+			switch_core_media_bug_remove(session, &bug);
+		} else {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n");
+		}
+		return;
+	}
+
+	sth = (struct stress_helper *) switch_core_session_alloc(session, sizeof(*sth));
+	assert(sth != NULL);
+
+
+	if (data && (lbuf = switch_core_session_strdup(session, data))
+		&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+        if (!strncasecmp(argv[x], "read", 4)) {
+            sth->read = 1;
+        }
+	}
+
+	sth->session = session;
+    
+	if ((status = switch_core_media_bug_add(session, stress_callback, sth, 0,
+											sth->read ? SMBF_READ_REPLACE : SMBF_WRITE_REPLACE, &bug)) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failure!\n");
+		return;
+	}
+
+	switch_channel_set_private(channel, "_stress_", bug);
+
+}
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_stress_load)
+{
+    switch_application_interface_t *app_interface;
+
+	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+	SWITCH_ADD_APP(app_interface, "stress", "Analyze the stream for voice stress", "Analyze the stream for voice stress", 
+                   stress_start_function, "[read|write|stop]", SAF_NONE);
+
+	/* indicate that the module should continue to be loaded */
+	return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_stress_shutdown)
+{
+    return SWITCH_STATUS_UNLOAD;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:nil
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */



More information about the Freeswitch-svn mailing list