[mod_stress] Remove from tree.
This commit is contained in:
parent
0acb3f2ccb
commit
866c235aa3
5
LICENSE
5
LICENSE
|
@ -1309,11 +1309,6 @@ Copyright: 2009-2012 10gen Inc.
|
|||
2001 Unicode, Inc.
|
||||
License: Apache-2.0
|
||||
|
||||
Files: src/mod/applications/mod_stress/FFTReal.h
|
||||
src/mod/applications/mod_stress/FFTReal.cpp
|
||||
Copyright: 1999 Laurent de Soras
|
||||
License: unclear
|
||||
|
||||
Files: src/mod/loggers/mod_syslog/mod_syslog.c
|
||||
Copyright: 2005-2010, James Martelletti <james@nerdc0re.com>
|
||||
License: MPL-1.1
|
||||
|
|
|
@ -43,7 +43,6 @@ applications/mod_sms
|
|||
#applications/mod_soundtouch
|
||||
applications/mod_spandsp
|
||||
#applications/mod_spy
|
||||
#applications/mod_stress
|
||||
applications/mod_test
|
||||
#applications/mod_translate
|
||||
applications/mod_valet_parking
|
||||
|
|
|
@ -43,7 +43,6 @@ applications/mod_sonar
|
|||
applications/mod_soundtouch
|
||||
applications/mod_spandsp
|
||||
applications/mod_spy
|
||||
applications/mod_stress
|
||||
applications/mod_test
|
||||
applications/mod_translate
|
||||
applications/mod_valet_parking
|
||||
|
|
|
@ -2135,7 +2135,6 @@ AC_CONFIG_FILES([Makefile
|
|||
src/mod/applications/mod_soundtouch/Makefile
|
||||
src/mod/applications/mod_spandsp/Makefile
|
||||
src/mod/applications/mod_spy/Makefile
|
||||
src/mod/applications/mod_stress/Makefile
|
||||
src/mod/applications/mod_test/Makefile
|
||||
src/mod/applications/mod_translate/Makefile
|
||||
src/mod/applications/mod_valet_parking/Makefile
|
||||
|
|
|
@ -551,7 +551,6 @@ Recommends:
|
|||
freeswitch-mod-soundtouch (= \${binary:Version}),
|
||||
freeswitch-mod-spandsp (= \${binary:Version}),
|
||||
freeswitch-mod-spy (= \${binary:Version}),
|
||||
freeswitch-mod-stress (= \${binary:Version}),
|
||||
freeswitch-mod-valet-parking (= \${binary:Version}),
|
||||
freeswitch-mod-vmd (= \${binary:Version}),
|
||||
freeswitch-mod-voicemail (= \${binary:Version}),
|
||||
|
@ -641,7 +640,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
|
|||
freeswitch-mod-soundtouch (= \${binary:Version}),
|
||||
freeswitch-mod-spandsp (= \${binary:Version}),
|
||||
freeswitch-mod-spy (= \${binary:Version}),
|
||||
freeswitch-mod-stress (= \${binary:Version}),
|
||||
freeswitch-mod-translate (= \${binary:Version}),
|
||||
freeswitch-mod-valet-parking (= \${binary:Version}),
|
||||
freeswitch-mod-video-filter (= \${binary:Version}),
|
||||
|
@ -868,7 +866,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
|
|||
freeswitch-mod-soundtouch-dbg (= \${binary:Version}),
|
||||
freeswitch-mod-spandsp-dbg (= \${binary:Version}),
|
||||
freeswitch-mod-spy-dbg (= \${binary:Version}),
|
||||
freeswitch-mod-stress-dbg (= \${binary:Version}),
|
||||
freeswitch-mod-translate-dbg (= \${binary:Version}),
|
||||
freeswitch-mod-valet-parking-dbg (= \${binary:Version}),
|
||||
freeswitch-mod-video-filter-dbg (= \${binary:Version}),
|
||||
|
|
|
@ -223,10 +223,6 @@ Module: applications/mod_spy
|
|||
Description: UserSpy
|
||||
This module adds the ability to monitor the audio of a channel.
|
||||
|
||||
Module: applications/mod_stress
|
||||
Description: Voice stress detection
|
||||
This module attempts to detect voice stress on an audio channel.
|
||||
|
||||
Module: applications/mod_translate
|
||||
Description: Number translation
|
||||
This module implements number translation.
|
||||
|
|
|
@ -1309,11 +1309,6 @@ Copyright: 2009-2012 10gen Inc.
|
|||
2001 Unicode, Inc.
|
||||
License: Apache-2.0
|
||||
|
||||
Files: src/mod/applications/mod_stress/FFTReal.h
|
||||
src/mod/applications/mod_stress/FFTReal.cpp
|
||||
Copyright: 1999 Laurent de Soras
|
||||
License: unclear
|
||||
|
||||
Files: src/mod/loggers/mod_syslog/mod_syslog.c
|
||||
Copyright: 2005-2010, James Martelletti <james@nerdc0re.com>
|
||||
License: MPL-1.1
|
||||
|
|
|
@ -535,15 +535,6 @@ Requires: %{name} = %{version}-%{release}
|
|||
Provides FreeSWITCH mod_spy, implements userspy application which provides
|
||||
persistent eavesdrop on all channels bridged to a certain user
|
||||
|
||||
%package application-stress
|
||||
Summary: FreeSWITCH mod_stress
|
||||
Group: System/Libraries
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
%description application-stress
|
||||
Provides FreeSWITCH mod_stress. mod_stress attempts to detect stress in a
|
||||
person's voice and generates FreeSWITCH events based on that data.
|
||||
|
||||
%package application-translate
|
||||
Summary: FreeSWITCH mod_translate
|
||||
Group: System/Libraries
|
||||
|
@ -1228,7 +1219,6 @@ Requires: freeswitch-application-snapshot
|
|||
Requires: freeswitch-application-snom
|
||||
Requires: freeswitch-application-soundtouch
|
||||
Requires: freeswitch-application-spy
|
||||
Requires: freeswitch-application-stress
|
||||
Requires: freeswitch-application-valet_parking
|
||||
Requires: freeswitch-application-video_filter
|
||||
Requires: freeswitch-application-voicemail
|
||||
|
@ -1307,7 +1297,7 @@ APPLICATION_MODULES_FR="applications/mod_fifo applications/mod_fsk applications/
|
|||
applications/mod_redis applications/mod_rss "
|
||||
|
||||
APPLICATION_MODULES_SZ="applications/mod_signalwire applications/mod_sms applications/mod_snapshot applications/mod_snom applications/mod_soundtouch \
|
||||
applications/mod_spandsp applications/mod_spy applications/mod_stress \
|
||||
applications/mod_spandsp applications/mod_spy \
|
||||
applications/mod_valet_parking applications/mod_translate applications/mod_voicemail \
|
||||
applications/mod_voicemail_ivr applications/mod_video_filter"
|
||||
|
||||
|
@ -1980,9 +1970,6 @@ fi
|
|||
%files application-spy
|
||||
%{MODINSTDIR}/mod_spy.so*
|
||||
|
||||
%files application-stress
|
||||
%{MODINSTDIR}/mod_stress.so*
|
||||
|
||||
%files application-translate
|
||||
%{MODINSTDIR}/mod_translate.so*
|
||||
|
||||
|
|
|
@ -21,9 +21,6 @@
|
|||
/applications/mod_spandsp/Makefile
|
||||
/applications/mod_spandsp/Makefile.in
|
||||
/applications/mod_spandsp/mod_spandsp.log
|
||||
/applications/mod_stress/Makefile
|
||||
/applications/mod_stress/Makefile.in
|
||||
/applications/mod_stress/mod_stress.log
|
||||
/applications/mod_translate/Makefile
|
||||
/applications/mod_valet_parking/Makefile
|
||||
/applications/mod_voicemail/Makefile
|
||||
|
|
|
@ -1,615 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* *
|
||||
* 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@club-internet.fr
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
|
|
@ -1,133 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* *
|
||||
* 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@club-internet.fr
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
|
|
@ -1,8 +0,0 @@
|
|||
include $(top_srcdir)/build/modmake.rulesam
|
||||
MODNAME=mod_stress
|
||||
|
||||
mod_LTLIBRARIES = mod_stress.la
|
||||
mod_stress_la_SOURCES = mod_stress.cpp FFTReal.cpp
|
||||
mod_stress_la_CFLAGS = $(AM_CFLAGS)
|
||||
mod_stress_la_LIBADD = $(switch_builddir)/libfreeswitch.la
|
||||
mod_stress_la_LDFLAGS = -avoid-version -module -no-undefined -shared
|
|
@ -1,264 +0,0 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* 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 <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* 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;
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_DEBUG, "Stress %0.2f\n", sth->stress);
|
||||
|
||||
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", "%0.2f", sth->stress);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(sth->session));
|
||||
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_SESSION_LOG(switch_core_media_bug_get_session(bug)), 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_channel_t *channel = switch_core_session_get_channel(session);
|
||||
struct stress_helper *sth;
|
||||
char *argv[6];
|
||||
char *lbuf = NULL;
|
||||
int x = 0;
|
||||
|
||||
if ((bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_stress_"))) {
|
||||
if (!zstr(data) && !strcasecmp(data, "stop")) {
|
||||
switch_channel_set_private(channel, "_stress_", NULL);
|
||||
switch_core_media_bug_remove(session, &bug);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), 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))
|
||||
&& switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) {
|
||||
if (!strncasecmp(argv[x], "read", 4)) {
|
||||
sth->read = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sth->session = session;
|
||||
|
||||
if (switch_core_media_bug_add(session, "stress", NULL, stress_callback, sth, 0, sth->read ? SMBF_READ_REPLACE : SMBF_WRITE_REPLACE, &bug) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), 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:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
Loading…
Reference in New Issue