00001 /* 00002 * SpanDSP - a series of DSP components for telephony 00003 * 00004 * tone_detect.h - General telephony tone detection. 00005 * 00006 * Written by Steve Underwood <steveu@coppice.org> 00007 * 00008 * Copyright (C) 2001, 2005 Steve Underwood 00009 * 00010 * All rights reserved. 00011 * 00012 * This program is free software; you can redistribute it and/or modify 00013 * it under the terms of the GNU Lesser General Public License version 2.1, 00014 * as published by the Free Software Foundation. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with this program; if not, write to the Free Software 00023 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00024 * 00025 * $Id: tone_detect.h,v 1.45 2009/02/10 13:06:47 steveu Exp $ 00026 */ 00027 00028 #if !defined(_SPANDSP_TONE_DETECT_H_) 00029 #define _SPANDSP_TONE_DETECT_H_ 00030 00031 /*! 00032 Goertzel filter descriptor. 00033 */ 00034 struct goertzel_descriptor_s 00035 { 00036 #if defined(SPANDSP_USE_FIXED_POINT) 00037 int16_t fac; 00038 #else 00039 float fac; 00040 #endif 00041 int samples; 00042 }; 00043 00044 /*! 00045 Goertzel filter state descriptor. 00046 */ 00047 struct goertzel_state_s 00048 { 00049 #if defined(SPANDSP_USE_FIXED_POINT) 00050 int16_t v2; 00051 int16_t v3; 00052 int16_t fac; 00053 #else 00054 float v2; 00055 float v3; 00056 float fac; 00057 #endif 00058 int samples; 00059 int current_sample; 00060 }; 00061 00062 /*! 00063 Goertzel filter descriptor. 00064 */ 00065 typedef struct goertzel_descriptor_s goertzel_descriptor_t; 00066 00067 /*! 00068 Goertzel filter state descriptor. 00069 */ 00070 typedef struct goertzel_state_s goertzel_state_t; 00071 00072 #if defined(__cplusplus) 00073 extern "C" 00074 { 00075 #endif 00076 00077 /*! \brief Create a descriptor for use with either a Goertzel transform */ 00078 SPAN_DECLARE(void) make_goertzel_descriptor(goertzel_descriptor_t *t, 00079 float freq, 00080 int samples); 00081 00082 /*! \brief Initialise the state of a Goertzel transform. 00083 \param s The Goertzel context. If NULL, a context is allocated with malloc. 00084 \param t The Goertzel descriptor. 00085 \return A pointer to the Goertzel state. */ 00086 SPAN_DECLARE(goertzel_state_t *) goertzel_init(goertzel_state_t *s, 00087 goertzel_descriptor_t *t); 00088 00089 SPAN_DECLARE(int) goertzel_release(goertzel_state_t *s); 00090 00091 SPAN_DECLARE(int) goertzel_free(goertzel_state_t *s); 00092 00093 /*! \brief Reset the state of a Goertzel transform. 00094 \param s The Goertzel context. */ 00095 SPAN_DECLARE(void) goertzel_reset(goertzel_state_t *s); 00096 00097 /*! \brief Update the state of a Goertzel transform. 00098 \param s The Goertzel context. 00099 \param amp The samples to be transformed. 00100 \param samples The number of samples. 00101 \return The number of samples unprocessed */ 00102 SPAN_DECLARE(int) goertzel_update(goertzel_state_t *s, 00103 const int16_t amp[], 00104 int samples); 00105 00106 /*! \brief Evaluate the final result of a Goertzel transform. 00107 \param s The Goertzel context. 00108 \return The result of the transform. The expected result for a pure sine wave 00109 signal of level x dBm0, at the very centre of the bin is: 00110 [Floating point] ((samples_per_goertzel_block*32768.0/1.4142)*10^((x - DBM0_MAX_SINE_POWER)/20.0))^2 00111 [Fixed point] ((samples_per_goertzel_block*256.0/1.4142)*10^((x - DBM0_MAX_SINE_POWER)/20.0))^2 */ 00112 #if defined(SPANDSP_USE_FIXED_POINT) 00113 SPAN_DECLARE(int32_t) goertzel_result(goertzel_state_t *s); 00114 #else 00115 SPAN_DECLARE(float) goertzel_result(goertzel_state_t *s); 00116 #endif 00117 00118 /*! \brief Update the state of a Goertzel transform. 00119 \param s The Goertzel context. 00120 \param amp The sample to be transformed. */ 00121 static __inline__ void goertzel_sample(goertzel_state_t *s, int16_t amp) 00122 { 00123 #if defined(SPANDSP_USE_FIXED_POINT) 00124 int16_t x; 00125 int16_t v1; 00126 #else 00127 float v1; 00128 #endif 00129 00130 v1 = s->v2; 00131 s->v2 = s->v3; 00132 #if defined(SPANDSP_USE_FIXED_POINT) 00133 x = (((int32_t) s->fac*s->v2) >> 14); 00134 /* Scale down the input signal to avoid overflows. 9 bits is enough to 00135 monitor the signals of interest with adequate dynamic range and 00136 resolution. In telephony we generally only start with 13 or 14 bits, 00137 anyway. */ 00138 s->v3 = x - v1 + (amp >> 7); 00139 #else 00140 s->v3 = s->fac*s->v2 - v1 + amp; 00141 #endif 00142 s->current_sample++; 00143 } 00144 /*- End of function --------------------------------------------------------*/ 00145 00146 /* Scale down the input signal to avoid overflows. 9 bits is enough to 00147 monitor the signals of interest with adequate dynamic range and 00148 resolution. In telephony we generally only start with 13 or 14 bits, 00149 anyway. This is sufficient for the longest Goertzel we currently use. */ 00150 #if defined(SPANDSP_USE_FIXED_POINT) 00151 #define goertzel_preadjust_amp(amp) (((int16_t) amp) >> 7) 00152 #else 00153 #define goertzel_preadjust_amp(amp) ((float) amp) 00154 #endif 00155 00156 /* Minimal update the state of a Goertzel transform. This is similar to 00157 goertzel_sample, but more suited to blocks of Goertzels. It assumes 00158 the amplitude is pre-shifted, and does not update the per-state sample 00159 count. 00160 \brief Update the state of a Goertzel transform. 00161 \param s The Goertzel context. 00162 \param amp The adjusted sample to be transformed. */ 00163 #if defined(SPANDSP_USE_FIXED_POINT) 00164 static __inline__ void goertzel_samplex(goertzel_state_t *s, int16_t amp) 00165 #else 00166 static __inline__ void goertzel_samplex(goertzel_state_t *s, float amp) 00167 #endif 00168 { 00169 #if defined(SPANDSP_USE_FIXED_POINT) 00170 int16_t x; 00171 int16_t v1; 00172 #else 00173 float v1; 00174 #endif 00175 00176 v1 = s->v2; 00177 s->v2 = s->v3; 00178 #if defined(SPANDSP_USE_FIXED_POINT) 00179 x = (((int32_t) s->fac*s->v2) >> 14); 00180 s->v3 = x - v1 + amp; 00181 #else 00182 s->v3 = s->fac*s->v2 - v1 + amp; 00183 #endif 00184 } 00185 /*- End of function --------------------------------------------------------*/ 00186 00187 /*! Generate a Hamming weighted coefficient set, to be used for a periodogram analysis. 00188 \param coeffs The generated coefficients. 00189 \param freq The frequency to be matched by the periodogram, in Hz. 00190 \param sample_rate The sample rate of the signal, in samples per second. 00191 \param window_len The length of the periodogram window. This must be an even number. 00192 \return The number of generated coefficients. 00193 */ 00194 SPAN_DECLARE(int) periodogram_generate_coeffs(complexf_t coeffs[], float freq, int sample_rate, int window_len); 00195 00196 /*! Generate the phase offset to be expected between successive periodograms evaluated at the 00197 specified interval. 00198 \param offset A point to the generated phase offset. 00199 \param freq The frequency being matched by the periodogram, in Hz. 00200 \param sample_rate The sample rate of the signal, in samples per second. 00201 \param interval The interval between periodograms, in samples. 00202 \return The scaling factor. 00203 */ 00204 SPAN_DECLARE(float) periodogram_generate_phase_offset(complexf_t *offset, float freq, int sample_rate, int interval); 00205 00206 /*! Evaluate a periodogram. 00207 \param coeffs A set of coefficients generated by periodogram_generate_coeffs(). 00208 \param amp The complex amplitude of the signal. 00209 \param len The length of the periodogram, in samples. This must be an even number. 00210 \return The periodogram result. 00211 */ 00212 SPAN_DECLARE(complexf_t) periodogram(const complexf_t coeffs[], const complexf_t amp[], int len); 00213 00214 /*! Prepare data for evaluating a set of periodograms. 00215 \param sum A vector of sums of pairs of signal samples. This will be half the length of len. 00216 \param diff A vector of differences between pairs of signal samples. This will be half the length of len. 00217 \param amp The complex amplitude of the signal. 00218 \param len The length of the periodogram, in samples. This must be an even number. 00219 \return The length of the vectors sum and diff. 00220 */ 00221 SPAN_DECLARE(int) periodogram_prepare(complexf_t sum[], complexf_t diff[], const complexf_t amp[], int len); 00222 00223 /*! Evaluate a periodogram, based on data prepared by periodogram_prepare(). This is more efficient 00224 than using periodogram() when several periodograms are to be applied to the same signal. 00225 \param coeffs A set of coefficients generated by periodogram_generate_coeffs(). 00226 \param sum A vector of sums produced by periodogram_prepare(). 00227 \param diff A vector of differences produced by periodogram_prepare(). 00228 \param len The length of the periodogram, in samples. This must be an even number. 00229 \return The periodogram result. 00230 */ 00231 SPAN_DECLARE(complexf_t) periodogram_apply(const complexf_t coeffs[], const complexf_t sum[], const complexf_t diff[], int len); 00232 00233 /*! Apply a phase offset, to find the frequency error between periodogram evaluations. 00234 specified interval. 00235 \param phase_offset A point to the expected phase offset. 00236 \param scale The scaling factor to be used. 00237 \param last_result A pointer to the previous periodogram result. 00238 \param result A pointer to the current periodogram result. 00239 \return The frequency error, in Hz. 00240 */ 00241 SPAN_DECLARE(float) periodogram_freq_error(const complexf_t *phase_offset, float scale, const complexf_t *last_result, const complexf_t *result); 00242 00243 #if defined(__cplusplus) 00244 } 00245 #endif 00246 00247 #endif 00248 /*- End of file ------------------------------------------------------------*/