FreeSWITCH API Documentation  1.7.0
Macros | Functions | Variables
libteletone_generate.c File Reference
#include <libteletone.h>
+ Include dependency graph for libteletone_generate.c:

Go to the source code of this file.

Macros

#define SMAX   32767
 
#define SMIN   -32768
 
#define normalize_to_16bit(n)   if (n > SMAX) n = SMAX; else if (n < SMIN) n = SMIN;
 

Functions

int teletone_set_tone (teletone_generation_session_t *ts, int index,...)
 Assign a set of tones to a tone_session indexed by a paticular index/character. More...
 
int teletone_set_map (teletone_tone_map_t *map,...)
 Assign a set of tones to a single tone map. More...
 
int teletone_init_session (teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data)
 Initilize a tone generation session. More...
 
int teletone_destroy_session (teletone_generation_session_t *ts)
 Free the buffer allocated by a tone generation session. More...
 
static int ensure_buffer (teletone_generation_session_t *ts, int need)
 
int teletone_mux_tones (teletone_generation_session_t *ts, teletone_tone_map_t *map)
 Execute a single tone generation instruction. More...
 
static char * my_strdup (const char *s)
 
int teletone_run (teletone_generation_session_t *ts, const char *cmd)
 Execute a tone generation script and call callbacks after each instruction. More...
 

Variables

int16_t TELETONE_SINES [SINE_TABLE_MAX]
 

Macro Definition Documentation

#define normalize_to_16bit (   n)    if (n > SMAX) n = SMAX; else if (n < SMIN) n = SMIN;

Definition at line 76 of file libteletone_generate.c.

#define SMAX   32767

Definition at line 74 of file libteletone_generate.c.

#define SMIN   -32768

Definition at line 75 of file libteletone_generate.c.

Function Documentation

static int ensure_buffer ( teletone_generation_session_t ts,
int  need 
)
static

Definition at line 187 of file libteletone_generate.c.

References teletone_generation_session::buffer, teletone_generation_session::channels, teletone_generation_session::datalen, teletone_generation_session::dynamic, and teletone_generation_session::samples.

Referenced by teletone_mux_tones().

188 {
189  need += ts->samples;
190  need *= sizeof(teletone_audio_t);
191  need *= ts->channels;
192 
193  if (need > ts->datalen) {
194  teletone_audio_t *tmp;
195  ts->datalen = need + ts->dynamic;
196  tmp = realloc(ts->buffer, ts->datalen);
197  if (!tmp) {
198  return -1;
199  }
200  ts->buffer = tmp;
201  }
202 
203  return 0;
204 }
int16_t teletone_audio_t
static char* my_strdup ( const char *  s)
static

Definition at line 309 of file libteletone_generate.c.

Referenced by teletone_run().

310 {
311  size_t len = strlen (s) + 1;
312  void *new = malloc (len);
313 
314  if (new == NULL) {
315  return NULL;
316  }
317 
318  return (char *) memcpy (new, s, len);
319 }
int teletone_destroy_session ( teletone_generation_session_t ts)

Free the buffer allocated by a tone generation session.

Parameters
tsthe tone generation session to destroy
Returns
0

Definition at line 177 of file libteletone_generate.c.

Referenced by inband_dtmf_generate_callback(), main(), setup_ringback(), switch_ivr_gentones(), switch_ivr_originate(), and switch_ivr_wait_for_answer().

178 {
179  if (ts->buffer) {
180  free(ts->buffer);
181  ts->buffer = NULL;
182  ts->samples = 0;
183  }
184  return 0;
185 }
int teletone_init_session ( teletone_generation_session_t ts,
int  buflen,
tone_handler  handler,
void *  user_data 
)

Initilize a tone generation session.

Parameters
tsthe tone generation session to initilize
buflenthe size of the buffer(in samples) to dynamically allocate
handlera callback function to execute when a tone generation instruction is complete
user_dataoptional user data to send
Returns
0

Definition at line 134 of file libteletone_generate.c.

References buflen, memset(), and teletone_set_tone().

Referenced by inband_dtmf_generate_callback(), main(), setup_ringback(), switch_ivr_gentones(), and switch_ivr_wait_for_answer().

