comparison spandsp-0.0.6pre17/src/spandsp/tone_detect.h @ 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_detect.h - General telephony tone detection.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2001, 2005 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_detect.h,v 1.45 2009/02/10 13:06:47 steveu Exp $
26 */
27
28 #if !defined(_SPANDSP_TONE_DETECT_H_)
29 #define _SPANDSP_TONE_DETECT_H_
30
31 /*!
32 Goertzel filter descriptor.
33 */
34 struct goertzel_descriptor_s
35 {
36 #if defined(SPANDSP_USE_FIXED_POINT)
37 int16_t fac;
38 #else
39 float fac;
40 #endif
41 int samples;
42 };
43
44 /*!
45 Goertzel filter state descriptor.
46 */
47 struct goertzel_state_s
48 {
49 #if defined(SPANDSP_USE_FIXED_POINT)
50 int16_t v2;
51 int16_t v3;
52 int16_t fac;
53 #else
54 float v2;
55 float v3;
56 float fac;
57 #endif
58 int samples;
59 int current_sample;
60 };
61
62 /*!
63 Goertzel filter descriptor.
64 */
65 typedef struct goertzel_descriptor_s goertzel_descriptor_t;
66
67 /*!
68 Goertzel filter state descriptor.
69 */
70 typedef struct goertzel_state_s goertzel_state_t;
71
72 #if defined(__cplusplus)
73 extern "C"
74 {
75 #endif
76
77 /*! \brief Create a descriptor for use with either a Goertzel transform */
78 SPAN_DECLARE(void) make_goertzel_descriptor(goertzel_descriptor_t *t,
79 float freq,
80 int samples);
81
82 /*! \brief Initialise the state of a Goertzel transform.
83 \param s The Goertzel context. If NULL, a context is allocated with malloc.
84 \param t The Goertzel descriptor.
85 \return A pointer to the Goertzel state. */
86 SPAN_DECLARE(goertzel_state_t *) goertzel_init(goertzel_state_t *s,
87 goertzel_descriptor_t *t);
88
89 SPAN_DECLARE(int) goertzel_release(goertzel_state_t *s);
90
91 SPAN_DECLARE(int) goertzel_free(goertzel_state_t *s);
92
93 /*! \brief Reset the state of a Goertzel transform.
94 \param s The Goertzel context. */
95 SPAN_DECLARE(void) goertzel_reset(goertzel_state_t *s);
96
97 /*! \brief Update the state of a Goertzel transform.
98 \param s The Goertzel context.
99 \param amp The samples to be transformed.
100 \param samples The number of samples.
101 \return The number of samples unprocessed */
102 SPAN_DECLARE(int) goertzel_update(goertzel_state_t *s,
103 const int16_t amp[],
104 int samples);
105
106 /*! \brief Evaluate the final result of a Goertzel transform.
107 \param s The Goertzel context.
108 \return The result of the transform. The expected result for a pure sine wave
109 signal of level x dBm0, at the very centre of the bin is:
110 [Floating point] ((samples_per_goertzel_block*32768.0/1.4142)*10^((x - DBM0_MAX_SINE_POWER)/20.0))^2
111 [Fixed point] ((samples_per_goertzel_block*256.0/1.4142)*10^((x - DBM0_MAX_SINE_POWER)/20.0))^2 */
112 #if defined(SPANDSP_USE_FIXED_POINT)
113 SPAN_DECLARE(int32_t) goertzel_result(goertzel_state_t *s);
114 #else
115 SPAN_DECLARE(float) goertzel_result(goertzel_state_t *s);
116 #endif
117
118 /*! \brief Update the state of a Goertzel transform.
119 \param s The Goertzel context.
120 \param amp The sample to be transformed. */
121 static __inline__ void goertzel_sample(goertzel_state_t *s, int16_t amp)
122 {
123 #if defined(SPANDSP_USE_FIXED_POINT)
124 int16_t x;
125 int16_t v1;
126 #else
127 float v1;
128 #endif
129
130 v1 = s->v2;
131 s->v2 = s->v3;
132 #if defined(SPANDSP_USE_FIXED_POINT)
133 x = (((int32_t) s->fac*s->v2) >> 14);
134 /* Scale down the input signal to avoid overflows. 9 bits is enough to
135 monitor the signals of interest with adequate dynamic range and
136 resolution. In telephony we generally only start with 13 or 14 bits,
137 anyway. */
138 s->v3 = x - v1 + (amp >> 7);
139 #else
140 s->v3 = s->fac*s->v2 - v1 + amp;
141 #endif
142 s->current_sample++;
143 }
144 /*- End of function --------------------------------------------------------*/
145
146 /* Scale down the input signal to avoid overflows. 9 bits is enough to
147 monitor the signals of interest with adequate dynamic range and
148 resolution. In telephony we generally only start with 13 or 14 bits,
149 anyway. This is sufficient for the longest Goertzel we currently use. */
150 #if defined(SPANDSP_USE_FIXED_POINT)
151 #define goertzel_preadjust_amp(amp) (((int16_t) amp) >> 7)
152 #else
153 #define goertzel_preadjust_amp(amp) ((float) amp)
154 #endif
155
156 /* Minimal update the state of a Goertzel transform. This is similar to
157 goertzel_sample, but more suited to blocks of Goertzels. It assumes
158 the amplitude is pre-shifted, and does not update the per-state sample
159 count.
160 \brief Update the state of a Goertzel transform.
161 \param s The Goertzel context.
162 \param amp The adjusted sample to be transformed. */
163 #if defined(SPANDSP_USE_FIXED_POINT)
164 static __inline__ void goertzel_samplex(goertzel_state_t *s, int16_t amp)
165 #else
166 static __inline__ void goertzel_samplex(goertzel_state_t *s, float amp)
167 #endif
168 {
169 #if defined(SPANDSP_USE_FIXED_POINT)
170 int16_t x;
171 int16_t v1;
172 #else
173 float v1;
174 #endif
175
176 v1 = s->v2;
177 s->v2 = s->v3;
178 #if defined(SPANDSP_USE_FIXED_POINT)
179 x = (((int32_t) s->fac*s->v2) >> 14);
180 s->v3 = x - v1 + amp;
181 #else
182 s->v3 = s->fac*s->v2 - v1 + amp;
183 #endif
184 }
185 /*- End of function --------------------------------------------------------*/
186
187 /*! Generate a Hamming weighted coefficient set, to be used for a periodogram analysis.
188 \param coeffs The generated coefficients.
189 \param freq The frequency to be matched by the periodogram, in Hz.
190 \param sample_rate The sample rate of the signal, in samples per second.
191 \param window_len The length of the periodogram window. This must be an even number.
192 \return The number of generated coefficients.
193 */
194 SPAN_DECLARE(int) periodogram_generate_coeffs(complexf_t coeffs[], float freq, int sample_rate, int window_len);
195
196 /*! Generate the phase offset to be expected between successive periodograms evaluated at the
197 specified interval.
198 \param offset A point to the generated phase offset.
199 \param freq The frequency being matched by the periodogram, in Hz.
200 \param sample_rate The sample rate of the signal, in samples per second.
201 \param interval The interval between periodograms, in samples.
202 \return The scaling factor.
203 */
204 SPAN_DECLARE(float) periodogram_generate_phase_offset(complexf_t *offset, float freq, int sample_rate, int interval);
205
206 /*! Evaluate a periodogram.
207 \param coeffs A set of coefficients generated by periodogram_generate_coeffs().
208 \param amp The complex amplitude of the signal.
209 \param len The length of the periodogram, in samples. This must be an even number.
210 \return The periodogram result.
211 */
212 SPAN_DECLARE(complexf_t) periodogram(const complexf_t coeffs[], const complexf_t amp[], int len);
213
214 /*! Prepare data for evaluating a set of periodograms.
215 \param sum A vector of sums of pairs of signal samples. This will be half the length of len.
216 \param diff A vector of differences between pairs of signal samples. This will be half the length of len.
217 \param amp The complex amplitude of the signal.
218 \param len The length of the periodogram, in samples. This must be an even number.
219 \return The length of the vectors sum and diff.
220 */
221 SPAN_DECLARE(int) periodogram_prepare(complexf_t sum[], complexf_t diff[], const complexf_t amp[], int len);
222
223 /*! Evaluate a periodogram, based on data prepared by periodogram_prepare(). This is more efficient
224 than using periodogram() when several periodograms are to be applied to the same signal.
225 \param coeffs A set of coefficients generated by periodogram_generate_coeffs().
226 \param sum A vector of sums produced by periodogram_prepare().
227 \param diff A vector of differences produced by periodogram_prepare().
228 \param len The length of the periodogram, in samples. This must be an even number.
229 \return The periodogram result.
230 */
231 SPAN_DECLARE(complexf_t) periodogram_apply(const complexf_t coeffs[], const complexf_t sum[], const complexf_t diff[], int len);
232
233 /*! Apply a phase offset, to find the frequency error between periodogram evaluations.
234 specified interval.
235 \param phase_offset A point to the expected phase offset.
236 \param scale The scaling factor to be used.
237 \param last_result A pointer to the previous periodogram result.
238 \param result A pointer to the current periodogram result.
239 \return The frequency error, in Hz.
240 */
241 SPAN_DECLARE(float) periodogram_freq_error(const complexf_t *phase_offset, float scale, const complexf_t *last_result, const complexf_t *result);
242
243 #if defined(__cplusplus)
244 }
245 #endif
246
247 #endif
248 /*- End of file ------------------------------------------------------------*/

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