#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 PI (4*atan(1)) |
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.
00339 { 00340 return ast_register_application(app, mwanalyze_exec, synopsis, tdescription); 00341 }
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 }
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] |