283 lines
8.9 KiB
C
283 lines
8.9 KiB
C
/*
|
|
* libteletone
|
|
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
|
|
*
|
|
* Version: MPL 1.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
|
|
*
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Stephen Underwood <steveu@coppice.org>
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* The the original interface designed by Steve Underwood was preserved to retain
|
|
*the optimizations when considering DTMF tones though the names were changed in the interest
|
|
* of namespace.
|
|
*
|
|
* Much less efficient expansion interface was added to allow for the detection of
|
|
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
|
|
* (controlled by compile time constant TELETONE_MAX_TONES)
|
|
*
|
|
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
|
|
*
|
|
*
|
|
* libteletone_detect.c Tone Detection Code
|
|
*
|
|
*
|
|
*********************************************************************************
|
|
*
|
|
* Derived from tone_detect.h - General telephony tone detection, and specific
|
|
* detection of DTMF.
|
|
*
|
|
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
|
|
*
|
|
* Despite my general liking of the GPL, I place this code in the
|
|
* public domain for the benefit of all mankind - even the slimy
|
|
* ones who might try to proprietize my work and use it to my
|
|
* detriment.
|
|
*
|
|
*
|
|
* Exception:
|
|
* The author hereby grants the use of this source code under the
|
|
* following license if and only if the source code is distributed
|
|
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
|
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
|
* following license and reinact the MPL 1.1 as stated above.
|
|
*
|
|
* Copyright (c) 2007, Anthony Minessale II
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of the original author; nor the names of any contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef LIBTELETONE_DETECT_H
|
|
#define LIBTELETONE_DETECT_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
#include <libteletone.h>
|
|
|
|
/*! \file libteletone_detect.h
|
|
\brief Tone Detection Routines
|
|
|
|
This module is responsible for tone detection specifics
|
|
*/
|
|
|
|
#ifndef FALSE
|
|
#define FALSE 0
|
|
#ifndef TRUE
|
|
#define TRUE (!FALSE)
|
|
#endif
|
|
#endif
|
|
|
|
/* Basic DTMF specs:
|
|
*
|
|
* Minimum tone on = 40ms
|
|
* Minimum tone off = 50ms
|
|
* Maximum digit rate = 10 per second
|
|
* Normal twist <= 8dB accepted
|
|
* Reverse twist <= 4dB accepted
|
|
* S/N >= 15dB will detect OK
|
|
* Attenuation <= 26dB will detect OK
|
|
* Frequency tolerance +- 1.5% will detect, +-3.5% will reject
|
|
*/
|
|
|
|
#define DTMF_THRESHOLD 8.0e7
|
|
#define DTMF_NORMAL_TWIST 6.3 /* 8dB */
|
|
#define DTMF_REVERSE_TWIST 2.5 /* 4dB */
|
|
#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
|
|
#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
|
|
#define DTMF_2ND_HARMONIC_ROW 2.5 /* 4dB */
|
|
#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */
|
|
#define GRID_FACTOR 4
|
|
#define BLOCK_LEN 102
|
|
#define M_TWO_PI 2.0*M_PI
|
|
|
|
typedef enum {
|
|
TT_HIT_NONE = 0,
|
|
TT_HIT_BEGIN = 1,
|
|
TT_HIT_MIDDLE = 2,
|
|
TT_HIT_END = 3
|
|
} teletone_hit_type_t;
|
|
|
|
|
|
/*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */
|
|
typedef struct {
|
|
float v2;
|
|
float v3;
|
|
double fac;
|
|
} teletone_goertzel_state_t;
|
|
|
|
/*! \brief A container for a DTMF detection state.*/
|
|
typedef struct {
|
|
int hit1;
|
|
int hit2;
|
|
int hit3;
|
|
int hit4;
|
|
int dur;
|
|
int zc;
|
|
|
|
|
|
teletone_goertzel_state_t row_out[GRID_FACTOR];
|
|
teletone_goertzel_state_t col_out[GRID_FACTOR];
|
|
teletone_goertzel_state_t row_out2nd[GRID_FACTOR];
|
|
teletone_goertzel_state_t col_out2nd[GRID_FACTOR];
|
|
float energy;
|
|
float lenergy;
|
|
|
|
int current_sample;
|
|
char digit;
|
|
int current_digits;
|
|
int detected_digits;
|
|
int lost_digits;
|
|
int digit_hits[16];
|
|
} teletone_dtmf_detect_state_t;
|
|
|
|
/*! \brief An abstraction to store the coefficient of a tone frequency */
|
|
typedef struct {
|
|
float fac;
|
|
} teletone_detection_descriptor_t;
|
|
|
|
/*! \brief A container for a single multi-tone detection
|
|
TELETONE_MAX_TONES dictates the maximum simultaneous tones that can be present
|
|
in a multi-tone representation.
|
|
*/
|
|
typedef struct {
|
|
int sample_rate;
|
|
|
|
teletone_detection_descriptor_t tdd[TELETONE_MAX_TONES];
|
|
teletone_goertzel_state_t gs[TELETONE_MAX_TONES];
|
|
teletone_goertzel_state_t gs2[TELETONE_MAX_TONES];
|
|
int tone_count;
|
|
|
|
float energy;
|
|
int current_sample;
|
|
|
|
int min_samples;
|
|
int total_samples;
|
|
|
|
int positives;
|
|
int negatives;
|
|
int hits;
|
|
|
|
int positive_factor;
|
|
int negative_factor;
|
|
int hit_factor;
|
|
|
|
} teletone_multi_tone_t;
|
|
|
|
|
|
/*!
|
|
\brief Initilize a multi-frequency tone detector
|
|
\param mt the multi-frequency tone descriptor
|
|
\param map a representation of the multi-frequency tone
|
|
*/
|
|
TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map);
|
|
|
|
/*!
|
|
\brief Check a sample buffer for the presence of the mulit-frequency tone described by mt
|
|
\param mt the multi-frequency tone descriptor
|
|
\param sample_buffer an array aof 16 bit signed linear samples
|
|
\param samples the number of samples present in sample_buffer
|
|
\return true when the tone was detected or false when it is not
|
|
*/
|
|
TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt,
|
|
int16_t sample_buffer[],
|
|
int samples);
|
|
|
|
/*!
|
|
\brief Initilize a DTMF detection state object
|
|
\param dtmf_detect_state the DTMF detection state to initilize
|
|
\param sample_rate the desired sample rate
|
|
*/
|
|
TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate);
|
|
|
|
/*!
|
|
\brief Check a sample buffer for the presence of DTMF digits
|
|
\param dtmf_detect_state the detection state object to check
|
|
\param sample_buffer an array aof 16 bit signed linear samples
|
|
\param samples the number of samples present in sample_buffer
|
|
\return true when DTMF was detected or false when it is not
|
|
*/
|
|
TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
|
int16_t sample_buffer[],
|
|
int samples);
|
|
/*!
|
|
\brief retrieve any collected digits into a string buffer
|
|
\param dtmf_detect_state the detection state object to check
|
|
\param buf the string buffer to write to
|
|
\param max the maximum length of buf
|
|
\return the number of characters written to buf
|
|
*/
|
|
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur);
|
|
|
|
/*!
|
|
\brief Step through the Goertzel Algorithm for each sample in a buffer
|
|
\param goertzel_state the goertzel state to step the samples through
|
|
\param sample_buffer an array aof 16 bit signed linear samples
|
|
\param samples the number of samples present in sample_buffer
|
|
*/
|
|
TELETONE_API(void) teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state,
|
|
int16_t sample_buffer[],
|
|
int samples);
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/* For Emacs:
|
|
* Local Variables:
|
|
* mode:c
|
|
* indent-tabs-mode:t
|
|
* tab-width:4
|
|
* c-basic-offset:4
|
|
* End:
|
|
* For VIM:
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
|
*/
|