1 /*
2 * libteletone
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is libteletone
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 *
28 *
29 * libteletone.h -- Tone Generator
30 *
31 *
32 *
33 * Exception:
34 * The author hereby grants the use of this source code under the
35 * following license if and only if the source code is distributed
36 * as part of the OpenZAP or FreeTDM library. Any use or distribution of this
37 * source code outside the scope of the OpenZAP or FreeTDM library will nullify the
38 * following license and reinact the MPL 1.1 as stated above.
39 *
40 * Copyright (c) 2007, Anthony Minessale II
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 *
47 * * Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 *
50 * * Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 *
54 * * Neither the name of the original author; nor the names of any contributors
55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission.
57 *
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
60 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
61 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
62 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
63 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
64 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
65 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
66 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
67 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
68 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
69 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70 */
71 #ifndef LIBTELETONE_GENERATE_H
72 #define LIBTELETONE_GENERATE_H
73 #ifdef __cplusplus
74 extern "C" {
75 #ifdef _doh
76 }
77 #endif
78 #endif
79
80 #include <stdio.h>
81 #include <stdlib.h>
82
83 #if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
84 #ifndef __inline__
85 #define __inline__ inline
86 #endif
87 #endif
88
89 #ifdef _MSC_VER
90 #ifndef __inline__
91 #define __inline__ __inline
92 #endif
93
94 #if !defined(_STDINT) && !defined(uint32_t)
95 typedef unsigned __int64 uint64_t;
96 typedef unsigned __int32 uint32_t;
97 typedef unsigned __int16 uint16_t;
98 typedef unsigned __int8 uint8_t;
99 typedef __int64 int64_t;
100 typedef __int32 int32_t;
101 typedef __int16 int16_t;
102 typedef __int8 int8_t;
103 #endif
104 #else
105 #include <stdint.h>
106 #endif
107 #include <sys/types.h>
108 #include <sys/stat.h>
109 #include <fcntl.h>
110 #include <math.h>
111 #if !defined(powf) && !defined(_WIN64)
112 #ifdef _MSC_VER
113 #pragma warning(push)
114 #pragma warning(disable: 28251)
115 #endif
116 extern float powf (float, float);
117 #ifdef _MSC_VER
118 #pragma warning(pop)
119 #endif
120 #endif
121 #include <string.h>
122 #include <errno.h>
123 #ifndef _MSC_VER
124 #include <unistd.h>
125 #endif
126 #include <assert.h>
127 #include <stdarg.h>
128 #include <libteletone.h>
129
130 #define TELETONE_VOL_DB_MAX 0
131 #define TELETONE_VOL_DB_MIN -63
132 #define MAX_PHASE_TONES 4
133
134 struct teletone_dds_state {
135 uint32_t phase_rate[MAX_PHASE_TONES];
136 uint32_t scale_factor;
137 uint32_t phase_accumulator;
138 teletone_process_t tx_level;
139 };
140 typedef struct teletone_dds_state teletone_dds_state_t;
141
142 #define SINE_TABLE_MAX 128
143 #define SINE_TABLE_LEN (SINE_TABLE_MAX - 1)
144 #define MAX_PHASE_ACCUMULATOR 0x10000 * 0x10000
145 /* 3.14 == the max power on ulaw (alaw is 3.17) */
146 /* 3.02 represents twice the power */
147 #define DBM0_MAX_POWER (3.14f + 3.02f)
148
149 TELETONE_API_DATA extern int16_t TELETONE_SINES[SINE_TABLE_MAX];
150
teletone_dds_phase_rate(teletone_process_t tone,uint32_t rate)151 static __inline__ int32_t teletone_dds_phase_rate(teletone_process_t tone, uint32_t rate)
152 {
153 return (int32_t) ((tone * MAX_PHASE_ACCUMULATOR) / rate);
154 }
155
teletone_dds_state_modulate_sample(teletone_dds_state_t * dds,uint32_t pindex)156 static __inline__ int16_t teletone_dds_state_modulate_sample(teletone_dds_state_t *dds, uint32_t pindex)
157 {
158 int32_t bitmask = dds->phase_accumulator, sine_index = (bitmask >>= 23) & SINE_TABLE_LEN;
159 int16_t sample;
160
161 if (pindex >= MAX_PHASE_TONES) {
162 pindex = 0;
163 }
164
165 if (bitmask & SINE_TABLE_MAX) {
166 sine_index = SINE_TABLE_LEN - sine_index;
167 }
168
169 sample = TELETONE_SINES[sine_index];
170
171 if (bitmask & (SINE_TABLE_MAX * 2)) {
172 sample *= -1;
173 }
174
175 dds->phase_accumulator += dds->phase_rate[pindex];
176 return (int16_t) (sample * dds->scale_factor >> 15);
177 }
178
teletone_dds_state_set_tx_level(teletone_dds_state_t * dds,float tx_level)179 static __inline__ void teletone_dds_state_set_tx_level(teletone_dds_state_t *dds, float tx_level)
180 {
181 dds->scale_factor = (int) (powf(10.0f, (tx_level - DBM0_MAX_POWER) / 20.0f) * (32767.0f * 1.414214f));
182 dds->tx_level = tx_level;
183 }
184
teletone_dds_state_reset_accum(teletone_dds_state_t * dds)185 static __inline__ void teletone_dds_state_reset_accum(teletone_dds_state_t *dds)
186 {
187 dds->phase_accumulator = 0;
188 }
189
teletone_dds_state_set_tone(teletone_dds_state_t * dds,teletone_process_t tone,uint32_t rate,uint32_t pindex)190 static __inline__ int teletone_dds_state_set_tone(teletone_dds_state_t *dds, teletone_process_t tone, uint32_t rate, uint32_t pindex)
191 {
192 if (pindex < MAX_PHASE_TONES) {
193 dds->phase_rate[pindex] = teletone_dds_phase_rate(tone, rate);
194 return 0;
195 }
196
197 return -1;
198 }
199
200
201
202 /*! \file libteletone_generate.h
203 \brief Tone Generation Routines
204
205 This module is responsible for tone generation specifics
206 */
207
208 typedef int16_t teletone_audio_t;
209 struct teletone_generation_session;
210 typedef int (*tone_handler)(struct teletone_generation_session *ts, teletone_tone_map_t *map);
211
212 /*! \brief An abstraction to store a tone generation session */
213 struct teletone_generation_session {
214 /*! An array of tone mappings to character mappings */
215 teletone_tone_map_t TONES[TELETONE_TONE_RANGE];
216 /*! The number of channels the output audio should be in */
217 int channels;
218 /*! The Rate in hz of the output audio */
219 int rate;
220 /*! The duration (in samples) of the output audio */
221 int duration;
222 /*! The duration of silence to append after the initial audio is generated */
223 int wait;
224 /*! The duration (in samples) of the output audio (takes prescedence over actual duration value) */
225 int tmp_duration;
226 /*! The duration of silence to append after the initial audio is generated (takes prescedence over actual wait value)*/
227 int tmp_wait;
228 /*! Number of loops to repeat a single instruction*/
229 int loops;
230 /*! Number of loops to repeat the entire set of instructions*/
231 int LOOPS;
232 /*! Number to mutiply total samples by to determine when to begin ascent or decent e.g. 0=beginning 4=(last 25%) */
233 float decay_factor;
234 /*! Direction to perform volume increase/decrease 1/-1*/
235 int decay_direction;
236 /*! Number of samples between increase/decrease of volume */
237 int decay_step;
238 /*! Volume factor of the tone */
239 float volume;
240 /*! Debug on/off */
241 int debug;
242 /*! FILE stream to write debug data to */
243 FILE *debug_stream;
244 /*! Extra user data to attach to the session*/
245 void *user_data;
246 /*! Buffer for storing sample data (dynamic) */
247 teletone_audio_t *buffer;
248 /*! Size of the buffer */
249 int datalen;
250 /*! In-Use size of the buffer */
251 int samples;
252 /*! Callback function called during generation */
253 int dynamic;
254 tone_handler handler;
255 };
256
257 typedef struct teletone_generation_session teletone_generation_session_t;
258
259
260 /*!
261 \brief Assign a set of tones to a tone_session indexed by a paticular index/character
262 \param ts the tone generation session
263 \param index the index to map the tone to
264 \param ... up to TELETONE_MAX_TONES frequencies terminated by 0.0
265 \return 0
266 */
267 TELETONE_API(int) teletone_set_tone(teletone_generation_session_t *ts, int index, ...);
268
269 /*!
270 \brief Assign a set of tones to a single tone map
271 \param map the map to assign the tones to
272 \param ... up to TELETONE_MAX_TONES frequencies terminated by 0.0
273 \return 0
274 */
275 TELETONE_API(int) teletone_set_map(teletone_tone_map_t *map, ...);
276
277 /*!
278 \brief Initilize a tone generation session
279 \param ts the tone generation session to initilize
280 \param buflen the size of the buffer(in samples) to dynamically allocate
281 \param handler a callback function to execute when a tone generation instruction is complete
282 \param user_data optional user data to send
283 \return 0
284 */
285 TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int buflen, tone_handler handler, void *user_data);
286
287 /*!
288 \brief Free the buffer allocated by a tone generation session
289 \param ts the tone generation session to destroy
290 \return 0
291 */
292 TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts);
293
294 /*!
295 \brief Execute a single tone generation instruction
296 \param ts the tone generation session to consult for parameters
297 \param map the tone mapping to use for the frequencies
298 \return 0
299 */
300 TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone_tone_map_t *map);
301
302 /*!
303 \brief Execute a tone generation script and call callbacks after each instruction
304 \param ts the tone generation session to execute on
305 \param cmd the script to execute
306 \return 0
307 */
308 TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd);
309
310 #ifdef __cplusplus
311 }
312 #endif
313
314 #endif
315
316 /* For Emacs:
317 * Local Variables:
318 * mode:c
319 * indent-tabs-mode:t
320 * tab-width:4
321 * c-basic-offset:4
322 * End:
323 * For VIM:
324 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
325 */
326