Skip to content

Instantly share code, notes, and snippets.

@r4d10n
Created April 9, 2022 21:13
Show Gist options
  • Select an option

  • Save r4d10n/93f6927eabb88294a0cda62d94ed5e23 to your computer and use it in GitHub Desktop.

Select an option

Save r4d10n/93f6927eabb88294a0cda62d94ed5e23 to your computer and use it in GitHub Desktop.
DTMF WAV files Generator
/*
DTMF WAV Generator
Based on (1) https://stackoverflow.com/a/23036909
(2) https://github.com/elshnkhll/DTMF_on_MAX98357A/blob/master/DTMF.h
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
#include <string.h>
int dtmf[16][2] = {
{941, 1336}, // 0
{697, 1209}, // 1
{697, 1336}, // 2
{697, 1477}, // 3
{770, 1209}, // 4
{770, 1336}, // 5
{770, 1477}, // 6
{852, 1209}, // 7
{852, 1336}, // 8
{852, 1477}, // 9
{697, 1633}, // A
{770, 1633}, // B
{852, 1633}, // C
{941, 1633}, // D
{941, 1209}, // *
{941, 1477} // #
};
char dtmf_key[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', '*', '#'};
/*
The header of a wav file Based on:
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
*/
typedef struct wavfile_header_s {
char ChunkID[4]; /* 4 */
int32_t ChunkSize; /* 4 */
char Format[4]; /* 4 */
char Subchunk1ID[4]; /* 4 */
int32_t Subchunk1Size; /* 4 */
int16_t AudioFormat; /* 2 */
int16_t NumChannels; /* 2 */
int32_t SampleRate; /* 4 */
int32_t ByteRate; /* 4 */
int16_t BlockAlign; /* 2 */
int16_t BitsPerSample; /* 2 */
char Subchunk2ID[4];
int32_t Subchunk2Size;
} wavfile_header_t;
typedef struct PCM16_stereo_s {
int16_t left;
int16_t right;
} PCM16_stereo_t;
#define SUBCHUNK1SIZE (16)
#define AUDIO_FORMAT (1) /*For PCM*/
#define NUM_CHANNELS (2)
#define SAMPLE_RATE (16000)
#define BITS_PER_SAMPLE (16)
#define BYTE_RATE (SAMPLE_RATE * NUM_CHANNELS * BITS_PER_SAMPLE / 8)
#define BLOCK_ALIGN (NUM_CHANNELS * BITS_PER_SAMPLE / 8)
#define TONE_DURATION (1) // 1s Duration
#define FRAME_COUNT (TONE_DURATION * SAMPLE_RATE)
#define HEADER_SIZE (sizeof(wavfile_header_t))
#define FILE_SIZE (HEADER_SIZE + FRAME_COUNT)
wavfile_header_t generate_wave_header() {
wavfile_header_t wav_header;
int32_t subchunk2_size;
int32_t chunk_size;
size_t write_count;
subchunk2_size = FRAME_COUNT * NUM_CHANNELS * BITS_PER_SAMPLE / 8;
chunk_size = 4 + (8 + SUBCHUNK1SIZE) + (8 + subchunk2_size);
wav_header.ChunkID[0] = 'R';
wav_header.ChunkID[1] = 'I';
wav_header.ChunkID[2] = 'F';
wav_header.ChunkID[3] = 'F';
wav_header.ChunkSize = chunk_size;
wav_header.Format[0] = 'W';
wav_header.Format[1] = 'A';
wav_header.Format[2] = 'V';
wav_header.Format[3] = 'E';
wav_header.Subchunk1ID[0] = 'f';
wav_header.Subchunk1ID[1] = 'm';
wav_header.Subchunk1ID[2] = 't';
wav_header.Subchunk1ID[3] = ' ';
wav_header.Subchunk1Size = SUBCHUNK1SIZE;
wav_header.AudioFormat = AUDIO_FORMAT;
wav_header.NumChannels = NUM_CHANNELS;
wav_header.SampleRate = SAMPLE_RATE;
wav_header.ByteRate = BYTE_RATE;
wav_header.BlockAlign = BLOCK_ALIGN;
wav_header.BitsPerSample = BITS_PER_SAMPLE;
wav_header.Subchunk2ID[0] = 'd';
wav_header.Subchunk2ID[1] = 'a';
wav_header.Subchunk2ID[2] = 't';
wav_header.Subchunk2ID[3] = 'a';
wav_header.Subchunk2Size = subchunk2_size;
return wav_header;
}
void generate_DTMF(int dtmf_index, PCM16_stereo_t *buffer_p) {
double amplitude = 0.5 * SHRT_MAX;
float w1 = 2.0 * 3.141592 * (float)dtmf[dtmf_index][0] / (float)SAMPLE_RATE;
float w2 = 2.0 * 3.141592 * (float)dtmf[dtmf_index][1] / (float)SAMPLE_RATE;
for(int32_t k = 0; k < FILE_SIZE; k++) {
if (k < HEADER_SIZE / sizeof(PCM16_stereo_t)) {
buffer_p[k].left = 0;
buffer_p[k].right = 0;
}
else {
buffer_p[k].left = (int16_t)((amplitude * sin((float)k * w1)) + (amplitude * sin((float)k * w2)));
buffer_p[k].right = buffer_p[k].left;
}
}
}
int main(int argc, char *argv[]) {
int ret;
FILE *fptr;
char fname[30];
PCM16_stereo_t buffer_p[sizeof(wavfile_header_t) + FRAME_COUNT];
wavfile_header_t wave_header = generate_wave_header();
for(int i=0; i < 16; i++) {
generate_DTMF(i, buffer_p);
memcpy((void *)&buffer_p, (void *)&wave_header, sizeof(wave_header));
sprintf(fname, "%d.wav", i);
fptr = fopen(fname, "wb");
fwrite((void *)&buffer_p, sizeof(PCM16_stereo_t), FRAME_COUNT, fptr);
fclose(fptr);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment