Created
April 9, 2022 21:13
-
-
Save r4d10n/93f6927eabb88294a0cda62d94ed5e23 to your computer and use it in GitHub Desktop.
DTMF WAV files Generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| 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