Mercurial > hg > audiostuff
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 ------------------------------------------------------------*/ |