#include #include #include #include #include #include #include "wav.h" void dtmf_freqs(char c, int *a, int *b) { switch (c) { case '1': case '2': case '3': case 'A': *a = 697; break; case '4': case '5': case '6': case 'B': *a = 770; break; case '7': case '8': case '9': case 'C': *a = 852; break; case '*': case '0': case '#': case 'D': *a = 941; break; default: *a = 0; } switch (c) { case '1': case '4': case '7': case '*': *b = 1209; break; case '2': case '5': case '8': case '0': *b = 1336; break; case '3': case '6': case '9': case '#': *b = 1477; break; case 'A': case 'B': case 'C': case 'D': *b = 1633; break; default: *b = 0; } } int16_t dtmf_gen(char c, int t, int rate) { int a, b; dtmf_freqs(c, &a, &b); double v = 0.5 * sin(2.0 * M_PI * (double)a * ((double)t / (double)rate)); v += 0.5 * sin(2.0 * M_PI * (double)b * ((double)t / (double)rate)); return v * 32767.0; } int main(int argc, char *argv[]) { /* usage */ if (argc != 5) { fprintf(stderr, "usage: %s \n", argv[0]); return 2; } /* read arguments */ char *outfilename = argv[1]; char *dtmf = argv[2]; int width, spacing; sscanf(argv[3], "%d", &width); sscanf(argv[4], "%d", &spacing); /* open output file */ FILE *fout = fopen(outfilename, "w"); if (fout == NULL) { fprintf(stderr, "could not open '%s' for writing.\n", outfilename); return 1; } /* create header */ struct wav_header wav_header; memcpy(wav_header.riff_magic, "RIFF", 4); memcpy(wav_header.wave_magic, "WAVE", 4); memcpy(wav_header.format_magic, "fmt ", 4); memcpy(wav_header.data_magic, "data", 4); wav_header.format_size = 16; wav_header.format_type = 1; wav_header.channels = 1; wav_header.sample_rate = 44100; wav_header.bits_per_sample = 16; wav_header.rate1 = (wav_header.sample_rate * wav_header.bits_per_sample * wav_header.channels) / 8; wav_header.rate2 = (wav_header.bits_per_sample * wav_header.channels) / 8; /* go past header */ fseek(fout, sizeof(wav_header), SEEK_SET); /* generate sound */ int num_digits = strlen(dtmf); uint32_t sample_count = wav_header.sample_rate * num_digits * (width + spacing); for (int digit_index = 0; digit_index < num_digits; digit_index++) { char digit = dtmf[digit_index]; /* emit dtmf tone */ for (int t = 0; t < (float)wav_header.sample_rate * (float)(width) / 1000.0f; t++) { int16_t sample = dtmf_gen(digit, t, wav_header.sample_rate); fwrite(&sample, sizeof(int16_t), 1, fout); } /* emit spacing */ fseek(fout, (float)wav_header.sample_rate * (float)(spacing) / 1000.0f, SEEK_CUR); } /* update header */ wav_header.size = ftell(fout) - 8; wav_header.data_size = ftell(fout) - sizeof(wav_header); /* write header */ fseek(fout, 0, SEEK_SET); fwrite(&wav_header, sizeof(wav_header), 1, fout); /* close file */ fclose(fout); return 0; }