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