mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 03:20:57 +00:00
dsp.c: Add fax and DTMF detection unit tests.
* Add fax amplitude and frequency sweep tests. * Add DTMF amplitude and twist unit tests. Change-Id: I8d77c9a1eec89e440d715f998c928687e870c3f7
This commit is contained in:
463
main/dsp.c
463
main/dsp.c
@@ -68,6 +68,7 @@ ASTERISK_REGISTER_FILE()
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/test.h"
|
||||
|
||||
/*! Number of goertzels for progress detect */
|
||||
enum gsamp_size {
|
||||
@@ -597,11 +598,11 @@ static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp
|
||||
tone_energy *= 2.0;
|
||||
s->energy *= s->block_size;
|
||||
|
||||
ast_debug(10, "tone %d, Ew=%.2E, Et=%.2E, s/n=%10.2f\n", s->freq, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
|
||||
ast_debug(10, "%d Hz tone %2d Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
|
||||
hit = 0;
|
||||
if (TONE_THRESHOLD <= tone_energy
|
||||
&& tone_energy > s->energy * s->threshold) {
|
||||
ast_debug(10, "Hit! count=%d\n", s->hit_count);
|
||||
ast_debug(10, "%d Hz tone Hit! %2d Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
|
||||
hit = 1;
|
||||
}
|
||||
|
||||
@@ -733,6 +734,10 @@ static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp
|
||||
best_col = i;
|
||||
}
|
||||
}
|
||||
ast_debug(10, "DTMF best '%c' Erow=%.4E Ecol=%.4E Erc=%.4E Et=%.4E\n",
|
||||
dtmf_positions[(best_row << 2) + best_col],
|
||||
row_energy[best_row], col_energy[best_col],
|
||||
row_energy[best_row] + col_energy[best_col], s->td.dtmf.energy);
|
||||
hit = 0;
|
||||
/* Basic signal level test and the twist test */
|
||||
if (row_energy[best_row] >= DTMF_THRESHOLD &&
|
||||
@@ -753,6 +758,7 @@ static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp
|
||||
(row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) {
|
||||
/* Got a hit */
|
||||
hit = dtmf_positions[(best_row << 2) + best_col];
|
||||
ast_debug(10, "DTMF hit '%c'\n", hit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1946,9 +1952,460 @@ int ast_dsp_get_threshold_from_settings(enum threshold which)
|
||||
return thresholds[which];
|
||||
}
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
static void test_tone_sample_gen(short *slin_buf, int samples, int rate, int freq, short amplitude)
|
||||
{
|
||||
int idx;
|
||||
double sample_step = 2.0 * M_PI * freq / rate;/* radians per step */
|
||||
|
||||
for (idx = 0; idx < samples; ++idx) {
|
||||
slin_buf[idx] = amplitude * sin(sample_step * idx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
static void test_tone_sample_gen_add(short *slin_buf, int samples, int rate, int freq, short amplitude)
|
||||
{
|
||||
int idx;
|
||||
double sample_step = 2.0 * M_PI * freq / rate;/* radians per step */
|
||||
|
||||
for (idx = 0; idx < samples; ++idx) {
|
||||
slin_buf[idx] += amplitude * sin(sample_step * idx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
static void test_dual_sample_gen(short *slin_buf, int samples, int rate, int f1, short a1, int f2, short a2)
|
||||
{
|
||||
test_tone_sample_gen(slin_buf, samples, rate, f1, a1);
|
||||
test_tone_sample_gen_add(slin_buf, samples, rate, f2, a2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
#define TONE_AMPLITUDE_MAX 0x7fff /* Max signed linear amplitude */
|
||||
#define TONE_AMPLITUDE_MIN 80 /* Min signed linear amplitude detectable */
|
||||
|
||||
static int test_tone_amplitude_sweep(struct ast_test *test, struct ast_dsp *dsp, tone_detect_state_t *tone_state)
|
||||
{
|
||||
short slin_buf[tone_state->block_size];
|
||||
int result;
|
||||
int idx;
|
||||
struct {
|
||||
short amp_val;
|
||||
int detect;
|
||||
} amp_tests[] = {
|
||||
{ .amp_val = TONE_AMPLITUDE_MAX, .detect = 1, },
|
||||
{ .amp_val = 10000, .detect = 1, },
|
||||
{ .amp_val = 1000, .detect = 1, },
|
||||
{ .amp_val = 100, .detect = 1, },
|
||||
{ .amp_val = TONE_AMPLITUDE_MIN, .detect = 1, },
|
||||
{ .amp_val = 75, .detect = 0, },
|
||||
{ .amp_val = 10, .detect = 0, },
|
||||
{ .amp_val = 1, .detect = 0, },
|
||||
};
|
||||
|
||||
result = 0;
|
||||
|
||||
for (idx = 0; idx < ARRAY_LEN(amp_tests); ++idx) {
|
||||
int detected;
|
||||
int duration;
|
||||
|
||||
ast_debug(1, "Test %d Hz at amplitude %d\n",
|
||||
tone_state->freq, amp_tests[idx].amp_val);
|
||||
test_tone_sample_gen(slin_buf, tone_state->block_size, DEFAULT_SAMPLE_RATE,
|
||||
tone_state->freq, amp_tests[idx].amp_val);
|
||||
|
||||
detected = 0;
|
||||
for (duration = 0; !detected && duration < tone_state->hits_required + 3; ++duration) {
|
||||
detected = tone_detect(dsp, tone_state, slin_buf, tone_state->block_size) ? 1 : 0;
|
||||
}
|
||||
if (amp_tests[idx].detect != detected) {
|
||||
/*
|
||||
* Both messages are needed. ast_debug for when figuring out
|
||||
* what went wrong and the test update for normal output before
|
||||
* you start debugging. The different logging methods are not
|
||||
* synchronized.
|
||||
*/
|
||||
ast_debug(1,
|
||||
"Test %d Hz at amplitude %d failed. Detected: %s\n",
|
||||
tone_state->freq, amp_tests[idx].amp_val,
|
||||
detected ? "yes" : "no");
|
||||
ast_test_status_update(test,
|
||||
"Test %d Hz at amplitude %d failed. Detected: %s\n",
|
||||
tone_state->freq, amp_tests[idx].amp_val,
|
||||
detected ? "yes" : "no");
|
||||
result = -1;
|
||||
}
|
||||
tone_state->hit_count = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
static int test_dtmf_amplitude_sweep(struct ast_test *test, struct ast_dsp *dsp, int digit_index)
|
||||
{
|
||||
short slin_buf[DTMF_GSIZE];
|
||||
int result;
|
||||
int row;
|
||||
int column;
|
||||
int idx;
|
||||
struct {
|
||||
short amp_val;
|
||||
int digit;
|
||||
} amp_tests[] = {
|
||||
/*
|
||||
* XXX Since there is no current DTMF level detection issue. This test
|
||||
* just checks the current detection levels.
|
||||
*/
|
||||
{ .amp_val = TONE_AMPLITUDE_MAX/2, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_val = 10000, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_val = 1000, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_val = 500, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_val = 250, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_val = 200, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_val = 180, .digit = dtmf_positions[digit_index], },
|
||||
/* Various digits detect and not detect in this range */
|
||||
{ .amp_val = 170, .digit = 0, },
|
||||
{ .amp_val = 100, .digit = 0, },
|
||||
/*
|
||||
* Amplitudes below TONE_AMPLITUDE_MIN start having questionable detection
|
||||
* over quantization and background noise.
|
||||
*/
|
||||
{ .amp_val = TONE_AMPLITUDE_MIN, .digit = 0, },
|
||||
{ .amp_val = 75, .digit = 0, },
|
||||
{ .amp_val = 10, .digit = 0, },
|
||||
{ .amp_val = 1, .digit = 0, },
|
||||
};
|
||||
|
||||
row = (digit_index >> 2) & 0x03;
|
||||
column = digit_index & 0x03;
|
||||
|
||||
result = 0;
|
||||
|
||||
for (idx = 0; idx < ARRAY_LEN(amp_tests); ++idx) {
|
||||
int digit;
|
||||
int duration;
|
||||
|
||||
ast_debug(1, "Test '%c' at amplitude %d\n",
|
||||
dtmf_positions[digit_index], amp_tests[idx].amp_val);
|
||||
test_dual_sample_gen(slin_buf, ARRAY_LEN(slin_buf), DEFAULT_SAMPLE_RATE,
|
||||
(int) dtmf_row[row], amp_tests[idx].amp_val,
|
||||
(int) dtmf_col[column], amp_tests[idx].amp_val);
|
||||
|
||||
digit = 0;
|
||||
for (duration = 0; !digit && duration < 3; ++duration) {
|
||||
digit = dtmf_detect(dsp, &dsp->digit_state, slin_buf, ARRAY_LEN(slin_buf),
|
||||
0, 0);
|
||||
}
|
||||
if (amp_tests[idx].digit != digit) {
|
||||
/*
|
||||
* Both messages are needed. ast_debug for when figuring out
|
||||
* what went wrong and the test update for normal output before
|
||||
* you start debugging. The different logging methods are not
|
||||
* synchronized.
|
||||
*/
|
||||
ast_debug(1,
|
||||
"Test '%c' at amplitude %d failed. Detected Digit: '%c'\n",
|
||||
dtmf_positions[digit_index], amp_tests[idx].amp_val,
|
||||
digit ?: ' ');
|
||||
ast_test_status_update(test,
|
||||
"Test '%c' at amplitude %d failed. Detected Digit: '%c'\n",
|
||||
dtmf_positions[digit_index], amp_tests[idx].amp_val,
|
||||
digit ?: ' ');
|
||||
result = -1;
|
||||
}
|
||||
ast_dsp_digitreset(dsp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
static int test_dtmf_twist_sweep(struct ast_test *test, struct ast_dsp *dsp, int digit_index)
|
||||
{
|
||||
short slin_buf[DTMF_GSIZE];
|
||||
int result;
|
||||
int row;
|
||||
int column;
|
||||
int idx;
|
||||
struct {
|
||||
short amp_row;
|
||||
short amp_col;
|
||||
int digit;
|
||||
} twist_tests[] = {
|
||||
/*
|
||||
* XXX Since there is no current DTMF twist detection issue. This test
|
||||
* just checks the current detection levels.
|
||||
*
|
||||
* Normal twist has the column higher than the row amplitude.
|
||||
* Reverse twist is the other way.
|
||||
*/
|
||||
{ .amp_row = 1000 + 1800, .amp_col = 1000 + 0, .digit = 0, },
|
||||
{ .amp_row = 1000 + 1700, .amp_col = 1000 + 0, .digit = 0, },
|
||||
/* Various digits detect and not detect in this range */
|
||||
{ .amp_row = 1000 + 1400, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 1300, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 1200, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 1100, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 1000, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 100, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 0, .amp_col = 1000 + 100, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 0, .amp_col = 1000 + 200, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 0, .amp_col = 1000 + 300, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 0, .amp_col = 1000 + 400, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 0, .amp_col = 1000 + 500, .digit = dtmf_positions[digit_index], },
|
||||
{ .amp_row = 1000 + 0, .amp_col = 1000 + 550, .digit = dtmf_positions[digit_index], },
|
||||
/* Various digits detect and not detect in this range */
|
||||
{ .amp_row = 1000 + 0, .amp_col = 1000 + 650, .digit = 0, },
|
||||
{ .amp_row = 1000 + 0, .amp_col = 1000 + 700, .digit = 0, },
|
||||
{ .amp_row = 1000 + 0, .amp_col = 1000 + 800, .digit = 0, },
|
||||
};
|
||||
float save_normal_twist;
|
||||
float save_reverse_twist;
|
||||
|
||||
save_normal_twist = dtmf_normal_twist;
|
||||
save_reverse_twist = dtmf_reverse_twist;
|
||||
dtmf_normal_twist = DEF_DTMF_NORMAL_TWIST;
|
||||
dtmf_reverse_twist = DEF_DTMF_REVERSE_TWIST;
|
||||
|
||||
row = (digit_index >> 2) & 0x03;
|
||||
column = digit_index & 0x03;
|
||||
|
||||
result = 0;
|
||||
|
||||
for (idx = 0; idx < ARRAY_LEN(twist_tests); ++idx) {
|
||||
int digit;
|
||||
int duration;
|
||||
|
||||
ast_debug(1, "Test '%c' twist row %d col %d amplitudes\n",
|
||||
dtmf_positions[digit_index],
|
||||
twist_tests[idx].amp_row, twist_tests[idx].amp_col);
|
||||
test_dual_sample_gen(slin_buf, ARRAY_LEN(slin_buf), DEFAULT_SAMPLE_RATE,
|
||||
(int) dtmf_row[row], twist_tests[idx].amp_row,
|
||||
(int) dtmf_col[column], twist_tests[idx].amp_col);
|
||||
|
||||
digit = 0;
|
||||
for (duration = 0; !digit && duration < 3; ++duration) {
|
||||
digit = dtmf_detect(dsp, &dsp->digit_state, slin_buf, ARRAY_LEN(slin_buf),
|
||||
0, 0);
|
||||
}
|
||||
if (twist_tests[idx].digit != digit) {
|
||||
/*
|
||||
* Both messages are needed. ast_debug for when figuring out
|
||||
* what went wrong and the test update for normal output before
|
||||
* you start debugging. The different logging methods are not
|
||||
* synchronized.
|
||||
*/
|
||||
ast_debug(1,
|
||||
"Test '%c' twist row %d col %d amplitudes failed. Detected Digit: '%c'\n",
|
||||
dtmf_positions[digit_index],
|
||||
twist_tests[idx].amp_row, twist_tests[idx].amp_col,
|
||||
digit ?: ' ');
|
||||
ast_test_status_update(test,
|
||||
"Test '%c' twist row %d col %d amplitudes failed. Detected Digit: '%c'\n",
|
||||
dtmf_positions[digit_index],
|
||||
twist_tests[idx].amp_row, twist_tests[idx].amp_col,
|
||||
digit ?: ' ');
|
||||
result = -1;
|
||||
}
|
||||
ast_dsp_digitreset(dsp);
|
||||
}
|
||||
|
||||
dtmf_normal_twist = save_normal_twist;
|
||||
dtmf_reverse_twist = save_reverse_twist;
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
static int test_tone_freq_sweep(struct ast_test *test, struct ast_dsp *dsp, tone_detect_state_t *tone_state, short amplitude)
|
||||
{
|
||||
short slin_buf[tone_state->block_size];
|
||||
int result;
|
||||
int freq;
|
||||
int lower_freq;
|
||||
int upper_freq;
|
||||
|
||||
/* Calculate detection frequency range */
|
||||
lower_freq = tone_state->freq - 4;
|
||||
upper_freq = tone_state->freq + 4;
|
||||
|
||||
result = 0;
|
||||
|
||||
/* Sweep frequencies loop. */
|
||||
for (freq = 100; freq <= 3500; freq += 1) {
|
||||
int detected;
|
||||
int duration;
|
||||
int expect_detection;
|
||||
|
||||
if (freq == tone_state->freq) {
|
||||
/* This case is done by the amplitude sweep. */
|
||||
continue;
|
||||
}
|
||||
|
||||
expect_detection = (lower_freq <= freq && freq <= upper_freq) ? 1 : 0;
|
||||
|
||||
ast_debug(1, "Test %d Hz detection given %d Hz tone at amplitude %d. Range:%d-%d Expect detect: %s\n",
|
||||
tone_state->freq, freq, amplitude, lower_freq, upper_freq,
|
||||
expect_detection ? "yes" : "no");
|
||||
test_tone_sample_gen(slin_buf, tone_state->block_size, DEFAULT_SAMPLE_RATE, freq,
|
||||
amplitude);
|
||||
|
||||
detected = 0;
|
||||
for (duration = 0; !detected && duration < tone_state->hits_required + 3; ++duration) {
|
||||
detected = tone_detect(dsp, tone_state, slin_buf, tone_state->block_size) ? 1 : 0;
|
||||
}
|
||||
if (expect_detection != detected) {
|
||||
/*
|
||||
* Both messages are needed. ast_debug for when figuring out
|
||||
* what went wrong and the test update for normal output before
|
||||
* you start debugging. The different logging methods are not
|
||||
* synchronized.
|
||||
*/
|
||||
ast_debug(1,
|
||||
"Test %d Hz detection given %d Hz tone at amplitude %d failed. Range:%d-%d Detected: %s\n",
|
||||
tone_state->freq, freq, amplitude, lower_freq, upper_freq,
|
||||
detected ? "yes" : "no");
|
||||
ast_test_status_update(test,
|
||||
"Test %d Hz detection given %d Hz tone at amplitude %d failed. Range:%d-%d Detected: %s\n",
|
||||
tone_state->freq, freq, amplitude, lower_freq, upper_freq,
|
||||
detected ? "yes" : "no");
|
||||
result = -1;
|
||||
}
|
||||
tone_state->hit_count = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
AST_TEST_DEFINE(test_dsp_fax_detect)
|
||||
{
|
||||
struct ast_dsp *dsp;
|
||||
enum ast_test_result_state result;
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = "fax";
|
||||
info->category = "/main/dsp/";
|
||||
info->summary = "DSP fax tone detect unit test";
|
||||
info->description =
|
||||
"Tests fax tone detection code.";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
dsp = ast_dsp_new();
|
||||
if (!dsp) {
|
||||
return AST_TEST_FAIL;
|
||||
}
|
||||
|
||||
result = AST_TEST_PASS;
|
||||
|
||||
/* Test CNG tone amplitude detection */
|
||||
if (test_tone_amplitude_sweep(test, dsp, &dsp->cng_tone_state)) {
|
||||
result = AST_TEST_FAIL;
|
||||
}
|
||||
|
||||
/* Test CED tone amplitude detection */
|
||||
if (test_tone_amplitude_sweep(test, dsp, &dsp->ced_tone_state)) {
|
||||
result = AST_TEST_FAIL;
|
||||
}
|
||||
|
||||
/* Test CNG tone frequency detection */
|
||||
if (test_tone_freq_sweep(test, dsp, &dsp->cng_tone_state, TONE_AMPLITUDE_MAX)) {
|
||||
result = AST_TEST_FAIL;
|
||||
}
|
||||
if (test_tone_freq_sweep(test, dsp, &dsp->cng_tone_state, TONE_AMPLITUDE_MIN)) {
|
||||
result = AST_TEST_FAIL;
|
||||
}
|
||||
|
||||
/* Test CED tone frequency detection */
|
||||
if (test_tone_freq_sweep(test, dsp, &dsp->ced_tone_state, TONE_AMPLITUDE_MAX)) {
|
||||
result = AST_TEST_FAIL;
|
||||
}
|
||||
if (test_tone_freq_sweep(test, dsp, &dsp->ced_tone_state, TONE_AMPLITUDE_MIN)) {
|
||||
result = AST_TEST_FAIL;
|
||||
}
|
||||
|
||||
ast_dsp_free(dsp);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
AST_TEST_DEFINE(test_dsp_dtmf_detect)
|
||||
{
|
||||
int idx;
|
||||
struct ast_dsp *dsp;
|
||||
enum ast_test_result_state result;
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = "dtmf";
|
||||
info->category = "/main/dsp/";
|
||||
info->summary = "DSP DTMF detect unit test";
|
||||
info->description =
|
||||
"Tests DTMF detection code.";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
dsp = ast_dsp_new();
|
||||
if (!dsp) {
|
||||
return AST_TEST_FAIL;
|
||||
}
|
||||
|
||||
result = AST_TEST_PASS;
|
||||
|
||||
for (idx = 0; dtmf_positions[idx]; ++idx) {
|
||||
if (test_dtmf_amplitude_sweep(test, dsp, idx)) {
|
||||
result = AST_TEST_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; dtmf_positions[idx]; ++idx) {
|
||||
if (test_dtmf_twist_sweep(test, dsp, idx)) {
|
||||
result = AST_TEST_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
ast_dsp_free(dsp);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
static void test_dsp_shutdown(void)
|
||||
{
|
||||
AST_TEST_UNREGISTER(test_dsp_fax_detect);
|
||||
AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ast_dsp_init(void)
|
||||
{
|
||||
return _dsp_init(0);
|
||||
int res = _dsp_init(0);
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
if (!res) {
|
||||
AST_TEST_REGISTER(test_dsp_fax_detect);
|
||||
AST_TEST_REGISTER(test_dsp_dtmf_detect);
|
||||
|
||||
ast_register_cleanup(test_dsp_shutdown);
|
||||
}
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_dsp_reload(void)
|
||||
|
Reference in New Issue
Block a user