5
|
1 /*
|
|
2 * SpanDSP - a series of DSP components for telephony
|
|
3 *
|
|
4 * tone_generate.c - General telephony tone generation, and specific
|
|
5 * generation of Bell MF, MFC/R2, and network supervisory tones.
|
|
6 *
|
|
7 * Written by Steve Underwood <steveu@coppice.org>
|
|
8 *
|
|
9 * Copyright (C) 2001 Steve Underwood
|
|
10 *
|
|
11 * All rights reserved.
|
|
12 *
|
|
13 * This program is free software; you can redistribute it and/or modify
|
|
14 * it under the terms of the GNU General Public License version 2, as
|
|
15 * published by the Free Software Foundation.
|
|
16 *
|
|
17 * This program is distributed in the hope that it will be useful,
|
|
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
20 * GNU General Public License for more details.
|
|
21 *
|
|
22 * You should have received a copy of the GNU General Public License
|
|
23 * along with this program; if not, write to the Free Software
|
|
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
25 *
|
|
26 * $Id: tone_generate.c,v 1.31 2006/11/28 16:59:56 steveu Exp $
|
|
27 */
|
|
28
|
|
29 /*! \file */
|
|
30
|
|
31 #ifdef HAVE_CONFIG_H
|
|
32 #include "config.h"
|
|
33 #endif
|
|
34
|
|
35 #include <inttypes.h>
|
|
36 #include <string.h>
|
|
37 #include <stdlib.h>
|
|
38 #include <stdio.h>
|
|
39 #include <time.h>
|
|
40 #include <fcntl.h>
|
|
41 #if defined(HAVE_TGMATH_H)
|
|
42 #include <tgmath.h>
|
|
43 #endif
|
|
44 #if defined(HAVE_MATH_H)
|
|
45 #include <math.h>
|
|
46 #endif
|
|
47
|
|
48 #include "spandsp/telephony.h"
|
|
49 #include "spandsp/dc_restore.h"
|
|
50 #include "spandsp/dds.h"
|
|
51 #include "spandsp/tone_generate.h"
|
|
52
|
|
53 #if !defined(M_PI)
|
|
54 /* C99 systems may not define M_PI */
|
|
55 #define M_PI 3.14159265358979323846264338327
|
|
56 #endif
|
|
57
|
|
58 #define ms_to_samples(t) (((t)*SAMPLE_RATE)/1000)
|
|
59
|
|
60 void make_tone_gen_descriptor(tone_gen_descriptor_t *s,
|
|
61 int f1,
|
|
62 int l1,
|
|
63 int f2,
|
|
64 int l2,
|
|
65 int d1,
|
|
66 int d2,
|
|
67 int d3,
|
|
68 int d4,
|
|
69 int repeat)
|
|
70 {
|
|
71 memset(s, 0, sizeof(*s));
|
|
72 if (f1 >= 1)
|
|
73 {
|
|
74 s->phase_rate[0] = dds_phase_ratef((float) f1);
|
|
75 s->gain[0] = dds_scaling_dbm0f((float) l1);
|
|
76 }
|
|
77 s->modulate = (f2 < 0);
|
|
78 if (f2)
|
|
79 {
|
|
80 s->phase_rate[1] = dds_phase_ratef((float) abs(f2));
|
|
81 s->gain[1] = (s->modulate) ? (float) l2/100.0f : dds_scaling_dbm0f((float) l2);
|
|
82 }
|
|
83
|
|
84 s->duration[0] = d1*8;
|
|
85 s->duration[1] = d2*8;
|
|
86 s->duration[2] = d3*8;
|
|
87 s->duration[3] = d4*8;
|
|
88
|
|
89 s->repeat = repeat;
|
|
90 }
|
|
91 /*- End of function --------------------------------------------------------*/
|
|
92
|
|
93 void make_tone_descriptor(tone_gen_descriptor_t *desc, cadenced_tone_t *tone)
|
|
94 {
|
|
95 make_tone_gen_descriptor(desc,
|
|
96 tone->f1,
|
|
97 tone->level1,
|
|
98 tone->f2,
|
|
99 tone->level2,
|
|
100 tone->on_time1,
|
|
101 tone->off_time1,
|
|
102 tone->on_time2,
|
|
103 tone->off_time2,
|
|
104 tone->repeat);
|
|
105 }
|
|
106 /*- End of function --------------------------------------------------------*/
|
|
107
|
|
108 void tone_gen_init(tone_gen_state_t *s, tone_gen_descriptor_t *t)
|
|
109 {
|
|
110 int i;
|
|
111
|
|
112 s->phase_rate[0] = t->phase_rate[0];
|
|
113 s->gain[0] = t->gain[0];
|
|
114 s->phase_rate[1] = t->phase_rate[1];
|
|
115 s->gain[1] = t->gain[1];
|
|
116 s->modulate = t->modulate;
|
|
117
|
|
118 for (i = 0; i < 4; i++)
|
|
119 s->duration[i] = t->duration[i];
|
|
120 s->repeat = t->repeat;
|
|
121
|
|
122 s->phase[0] = 0;
|
|
123 s->phase[1] = 0;
|
|
124
|
|
125 s->current_section = 0;
|
|
126 s->current_position = 0;
|
|
127 }
|
|
128 /*- End of function --------------------------------------------------------*/
|
|
129
|
|
130 int tone_gen(tone_gen_state_t *s, int16_t amp[], int max_samples)
|
|
131 {
|
|
132 int samples;
|
|
133 int limit;
|
|
134 float xamp;
|
|
135 float yamp;
|
|
136
|
|
137 if (s->current_section < 0)
|
|
138 return 0;
|
|
139
|
|
140 for (samples = 0; samples < max_samples; )
|
|
141 {
|
|
142 limit = samples + s->duration[s->current_section] - s->current_position;
|
|
143 if (limit > max_samples)
|
|
144 limit = max_samples;
|
|
145
|
|
146 s->current_position += (limit - samples);
|
|
147 if (s->current_section & 1)
|
|
148 {
|
|
149 /* A silent section */
|
|
150 for ( ; samples < limit; samples++)
|
|
151 amp[samples] = 0;
|
|
152 }
|
|
153 else
|
|
154 {
|
|
155 for ( ; samples < limit; samples++)
|
|
156 {
|
|
157 xamp = 0.0;
|
|
158 if (s->phase_rate[0])
|
|
159 xamp = dds_modf(&(s->phase[0]), s->phase_rate[0], s->gain[0], 0);
|
|
160 if (s->phase_rate[1])
|
|
161 {
|
|
162 yamp = dds_modf(&(s->phase[1]), s->phase_rate[1], s->gain[1], 0);
|
|
163 if (s->modulate)
|
|
164 xamp *= (1.0f + yamp);
|
|
165 else
|
|
166 xamp += yamp;
|
|
167 }
|
|
168 /* Saturation of the answer is the right thing at this point.
|
|
169 However, we are normally generating well controlled tones,
|
|
170 that cannot clip. So, the overhead of doing saturation is
|
|
171 a waste of valuable time. */
|
|
172 amp[samples] = (int16_t) lrintf(xamp);
|
|
173 }
|
|
174 }
|
|
175 if (s->current_position >= s->duration[s->current_section])
|
|
176 {
|
|
177 s->current_position = 0;
|
|
178 if (++s->current_section > 3 || s->duration[s->current_section] == 0)
|
|
179 {
|
|
180 if (!s->repeat)
|
|
181 {
|
|
182 /* Force a quick exit */
|
|
183 s->current_section = -1;
|
|
184 break;
|
|
185 }
|
|
186 s->current_section = 0;
|
|
187 }
|
|
188 }
|
|
189 }
|
|
190 return samples;
|
|
191 }
|
|
192 /*- End of function --------------------------------------------------------*/
|
|
193 /*- End of file ------------------------------------------------------------*/
|