RTS API Documentation  1.10.11
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;
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 
219  ts->samples = 0;
220  memset(tones, 0, sizeof(tones[0]) * TELETONE_MAX_TONES);
221  duration = (ts->tmp_duration > -1) ? ts->tmp_duration : ts->duration;
222  wait = (ts->tmp_wait > -1) ? ts->tmp_wait : ts->wait;
223 
224  if (map->freqs[0] > 0) {
225  for (freqlen = 0; freqlen < TELETONE_MAX_TONES && map->freqs[freqlen]; freqlen++) {
226  teletone_dds_state_set_tone(&tones[freqlen], map->freqs[freqlen], ts->rate, 0);
227  teletone_dds_state_set_tx_level(&tones[freqlen], vol);
228  }
229 
230  if (ts->dynamic) {
231  if (ensure_buffer(ts, duration * ts->channels)) {
232  return -1;
233  }
234  }
235 
236  for (ts->samples = 0; ts->samples < ts->datalen && ts->samples < duration; ts->samples++) {
237  if (ts->decay_direction && ++dc >= ts->decay_step) {
238  float nvol = vol + ts->decay_direction * ts->decay_factor;
239  int j;
240 
241  if (nvol <= TELETONE_VOL_DB_MAX && nvol >= TELETONE_VOL_DB_MIN) {
242  vol = nvol;
243  for (j = 0; j < TELETONE_MAX_TONES && map->freqs[j]; j++) {
244  teletone_dds_state_set_tx_level(&tones[j], vol);
245  }
246  dc = 0;
247  }
248  }
249 
250  sample = 128;
251 
252  for (i = 0; i < freqlen; i++) {
253  int32_t s = teletone_dds_state_modulate_sample(&tones[i], 0);
254  sample += s;
255  }
256  if (freqlen) {
257  sample /= freqlen;
258  }
259  ts->buffer[ts->samples] = (teletone_audio_t)sample;
260  }
261  }
262 
263  if (ts->dynamic) {
264  if (ensure_buffer(ts, wait * ts->channels)) {
265  return -1;
266  }
267  }
268 
269  for (i = 0; i < wait && ts->samples < ts->datalen; i++) {
270  ts->buffer[ts->samples++] = 0;
271  }
272 
273  if (ts->debug && ts->debug_stream) {
274  if (map->freqs[0] <= 0) {
275  fprintf(ts->debug_stream, "wait %d (%dms)\n", wait, wait / (ts->rate / 1000));
276  } else {
277  fprintf(ts->debug_stream, "Generate: (");
278 
279  for (i = 0; i < TELETONE_MAX_TONES && map->freqs[i]; i++) {
280  fprintf(ts->debug_stream, "%s%0.2f", i == 0 ? "" : "+",map->freqs[i]);
281  }
282 
283  fprintf(ts->debug_stream,
284  ") [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",
285  ts->volume,
286  duration,
287  duration / (ts->rate / 1000),
288  ts->channels,
289  ts->channels == 1 ? "" : "s",
290  wait,
291  wait / (ts->rate / 1000),
292  ts->decay_factor,
293  ts->decay_step,
294  ts->decay_step / (ts->rate / 1000),
295  ts->samples * 2);
296  }
297  }
298  return ts->samples;
299 }
300 
301 /* don't ask */
302 static char *my_strdup (const char *s)
303 {
304  size_t len = strlen (s) + 1;
305  void *new = malloc (len);
306 
307  if (new == NULL) {
308  return NULL;
309  }
310 
311  return (char *) memcpy (new, s, len);
312 }
313 
315 {
316  char *data = NULL, *cur = NULL, *end = NULL;
317  int LOOPING = 0;
318 
319  if (!cmd) {
320  return -1;
321  }
322 
323  do {
324  if (!(data = my_strdup(cmd))) {
325  return -1;
326  }
327 
328  cur = data;
329 
330  while (*cur) {
331  if (*cur == ' ' || *cur == '\r' || *cur == '\n') {
332  cur++;
333  continue;
334  }
335 
336  if ((end = strchr(cur, ';')) != 0) {
337  *end++ = '\0';
338  }
339 
340  if (*(cur + 1) == '=') {
341  switch(*cur) {
342  case 'c':
343  ts->channels = atoi(cur + 2);
344  break;
345  case 'r':
346  ts->rate = atoi(cur + 2);
347  break;
348  case 'd':
349  ts->duration = atoi(cur + 2) * (ts->rate / 1000);
350  break;
351  case 'v':
352  {
353  float vol = (float)atof(cur + 2);
354  if (vol <= TELETONE_VOL_DB_MAX && vol >= TELETONE_VOL_DB_MIN) {
355  ts->volume = vol;
356  }
357  }
358  break;
359  case '>':
360  ts->decay_step = atoi(cur + 2) * (ts->rate / 1000);
361  ts->decay_direction = -1;
362  break;
363  case '<':
364  ts->decay_step = atoi(cur + 2) * (ts->rate / 1000);
365  ts->decay_direction = 1;
366  break;
367  case '+':
368  ts->decay_factor = (float)atof(cur + 2);
369  break;
370  case 'w':
371  ts->wait = atoi(cur + 2) * (ts->rate / 1000);
372  break;
373  case 'l':
374  ts->loops = atoi(cur + 2);
375  break;
376  case 'L':
377  if (!LOOPING) {
378  int L;
379  if ((L = atoi(cur + 2)) > 0) {
380  ts->LOOPS = L;
381  LOOPING++;
382  }
383  }
384  break;
385  }
386  } else {
387  while (*cur) {
388  char *p = NULL, *e = NULL;
389  teletone_tone_map_t mymap, *mapp = NULL;
390 
391  if (*cur == ' ' || *cur == '\r' || *cur == '\n') {
392  cur++;
393  continue;
394  }
395 
396  ts->tmp_duration = -1;
397  ts->tmp_wait = -1;
398 
399  memset(&mymap, 0, sizeof(mymap));
400 
401  if (*(cur + 1) == '(') {
402  p = cur + 2;
403  if (*cur) {
404  char *next;
405  int i = 0;
406  if ((e = strchr(p, ')')) != 0) {
407  *e++ = '\0';
408  }
409  do {
410 #if (_MSC_VER == 1600)
411  if (!p) {
412  break;
413  }
414 #endif
415  if ((next = strchr(p, ',')) != 0) {
416  *next++ = '\0';
417  }
418  if (i == 0) {
419  ts->tmp_duration = atoi(p) * (ts->rate / 1000);
420  i++;
421  } else if (i == 1) {
422  ts->tmp_wait = atoi(p) * (ts->rate / 1000);
423  i++;
424  } else {
425  mymap.freqs[i++ - 2] = atof(p);
426  }
427  p = next;
428 
429  } while (next && (i-2) < TELETONE_MAX_TONES);
430  if (i > 2 && *cur == '%') {
431  mapp = &mymap;
432  } else if ((i != 2 || *cur == '%')) {
433  if (ts->debug && ts->debug_stream) {
434  fprintf(ts->debug_stream, "Syntax Error!\n");
435  }
436  goto bottom;
437  }
438  }
439  }
440 
441  if (*cur && !mapp) {
442  if (*cur > 0 && *cur < TELETONE_TONE_RANGE) {
443  mapp = &ts->TONES[(int)*cur];
444  } else if (ts->debug && ts->debug_stream) {
445  fprintf(ts->debug_stream, "Map [%c] Out Of Range!\n", *cur);
446  }
447  }
448 
449  if (mapp) {
450  if (mapp->freqs[0]) {
451  if (ts->handler) {
452  do {
453  ts->handler(ts, mapp);
454  if (ts->loops > 0) {
455  ts->loops--;
456  }
457  } while (ts->loops);
458  }
459  } else if (ts->debug && ts->debug_stream) {
460  fprintf(ts->debug_stream, "Ignoring Empty Map [%c]!\n", *cur);
461  }
462  }
463 
464  if (e) {
465  cur = e;
466  } else {
467  cur++;
468  }
469  }
470  }
471 
472  if (end) {
473  cur = end;
474  } else if (*cur){
475  cur++;
476  }
477  }
478  bottom:
479  free(data);
480  data = NULL;
481 
482  if (ts->LOOPS > 0) {
483  ts->LOOPS--;
484  }
485 
486  } while (ts->LOOPS);
487 
488  return 0;
489 }
490 
491 /* For Emacs:
492  * Local Variables:
493  * mode:c
494  * indent-tabs-mode:t
495  * tab-width:4
496  * c-basic-offset:4
497  * End:
498  * For VIM:
499  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
500  */
#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
teletone_tone_map_t TONES[TELETONE_TONE_RANGE]
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.
int index
Definition: switch_cJSON.h:160
static int ensure_buffer(teletone_generation_session_t *ts, int need)
switch_byte_t switch_byte_t uint32_t buflen
Top level include file.
int(* tone_handler)(struct teletone_generation_session *ts, teletone_tone_map_t *map)
int16_t teletone_audio_t
#define TELETONE_TONE_RANGE
Definition: libteletone.h:82
An abstraction to store a tone generation session.
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]