comparison spandsp-0.0.6pre17/src/tone_generate.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * tone_generate.c - General telephony tone generation.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2001 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: tone_generate.c,v 1.53.4.1 2009/12/23 14:23:49 steveu Exp $
26 */
27
28 /*! \file */
29
30 #if defined(HAVE_CONFIG_H)
31 #include "config.h"
32 #endif
33
34 #include <inttypes.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <time.h>
39 #include <fcntl.h>
40 #if defined(HAVE_TGMATH_H)
41 #include <tgmath.h>
42 #endif
43 #if defined(HAVE_MATH_H)
44 #include <math.h>
45 #endif
46 #include "floating_fudge.h"
47
48 #include "spandsp/telephony.h"
49 #include "spandsp/fast_convert.h"
50 #include "spandsp/dc_restore.h"
51 #include "spandsp/complex.h"
52 #include "spandsp/dds.h"
53 #include "spandsp/tone_generate.h"
54
55 #include "spandsp/private/tone_generate.h"
56
57 #if !defined(M_PI)
58 /* C99 systems may not define M_PI */
59 #define M_PI 3.14159265358979323846264338327
60 #endif
61
62 SPAN_DECLARE(void) make_tone_gen_descriptor(tone_gen_descriptor_t *s,
63 int f1,
64 int l1,
65 int f2,
66 int l2,
67 int d1,
68 int d2,
69 int d3,
70 int d4,
71 int repeat)
72 {
73 memset(s, 0, sizeof(*s));
74 if (f1)
75 {
76 #if defined(SPANDSP_USE_FIXED_POINT)
77 s->tone[0].phase_rate = dds_phase_rate((float) f1);
78 if (f2 < 0)
79 s->tone[0].phase_rate = -s->tone[0].phase_rate;
80 s->tone[0].gain = dds_scaling_dbm0((float) l1);
81 #else
82 s->tone[0].phase_rate = dds_phase_ratef((float) f1);
83 if (f2 < 0)
84 s->tone[0].phase_rate = -s->tone[0].phase_rate;
85 s->tone[0].gain = dds_scaling_dbm0f((float) l1);
86 #endif
87 }
88 if (f2)
89 {
90 #if defined(SPANDSP_USE_FIXED_POINT)
91 s->tone[1].phase_rate = dds_phase_rate((float) abs(f2));
92 s->tone[1].gain = (f2 < 0) ? (float) 32767.0f*l2/100.0f : dds_scaling_dbm0((float) l2);
93 #else
94 s->tone[1].phase_rate = dds_phase_ratef((float) abs(f2));
95 s->tone[1].gain = (f2 < 0) ? (float) l2/100.0f : dds_scaling_dbm0f((float) l2);
96 #endif
97 }
98
99 s->duration[0] = d1*SAMPLE_RATE/1000;
100 s->duration[1] = d2*SAMPLE_RATE/1000;
101 s->duration[2] = d3*SAMPLE_RATE/1000;
102 s->duration[3] = d4*SAMPLE_RATE/1000;
103
104 s->repeat = repeat;
105 }
106 /*- End of function --------------------------------------------------------*/
107
108 SPAN_DECLARE(tone_gen_state_t *) tone_gen_init(tone_gen_state_t *s, tone_gen_descriptor_t *t)
109 {
110 int i;
111
112 if (s == NULL)
113 return NULL;
114 for (i = 0; i < 4; i++)
115 {
116 s->tone[i] = t->tone[i];
117 s->phase[i] = 0;
118 }
119
120 for (i = 0; i < 4; i++)
121 s->duration[i] = t->duration[i];
122 s->repeat = t->repeat;
123
124 s->current_section = 0;
125 s->current_position = 0;
126 return s;
127 }
128 /*- End of function --------------------------------------------------------*/
129
130 SPAN_DECLARE(int) tone_gen_release(tone_gen_state_t *s)
131 {
132 return 0;
133 }
134 /*- End of function --------------------------------------------------------*/
135
136 SPAN_DECLARE(int) tone_gen_free(tone_gen_state_t *s)
137 {
138 if (s)
139 free(s);
140 return 0;
141 }
142 /*- End of function --------------------------------------------------------*/
143
144 SPAN_DECLARE_NONSTD(int) tone_gen(tone_gen_state_t *s, int16_t amp[], int max_samples)
145 {
146 int samples;
147 int limit;
148 #if defined(SPANDSP_USE_FIXED_POINT)
149 int16_t xamp;
150 #else
151 float xamp;
152 #endif
153 int i;
154
155 if (s->current_section < 0)
156 return 0;
157
158 for (samples = 0; samples < max_samples; )
159 {
160 limit = samples + s->duration[s->current_section] - s->current_position;
161 if (limit > max_samples)
162 limit = max_samples;
163
164 s->current_position += (limit - samples);
165 if (s->current_section & 1)
166 {
167 /* A silent section */
168 for ( ; samples < limit; samples++)
169 amp[samples] = 0;
170 }
171 else
172 {
173 if (s->tone[0].phase_rate < 0)
174 {
175 /* Modulated tone */
176 for ( ; samples < limit; samples++)
177 {
178 /* There must be two, and only two, tones */
179 #if defined(SPANDSP_USE_FIXED_POINT)
180 xamp = ((int32_t) dds_mod(&s->phase[0], -s->tone[0].phase_rate, s->tone[0].gain, 0)
181 *(32767 + (int32_t) dds_mod(&s->phase[1], s->tone[1].phase_rate, s->tone[1].gain, 0))) >> 15;
182 amp[samples] = xamp;
183 #else
184 xamp = dds_modf(&s->phase[0], -s->tone[0].phase_rate, s->tone[0].gain, 0)
185 *(1.0f + dds_modf(&s->phase[1], s->tone[1].phase_rate, s->tone[1].gain, 0));
186 amp[samples] = (int16_t) lfastrintf(xamp);
187 #endif
188 }
189 }
190 else
191 {
192 for ( ; samples < limit; samples++)
193 {
194 #if defined(SPANDSP_USE_FIXED_POINT)
195 xamp = 0;
196 #else
197 xamp = 0.0f;
198 #endif
199 for (i = 0; i < 4; i++)
200 {
201 if (s->tone[i].phase_rate == 0)
202 break;
203 #if defined(SPANDSP_USE_FIXED_POINT)
204 xamp += dds_mod(&s->phase[i], s->tone[i].phase_rate, s->tone[i].gain, 0);
205 #else
206 xamp += dds_modf(&s->phase[i], s->tone[i].phase_rate, s->tone[i].gain, 0);
207 #endif
208 }
209 /* Saturation of the answer is the right thing at this point.
210 However, we are normally generating well controlled tones,
211 that cannot clip. So, the overhead of doing saturation is
212 a waste of valuable time. */
213 #if defined(SPANDSP_USE_FIXED_POINT)
214 amp[samples] = xamp;
215 #else
216 amp[samples] = (int16_t) lfastrintf(xamp);
217 #endif
218 }
219 }
220 }
221 if (s->current_position >= s->duration[s->current_section])
222 {
223 s->current_position = 0;
224 if (++s->current_section > 3 || s->duration[s->current_section] == 0)
225 {
226 if (!s->repeat)
227 {
228 /* Force a quick exit */
229 s->current_section = -1;
230 break;
231 }
232 s->current_section = 0;
233 }
234 }
235 }
236 return samples;
237 }
238 /*- End of function --------------------------------------------------------*/
239 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.