Index: src/libteletone_detect.c =================================================================== --- src/libteletone_detect.c (revision 321) +++ src/libteletone_detect.c (working copy) @@ -54,7 +54,7 @@ * 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 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 * 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 * "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 + * 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 @@ -106,64 +106,64 @@ static teletone_detection_descriptor_t dtmf_detect_row_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 char dtmf_positions[] = "123A" "456B" "789C" "*0#D"; 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->fac = tdesc->fac; + goertzel_state->v2 = goertzel_state->v3 = 0.0; + goertzel_state->fac = tdesc->fac; } void teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state, int16_t sample_buffer[], int samples) { - int i; - float v1; - - for (i = 0; i < samples; i++) { - v1 = goertzel_state->v2; - goertzel_state->v2 = goertzel_state->v3; - goertzel_state->v3 = (float)(goertzel_state->fac*goertzel_state->v2 - v1 + sample_buffer[i]); - } + int i; + float v1; + + for (i = 0; i < samples; i++) { + v1 = goertzel_state->v2; + goertzel_state->v2 = goertzel_state->v3; + goertzel_state->v3 = (float)(goertzel_state->fac*goertzel_state->v2 - v1 + sample_buffer[i]); + } } -#define teletone_goertzel_result(gs) (float)(((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) { - int i; - float theta; + int i; + 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++) { - theta = (float)(M_TWO_PI*(dtmf_row[i]/(float)sample_rate)); - dtmf_detect_row[i].fac = (float)(2.0*cos(theta)); + for (i = 0; i < GRID_FACTOR; i++) { + theta = (float)(M_TWO_PI*(dtmf_row[i]/(float)sample_rate)); + dtmf_detect_row[i].fac = (float)(2.0f*cos(theta)); - theta = (float)(M_TWO_PI*(dtmf_col[i]/(float)sample_rate)); - dtmf_detect_col[i].fac = (float)(2.0*cos(theta)); - - theta = (float)(M_TWO_PI*(dtmf_row[i]*2.0/(float)sample_rate)); - dtmf_detect_row_2nd[i].fac = (float)(2.0*cos(theta)); + theta = (float)(M_TWO_PI*(dtmf_col[i]/(float)sample_rate)); + dtmf_detect_col[i].fac = (float)(2.0f*cos(theta)); + + theta = (float)(M_TWO_PI*(dtmf_row[i]*2.0/(float)sample_rate)); + dtmf_detect_row_2nd[i].fac = (float)(2.0f*cos(theta)); - theta = (float)(M_TWO_PI*(dtmf_col[i]*2.0/(float)sample_rate)); - dtmf_detect_col_2nd[i].fac = (float)(2.0*cos(theta)); - + theta = (float)(M_TWO_PI*(dtmf_col[i]*2.0/(float)sample_rate)); + dtmf_detect_col_2nd[i].fac = (float)(2.0f*cos(theta)); + 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->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_out[i], &dtmf_detect_col[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]); dtmf_detect_state->energy = 0.0; - } - dtmf_detect_state->current_sample = 0; - dtmf_detect_state->detected_digits = 0; - dtmf_detect_state->lost_digits = 0; - dtmf_detect_state->digits[0] = '\0'; - dtmf_detect_state->mhit = 0; + } + dtmf_detect_state->current_sample = 0; + dtmf_detect_state->detected_digits = 0; + dtmf_detect_state->lost_digits = 0; + dtmf_detect_state->digits[0] = '\0'; + dtmf_detect_state->mhit = 0; } void teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map) @@ -197,7 +197,7 @@ } mt->tone_count++; theta = (float)(M_TWO_PI*(map->freqs[x]/(float)mt->sample_rate)); - mt->tdd[x].fac = (float)(2.0 * cos(theta)); + mt->tdd[x].fac = (float)(2.0f * cos(theta)); goertzel_init (&mt->gs[x], &mt->tdd[x]); goertzel_init (&mt->gs2[x], &mt->tdd[x]); } @@ -213,17 +213,17 @@ float eng_sum = 0, eng_all[TELETONE_MAX_TONES]; int gtest = 0, see_hit = 0; - for (sample = 0; sample < samples; sample = limit) { + for (sample = 0; sample < samples; sample = limit) { mt->total_samples++; - if ((samples - sample) >= (mt->min_samples - mt->current_sample)) { - limit = sample + (mt->min_samples - mt->current_sample); + if ((samples - sample) >= (mt->min_samples - mt->current_sample)) { + limit = sample + (mt->min_samples - mt->current_sample); } else { - limit = samples; + limit = samples; } - for (j = sample; j < limit; j++) { - famp = sample_buffer[j]; + for (j = sample; j < limit; j++) { + famp = sample_buffer[j]; mt->energy += famp*famp; @@ -231,16 +231,16 @@ v1 = mt->gs[x].v2; mt->gs[x].v2 = mt->gs[x].v3; mt->gs[x].v3 = (float)(mt->gs[x].fac * mt->gs[x].v2 - v1 + famp); - + v1 = mt->gs2[x].v2; mt->gs2[x].v2 = mt->gs2[x].v3; mt->gs2[x].v3 = (float)(mt->gs2[x].fac*mt->gs2[x].v2 - v1 + famp); } } - mt->current_sample += (limit - sample); - if (mt->current_sample < mt->min_samples) { - continue; + mt->current_sample += (limit - sample); + if (mt->current_sample < mt->min_samples) { + continue; } eng_sum = 0; @@ -277,15 +277,15 @@ } } - /* Reinitialise the detector for the next block */ + /* Reinitialise the detector for the next block */ for(x = 0; x < mt->tone_count; x++) { goertzel_init (&mt->gs[x], &mt->tdd[x]); goertzel_init (&mt->gs2[x], &mt->tdd[x]); } mt->energy = 0.0; - mt->current_sample = 0; - } + mt->current_sample = 0; + } return see_hit; } @@ -295,30 +295,30 @@ int16_t sample_buffer[], int samples) { - float row_energy[GRID_FACTOR]; - float col_energy[GRID_FACTOR]; - float famp; - float v1; - int i; - int j; - int sample; - int best_row; - int best_col; - char hit; - int limit; + float row_energy[GRID_FACTOR]; + float col_energy[GRID_FACTOR]; + float famp; + float v1; + int i; + int j; + int sample; + int best_row; + int best_col; + char hit; + int limit; - hit = 0; - for (sample = 0; sample < samples; sample = limit) { - /* BLOCK_LEN is optimised to meet the DTMF specs. */ - if ((samples - sample) >= (BLOCK_LEN - dtmf_detect_state->current_sample)) { - limit = sample + (BLOCK_LEN - dtmf_detect_state->current_sample); + hit = 0; + for (sample = 0; sample < samples; sample = limit) { + /* BLOCK_LEN is optimised to meet the DTMF specs. */ + if ((samples - sample) >= (BLOCK_LEN - dtmf_detect_state->current_sample)) { + limit = sample + (BLOCK_LEN - dtmf_detect_state->current_sample); } else { - limit = samples; + limit = samples; } - for (j = sample; j < limit; j++) { + for (j = sample; j < limit; j++) { int x = 0; - famp = sample_buffer[j]; + famp = sample_buffer[j]; dtmf_detect_state->energy += famp*famp; @@ -326,7 +326,7 @@ v1 = dtmf_detect_state->row_out[x].v2; dtmf_detect_state->row_out[x].v2 = dtmf_detect_state->row_out[x].v3; dtmf_detect_state->row_out[x].v3 = (float)(dtmf_detect_state->row_out[x].fac*dtmf_detect_state->row_out[x].v2 - v1 + famp); - + v1 = dtmf_detect_state->col_out[x].v2; dtmf_detect_state->col_out[x].v2 = dtmf_detect_state->col_out[x].v3; dtmf_detect_state->col_out[x].v3 = (float)(dtmf_detect_state->col_out[x].fac*dtmf_detect_state->col_out[x].v2 - v1 + famp); @@ -334,59 +334,59 @@ v1 = dtmf_detect_state->col_out2nd[x].v2; dtmf_detect_state->col_out2nd[x].v2 = dtmf_detect_state->col_out2nd[x].v3; dtmf_detect_state->col_out2nd[x].v3 = (float)(dtmf_detect_state->col_out2nd[x].fac*dtmf_detect_state->col_out2nd[x].v2 - v1 + famp); - + v1 = dtmf_detect_state->row_out2nd[x].v2; dtmf_detect_state->row_out2nd[x].v2 = dtmf_detect_state->row_out2nd[x].v3; dtmf_detect_state->row_out2nd[x].v3 = (float)(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; + 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]); + /* We are at the end of a DTMF detection block */ + /* Find the peak row and the peak column */ + row_energy[0] = (float)(teletone_goertzel_result (&dtmf_detect_state->row_out[0])); + col_energy[0] = (float)(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; + for (best_row = best_col = 0, i = 1; i < GRID_FACTOR; i++) { + row_energy[i] = (float)(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]); - if (col_energy[i] > col_energy[best_col]) { - best_col = i; + col_energy[i] = (float)(teletone_goertzel_result (&dtmf_detect_state->col_out[i])); + if (col_energy[i] > col_energy[best_col]) { + best_col = i; } - } - hit = 0; - /* Basic signal level test and the twist test */ - if (row_energy[best_row] >= DTMF_THRESHOLD && + } + hit = 0; + /* Basic signal level test and the twist test */ + if (row_energy[best_row] >= DTMF_THRESHOLD && col_energy[best_col] >= DTMF_THRESHOLD && - col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && - col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { - /* Relative peak test */ - for (i = 0; i < GRID_FACTOR; i++) { - 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])) { - break; - } - } - /* ... and second harmonic test */ - 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->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) { - hit = dtmf_positions[(best_row << 2) + best_col]; - /* Look for two successive similar results */ - /* The logic in the next test is: - We need two successive identical clean detects, with + col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && + col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { + /* Relative peak test */ + for (i = 0; i < GRID_FACTOR; i++) { + 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])) { + break; + } + } + /* ... and second harmonic test */ + 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->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) { + hit = dtmf_positions[(best_row << 2) + best_col]; + /* Look for two successive similar results */ + /* The logic in the next test is: + We need two successive identical clean detects, with something different preceeding it. This can work with back to back differing digits. More importantly, it can work with nasty phones that give a very wobbly start 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->digit_hits[(best_row << 2) + best_col]++; dtmf_detect_state->detected_digits++; @@ -399,26 +399,26 @@ dtmf_detect_state->lost_digits++; } } - } - } - dtmf_detect_state->hit1 = dtmf_detect_state->hit2; - dtmf_detect_state->hit2 = dtmf_detect_state->hit3; - dtmf_detect_state->hit3 = hit; - /* Reinitialise the detector for the next block */ - for (i = 0; i < GRID_FACTOR; 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->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]); - } + } + } + dtmf_detect_state->hit1 = dtmf_detect_state->hit2; + dtmf_detect_state->hit2 = dtmf_detect_state->hit3; + dtmf_detect_state->hit3 = hit; + /* Reinitialise the detector for the next block */ + for (i = 0; i < GRID_FACTOR; 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->row_out2nd[i], &dtmf_detect_row_2nd[i]); + goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]); + } dtmf_detect_state->energy = 0.0; - dtmf_detect_state->current_sample = 0; - } - if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) { + dtmf_detect_state->current_sample = 0; + } + if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) { dtmf_detect_state->mhit = 0; return(0); - } - return (hit); + } + return (hit); } @@ -426,16 +426,16 @@ char *buf, int max) { - if (max > dtmf_detect_state->current_digits) { - max = dtmf_detect_state->current_digits; + if (max > dtmf_detect_state->current_digits) { + max = dtmf_detect_state->current_digits; } - if (max > 0) { - memcpy (buf, dtmf_detect_state->digits, max); - memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max); - dtmf_detect_state->current_digits -= max; - } - buf[max] = '\0'; - return max; + if (max > 0) { + memcpy (buf, dtmf_detect_state->digits, max); + memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max); + dtmf_detect_state->current_digits -= max; + } + buf[max] = '\0'; + return max; } /* For Emacs: Index: src/libteletone_generate.c =================================================================== --- src/libteletone_generate.c (revision 321) +++ src/libteletone_generate.c (working copy) @@ -33,7 +33,7 @@ * 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 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 * 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 * "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 + * 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 @@ -219,8 +219,7 @@ if (map->freqs[0] > 0) { for (freqlen = 0; map->freqs[freqlen] && freqlen < TELETONE_MAX_TONES; freqlen++) { - teletone_dds_state_set_tone(&tones[freqlen], map->freqs[freqlen], ts->rate, 0); - teletone_dds_state_set_tx_level(&tones[freqlen], vol); + teletone_dds_state_set_tone(&tones[freqlen], map->freqs[freqlen], ts->rate, vol); } if (ts->channels > 1) { @@ -250,7 +249,7 @@ sample = 128; for (i = 0; i < freqlen; i++) { - int32_t s = teletone_dds_state_modulate_sample(&tones[i], 0); + int32_t s = teletone_dds_modulate_sample(&tones[i]); sample += s; } sample /= freqlen; @@ -315,7 +314,7 @@ return (char *) memcpy (new, s, len); } -int teletone_run(teletone_generation_session_t *ts, char *cmd) +int teletone_run(teletone_generation_session_t *ts, const char *cmd) { char *data = NULL, *cur = NULL, *end = NULL; int var = 0, LOOPING = 0; Index: src/include/libteletone_detect.h =================================================================== --- src/include/libteletone_detect.h (revision 321) +++ src/include/libteletone_detect.h (working copy) @@ -54,7 +54,7 @@ * 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 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 * 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 * "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 + * 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 @@ -105,9 +105,9 @@ */ #ifndef FALSE -#define FALSE 0 +#define FALSE 0 #ifndef TRUE -#define TRUE (!FALSE) +#define TRUE (!FALSE) #endif #endif @@ -123,13 +123,13 @@ * 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 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 @@ -154,7 +154,7 @@ teletone_goertzel_state_t row_out2nd[GRID_FACTOR]; teletone_goertzel_state_t col_out2nd[GRID_FACTOR]; float energy; - + int current_sample; char digits[TELETONE_MAX_DTMF_DIGITS + 1]; int current_digits; Index: src/include/libteletone_generate.h =================================================================== --- src/include/libteletone_generate.h (revision 321) +++ src/include/libteletone_generate.h (working copy) @@ -33,7 +33,7 @@ * 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 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 * 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 * "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 + * 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 @@ -80,9 +80,8 @@ #include #include #ifdef _MSC_VER -#ifndef __inline__ -#define __inline__ __inline -#endif +#undef inline +#define inline __inline typedef unsigned __int64 uint64_t; typedef unsigned __int32 uint32_t; typedef unsigned __int16 uint16_t; @@ -112,12 +111,12 @@ #define TELETONE_VOL_DB_MAX 0 #define TELETONE_VOL_DB_MIN -63 -#define MAX_PHASE_TONES 4 struct teletone_dds_state { - uint32_t phase_rate[MAX_PHASE_TONES]; + uint32_t phase_rate; uint32_t scale_factor; uint32_t phase_accumulator; + int16_t sample; teletone_process_t tx_level; }; typedef struct teletone_dds_state teletone_dds_state_t; @@ -131,53 +130,42 @@ extern int16_t TELETONE_SINES[SINE_TABLE_MAX]; -static __inline__ int32_t teletone_dds_phase_rate(teletone_process_t tone, uint32_t rate) +static inline int16_t teletone_dds_modulate_sample(teletone_dds_state_t *dds) { - return (int32_t) ((tone * MAX_PHASE_ACCUMULATOR) / rate); -} - -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; - if (pindex >= MAX_PHASE_TONES) { - pindex = 0; + if (bitmask & SINE_TABLE_MAX) { + sine_index = SINE_TABLE_LEN - sine_index; } - if (bitmask & SINE_TABLE_MAX) { - 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; } - dds->phase_accumulator += dds->phase_rate[pindex]; - return (int16_t) (sample * dds->scale_factor >> 15); + dds->phase_accumulator += dds->phase_rate; + + 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) { dds->scale_factor = (int) (powf(10.0f, (tx_level - DBM0_MAX_POWER) / 20.0f) * (32767.0f * 1.414214f)); - dds->tx_level = tx_level; } -static __inline__ void teletone_dds_state_reset_accum(teletone_dds_state_t *dds) +static inline void teletone_dds_state_set_tone(teletone_dds_state_t *dds, teletone_process_t tone, uint32_t rate, float tx_level) { dds->phase_accumulator = 0; -} + dds->phase_rate = (int32_t) ((tone * MAX_PHASE_ACCUMULATOR) / rate); + -static __inline__ int teletone_dds_state_set_tone(teletone_dds_state_t *dds, teletone_process_t tone, uint32_t rate, uint32_t pindex) -{ - if (pindex < MAX_PHASE_TONES) { - dds->phase_rate[pindex] = teletone_dds_phase_rate(tone, rate); - return 0; + if (dds->tx_level != tx_level || !dds->scale_factor) { + teletone_dds_state_set_tx_level(dds, tx_level); } - return -1; + dds->tx_level = tx_level; } @@ -288,7 +276,7 @@ \param cmd the script to execute \return 0 */ -int teletone_run(teletone_generation_session_t *ts, char *cmd); +int teletone_run(teletone_generation_session_t *ts, const char *cmd); #ifdef __cplusplus } Index: src/include/libteletone.h =================================================================== --- src/include/libteletone.h (revision 321) +++ src/include/libteletone.h (working copy) @@ -74,6 +74,9 @@ #ifdef __cplusplus extern "C" { #endif + +#include + #define TELETONE_MAX_DTMF_DIGITS 128 #define TELETONE_MAX_TONES 6 #define TELETONE_TONE_RANGE 127