diff spandsp-0.0.3/spandsp-0.0.3/tests/gsm0610_tests.c @ 5:f762bf195c4b

import spandsp-0.0.3
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 16:00:21 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spandsp-0.0.3/spandsp-0.0.3/tests/gsm0610_tests.c	Fri Jun 25 16:00:21 2010 +0200
@@ -0,0 +1,587 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * gsm0610_tests.c - Test the GSM 06.10 FR codec.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2006 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: gsm0610_tests.c,v 1.6 2006/11/19 14:07:27 steveu Exp $
+ */
+
+/*! \file */
+
+/*! \page gsm0610_tests_page GSM 06.10 full rate codec tests
+\section gsm0610_tests_page_sec_1 What does it do?
+Two sets of tests are performed:
+    - The tests defined in the GSM 06.10 specification, using the test data files supplied with
+      the specification.
+    - A generally audio quality test, consisting of compressing and decompressing a speeech
+      file for audible comparison.
+
+The speech file should be recorded at 16 bits/sample, 8000 samples/second, and named
+"pre_gsm0610.wav".
+
+\section gsm0610_tests_page_sec_2 How is it used?
+To perform the tests in the GSM 06.10 specification you need to obtain the test data files from the
+specification. These are copyright material, and so cannot be distributed with spandsp. They can,
+however, be freely downloaded from the ETSI web site.
+
+The files, containing test vectors, which are supplied with the GSM 06.10 specification, should be
+copied to etsitests/gsm0610/unpacked so the files are arranged in the following directories.
+
+./fr_A:
+    Seq01-A.cod Seq01-A.inp Seq01-A.out
+    Seq02-A.cod Seq02-A.inp Seq02-A.out
+    Seq03-A.cod Seq03-A.inp Seq03-A.out
+    Seq04-A.cod Seq04-A.inp Seq04-A.out
+    Seq05-A.out
+
+./fr_L:
+    Seq01.cod   Seq01.inp   Seq01.out
+    Seq02.cod   Seq02.inp   Seq02.out
+    Seq03.cod   Seq03.inp   Seq03.out
+    Seq04.cod   Seq04.inp   Seq04.out
+    Seq05.cod   Seq05.out
+
+./fr_U:
+    Seq01-U.cod Seq01-U.inp Seq01-U.out
+    Seq02-U.cod Seq02-U.inp Seq02-U.out
+    Seq03-U.cod Seq03-U.inp Seq03-U.out
+    Seq04-U.cod Seq04-U.inp Seq04-U.out
+    Seq05-U.out
+
+./fr_homing_A:
+    Homing01_A.out
+    Seq01H_A.cod    Seq01H_A.inp    Seq01H_A.out
+    Seq02H_A.cod    Seq02H_A.inp    Seq02H_A.out
+    Seq03H_A.cod    Seq03H_A.inp    Seq03H_A.out
+    Seq04H_A.cod    Seq04H_A.inp    Seq04H_A.out
+    Seq05H_A.out
+    Seq06H_A.cod    Seq06H_A.inp
+
+./fr_homing_L:
+    Homing01.cod    Homing01.out
+    Seq01h.cod      Seq01h.inp      Seq01h.out
+    Seq02h.cod      Seq02h.inp      Seq02h.out
+    Seq03h.cod      Seq03h.inp      Seq03h.out
+    Seq04h.cod      Seq04h.inp      Seq04h.out
+    Seq05h.cod      Seq05h.out
+    Seq06h.cod      Seq06h.inp
+
+./fr_homing_U:
+    Homing01_U.out
+    Seq01H_U.cod    Seq01H_U.inp    Seq01H_U.out
+    Seq02H_U.cod    Seq02H_U.inp    Seq02H_U.out
+    Seq03H_U.cod    Seq03H_U.inp    Seq03H_U.out
+    Seq04H_U.cod    Seq04H_U.inp    Seq04H_U.out
+    Seq05H_U.out
+    Seq06H_U.cod    Seq06H_U.inp
+
+./fr_sync_A:
+    Seqsync_A.inp
+    Sync000_A.cod   --to--          Sync159_A.cod
+    
+./fr_sync_L:
+    Bitsync.inp
+    Seqsync.inp
+    Sync000.cod     --to--          Sync159.cod
+
+./fr_sync_U:
+    Seqsync_U.inp
+    Sync000_U.cod   --to--          Sync159_U.cod
+
+This is different from the directory structure in which they are supplied. Also, the files names are a little
+different. The supplied names are messy, and inconsistent across the sets. The names required by these tests
+just clean up these inconsistencies. Note that you will need a Windows machine to unpack some of the supplied
+files.
+
+To perform a general audio quality test, gsm0610_tests should be run. The file ../localtests/short_nb_voice.wav
+will be compressed to GSM 06.10 data, decompressed, and the resulting audio stored in post_gsm0610.wav.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#if defined(HAVE_TGMATH_H)
+#include <tgmath.h>
+#endif
+#if defined(HAVE_MATH_H)
+#include <math.h>
+#endif
+#include <assert.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <audiofile.h>
+#include <tiffio.h>
+
+#include "spandsp.h"
+
+#define BLOCK_LEN       160
+
+#define TEST_DIR "../etsitests/gsm0610/unpacked/fr_"
+
+#define IN_FILE_NAME    "../localtests/short_nb_voice.wav"
+#define OUT_FILE_NAME   "post_gsm0610.wav"
+
+#define HIST_LEN        1000
+
+uint8_t law_in_vector[1000000];
+int16_t in_vector[1000000];
+uint16_t code_vector_buf[1000000];
+uint8_t code_vector[1000000];
+uint8_t ref_code_vector[1000000];
+uint8_t decoder_code_vector[1000000];
+uint8_t law_out_vector[1000000];
+int16_t out_vector[1000000];
+int16_t ref_out_vector[1000000];
+uint8_t ref_law_out_vector[1000000];
+int vector_len;
+
+static int get_test_vector(int full, int disk, const char *name)
+{
+    char buf[500];
+    int in;
+    int len;
+    int i;
+    
+    if (full)
+    {
+        sprintf(buf, "%s%c/%s.inp", TEST_DIR, 'L', name);
+        if ((in = open(buf, O_RDONLY)) < 0)
+        {
+            fprintf(stderr, "Cannot open %s\n", buf);
+            exit(2);
+        }
+        len = read(in, in_vector, 1000000);
+        close(in);
+        len /= sizeof(int16_t);
+        vector_len = len;
+    }
+
+    sprintf(buf, "%s%c/%s.out", TEST_DIR, 'L', name);
+    if ((in = open(buf, O_RDONLY)) < 0)
+    {
+        fprintf(stderr, "Cannot open %s\n", buf);
+        exit(2);
+    }
+    len = read(in, ref_out_vector, 1000000);
+    close(in);
+    len /= sizeof(int16_t);
+    if (full)
+    {
+        if (len != vector_len)
+        {
+            fprintf(stderr, "Input and reference vector lengths do not match - %d %d\n", vector_len, len);
+            exit(2);
+        }
+    }
+    else
+    {
+        vector_len = len;
+    }
+    
+    sprintf(buf, "%s%c/%s.cod", TEST_DIR, 'L', name);
+    if ((in = open(buf, O_RDONLY)) < 0)
+    {
+        fprintf(stderr, "Cannot open %s\n", buf);
+        exit(2);
+    }
+    len = read(in, code_vector_buf, 1000000);
+    close(in);
+    len /= sizeof(int16_t);
+    for (i = 0;  i < len;  i++)
+    {
+        ref_code_vector[i] = code_vector_buf[i];
+        decoder_code_vector[i] = code_vector_buf[i];
+    }
+    if (len*BLOCK_LEN != vector_len*76)
+    {
+        fprintf(stderr, "Input and code vector lengths do not match - %d %d\n", vector_len, len);
+        exit(2);
+    }
+
+    return len;
+}
+
+static int get_law_test_vector(int full, int law, const char *name)
+{
+    char buf[500];
+    int in;
+    int len;
+    int i;
+    int law_uc;
+    
+    law_uc = toupper(law);
+    
+    if (full)
+    {
+        sprintf(buf, "%s%c/%s-%c.inp", TEST_DIR, law_uc, name, law_uc);
+        if ((in = open(buf, O_RDONLY)) < 0)
+        {
+            fprintf(stderr, "Cannot open %s\n", buf);
+            exit(2);
+        }
+        len = read(in, law_in_vector, 1000000);
+        close(in);
+        vector_len = len;
+
+        sprintf(buf, "%s%c/%s-%c.cod", TEST_DIR, law_uc, name, law_uc);
+        if ((in = open(buf, O_RDONLY)) < 0)
+        {
+            fprintf(stderr, "Cannot open %s\n", buf);
+            exit(2);
+        }
+        len = read(in, code_vector_buf, 1000000);
+        close(in);
+        len /= sizeof(int16_t);
+        for (i = 0;  i < len;  i++)
+            ref_code_vector[i] = code_vector_buf[i];
+        if (len*BLOCK_LEN != vector_len*76)
+        {
+            fprintf(stderr, "Input and code vector lengths do not match - %d %d\n", vector_len, len);
+            exit(2);
+        }
+    }
+
+    sprintf(buf, "%s%c/%s-%c.out", TEST_DIR, law_uc, name, law_uc);
+    if ((in = open(buf, O_RDONLY)) < 0)
+    {
+        fprintf(stderr, "Cannot open %s\n", buf);
+        exit(2);
+    }
+    len = read(in, ref_law_out_vector, 1000000);
+    close(in);
+    if (full)
+    {
+        if (len != vector_len)
+        {
+            fprintf(stderr, "Input and reference vector lengths do not match - %d %d\n", vector_len, len);
+            exit(2);
+        }
+    }
+    else
+    {
+        vector_len = len;
+    }
+
+    sprintf(buf, "%s%c/%s.cod", TEST_DIR, 'L', name);
+    if ((in = open(buf, O_RDONLY)) < 0)
+    {
+        fprintf(stderr, "Cannot open %s\n", buf);
+        exit(2);
+    }
+    len = read(in, code_vector_buf, 1000000);
+    close(in);
+    len /= sizeof(int16_t);
+    for (i = 0;  i < len;  i++)
+        decoder_code_vector[i] = code_vector_buf[i];
+    
+    return len;
+}
+
+static int perform_linear_test(int full, int disk, const char *name)
+{
+    gsm0610_state_t *gsm0610_enc_state;
+    gsm0610_state_t *gsm0610_dec_state;
+    int i;
+    int xxx;
+    int mismatches;
+
+    printf("Performing linear test '%s' from disk %d\n", name, disk);
+
+    get_test_vector(full, disk, name);
+
+    if (full)
+    {
+        if ((gsm0610_enc_state = gsm0610_init(NULL, GSM0610_PACKING_NONE)) == NULL)
+        {
+            fprintf(stderr, "    Cannot create encoder\n");
+            exit(2);
+        }
+        xxx = gsm0610_encode(gsm0610_enc_state, code_vector, in_vector, vector_len/BLOCK_LEN);
+
+        printf("Check code vector of length %d\n", xxx);
+        for (i = 0, mismatches = 0;  i < xxx;  i++)
+        {
+            if (code_vector[i] != ref_code_vector[i])
+            {
+                printf("%8d/%3d: %6d %6d\n", i/76, i%76, code_vector[i], ref_code_vector[i]);
+                mismatches++;
+            }
+        }
+        gsm0610_release(gsm0610_enc_state);
+        if (mismatches)
+        {
+            printf("Test failed: %d of %d samples mismatch\n", mismatches, xxx);
+            exit(2);
+        }
+        printf("Test passed\n");
+    }
+
+    if ((gsm0610_dec_state = gsm0610_init(NULL, GSM0610_PACKING_NONE)) == NULL)
+    {
+        fprintf(stderr, "    Cannot create decoder\n");
+        exit(2);
+    }
+    xxx = gsm0610_decode(gsm0610_dec_state, out_vector, decoder_code_vector, vector_len/BLOCK_LEN);
+    printf("Check output vector of length %d\n", vector_len);
+    for (i = 0, mismatches = 0;  i < vector_len;  i++)
+    {
+        if (out_vector[i] != ref_out_vector[i])
+        {
+            printf("%8d: %6d %6d\n", i, out_vector[i], ref_out_vector[i]);
+            mismatches++;
+        }
+    }
+    if (mismatches)
+    {
+        printf("Test failed: %d of %d samples mismatch\n", mismatches, vector_len);
+        exit(2);
+    }
+    gsm0610_release(gsm0610_dec_state);
+    printf("Test passed\n");
+    return 0;
+}
+
+static int perform_law_test(int full, int law, const char *name)
+{
+    gsm0610_state_t *gsm0610_enc_state;
+    gsm0610_state_t *gsm0610_dec_state;
+    int i;
+    int xxx;
+    int mismatches;
+
+    if (law == 'a')
+        printf("Performing A-law test '%s'\n", name);
+    else
+        printf("Performing u-law test '%s'\n", name);
+        
+    get_law_test_vector(full, law, name);
+
+    if (full)
+    {
+        if ((gsm0610_enc_state = gsm0610_init(NULL, GSM0610_PACKING_NONE)) == NULL)
+        {
+            fprintf(stderr, "    Cannot create encoder\n");
+            exit(2);
+        }
+        if (law == 'a')
+        {
+            for (i = 0;  i < vector_len;  i++)
+                in_vector[i] = alaw_to_linear(law_in_vector[i]);
+        }
+        else
+        {
+            for (i = 0;  i < vector_len;  i++)
+                in_vector[i] = ulaw_to_linear(law_in_vector[i]);
+        }
+        xxx = gsm0610_encode(gsm0610_enc_state, code_vector, in_vector, vector_len/BLOCK_LEN);
+
+        printf("Check code vector of length %d\n", xxx);
+        for (i = 0, mismatches = 0;  i < xxx;  i++)
+        {
+            if (code_vector[i] != ref_code_vector[i])
+            {
+                printf("%8d/%3d: %6d %6d %6d\n", i/76, i%76, code_vector[i], ref_code_vector[i], decoder_code_vector[i]);
+                mismatches++;
+            }
+        }
+        if (mismatches)
+        {
+            printf("Test failed: %d of %d samples mismatch\n", mismatches, xxx);
+            exit(2);
+        }
+        printf("Test passed\n");
+        gsm0610_release(gsm0610_enc_state);
+    }
+
+    if ((gsm0610_dec_state = gsm0610_init(NULL, GSM0610_PACKING_NONE)) == NULL)
+    {
+        fprintf(stderr, "    Cannot create decoder\n");
+        exit(2);
+    }
+    xxx = gsm0610_decode(gsm0610_dec_state, out_vector, decoder_code_vector, vector_len/BLOCK_LEN);
+    if (law == 'a')
+    {
+        for (i = 0;  i < vector_len;  i++)
+            law_out_vector[i] = linear_to_alaw(out_vector[i]);
+    }
+    else
+    {
+        for (i = 0;  i < vector_len;  i++)
+            law_out_vector[i] = linear_to_ulaw(out_vector[i]);
+    }
+    printf("Check output vector of length %d\n", vector_len);
+    for (i = 0, mismatches = 0;  i < vector_len;  i++)
+    {
+        if (law_out_vector[i] != ref_law_out_vector[i])
+        {
+            printf("%8d: %6d %6d\n", i, law_out_vector[i], ref_law_out_vector[i]);
+            mismatches++;
+        }
+    }
+    if (mismatches)
+    {
+        printf("Test failed: %d of %d samples mismatch\n", mismatches, vector_len);
+        exit(2);
+    }
+    gsm0610_release(gsm0610_dec_state);
+    printf("Test passed\n");
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    AFfilehandle inhandle;
+    AFfilehandle outhandle;
+    AFfilesetup filesetup;
+    int frames;
+    int outframes;
+    float x;
+    int16_t pre_amp[HIST_LEN];
+    int16_t post_amp[HIST_LEN];
+    uint8_t gsm0610_data[HIST_LEN];
+    gsm0610_state_t *gsm0610_enc_state;
+    gsm0610_state_t *gsm0610_dec_state;
+    int etsitests;
+    int packing;
+    int i;
+
+    etsitests = TRUE;
+    packing = GSM0610_PACKING_NONE;
+    for (i = 1;  i < argc;  i++)
+    {
+        if (strcmp(argv[i], "-l") == 0)
+        {
+            etsitests = FALSE;
+            continue;
+        }
+        if (strcmp(argv[i], "-p") == 0)
+        {
+            packing = atoi(argv[++i]);
+            continue;
+        }
+        fprintf(stderr, "Unknown parameter %s specified.\n", argv[i]);
+        exit(2);
+    }
+
+    if (etsitests)
+    {
+        perform_linear_test(TRUE, 1, "Seq01");
+        perform_linear_test(TRUE, 1, "Seq02");
+        perform_linear_test(TRUE, 1, "Seq03");
+        perform_linear_test(TRUE, 1, "Seq04");
+        perform_linear_test(FALSE, 1, "Seq05");
+        perform_law_test(TRUE, 'a', "Seq01");
+        perform_law_test(TRUE, 'a', "Seq02");
+        perform_law_test(TRUE, 'a', "Seq03");
+        perform_law_test(TRUE, 'a', "Seq04");
+        perform_law_test(FALSE, 'a', "Seq05");
+        perform_law_test(TRUE, 'u', "Seq01");
+        perform_law_test(TRUE, 'u', "Seq02");
+        perform_law_test(TRUE, 'u', "Seq03");
+        perform_law_test(TRUE, 'u', "Seq04");
+        perform_law_test(FALSE, 'u', "Seq05");
+
+        printf("Tests passed.\n");
+    }
+    else
+    {
+        if ((inhandle = afOpenFile(IN_FILE_NAME, "r", 0)) == AF_NULL_FILEHANDLE)
+        {
+            printf("    Cannot open wave file '%s'\n", IN_FILE_NAME);
+            exit(2);
+        }
+        if ((x = afGetFrameSize(inhandle, AF_DEFAULT_TRACK, 1)) != 2.0)
+        {
+            printf("    Unexpected frame size in wave file '%s'\n", IN_FILE_NAME);
+            exit(2);
+        }
+        if ((x = afGetRate(inhandle, AF_DEFAULT_TRACK)) != (float) SAMPLE_RATE)
+        {
+            printf("    Unexpected sample rate in wave file '%s'\n", IN_FILE_NAME);
+            exit(2);
+        }
+        if ((x = afGetChannels(inhandle, AF_DEFAULT_TRACK)) != 1.0)
+        {
+            printf("    Unexpected number of channels in wave file '%s'\n", IN_FILE_NAME);
+            exit(2);
+        }
+        if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP)
+        {
+            fprintf(stderr, "    Failed to create file setup\n");
+            exit(2);
+        }
+        afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
+        afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
+        afInitFileFormat(filesetup, AF_FILE_WAVE);
+        afInitChannels(filesetup, AF_DEFAULT_TRACK, 1);
+    
+        outhandle = afOpenFile(OUT_FILE_NAME, "w", filesetup);
+        if (outhandle == AF_NULL_FILEHANDLE)
+        {
+            fprintf(stderr, "    Cannot create wave file '%s'\n", OUT_FILE_NAME);
+            exit(2);
+        }
+    
+        if ((gsm0610_enc_state = gsm0610_init(NULL, packing)) == NULL)
+        {
+            fprintf(stderr, "    Cannot create encoder\n");
+            exit(2);
+        }
+            
+        if ((gsm0610_dec_state = gsm0610_init(NULL, packing)) == NULL)
+        {
+            fprintf(stderr, "    Cannot create decoder\n");
+            exit(2);
+        }
+
+        while ((frames = afReadFrames(inhandle, AF_DEFAULT_TRACK, pre_amp, 2*BLOCK_LEN)))
+        {
+            gsm0610_encode(gsm0610_enc_state, gsm0610_data, pre_amp, (packing == GSM0610_PACKING_WAV49)  ?  1  :  2);
+            gsm0610_decode(gsm0610_dec_state, post_amp, gsm0610_data, (packing == GSM0610_PACKING_WAV49)  ?  1  :  2);
+            outframes = afWriteFrames(outhandle, AF_DEFAULT_TRACK, post_amp, frames);
+        }
+    
+        if (afCloseFile(inhandle) != 0)
+        {
+            printf("    Cannot close wave file '%s'\n", IN_FILE_NAME);
+            exit(2);
+        }
+        if (afCloseFile(outhandle) != 0)
+        {
+            printf("    Cannot close wave file '%s'\n", OUT_FILE_NAME);
+            exit(2);
+        }
+        afFreeFileSetup(filesetup);
+        gsm0610_release(gsm0610_enc_state);
+        gsm0610_release(gsm0610_dec_state);
+    }
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.