root/src/libteletone_generate.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. TELETONE_API
  2. TELETONE_API
  3. TELETONE_API
  4. TELETONE_API
  5. ensure_buffer
  6. TELETONE_API
  7. TELETONE_API

   1 /* 
   2  * libteletone_generate.c -- Tone Generator
   3  *
   4  * Copyright (c) 2007, Anthony Minessale II
   5  * All rights reserved.
   6  * 
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  * 
  11  * * Redistributions of source code must retain the above copyright
  12  * notice, this list of conditions and the following disclaimer.
  13  * 
  14  * * Redistributions in binary form must reproduce the above copyright
  15  * notice, this list of conditions and the following disclaimer in the
  16  * documentation and/or other materials provided with the distribution.
  17  * 
  18  * * Neither the name of the original author; nor the names of any contributors
  19  * may be used to endorse or promote products derived from this software
  20  * without specific prior written permission.
  21  * 
  22  * 
  23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  26  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  27  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  29  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34  */
  35 
  36 #include <libteletone.h>
  37 #include "private/ftdm_core.h"
  38 
  39 #define SMAX 32767
  40 #define SMIN -32768
  41 #define normalize_to_16bit(n) if (n > SMAX) n = SMAX; else if (n < SMIN) n = SMIN;
  42 
  43 #ifdef _MSC_VER
  44 #pragma warning(disable:4706)
  45 #endif
  46 
  47 TELETONE_API_DATA int16_t TELETONE_SINES[SINE_TABLE_MAX] = {
  48         0x00c9, 0x025b, 0x03ed, 0x057f, 0x0711, 0x08a2, 0x0a33, 0x0bc4,
  49         0x0d54, 0x0ee4, 0x1073, 0x1201, 0x138f, 0x151c, 0x16a8, 0x1833,
  50         0x19be, 0x1b47, 0x1cd0, 0x1e57, 0x1fdd, 0x2162, 0x22e5, 0x2467,
  51         0x25e8, 0x2768, 0x28e5, 0x2a62, 0x2bdc, 0x2d55, 0x2ecc, 0x3042,
  52         0x31b5, 0x3327, 0x3497, 0x3604, 0x3770, 0x38d9, 0x3a40, 0x3ba5,
  53         0x3d08, 0x3e68, 0x3fc6, 0x4121, 0x427a, 0x43d1, 0x4524, 0x4675,
  54         0x47c4, 0x490f, 0x4a58, 0x4b9e, 0x4ce1, 0x4e21, 0x4f5e, 0x5098,
  55         0x51cf, 0x5303, 0x5433, 0x5560, 0x568a, 0x57b1, 0x58d4, 0x59f4,
  56         0x5b10, 0x5c29, 0x5d3e, 0x5e50, 0x5f5e, 0x6068, 0x616f, 0x6272,
  57         0x6371, 0x646c, 0x6564, 0x6657, 0x6747, 0x6832, 0x691a, 0x69fd,
  58         0x6add, 0x6bb8, 0x6c8f, 0x6d62, 0x6e31, 0x6efb, 0x6fc2, 0x7083,
  59         0x7141, 0x71fa, 0x72af, 0x735f, 0x740b, 0x74b3, 0x7556, 0x75f4,
  60         0x768e, 0x7723, 0x77b4, 0x7840, 0x78c8, 0x794a, 0x79c9, 0x7a42,
  61         0x7ab7, 0x7b27, 0x7b92, 0x7bf9, 0x7c5a, 0x7cb7, 0x7d0f, 0x7d63,
  62         0x7db1, 0x7dfb, 0x7e3f, 0x7e7f, 0x7eba, 0x7ef0, 0x7f22, 0x7f4e,
  63         0x7f75, 0x7f98, 0x7fb5, 0x7fce, 0x7fe2, 0x7ff1, 0x7ffa, 0x7fff
  64 };
  65 
  66 
  67 TELETONE_API(int) teletone_set_tone(teletone_generation_session_t *ts, int index, ...)
  68 {
  69         va_list ap;
  70         int i = 0;
  71         teletone_process_t x = 0;
  72 
  73         va_start(ap, index);
  74         while (i < TELETONE_MAX_TONES && (x = va_arg(ap, teletone_process_t))) {
  75                 ts->TONES[index].freqs[i++] = x;
  76         }
  77         va_end(ap);
  78 
  79         return (i > TELETONE_MAX_TONES) ? -1 : 0;
  80         
  81 }
  82 
  83 TELETONE_API(int) teletone_set_map(teletone_tone_map_t *map, ...)
  84 {
  85         va_list ap;
  86         int i = 0;
  87         teletone_process_t x = 0;
  88 
  89         va_start(ap, map);
  90         while (i < TELETONE_MAX_TONES && (x = va_arg(ap, teletone_process_t))) {
  91                 map->freqs[i++] = x;
  92         }
  93         va_end(ap);
  94 
  95         return (i > TELETONE_MAX_TONES) ? -1 : 0;
  96         
  97 }
  98 
  99 TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data)
 100 {
 101         memset(ts, 0, sizeof(*ts));
 102         ts->rate = 8000;
 103         ts->channels = 1;
 104         ts->duration = 2000;
 105         ts->wait = 500;
 106         ts->tmp_duration = -1;
 107         ts->tmp_wait = -1;
 108         ts->handler = handler;
 109         ts->user_data = user_data;
 110         ts->volume = -7;
 111         ts->decay_step = 0;
 112         ts->decay_factor = 1;
 113         if (buflen) {
 114                 if ((ts->buffer = ftdm_calloc(buflen, sizeof(teletone_audio_t))) == 0) {
 115                         return -1;
 116                 }
 117                 ts->datalen = buflen;
 118         } else {
 119                 ts->dynamic = 1024;
 120         }
 121         /* Add Standard DTMF Tones */
 122         teletone_set_tone(ts, '1', 697.0, 1209.0, 0.0);
 123         teletone_set_tone(ts, '2', 697.0, 1336.0, 0.0);
 124         teletone_set_tone(ts, '3', 697.0, 1477.0, 0.0);
 125         teletone_set_tone(ts, 'A', 697.0, 1633.0, 0.0);
 126         teletone_set_tone(ts, '4', 770.0, 1209.0, 0.0);
 127         teletone_set_tone(ts, '5', 770.0, 1336.0, 0.0);
 128         teletone_set_tone(ts, '6', 770.0, 1477.0, 0.0);
 129         teletone_set_tone(ts, 'B', 770.0, 1633.0, 0.0);
 130         teletone_set_tone(ts, '7', 859.0, 1209.0, 0.0);
 131         teletone_set_tone(ts, '8', 859.0, 1336.0, 0.0);
 132         teletone_set_tone(ts, '9', 859.0, 1477.0, 0.0);
 133         teletone_set_tone(ts, 'C', 859.0, 1633.0, 0.0);
 134         teletone_set_tone(ts, '*', 941.0, 1209.0, 0.0);
 135         teletone_set_tone(ts, '0', 941.0, 1336.0, 0.0);
 136         teletone_set_tone(ts, '#', 941.0, 1477.0, 0.0);
 137         teletone_set_tone(ts, 'D', 941.0, 1633.0, 0.0);
 138         
 139         return 0;
 140 }
 141 
 142 TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts)
 143 {
 144         if (ts->buffer) {
 145                 ftdm_safe_free(ts->buffer);
 146                 ts->buffer = NULL;
 147                 ts->samples = 0;
 148         }
 149         return 0;
 150 }
 151 
 152 static int ensure_buffer(teletone_generation_session_t *ts, int need)
 153 {
 154         need += ts->samples;
 155         need *= sizeof(teletone_audio_t);
 156         need *= ts->channels;
 157 
 158         if (need > ts->datalen) {
 159                 teletone_audio_t *tmp;
 160                 ts->datalen = need + ts->dynamic;
 161                 tmp = realloc(ts->buffer, ts->datalen);
 162                 if (!tmp) {
 163                         return -1;
 164                 }
 165                 ts->buffer = tmp;
 166         }
 167 
 168         return 0;
 169 }
 170 
 171 TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone_tone_map_t *map)
 172 {
 173         /*teletone_process_t period = (1.0 / ts->rate) / ts->channels;*/
 174         int i, c;
 175         int freqlen = 0;
 176         teletone_dds_state_t tones[TELETONE_MAX_TONES+1];
 177         //int decay = 0;
 178         int duration;
 179         int wait = 0;
 180         int32_t sample;
 181         int32_t dc = 0;
 182         float vol = ts->volume;
 183         ts->samples = 0;
 184         memset(tones, 0, sizeof(tones[0]) * TELETONE_MAX_TONES);
 185         duration = (ts->tmp_duration > -1) ? ts->tmp_duration : ts->duration;
 186         wait = (ts->tmp_wait > -1) ? ts->tmp_wait : ts->wait;
 187 
 188         if (map->freqs[0] > 0) {
 189                 for (freqlen = 0; freqlen < TELETONE_MAX_TONES && map->freqs[freqlen]; freqlen++) {
 190                         teletone_dds_state_set_tone(&tones[freqlen], map->freqs[freqlen], ts->rate, 0);
 191                         teletone_dds_state_set_tx_level(&tones[freqlen], vol);
 192                 }
 193         
 194                 if (ts->channels > 1) {
 195                         duration *= ts->channels;
 196                 }
 197 
 198                 if (ts->dynamic) {
 199                         if (ensure_buffer(ts, duration)) {
 200                                 return -1;
 201                         }
 202                 }
 203 
 204                 for (ts->samples = 0; ts->samples < ts->datalen && ts->samples < duration; ts->samples++) {
 205                         if (ts->decay_direction && ++dc >= ts->decay_step) {
 206                                 float nvol = vol + ts->decay_direction * ts->decay_factor;
 207                                 int j;
 208 
 209                                 if (nvol <= TELETONE_VOL_DB_MAX && nvol >= TELETONE_VOL_DB_MIN) {
 210                                         vol = nvol;
 211                                         for (j = 0; j < TELETONE_MAX_TONES && map->freqs[j]; j++) {                                     
 212                                                 teletone_dds_state_set_tx_level(&tones[j], vol);
 213                                         }
 214                                         dc = 0;
 215                                 }
 216                         }
 217 
 218                         sample = 128;
 219 
 220                         for (i = 0; i < freqlen; i++) {
 221                                 int32_t s = teletone_dds_state_modulate_sample(&tones[i], 0);
 222                                 sample += s;
 223                         }
 224                         sample /= freqlen;
 225                         ts->buffer[ts->samples] = (teletone_audio_t)sample;
 226                         
 227                         for (c = 1; c < ts->channels; c++) {
 228                                 ts->buffer[ts->samples+1] = ts->buffer[ts->samples];
 229                                 ts->samples++;
 230                         }
 231                         
 232                 }
 233         }
 234         if (ts->dynamic) {
 235                 if (ensure_buffer(ts, wait)) {
 236                         return -1;
 237                 }
 238         }
 239         for (c = 0; c < ts->channels; c++) {
 240                 for (i = 0; i < wait && ts->samples < ts->datalen; i++) {
 241                         ts->buffer[ts->samples++] = 0;
 242                 }
 243         }
 244 
 245         if (ts->debug && ts->debug_stream) {
 246                 if (map->freqs[0] <= 0) {
 247                         fprintf(ts->debug_stream, "wait %d (%dms)\n", wait, wait / (ts->rate / 1000));
 248                 } else {
 249                         fprintf(ts->debug_stream, "Generate: (");
 250 
 251                         for (i = 0; i < TELETONE_MAX_TONES && map->freqs[i]; i++) {
 252                                 fprintf(ts->debug_stream, "%s%0.2f", i == 0 ? "" : "+",map->freqs[i]);
 253                         }
 254                          
 255                         fprintf(ts->debug_stream, 
 256                                         ") [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",
 257                                         ts->volume,
 258                                         duration,
 259                                         duration / (ts->rate / 1000), 
 260                                         ts->channels,
 261                                         ts->channels == 1 ? "" : "s",
 262                                         wait,
 263                                         wait / (ts->rate / 1000),
 264                                         ts->decay_factor,
 265                                         ts->decay_step,
 266                                         ts->decay_step / (ts->rate / 1000),                                     
 267                                         ts->samples * 2);
 268                 }
 269         }       
 270         return ts->samples / ts->channels;
 271 }
 272 
 273 TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd)
 274 {
 275         char *data = NULL, *cur = NULL, *end = NULL;
 276         int var = 0, LOOPING = 0;
 277         
 278         if (!cmd) {
 279                 return -1;
 280         }
 281 
 282         do {
 283                 if (!(data = ftdm_strdup(cmd))) {
 284                         return -1;
 285                 }
 286 
 287                 cur = data;
 288 
 289                 while (*cur) {
 290                         var = 0;
 291                         if (*cur == ' ' || *cur == '\r' || *cur == '\n') {
 292                                 cur++;
 293                                 continue;
 294                         }
 295 
 296                         if ((end = strchr(cur, ';')) != 0) {
 297                                 *end++ = '\0';
 298                         }
 299                         
 300                         if (*(cur + 1) == '=') {
 301                                 var = 1;
 302                                 switch(*cur) {
 303                                 case 'c':
 304                                         ts->channels = atoi(cur + 2);
 305                                         break;
 306                                 case 'r':
 307                                         ts->rate = atoi(cur + 2);
 308                                         break;
 309                                 case 'd':
 310                                         ts->duration = atoi(cur + 2) * (ts->rate / 1000);
 311                                         break;
 312                                 case 'v':
 313                                         {
 314                                                 float vol = (float)atof(cur + 2);
 315                                                 if (vol <= TELETONE_VOL_DB_MAX && vol >= TELETONE_VOL_DB_MIN) {
 316                                                         ts->volume = vol;
 317                                                 }
 318                                         }
 319                                         break;
 320                                 case '>':
 321                                         ts->decay_step = atoi(cur + 2) * (ts->rate / 1000);
 322                                         ts->decay_direction = -1;
 323                                         break;
 324                                 case '<':
 325                                         ts->decay_step = atoi(cur + 2) * (ts->rate / 1000);
 326                                         ts->decay_direction = 1;
 327                                         break;
 328                                 case '+':
 329                                         ts->decay_factor = (float)atof(cur + 2);
 330                                         break;
 331                                 case 'w':
 332                                         ts->wait = atoi(cur + 2) * (ts->rate / 1000);
 333                                         break;
 334                                 case 'l':
 335                                         ts->loops = atoi(cur + 2); 
 336                                         break;
 337                                 case 'L':
 338                                         if (!LOOPING) {
 339                                                 ts->LOOPS = atoi(cur + 2); 
 340                                         }
 341                                         LOOPING++;
 342                                         break;
 343                                 }
 344                         } else {
 345                                 while (*cur) {
 346                                         char *p = NULL, *e = NULL;
 347                                         teletone_tone_map_t mymap, *mapp = NULL;
 348 
 349                                         if (*cur == ' ' || *cur == '\r' || *cur == '\n') {
 350                                                 cur++;
 351                                                 continue;
 352                                         }
 353                                         
 354                                         ts->tmp_duration = -1;
 355                                         ts->tmp_wait = -1;
 356 
 357                                         memset(&mymap, 0, sizeof(mymap));
 358 
 359                                         if (*(cur + 1) == '(') {
 360                                                 p = cur + 2;
 361                                                 if (*cur) {
 362                                                         char *next;
 363                                                         int i = 0;
 364                                                         if ((e = strchr(p, ')')) != 0) {
 365                                                                 *e++ = '\0';
 366                                                         }
 367                                                         do {
 368                                                                 if ((next = strchr(p, ',')) != 0) {
 369                                                                         *next++ = '\0';
 370                                                                 }
 371                                                                 if (i == 0) {
 372                                                                         ts->tmp_duration = atoi(p) * (ts->rate / 1000);
 373                                                                         i++;
 374                                                                 } else if (i == 1) {
 375                                                                         ts->tmp_wait = atoi(p) * (ts->rate / 1000);
 376                                                                         i++;
 377                                                                 } else {
 378                                                                         mymap.freqs[i++ - 2] = atof(p);
 379                                                                 }
 380                                                                 p = next;
 381 
 382                                                         } while (next && (i-2) < TELETONE_MAX_TONES);
 383                                                         if (i > 2 && *cur == '%') {
 384                                                                 mapp = &mymap;
 385                                                         } else if ((i != 2 || *cur == '%')) { 
 386                                                                 if (ts->debug && ts->debug_stream) {
 387                                                                         fprintf(ts->debug_stream, "Syntax Error!\n");
 388                                                                 }
 389                                                                 goto bottom;
 390                                                         }
 391                                                 } 
 392                                         }
 393 
 394                                         if (*cur && !mapp) {
 395                                                 if (*cur > 0 && *cur < TELETONE_TONE_RANGE) { 
 396                                                         mapp = &ts->TONES[(int)*cur];
 397                                                 } else if (ts->debug && ts->debug_stream) {
 398                                                         fprintf(ts->debug_stream, "Map [%c] Out Of Range!\n", *cur);
 399                                                 }
 400                                         }
 401 
 402                                         if (mapp) {
 403                                                 if (mapp->freqs[0]) {
 404                                                         if (ts->handler) {
 405                                                                 do {
 406                                                                         ts->handler(ts, mapp);
 407                                                                         if (ts->loops > 0) {
 408                                                                                 ts->loops--;
 409                                                                         }
 410                                                                 } while (ts->loops);
 411                                                         }
 412                                                 } else if (ts->debug && ts->debug_stream) {
 413                                                         fprintf(ts->debug_stream, "Ignoring Empty Map [%c]!\n", *cur);
 414                                                 }
 415                                         }
 416                                         
 417                                         if (e) {
 418                                                 cur = e;
 419                                         } else {
 420                                                 cur++;
 421                                         }
 422                                 }
 423                         }
 424 
 425                         if (end) {
 426                                 cur = end;
 427                         } else if (*cur){
 428                                 cur++;
 429                         }
 430                 }
 431         bottom:
 432                 ftdm_safe_free(data);
 433                 data = NULL;
 434                 if (ts->LOOPS > 0) {
 435                         ts->LOOPS--;
 436                 }
 437 
 438         } while (ts->LOOPS);
 439 
 440         return 0;
 441 }
 442 
 443 /* For Emacs:
 444  * Local Variables:
 445  * mode:c
 446  * indent-tabs-mode:t
 447  * tab-width:4
 448  * c-basic-offset:4
 449  * End:
 450  * For VIM:
 451  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
 452  */

/* [<][>][^][v][top][bottom][index][help] */