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 
82 TELETONE_API_DATA int16_t TELETONE_SINES[SINE_TABLE_MAX] = {
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 
teletone_set_tone(teletone_generation_session_t * ts,int index,...)102 TELETONE_API(int) teletone_set_tone(teletone_generation_session_t *ts, int index, ...)
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 
teletone_set_map(teletone_tone_map_t * map,...)118 TELETONE_API(int) teletone_set_map(teletone_tone_map_t *map, ...)
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 
teletone_init_session(teletone_generation_session_t * ts,int buflen,tone_handler handler,void * user_data)134 TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data)
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 
teletone_destroy_session(teletone_generation_session_t * ts)177 TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts)
178 {
179 	if (ts->buffer) {
180 		free(ts->buffer);
181 		ts->buffer = NULL;
182 		ts->samples = 0;
183 	}
184 	return 0;
185 }
186 
ensure_buffer(teletone_generation_session_t * ts,int need)187 static int ensure_buffer(teletone_generation_session_t *ts, int need)
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 
teletone_mux_tones(teletone_generation_session_t * ts,teletone_tone_map_t * map)206 TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone_tone_map_t *map)
207 {
208 	/*teletone_process_t period = (1.0 / ts->rate) / ts->channels;*/
209 	int i;
210 	int freqlen = 0;
211 	teletone_dds_state_t tones[TELETONE_MAX_TONES+1];
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 */
my_strdup(const char * s)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 
teletone_run(teletone_generation_session_t * ts,const char * cmd)314 TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd)
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  */
501