/* Telphone Tones generator A.J. Fisher August 1995 C++ vsn AJF Dec. 1999 */ #include #include #include #include #include #define global #define unless(x) if(!(x)) #define until(x) while(!(x)) #define MAXSTR 512 #define SAMPLERATE 8000 #define SINEBITS 11 #define SINELEN (1 << SINEBITS) #define TWOPI (2.0 * M_PI) #define TWO32 4294967296.0 /* 2^32 */ typedef unsigned char uchar; typedef unsigned int uint; union word { word(char *sx) { s = sx; } word(int nx) { n = nx; } char *s; int n; }; static short expandtab[128]; /* entries 0 .. 32767 */ static char compresstab[32768]; /* entries 0 .. 127 */ static double sinetab[SINELEN]; static int header[8] = { 0x2e736e64, /* ".snd" magic number */ 32, /* length of hdr */ 0, /* *nominal* length of body, in samples */ 1, SAMPLERATE, 1, 0, 0, /* don't ask me what this means! */ }; extern "C" int atoi(char*); static void newhandler(), initaudio(), makeexpandtab(), makecompresstab(), makesinetab(); static void sendheader(), writeword(uint); static void senddtmf(char*), sendtone(int), sendwarble(double, double), sendfreqs(double, double, int, int); static void usage(), fail(char*, word = 0); inline int ifix(double x) { return (x >= 0.0) ? (int) (x+0.5) : (int) (x-0.5); } global void main() { set_new_handler(newhandler); logweb("teletones", ""); getentries(); initaudio(); if (isset("dial")) { char *s = getval("dial"); senddtmf(s); } else if (isset("tone")) { char *s = getval("tone"); sendtone(atoi(s)); } else usage(); exit(0); } static void newhandler() { fail("No room!"); } static void initaudio() { makeexpandtab(); makecompresstab(); makesinetab(); sendheader(); } static void makeexpandtab() { /* make mu-law expanding table */ for (int n = 0; n < 128; n++) { double x = (pow(256.0, (double) n / 127.0) - 1.0) / 255.0; /* result in range 0 .. 1 */ expandtab[n] = ifix(x * 32767.0); /* in range 0 .. 32767 */ } } static void makecompresstab() { /* make mu-law compressing table */ int i = 0, j = 0; while (i < 32768) { compresstab[i] = j; if (j < 127 && (expandtab[j+1] - i) < (i - expandtab[j])) j++; i++; } } static void makesinetab() { for (int k = 0; k < SINELEN; k++) { double th = TWOPI * (double) k / (double) SINELEN; sinetab[k] = sin(th); } } static void sendheader() { printf("Content-Type: audio/basic\n\n"); for (int i = 0; i < 8; i++) writeword(header[i]); } static void writeword(uint n) { #ifdef linux for (int i = 0; i < 4; i++) { putchar(n >> 24); n <<= 8; } #else for (int i = 0; i < 4; i++) { putchar(n & 0xff); n >>= 8; } #endif } static double rowtab[4] = { 697.0, 770.0, 852.0, 941.0 }; static double coltab[4] = { 1209.0, 1336.0, 1477.0, 1633.0 }; static void senddtmf(char *s) { int k = 0; until (s[k] == '\0') { char c = s[k++]; char *dstr = "123A456B789C*0#D"; char *p = strchr(dstr, c); unless (p == NULL) { uchar n = p - dstr; sendfreqs(rowtab[n >> 2], coltab[n & 3], 100, 1); /* tones for 100 ms */ sendfreqs(0.0, 0.0, 100, 1); /* silence for 100 ms */ } } } static void sendtone(int n) { switch (n) { default: usage(); case 0: /* BT */ { for (int i = 0; i < 14; i++) { sendfreqs(400.0, 400.0, 375, 1); sendfreqs(0.0, 0.0, 375, 1); } break; } case 1: /* EET */ { for (int i = 0; i < 7; i++) { sendfreqs(400.0, 400.0, 400, 0); /* quieter */ sendfreqs(0.0, 0.0, 350, 0); sendfreqs(400.0, 400.0, 225, 1); sendfreqs(0.0, 0.0, 525, 1); } break; } case 2: /* RT */ { for (int i = 0; i < 4; i++) { sendfreqs(400.0, 450.0, 400, 1); sendfreqs(0.0, 0.0, 200, 1); sendfreqs(400.0, 450.0, 400, 1); sendfreqs(0.0, 0.0, 2000, 1); } break; } case 3: /* NU */ { sendfreqs(400.0, 400.0, 10000, 1); break; } case 4: /* PT */ { for (int i = 0; i < 40; i++) { sendfreqs(400.0, 400.0, 125, 1); sendfreqs(0.0, 0.0, 125, 1); } break; } case 5: /* DT */ { sendfreqs(350.0, 450.0, 10000, 1); break; } case 6: /* Warble 1 */ { for (int i = 0; i < 4; i++) { sendwarble(1500.0, 1700.0); sendfreqs(0.0, 0.0, 200, 1); sendwarble(1500.0, 1700.0); sendfreqs(0.0, 0.0, 2000, 1); } break; } case 7: /* Warble 2 */ { for (int i = 0; i < 4; i++) { sendwarble(900.0, 1100.0); sendfreqs(0.0, 0.0, 200, 1); sendwarble(900.0, 1100.0); sendfreqs(0.0, 0.0, 2000, 1); } break; } } } static void sendwarble(double f1, double f2) { /* 400ms of warble */ for (int i = 0; i < 3; i++) { sendfreqs(f1, f1, 62, 1); sendfreqs(f2, f2, 63, 1); } sendfreqs(f1, f1, 25, 1); } static double amptab[2] = { 8191.75, 16383.5 }; inline int phinc(double f) { /* given frequency f, return corresponding phase increment */ return ifix(TWO32 * f / (double) SAMPLERATE); } inline double sine(uint ptr) { /* given 32-bit pointer ptr, return corresponding element from sine table */ return sinetab[ptr >> (32-SINEBITS)]; } static void sendfreqs(double f1, double f2, int ms, int ak) { double amp = amptab[ak]; int phinc1 = phinc(f1), phinc2 = phinc(f2); int ns = ms * (SAMPLERATE/1000); uint ptr1 = 0, ptr2 = 0; for (int n = 0; n < ns; n++) { double val = amp * (sine(ptr1) + sine(ptr2)); int ival = ifix(val); if (ival < -32768 || ival > 32767) fail("Bug! out of range: %08x", ival); putchar((ival >= 0) ? 255 - compresstab[ival] : 127 - compresstab[~ival]); ptr1 += phinc1; ptr2 += phinc2; } } static void usage() { fail("Usage error!"); } static void fail(char *msg, word p1) { discard_output(); /* in case we've sent audio/basic */ printf("Content-type: text/html\n\n"); printf("\n\n"); printf("

Error!

\n"); printf(msg, p1); putchar('\n'); exit(0); }
file: /Techref/uk/ac/york/cs/www-users/http/~fisher/telecom/tones/teletones.C, 5KB, , updated: 2000/4/4 12:33, local time: 2024/6/14 10:06,
TOP NEW HELP FIND: 
3.16.75.9:LOG IN

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://www.piclist.com/techref/uk/ac/york/cs/www-users/http/~fisher/telecom/tones/teletones.C"> uk ac york cs www-users http ~fisher telecom tones teletones</A>

Did you find what you needed?

  PICList 2024 contributors:
o List host: MIT, Site host massmind.org, Top posters @none found
- Page Editors: James Newton, David Cary, and YOU!
* Roman Black of Black Robotics donates from sales of Linistep stepper controller kits.
* Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters.
* Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated!
* Contributors: Richard Seriani, Sr.
 
Quick, Easy and CHEAP! RCL-1 RS232 Level Converter in a DB9 backshell
Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .