FreeSWITCH API Documentation  1.7.0
libteletone_generate.c
Go to the documentation of this file.
1 /*
2  * libteletone
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is libteletone
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  *
28  *
29  * libteletone.c -- Tone Generator
30  *
31  *
32  *
33  * Exception:
34  * The author hereby grants the use of this source code under the
35  * following license if and only if the source code is distributed
36  * as part of the OpenZAP or FreeTDM library. Any use or distribution of this
37  * source code outside the scope of the OpenZAP or FreeTDM library will nullify the
38  * following license and reinact the MPL 1.1 as stated above.
39  *
40  * Copyright (c) 2007, Anthony Minessale II
41  * All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  *
47  * * Redistributions of source code must retain the above copyright
48  * notice, this list of conditions and the following disclaimer.
49  *
50  * * Redistributions in binary form must reproduce the above copyright
51  * notice, this list of conditions and the following disclaimer in the
52  * documentation and/or other materials provided with the distribution.
53  *
54  * * Neither the name of the original author; nor the names of any contributors
55  * may be used to endorse or promote products derived from this software
56  * without specific prior written permission.
57  *
58  *
59  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
60  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
61  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
62  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
63  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
64  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
65  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
66  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
67  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
68  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
69  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70  */
71 
72 #include <libteletone.h>
73 
74 #define SMAX 32767
75 #define SMIN -32768
76 #define normalize_to_16bit(n) if (n > SMAX) n = SMAX; else if (n < SMIN) n = SMIN;
77 
78 #ifdef _MSC_VER
79 #pragma warning(disable:4706)
80 #endif
81 
83  0x00c9, 0x025b, 0x03ed, 0x057f, 0x0711, 0x08a2, 0x0a33, 0x0bc4,
84  0x0d54, 0x0ee4, 0x1073, 0x1201, 0x138f, 0x151c, 0x16a8, 0x1833,
85  0x19be, 0x1b47, 0x1cd0, 0x1e57, 0x1fdd, 0x2162, 0x22e5, 0x2467,
86  0x25e8, 0x2768, 0x28e5, 0x2a62, 0x2bdc, 0x2d55, 0x2ecc, 0x3042,
87  0x31b5, 0x3327, 0x3497, 0x3604, 0x3770, 0x38d9, 0x3a40, 0x3ba5,
88  0x3d08, 0x3e68, 0x3fc6, 0x4121, 0x427a, 0x43d1, 0x4524, 0x4675,
89  0x47c4, 0x490f, 0x4a58, 0x4b9e, 0x4ce1, 0x4e21, 0x4f5e, 0x5098,
90  0x51cf, 0x5303, 0x5433, 0x5560, 0x568a, 0x57b1, 0x58d4, 0x59f4,
91  0x5b10, 0x5c29, 0x5d3e, 0x5e50, 0x5f5e, 0x6068, 0x616f, 0x6272,
92  0x6371, 0x646c, 0x6564, 0x6657, 0x6747, 0x6832, 0x691a, 0x69fd,
93  0x6add, 0x6bb8, 0x6c8f, 0x6d62, 0x6e31, 0x6efb, 0x6fc2, 0x7083,
94  0x7141, 0x71fa, 0x72af, 0x735f, 0x740b, 0x74b3, 0x7556, 0x75f4,
95  0x768e, 0x7723, 0x77b4, 0x7840, 0x78c8, 0x794a, 0x79c9, 0x7a42,
96  0x7ab7, 0x7b27, 0x7b92, 0x7bf9, 0x7c5a, 0x7cb7, 0x7d0f, 0x7d63,
97  0x7db1, 0x7dfb, 0x7e3f, 0x7e7f, 0x7eba, 0x7ef0, 0x7f22, 0x7f4e,
98  0x7f75, 0x7f98, 0x7fb5, 0x7fce, 0x7fe2, 0x7ff1, 0x7ffa, 0x7fff
99 };
100 
101 
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 }
117 
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 }
133 
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 }
176 
178 {
179  if (ts->buffer) {
180  free(ts->buffer);
181  ts->buffer = NULL;
182  ts->samples = 0;
183  }
184  return 0;
185 }
186 
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 }
205 
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 }
307 
308 /* don't ask */
309 static char *my_strdup (const char *s)
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 }
320 
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 }
497 
498 /* For Emacs:
499  * Local Variables:
500  * mode:c
501  * indent-tabs-mode:t
502  * tab-width:4
503  * c-basic-offset:4
504  * End:
505  * For VIM:
506  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
507  */
#define TELETONE_API_DATA
Definition: libteletone.h:135
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
An abstraction to store a tone mapping.
Definition: libteletone.h:93
static char * my_strdup(const char *s)
double teletone_process_t
Definition: libteletone.h:84
int teletone_mux_tones(teletone_generation_session_t *ts, teletone_tone_map_t *map)
Execute a single tone generation instruction.
int teletone_destroy_session(teletone_generation_session_t *ts)
Free the buffer allocated by a tone generation session.
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_API(type)
Definition: libteletone.h:133
pack cur
int teletone_run(teletone_generation_session_t *ts, const char *cmd)
Execute a tone generation script and call callbacks after each instruction.
#define TELETONE_VOL_DB_MIN
int teletone_init_session(teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data)
Initilize a tone generation session.
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
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.
static int ensure_buffer(teletone_generation_session_t *ts, int need)
switch_byte_t switch_byte_t uint32_t buflen
Top level include file.
int16_t teletone_audio_t
#define TELETONE_TONE_RANGE
Definition: libteletone.h:82
An abstraction to store a tone generation session.
int(* tone_handler)(struct teletone_generation_session *ts, teletone_tone_map_t *map)
int teletone_set_map(teletone_tone_map_t *map,...)
Assign a set of tones to a single tone map.
#define SINE_TABLE_MAX
memset(buf, 0, buflen)
int16_t TELETONE_SINES[SINE_TABLE_MAX]