135 {
136  memset(ts, 0, sizeof(*ts));
137  ts->rate = 8000;
138  ts->channels = 1;
139  ts->duration = 2000;
140  ts->wait = 500;
141  ts->tmp_duration = -1;
142  ts->tmp_wait = -1;
143  ts->handler = handler;
144  ts->user_data = user_data;
145  ts->volume = -7;
146  ts->decay_step = 0;
147  ts->decay_factor = 1;
148  if (buflen) {
149  if ((ts->buffer = calloc(buflen, sizeof(teletone_audio_t))) == 0) {
150  return -1;
151  }
152  ts->datalen = buflen;
153  } else {
154  ts->dynamic = 1024;
155  }
156  /* Add Standard DTMF Tones */
157  teletone_set_tone(ts, '1', 697.0, 1209.0, 0.0);
158  teletone_set_tone(ts, '2', 697.0, 1336.0, 0.0);
159  teletone_set_tone(ts, '3', 697.0, 1477.0, 0.0);
160  teletone_set_tone(ts, 'A', 697.0, 1633.0, 0.0);
161  teletone_set_tone(ts, '4', 770.0, 1209.0, 0.0);
162  teletone_set_tone(ts, '5', 770.0, 1336.0, 0.0);
163  teletone_set_tone(ts, '6', 770.0, 1477.0, 0.0);
164  teletone_set_tone(ts, 'B', 770.0, 1633.0, 0.0);
165  teletone_set_tone(ts, '7', 859.0, 1209.0, 0.0);
166  teletone_set_tone(ts, '8', 859.0, 1336.0, 0.0);
167  teletone_set_tone(ts, '9', 859.0, 1477.0, 0.0);
168  teletone_set_tone(ts, 'C', 859.0, 1633.0, 0.0);
169  teletone_set_tone(ts, '*', 941.0, 1209.0, 0.0);
170  teletone_set_tone(ts, '0', 941.0, 1336.0, 0.0);
171  teletone_set_tone(ts, '#', 941.0, 1477.0, 0.0);
172  teletone_set_tone(ts, 'D', 941.0, 1633.0, 0.0);
173 
174  return 0;
175 }
int teletone_set_tone(teletone_generation_session_t *ts, int index,...)
Assign a set of tones to a tone_session indexed by a paticular index/character.
switch_byte_t switch_byte_t uint32_t buflen
int16_t teletone_audio_t
memset(buf, 0, buflen)
int teletone_mux_tones ( teletone_generation_session_t ts,
teletone_tone_map_t map 
)

Execute a single tone generation instruction.

Parameters
tsthe tone generation session to consult for parameters
mapthe tone mapping to use for the frequencies
Returns
0

Definition at line 206 of file libteletone_generate.c.

References ensure_buffer(), memset(), teletone_dds_state_modulate_sample(), teletone_dds_state_set_tone(), teletone_dds_state_set_tx_level(), TELETONE_MAX_TONES, and TELETONE_VOL_DB_MIN.

Referenced by teletone_dtmf_generate_handler(), and teletone_handler().

