format
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@267 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
parent
cae2014e76
commit
c80c4e3385
|
@ -54,7 +54,7 @@
|
||||||
* Exception:
|
* Exception:
|
||||||
* The author hereby grants the use of this source code under the
|
* The author hereby grants the use of this source code under the
|
||||||
* following license if and only if the source code is distributed
|
* following license if and only if the source code is distributed
|
||||||
* as part of the openzap library. Any use or distribution of this
|
* as part of the openzap library. Any use or distribution of this
|
||||||
* source code outside the scope of the openzap library will nullify the
|
* source code outside the scope of the openzap library will nullify the
|
||||||
* following license and reinact the MPL 1.1 as stated above.
|
* following license and reinact the MPL 1.1 as stated above.
|
||||||
*
|
*
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
@ -105,9 +105,9 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FALSE
|
#ifndef FALSE
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#ifndef TRUE
|
#ifndef TRUE
|
||||||
#define TRUE (!FALSE)
|
#define TRUE (!FALSE)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -123,13 +123,13 @@ extern "C" {
|
||||||
* Frequency tolerance +- 1.5% will detect, +-3.5% will reject
|
* Frequency tolerance +- 1.5% will detect, +-3.5% will reject
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DTMF_THRESHOLD 8.0e7
|
#define DTMF_THRESHOLD 8.0e7
|
||||||
#define DTMF_NORMAL_TWIST 6.3 /* 8dB */
|
#define DTMF_NORMAL_TWIST 6.3 /* 8dB */
|
||||||
#define DTMF_REVERSE_TWIST 2.5 /* 4dB */
|
#define DTMF_REVERSE_TWIST 2.5 /* 4dB */
|
||||||
#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
|
#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
|
||||||
#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
|
#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
|
||||||
#define DTMF_2ND_HARMONIC_ROW 2.5 /* 4dB */
|
#define DTMF_2ND_HARMONIC_ROW 2.5 /* 4dB */
|
||||||
#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */
|
#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */
|
||||||
#define GRID_FACTOR 4
|
#define GRID_FACTOR 4
|
||||||
#define BLOCK_LEN 102
|
#define BLOCK_LEN 102
|
||||||
#define M_TWO_PI 2.0*M_PI
|
#define M_TWO_PI 2.0*M_PI
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
* Exception:
|
* Exception:
|
||||||
* The author hereby grants the use of this source code under the
|
* The author hereby grants the use of this source code under the
|
||||||
* following license if and only if the source code is distributed
|
* following license if and only if the source code is distributed
|
||||||
* as part of the openzap library. Any use or distribution of this
|
* as part of the openzap library. Any use or distribution of this
|
||||||
* source code outside the scope of the openzap library will nullify the
|
* source code outside the scope of the openzap library will nullify the
|
||||||
* following license and reinact the MPL 1.1 as stated above.
|
* following license and reinact the MPL 1.1 as stated above.
|
||||||
*
|
*
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
@ -138,25 +138,25 @@ static __inline__ int32_t teletone_dds_phase_rate(teletone_process_t tone, uint3
|
||||||
|
|
||||||
static __inline__ int16_t teletone_dds_state_modulate_sample(teletone_dds_state_t *dds, uint32_t pindex)
|
static __inline__ int16_t teletone_dds_state_modulate_sample(teletone_dds_state_t *dds, uint32_t pindex)
|
||||||
{
|
{
|
||||||
int32_t bitmask = dds->phase_accumulator, sine_index = (bitmask >>= 23) & SINE_TABLE_LEN;
|
int32_t bitmask = dds->phase_accumulator, sine_index = (bitmask >>= 23) & SINE_TABLE_LEN;
|
||||||
int16_t sample;
|
int16_t sample;
|
||||||
|
|
||||||
if (pindex >= MAX_PHASE_TONES) {
|
if (pindex >= MAX_PHASE_TONES) {
|
||||||
pindex = 0;
|
pindex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bitmask & SINE_TABLE_MAX) {
|
if (bitmask & SINE_TABLE_MAX) {
|
||||||
sine_index = SINE_TABLE_LEN - sine_index;
|
sine_index = SINE_TABLE_LEN - sine_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
sample = TELETONE_SINES[sine_index];
|
sample = TELETONE_SINES[sine_index];
|
||||||
|
|
||||||
if (bitmask & (SINE_TABLE_MAX * 2)) {
|
if (bitmask & (SINE_TABLE_MAX * 2)) {
|
||||||
sample *= -1;
|
sample *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dds->phase_accumulator += dds->phase_rate[pindex];
|
dds->phase_accumulator += dds->phase_rate[pindex];
|
||||||
return (int16_t) (sample * dds->scale_factor >> 15);
|
return (int16_t) (sample * dds->scale_factor >> 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ void teletone_dds_state_set_tx_level(teletone_dds_state_t *dds, float tx_level)
|
static __inline__ void teletone_dds_state_set_tx_level(teletone_dds_state_t *dds, float tx_level)
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
* Exception:
|
* Exception:
|
||||||
* The author hereby grants the use of this source code under the
|
* The author hereby grants the use of this source code under the
|
||||||
* following license if and only if the source code is distributed
|
* following license if and only if the source code is distributed
|
||||||
* as part of the openzap library. Any use or distribution of this
|
* as part of the openzap library. Any use or distribution of this
|
||||||
* source code outside the scope of the openzap library will nullify the
|
* source code outside the scope of the openzap library will nullify the
|
||||||
* following license and reinact the MPL 1.1 as stated above.
|
* following license and reinact the MPL 1.1 as stated above.
|
||||||
*
|
*
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
@ -106,64 +106,64 @@ static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
|
||||||
static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
|
static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
|
||||||
static teletone_detection_descriptor_t dtmf_detect_col_2nd[GRID_FACTOR];
|
static teletone_detection_descriptor_t dtmf_detect_col_2nd[GRID_FACTOR];
|
||||||
|
|
||||||
static float dtmf_row[] = {697.0f, 770.0f, 852.0f, 941.0f};
|
static float dtmf_row[] = {697.0f, 770.0f, 852.0f, 941.0f};
|
||||||
static float dtmf_col[] = {1209.0f, 1336.0f, 1477.0f, 1633.0f};
|
static float dtmf_col[] = {1209.0f, 1336.0f, 1477.0f, 1633.0f};
|
||||||
|
|
||||||
static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
|
static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
|
||||||
|
|
||||||
static void goertzel_init(teletone_goertzel_state_t *goertzel_state, teletone_detection_descriptor_t *tdesc) {
|
static void goertzel_init(teletone_goertzel_state_t *goertzel_state, teletone_detection_descriptor_t *tdesc) {
|
||||||
goertzel_state->v2 = goertzel_state->v3 = 0.0;
|
goertzel_state->v2 = goertzel_state->v3 = 0.0;
|
||||||
goertzel_state->fac = tdesc->fac;
|
goertzel_state->fac = tdesc->fac;
|
||||||
}
|
}
|
||||||
|
|
||||||
void teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state,
|
void teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state,
|
||||||
int16_t sample_buffer[],
|
int16_t sample_buffer[],
|
||||||
int samples)
|
int samples)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
float v1;
|
float v1;
|
||||||
|
|
||||||
for (i = 0; i < samples; i++) {
|
for (i = 0; i < samples; i++) {
|
||||||
v1 = goertzel_state->v2;
|
v1 = goertzel_state->v2;
|
||||||
goertzel_state->v2 = goertzel_state->v3;
|
goertzel_state->v2 = goertzel_state->v3;
|
||||||
goertzel_state->v3 = goertzel_state->fac*goertzel_state->v2 - v1 + sample_buffer[i];
|
goertzel_state->v3 = goertzel_state->fac*goertzel_state->v2 - v1 + sample_buffer[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define teletone_goertzel_result(gs) ((gs)->v3 * (gs)->v3 + (gs)->v2 * (gs)->v2 - (gs)->v2 * (gs)->v3 * (gs)->fac)
|
#define teletone_goertzel_result(gs) ((gs)->v3 * (gs)->v3 + (gs)->v2 * (gs)->v2 - (gs)->v2 * (gs)->v3 * (gs)->fac)
|
||||||
|
|
||||||
void teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate)
|
void teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
float theta;
|
float theta;
|
||||||
|
|
||||||
dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
|
dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
|
||||||
|
|
||||||
for (i = 0; i < GRID_FACTOR; i++) {
|
for (i = 0; i < GRID_FACTOR; i++) {
|
||||||
theta = M_TWO_PI*(dtmf_row[i]/(float)sample_rate);
|
theta = M_TWO_PI*(dtmf_row[i]/(float)sample_rate);
|
||||||
dtmf_detect_row[i].fac = 2.0*cos(theta);
|
dtmf_detect_row[i].fac = 2.0*cos(theta);
|
||||||
|
|
||||||
theta = M_TWO_PI*(dtmf_col[i]/(float)sample_rate);
|
theta = M_TWO_PI*(dtmf_col[i]/(float)sample_rate);
|
||||||
dtmf_detect_col[i].fac = 2.0*cos(theta);
|
dtmf_detect_col[i].fac = 2.0*cos(theta);
|
||||||
|
|
||||||
theta = M_TWO_PI*(dtmf_row[i]*2.0/(float)sample_rate);
|
theta = M_TWO_PI*(dtmf_row[i]*2.0/(float)sample_rate);
|
||||||
dtmf_detect_row_2nd[i].fac = 2.0*cos(theta);
|
dtmf_detect_row_2nd[i].fac = 2.0*cos(theta);
|
||||||
|
|
||||||
theta = M_TWO_PI*(dtmf_col[i]*2.0/(float)sample_rate);
|
theta = M_TWO_PI*(dtmf_col[i]*2.0/(float)sample_rate);
|
||||||
dtmf_detect_col_2nd[i].fac = 2.0*cos(theta);
|
dtmf_detect_col_2nd[i].fac = 2.0*cos(theta);
|
||||||
|
|
||||||
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
|
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
|
||||||
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
|
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
|
||||||
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
|
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
|
||||||
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
|
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
|
||||||
|
|
||||||
dtmf_detect_state->energy = 0.0;
|
dtmf_detect_state->energy = 0.0;
|
||||||
}
|
}
|
||||||
dtmf_detect_state->current_sample = 0;
|
dtmf_detect_state->current_sample = 0;
|
||||||
dtmf_detect_state->detected_digits = 0;
|
dtmf_detect_state->detected_digits = 0;
|
||||||
dtmf_detect_state->lost_digits = 0;
|
dtmf_detect_state->lost_digits = 0;
|
||||||
dtmf_detect_state->digits[0] = '\0';
|
dtmf_detect_state->digits[0] = '\0';
|
||||||
dtmf_detect_state->mhit = 0;
|
dtmf_detect_state->mhit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
|
void teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
|
||||||
|
@ -213,17 +213,17 @@ int teletone_multi_tone_detect (teletone_multi_tone_t *mt,
|
||||||
float eng_sum = 0, eng_all[TELETONE_MAX_TONES];
|
float eng_sum = 0, eng_all[TELETONE_MAX_TONES];
|
||||||
int gtest = 0, see_hit = 0;
|
int gtest = 0, see_hit = 0;
|
||||||
|
|
||||||
for (sample = 0; sample < samples; sample = limit) {
|
for (sample = 0; sample < samples; sample = limit) {
|
||||||
mt->total_samples++;
|
mt->total_samples++;
|
||||||
|
|
||||||
if ((samples - sample) >= (mt->min_samples - mt->current_sample)) {
|
if ((samples - sample) >= (mt->min_samples - mt->current_sample)) {
|
||||||
limit = sample + (mt->min_samples - mt->current_sample);
|
limit = sample + (mt->min_samples - mt->current_sample);
|
||||||
} else {
|
} else {
|
||||||
limit = samples;
|
limit = samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = sample; j < limit; j++) {
|
for (j = sample; j < limit; j++) {
|
||||||
famp = sample_buffer[j];
|
famp = sample_buffer[j];
|
||||||
|
|
||||||
mt->energy += famp*famp;
|
mt->energy += famp*famp;
|
||||||
|
|
||||||
|
@ -238,9 +238,9 @@ int teletone_multi_tone_detect (teletone_multi_tone_t *mt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mt->current_sample += (limit - sample);
|
mt->current_sample += (limit - sample);
|
||||||
if (mt->current_sample < mt->min_samples) {
|
if (mt->current_sample < mt->min_samples) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
eng_sum = 0;
|
eng_sum = 0;
|
||||||
|
@ -277,15 +277,15 @@ int teletone_multi_tone_detect (teletone_multi_tone_t *mt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reinitialise the detector for the next block */
|
/* Reinitialise the detector for the next block */
|
||||||
for(x = 0; x < mt->tone_count; x++) {
|
for(x = 0; x < mt->tone_count; x++) {
|
||||||
goertzel_init (&mt->gs[x], &mt->tdd[x]);
|
goertzel_init (&mt->gs[x], &mt->tdd[x]);
|
||||||
goertzel_init (&mt->gs2[x], &mt->tdd[x]);
|
goertzel_init (&mt->gs2[x], &mt->tdd[x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
mt->energy = 0.0;
|
mt->energy = 0.0;
|
||||||
mt->current_sample = 0;
|
mt->current_sample = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return see_hit;
|
return see_hit;
|
||||||
}
|
}
|
||||||
|
@ -295,30 +295,30 @@ int teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||||
int16_t sample_buffer[],
|
int16_t sample_buffer[],
|
||||||
int samples)
|
int samples)
|
||||||
{
|
{
|
||||||
float row_energy[GRID_FACTOR];
|
float row_energy[GRID_FACTOR];
|
||||||
float col_energy[GRID_FACTOR];
|
float col_energy[GRID_FACTOR];
|
||||||
float famp;
|
float famp;
|
||||||
float v1;
|
float v1;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
int sample;
|
int sample;
|
||||||
int best_row;
|
int best_row;
|
||||||
int best_col;
|
int best_col;
|
||||||
char hit;
|
char hit;
|
||||||
int limit;
|
int limit;
|
||||||
|
|
||||||
hit = 0;
|
hit = 0;
|
||||||
for (sample = 0; sample < samples; sample = limit) {
|
for (sample = 0; sample < samples; sample = limit) {
|
||||||
/* BLOCK_LEN is optimised to meet the DTMF specs. */
|
/* BLOCK_LEN is optimised to meet the DTMF specs. */
|
||||||
if ((samples - sample) >= (BLOCK_LEN - dtmf_detect_state->current_sample)) {
|
if ((samples - sample) >= (BLOCK_LEN - dtmf_detect_state->current_sample)) {
|
||||||
limit = sample + (BLOCK_LEN - dtmf_detect_state->current_sample);
|
limit = sample + (BLOCK_LEN - dtmf_detect_state->current_sample);
|
||||||
} else {
|
} else {
|
||||||
limit = samples;
|
limit = samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = sample; j < limit; j++) {
|
for (j = sample; j < limit; j++) {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
famp = sample_buffer[j];
|
famp = sample_buffer[j];
|
||||||
|
|
||||||
dtmf_detect_state->energy += famp*famp;
|
dtmf_detect_state->energy += famp*famp;
|
||||||
|
|
||||||
|
@ -340,53 +340,53 @@ int teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||||
dtmf_detect_state->row_out2nd[x].v3 = dtmf_detect_state->row_out2nd[x].fac*dtmf_detect_state->row_out2nd[x].v2 - v1 + famp;
|
dtmf_detect_state->row_out2nd[x].v3 = dtmf_detect_state->row_out2nd[x].fac*dtmf_detect_state->row_out2nd[x].v2 - v1 + famp;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
dtmf_detect_state->current_sample += (limit - sample);
|
|
||||||
if (dtmf_detect_state->current_sample < BLOCK_LEN) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
/* We are at the end of a DTMF detection block */
|
|
||||||
/* Find the peak row and the peak column */
|
|
||||||
row_energy[0] = teletone_goertzel_result (&dtmf_detect_state->row_out[0]);
|
|
||||||
col_energy[0] = teletone_goertzel_result (&dtmf_detect_state->col_out[0]);
|
|
||||||
|
|
||||||
for (best_row = best_col = 0, i = 1; i < GRID_FACTOR; i++) {
|
dtmf_detect_state->current_sample += (limit - sample);
|
||||||
row_energy[i] = teletone_goertzel_result (&dtmf_detect_state->row_out[i]);
|
if (dtmf_detect_state->current_sample < BLOCK_LEN) {
|
||||||
if (row_energy[i] > row_energy[best_row]) {
|
continue;
|
||||||
best_row = i;
|
}
|
||||||
|
/* We are at the end of a DTMF detection block */
|
||||||
|
/* Find the peak row and the peak column */
|
||||||
|
row_energy[0] = teletone_goertzel_result (&dtmf_detect_state->row_out[0]);
|
||||||
|
col_energy[0] = teletone_goertzel_result (&dtmf_detect_state->col_out[0]);
|
||||||
|
|
||||||
|
for (best_row = best_col = 0, i = 1; i < GRID_FACTOR; i++) {
|
||||||
|
row_energy[i] = teletone_goertzel_result (&dtmf_detect_state->row_out[i]);
|
||||||
|
if (row_energy[i] > row_energy[best_row]) {
|
||||||
|
best_row = i;
|
||||||
}
|
}
|
||||||
col_energy[i] = teletone_goertzel_result (&dtmf_detect_state->col_out[i]);
|
col_energy[i] = teletone_goertzel_result (&dtmf_detect_state->col_out[i]);
|
||||||
if (col_energy[i] > col_energy[best_col]) {
|
if (col_energy[i] > col_energy[best_col]) {
|
||||||
best_col = i;
|
best_col = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hit = 0;
|
hit = 0;
|
||||||
/* Basic signal level test and the twist test */
|
/* Basic signal level test and the twist test */
|
||||||
if (row_energy[best_row] >= DTMF_THRESHOLD &&
|
if (row_energy[best_row] >= DTMF_THRESHOLD &&
|
||||||
col_energy[best_col] >= DTMF_THRESHOLD &&
|
col_energy[best_col] >= DTMF_THRESHOLD &&
|
||||||
col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
|
col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
|
||||||
col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
|
col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
|
||||||
/* Relative peak test */
|
/* Relative peak test */
|
||||||
for (i = 0; i < GRID_FACTOR; i++) {
|
for (i = 0; i < GRID_FACTOR; i++) {
|
||||||
if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
|
if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
|
||||||
(i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
|
(i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* ... and second harmonic test */
|
/* ... and second harmonic test */
|
||||||
if (i >= GRID_FACTOR && (row_energy[best_row] + col_energy[best_col]) > 42.0*dtmf_detect_state->energy &&
|
if (i >= GRID_FACTOR && (row_energy[best_row] + col_energy[best_col]) > 42.0*dtmf_detect_state->energy &&
|
||||||
teletone_goertzel_result (&dtmf_detect_state->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] &&
|
teletone_goertzel_result (&dtmf_detect_state->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] &&
|
||||||
teletone_goertzel_result (&dtmf_detect_state->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
|
teletone_goertzel_result (&dtmf_detect_state->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
|
||||||
hit = dtmf_positions[(best_row << 2) + best_col];
|
hit = dtmf_positions[(best_row << 2) + best_col];
|
||||||
/* Look for two successive similar results */
|
/* Look for two successive similar results */
|
||||||
/* The logic in the next test is:
|
/* The logic in the next test is:
|
||||||
We need two successive identical clean detects, with
|
We need two successive identical clean detects, with
|
||||||
something different preceeding it. This can work with
|
something different preceeding it. This can work with
|
||||||
back to back differing digits. More importantly, it
|
back to back differing digits. More importantly, it
|
||||||
can work with nasty phones that give a very wobbly start
|
can work with nasty phones that give a very wobbly start
|
||||||
to a digit. */
|
to a digit. */
|
||||||
if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
|
if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
|
||||||
dtmf_detect_state->mhit = hit;
|
dtmf_detect_state->mhit = hit;
|
||||||
dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
|
dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
|
||||||
dtmf_detect_state->detected_digits++;
|
dtmf_detect_state->detected_digits++;
|
||||||
|
@ -399,26 +399,26 @@ int teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||||
dtmf_detect_state->lost_digits++;
|
dtmf_detect_state->lost_digits++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
|
dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
|
||||||
dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
|
dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
|
||||||
dtmf_detect_state->hit3 = hit;
|
dtmf_detect_state->hit3 = hit;
|
||||||
/* Reinitialise the detector for the next block */
|
/* Reinitialise the detector for the next block */
|
||||||
for (i = 0; i < GRID_FACTOR; i++) {
|
for (i = 0; i < GRID_FACTOR; i++) {
|
||||||
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
|
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
|
||||||
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
|
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
|
||||||
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
|
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
|
||||||
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
|
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
|
||||||
}
|
}
|
||||||
dtmf_detect_state->energy = 0.0;
|
dtmf_detect_state->energy = 0.0;
|
||||||
dtmf_detect_state->current_sample = 0;
|
dtmf_detect_state->current_sample = 0;
|
||||||
}
|
}
|
||||||
if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
|
if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
|
||||||
dtmf_detect_state->mhit = 0;
|
dtmf_detect_state->mhit = 0;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
return (hit);
|
return (hit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -426,16 +426,16 @@ int teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||||
char *buf,
|
char *buf,
|
||||||
int max)
|
int max)
|
||||||
{
|
{
|
||||||
if (max > dtmf_detect_state->current_digits) {
|
if (max > dtmf_detect_state->current_digits) {
|
||||||
max = dtmf_detect_state->current_digits;
|
max = dtmf_detect_state->current_digits;
|
||||||
}
|
}
|
||||||
if (max > 0) {
|
if (max > 0) {
|
||||||
memcpy (buf, dtmf_detect_state->digits, max);
|
memcpy (buf, dtmf_detect_state->digits, max);
|
||||||
memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
|
memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
|
||||||
dtmf_detect_state->current_digits -= max;
|
dtmf_detect_state->current_digits -= max;
|
||||||
}
|
}
|
||||||
buf[max] = '\0';
|
buf[max] = '\0';
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For Emacs:
|
/* For Emacs:
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
* Exception:
|
* Exception:
|
||||||
* The author hereby grants the use of this source code under the
|
* The author hereby grants the use of this source code under the
|
||||||
* following license if and only if the source code is distributed
|
* following license if and only if the source code is distributed
|
||||||
* as part of the openzap library. Any use or distribution of this
|
* as part of the openzap library. Any use or distribution of this
|
||||||
* source code outside the scope of the openzap library will nullify the
|
* source code outside the scope of the openzap library will nullify the
|
||||||
* following license and reinact the MPL 1.1 as stated above.
|
* following license and reinact the MPL 1.1 as stated above.
|
||||||
*
|
*
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
|
Loading…
Reference in New Issue