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;
}