207 {
208  /*teletone_process_t period = (1.0 / ts->rate) / ts->channels;*/
209  int i, c;
210  int freqlen = 0;
212  //int decay = 0;
213  int duration;
214  int wait = 0;
215  int32_t sample;
216  int32_t dc = 0;
217  float vol = ts->volume;
218  ts->samples = 0;
219  memset(tones, 0, sizeof(tones[0]) * TELETONE_MAX_TONES);
220  duration = (ts->tmp_duration > -1) ? ts->tmp_duration : ts->duration;
221  wait = (ts->tmp_wait > -1) ? ts->tmp_wait : ts->wait;
222 
223  if (map->freqs[0] > 0) {
224  for (freqlen = 0; freqlen < TELETONE_MAX_TONES && map->freqs[freqlen]; freqlen++) {
225  teletone_dds_state_set_tone(&tones[freqlen], map->freqs[freqlen], ts->rate, 0);
226  teletone_dds_state_set_tx_level(&tones[freqlen], vol);
227  }
228 
229  if (ts->channels > 1) {
230  duration *= ts->channels;
231  }
232 
233  if (ts->dynamic) {
234  if (ensure_buffer(ts, duration)) {
235  return -1;
236  }
237  }
238 
239  for (ts->samples = 0; ts->samples < ts->datalen && ts->samples < duration; ts->samples++) {
240  if (ts->decay_direction && ++dc >= ts->decay_step) {
241  float nvol = vol + ts->decay_direction * ts->decay_factor;
242  int j;
243 
244  if (nvol <= TELETONE_VOL_DB_MAX && nvol >= TELETONE_VOL_DB_MIN) {
245  vol = nvol;
246  for (j = 0; j < TELETONE_MAX_TONES && map->freqs[j]; j++) {
247  teletone_dds_state_set_tx_level(&tones[j], vol);
248  }
249  dc = 0;
250  }
251  }
252 
253  sample = 128;
254 
255  for (i = 0; i < freqlen; i++) {
256  int32_t s = teletone_dds_state_modulate_sample(&tones[i], 0);
257  sample += s;
258  }
259  sample /= freqlen;
260  ts->buffer[ts->samples] = (teletone_audio_t)sample;
261 
262  for (c = 1; c < ts->channels; c++) {
263  ts->buffer[ts->samples+1] = ts->buffer[ts->samples];
264  ts->samples++;
265  }
266 
267  }
268  }
269  if (ts->dynamic) {
270  if (ensure_buffer(ts, wait)) {
271  return -1;
272  }
273  }
274  for (c = 0; c < ts->channels; c++) {
275  for (i = 0; i < wait && ts->samples < ts->datalen; i++) {
276  ts->buffer[ts->samples++] = 0;
277  }
278  }
279 
280  if (ts->debug && ts->debug_stream) {
281  if (map->freqs[0] <= 0) {
282  fprintf(ts->debug_stream, "wait %d (%dms)\n", wait, wait / (ts->rate / 1000));
283  } else {
284  fprintf(ts->debug_stream, "Generate: (");
285 
286  for (i = 0; i < TELETONE_MAX_TONES && map->freqs[i]; i++) {
287  fprintf(ts->debug_stream, "%s%0.2f", i == 0 ? "" : "+",map->freqs[i]);
288  }
289 
290  fprintf(ts->debug_stream,
291  ") [volume %0.2fdB; samples %d(%dms) x %d channel%s; wait %d(%dms); decay_factor %0.2fdB; decay_step %d(%dms); wrote %d bytes]\n",
292  ts->volume,
293  duration,
294  duration / (ts->rate / 1000),
295  ts->channels,
296  ts->channels == 1 ? "" : "s",
297  wait,
298  wait / (ts->rate / 1000),
299  ts->decay_factor,
300  ts->decay_step,
301  ts->decay_step / (ts->rate / 1000),
302  ts->samples * 2);
303  }
304  }
305  return ts->samples / ts->channels;
306 }
static __inline__ int16_t teletone_dds_state_modulate_sample(teletone_dds_state_t *dds, uint32_t pindex)
#define TELETONE_MAX_TONES
Definition: libteletone.h:81
static __inline__ int teletone_dds_state_set_tone(teletone_dds_state_t *dds, teletone_process_t tone, uint32_t rate, uint32_t pindex)
#define TELETONE_VOL_DB_MIN
static __inline__ void teletone_dds_state_set_tx_level(teletone_dds_state_t *dds, float tx_level)
teletone_process_t freqs[TELETONE_MAX_TONES]
Definition: libteletone.h:95
static int ensure_buffer(teletone_generation_session_t *ts, int need)
int16_t teletone_audio_t
memset(buf, 0, buflen)
int teletone_run ( teletone_generation_session_t ts,
const char *  cmd 
)

Execute a tone generation script and call callbacks after each instruction.

Parameters
tsthe tone generation session to execute on
cmdthe script to execute
Returns
0

Definition at line 321 of file libteletone_generate.c.

References cur, teletone_tone_map_t::freqs, memset(), my_strdup(), TELETONE_MAX_TONES, TELETONE_TONE_RANGE, and TELETONE_VOL_DB_MIN.

Referenced by inband_dtmf_generate_callback(), main(), setup_ringback(), switch_ivr_gentones(), and switch_ivr_wait_for_answer().

