#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <math.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <stdarg.h>
#include <libteletone.h>
Include dependency graph for libteletone_generate.h:
This graph shows which files directly or indirectly include this file:
Go to the source code of this file.
Data Structures | |
| struct | teletone_dds_state |
| struct | teletone_generation_session |
| An abstraction to store a tone generation session. More... | |
Defines | |
| #define | TELETONE_VOL_DB_MAX 0 |
| #define | TELETONE_VOL_DB_MIN -63 |
| #define | MAX_PHASE_TONES 4 |
| #define | SINE_TABLE_MAX 128 |
| #define | SINE_TABLE_LEN (SINE_TABLE_MAX - 1) |
| #define | MAX_PHASE_ACCUMULATOR 0x10000 * 0x10000 |
| #define | DBM0_MAX_POWER (3.14f + 3.02f) |
Typedefs | |
| typedef teletone_dds_state | teletone_dds_state_t |
| typedef int16_t | teletone_audio_t |
| typedef int(*) | tone_handler (struct teletone_generation_session *ts, teletone_tone_map_t *map) |
| typedef teletone_generation_session | teletone_generation_session_t |
Functions | |
| float | powf (float, float) |
| static __inline__ int32_t | teletone_dds_phase_rate (teletone_process_t tone, uint32_t rate) |
| static __inline__ int16_t | teletone_dds_state_modulate_sample (teletone_dds_state_t *dds, uint32_t pindex) |
| static __inline__ void | teletone_dds_state_set_tx_level (teletone_dds_state_t *dds, float tx_level) |
| static __inline__ void | teletone_dds_state_reset_accum (teletone_dds_state_t *dds) |
| static __inline__ int | teletone_dds_state_set_tone (teletone_dds_state_t *dds, teletone_process_t tone, uint32_t rate, uint32_t pindex) |
| 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 | teletone_set_map (teletone_tone_map_t *map,...) |
| Assign a set of tones to a single tone map. | |
| int | teletone_init_session (teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data) |
| Initilize a tone generation session. | |
| int | teletone_destroy_session (teletone_generation_session_t *ts) |
| Free the buffer allocated by a tone generation session. | |
| int | teletone_mux_tones (teletone_generation_session_t *ts, teletone_tone_map_t *map) |
| Execute a single tone generation instruction. | |
| int | teletone_run (teletone_generation_session_t *ts, const char *cmd) |
| Execute a tone generation script and call callbacks after each instruction. | |
Variables | |
| int16_t | TELETONE_SINES [SINE_TABLE_MAX] |
This module is responsible for tone generation specifics
Definition in file libteletone_generate.h.
| #define DBM0_MAX_POWER (3.14f + 3.02f) |
Definition at line 138 of file libteletone_generate.h.
Referenced by teletone_dds_state_set_tx_level().
| #define MAX_PHASE_ACCUMULATOR 0x10000 * 0x10000 |
| #define MAX_PHASE_TONES 4 |
Definition at line 123 of file libteletone_generate.h.
Referenced by teletone_dds_state_modulate_sample(), and teletone_dds_state_set_tone().
| #define SINE_TABLE_LEN (SINE_TABLE_MAX - 1) |
Definition at line 134 of file libteletone_generate.h.
Referenced by teletone_dds_state_modulate_sample().
| #define SINE_TABLE_MAX 128 |
Definition at line 133 of file libteletone_generate.h.
Referenced by teletone_dds_state_modulate_sample().
| #define TELETONE_VOL_DB_MAX 0 |
Definition at line 121 of file libteletone_generate.h.
| #define TELETONE_VOL_DB_MIN -63 |
| typedef int16_t teletone_audio_t |
Definition at line 199 of file libteletone_generate.h.
| typedef struct teletone_dds_state teletone_dds_state_t |
Definition at line 131 of file libteletone_generate.h.
| typedef struct teletone_generation_session teletone_generation_session_t |
Definition at line 248 of file libteletone_generate.h.
| typedef int(*) tone_handler(struct teletone_generation_session *ts, teletone_tone_map_t *map) |
Definition at line 201 of file libteletone_generate.h.
| float powf | ( | float | , | |
| float | ||||
| ) |
Referenced by teletone_dds_state_set_tx_level().
| static __inline__ int32_t teletone_dds_phase_rate | ( | teletone_process_t | tone, | |
| uint32_t | rate | |||
| ) | [static] |
Definition at line 142 of file libteletone_generate.h.
References MAX_PHASE_ACCUMULATOR.
Referenced by teletone_dds_state_set_tone().
00143 { 00144 return (int32_t) ((tone * MAX_PHASE_ACCUMULATOR) / rate); 00145 }
| static __inline__ int16_t teletone_dds_state_modulate_sample | ( | teletone_dds_state_t * | dds, | |
| uint32_t | pindex | |||
| ) | [static] |
Definition at line 147 of file libteletone_generate.h.
References MAX_PHASE_TONES, teletone_dds_state::phase_accumulator, teletone_dds_state::phase_rate, teletone_dds_state::scale_factor, SINE_TABLE_LEN, SINE_TABLE_MAX, and TELETONE_SINES.
00148 { 00149 int32_t bitmask = dds->phase_accumulator, sine_index = (bitmask >>= 23) & SINE_TABLE_LEN; 00150 int16_t sample; 00151 00152 if (pindex >= MAX_PHASE_TONES) { 00153 pindex = 0; 00154 } 00155 00156 if (bitmask & SINE_TABLE_MAX) { 00157 sine_index = SINE_TABLE_LEN - sine_index; 00158 } 00159 00160 sample = TELETONE_SINES[sine_index]; 00161 00162 if (bitmask & (SINE_TABLE_MAX * 2)) { 00163 sample *= -1; 00164 } 00165 00166 dds->phase_accumulator += dds->phase_rate[pindex]; 00167 return (int16_t) (sample * dds->scale_factor >> 15); 00168 }
| static __inline__ void teletone_dds_state_reset_accum | ( | teletone_dds_state_t * | dds | ) | [static] |
Definition at line 176 of file libteletone_generate.h.
References teletone_dds_state::phase_accumulator.
00177 { 00178 dds->phase_accumulator = 0; 00179 }
| static __inline__ int teletone_dds_state_set_tone | ( | teletone_dds_state_t * | dds, | |
| teletone_process_t | tone, | |||
| uint32_t | rate, | |||
| uint32_t | pindex | |||
| ) | [static] |
Definition at line 181 of file libteletone_generate.h.
References MAX_PHASE_TONES, teletone_dds_state::phase_rate, and teletone_dds_phase_rate().
Referenced by teletone_mux_tones().
00182 { 00183 if (pindex < MAX_PHASE_TONES) { 00184 dds->phase_rate[pindex] = teletone_dds_phase_rate(tone, rate); 00185 return 0; 00186 } 00187 00188 return -1; 00189 }
| static __inline__ void teletone_dds_state_set_tx_level | ( | teletone_dds_state_t * | dds, | |
| float | tx_level | |||
| ) | [static] |
Definition at line 170 of file libteletone_generate.h.
References DBM0_MAX_POWER, powf(), teletone_dds_state::scale_factor, and teletone_dds_state::tx_level.
Referenced by teletone_mux_tones().
00171 { 00172 dds->scale_factor = (int) (powf(10.0f, (tx_level - DBM0_MAX_POWER) / 20.0f) * (32767.0f * 1.414214f)); 00173 dds->tx_level = tx_level; 00174 }
| int teletone_destroy_session | ( | teletone_generation_session_t * | ts | ) |
Free the buffer allocated by a tone generation session.
| ts | the tone generation session to destroy |
Definition at line 177 of file libteletone_generate.c.
Referenced by inband_dtmf_generate_callback(), main(), setup_ringback(), switch_ivr_gentones(), and switch_ivr_wait_for_answer().
00178 { 00179 if (ts->buffer) { 00180 free(ts->buffer); 00181 ts->buffer = NULL; 00182 ts->samples = 0; 00183 } 00184 return 0; 00185 }
| int teletone_init_session | ( | teletone_generation_session_t * | ts, | |
| int | buflen, | |||
| tone_handler | handler, | |||
| void * | user_data | |||
| ) |
Initilize a tone generation session.
| ts | the tone generation session to initilize | |
| buflen | the size of the buffer(in samples) to dynamically allocate | |
| handler | a callback function to execute when a tone generation instruction is complete | |
| user_data | optional user data to send |
Definition at line 134 of file libteletone_generate.c.
References teletone_set_tone().
Referenced by inband_dtmf_generate_callback(), main(), setup_ringback(), switch_ivr_gentones(), and switch_ivr_wait_for_answer().
00135 { 00136 memset(ts, 0, sizeof(*ts)); 00137 ts->rate = 8000; 00138 ts->channels = 1; 00139 ts->duration = 2000; 00140 ts->wait = 500; 00141 ts->tmp_duration = -1; 00142 ts->tmp_wait = -1; 00143 ts->handler = handler; 00144 ts->user_data = user_data; 00145 ts->volume = -7; 00146 ts->decay_step = 0; 00147 ts->decay_factor = 1; 00148 if (buflen) { 00149 if ((ts->buffer = calloc(buflen, sizeof(teletone_audio_t))) == 0) { 00150 return -1; 00151 } 00152 ts->datalen = buflen; 00153 } else { 00154 ts->dynamic = 1024; 00155 } 00156 /* Add Standard DTMF Tones */ 00157 teletone_set_tone(ts, '1', 697.0, 1209.0, 0.0); 00158 teletone_set_tone(ts, '2', 697.0, 1336.0, 0.0); 00159 teletone_set_tone(ts, '3', 697.0, 1477.0, 0.0); 00160 teletone_set_tone(ts, 'A', 697.0, 1633.0, 0.0); 00161 teletone_set_tone(ts, '4', 770.0, 1209.0, 0.0); 00162 teletone_set_tone(ts, '5', 770.0, 1336.0, 0.0); 00163 teletone_set_tone(ts, '6', 770.0, 1477.0, 0.0); 00164 teletone_set_tone(ts, 'B', 770.0, 1633.0, 0.0); 00165 teletone_set_tone(ts, '7', 859.0, 1209.0, 0.0); 00166 teletone_set_tone(ts, '8', 859.0, 1336.0, 0.0); 00167 teletone_set_tone(ts, '9', 859.0, 1477.0, 0.0); 00168 teletone_set_tone(ts, 'C', 859.0, 1633.0, 0.0); 00169 teletone_set_tone(ts, '*', 941.0, 1209.0, 0.0); 00170 teletone_set_tone(ts, '0', 941.0, 1336.0, 0.0); 00171 teletone_set_tone(ts, '#', 941.0, 1477.0, 0.0); 00172 teletone_set_tone(ts, 'D', 941.0, 1633.0, 0.0); 00173 00174 return 0; 00175 }
| int teletone_mux_tones | ( | teletone_generation_session_t * | ts, | |
| teletone_tone_map_t * | map | |||
| ) |
Execute a single tone generation instruction.
| ts | the tone generation session to consult for parameters | |
| map | the tone mapping to use for the frequencies |
Definition at line 206 of file libteletone_generate.c.
References ensure_buffer(), teletone_dds_state_set_tone(), teletone_dds_state_set_tx_level(), and TELETONE_MAX_TONES.
Referenced by teletone_dtmf_generate_handler(), and teletone_handler().
00207 { 00208 /*teletone_process_t period = (1.0 / ts->rate) / ts->channels;*/ 00209 int i, c; 00210 int freqlen = 0; 00211 teletone_dds_state_t tones[TELETONE_MAX_TONES+1]; 00212 //int decay = 0; 00213 int duration; 00214 int wait = 0; 00215 int32_t sample; 00216 int32_t dc = 0; 00217 float vol = ts->volume; 00218 ts->samples = 0; 00219 memset(tones, 0, sizeof(tones[0]) * TELETONE_MAX_TONES); 00220 duration = (ts->tmp_duration > -1) ? ts->tmp_duration : ts->duration; 00221 wait = (ts->tmp_wait > -1) ? ts->tmp_wait : ts->wait; 00222 00223 if (map->freqs[0] > 0) { 00224 for (freqlen = 0; freqlen < TELETONE_MAX_TONES && map->freqs[freqlen]; freqlen++) { 00225 teletone_dds_state_set_tone(&tones[freqlen], map->freqs[freqlen], ts->rate, 0); 00226 teletone_dds_state_set_tx_level(&tones[freqlen], vol); 00227 } 00228 00229 if (ts->channels > 1) { 00230 duration *= ts->channels; 00231 } 00232 00233 if (ts->dynamic) { 00234 if (ensure_buffer(ts, duration)) { 00235 return -1; 00236 } 00237 } 00238 00239 for (ts->samples = 0; ts->samples < ts->datalen && ts->samples < duration; ts->samples++) { 00240 if (ts->decay_direction && ++dc >= ts->decay_step) { 00241 float nvol = vol + ts->decay_direction * ts->decay_factor; 00242 int j; 00243 00244 if (nvol <= TELETONE_VOL_DB_MAX && nvol >= TELETONE_VOL_DB_MIN) { 00245 vol = nvol; 00246 for (j = 0; j < TELETONE_MAX_TONES && map->freqs[j]; j++) { 00247 teletone_dds_state_set_tx_level(&tones[j], vol); 00248 } 00249 dc = 0; 00250 } 00251 } 00252 00253 sample = 128; 00254 00255 for (i = 0; i < freqlen; i++) { 00256 int32_t s = teletone_dds_state_modulate_sample(&tones[i], 0); 00257 sample += s; 00258 } 00259 sample /= freqlen; 00260 ts->buffer[ts->samples] = (teletone_audio_t)sample; 00261 00262 for (c = 1; c < ts->channels; c++) { 00263 ts->buffer[ts->samples+1] = ts->buffer[ts->samples]; 00264 ts->samples++; 00265 } 00266 00267 } 00268 } 00269 if (ts->dynamic) { 00270 if (ensure_buffer(ts, wait)) { 00271 return -1; 00272 } 00273 } 00274 for (c = 0; c < ts->channels; c++) { 00275 for (i = 0; i < wait && ts->samples < ts->datalen; i++) { 00276 ts->buffer[ts->samples++] = 0; 00277 } 00278 } 00279 00280 if (ts->debug && ts->debug_stream) { 00281 if (map->freqs[0] <= 0) { 00282 fprintf(ts->debug_stream, "wait %d (%dms)\n", wait, wait / (ts->rate / 1000)); 00283 } else { 00284 fprintf(ts->debug_stream, "Generate: ("); 00285 00286 for (i = 0; i < TELETONE_MAX_TONES && map->freqs[i]; i++) { 00287 fprintf(ts->debug_stream, "%s%0.2f", i == 0 ? "" : "+",map->freqs[i]); 00288 } 00289 00290 fprintf(ts->debug_stream, 00291 ") [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", 00292 ts->volume, 00293 duration, 00294 duration / (ts->rate / 1000), 00295 ts->channels, 00296 ts->channels == 1 ? "" : "s", 00297 wait, 00298 wait / (ts->rate / 1000), 00299 ts->decay_factor, 00300 ts->decay_step, 00301 ts->decay_step / (ts->rate / 1000), 00302 ts->samples * 2); 00303 } 00304 } 00305 return ts->samples / ts->channels; 00306 }
| int teletone_run | ( | teletone_generation_session_t * | ts, | |
| const char * | cmd | |||
| ) |
Execute a tone generation script and call callbacks after each instruction.
| ts | the tone generation session to execute on | |
| cmd | the script to execute |
Definition at line 321 of file libteletone_generate.c.
References teletone_tone_map_t::freqs, 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().
00322 { 00323 char *data = NULL, *cur = NULL, *end = NULL; 00324 int LOOPING = 0; 00325 00326 if (!cmd) { 00327 return -1; 00328 } 00329 00330 do { 00331 if (!(data = my_strdup(cmd))) { 00332 return -1; 00333 } 00334 00335 cur = data; 00336 00337 while (*cur) { 00338 if (*cur == ' ' || *cur == '\r' || *cur == '\n') { 00339 cur++; 00340 continue; 00341 } 00342 00343 if ((end = strchr(cur, ';')) != 0) { 00344 *end++ = '\0'; 00345 } 00346 00347 if (*(cur + 1) == '=') { 00348 switch(*cur) { 00349 case 'c': 00350 ts->channels = atoi(cur + 2); 00351 break; 00352 case 'r': 00353 ts->rate = atoi(cur + 2); 00354 break; 00355 case 'd': 00356 ts->duration = atoi(cur + 2) * (ts->rate / 1000); 00357 break; 00358 case 'v': 00359 { 00360 float vol = (float)atof(cur + 2); 00361 if (vol <= TELETONE_VOL_DB_MAX && vol >= TELETONE_VOL_DB_MIN) { 00362 ts->volume = vol; 00363 } 00364 } 00365 break; 00366 case '>': 00367 ts->decay_step = atoi(cur + 2) * (ts->rate / 1000); 00368 ts->decay_direction = -1; 00369 break; 00370 case '<': 00371 ts->decay_step = atoi(cur + 2) * (ts->rate / 1000); 00372 ts->decay_direction = 1; 00373 break; 00374 case '+': 00375 ts->decay_factor = (float)atof(cur + 2); 00376 break; 00377 case 'w': 00378 ts->wait = atoi(cur + 2) * (ts->rate / 1000); 00379 break; 00380 case 'l': 00381 ts->loops = atoi(cur + 2); 00382 break; 00383 case 'L': 00384 if (!LOOPING) { 00385 ts->LOOPS = atoi(cur + 2); 00386 } 00387 LOOPING++; 00388 break; 00389 } 00390 } else { 00391 while (*cur) { 00392 char *p = NULL, *e = NULL; 00393 teletone_tone_map_t mymap, *mapp = NULL; 00394 00395 if (*cur == ' ' || *cur == '\r' || *cur == '\n') { 00396 cur++; 00397 continue; 00398 } 00399 00400 ts->tmp_duration = -1; 00401 ts->tmp_wait = -1; 00402 00403 memset(&mymap, 0, sizeof(mymap)); 00404 00405 if (*(cur + 1) == '(') { 00406 p = cur + 2; 00407 if (*cur) { 00408 char *next; 00409 int i = 0; 00410 if ((e = strchr(p, ')')) != 0) { 00411 *e++ = '\0'; 00412 } 00413 do { 00414 if (!p) { 00415 break; 00416 } 00417 if ((next = strchr(p, ',')) != 0) { 00418 *next++ = '\0'; 00419 } 00420 if (i == 0) { 00421 ts->tmp_duration = atoi(p) * (ts->rate / 1000); 00422 i++; 00423 } else if (i == 1) { 00424 ts->tmp_wait = atoi(p) * (ts->rate / 1000); 00425 i++; 00426 } else { 00427 mymap.freqs[i++ - 2] = atof(p); 00428 } 00429 p = next; 00430 00431 } while (next && (i-2) < TELETONE_MAX_TONES); 00432 if (i > 2 && *cur == '%') { 00433 mapp = &mymap; 00434 } else if ((i != 2 || *cur == '%')) { 00435 if (ts->debug && ts->debug_stream) { 00436 fprintf(ts->debug_stream, "Syntax Error!\n"); 00437 } 00438 goto bottom; 00439 } 00440 } 00441 } 00442 00443 if (*cur && !mapp) { 00444 if (*cur > 0 && *cur < TELETONE_TONE_RANGE) { 00445 mapp = &ts->TONES[(int)*cur]; 00446 } else if (ts->debug && ts->debug_stream) { 00447 fprintf(ts->debug_stream, "Map [%c] Out Of Range!\n", *cur); 00448 } 00449 } 00450 00451 if (mapp) { 00452 if (mapp->freqs[0]) { 00453 if (ts->handler) { 00454 do { 00455 ts->handler(ts, mapp); 00456 if (ts->loops > 0) { 00457 ts->loops--; 00458 } 00459 } while (ts->loops); 00460 } 00461 } else if (ts->debug && ts->debug_stream) { 00462 fprintf(ts->debug_stream, "Ignoring Empty Map [%c]!\n", *cur); 00463 } 00464 } 00465 00466 if (e) { 00467 cur = e; 00468 } else { 00469 cur++; 00470 } 00471 } 00472 } 00473 00474 if (end) { 00475 cur = end; 00476 } else if (*cur){ 00477 cur++; 00478 } 00479 } 00480 bottom: 00481 free(data); 00482 data = NULL; 00483 if (ts->LOOPS > 0) { 00484 ts->LOOPS--; 00485 } 00486 00487 } while (ts->LOOPS); 00488 00489 return 0; 00490 }
| int teletone_set_map | ( | teletone_tone_map_t * | map, | |
| ... | ||||
| ) |
Assign a set of tones to a single tone map.
| map | the map to assign the tones to | |
| ... | up to TELETONE_MAX_TONES frequencies terminated by 0.0 |
Definition at line 118 of file libteletone_generate.c.
References TELETONE_MAX_TONES.
00119 { 00120 va_list ap; 00121 int i = 0; 00122 teletone_process_t x = 0; 00123 00124 va_start(ap, map); 00125 while (i < TELETONE_MAX_TONES && (x = va_arg(ap, teletone_process_t))) { 00126 map->freqs[i++] = x; 00127 } 00128 va_end(ap); 00129 00130 return (i > TELETONE_MAX_TONES) ? -1 : 0; 00131 00132 }
| 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.
| ts | the tone generation session | |
| index | the index to map the tone to | |
| ... | up to TELETONE_MAX_TONES frequencies terminated by 0.0 |
Definition at line 102 of file libteletone_generate.c.
References TELETONE_MAX_TONES.
Referenced by teletone_init_session().
00103 { 00104 va_list ap; 00105 int i = 0; 00106 teletone_process_t x = 0; 00107 00108 va_start(ap, index); 00109 while (i < TELETONE_MAX_TONES && (x = va_arg(ap, teletone_process_t))) { 00110 ts->TONES[index].freqs[i++] = x; 00111 } 00112 va_end(ap); 00113 00114 return (i > TELETONE_MAX_TONES) ? -1 : 0; 00115 00116 }
| int16_t TELETONE_SINES[SINE_TABLE_MAX] |
Definition at line 82 of file libteletone_generate.c.
Referenced by teletone_dds_state_modulate_sample().
1.4.7