diff options
author | kpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-12-14 23:47:31 +0000 |
---|---|---|
committer | kpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-12-14 23:47:31 +0000 |
commit | e82cf68ec969ba027f671b27261442b54b5f8737 (patch) | |
tree | 4a8a03d12bd400e69f53b7fce7f3075a41a407c2 /tonezone.c | |
parent | ef2eddaeb8ac4e25b283081911a36a642ce5f157 (diff) |
(merging dtmf-twister branch plus a few fixes)
move DTMF/MF generation into tonezone.c (libtonezone) so that it can happen at runtime instead of compile time; this allows for DTMF/MF to be different on a zone-by-zone basis without requiring a recompile of Zaptel
set DTMF 'twist' for Brazil (zone 'br') to 2dB
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@3490 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'tonezone.c')
-rw-r--r-- | tonezone.c | 217 |
1 files changed, 160 insertions, 57 deletions
@@ -29,6 +29,7 @@ #include <stdlib.h> #include <unistd.h> #include <errno.h> + #include "tonezone.h" #define DEFAULT_ZT_DEV "/dev/zap/ctl" @@ -63,15 +64,15 @@ struct tone_zone *tone_zone_find_by_num(int id) #define LEVEL -10 -static int build_tone(char *data, int size, struct tone_zone_sound *t, int *count) +static int build_tone(void *data, int size, struct tone_zone_sound *t, int *count) { char *dup, *s; struct zt_tone_def *td=NULL; int firstnobang = -1; int freq1, freq2, time; - int used = 0; int modulate = 0; float gain; + int used = 0; dup = strdup(t->data); s = strtok(dup, ","); while(s && strlen(s)) { @@ -125,11 +126,11 @@ static int build_tone(char *data, int size, struct tone_zone_sound *t, int *coun #if 0 printf("Using %d samples for %d and %d\n", time * 8, freq1, freq2); #endif - if (size < sizeof(struct zt_tone_def)) { - fprintf(stderr, "Not enough space for samples\n"); + if (size < sizeof(*td)) { + fprintf(stderr, "Not enough space for tones\n"); return -1; } - td = (struct zt_tone_def *)data; + td = data; /* Bring it down -8 dbm */ gain = pow(10.0, (LEVEL - 3.14) / 20.0) * 65536.0 / 2.0; @@ -144,9 +145,9 @@ static int build_tone(char *data, int size, struct tone_zone_sound *t, int *coun td->modulate = modulate; - data += (sizeof(struct zt_tone_def)); - used += (sizeof(struct zt_tone_def)); - size -= (sizeof(struct zt_tone_def)); + data += sizeof(*td); + used += sizeof(*td); + size -= sizeof(*td); td->tone = t->toneid; if (time) { /* We should move to the next tone */ @@ -157,7 +158,7 @@ static int build_tone(char *data, int size, struct tone_zone_sound *t, int *coun td->next = *count; td->samples = 8000; } - (*count)++; + *count += 1; s = strtok(NULL, ","); } if (td && time) { @@ -203,85 +204,187 @@ char *tone_zone_tone_name(int id) } #ifdef TONEZONE_DRIVER -static void dump_tone_zone(void *data) +static void dump_tone_zone(void *data, int size) { struct zt_tone_def_header *z; struct zt_tone_def *td; int x; - int len=0; + int len = sizeof(*z); + z = data; data += sizeof(*z); printf("Header: %d tones, %d bytes of data, zone %d (%s)\n", - z->count, z->size, z->zone, z->name); - for (x=0;x < z->count; x++) { + z->count, size, z->zone, z->name); + for (x = 0; x < z->count; x++) { td = data; - printf("Tone Fragment %d: %d bytes, %s tone, next is %d, %d samples total\n", - x, td->size, tone_name(td->tone), td->next, td->samples); + printf("Tone Fragment %d: tone is %d, next is %d, %d samples\n", + x, td->tone, td->next, td->samples); data += sizeof(*td); - data += td->size; - len += td->size; + len += sizeof(*td); } printf("Total measured bytes of data: %d\n", len); } #endif +/* Tone frequency tables */ +struct mf_tone { + int tone; + float f1; /* first freq */ + float f2; /* second freq */ +}; + +static struct mf_tone dtmf_dial[] = { + { ZT_TONE_DTMF_0, 941.0, 1336.0 }, + { ZT_TONE_DTMF_1, 697.0, 1209.0 }, + { ZT_TONE_DTMF_2, 697.0, 1336.0 }, + { ZT_TONE_DTMF_3, 697.0, 1477.0 }, + { ZT_TONE_DTMF_4, 770.0, 1209.0 }, + { ZT_TONE_DTMF_5, 770.0, 1336.0 }, + { ZT_TONE_DTMF_6, 770.0, 1477.0 }, + { ZT_TONE_DTMF_7, 852.0, 1209.0 }, + { ZT_TONE_DTMF_8, 852.0, 1336.0 }, + { ZT_TONE_DTMF_9, 852.0, 1477.0 }, + { ZT_TONE_DTMF_s, 941.0, 1209.0 }, + { ZT_TONE_DTMF_p, 941.0, 1477.0 }, + { ZT_TONE_DTMF_A, 697.0, 1633.0 }, + { ZT_TONE_DTMF_B, 770.0, 1633.0 }, + { ZT_TONE_DTMF_C, 852.0, 1633.0 }, + { ZT_TONE_DTMF_D, 941.0, 1633.0 }, + { 0, 0, 0 } +}; + +static struct mf_tone mf_dial[] = { + { ZT_TONE_MF_0, 1300.0, 1500.0 }, + { ZT_TONE_MF_1, 700.0, 900.0 }, + { ZT_TONE_MF_2, 700.0, 1100.0 }, + { ZT_TONE_MF_3, 900.0, 1100.0 }, + { ZT_TONE_MF_4, 700.0, 1300.0 }, + { ZT_TONE_MF_5, 900.0, 1300.0 }, + { ZT_TONE_MF_6, 1100.0, 1300.0 }, + { ZT_TONE_MF_7, 700.0, 1500.0 }, + { ZT_TONE_MF_8, 900.0, 1500.0 }, + { ZT_TONE_MF_9, 1100.0, 1500.0 }, + { ZT_TONE_MF_s, 1100.0, 1700.0 }, /* KP */ + { ZT_TONE_MF_p, 1500.0, 1700.0 }, /* ST */ + { ZT_TONE_MF_A, 900.0, 1700.0 }, /* ST' */ + { ZT_TONE_MF_B, 1300.0, 1700.0 }, /* ST'' */ + { ZT_TONE_MF_C, 700.0, 1700.0 }, /* ST''' */ + { 0, 0, 0 } +}; + +static int build_mf_tones(void *data, int size, int *count, struct mf_tone *tone, int low_tone_level, int high_tone_level) +{ + struct zt_tone_def *td; + float gain; + int used = 0; + + while (tone->tone) { + if (size < sizeof(*td)) { + fprintf(stderr, "Not enough space for samples\n"); + return -1; + } + td = data; + data += sizeof(*td); + used += sizeof(*td); + size -= sizeof(*td); + td->tone = tone->tone; + *count += 1; + + /* Bring it down 6 dBm */ + gain = pow(10.0, (low_tone_level - 3.14) / 20.0) * 65536.0 / 2.0; + td->fac1 = 2.0 * cos(2.0 * M_PI * (tone->f1 / 8000.0)) * 32768.0; + td->init_v2_1 = sin(-4.0 * M_PI * (tone->f1 / 8000.0)) * gain; + td->init_v3_1 = sin(-2.0 * M_PI * (tone->f1 / 8000.0)) * gain; + + gain = pow(10.0, (high_tone_level - 3.14) / 20.0) * 65536.0 / 2.0; + td->fac2 = 2.0 * cos(2.0 * M_PI * (tone->f2 / 8000.0)) * 32768.0; + td->init_v2_2 = sin(-4.0 * M_PI * (tone->f2 / 8000.0)) * gain; + td->init_v3_2 = sin(-2.0 * M_PI * (tone->f2 / 8000.0)) * gain; + + tone++; + } + + return used; +} + int tone_zone_register_zone(int fd, struct tone_zone *z) { char buf[MAX_SIZE]; int res; - int count=0; + int count = 0; int x; - int used = 0; - int iopenedit = 0; int space = MAX_SIZE; - char *ptr = buf; + void *ptr = buf; + int iopenedit = 1; struct zt_tone_def_header *h; - if (fd < 0) { - fd = open(DEFAULT_ZT_DEV, O_RDWR); - iopenedit=1; - if (fd < 0) { - fprintf(stderr, "Unable to open %s and fd not provided\n", DEFAULT_ZT_DEV); - return -1; - } - } - h = (struct zt_tone_def_header *)ptr; - ptr += sizeof(struct zt_tone_def_header); - space -= sizeof(struct zt_tone_def_header); - used += sizeof(struct zt_tone_def_header); - /* - * Fill in ring cadence - */ - for (x=0;x<ZT_MAX_CADENCE;x++) + + h = ptr; + ptr += sizeof(*h); + space -= sizeof(*h); + h->zone = z->zone; + + strncpy(h->name, z->description, sizeof(h->name) - 1); + + for (x = 0; x < ZT_MAX_CADENCE; x++) h->ringcadence[x] = z->ringcadence[x]; - /* Put in an appropriate method for a kernel ioctl */ - for (x=0;x<ZT_TONE_MAX;x++) { - if (strlen(z->tones[x].data)) { - /* It's a real tone */ + + for (x = 0; x < ZT_TONE_MAX; x++) { + if (!strlen(z->tones[x].data)) + continue; + #if 0 - printf("Tone: %d, string: %s\n", z->tones[x].toneid, z->tones[x].data); + printf("Tone: %d, string: %s\n", z->tones[x].toneid, z->tones[x].data); #endif - res = build_tone(ptr, space, &z->tones[x], &count); - if (res < 0) { - fprintf(stderr, "Tone not built.\n"); - if (iopenedit) - close(fd); - return -1; - } - ptr += res; - used += res; - space -= res; + if ((res = build_tone(ptr, space, &z->tones[x], &count)) < 0) { + fprintf(stderr, "Tone %d not built.\n", x); + return -1; } + ptr += res; + space -= res; } + + if ((res = build_mf_tones(ptr, space, &count, dtmf_dial, z->dtmf_low_level, z->dtmf_high_level)) < 0) { + fprintf(stderr, "Could not build DTMF tones.\n"); + return -1; + } + ptr += res; + space -= res; + + if ((res = build_mf_tones(ptr, space, &count, mf_dial, z->mf_level, z->mf_level)) < 0) { + fprintf(stderr, "Could not build MF tones.\n"); + return -1; + } + ptr += res; + space -= res; + h->count = count; - h->zone = z->zone; - strncpy(h->name, z->description, sizeof(h->name)); + + if (fd < 0) { + if ((fd = open(DEFAULT_ZT_DEV, O_RDWR)) < 0) { + fprintf(stderr, "Unable to open %s and fd not provided\n", DEFAULT_ZT_DEV); + return -1; + } + iopenedit = 1; + } + x = z->zone; - ioctl(fd, ZT_FREEZONE, &x); - res = ioctl(fd, ZT_LOADZONE, h); - if (res) + if ((res = ioctl(fd, ZT_FREEZONE, &x))) { + fprintf(stderr, "ioctl(ZT_FREEZONE) failed: %s\n", strerror(errno)); + return res; + } + +#if defined(TONEZONE_DRIVER) + dump_tone_zone(h, MAX_SIZE - space); +#endif + + if ((res = ioctl(fd, ZT_LOADZONE, h))) { fprintf(stderr, "ioctl(ZT_LOADZONE) failed: %s\n", strerror(errno)); + return res; + } + if (iopenedit) close(fd); + return res; } |