Fri Aug 24 02:22:46 2007

Asterisk developer's documentation


app_mwanalyze.c File Reference

#include <asterisk.h>
#include <stdio.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>

Include dependency graph for app_mwanalyze.c:

Go to the source code of this file.

Defines

#define PI   (4*atan(1))

Functions

 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Digital Analyzer for Milliwatt Application (slin)")
static int load_module (void)
static int mwanalyze_exec (struct ast_channel *chan, void *data)
static int unload_module (void)

Variables

static char * app = "Mwanalyze"
static char * synopsis = "Spectral analyses based on a given frequency (slin)"
static char * tdescription


Define Documentation

#define PI   (4*atan(1))

Definition at line 29 of file app_mwanalyze.c.

Referenced by mwanalyze_exec().


Function Documentation

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"Digital Analyzer for Milliwatt Application (slin)"   
)

static int load_module ( void   )  [static]

Definition at line 338 of file app_mwanalyze.c.

References app, ast_register_application(), mwanalyze_exec(), synopsis, and tdescription.

static int mwanalyze_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 45 of file app_mwanalyze.c.

References ast_channel::_state, ast_answer(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_frfree(), AST_FRIENDLY_OFFSET, ast_log(), ast_module_user_add, ast_module_user_remove, ast_read(), ast_set_read_format(), ast_set_write_format(), AST_STATE_UP, ast_waitfor(), ast_write(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_frame::frametype, free, len, LOG_WARNING, malloc, ast_frame::mallocd, ast_frame::offset, pbx_builtin_setvar_helper(), PI, ast_channel::readformat, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_channel::writeformat.

Referenced by load_module().

00046 {
00047    int res = 0;
00048    struct ast_module_user *u;
00049    char *args, *cp, *cp0, linebuf[320];
00050    unsigned int frequency = 0, timeslice = 0, duration = 0, j;
00051    int i, v, treshold = 0;
00052 
00053    int original_read_fmt;
00054    int original_write_fmt;
00055    struct ast_frame *inf = NULL;
00056    struct ast_frame outf;
00057    unsigned char waste[AST_FRIENDLY_OFFSET]; /* seen in app_millitwatt.c, don't understand what this is useful for */
00058    short buf[640];
00059    unsigned int indexp, len, ts_index, ts_offset, phase;
00060    short sin_x, cos_x, val;
00061    long long sum_sin, sum_cos, total_deviation = 0, sum_sin0 = 0, sum_cos0 = 0;
00062    int total_samples, *periods_in_timeslice, total_bad_timeslices;
00063    double coeff_sin, coeff_cos, amplitude, timeslice_ripple, total_ripple, modell_val, avg_val;
00064    short *tone, *lastperiod;
00065    long long *avg_period;
00066 
00067 
00068    /*** check whether arguments are provided ... */
00069 
00070    if ((data == NULL) || (!((char *) data)[0])) {
00071       ast_log(LOG_WARNING, "Mwanalyze needs arguments frequency, timeslice, duration and treshold.\n");
00072       return -1;
00073    }
00074 
00075    if ((args = (char *) malloc(strlen((char *) data))) == NULL) {
00076       ast_log(LOG_WARNING, "Mwanalyze cannot allocate enough memory.\n");
00077       return -1;
00078    }
00079 
00080    /*** now parse arguments ... */
00081    strcpy(args, (char *) data);
00082    cp = args;
00083    for (i = 0; i < 4; i++) {
00084       cp0 = cp;
00085       cp = strchr(cp, '|');
00086       if (cp) {
00087          *cp++ = 0;
00088       } else if (i < 3) {
00089          ast_log(LOG_WARNING, "Mwanalyze needs arguments frequency, timeslice, duration and treshold.\n");
00090          free(args);
00091          return -1;
00092       }
00093 
00094       if (sscanf(cp0, "%d", &v) != 1) {
00095          ast_log(LOG_WARNING, "Mwanalyze needs only integers as arguments.\n");
00096          free(args);
00097          return -1;
00098       }
00099 
00100       switch (i) {
00101          case 0:
00102             frequency = v;
00103          case 1:
00104             timeslice = v;
00105          case 2:
00106             duration = v;
00107          case 3:
00108             treshold = v;
00109       }
00110    }
00111 
00112    /*** prepare sine wave */
00113    if (frequency % 4)
00114       frequency--;
00115    if (frequency % 4)
00116       frequency--;
00117    if (frequency % 4)
00118       frequency--;
00119    if (frequency < 4) {
00120       frequency = 4;
00121    }
00122    if (timeslice < frequency) {
00123       timeslice = frequency;
00124    }
00125    if (duration < 1) {
00126       duration = 1;
00127    }
00128    if (treshold < 1) {
00129       treshold = 1;
00130    }
00131 
00132    if ((tone = (short *) malloc(frequency * sizeof(short))) == NULL) {
00133       ast_log(LOG_WARNING, "Mwanalyze cannot allocate enough memory.\n");
00134       free(args);
00135       return -1;
00136    }
00137    if ((lastperiod = (short *) malloc(frequency * sizeof(short))) == NULL) {
00138       ast_log(LOG_WARNING, "Mwanalyze cannot allocate enough memory.\n");
00139       free(tone);
00140       free(args);
00141       return -1;
00142    }
00143    if ((avg_period = (long long *) malloc(frequency * sizeof(long long))) == NULL) {
00144       ast_log(LOG_WARNING, "Mwanalyze cannot allocate enough memory.\n");
00145       free(lastperiod);
00146       free(tone);
00147       free(args);
00148       return -1;
00149    }
00150    if ((periods_in_timeslice = (int *) malloc(frequency * sizeof(int))) == NULL) {
00151       ast_log(LOG_WARNING, "Mwanalyze cannot allocate enough memory.\n");
00152       free(avg_period);
00153       free(lastperiod);
00154       free(tone);
00155       free(args);
00156       return -1;
00157    }
00158 
00159    for (indexp = 0; indexp < frequency; indexp++) {
00160       tone[indexp] = (short) (sin((double) indexp / frequency * 2 * PI) * ((1 << 15) - 1));
00161    }
00162 
00163    u = ast_module_user_add(chan);
00164 
00165    /*** answer if necessary */
00166    if ((!res) && (chan->_state != AST_STATE_UP)) {
00167       if ((res = ast_answer(chan)) < 0) {
00168          ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
00169       }
00170    }
00171 
00172    /*** save audio codecs and switch to slin if necessary */
00173    original_read_fmt = AST_FORMAT_SLINEAR;
00174    if ((!res) && ((original_read_fmt = chan->readformat) != AST_FORMAT_SLINEAR)) {
00175       if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
00176          ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up.\n");
00177       }
00178    }
00179    original_write_fmt = AST_FORMAT_SLINEAR;
00180    if ((!res) && ((original_write_fmt = chan->writeformat) != AST_FORMAT_SLINEAR)) {
00181       if ((res = ast_set_write_format(chan, AST_FORMAT_SLINEAR)) < 0) {
00182          ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up.\n");
00183       }
00184    }
00185 
00186 
00187    ts_index = 0;
00188    ts_offset = 0;
00189    phase = 0;
00190    sum_sin = sum_cos = 0.0;
00191    total_samples = 0;
00192    total_ripple = 0.0;
00193    total_bad_timeslices = 0;
00194 
00195    while ((ts_index < duration) && (!res) && (ast_waitfor(chan, -1) > -1)) {
00196       if ((inf = ast_read(chan)) == NULL) {
00197          /*** got hangup */
00198          res = -1;
00199          break;
00200       }
00201 
00202       if (inf->frametype == AST_FRAME_VOICE) {
00203          len = inf->samples;
00204          if (len > sizeof(buf)) {
00205             ast_log(LOG_WARNING, "Can only exchange %d bytes.\n", (int) sizeof(buf));
00206             len = sizeof(buf);
00207          }
00208 
00209          /*** analyze */
00210          for (i = 0; i < (int) len; i++) {
00211             /*** Fourier */
00212             val = ((short *) inf->data)[i];
00213             sin_x = tone[phase];
00214             cos_x = tone[(phase < 3 * frequency / 4) ? (phase + frequency / 4) : (phase - 3 * frequency / 4)];
00215             sum_sin += sin_x * val;
00216             sum_cos += cos_x * val;
00217 
00218             /*** total deviatian from real waveshape */
00219             if (ts_offset == 0) {
00220                total_deviation = 0;
00221                sum_sin0 = sum_sin;
00222                sum_cos0 = sum_cos;
00223             }
00224             if (ts_offset >= frequency) {
00225                total_deviation += (val >= lastperiod[phase]) ? (val - lastperiod[phase]) : (lastperiod[phase] - val);
00226             } else {
00227                avg_period[phase] = 0;
00228                periods_in_timeslice[phase] = 0;
00229             }
00230             lastperiod[phase] = val;
00231             avg_period[phase] += val;
00232             periods_in_timeslice[phase]++;
00233 
00234 
00235             /*** adavance pointers */
00236             if (++ts_offset == timeslice) {
00237                timeslice_ripple = (double) total_deviation / 2 / timeslice;
00238                coeff_sin = (sum_sin - sum_sin0) * 2.0 / ((1 << 15) - 1) / timeslice;
00239                coeff_cos = (sum_cos - sum_cos0) * 2.0 / ((1 << 15) - 1) / timeslice;
00240 
00241                total_deviation = 0;
00242                for (j = 0; j < frequency; j++) {
00243                   sin_x = tone[j];
00244                   cos_x = tone[(j < 3 * frequency / 4) ? (j + frequency / 4) : (j - 3 * frequency / 4)];
00245                   modell_val = coeff_sin * sin_x / ((1 << 15) - 1) + coeff_cos * cos_x / ((1 << 15) - 1);
00246                   avg_val = (double) avg_period[j] / periods_in_timeslice[j];
00247                   total_deviation += (long long) ((avg_val >= modell_val) ? (avg_val - modell_val) : (modell_val - avg_val));
00248                }
00249                timeslice_ripple += (double) total_deviation / frequency;
00250                total_ripple += timeslice_ripple;
00251                if (timeslice_ripple > treshold) {
00252                   total_bad_timeslices++;
00253                }
00254 
00255                ts_offset = 0;
00256                ts_index++;
00257             }
00258 
00259             if (++phase == frequency) {
00260                phase = 0;
00261             }
00262             total_samples++;
00263          }
00264 
00265          waste[0] = 0;     /* ???? */
00266          outf.frametype = AST_FRAME_VOICE;
00267          outf.subclass = AST_FORMAT_SLINEAR;
00268          outf.offset = AST_FRIENDLY_OFFSET;  /* ???? */
00269          outf.mallocd = 0;
00270          outf.data = buf;
00271          outf.datalen = len * sizeof(short);
00272          outf.samples = len;
00273          outf.src = "app_mwanalyze";
00274          outf.delivery.tv_sec = 0;
00275          outf.delivery.tv_usec = 0;
00276          for (i = 0; i < (int) len; i++) {
00277             if (indexp == frequency) {
00278                indexp = 0;
00279             }
00280             buf[i] = tone[indexp++];
00281          }
00282 
00283          if ((res = ast_write(chan, &outf)) < 0) {
00284             ast_log(LOG_WARNING, "Failed to write frame to '%s'.\n", chan->name);
00285          }
00286 
00287       }
00288 
00289       ast_frfree(inf);
00290    }
00291 
00292 
00293    /*** restore audio codecs if necessary */
00294    if (original_read_fmt != AST_FORMAT_SLINEAR) {
00295       if (ast_set_read_format(chan, original_read_fmt) < 0) {
00296          ast_log(LOG_WARNING, "Unable to restore read mode.\n");
00297       }
00298    }
00299    if (original_write_fmt != AST_FORMAT_SLINEAR) {
00300       if (ast_set_write_format(chan, original_write_fmt) < 0) {
00301          ast_log(LOG_WARNING, "Unable to restore write mode.\n");
00302       }
00303    }
00304 
00305 
00306    coeff_sin = (total_samples) ? (sum_sin * 2.0 / ((1 << 15) - 1) / total_samples) : 0.0;
00307    coeff_cos = (total_samples) ? (sum_cos * 2.0 / ((1 << 15) - 1) / total_samples) : 0.0;
00308    amplitude = sqrt(coeff_sin * coeff_sin + coeff_cos * coeff_cos);
00309 
00310    sprintf(linebuf, "%lg", amplitude);
00311    pbx_builtin_setvar_helper(chan, "mwa_amplitude", linebuf);
00312    sprintf(linebuf, "%lg", (duration) ? (total_ripple / duration) : 0.0);
00313    pbx_builtin_setvar_helper(chan, "mwa_ripple", linebuf);
00314    sprintf(linebuf, "%d", total_bad_timeslices);
00315    pbx_builtin_setvar_helper(chan, "mwa_bad_timeslices", linebuf);
00316 
00317    ast_module_user_remove(u);
00318    free(periods_in_timeslice);
00319    free(avg_period);
00320    free(lastperiod);
00321    free(tone);
00322    free(args);
00323    return res;
00324 }

static int unload_module ( void   )  [static]

Definition at line 327 of file app_mwanalyze.c.

References app, ast_module_user_hangup_all, and ast_unregister_application().

00328 {
00329    int res;
00330 
00331    res = ast_unregister_application(app);
00332 
00333    ast_module_user_hangup_all();
00334 
00335    return res;
00336 }


Variable Documentation

char* app = "Mwanalyze" [static]

Definition at line 32 of file app_mwanalyze.c.

char* synopsis = "Spectral analyses based on a given frequency (slin)" [static]

Definition at line 33 of file app_mwanalyze.c.

char* tdescription [static]

Definition at line 34 of file app_mwanalyze.c.

Referenced by load_module().


Generated on Fri Aug 24 02:22:46 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1