2006-02-19 20:28:24 +00:00
|
|
|
/*
|
|
|
|
* libteletone
|
|
|
|
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
* 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 <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
#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
|
|
|
|
*/
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
#ifndef FALSE
|
2006-02-19 20:28:24 +00:00
|
|
|
#define FALSE 0
|
2006-03-01 06:25:56 +00:00
|
|
|
#ifndef TRUE
|
2006-02-19 20:28:24 +00:00
|
|
|
#define TRUE (!FALSE)
|
2006-03-01 06:25:56 +00:00
|
|
|
#endif
|
2007-03-29 22:31:56 +00:00
|
|
|
#endif
|
2006-02-19 20:28:24 +00:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
|
|
|
/*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */
|
|
|
|
typedef struct {
|
2006-02-19 21:01:55 +00:00
|
|
|
teletone_process_t v2;
|
|
|
|
teletone_process_t v3;
|
|
|
|
teletone_process_t fac;
|
2006-02-19 20:28:24 +00:00
|
|
|
} teletone_goertzel_state_t;
|
|
|
|
|
|
|
|
/*! \brief A container for a DTMF detection state.*/
|
|
|
|
typedef struct {
|
|
|
|
int hit1;
|
|
|
|
int hit2;
|
|
|
|
int hit3;
|
|
|
|
int hit4;
|
|
|
|
int mhit;
|
|
|
|
|
|
|
|
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];
|
2006-02-19 21:01:55 +00:00
|
|
|
teletone_process_t energy;
|
2006-02-19 20:28:24 +00:00
|
|
|
|
|
|
|
int current_sample;
|
|
|
|
char digits[TELETONE_MAX_DTMF_DIGITS + 1];
|
|
|
|
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 {
|
2006-02-19 21:01:55 +00:00
|
|
|
teletone_process_t fac;
|
2006-02-19 20:28:24 +00:00
|
|
|
} 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;
|
|
|
|
|
2006-02-19 21:01:55 +00:00
|
|
|
teletone_process_t energy;
|
2006-02-19 20:28:24 +00:00
|
|
|
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
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
int teletone_multi_tone_detect (teletone_multi_tone_t *mt,
|
|
|
|
int16_t sample_buffer[],
|
|
|
|
int samples);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Initilize a DTMF detection state object
|
2006-02-19 21:01:55 +00:00
|
|
|
\param dtmf_detect_state the DTMF detection state to initilize
|
2006-02-19 20:28:24 +00:00
|
|
|
\param sample_rate the desired sample rate
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
int 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
|
|
|
|
*/
|
|
|
|
int teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
|
|
|
char *buf,
|
|
|
|
int max);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\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
|
|
|
|
*/
|
|
|
|
void teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state,
|
|
|
|
int16_t sample_buffer[],
|
|
|
|
int samples);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Compute the result of the last applied step of the Goertzel Algorithm
|
|
|
|
\param goertzel_state the goertzel state to retrieve from
|
|
|
|
\return the computed value for consideration in furthur audio tests
|
|
|
|
*/
|
2006-02-19 21:01:55 +00:00
|
|
|
teletone_process_t teletone_goertzel_result (teletone_goertzel_state_t *goertzel_state);
|
2006-02-19 20:28:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
2006-11-27 22:30:48 +00:00
|
|
|
|
|
|
|
/* For Emacs:
|
|
|
|
* Local Variables:
|
|
|
|
* mode:c
|
2007-02-09 02:36:03 +00:00
|
|
|
* indent-tabs-mode:t
|
2006-11-27 22:30:48 +00:00
|
|
|
* tab-width:4
|
|
|
|
* c-basic-offset:4
|
|
|
|
* End:
|
|
|
|
* For VIM:
|
|
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
|
|
*/
|