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 ------------------------------------------------------------*/ |