322 {
323  char *data = NULL, *cur = NULL, *end = NULL;
324  int LOOPING = 0;
325 
326  if (!cmd) {
327  return -1;
328  }
329 
330  do {
331  if (!(data = my_strdup(cmd))) {
332  return -1;
333  }
334 
335  cur = data;
336 
337  while (*cur) {
338  if (*cur == ' ' || *cur == '\r' || *cur == '\n') {
339  cur++;
340  continue;
341  }
342 
343  if ((end = strchr(cur, ';')) != 0) {
344  *end++ = '\0';
345  }
346 
347  if (*(cur + 1) == '=') {
348  switch(*cur) {
349  case 'c':
350  ts->channels = atoi(cur + 2);
351  break;
352  case 'r':
353  ts->rate = atoi(cur + 2);
354  break;
355  case 'd':
356  ts->duration = atoi(cur + 2) * (ts->rate / 1000);
357  break;
358  case 'v':
359  {
360  float vol = (float)atof(cur + 2);
361  if (vol <= TELETONE_VOL_DB_MAX && vol >= TELETONE_VOL_DB_MIN) {
362  ts->volume = vol;
363  }
364  }
365  break;
366  case '>':
367  ts->decay_step = atoi(cur + 2) * (ts->rate / 1000);
368  ts->decay_direction = -1;
369  break;
370  case '<':
371  ts->decay_step = atoi(cur + 2) * (ts->rate / 1000);
372  ts->decay_direction = 1;
373  break;
374  case '+':
375  ts->decay_factor = (float)atof(cur + 2);
376  break;
377  case 'w':
378  ts->wait = atoi(cur + 2) * (ts->rate / 1000);
379  break;
380  case 'l':
381  ts->loops = atoi(cur + 2);
382  break;
383  case 'L':
384  if (!LOOPING) {
385  int L;
386  if ((L = atoi(cur + 2)) > 0) {
387  ts->LOOPS = L;
388  LOOPING++;
389  }
390  }
391  break;
392  }
393  } else {
394  while (*cur) {
395  char *p = NULL, *e = NULL;
396  teletone_tone_map_t mymap, *mapp = NULL;
397 
398  if (*cur == ' ' || *cur == '\r' || *cur == '\n') {
399  cur++;
400  continue;
401  }
402 
403  ts->tmp_duration = -1;
404  ts->tmp_wait = -1;
405 
406  memset(&mymap, 0, sizeof(mymap));
407 
408  if (*(cur + 1) == '(') {
409  p = cur + 2;
410  if (*cur) {
411  char *next;
412  int i = 0;
413  if ((e = strchr(p, ')')) != 0) {
414  *e++ = '\0';
415  }
416  do {
417 #if (_MSC_VER == 1600)
418  if (!p) {
419  break;
420  }
421 #endif
422  if ((next = strchr(p, ',')) != 0) {
423  *next++ = '\0';
424  }
425  if (i == 0) {
426  ts->tmp_duration = atoi(p) * (ts->rate / 1000);
427  i++;
428  } else if (i == 1) {
429  ts->tmp_wait = atoi(p) * (ts->rate / 1000);
430  i++;
431  } else {
432  mymap.freqs[i++ - 2] = atof(p);
433  }
434  p = next;
435 
436  } while (next && (i-2) < TELETONE_MAX_TONES);
437  if (i > 2 && *cur == '%') {
438  mapp = &mymap;
439  } else if ((i != 2 || *cur == '%')) {
440  if (ts->debug && ts->debug_stream) {
441  fprintf(ts->debug_stream, "Syntax Error!\n");
442  }
443  goto bottom;
444  }
445  }
446  }
447 
448  if (*cur && !mapp) {
449  if (*cur > 0 && *cur < TELETONE_TONE_RANGE) {
450  mapp = &ts->TONES[(int)*cur];
451  } else if (ts->debug && ts->debug_stream) {
452  fprintf(ts->debug_stream, "Map [%c] Out Of Range!\n", *cur);
453  }
454  }
455 
456  if (mapp) {
457  if (mapp->freqs[0]) {
458  if (ts->handler) {
459  do {
460  ts->handler(ts, mapp);
461  if (ts->loops > 0) {
462  ts->loops--;
463  }
464  } while (ts->loops);
465  }
466  } else if (ts->debug && ts->debug_stream) {
467  fprintf(ts->debug_stream, "Ignoring Empty Map [%c]!\n", *cur);
468  }
469  }
470 
471  if (e) {
472  cur = e;
473  } else {
474  cur++;
475  }
476  }
477  }
478 
479  if (end) {
480  cur = end;
481  } else if (*cur){
482  cur++;
483  }
484  }
485  bottom:
486  free(data);
487  data = NULL;
488 
489  if (ts->LOOPS > 0) {
490  ts->LOOPS--;
491  }
492 
493  } while (ts->LOOPS);
494 
495  return 0;
496 }
#define TELETONE_MAX_TONES
Definition: libteletone.h:81
An abstraction to store a tone mapping.
Definition: libteletone.h:93
static char * my_strdup(const char *s)
pack cur
teletone_tone_map_t TONES[TELETONE_TONE_RANGE]
#define TELETONE_VOL_DB_MIN
teletone_process_t freqs[TELETONE_MAX_TONES]
Definition: libteletone.h:95
#define TELETONE_TONE_RANGE
Definition: libteletone.h:82
memset(buf, 0, buflen)
int teletone_set_map ( teletone_tone_map_t map,
  ... 
)

