tone_detect.h

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

Generated on Thu Oct 18 15:29:15 2012 for spandsp by  doxygen 1.4.7