]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add mod_stress (needs work)
authorAnthony Minessale <anthony.minessale@gmail.com>
Thu, 21 Aug 2008 20:58:43 +0000 (20:58 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Thu, 21 Aug 2008 20:58:43 +0000 (20:58 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9345 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/applications/mod_stress/FFTReal.cpp [new file with mode: 0644]
src/mod/applications/mod_stress/FFTReal.h [new file with mode: 0644]
src/mod/applications/mod_stress/Makefile [new file with mode: 0644]
src/mod/applications/mod_stress/mod_stress.cpp [new file with mode: 0644]

diff --git a/src/mod/applications/mod_stress/FFTReal.cpp b/src/mod/applications/mod_stress/FFTReal.cpp
new file mode 100644 (file)
index 0000000..e1a77b4
--- /dev/null
@@ -0,0 +1,615 @@
+/*****************************************************************************\r
+*                                                                            *\r
+*       DIGITAL SIGNAL PROCESSING TOOLS                                      *\r
+*       Version 1.03, 2001/06/15                                             *\r
+*       (c) 1999 - Laurent de Soras                                          *\r
+*                                                                            *\r
+*       FFTReal.cpp                                                          *\r
+*       Fourier transformation of real number arrays.                        *\r
+*       Portable ISO C++                                                     *\r
+*                                                                            *\r
+* Tab = 3                                                                    *\r
+*****************************************************************************/\r
+\r
+\r
+\r
+/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/\r
+\r
+#include       "FFTReal.h"\r
+\r
+#include       <cassert>\r
+#include       <cmath>\r
+\r
+\r
+\r
+#if defined (_MSC_VER)\r
+#pragma pack (push, 8)\r
+#endif // _MSC_VER\r
+\r
+\r
+\r
+/*\\\ PUBLIC MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/\r
+\r
+\r
+\r
+/*==========================================================================*/\r
+/*      Name: Constructor                                                   */\r
+/*      Input parameters:                                                   */\r
+/*        - length: length of the array on which we want to do a FFT.       */\r
+/*                  Range: power of 2 only, > 0.                            */\r
+/*      Throws: std::bad_alloc, anything                                    */\r
+/*==========================================================================*/\r
+\r
+FFTReal::FFTReal (const long length)\r
+:      _length (length)\r
+,      _nbr_bits (int (floor (log (length) / log (2) + 0.5)))\r
+,      _bit_rev_lut (int (floor (log (length) / log (2) + 0.5)))\r
+,      _trigo_lut (int (floor (log (length) / log (2) + 0.5)))\r
+,      _sqrt2_2 (flt_t (sqrt (2) * 0.5))\r
+{\r
+       assert ((1L << _nbr_bits) == length);\r
+\r
+       _buffer_ptr = 0;\r
+       if (_nbr_bits > 2)\r
+       {\r
+               _buffer_ptr = new flt_t [_length];\r
+       }\r
+}\r
+\r
+\r
+\r
+/*==========================================================================*/\r
+/*      Name: Destructor                                                    */\r
+/*==========================================================================*/\r
+\r
+FFTReal::~FFTReal (void)\r
+{\r
+       delete [] _buffer_ptr;\r
+       _buffer_ptr = 0;\r
+}\r
+\r
+\r
+\r
+/*==========================================================================*/\r
+/*      Name: do_fft                                                        */\r
+/*      Description: Compute the FFT of the array.                          */\r
+/*      Input parameters:                                                   */\r
+/*        - x: pointer on the source array (time).                          */\r
+/*      Output parameters:                                                  */\r
+/*        - f: pointer on the destination array (frequencies).              */\r
+/*             f [0...length(x)/2] = real values,                           */\r
+/*             f [length(x)/2+1...length(x)-1] = imaginary values of        */\r
+/*               coefficents 1...length(x)/2-1.                             */\r
+/*      Throws: Nothing                                                     */\r
+/*==========================================================================*/\r
+\r
+void   FFTReal::do_fft (flt_t f [], const flt_t x []) const\r
+{\r
+\r
+/*______________________________________________\r
+ *\r
+ * General case\r
+ *______________________________________________\r
+ */\r
+\r
+       if (_nbr_bits > 2)\r
+       {\r
+               flt_t *                 sf;\r
+               flt_t *                 df;\r
+\r
+               if (_nbr_bits & 1)\r
+               {\r
+                       df = _buffer_ptr;\r
+                       sf = f;\r
+               }\r
+               else\r
+               {\r
+                       df = f;\r
+                       sf = _buffer_ptr;\r
+               }\r
+\r
+               /* Do the transformation in several pass */\r
+               {\r
+                       int             pass;\r
+                       long            nbr_coef;\r
+                       long            h_nbr_coef;\r
+                       long            d_nbr_coef;\r
+                       long            coef_index;\r
+\r
+                       /* First and second pass at once */\r
+                       {\r
+                               const long * const      bit_rev_lut_ptr = _bit_rev_lut.get_ptr ();\r
+                               coef_index = 0;\r
+                               do\r
+                               {\r
+                                       const long              rev_index_0 = bit_rev_lut_ptr [coef_index];\r
+                                       const long              rev_index_1 = bit_rev_lut_ptr [coef_index + 1];\r
+                                       const long              rev_index_2 = bit_rev_lut_ptr [coef_index + 2];\r
+                                       const long              rev_index_3 = bit_rev_lut_ptr [coef_index + 3];\r
+\r
+                                       flt_t   * const df2 = df + coef_index;\r
+                                       df2 [1] = x [rev_index_0] - x [rev_index_1];\r
+                                       df2 [3] = x [rev_index_2] - x [rev_index_3];\r
+\r
+                                       const flt_t             sf_0 = x [rev_index_0] + x [rev_index_1];\r
+                                       const flt_t             sf_2 = x [rev_index_2] + x [rev_index_3];\r
+\r
+                                       df2 [0] = sf_0 + sf_2;\r
+                                       df2 [2] = sf_0 - sf_2;\r
+                                       \r
+                                       coef_index += 4;\r
+                               }\r
+                               while (coef_index < _length);\r
+                       }\r
+\r
+                       /* Third pass */\r
+                       {\r
+                               coef_index = 0;\r
+                               const flt_t             sqrt2_2 = _sqrt2_2;\r
+                               do\r
+                               {\r
+                                       flt_t                           v;\r
+\r
+                                       sf [coef_index] = df [coef_index] + df [coef_index + 4];\r
+                                       sf [coef_index + 4] = df [coef_index] - df [coef_index + 4];\r
+                                       sf [coef_index + 2] = df [coef_index + 2];\r
+                                       sf [coef_index + 6] = df [coef_index + 6];\r
+\r
+                                       v = (df [coef_index + 5] - df [coef_index + 7]) * sqrt2_2;\r
+                                       sf [coef_index + 1] = df [coef_index + 1] + v;\r
+                                       sf [coef_index + 3] = df [coef_index + 1] - v;\r
+\r
+                                       v = (df [coef_index + 5] + df [coef_index + 7]) * sqrt2_2;\r
+                                       sf [coef_index + 5] = v + df [coef_index + 3];\r
+                                       sf [coef_index + 7] = v - df [coef_index + 3];\r
+\r
+                                       coef_index += 8;\r
+                               }\r
+                               while (coef_index < _length);\r
+                       }\r
+\r
+                       /* Next pass */\r
+                       for (pass = 3; pass < _nbr_bits; ++pass)\r
+                       {\r
+                               coef_index = 0;\r
+                               nbr_coef = 1 << pass;\r
+                               h_nbr_coef = nbr_coef >> 1;\r
+                               d_nbr_coef = nbr_coef << 1;\r
+                               const flt_t     * const cos_ptr = _trigo_lut.get_ptr (pass);\r
+                               do\r
+                               {\r
+                                       long                            i;\r
+                                       const flt_t     *       const sf1r = sf + coef_index;\r
+                                       const flt_t     *       const sf2r = sf1r + nbr_coef;\r
+                                       flt_t *                 const dfr = df + coef_index;\r
+                                       flt_t *                 const dfi = dfr + nbr_coef;\r
+\r
+                                       /* Extreme coefficients are always real */\r
+                                       dfr [0] = sf1r [0] + sf2r [0];\r
+                                       dfi [0] = sf1r [0] - sf2r [0];  // dfr [nbr_coef] =\r
+                                       dfr [h_nbr_coef] = sf1r [h_nbr_coef];\r
+                                       dfi [h_nbr_coef] = sf2r [h_nbr_coef];\r
+\r
+                                       /* Others are conjugate complex numbers */\r
+                                       const flt_t     * const sf1i = sf1r + h_nbr_coef;\r
+                                       const flt_t     * const sf2i = sf1i + nbr_coef;\r
+                                       for (i = 1; i < h_nbr_coef; ++ i)\r
+                                       {\r
+                                               const flt_t             c = cos_ptr [i];                                        // cos (i*PI/nbr_coef);\r
+                                               const flt_t             s = cos_ptr [h_nbr_coef - i];   // sin (i*PI/nbr_coef);\r
+                                               flt_t                           v;\r
+\r
+                                               v = sf2r [i] * c - sf2i [i] * s;\r
+                                               dfr [i] = sf1r [i] + v;\r
+                                               dfi [-i] = sf1r [i] - v;        // dfr [nbr_coef - i] =\r
+\r
+                                               v = sf2r [i] * s + sf2i [i] * c;\r
+                                               dfi [i] = v + sf1i [i];\r
+                                               dfi [nbr_coef - i] = v - sf1i [i];\r
+                                       }\r
+\r
+                                       coef_index += d_nbr_coef;\r
+                               }\r
+                               while (coef_index < _length);\r
+\r
+                               /* Prepare to the next pass */\r
+                               {\r
+                                       flt_t   * const         temp_ptr = df;\r
+                                       df = sf;\r
+                                       sf = temp_ptr;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+/*______________________________________________\r
+ *\r
+ * Special cases\r
+ *______________________________________________\r
+ */\r
+\r
+       /* 4-point FFT */\r
+       else if (_nbr_bits == 2)\r
+       {\r
+               f [1] = x [0] - x [2];\r
+               f [3] = x [1] - x [3];\r
+\r
+               const flt_t                     b_0 = x [0] + x [2];\r
+               const flt_t                     b_2 = x [1] + x [3];\r
+               \r
+               f [0] = b_0 + b_2;\r
+               f [2] = b_0 - b_2;\r
+       }\r
+\r
+       /* 2-point FFT */\r
+       else if (_nbr_bits == 1)\r
+       {\r
+               f [0] = x [0] + x [1];\r
+               f [1] = x [0] - x [1];\r
+       }\r
+\r
+       /* 1-point FFT */\r
+       else\r
+       {\r
+               f [0] = x [0];\r
+       }\r
+}\r
+\r
+\r
+\r
+/*==========================================================================*/\r
+/*      Name: do_ifft                                                       */\r
+/*      Description: Compute the inverse FFT of the array. Notice that      */\r
+/*                   IFFT (FFT (x)) = x * length (x). Data must be          */\r
+/*                   post-scaled.                                           */\r
+/*      Input parameters:                                                   */\r
+/*        - f: pointer on the source array (frequencies).                   */\r
+/*             f [0...length(x)/2] = real values,                           */\r
+/*             f [length(x)/2+1...length(x)] = imaginary values of          */\r
+/*               coefficents 1...length(x)-1.                               */\r
+/*      Output parameters:                                                  */\r
+/*        - x: pointer on the destination array (time).                     */\r
+/*      Throws: Nothing                                                     */\r
+/*==========================================================================*/\r
+\r
+void   FFTReal::do_ifft (const flt_t f [], flt_t x []) const\r
+{\r
+\r
+/*______________________________________________\r
+ *\r
+ * General case\r
+ *______________________________________________\r
+ */\r
+\r
+       if (_nbr_bits > 2)\r
+       {\r
+               flt_t *                 sf = const_cast <flt_t *> (f);\r
+               flt_t *                 df;\r
+               flt_t *                 df_temp;\r
+\r
+               if (_nbr_bits & 1)\r
+               {\r
+                       df = _buffer_ptr;\r
+                       df_temp = x;\r
+               }\r
+               else\r
+               {\r
+                       df = x;\r
+                       df_temp = _buffer_ptr;\r
+               }\r
+\r
+               /* Do the transformation in several pass */\r
+               {\r
+                       int                     pass;\r
+                       long                    nbr_coef;\r
+                       long                    h_nbr_coef;\r
+                       long                    d_nbr_coef;\r
+                       long                    coef_index;\r
+\r
+                       /* First pass */\r
+                       for (pass = _nbr_bits - 1; pass >= 3; --pass)\r
+                       {\r
+                               coef_index = 0;\r
+                               nbr_coef = 1 << pass;\r
+                               h_nbr_coef = nbr_coef >> 1;\r
+                               d_nbr_coef = nbr_coef << 1;\r
+                               const flt_t     *const cos_ptr = _trigo_lut.get_ptr (pass);\r
+                               do\r
+                               {\r
+                                       long                            i;\r
+                                       const flt_t     *       const sfr = sf + coef_index;\r
+                                       const flt_t     *       const sfi = sfr + nbr_coef;\r
+                                       flt_t *                 const df1r = df + coef_index;\r
+                                       flt_t *                 const df2r = df1r + nbr_coef;\r
+\r
+                                       /* Extreme coefficients are always real */\r
+                                       df1r [0] = sfr [0] + sfi [0];           // + sfr [nbr_coef]\r
+                                       df2r [0] = sfr [0] - sfi [0];           // - sfr [nbr_coef]\r
+                                       df1r [h_nbr_coef] = sfr [h_nbr_coef] * 2;\r
+                                       df2r [h_nbr_coef] = sfi [h_nbr_coef] * 2;\r
+\r
+                                       /* Others are conjugate complex numbers */\r
+                                       flt_t * const   df1i = df1r + h_nbr_coef;\r
+                                       flt_t * const   df2i = df1i + nbr_coef;\r
+                                       for (i = 1; i < h_nbr_coef; ++ i)\r
+                                       {\r
+                                               df1r [i] = sfr [i] + sfi [-i];          // + sfr [nbr_coef - i]\r
+                                               df1i [i] = sfi [i] - sfi [nbr_coef - i];\r
+\r
+                                               const flt_t             c = cos_ptr [i];                                        // cos (i*PI/nbr_coef);\r
+                                               const flt_t             s = cos_ptr [h_nbr_coef - i];   // sin (i*PI/nbr_coef);\r
+                                               const flt_t             vr = sfr [i] - sfi [-i];                // - sfr [nbr_coef - i]\r
+                                               const flt_t             vi = sfi [i] + sfi [nbr_coef - i];\r
+\r
+                                               df2r [i] = vr * c + vi * s;\r
+                                               df2i [i] = vi * c - vr * s;\r
+                                       }\r
+\r
+                                       coef_index += d_nbr_coef;\r
+                               }\r
+                               while (coef_index < _length);\r
+\r
+                               /* Prepare to the next pass */\r
+                               if (pass < _nbr_bits - 1)\r
+                               {\r
+                                       flt_t   * const temp_ptr = df;\r
+                                       df = sf;\r
+                                       sf = temp_ptr;\r
+                               }\r
+                               else\r
+                               {\r
+                                       sf = df;\r
+                                       df = df_temp;\r
+                               }\r
+                       }\r
+\r
+                       /* Antepenultimate pass */\r
+                       {\r
+                               const flt_t             sqrt2_2 = _sqrt2_2;\r
+                               coef_index = 0;\r
+                               do\r
+                               {\r
+                                       df [coef_index] = sf [coef_index] + sf [coef_index + 4];\r
+                                       df [coef_index + 4] = sf [coef_index] - sf [coef_index + 4];\r
+                                       df [coef_index + 2] = sf [coef_index + 2] * 2;\r
+                                       df [coef_index + 6] = sf [coef_index + 6] * 2;\r
+\r
+                                       df [coef_index + 1] = sf [coef_index + 1] + sf [coef_index + 3];\r
+                                       df [coef_index + 3] = sf [coef_index + 5] - sf [coef_index + 7];\r
+\r
+                                       const flt_t             vr = sf [coef_index + 1] - sf [coef_index + 3];\r
+                                       const flt_t             vi = sf [coef_index + 5] + sf [coef_index + 7];\r
+\r
+                                       df [coef_index + 5] = (vr + vi) * sqrt2_2;\r
+                                       df [coef_index + 7] = (vi - vr) * sqrt2_2;\r
+\r
+                                       coef_index += 8;\r
+                               }\r
+                               while (coef_index < _length);\r
+                       }\r
+\r
+                       /* Penultimate and last pass at once */\r
+                       {\r
+                               coef_index = 0;\r
+                               const long *    bit_rev_lut_ptr = _bit_rev_lut.get_ptr ();\r
+                               const flt_t     *       sf2 = df;\r
+                               do\r
+                               {\r
+                                       {\r
+                                               const flt_t             b_0 = sf2 [0] + sf2 [2];\r
+                                               const flt_t             b_2 = sf2 [0] - sf2 [2];\r
+                                               const flt_t             b_1 = sf2 [1] * 2;\r
+                                               const flt_t             b_3 = sf2 [3] * 2;\r
+\r
+                                               x [bit_rev_lut_ptr [0]] = b_0 + b_1;\r
+                                               x [bit_rev_lut_ptr [1]] = b_0 - b_1;\r
+                                               x [bit_rev_lut_ptr [2]] = b_2 + b_3;\r
+                                               x [bit_rev_lut_ptr [3]] = b_2 - b_3;\r
+                                       }\r
+                                       {\r
+                                               const flt_t             b_0 = sf2 [4] + sf2 [6];\r
+                                               const flt_t             b_2 = sf2 [4] - sf2 [6];\r
+                                               const flt_t             b_1 = sf2 [5] * 2;\r
+                                               const flt_t             b_3 = sf2 [7] * 2;\r
+\r
+                                               x [bit_rev_lut_ptr [4]] = b_0 + b_1;\r
+                                               x [bit_rev_lut_ptr [5]] = b_0 - b_1;\r
+                                               x [bit_rev_lut_ptr [6]] = b_2 + b_3;\r
+                                               x [bit_rev_lut_ptr [7]] = b_2 - b_3;\r
+                                       }\r
+\r
+                                       sf2 += 8;\r
+                                       coef_index += 8;\r
+                                       bit_rev_lut_ptr += 8;\r
+                               }\r
+                               while (coef_index < _length);\r
+                       }\r
+               }\r
+       }\r
+\r
+/*______________________________________________\r
+ *\r
+ * Special cases\r
+ *______________________________________________\r
+ */\r
+\r
+       /* 4-point IFFT */\r
+       else if (_nbr_bits == 2)\r
+       {\r
+               const flt_t             b_0 = f [0] + f [2];\r
+               const flt_t             b_2 = f [0] - f [2];\r
+\r
+               x [0] = b_0 + f [1] * 2;\r
+               x [2] = b_0 - f [1] * 2;\r
+               x [1] = b_2 + f [3] * 2;\r
+               x [3] = b_2 - f [3] * 2;\r
+       }\r
+\r
+       /* 2-point IFFT */\r
+       else if (_nbr_bits == 1)\r
+       {\r
+               x [0] = f [0] + f [1];\r
+               x [1] = f [0] - f [1];\r
+       }\r
+\r
+       /* 1-point IFFT */\r
+       else\r
+       {\r
+               x [0] = f [0];\r
+       }\r
+}\r
+\r
+\r
+\r
+/*==========================================================================*/\r
+/*      Name: rescale                                                       */\r
+/*      Description: Scale an array by divide each element by its length.   */\r
+/*                   This function should be called after FFT + IFFT.       */\r
+/*      Input/Output parameters:                                            */\r
+/*        - x: pointer on array to rescale (time or frequency).             */\r
+/*      Throws: Nothing                                                     */\r
+/*==========================================================================*/\r
+\r
+void   FFTReal::rescale (flt_t x []) const\r
+{\r
+       const flt_t             mul = flt_t (1.0 / _length);\r
+       long                            i = _length - 1;\r
+\r
+       do\r
+       {\r
+               x [i] *= mul;\r
+               --i;\r
+       }\r
+       while (i >= 0);\r
+}\r
+\r
+\r
+\r
+/*\\\ NESTED CLASS MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/\r
+\r
+\r
+\r
+/*==========================================================================*/\r
+/*      Name: Constructor                                                   */\r
+/*      Input parameters:                                                   */\r
+/*        - nbr_bits: number of bits of the array on which we want to do a  */\r
+/*                    FFT. Range: > 0                                       */\r
+/*      Throws: std::bad_alloc                                              */\r
+/*==========================================================================*/\r
+\r
+FFTReal::BitReversedLUT::BitReversedLUT (const int nbr_bits)\r
+{\r
+       long                            length;\r
+       long                            cnt;\r
+       long                            br_index;\r
+       long                            bit;\r
+\r
+       length = 1L << nbr_bits;\r
+       _ptr = new long [length];\r
+\r
+       br_index = 0;\r
+       _ptr [0] = 0;\r
+       for (cnt = 1; cnt < length; ++cnt)\r
+       {\r
+               /* ++br_index (bit reversed) */\r
+               bit = length >> 1;\r
+               while (((br_index ^= bit) & bit) == 0)\r
+               {\r
+                       bit >>= 1;\r
+               }\r
+\r
+               _ptr [cnt] = br_index;\r
+       }\r
+}\r
+\r
+\r
+\r
+/*==========================================================================*/\r
+/*      Name: Destructor                                                    */\r
+/*==========================================================================*/\r
+\r
+FFTReal::BitReversedLUT::~BitReversedLUT (void)\r
+{\r
+       delete [] _ptr;\r
+       _ptr = 0;\r
+}\r
+\r
+\r
+\r
+/*==========================================================================*/\r
+/*      Name: Constructor                                                   */\r
+/*      Input parameters:                                                   */\r
+/*        - nbr_bits: number of bits of the array on which we want to do a  */\r
+/*                    FFT. Range: > 0                                       */\r
+/*      Throws: std::bad_alloc, anything                                    */\r
+/*==========================================================================*/\r
+\r
+FFTReal::TrigoLUT::TrigoLUT (const int nbr_bits)\r
+{\r
+       long            total_len;\r
+\r
+       _ptr = 0;\r
+       if (nbr_bits > 3)\r
+       {\r
+               total_len = (1L << (nbr_bits - 1)) - 4;\r
+               _ptr = new flt_t [total_len];\r
+\r
+               const double    PI = atan (1) * 4;\r
+               for (int level = 3; level < nbr_bits; ++level)\r
+               {\r
+                       const long              level_len = 1L << (level - 1);\r
+                       flt_t   * const level_ptr = const_cast<flt_t *> (get_ptr (level));\r
+                       const double    mul = PI / (level_len << 1);\r
+\r
+                       for (long i = 0; i < level_len; ++ i)\r
+                       {\r
+                               level_ptr [i] = (flt_t) cos (i * mul);\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+\r
+\r
+/*==========================================================================*/\r
+/*      Name: Destructor                                                    */\r
+/*==========================================================================*/\r
+\r
+FFTReal::TrigoLUT::~TrigoLUT (void)\r
+{\r
+       delete [] _ptr;\r
+       _ptr = 0;\r
+}\r
+\r
+\r
+\r
+#if defined (_MSC_VER)\r
+#pragma pack (pop)\r
+#endif // _MSC_VER\r
+\r
+\r
+\r
+/*****************************************************************************\r
+\r
+       LEGAL\r
+\r
+       Source code may be freely used for any purpose, including commercial\r
+       applications. Programs must display in their "About" dialog-box (or\r
+       documentation) a text telling they use these routines by Laurent de Soras.\r
+       Modified source code can be distributed, but modifications must be clearly\r
+       indicated.\r
+\r
+       CONTACT\r
+\r
+       Laurent de Soras\r
+       92 avenue Albert 1er\r
+       92500 Rueil-Malmaison\r
+       France\r
+\r
+       ldesoras@club-internet.fr\r
+\r
+*****************************************************************************/\r
+\r
+\r
+\r
+/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/\r
diff --git a/src/mod/applications/mod_stress/FFTReal.h b/src/mod/applications/mod_stress/FFTReal.h
new file mode 100644 (file)
index 0000000..792a97b
--- /dev/null
@@ -0,0 +1,139 @@
+/*****************************************************************************\r
+*                                                                            *\r
+*       DIGITAL SIGNAL PROCESSING TOOLS                                      *\r
+*       Version 1.03, 2001/06/15                                             *\r
+*       (c) 1999 - Laurent de Soras                                          *\r
+*                                                                            *\r
+*       FFTReal.h                                                            *\r
+*       Fourier transformation of real number arrays.                        *\r
+*       Portable ISO C++                                                     *\r
+*                                                                            *\r
+* Tab = 3                                                                    *\r
+*****************************************************************************/\r
+\r
+\r
+\r
+#if defined (FFTReal_CURRENT_HEADER)\r
+       #error Recursive inclusion of FFTReal header file.\r
+#endif\r
+#define        FFTReal_CURRENT_HEADER\r
+\r
+#if ! defined (FFTReal_HEADER_INCLUDED)\r
+#define        FFTReal_HEADER_INCLUDED\r
+\r
+\r
+\r
+#if defined (_MSC_VER)\r
+#pragma pack (push, 8)\r
+#endif // _MSC_VER\r
+\r
+\r
+\r
+class  FFTReal\r
+{\r
+\r
+/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/\r
+\r
+public:\r
+\r
+       /* Change this typedef to use a different floating point type in your FFTs\r
+               (i.e. float, double or long double). */\r
+       typedef float   flt_t;\r
+\r
+       explicit                        FFTReal (const long length);\r
+                                               ~FFTReal ();\r
+       void                            do_fft (flt_t f [], const flt_t x []) const;\r
+       void                            do_ifft (const flt_t f [], flt_t x []) const;\r
+       void                            rescale (flt_t x []) const;\r
+\r
+\r
+\r
+/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/\r
+\r
+private:\r
+\r
+       /* Bit-reversed look-up table nested class */\r
+       class BitReversedLUT\r
+       {\r
+       public:\r
+               explicit                        BitReversedLUT (const int nbr_bits);\r
+                                                       ~BitReversedLUT ();\r
+               const long *    get_ptr () const\r
+               {\r
+                       return (_ptr);\r
+               }\r
+       private:\r
+               long *                  _ptr;\r
+       };\r
+\r
+       /* Trigonometric look-up table nested class */\r
+       class   TrigoLUT\r
+       {\r
+       public:\r
+               explicit                        TrigoLUT (const int nbr_bits);\r
+                                                       ~TrigoLUT ();\r
+               const flt_t     *       get_ptr (const int level) const\r
+               {\r
+                       return (_ptr + (1L << (level - 1)) - 4);\r
+               };\r
+       private:\r
+               flt_t   *                       _ptr;\r
+       };\r
+\r
+       const BitReversedLUT    _bit_rev_lut;\r
+       const TrigoLUT  _trigo_lut;\r
+       const flt_t             _sqrt2_2;\r
+       const long              _length;\r
+       const int               _nbr_bits;\r
+       flt_t *                 _buffer_ptr;\r
+\r
+\r
+\r
+/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/\r
+\r
+private:\r
+\r
+                                               FFTReal (const FFTReal &other);\r
+       const FFTReal&  operator = (const FFTReal &other);\r
+       int                             operator == (const FFTReal &other);\r
+       int                             operator != (const FFTReal &other);\r
+};\r
+\r
+\r
+\r
+#if defined (_MSC_VER)\r
+#pragma pack (pop)\r
+#endif // _MSC_VER\r
+\r
+\r
+\r
+#endif // FFTReal_HEADER_INCLUDED\r
+\r
+#undef FFTReal_CURRENT_HEADER\r
+\r
+\r
+\r
+/*****************************************************************************\r
+\r
+       LEGAL\r
+\r
+       Source code may be freely used for any purpose, including commercial\r
+       applications. Programs must display in their "About" dialog-box (or\r
+       documentation) a text telling they use these routines by Laurent de Soras.\r
+       Modified source code can be distributed, but modifications must be clearly\r
+       indicated.\r
+\r
+       CONTACT\r
+\r
+       Laurent de Soras\r
+       92 avenue Albert 1er\r
+       92500 Rueil-Malmaison\r
+       France\r
+\r
+       ldesoras@club-internet.fr\r
+\r
+*****************************************************************************/\r
+\r
+\r
+\r
+/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/\r
diff --git a/src/mod/applications/mod_stress/Makefile b/src/mod/applications/mod_stress/Makefile
new file mode 100644 (file)
index 0000000..a3203c7
--- /dev/null
@@ -0,0 +1,3 @@
+BASE=../../../..
+LOCAL_OBJS=FFTReal.o
+include $(BASE)/build/modmake.rules
diff --git a/src/mod/applications/mod_stress/mod_stress.cpp b/src/mod/applications/mod_stress/mod_stress.cpp
new file mode 100644 (file)
index 0000000..552085a
--- /dev/null
@@ -0,0 +1,266 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@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@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct@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:
+ */