DTMF Sound Generator
This is a simple program to generate DTMF sounds using SDL as used by telephones. Simply pass the "phone number" as the command line argument.
The code:
#include <stdlib.h> #include <stdint.h> #include <stdbool.h> #include <string.h> #include <SDL2/SDL.h> #include <SDL2/SDL_audio.h> #include <math.h> /* sin() */ #define AUDIO_SAMPLE_RATE 44100 typedef struct audio_data_s { uint32_t sample_no; double freq_1; double freq_2; bool stop; bool stopped; } audio_data_t; static void dtmf(char c, double *freq_h, double *freq_v) { switch (c) { default: case '1': case '4': case '7': case '*': *freq_h = 1209; break; case '2': case '5': case '8': case '0': *freq_h = 1336; break; case '3': case '6': case '9': case '#': *freq_h = 1477; break; case 'A': case 'B': case 'C': case 'D': *freq_h = 1633; break; } switch (c) { default: case '1': case '2': case '3': case 'A': *freq_v = 697; break; case '4': case '5': case '6': case 'B': *freq_v = 770; break; case '7': case '8': case '9': case 'C': *freq_v = 852; break; case '*': case '0': case '#': case 'D': *freq_v = 941; break; } } static void audio_callback(void *userdata, Uint8 *stream, int len) { int i; audio_data_t *audio_data; double sample; double time; audio_data = (audio_data_t *)userdata; if (audio_data->stop == false) { audio_data->stopped = false; } for (i = 0; i < len; i++) { time = audio_data->sample_no / (double)AUDIO_SAMPLE_RATE; sample = sin(2.0 * M_PI * audio_data->freq_1 * time); sample += sin(2.0 * M_PI * audio_data->freq_2 * time); sample /= 2; if (audio_data->stopped) { stream[i] = 128; } else { stream[i] = (Uint8)(127 + (sample * 127)); if (audio_data->stop && stream[i] >= 126 && stream[i] <= 130) { audio_data->stopped = true; } } audio_data->sample_no++; } } int main(int argc, char *argv[]) { SDL_AudioSpec desired, obtained; audio_data_t audio_data; char *number; if (argc != 2) { fprintf(stderr, "Usage: %s <number>\n", argv[0]); return 0; } if (SDL_Init(SDL_INIT_AUDIO) != 0) { fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError()); return 1; } atexit(SDL_Quit); desired.freq = AUDIO_SAMPLE_RATE; desired.format = AUDIO_U8; desired.channels = 1; desired.samples = 1024; desired.userdata = &audio_data; desired.callback = audio_callback; if (SDL_OpenAudio(&desired, &obtained) != 0) { fprintf(stderr, "SDL_OpenAudio() failed: %s\n", SDL_GetError()); return 1; } if (obtained.format != AUDIO_U8) { fprintf(stderr, "Did not get unsigned 8-bit audio format!\n"); SDL_CloseAudio(); return 1; } for (number = &argv[1][0]; *number != '\0'; number++) { audio_data.sample_no = 0; audio_data.stop = false; dtmf(*number, &audio_data.freq_1, &audio_data.freq_2); SDL_PauseAudio(0); SDL_Delay(200); audio_data.stop = true; SDL_Delay(20); SDL_PauseAudio(1); SDL_Delay(30); } SDL_CloseAudio(); return 0; }