diff --git a/README.md b/README.md index dacec9b07..e1982f6ef 100644 --- a/README.md +++ b/README.md @@ -1523,8 +1523,8 @@ Optionally included keys are: Used in the `block DTMF` message to select the DTMF blocking mode. The default mode is `drop` which simply drops DTMF event packets. The other - supported mode is `silence` which replaces DTMF events with silence - audio. + supported modes are: `silence` which replaces DTMF events with silence + audio; `tone` which replaces DTMF events with a single sine wave tone. * `delay-buffer` diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 0c17c6f67..5900cfb43 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1332,6 +1332,9 @@ static void call_ng_main_flags(struct sdp_ng_flags *out, str *key, bencode_item_ case CSH_LOOKUP("silence"): out->block_dtmf_mode = BLOCK_DTMF_SILENCE; break; + case CSH_LOOKUP("tone"): + out->block_dtmf_mode = BLOCK_DTMF_TONE; + break; default: ilog(LOG_WARN, "Unknown 'DTMF-security' flag encountered: '" STR_FORMAT "'", STR_FMT(&s)); diff --git a/daemon/codec.c b/daemon/codec.c index 9039c49c1..50a1e9259 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -2386,6 +2386,10 @@ static void delay_frame_manipulate(struct delay_frame *dframe) { case BLOCK_DTMF_SILENCE: memset(frame->extended_data[0], 0, frame->linesize[0]); break; + case BLOCK_DTMF_TONE: + frame_fill_tone_samples(frame->format, frame->extended_data[0], dframe->ts, + frame->nb_samples, 400, 10, frame->sample_rate, frame->channels); + break; default: break; } diff --git a/include/call.h b/include/call.h index 9de2f8823..39eb53fd2 100644 --- a/include/call.h +++ b/include/call.h @@ -205,7 +205,8 @@ enum block_dtmf_mode { BLOCK_DTMF___PCM_REPLACE_START = 2, BLOCK_DTMF_SILENCE = 2, - BLOCK_DTMF___PCM_REPLACE_END = 2, + BLOCK_DTMF_TONE = 3, + BLOCK_DTMF___PCM_REPLACE_END = 3, }; diff --git a/lib/codeclib.c b/lib/codeclib.c index c3757550b..0ef6dc152 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -2633,3 +2633,26 @@ static int cn_decoder_input(decoder_t *dec, const str *data, GQueue *out) { return -1; return 0; } + + +void frame_fill_tone_samples(enum AVSampleFormat fmt, void *samples, unsigned int offset, unsigned int num, + unsigned int freq, unsigned int volume, unsigned int sample_rate, unsigned int channels) +{ + switch (fmt) { + case AV_SAMPLE_FMT_S16: + tone_samples_int16_t(samples, offset, num, freq, volume, sample_rate, channels); + break; + case AV_SAMPLE_FMT_S32: + tone_samples_int32_t(samples, offset, num, freq, volume, sample_rate, channels); + break; + case AV_SAMPLE_FMT_DBL: + tone_samples_double(samples, offset, num, freq, volume, sample_rate, channels); + break; + case AV_SAMPLE_FMT_FLT: + tone_samples_float(samples, offset, num, freq, volume, sample_rate, channels); + break; + default: + ilog(LOG_ERR | LOG_FLAG_LIMIT, "Unsupported sample format %u", fmt); + break; + } +} diff --git a/lib/codeclib.h b/lib/codeclib.h index 4ebbe1908..9e6e9459d 100644 --- a/lib/codeclib.h +++ b/lib/codeclib.h @@ -341,6 +341,10 @@ void *packet_sequencer_force_next_packet(packet_sequencer_t *ps); int packet_sequencer_insert(packet_sequencer_t *ps, seq_packet_t *); +void frame_fill_tone_samples(enum AVSampleFormat fmt, void *samples, unsigned int offset, unsigned int num, + unsigned int freq, unsigned int volume, unsigned int sample_rate, unsigned int channels); + + #include "auxlib.h" diff --git a/lib/dtmflib.c b/lib/dtmflib.c index 4b3e91065..02ea025e7 100644 --- a/lib/dtmflib.c +++ b/lib/dtmflib.c @@ -209,6 +209,18 @@ freq_samples_x(int32_t, 2147483647.0) freq_samples_x(double, 1.0) freq_samples_x(float, 1.0) +#define tone_samples_x(type) \ +void tone_samples_ ## type(type *samples, unsigned long offset, unsigned long num, unsigned int freq, \ + unsigned int volume, unsigned int sample_rate, unsigned int channels) \ +{ \ + freq_samples_ ## type(samples, offset, num, freq, 0, volume, sample_rate, channels); \ +} + +tone_samples_x(int16_t) +tone_samples_x(int32_t) +tone_samples_x(double) +tone_samples_x(float) + void dtmf_samples_int16_t_mono(void *buf, unsigned long offset, unsigned long num, unsigned int event, unsigned int volume, unsigned int sample_rate) { diff --git a/lib/dtmflib.h b/lib/dtmflib.h index 8c85d9e6c..db0decb46 100644 --- a/lib/dtmflib.h +++ b/lib/dtmflib.h @@ -26,4 +26,14 @@ void dtmf_samples_int16_t_mono(void *buf, unsigned long offset, unsigned long nu unsigned int volume, unsigned int sample_rate); +void tone_samples_int16_t(int16_t *buf, unsigned long offset, unsigned long num, unsigned int freq, + unsigned int volume, unsigned int sample_rate, unsigned int channels); +void tone_samples_int32_t(int32_t *buf, unsigned long offset, unsigned long num, unsigned int freq, + unsigned int volume, unsigned int sample_rate, unsigned int channels); +void tone_samples_double(double *buf, unsigned long offset, unsigned long num, unsigned int freq, + unsigned int volume, unsigned int sample_rate, unsigned int channels); +void tone_samples_float(float *buf, unsigned long offset, unsigned long num, unsigned int freq, + unsigned int volume, unsigned int sample_rate, unsigned int channels); + + #endif