/* nakodil NiO, autor neruci za cokolvek, pouzivat na vlastne riziko vsetko okrem funkcie Write_AIFF je pod licenciou GNU/GPL v2 ta funkcia pochadza z webu, vygooglite si jej zdroj. AIFF = Audio Intechangable File Format */ // samplovacia frekvencia, povolene hodnoty su 11025,22050,44100 #define SF 44100 #include #include #include #include // ** prototypy ** int zapis(char*, double*, long); double* vlna(double, long*, double); double* vytoc(char*, long*, double, double); inline long dvojton(double[], long, double, double, long); double dtmf_a(char); double dtmf_b(char); void Write_AIFF(FILE*,double*,long, int); // ** hlavna funkcia ** int main(int argc, char *argv[]) { double *p = NULL; long ns; // generacia DTMF sekvencie if((argc==6) && (!strcmp(argv[1],"dtmf"))) { double dlzka = atof(argv[3]), pauza = atof(argv[4]); p = vytoc(argv[2], &ns, dlzka, pauza); if(p==NULL) return 1; zapis(argv[5], p, ns); free(p); } else if((argc==5) && (!strcmp(argv[1],"sin"))) { double dlzka = atof(argv[3]), f = atof(argv[2]); p = vlna(f, &ns, dlzka); if(p==NULL) return 1; zapis(argv[4], p, ns); free(p); } else { printf( "%s - DTMF GENERATOR\n \n" "usage:\t%s dtmf [dtmf ton] .[dlzka tonu v sec.] .[dlzka pauzy] [vystup.au]\n" "\t%s sin [frekvencia] [dlzka tonu v sec.] [vystup.au]\n \n" "examples: %s dtmf 0123456789ABCD*# .3 .1 /tmp/phone.au\n" "\t %s dtmf 0910759842 .2 .2 /dtmf/phone.au\n" "\t %s sin 2600 1 /tmp/2600.au\n", argv[0], argv[0], argv[0], argv[0],argv[0],argv[0]); } return 0; } // zapise zvukovy buffer do suboru int zapis(char *meno, double *b, long ns) { FILE *f = NULL; f = fopen(meno,"wb"); if(f==NULL) return 1; Write_AIFF(f, b, ns, SF); fclose(f); return 0; } /* double* vlna(long* ns, double dlzka, double f) { double* b = NULL; double t = 0, tinc = 1.0f / (float)SF; // prirastok casu za jednu vzorku long i = 0, m = (int)(dlzka * (float)SF); // pocet vzorkov *ns = m + 10; // vypocet velk. bufferu + rezerva b = malloc( *ns * sizeof(double) ); // alokacia bufferu if(b==NULL) return NULL; for(i=0;i < m;i++) { // generovanie sinusu b[i] = sin(6.28f * f * t); // u = sin(2 * PI * f * t) - hodnota sinusu frekvencie f v case t t += tinc; } return b; // vraciame adresu na buffer } */ // generuje sinus do bufferu double* vlna(double f, long* ns, double dlzka) { double* b = NULL; double foo = 0, fooinc = 6.28f / (float)SF; // PI * prirastok casu za jednu vzorku long i = 0, m = (int)(dlzka * (float)SF); // pocet vzorkov *ns = m + 10; // vypocet velk. bufferu + rezerva b = malloc( *ns * sizeof(double) ); // alokacia bufferu if(b==NULL) return NULL; for(i=0;i < m;i++) { // generovanie sinusu b[i] = sin(foo * f); // u = sin(2 * PI * f * t) - hodnota sinusu frekvencie f v case t foo += fooinc; } return b; // vraciame adresu na buffer } // vygeneruje buffer podla telefonneho cisla double* vytoc(char cislo[], long* ns, double dlzka, double pauza) { double* b = NULL; long n = strlen(cislo), // pocet cifier tel. cisla ton = (int)(dlzka * (float)SF), // dlzka znenia kazdeho tonu (vo vzorkoch / 1s), ticho = (int)(pauza * (float)SF), // pauzy p = 0, // index v bufferi i = 0, cifra = 0; double fa, fb; // alokacia bufferu *ns = (int)( (double)n * (ton + ticho) ) + 10; b = malloc( *ns * sizeof(double) ); if(b==NULL) return NULL; // pre kazdu ciftu tel. cisla: for(cifra=0;cifra < n;cifra++){ // vyber frekv. tonu podla cifry fa = dtmf_a(cislo[cifra]); fb = dtmf_b(cislo[cifra]); p = dvojton(b, p, fa, fb, ton); for(i=0;i < ticho;i++){ b[p]=0; p++; } } return b; } // pom. funkcia, generuje DTMF ton, // pozor! navratova hodn. = zmeneny index v bufferi! inline long dvojton(double b[], long p, double fa, double fb, long dlzka) { long i = 0; double foo = 0, fooinc = 6.28f / (double)SF, // inkrement = PI * prirastok casu za 1 vzorku h = 1.0f; for(i=0;i < dlzka ;i++){ // vyhladi zaciatocne a konecne puknutie tonu // (zakomentovat a vyskusat pre lepsie pochopenie) if( i < 30) h = (double)i / 30.0f; else if (i > dlzka - 30) h = (double)(dlzka - i) / 30.0f; else h = 1.0f; // u = sin ( 2 * PI * f *t) - funkcia striedaveho sinusoveho napatia b[p] = h * ( sin(foo * fa) + sin(foo * fb) ) * 0.5f; p++; // index v bufferi foo += fooinc; } return p; } // vrati 1. frekv. zlozku DTMF tonu, hodnota je v Hz double dtmf_a(char c) { switch(c){ case '1': case '2': case '3': case 'A': return 697.0f; case '4': case '5': case '6': case 'B': return 770.0f; case '7': case '8': case '9': case 'C': return 852.0f; case '*': case '0': case '#': case 'D': return 941.0f; default: return 0.0f; } } // vrati 2. frekv. zlozku DTMF tonu, hodnota je v Hz double dtmf_b(char c) { switch(c){ case '1': case '4': case '7': case '*': return 1209.0f; case '2': case '5': case '8': case '0': return 1336.0f; case '3': case '6': case '9': case '#': return 1477.0f; case 'A': case 'B': case 'C': case 'D': return 1633.0f; default: return 0.0f; } } // funkcia ABS(x) // ABS(-123) = 123, ABS(321) = 321 double ABS(x) { if(x<0) return -x; return x; } // zapise buffer do suboru v AIFF formate /* Write an AIFF sound file Only do one channel, only support 16 bit. Supports sample frequencies of 11, 22, 44KHz (default). Little/big endian independent! */ void Write_AIFF(FILE *fptr,double *samples,long nsamples,int nfreq) { unsigned short v; int i; unsigned long totalsize; double themin, themax, scale, themid; /* Write the form chunk */ fprintf(fptr,"FORM"); totalsize = 4 + 8 + 18 + 8 + 2 * nsamples + 8; fputc((totalsize & 0xff000000) >> 24, fptr); fputc((totalsize & 0x00ff0000) >> 16, fptr); fputc((totalsize & 0x0000ff00) >> 8, fptr); fputc((totalsize & 0x000000ff), fptr); fprintf(fptr, "AIFF"); /* Write the common chunk */ fprintf(fptr, "COMM"); fputc(0, fptr); /* Size */ fputc(0, fptr); fputc(0, fptr); fputc(18, fptr); fputc(0, fptr); /* Channels = 1 */ fputc(1, fptr); fputc((nsamples & 0xff000000) >> 24, fptr); /* Samples */ fputc((nsamples & 0x00ff0000) >> 16, fptr); fputc((nsamples & 0x0000ff00) >> 8, fptr); fputc((nsamples & 0x000000ff), fptr); fputc(0, fptr); /* Size = 16 */ fputc(16, fptr); fputc(0x40, fptr); /* 10 byte sampee rate */ if (nfreq == 11025) fputc(0x0c, fptr); else if (nfreq == 22050) fputc(0x0d, fptr); else fputc(0x0e, fptr); fputc(0xac, fptr); fputc(0x44, fptr); fputc(0, fptr); fputc(0, fptr); fputc(0, fptr); fputc(0, fptr); fputc(0, fptr); fputc(0, fptr); /* Write the sound data chunk */ fprintf(fptr, "SSND"); fputc((2*nsamples+8 & 0xff000000) >> 24, fptr);/* Size */ fputc((2*nsamples+8 & 0x00ff0000) >> 16, fptr); fputc((2*nsamples+8 & 0x0000ff00) >> 8, fptr); fputc((2*nsamples+8 & 0x000000ff), fptr); fputc(0, fptr); /* Offset */ fputc(0, fptr); fputc(0, fptr); fputc(0, fptr); fputc(0, fptr); /* Block */ fputc(0, fptr); fputc(0, fptr); fputc(0, fptr); /* Find the range */ themin = samples[0]; themax = themin; for (i=1;i themax) themax = samples[i]; if (samples[i] < themin) themin = samples[i]; } if (themin >= themax) { themin -= 1; themax += 1; } themid = (themin + themax) / 2; themin -= themid; themax -= themid; if (ABS(themin) > ABS(themax)) themax = ABS(themin); scale = 32760 / (themax + 1); /* Write the data */ for (i=0;i> 8, fptr); fputc((v & 0x00ff), fptr); } }