Assign a set of tones to a single tone map.

Parameters
mapthe map to assign the tones to
...up to TELETONE_MAX_TONES frequencies terminated by 0.0
Returns
0

Definition at line 118 of file libteletone_generate.c.

References TELETONE_MAX_TONES.

119 {
120  va_list ap;
121  int i = 0;
122  teletone_process_t x = 0;
123 
124  va_start(ap, map);
125  while (i < TELETONE_MAX_TONES && (x = va_arg(ap, teletone_process_t))) {
126  map->freqs[i++] = x;
127  }
128  va_end(ap);
129 
130  return (i > TELETONE_MAX_TONES) ? -1 : 0;
131 
132 }
#define TELETONE_MAX_TONES
Definition: libteletone.h:81
double teletone_process_t
Definition: libteletone.h:84
teletone_process_t freqs[TELETONE_MAX_TONES]
Definition: libteletone.h:95
int teletone_set_tone ( teletone_generation_session_t ts,
int  index,
  ... 
)

Assign a set of tones to a tone_session indexed by a paticular index/character.

Parameters
tsthe tone generation session
indexthe index to map the tone to
...up to TELETONE_MAX_TONES frequencies terminated by 0.0
Returns
0

Definition at line 102 of file libteletone_generate.c.

References TELETONE_MAX_TONES.

Referenced by teletone_init_session().

103 {
104  va_list ap;
105  int i = 0;
106  teletone_process_t x = 0;
107 
108  va_start(ap, index);
109  while (i < TELETONE_MAX_TONES && (x = va_arg(ap, teletone_process_t))) {
110  ts->TONES[index].freqs[i++] = x;
111  }
112  va_end(ap);
113 
114  return (i > TELETONE_MAX_TONES) ? -1 : 0;
115 
116 }
#define TELETONE_MAX_TONES
Definition: libteletone.h:81
double teletone_process_t
Definition: libteletone.h:84
teletone_tone_map_t TONES[TELETONE_TONE_RANGE]
teletone_process_t freqs[TELETONE_MAX_TONES]
Definition: libteletone.h:95

Variable Documentation

int16_t TELETONE_SINES[SINE_TABLE_MAX]
Initial value:
= {
0x00c9, 0x025b, 0x03ed, 0x057f, 0x0711, 0x08a2, 0x0a33, 0x0bc4,
0x0d54, 0x0ee4, 0x1073, 0x1201, 0x138f, 0x151c, 0x16a8, 0x1833,
0x19be, 0x1b47, 0x1cd0, 0x1e57, 0x1fdd, 0x2162, 0x22e5, 0x2467,
0x25e8, 0x2768, 0x28e5, 0x2a62, 0x2bdc, 0x2d55, 0x2ecc, 0x3042,
0x31b5, 0x3327, 0x3497, 0x3604, 0x3770, 0x38d9, 0x3a40, 0x3ba5,
0x3d08, 0x3e68, 0x3fc6, 0x4121, 0x427a, 0x43d1, 0x4524, 0x4675,
0x47c4, 0x490f, 0x4a58, 0x4b9e, 0x4ce1, 0x4e21, 0x4f5e, 0x5098,
0x51cf, 0x5303, 0x5433, 0x5560, 0x568a, 0x57b1, 0x58d4, 0x59f4,
0x5b10, 0x5c29, 0x5d3e, 0x5e50, 0x5f5e, 0x6068, 0x616f, 0x6272,
0x6371, 0x646c, 0x6564, 0x6657, 0x6747, 0x6832, 0x691a, 0x69fd,
0x6add, 0x6bb8, 0x6c8f, 0x6d62, 0x6e31, 0x6efb, 0x6fc2, 0x7083,
0x7141, 0x71fa, 0x72af, 0x735f, 0x740b, 0x74b3, 0x7556, 0x75f4,
0x768e, 0x7723, 0x77b4, 0x7840, 0x78c8, 0x794a, 0x79c9, 0x7a42,
0x7ab7, 0x7b27, 0x7b92, 0x7bf9, 0x7c5a, 0x7cb7, 0x7d0f, 0x7d63,
0x7db1, 0x7dfb, 0x7e3f, 0x7e7f, 0x7eba, 0x7ef0, 0x7f22, 0x7f4e,
0x7f75, 0x7f98, 0x7fb5, 0x7fce, 0x7fe2, 0x7ff1, 0x7ffa, 0x7fff
}

Definition at line 82 of file libteletone_generate.c.

Referenced by teletone_dds_state_modulate_sample().