From a1a0b03ab9cb691dfb3d1605adbf18549d651cd6 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 5 Oct 2021 10:10:02 -0400 Subject: [PATCH] TT#136956 refactor DTMF frequency generator code Change-Id: Ibcecc6dd04971e575747e3609f01858435351d92 --- lib/codeclib.c | 40 +++++++++++++++++++++++-------------- lib/dtmflib.c | 54 +++++++++++++++++++++++++++++++++++--------------- lib/dtmflib.h | 4 ++-- 3 files changed, 65 insertions(+), 33 deletions(-) diff --git a/lib/codeclib.c b/lib/codeclib.c index 56af4f61c..c3757550b 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -2538,6 +2538,29 @@ static const char *dtmf_decoder_init(decoder_t *dec, const str *fmtp, const str return NULL; } +static AVFrame *dtmf_frame_int16_t_mono(unsigned long frame_ts, unsigned long num_samples, unsigned int event, + unsigned int volume, + unsigned int sample_rate) +{ + // synthesise PCM + // first get our frame and figure out how many samples we need, and the start offset + AVFrame *frame = av_frame_alloc(); + frame->nb_samples = num_samples; + frame->format = AV_SAMPLE_FMT_S16; + frame->sample_rate = sample_rate; + frame->channel_layout = AV_CH_LAYOUT_MONO; + frame->pts = frame_ts; + if (av_frame_get_buffer(frame, 0) < 0) + abort(); + + // fill samples + dtmf_samples_int16_t_mono(frame->extended_data[0], frame_ts, frame->nb_samples, event, + volume, sample_rate); + + return frame; + +} + static int dtmf_decoder_input(decoder_t *dec, const str *data, GQueue *out) { struct telephone_event_payload *dtmf; if (data->len < sizeof(*dtmf)) { @@ -2572,21 +2595,8 @@ static int dtmf_decoder_input(decoder_t *dec, const str *data, GQueue *out) { return -1; } - // synthesise PCM - // first get our frame and figure out how many samples we need, and the start offset - AVFrame *frame = av_frame_alloc(); - frame->nb_samples = num_samples; - frame->format = AV_SAMPLE_FMT_S16; - frame->sample_rate = dec->in_format.clockrate; - frame->channel_layout = AV_CH_LAYOUT_MONO; - frame->pts = frame_ts; - if (av_frame_get_buffer(frame, 0) < 0) - abort(); - - // fill samples - dtmf_samples(frame->extended_data[0], frame_ts, frame->nb_samples, dtmf->event, - dtmf->volume, dec->in_format.clockrate); - + AVFrame *frame = dtmf_frame_int16_t_mono(frame_ts, num_samples, dtmf->event, dtmf->volume, + dec->in_format.clockrate); g_queue_push_tail(out, frame); dec->u.dtmf.duration = duration; diff --git a/lib/dtmflib.c b/lib/dtmflib.c index 466d8efbe..a2c6da269 100644 --- a/lib/dtmflib.c +++ b/lib/dtmflib.c @@ -35,8 +35,43 @@ INLINE double freq2iter(unsigned int hz, unsigned int sample_rate) { return ret; } -void dtmf_samples(void *buf, unsigned long offset, unsigned long num, unsigned int event, unsigned int volume, - unsigned int sample_rate) +// only packed audio supported + +#define freq_samples_x(type, mult) \ +INLINE void freq_samples_ ## type(type *samples, unsigned long offset, unsigned long num, unsigned int prim_freq, \ + unsigned int sec_freq, unsigned int volume, unsigned int sample_rate, unsigned int channels) \ +{ \ + if (!channels) \ + channels = 1; \ + /* XXX initialise/save these when the DTMF event starts */ \ + double vol = pow(1.122018, volume) * 2.0; \ + \ + double prim_iter = freq2iter(prim_freq, sample_rate); \ + double sec_iter = sec_freq ? freq2iter(sec_freq, sample_rate) : 0; \ + \ + num += offset; /* end here */ \ + while (offset < num) { \ + double prim = sin(prim_iter * offset) / vol; \ + type sample; \ + if (!sec_freq) \ + sample = prim * mult; \ + else { \ + double sec = sin(sec_iter * offset) / vol; \ + sample = prim * mult + sec * mult; \ + } \ + for (unsigned int ch = 0; ch < channels; ch++) \ + *samples++ = sample; \ + offset++; \ + } \ +} + +freq_samples_x(int16_t, 32767.0) +freq_samples_x(int32_t, 2147483647.0) +freq_samples_x(double, 1.0) +freq_samples_x(float, 1.0) + +void dtmf_samples_int16_t_mono(void *buf, unsigned long offset, unsigned long num, unsigned int event, + unsigned int volume, unsigned int sample_rate) { int16_t *samples = buf; const struct dtmf_freq *df; @@ -54,18 +89,5 @@ void dtmf_samples(void *buf, unsigned long offset, unsigned long num, unsigned i } df = &dtmf_freqs[event]; - // XXX initialise/save these when the DTMF event starts - double vol = pow(1.122018, volume) * 2.0; - - double prim_freq = freq2iter(df->prim, sample_rate); - double sec_freq = freq2iter(df->sec, sample_rate); - - num += offset; // end here - while (offset < num) { - double prim = sin(prim_freq * offset) / vol; - double sec = sin(sec_freq * offset) / vol; - int16_t sample = prim * 32767.0 + sec * 32767.0; - *samples++ = sample; - offset++; - } + freq_samples_int16_t(samples, offset, num, df->prim, df->sec, volume, sample_rate, 1); } diff --git a/lib/dtmflib.h b/lib/dtmflib.h index 4d1b08e03..8c85d9e6c 100644 --- a/lib/dtmflib.h +++ b/lib/dtmflib.h @@ -22,8 +22,8 @@ struct telephone_event_payload { } __attribute__ ((packed)); -void dtmf_samples(void *buf, unsigned long offset, unsigned long num, unsigned int event, unsigned int volume, - unsigned int sample_rate); +void dtmf_samples_int16_t_mono(void *buf, unsigned long offset, unsigned long num, unsigned int event, + unsigned int volume, unsigned int sample_rate); #endif