Example #1
0
int main(int argc, char *argv[])
{
	int rc = 0;
	short readbuf[160];
	char digitsbuf[255];
	int fd = open(argv[1], O_RDONLY);

#if defined(BELL_DETECTOR)
	bell_mf_rx_state_t *rxstate = NULL;
	if (!(rxstate = bell_mf_rx_init(rxstate, NULL, NULL))) {
		fprintf(stderr, "bell_mf_rx_init\n");
		return -1;
	}
#elif defined(MF_DETECTOR_FWD)
	r2_mf_rx_state_t *rxstate = NULL;
	if (!(rxstate = r2_mf_rx_init(rxstate, 1, NULL, NULL))) {
		fprintf(stderr, "r2_mf_rx_init fwd\n");
		return -1;
	}
#elif defined(MF_DETECTOR_BWD)
	r2_mf_rx_state_t *rxstate = NULL;
	if (!(rxstate = r2_mf_rx_init(rxstate, 0, NULL, NULL))) {
		fprintf(stderr, "r2_mf_rx_init backward\n");
		return -1;
	}
#elif defined(DTMF_DETECTOR)
	dtmf_rx_state_t *rxstate = NULL;
	if (!(rxstate = dtmf_rx_init(rxstate, NULL, NULL))) {
		fprintf(stderr, "dtmf_rx_init\n");
		return -1;
	}
#else
#error "define detector type!"
#endif

	if (fd == -1) {
		perror("fopen");
		return -1;
	}

	while (1) {
		rc = read(fd, readbuf, sizeof(readbuf)/sizeof(readbuf[0]));
		if (rc < 0) {
			perror("read");
			break;
		}
		if (!rc) {
			break;
		}
#if defined(BELL_DETECTOR)
		rc = bell_mf_rx(rxstate, readbuf, rc/2);
		if (rc != 0) {
			fprintf(stderr, "Unprocessed samples: %d\n", rc);
			break;
		}
		digitsbuf[0] = '\0';
		rc = bell_mf_rx_get(rxstate, digitsbuf, sizeof(digitsbuf)-1);
		if (rc > 0) {
			printf("Rx digits: %s\n", digitsbuf);
		}
#elif defined(MF_DETECTOR_FWD) || defined(MF_DETECTOR_BWD)
		rc = r2_mf_rx(rxstate, readbuf, rc/2);
		if (rc != 0) {
			fprintf(stderr, "Unprocessed samples: %d\n", rc);
			break;
		}
		rc = r2_mf_rx_get(rxstate);
		if (rc > 0) {
			printf("Rx digit: %c\n", rc);
		}
#elif defined(DTMF_DETECTOR)
		rc = dtmf_rx(rxstate, readbuf, rc/2);
		if (rc != 0) {
			fprintf(stderr, "Unprocessed samples: %d\n", rc);
			break;
		}
		digitsbuf[0] = '\0';
		rc = dtmf_rx_get(rxstate, digitsbuf, sizeof(digitsbuf)-1);
		if (rc > 0) {
			printf("Rx digit: %s\n", digitsbuf);
		}
#else
#error "define detector type!"
#endif
	}

#if defined(BELL_DETECTOR)
	bell_mf_rx_free(rxstate);
#elif defined(MF_DETECTOR_FWD) || defined(MF_DETECTOR_BWD)
	r2_mf_rx_free(rxstate);
#elif defined(DTMF_DETECTOR)
	dtmf_rx_free(rxstate);
#endif

	close(fd);
	return 0;
}
Example #2
0
static int test_a_tone_set(int fwd)
{
    int i;
    int j;
    int len;
    int sample;
    const char *s;
    char digit;
    int actual;
    int nplus;
    int nminus;
    float rrb;
    float rcfo;
    int16_t amp[100000];
    r2_mf_rx_state_t mf_state;
    awgn_state_t noise_source;
    const mf_digit_tones_t *tone;

    if (fwd)
        tone = &r2_mf_fwd_tones[0];
    else
        tone = &r2_mf_back_tones[0];
    r2_mf_rx_init(&mf_state, fwd);

    /* Test 1: Mitel's test 1 isn't really a test. Its a calibration step,
       which has no meaning here. */

    printf ("Test 1: Calibration\n");
    printf ("    Passed\n");

    /* Test 2: Decode check
       This is a sanity check, that all digits are reliably detected
       under ideal conditions.  Each possible digit is repeated 10 times,
       with 68ms bursts. The level of each tone is about 6dB down from clip */

    printf ("Test 2: Decode check\n");
    my_mf_gen_init(0.0, -3, 0.0, -3, 68, fwd);
    s = r2_mf_tone_codes;
    while (*s)
    {
        digit = *s++;
        for (i = 0;  i < 10;  i++)
        {
            len = my_mf_generate(amp, digit);
            codec_munge (amp, len);
            actual = r2_mf_rx(&mf_state, amp, len);
            if (actual != digit)
            {
                printf ("    Sent     '%c'\n", digit);
                printf ("    Received 0x%X\n", actual);
                printf ("    Failed\n");
                exit (2);
            }
        }
    }
    printf ("    Passed\n");

    /* Test 3: Recognition bandwidth and channel centre frequency check.
       Use all digits. Each digit types requires four tests to complete
       the check. Each section contains 40 pulses of 68ms duration,
       with an amplitude of -20dB from clip per frequency.

       Four sections covering the tests for one tone (1 digit) are:
       a. H frequency at 0% deviation from center, L frequency at +0.1%.
          L frequency is then increments in +01.% steps up to +4%. The
          number of tone bursts is noted and designated N+.
       b. H frequency at 0% deviation, L frequency at -0.1%. L frequency
          is then incremental in -0.1% steps, up to -4%. The number of
          tone bursts is noted and designated N-.
       c. The test in (a) is repeated with the L frequency at 0% and the
          H frequency varied up to +4%.
       d. The test in (b) is repeated with the L frequency and 0% and the
          H frequency varied to -4%.

       Receiver Recognition Bandwidth (RRB) is calculated as follows:
            RRB% = (N+ + N-)/10
       Receiver Center Frequency Offset (RCFO) is calculated as follows:
            RCFO% = X + (N+ - N-)/20
            
       Note that this test doesn't test what it says it is testing at all,
       and the results are quite inaccurate, if not a downright lie! However,
       it follows the Mitel procedure, so how can it be bad? :)
       
       The spec calls for +-4 +-10Hz (ie +-14Hz) of bandwidth. */

    printf ("Test 3: Recognition bandwidth and channel centre frequency check\n");
    s = r2_mf_tone_codes;
    j = 0;
    while (*s)
    {
        digit = *s++;
        for (nplus = 0, i = 1;  i <= 60;  i++)
        {
            my_mf_gen_init((float) i/1000.0, -17, 0.0, -17, 68, fwd);
            len = my_mf_generate(amp, digit);
            codec_munge(amp, len);
            if (r2_mf_rx(&mf_state, amp, len) == digit)
                nplus++;
        }
        for (nminus = 0, i = -1;  i >= -60;  i--)
        {
            my_mf_gen_init((float) i/1000.0, -17, 0.0, -17, 68, fwd);
            len = my_mf_generate(amp, digit);
            codec_munge(amp, len);
            if (r2_mf_rx(&mf_state, amp, len) == digit)
                nminus++;
        }
        rrb = (float) (nplus + nminus)/10.0;
        rcfo = (float) (nplus - nminus)/10.0;
        printf ("    %c (low)  rrb = %5.2f%%, rcfo = %5.2f%%, max -ve = %5.2f, max +ve = %5.2f\n",
                digit,
                rrb,
                rcfo,
                (float) nminus/10.0,
                (float) nplus/10.0);

        if (rrb < rcfo + (2.0*100.0*14.0/r2_mf_fwd_tones[j].f1)  ||  rrb >= 15.0 + rcfo)
        {
            printf ("    Failed\n");
            exit (2);
        }

        for (nplus = 0, i = 1;  i <= 60;  i++)
        {
            my_mf_gen_init(0.0, -17, (float) i/1000.0, -17, 68, fwd);
            len = my_mf_generate(amp, digit);
            codec_munge(amp, len);
            if (r2_mf_rx(&mf_state, amp, len) == digit)
                nplus++;
        }
        for (nminus = 0, i = -1;  i >= -60;  i--)
        {
            my_mf_gen_init(0.0, -17, (float) i/1000.0, -17, 68, fwd);
            len = my_mf_generate(amp, digit);
            codec_munge(amp, len);
            if (r2_mf_rx(&mf_state, amp, len) == digit)
                nminus++;
        }
        rrb = (float) (nplus + nminus)/10.0;
        rcfo = (float) (nplus - nminus)/10.0;
        printf ("    %c (high) rrb = %5.2f%%, rcfo = %5.2f%%, max -ve = %5.2f, max +ve = %5.2f\n",
                digit,
                rrb,
                rcfo,
                (float) nminus/10.0,
                (float) nplus/10.0);
        if (rrb < rcfo + (2.0*100.0*14.0/r2_mf_fwd_tones[j].f2)  ||  rrb >= 15.0 + rcfo)
        {
            printf ("    Failed\n");
            exit (2);
        }
        j++;
    }
    printf ("    Passed\n");

    /* Test 4: Acceptable amplitude ratio (twist).
       Twist all digits in both directions, and check the maximum twist
       we can accept. The way this is done is styled after the Mitel DTMF
       test, and has good and bad points. */

    printf ("Test 4: Acceptable amplitude ratio (twist)\n");
    s = r2_mf_tone_codes;
    while (*s)
    {
        digit = *s++;
        for (nplus = 0, i = -50;  i >= -250;  i--)
        {
            my_mf_gen_init(0.0, -5, 0.0, i/10, 68, fwd);

            len = my_mf_generate(amp, digit);
            codec_munge (amp, len);
            if (r2_mf_rx(&mf_state, amp, len) == digit)
                nplus++;
        }
        printf ("    %c normal twist  = %.2fdB\n", digit, (float) nplus/10.0);
        if (nplus < 70)
        {
            printf ("    Failed\n");
            exit (2);
        }
        for (nminus = 0, i = -50;  i >= -250;  i--)
        {
            my_mf_gen_init(0.0, i/10, 0.0, -5, 68, fwd);

            len = my_mf_generate(amp, digit);
            codec_munge(amp, len);
            if (r2_mf_rx(&mf_state, amp, len) == digit)
                nminus++;
        }
        printf ("    %c reverse twist = %.2fdB\n", digit, (float) nminus/10.0);
        if (nminus < 70)
        {
            printf ("    Failed\n");
            exit (2);
        }
    }
    printf ("    Passed\n");

    /* Test 5: Dynamic range
       This test sends all possible digits, with gradually increasing 
       amplitude. We determine the span over which we achieve reliable
       detection. */
       
    printf ("Test 5: Dynamic range\n");
    for (nplus = nminus = -1000, i = -50;  i <= 3;  i++)
    {
        s = r2_mf_tone_codes;
        while (*s)
        {
            digit = *s++;
            my_mf_gen_init(0.0, i, 0.0, i, 68, fwd);
            for (j = 0;  j < 100;  j++)
            {
                len = my_mf_generate(amp, digit);
                codec_munge(amp, len);
                if (r2_mf_rx(&mf_state, amp, len) != digit)
                    break;
            }
            if (j < 100)
                break;
        }
        if (j == 100)
        {
            if (nplus == -1000)
                nplus = i;
        }
        else
        {
            if (nplus != -1000  &&  nminus == -1000)
                nminus = i;
        }
    }
    printf ("    Dynamic range = %ddB to %ddB\n", nplus, nminus - 1);
    if (nplus > -35  ||  nminus <= -5)
    {
        printf("    Failed\n");
        exit(2);
    }
    printf ("    Passed\n");

    /* Test 6: Guard time
       This test sends all possible digits, with a gradually reducing 
       duration. */

    printf ("Test 6: Guard time\n");
    for (i = 30;  i < 62;  i++)
    {
        s = r2_mf_tone_codes;
        j = 0;
        while (*s)
        {
            digit = *s++;
            my_mf_gen_init(0.0, -5, 0.0, -3, i, fwd);
            for (j = 0;  j < 500;  j++)
            {
                len = my_mf_generate(amp, digit);
                codec_munge(amp, len);
                if (r2_mf_rx(&mf_state, amp, len) != digit)
                    break;
            }
            if (j < 500)
                break;
        }
        if (j == 500)
            break;
    }
    printf ("    Guard time = %dms\n", i);
    if (i > 61)
    {
        printf("    Failed\n");
        exit(2);
    }
    printf ("    Passed\n");

    /* Test 7: Acceptable signal to noise ratio
       We send all possible digits at -6dBm from clip, mixed with AWGN.
       We gradually reduce the noise until we get clean detection. */

    printf ("Test 7: Acceptable signal to noise ratio\n");
    my_mf_gen_init(0.0, -3, 0.0, -3, 68, fwd);
    for (i = -3;  i > -50;  i--)
    {
        s = r2_mf_tone_codes;
        while (*s)
        {
            digit = *s++;
            awgn_init_dbm0(&noise_source, 1234567, (float) i);
            for (j = 0;  j < 500;  j++)
            {
                len = my_mf_generate(amp, digit);
                for (sample = 0;  sample < len;  sample++)
                    amp[sample] = saturate(amp[sample] + awgn(&noise_source));
                codec_munge(amp, len);
                if (r2_mf_rx(&mf_state, amp, len) != digit)
                    break;
            }
            if (j < 500)
                break;
        }
        if (j == 500)
            break;
    }
    printf("    Acceptable S/N ratio is %ddB\n", -3 - i);
    if (-3 - i > 26)
    {
        printf("    Failed\n");
        exit(2);
    }
    printf("    Passed\n");

    /* The remainder of the Mitel tape is the talk-off test. This is
       meaningless for R2 MF. However the decoder's tolerance of
       out of band noise is significant. */
    /* TODO: add a OOB tolerance test. */
    
    return 0;
}