Line data Source code
1 : /*
2 : * Copyright (C) 2004-2024 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 :
24 : namespace jami {
25 :
26 : /*
27 : * Tone frequencies
28 : */
29 : const 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 : */
49 33 : DTMFGenerator::DTMFGenerator(unsigned int sampleRate, AVSampleFormat sampleFormat)
50 33 : : state()
51 33 : , sampleRate_(sampleRate)
52 33 : , tone_("", sampleRate, sampleFormat)
53 : {
54 33 : state.offset = 0;
55 33 : state.sample = 0;
56 :
57 561 : for (int i = 0; i < NUM_TONES; i++)
58 528 : toneBuffers_[i] = fillToneBuffer(i);
59 33 : }
60 :
61 33 : DTMFGenerator::~DTMFGenerator()
62 33 : {}
63 :
64 : using std::vector;
65 :
66 0 : void DTMFGenerator::getSamples(AVFrame* frame, unsigned char code) {
67 0 : code = toupper(code);
68 :
69 0 : if (code >= '0' and code <= '9')
70 0 : state.sample = toneBuffers_[code - '0'].get();
71 0 : else if (code >= 'A' and code <= 'D')
72 0 : state.sample = toneBuffers_[code - 'A' + 10].get();
73 : else {
74 0 : switch (code) {
75 0 : case '*':
76 0 : state.sample = toneBuffers_[NUM_TONES - 2].get();
77 0 : break;
78 :
79 0 : case '#':
80 0 : state.sample = toneBuffers_[NUM_TONES - 1].get();
81 0 : break;
82 :
83 0 : default:
84 0 : throw DTMFException("Invalid code");
85 : break;
86 : }
87 : }
88 :
89 0 : av_samples_copy(frame->data, state.sample->data, 0, state.offset, frame->nb_samples, frame->ch_layout.nb_channels, (AVSampleFormat)frame->format);
90 0 : state.offset = frame->nb_samples % sampleRate_;
91 0 : }
92 :
93 : /*
94 : * Get next n samples (continues where previous call to
95 : * genSample or genNextSamples stopped
96 : */
97 0 : void DTMFGenerator::getNextSamples(AVFrame* frame) {
98 0 : if (state.sample == 0)
99 0 : throw DTMFException("DTMF generator not initialized");
100 :
101 0 : av_samples_copy(frame->data, state.sample->data, 0, state.offset, frame->nb_samples, frame->ch_layout.nb_channels, (AVSampleFormat)frame->format);
102 0 : state.offset = (state.offset + frame->nb_samples) % sampleRate_;
103 0 : }
104 :
105 :
106 : libjami::FrameBuffer
107 528 : DTMFGenerator::fillToneBuffer(int index)
108 : {
109 528 : assert(index >= 0 and index < NUM_TONES);
110 528 : libjami::FrameBuffer ptr(av_frame_alloc());
111 528 : ptr->nb_samples = sampleRate_;
112 528 : ptr->format = tone_.getFormat().sampleFormat;
113 528 : ptr->sample_rate = sampleRate_;
114 528 : ptr->channel_layout = AV_CH_LAYOUT_MONO;
115 528 : av_channel_layout_from_mask(&ptr->ch_layout, AV_CH_LAYOUT_MONO);
116 528 : av_frame_get_buffer(ptr.get(), 0);
117 528 : tone_.genSin(ptr.get(), 0, ptr->nb_samples, tones_[index].higher, tones_[index].lower);
118 528 : return ptr;
119 0 : }
120 :
121 : } // namespace jami
|