Ring Daemon 16.0.0
Loading...
Searching...
No Matches
dtmfgenerator.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2004-2025 Savoir-faire Linux Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#include "dtmfgenerator.h"
18#include "libav_deps.h"
19
20#include <cmath>
21#include <cassert>
22#include <ciso646> // fix windows compiler bug
23
24namespace jami {
25
26/*
27 * Tone frequencies
28 */
29const DTMFGenerator::DTMFTone DTMFGenerator::tones_[] = {{'0', 941, 1336},
30 {'1', 697, 1209},
31 {'2', 697, 1336},
32 {'3', 697, 1477},
33 {'4', 770, 1209},
34 {'5', 770, 1336},
35 {'6', 770, 1477},
36 {'7', 852, 1209},
37 {'8', 852, 1336},
38 {'9', 852, 1477},
39 {'A', 697, 1633},
40 {'B', 770, 1633},
41 {'C', 852, 1633},
42 {'D', 941, 1633},
43 {'*', 941, 1209},
44 {'#', 941, 1477}};
45
46/*
47 * Initialize the generator
48 */
49DTMFGenerator::DTMFGenerator(unsigned int sampleRate, AVSampleFormat sampleFormat)
50 : state()
51 , sampleRate_(sampleRate)
52 , tone_("", sampleRate, sampleFormat)
53{
54 state.offset = 0;
55 state.sample = 0;
56
57 for (int i = 0; i < NUM_TONES; i++)
58 toneBuffers_[i] = fillToneBuffer(i);
59}
60
63
64using std::vector;
65
66void DTMFGenerator::getSamples(AVFrame* frame, unsigned char code) {
67 code = toupper(code);
68
69 if (code >= '0' and code <= '9')
70 state.sample = toneBuffers_[code - '0'].get();
71 else if (code >= 'A' and code <= 'D')
72 state.sample = toneBuffers_[code - 'A' + 10].get();
73 else {
74 switch (code) {
75 case '*':
76 state.sample = toneBuffers_[NUM_TONES - 2].get();
77 break;
78
79 case '#':
80 state.sample = toneBuffers_[NUM_TONES - 1].get();
81 break;
82
83 default:
84 throw DTMFException("Invalid code");
85 break;
86 }
87 }
88
89 av_samples_copy(frame->data, state.sample->data, 0, state.offset, frame->nb_samples, frame->ch_layout.nb_channels, (AVSampleFormat)frame->format);
90 state.offset = frame->nb_samples % sampleRate_;
91}
92
93/*
94 * Get next n samples (continues where previous call to
95 * genSample or genNextSamples stopped
96 */
98 if (state.sample == 0)
99 throw DTMFException("DTMF generator not initialized");
100
101 av_samples_copy(frame->data, state.sample->data, 0, state.offset, frame->nb_samples, frame->ch_layout.nb_channels, (AVSampleFormat)frame->format);
102 state.offset = (state.offset + frame->nb_samples) % sampleRate_;
103}
104
105
107DTMFGenerator::fillToneBuffer(int index)
108{
109 assert(index >= 0 and index < NUM_TONES);
111 ptr->nb_samples = sampleRate_;
112 ptr->format = tone_.getFormat().sampleFormat;
113 ptr->sample_rate = sampleRate_;
114 ptr->channel_layout = AV_CH_LAYOUT_MONO;
116 av_frame_get_buffer(ptr.get(), 0);
117 tone_.genSin(ptr.get(), 0, ptr->nb_samples, tones_[index].higher, tones_[index].lower);
118 return ptr;
119}
120
121} // namespace jami
AudioFormat getFormat() const
Definition audioloop.h:74
void getNextSamples(AVFrame *frame)
DTMFGenerator(unsigned int sampleRate, AVSampleFormat sampleFormat)
DTMF Generator contains frequency of each keys and can build one DTMF.
void getSamples(AVFrame *frame, unsigned char code)
static void genSin(AVFrame *buffer, size_t outPos, unsigned nb_samples, unsigned frequency1, unsigned frequency2)
Add a simple or double sin to the buffer, it double the sin in stereo.
Definition tone.cpp:111
#define NUM_TONES
void emitSignal(Args... args)
Definition ring_signal.h:64
std::unique_ptr< AVFrame, AVFrame_deleter > FrameBuffer
AVSampleFormat sampleFormat