From b86e88413d4c6ec428aaedb147f7675f28882fe4 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Fri, 14 Jul 2023 12:36:50 +0930 Subject: clang-format -i applied to src unittest misc --- unittest/compare_floats.c | 138 +- unittest/compare_ints.c | 269 +- unittest/freedv_700d_comprx.c | 218 +- unittest/freedv_700d_comptx.c | 49 +- unittest/hts1a.h | 8890 ++++---------------------------------- unittest/mksine.c | 78 +- unittest/t16_8.c | 140 +- unittest/t16_8_short.c | 108 +- unittest/t48_8.c | 129 +- unittest/t48_8_short.c | 101 +- unittest/tcohpsk.c | 472 +- unittest/tesno_est.c | 31 +- unittest/tfdmdv.c | 453 +- unittest/tfifo.c | 131 +- unittest/tfmfsk.c | 306 +- unittest/tfreedv_2400A_rawdata.c | 155 +- unittest/tfreedv_2400B_rawdata.c | 155 +- unittest/tfreedv_800XA_rawdata.c | 220 +- unittest/tfreedv_data_channel.c | 393 +- unittest/tfsk.c | 360 +- unittest/tfsk_llr.c | 66 +- unittest/thash.c | 9 +- unittest/tnewamp1.c | 482 +-- unittest/tnlp.c | 206 +- unittest/tofdm.c | 893 ++-- unittest/tofdm_acq.c | 142 +- unittest/tqam16.c | 36 +- unittest/tquisk_filter.c | 59 +- unittest/tvq_mbest.c | 33 +- unittest/vq_mbest.c | 498 ++- 30 files changed, 4083 insertions(+), 11137 deletions(-) (limited to 'unittest') diff --git a/unittest/compare_floats.c b/unittest/compare_floats.c index 572ce16..1d98968 100644 --- a/unittest/compare_floats.c +++ b/unittest/compare_floats.c @@ -1,11 +1,11 @@ /* compare floats - a test utility */ +#include +#include +#include #include #include #include -#include -#include -#include /* Declarations */ @@ -14,76 +14,74 @@ /* Main */ int main(int argc, char *argv[]) { + char usage[] = "Usage: %s [-t tolerance] file1 file2\n"; - char usage[] = "Usage: %s [-t tolerance] file1 file2\n"; - - float tol = .001; - - int opt; - while ((opt = getopt(argc, argv, "t:")) != -1) { - switch (opt) { - case 't': - tol = atof(optarg); - break; - default: - fprintf(stderr, usage, argv[0]); - exit(1); - } - } + float tol = .001; - if ((optind + 2) > argc) { + int opt; + while ((opt = getopt(argc, argv, "t:")) != -1) { + switch (opt) { + case 't': + tol = atof(optarg); + break; + default: fprintf(stderr, usage, argv[0]); exit(1); - } - char *fname1 = argv[optind++]; - char *fname2 = argv[optind++]; - - FILE *f1 = fopen(fname1, "rb"); - if (f1 == NULL) { - fprintf(stderr, "Error opening file1 \"%s\": ", fname1); - perror(NULL); - exit(1); - } - - FILE *f2 = fopen(fname2, "rb"); - if (f2 == NULL) { - fprintf(stderr, "Error opening file2 \"%s\": ", fname2); - perror(NULL); - exit(1); - } - - float data1, data2; - int count = 0; - int errors = 0; - double rms_sum = 0; - - while (fread(&data1, sizeof(float), 1, f1)) { - if (!fread(&data2, sizeof(float), 1, f2)) { - fprintf(stderr, "Error: file2 is shorter!"); - exit(1); - } - float err = fabsf((data1 - data2) / data1); - if (err > tol) { - errors ++; - printf("%d %g %g %g\n", count, data1, data2, err); - } - rms_sum += (err * err); - count ++; - } - if (fread(&data2, sizeof(float), 1, f2)) { - fprintf(stderr, "Error: file1 is shorter\n"); - exit(1); - } - - if (errors) { - printf("Fail: %d errors\n", errors); - printf(" rms error = %g\n", ((double)rms_sum/count)); - exit(1); - } - else printf("Pass\n"); - exit(0); - - } // main - + } + } + + if ((optind + 2) > argc) { + fprintf(stderr, usage, argv[0]); + exit(1); + } + char *fname1 = argv[optind++]; + char *fname2 = argv[optind++]; + + FILE *f1 = fopen(fname1, "rb"); + if (f1 == NULL) { + fprintf(stderr, "Error opening file1 \"%s\": ", fname1); + perror(NULL); + exit(1); + } + + FILE *f2 = fopen(fname2, "rb"); + if (f2 == NULL) { + fprintf(stderr, "Error opening file2 \"%s\": ", fname2); + perror(NULL); + exit(1); + } + + float data1, data2; + int count = 0; + int errors = 0; + double rms_sum = 0; + + while (fread(&data1, sizeof(float), 1, f1)) { + if (!fread(&data2, sizeof(float), 1, f2)) { + fprintf(stderr, "Error: file2 is shorter!"); + exit(1); + } + float err = fabsf((data1 - data2) / data1); + if (err > tol) { + errors++; + printf("%d %g %g %g\n", count, data1, data2, err); + } + rms_sum += (err * err); + count++; + } + if (fread(&data2, sizeof(float), 1, f2)) { + fprintf(stderr, "Error: file1 is shorter\n"); + exit(1); + } + + if (errors) { + printf("Fail: %d errors\n", errors); + printf(" rms error = %g\n", ((double)rms_sum / count)); + exit(1); + } else + printf("Pass\n"); + exit(0); + +} // main /* vi:set ts=4 et sts=4: */ diff --git a/unittest/compare_ints.c b/unittest/compare_ints.c index ef68a06..85ef2f3 100644 --- a/unittest/compare_ints.c +++ b/unittest/compare_ints.c @@ -1,11 +1,11 @@ /* compare ints - a test utility */ +#include +#include +#include #include #include #include -#include -#include -#include /* Declarations */ @@ -13,147 +13,148 @@ /* Functions */ int get_data(FILE *f, int64_t *dd, int signed_flag, int bytes) { - int res; - int8_t d_8; - int16_t d_16; - uint8_t d_u8; - uint16_t d_u16; - // TODO Loop on reads until, but catch EOF!! - if (signed_flag) { - switch (bytes) { - case 1: - res = fread(&d_8, bytes, 1, f); - *dd = d_8; - break; - case 2: - res = fread(&d_16, bytes, 1, f); - *dd = d_16; - break; - default: - fprintf(stderr, "Error: unsupported size %d bytes\n", bytes); - exit(1); - } - } - else { // unsigned - switch (bytes) { - case 1: - res = fread(&d_u8, bytes, 1, f); - *dd = d_u8; - break; - case 2: - res = fread(&d_u16, bytes, 1, f); - *dd = d_u16; - break; - default: - fprintf(stderr, "Error: unsupported size %d bytes\n", bytes); - exit(1); - } - } - - if (res != 1) return(0); - else return(1); + int res; + int8_t d_8; + int16_t d_16; + uint8_t d_u8; + uint16_t d_u16; + // TODO Loop on reads until, but catch EOF!! + if (signed_flag) { + switch (bytes) { + case 1: + res = fread(&d_8, bytes, 1, f); + *dd = d_8; + break; + case 2: + res = fread(&d_16, bytes, 1, f); + *dd = d_16; + break; + default: + fprintf(stderr, "Error: unsupported size %d bytes\n", bytes); + exit(1); + } + } else { // unsigned + switch (bytes) { + case 1: + res = fread(&d_u8, bytes, 1, f); + *dd = d_u8; + break; + case 2: + res = fread(&d_u16, bytes, 1, f); + *dd = d_u16; + break; + default: + fprintf(stderr, "Error: unsupported size %d bytes\n", bytes); + exit(1); } + } + if (res != 1) + return (0); + else + return (1); +} /* Main */ int main(int argc, char *argv[]) { - - char usage[] = "Usage: %s [-b size_in_bytes] [-c] [-s] [-t tolerance] [-n numerrorstoexit] file1 file2\n"; - - int bytes = 1; - int count_errors = 0; - int signed_flag = 0; - int tol = 1; - int numerrorstoexit = -1; - - int opt; - while ((opt = getopt(argc, argv, "b:cst:n:")) != -1) { - switch (opt) { - case 'b': - bytes = atoi(optarg); - break; - case 'c': - count_errors = 1; - break; - case 's': - signed_flag = 1; - break; - case 'n': - numerrorstoexit = atoi(optarg); - break; - case 't': - tol = atof(optarg); - break; - default: - fprintf(stderr, usage, argv[0]); - exit(1); - } - } - - if ((optind + 2) > argc) { + char usage[] = + "Usage: %s [-b size_in_bytes] [-c] [-s] [-t tolerance] [-n " + "numerrorstoexit] file1 file2\n"; + + int bytes = 1; + int count_errors = 0; + int signed_flag = 0; + int tol = 1; + int numerrorstoexit = -1; + + int opt; + while ((opt = getopt(argc, argv, "b:cst:n:")) != -1) { + switch (opt) { + case 'b': + bytes = atoi(optarg); + break; + case 'c': + count_errors = 1; + break; + case 's': + signed_flag = 1; + break; + case 'n': + numerrorstoexit = atoi(optarg); + break; + case 't': + tol = atof(optarg); + break; + default: fprintf(stderr, usage, argv[0]); exit(1); - } - char *fname1 = argv[optind++]; - char *fname2 = argv[optind++]; - - FILE *f1 = fopen(fname1, "rb"); - if (f1 == NULL) { - fprintf(stderr, "Error opening file1 \"%s\": ", fname1); - perror(NULL); - exit(1); - } - - FILE *f2 = fopen(fname2, "rb"); - if (f2 == NULL) { - fprintf(stderr, "Error opening file2 \"%s\": ", fname2); - perror(NULL); - exit(1); - } - - // Convert inputs to SIGNED long values - int64_t data1, data2; - - int count = 0; - int errors = 0; - int rms_sum = 0; - - while (get_data(f1, &data1, signed_flag, bytes)) { - if (!get_data(f2, &data2, signed_flag, bytes)) { - fprintf(stderr, "Error: file2 is shorter\n"); - exit(1); - } - uint64_t err = llabs(data1 - data2); - if (err > tol) { - errors ++; - printf("%d %" PRId64 " %" PRId64 "\n", count, data1, data2); - if (numerrorstoexit != -1) - if (errors > numerrorstoexit) { - printf("reached errors: %d, bailing!", numerrorstoexit); - exit(1); - } - } - rms_sum += (err * err); - count ++; } - if (get_data(f2, &data2, signed_flag, bytes)) { - fprintf(stderr, "Error: file1 is shorter\n"); - exit(1); + } + + if ((optind + 2) > argc) { + fprintf(stderr, usage, argv[0]); + exit(1); + } + char *fname1 = argv[optind++]; + char *fname2 = argv[optind++]; + + FILE *f1 = fopen(fname1, "rb"); + if (f1 == NULL) { + fprintf(stderr, "Error opening file1 \"%s\": ", fname1); + perror(NULL); + exit(1); + } + + FILE *f2 = fopen(fname2, "rb"); + if (f2 == NULL) { + fprintf(stderr, "Error opening file2 \"%s\": ", fname2); + perror(NULL); + exit(1); + } + + // Convert inputs to SIGNED long values + int64_t data1, data2; + + int count = 0; + int errors = 0; + int rms_sum = 0; + + while (get_data(f1, &data1, signed_flag, bytes)) { + if (!get_data(f2, &data2, signed_flag, bytes)) { + fprintf(stderr, "Error: file2 is shorter\n"); + exit(1); } - - if (count_errors) exit(errors); - else { - if (errors) { - printf("Fail: %d errors\n", errors); - printf(" rms error = %f\n", ((double)rms_sum/count)); - exit(1); - } - else printf("Pass\n"); - exit(0); + uint64_t err = llabs(data1 - data2); + if (err > tol) { + errors++; + printf("%d %" PRId64 " %" PRId64 "\n", count, data1, data2); + if (numerrorstoexit != -1) + if (errors > numerrorstoexit) { + printf("reached errors: %d, bailing!", numerrorstoexit); + exit(1); } - - } // main - + } + rms_sum += (err * err); + count++; + } + if (get_data(f2, &data2, signed_flag, bytes)) { + fprintf(stderr, "Error: file1 is shorter\n"); + exit(1); + } + + if (count_errors) + exit(errors); + else { + if (errors) { + printf("Fail: %d errors\n", errors); + printf(" rms error = %f\n", ((double)rms_sum / count)); + exit(1); + } else + printf("Pass\n"); + exit(0); + } + +} // main /* vi:set ts=4 et sts=4: */ diff --git a/unittest/freedv_700d_comprx.c b/unittest/freedv_700d_comprx.c index 9fdf43b..0cf8407 100644 --- a/unittest/freedv_700d_comprx.c +++ b/unittest/freedv_700d_comprx.c @@ -6,121 +6,135 @@ Complex valued rx to support ctests. Includes a few operations that will only work if complex Tx and Rx signals are being handled correctly. - + \*---------------------------------------------------------------------------*/ #include -#include #include +#include +#include "codec2_cohpsk.h" +#include "comp_prim.h" #include "freedv_api.h" #include "freedv_api_internal.h" #include "ofdm_internal.h" -#include "codec2_cohpsk.h" -#include "comp_prim.h" int main(int argc, char *argv[]) { - - /* with no arguments then run with no test code */ - int test_num = 0; - if (argc == 2) { - if (strcmp(argv[1],"tx") == 0) { - test_num = 1; - } - if (strcmp(argv[1],"rx") == 0) { - test_num = 2; - } + /* with no arguments then run with no test code */ + int test_num = 0; + if (argc == 2) { + if (strcmp(argv[1], "tx") == 0) { + test_num = 1; + } + if (strcmp(argv[1], "rx") == 0) { + test_num = 2; } - fprintf(stderr,"%d\n", test_num); - - struct freedv *freedv; - freedv = freedv_open(FREEDV_MODE_700D); - assert(freedv != NULL); - - /* note API functions to tell us how big our buffers need to be */ - short speech_out[freedv_get_n_max_speech_samples(freedv)]; - short demod_in[2*freedv_get_n_max_modem_samples(freedv)]; - COMP demod_in_comp[2*freedv_get_n_max_modem_samples(freedv)]; - - /* set up small freq offset */ - float foff_hz = 25; - COMP phase_ch; phase_ch.real = 1.0; phase_ch.imag = 0.0; - - /* set complex sine wave interferer at -fc */ - COMP interferer_phase = {1.0,0.0}; - COMP interferer_freq; - interferer_freq.real = cos(2.0*M_PI*freedv->ofdm->tx_centre/FREEDV_FS_8000); - interferer_freq.imag = sin(2.0*M_PI*freedv->ofdm->tx_centre/FREEDV_FS_8000); - interferer_freq = cconj(interferer_freq); - - /* log a file of demod input samples for plotting in Octave */ - FILE *fdemod = fopen("demod.f32","wb"); assert(fdemod != NULL); - - /* measure demod input power, interferer input power */ - float power_d = 0.0; float power_interferer = 0.0; - - int frames = 0, sum_sync = 0, frames_snr = 0; float sum_snr = 0.0; - size_t nin, nout; - nin = freedv_nin(freedv); - - while(fread(demod_in, sizeof(short), 2*nin, stdin) == 2*nin) { - for(int i=0; iofdm->tx_centre / FREEDV_FS_8000); + interferer_freq.imag = + sin(2.0 * M_PI * freedv->ofdm->tx_centre / FREEDV_FS_8000); + interferer_freq = cconj(interferer_freq); + + /* log a file of demod input samples for plotting in Octave */ + FILE *fdemod = fopen("demod.f32", "wb"); + assert(fdemod != NULL); + + /* measure demod input power, interferer input power */ + float power_d = 0.0; + float power_interferer = 0.0; + + int frames = 0, sum_sync = 0, frames_snr = 0; + float sum_snr = 0.0; + size_t nin, nout; + nin = freedv_nin(freedv); + + while (fread(demod_in, sizeof(short), 2 * nin, stdin) == 2 * nin) { + for (int i = 0; i < nin; i++) { + demod_in_comp[i].real = (float)demod_in[2 * i]; + demod_in_comp[i].imag = (float)demod_in[2 * i + 1]; + // demod_in_comp[i].imag = 0; } - fclose(fdemod); - freedv_close(freedv); + if (test_num == 1) { + /* So Tx is a complex OFDM signal centered at +fc. A small + shift fd followed by Re{} will only work if Tx is complex. + If Tx is real, neg freq components at -fc+fd will be + aliased on top of fc+fd wanted signal by Re{} operation. + This can be tested by setting demod_in_comp[i].imag = 0 + above */ + fdmdv_freq_shift_coh(demod_in_comp, demod_in_comp, foff_hz, + FREEDV_FS_8000, &phase_ch, nin); + for (int i = 0; i < nin; i++) demod_in_comp[i].imag = 0.0; + } - if (test_num == 2) - fprintf(stderr, "Demod/Interferer power ratio: %3.2f dB\n", 10*log10(power_d/power_interferer)); - float snr_av = sum_snr/frames_snr; - fprintf(stderr, "frames: %d sum_sync: %d snr_av: %3.2f dB\n", frames, sum_sync, snr_av); + if (test_num == 2) { + /* a complex sinewave (carrier) at -fc will only be ignored if + Rx is treating signal as complex, otherwise if real a +fc + alias will appear in the middle of our wanted signal at + +fc, this can be tested by setting demod_in_comp[i].imag = + 0 below */ + for (int i = 0; i < nin; i++) { + COMP a = fcmult(2E4, interferer_phase); + interferer_phase = cmult(interferer_phase, interferer_freq); + power_interferer += a.real * a.real + a.imag * a.imag; + COMP d = demod_in_comp[i]; + power_d += d.real * d.real + d.imag * d.imag; + demod_in_comp[i] = cadd(d, a); + // demod_in_comp[i].imag = 0; + } + } - if (snr_av > 8.0) - return 0; - else - return 1; + /* useful to take a look at this with Octave */ + fwrite(demod_in_comp, sizeof(COMP), nin, fdemod); + + nout = freedv_comprx(freedv, speech_out, demod_in_comp); + nin = freedv_nin(freedv); /* call me on every loop! */ + fwrite(speech_out, sizeof(short), nout, stdout); + int sync; + float snr_est; + freedv_get_modem_stats(freedv, &sync, &snr_est); + fprintf(stderr, "sync: %d snr_est: %f\n", sync, snr_est); + frames++; + sum_sync += sync; + if (sync) { + sum_snr += snr_est; + frames_snr++; + } + } + + fclose(fdemod); + freedv_close(freedv); + + if (test_num == 2) + fprintf(stderr, "Demod/Interferer power ratio: %3.2f dB\n", + 10 * log10(power_d / power_interferer)); + float snr_av = sum_snr / frames_snr; + fprintf(stderr, "frames: %d sum_sync: %d snr_av: %3.2f dB\n", frames, + sum_sync, snr_av); + + if (snr_av > 8.0) + return 0; + else + return 1; } diff --git a/unittest/freedv_700d_comptx.c b/unittest/freedv_700d_comptx.c index 0e5350e..9f66c76 100644 --- a/unittest/freedv_700d_comptx.c +++ b/unittest/freedv_700d_comptx.c @@ -7,37 +7,38 @@ \*---------------------------------------------------------------------------*/ #include -#include #include +#include #include #include "freedv_api.h" int main(int argc, char *argv[]) { - struct freedv *freedv; - - freedv = freedv_open(FREEDV_MODE_700D); - assert(freedv != NULL); - - /* handy functions to set buffer sizes */ - int n_speech_samples = freedv_get_n_speech_samples(freedv); - short speech_in[n_speech_samples]; - int n_nom_modem_samples = freedv_get_n_nom_modem_samples(freedv); - COMP mod_out[n_nom_modem_samples]; - short mod_out_short[2*n_nom_modem_samples]; - - /* OK main loop --------------------------------------- */ - - while(fread(speech_in, sizeof(short), n_speech_samples, stdin) == n_speech_samples) { - freedv_comptx(freedv, mod_out, speech_in); - for(int i=0; i -#include +#include +#include #include +#include #include -#include -#include -#define TWO_PI 6.283185307 -#define FS 8000.0 +#define TWO_PI 6.283185307 +#define FS 8000.0 int main(int argc, char *argv[]) { - FILE *f; - int i,n; - float freq, length; - short *buf; - float amp = 1E4; - - if (argc < 4) { - printf("usage: %s outputFile frequencyHz lengthSecs [PeakAmp]\n", argv[0]); - exit(1); - } - - if (strcmp(argv[1], "-") == 0) { - f = stdout; - } else if ( (f = fopen(argv[1],"wb")) == NULL ) { - fprintf(stderr, "Error opening output file: %s: %s.\n", argv[3], strerror(errno)); - exit(1); - } - freq = atof(argv[2]); - length = atof(argv[3]); - if (argc == 5) amp = atof(argv[4]); - - n = length*FS; - buf = (short*)malloc(sizeof(short)*n); - assert(buf != NULL); - - for(i=0; i 8 kHz sample rate conversion functions. I - + Evaluated output by plotting using Octave and looking for jaggies: pl("../unittest/out16.raw",1,3000) @@ -19,87 +19,81 @@ #include #include -#include #include +#include + #include "codec2_fdmdv.h" -#define N8 159 /* processing buffer size at 8 kHz (odd number deliberate) */ -#define N16 (N8*FDMDV_OS) -#define FRAMES 50 -#define TWO_PI 6.283185307 -#define FS 16000 +#define N8 159 /* processing buffer size at 8 kHz (odd number deliberate) */ +#define N16 (N8 * FDMDV_OS) +#define FRAMES 50 +#define TWO_PI 6.283185307 +#define FS 16000 #define SINE int main() { - float in8k[FDMDV_OS_TAPS_8K + N8]; - short in8k_short[N8]; - float out16k[N16]; - short out16k_short[N16]; - FILE *f16; - - float in16k[FDMDV_OS_TAPS_16K + N16]; - float out8k[N16]; - short out8k_short[N8]; - FILE *f8, *f8in; - - int i,f,t,t1; - float freq = 800.0; - - f16 = fopen("out16.raw", "wb"); - assert(f16 != NULL); - f8 = fopen("out8.raw", "wb"); - assert(f8 != NULL); - f8in = fopen("in8.raw", "wb"); - assert(f8in != NULL); - - /* clear filter memories */ - for(i=0; i #include -#include #include +#include + #include "codec2_fdmdv.h" -#define N8 159 /* procssing buffer size at 8 kHz */ -#define N16 (N8*FDMDV_OS) -#define FRAMES 100 -#define TWO_PI 6.283185307 -#define FS 16000 +#define N8 159 /* procssing buffer size at 8 kHz */ +#define N16 (N8 * FDMDV_OS) +#define FRAMES 100 +#define TWO_PI 6.283185307 +#define FS 16000 #define SINE int main() { - short in8k_short[FDMDV_OS_TAPS_8K + N8]; - short out16k_short[N16]; - FILE *f16; - - short in16k_short[FDMDV_OS_TAPS_16K + N16]; - short out8k_short[N16]; - FILE *f8, *f8in; - - int i,f,t,t1; - float freq = 800.0; - - f16 = fopen("out16_short.raw", "wb"); - assert(f16 != NULL); - f8 = fopen("out8_short.raw", "wb"); - assert(f8 != NULL); - f8in = fopen("in8_short.raw", "wb"); - assert(f8in != NULL); - - /* clear filter memories */ - for(i=0; i #include -#include #include +#include + #include "codec2_fdmdv.h" -#define N8 180 /* processing buffer size at 8 kHz */ -#define N48 (N8*FDMDV_OS_48) -#define MEM8 FDMDV_OS_TAPS_48_8K -#define FRAMES 50 -#define TWO_PI 6.283185307 -#define FS 48000 +#define N8 180 /* processing buffer size at 8 kHz */ +#define N48 (N8 * FDMDV_OS_48) +#define MEM8 FDMDV_OS_TAPS_48_8K +#define FRAMES 50 +#define TWO_PI 6.283185307 +#define FS 48000 #define SINE int main() { - float in8k[MEM8 + N8]; - short in8k_short[N8]; - float out48k[N48]; - short out48k_short[N48]; - FILE *f48; - - float in48k[FDMDV_OS_TAPS_48K + N48]; - float out8k[N48]; - short out8k_short[N8]; - FILE *f8, *f8in; - - int i,f,t,t1; - float freq = 800.0; - - f48 = fopen("out48.raw", "wb"); - assert(f48 != NULL); - f8 = fopen("out8.raw", "wb"); - assert(f8 != NULL); - f8in = fopen("in8.raw", "wb"); - assert(f8in != NULL); - - /* clear filter memories */ - - for(i=0; i #include -#include #include +#include + #include "codec2_fdmdv.h" -#define N8 180 /* processing buffer size at 8 kHz */ -#define N48 (N8*FDMDV_OS_48) -#define MEM8 FDMDV_OS_TAPS_48_8K -#define FRAMES 50 -#define TWO_PI 6.283185307 -#define FS 48000 +#define N8 180 /* processing buffer size at 8 kHz */ +#define N48 (N8 * FDMDV_OS_48) +#define MEM8 FDMDV_OS_TAPS_48_8K +#define FRAMES 50 +#define TWO_PI 6.283185307 +#define FS 48000 #define SINE int main() { - short in8k[MEM8+N8]; - short out48k[N48]; - FILE *f48; + short in8k[MEM8 + N8]; + short out48k[N48]; + FILE *f48; - short in48k[FDMDV_OS_TAPS_48K + N48]; - short out8k[N48]; - FILE *f8, *f8in; + short in48k[FDMDV_OS_TAPS_48K + N48]; + short out8k[N48]; + FILE *f8, *f8in; - int i,f,t,t1; - float freq = 800.0; + int i, f, t, t1; + float freq = 800.0; - f48 = fopen("out48.raw", "wb"); - assert(f48 != NULL); - f8 = fopen("out8.raw", "wb"); - assert(f8 != NULL); - f8in = fopen("in8.raw", "wb"); - assert(f8in != NULL); + f48 = fopen("out48.raw", "wb"); + assert(f48 != NULL); + f8 = fopen("out8.raw", "wb"); + assert(f8 != NULL); + f8in = fopen("in8.raw", "wb"); + assert(f8in != NULL); - /* clear filter memories */ + /* clear filter memories */ - for(i=0; i +#include #include #include #include -#include -#include "fdmdv_internal.h" -#include "codec2_fdmdv.h" #include "codec2_cohpsk.h" +#include "codec2_fdmdv.h" #include "cohpsk_defs.h" #include "cohpsk_internal.h" -#include "octave.h" #include "comp_prim.h" +#include "fdmdv_internal.h" #include "noise_samples.h" +#include "octave.h" -#define FRAMES 30 /* LOG_FRAMES is #defined in cohpsk_internal.h */ -#define SYNC_FRAMES 12 /* sync state uses up extra log storage as we reprocess several times */ -#define FRAMESL (SYNC_FRAMES*FRAMES) /* worst case is every frame is out of sync */ +#define FRAMES \ + 30 /* LOG_FRAMES is #defined in cohpsk_internal.h */ +#define SYNC_FRAMES \ + 12 /* sync state uses up extra log storage as we reprocess several times */ +#define FRAMESL \ + (SYNC_FRAMES * FRAMES) /* worst case is every frame is out of sync */ -#define FOFF 58.7 -#define DFOFF (-0.5/(float)COHPSK_FS) -#define ESNODB 8 -#define PPM -1500 +#define FOFF 58.7 +#define DFOFF (-0.5 / (float)COHPSK_FS) +#define ESNODB 8 +#define PPM -1500 extern float pilots_coh[][PILOTS_NC]; -int main(int argc, char *argv[]) -{ - struct COHPSK *coh; - int tx_bits[COHPSK_BITS_PER_FRAME]; - COMP tx_symb[NSYMROWPILOT][COHPSK_NC*COHPSK_ND]; - COMP tx_fdm_frame[COHPSK_M*NSYMROWPILOT]; - COMP ch_fdm_frame[COHPSK_M*NSYMROWPILOT]; - //COMP rx_fdm_frame_bb[M*NSYMROWPILOT]; - //COMP ch_symb[NSYMROWPILOT][COHPSK_NC*COHPSK_ND]; - float rx_bits_sd[COHPSK_BITS_PER_FRAME]; - int rx_bits[COHPSK_BITS_PER_FRAME]; - - int tx_bits_log[COHPSK_BITS_PER_FRAME*FRAMES]; - COMP tx_symb_log[NSYMROWPILOT*FRAMES][COHPSK_NC*COHPSK_ND]; - COMP tx_fdm_frame_log[COHPSK_M*NSYMROWPILOT*FRAMES]; - COMP ch_fdm_frame_log[COHPSK_M*NSYMROWPILOT*FRAMES]; - COMP ch_fdm_frame_log_out[(COHPSK_M*NSYMROWPILOT+1)*FRAMES]; - //COMP rx_fdm_frame_bb_log[M*NSYMROWPILOT*FRAMES]; - //COMP ch_symb_log[NSYMROWPILOT*FRAMES][COHPSK_NC*COHPSK_ND]; - COMP ct_symb_ff_log[NSYMROWPILOT*FRAMES][COHPSK_NC*COHPSK_ND]; - float rx_amp_log[NSYMROW*FRAMES][COHPSK_NC*COHPSK_ND]; - float rx_phi_log[NSYMROW*FRAMES][COHPSK_NC*COHPSK_ND]; - COMP rx_symb_log[NSYMROW*FRAMES][COHPSK_NC*COHPSK_ND]; - int rx_bits_log[COHPSK_BITS_PER_FRAME*FRAMES]; - - FILE *fout; - int f, r, c, log_r, log_data_r, noise_r, ff_log_r, i; - double foff; - COMP foff_rect, phase_ch; - - struct FDMDV *fdmdv; - //COMP rx_filt[COHPSK_NC*COHPSK_ND][P+1]; - //int rx_filt_log_col_index = 0; - //float env[NT*P]; - //float __attribute__((unused)) rx_timing; - COMP tx_onesym[COHPSK_NC*COHPSK_ND]; - //COMP rx_onesym[COHPSK_NC*COHPSK_ND]; - //int rx_baseband_log_col_index = 0; - //COMP rx_baseband_log[COHPSK_NC*COHPSK_ND][(M+M/P)*NSYMROWPILOT*FRAMES]; - float f_est_log[FRAMES], sig_rms_log[FRAMES], noise_rms_log[FRAMES]; - int f_est_samples; - - int log_bits; - float EsNo, variance; - COMP scaled_noise; - int reliable_sync_bit; - int ch_fdm_frame_log_index, nin_frame, tmp, nout; - - coh = cohpsk_create(); - fdmdv = coh->fdmdv; - assert(coh != NULL); - cohpsk_set_verbose(coh, 1); - - /* these puppies are used for logging data in the bowels on the modem */ - - coh->rx_baseband_log_col_sz = (COHPSK_M+COHPSK_M/P)*NSYMROWPILOT*FRAMESL; - coh->rx_baseband_log = (COMP *)malloc(sizeof(COMP)*COHPSK_NC*COHPSK_ND*coh->rx_baseband_log_col_sz); - - coh->rx_filt_log_col_sz = (P+1)*NSYMROWPILOT*FRAMESL; - coh->rx_filt_log = (COMP *)malloc(sizeof(COMP)*COHPSK_NC*COHPSK_ND*coh->rx_filt_log_col_sz); - - coh->ch_symb_log_col_sz = COHPSK_NC*COHPSK_ND; - coh->ch_symb_log = (COMP *)malloc(sizeof(COMP)*NSYMROWPILOT*FRAMESL*coh->ch_symb_log_col_sz); - - coh->rx_timing_log = (float*)malloc(sizeof(float)*NSYMROWPILOT*FRAMESL); - - /* init stuff */ - - log_r = log_data_r = noise_r = log_bits = ff_log_r = f_est_samples = 0; - phase_ch.real = 1.0; phase_ch.imag = 0.0; - foff = FOFF; - - /* each carrier has power = 2, total power 2Nc, total symbol rate - NcRs, noise BW B=Fs Es/No = (C/Rs)/(N/B), N = var = - 2NcFs/NcRs(Es/No) = 2Fs/Rs(Es/No) */ - - EsNo = pow(10.0, ESNODB/10.0); - variance = 2.0*COHPSK_FS/(COHPSK_RS*EsNo); - //fprintf(stderr, "doff: %e\n", DFOFF); - - /* Main Loop ---------------------------------------------------------------------*/ - - for(f=0; ftx_filter_memory, - fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect); - } - cohpsk_clip(tx_fdm_frame, COHPSK_CLIP, NSYMROWPILOT*COHPSK_M); +int main(int argc, char *argv[]) { + struct COHPSK *coh; + int tx_bits[COHPSK_BITS_PER_FRAME]; + COMP tx_symb[NSYMROWPILOT][COHPSK_NC * COHPSK_ND]; + COMP tx_fdm_frame[COHPSK_M * NSYMROWPILOT]; + COMP ch_fdm_frame[COHPSK_M * NSYMROWPILOT]; + // COMP rx_fdm_frame_bb[M*NSYMROWPILOT]; + // COMP ch_symb[NSYMROWPILOT][COHPSK_NC*COHPSK_ND]; + float rx_bits_sd[COHPSK_BITS_PER_FRAME]; + int rx_bits[COHPSK_BITS_PER_FRAME]; + + int tx_bits_log[COHPSK_BITS_PER_FRAME * FRAMES]; + COMP tx_symb_log[NSYMROWPILOT * FRAMES][COHPSK_NC * COHPSK_ND]; + COMP tx_fdm_frame_log[COHPSK_M * NSYMROWPILOT * FRAMES]; + COMP ch_fdm_frame_log[COHPSK_M * NSYMROWPILOT * FRAMES]; + COMP ch_fdm_frame_log_out[(COHPSK_M * NSYMROWPILOT + 1) * FRAMES]; + // COMP rx_fdm_frame_bb_log[M*NSYMROWPILOT*FRAMES]; + // COMP ch_symb_log[NSYMROWPILOT*FRAMES][COHPSK_NC*COHPSK_ND]; + COMP ct_symb_ff_log[NSYMROWPILOT * FRAMES][COHPSK_NC * COHPSK_ND]; + float rx_amp_log[NSYMROW * FRAMES][COHPSK_NC * COHPSK_ND]; + float rx_phi_log[NSYMROW * FRAMES][COHPSK_NC * COHPSK_ND]; + COMP rx_symb_log[NSYMROW * FRAMES][COHPSK_NC * COHPSK_ND]; + int rx_bits_log[COHPSK_BITS_PER_FRAME * FRAMES]; + + FILE *fout; + int f, r, c, log_r, log_data_r, noise_r, ff_log_r, i; + double foff; + COMP foff_rect, phase_ch; + + struct FDMDV *fdmdv; + // COMP rx_filt[COHPSK_NC*COHPSK_ND][P+1]; + // int rx_filt_log_col_index = 0; + // float env[NT*P]; + // float __attribute__((unused)) rx_timing; + COMP tx_onesym[COHPSK_NC * COHPSK_ND]; + // COMP rx_onesym[COHPSK_NC*COHPSK_ND]; + // int rx_baseband_log_col_index = 0; + // COMP rx_baseband_log[COHPSK_NC*COHPSK_ND][(M+M/P)*NSYMROWPILOT*FRAMES]; + float f_est_log[FRAMES], sig_rms_log[FRAMES], noise_rms_log[FRAMES]; + int f_est_samples; + + int log_bits; + float EsNo, variance; + COMP scaled_noise; + int reliable_sync_bit; + int ch_fdm_frame_log_index, nin_frame, tmp, nout; + + coh = cohpsk_create(); + fdmdv = coh->fdmdv; + assert(coh != NULL); + cohpsk_set_verbose(coh, 1); + + /* these puppies are used for logging data in the bowels on the modem */ + + coh->rx_baseband_log_col_sz = + (COHPSK_M + COHPSK_M / P) * NSYMROWPILOT * FRAMESL; + coh->rx_baseband_log = (COMP *)malloc(sizeof(COMP) * COHPSK_NC * COHPSK_ND * + coh->rx_baseband_log_col_sz); + + coh->rx_filt_log_col_sz = (P + 1) * NSYMROWPILOT * FRAMESL; + coh->rx_filt_log = (COMP *)malloc(sizeof(COMP) * COHPSK_NC * COHPSK_ND * + coh->rx_filt_log_col_sz); + + coh->ch_symb_log_col_sz = COHPSK_NC * COHPSK_ND; + coh->ch_symb_log = (COMP *)malloc(sizeof(COMP) * NSYMROWPILOT * FRAMESL * + coh->ch_symb_log_col_sz); + + coh->rx_timing_log = (float *)malloc(sizeof(float) * NSYMROWPILOT * FRAMESL); + + /* init stuff */ + + log_r = log_data_r = noise_r = log_bits = ff_log_r = f_est_samples = 0; + phase_ch.real = 1.0; + phase_ch.imag = 0.0; + foff = FOFF; + + /* each carrier has power = 2, total power 2Nc, total symbol rate + NcRs, noise BW B=Fs Es/No = (C/Rs)/(N/B), N = var = + 2NcFs/NcRs(Es/No) = 2Fs/Rs(Es/No) */ + + EsNo = pow(10.0, ESNODB / 10.0); + variance = 2.0 * COHPSK_FS / (COHPSK_RS * EsNo); + // fprintf(stderr, "doff: %e\n", DFOFF); + + /* Main Loop + * ---------------------------------------------------------------------*/ + + for (f = 0; f < FRAMES; f++) { + /* --------------------------------------------------------*\ + Mod + \*---------------------------------------------------------*/ - /* --------------------------------------------------------*\ - Channel - \*---------------------------------------------------------*/ + cohpsk_get_test_bits(coh, tx_bits); + bits_to_qpsk_symbols(tx_symb, (int *)tx_bits, COHPSK_BITS_PER_FRAME); - for(r=0; rtx_filter_memory, fdmdv->phase_tx, fdmdv->freq, + &fdmdv->fbb_phase_tx, fdmdv->fbb_rect); + } + cohpsk_clip(tx_fdm_frame, COHPSK_CLIP, NSYMROWPILOT * COHPSK_M); - /* optional gain to test level sensitivity */ + /* --------------------------------------------------------*\ + Channel + \*---------------------------------------------------------*/ - for(r=0; rframe = f; + + // printf("nin_frame: %d\n", nin_frame); + + assert(ch_fdm_frame_log_index < COHPSK_M * NSYMROWPILOT * FRAMES); + tmp = nin_frame; + cohpsk_demod(coh, rx_bits_sd, &reliable_sync_bit, + &ch_fdm_frame_log_out[ch_fdm_frame_log_index], &nin_frame); + for (i = 0; i < COHPSK_BITS_PER_FRAME; i++) + rx_bits[i] = rx_bits_sd[i] < 0.0; + + ch_fdm_frame_log_index += tmp; /* --------------------------------------------------------*\ - Demod + Log each vector \*---------------------------------------------------------*/ - for(f=0; fframe = f; - - //printf("nin_frame: %d\n", nin_frame); - - assert(ch_fdm_frame_log_index < COHPSK_M*NSYMROWPILOT*FRAMES); - tmp = nin_frame; - cohpsk_demod(coh, rx_bits_sd, &reliable_sync_bit, &ch_fdm_frame_log_out[ch_fdm_frame_log_index], &nin_frame); - for(i=0; isync == 1) { - - for(r=0; rct_symb_ff_buf[r][c]; - } - } - - for(r=0; ramp_[r][c]; - rx_phi_log[log_data_r][c] = coh->phi_[r][c]; - rx_symb_log[log_data_r][c] = coh->rx_symb[r][c]; - } - } - memcpy(&rx_bits_log[COHPSK_BITS_PER_FRAME*log_bits], rx_bits, sizeof(int)*COHPSK_BITS_PER_FRAME); - log_bits++; - f_est_log[f_est_samples] = coh->f_est; - sig_rms_log[f_est_samples] = coh->sig_rms; - noise_rms_log[f_est_samples] = coh->noise_rms; - f_est_samples++;; + if (coh->sync == 1) { + for (r = 0; r < NSYMROWPILOT; r++, ff_log_r++) { + for (c = 0; c < COHPSK_NC * COHPSK_ND; c++) { + ct_symb_ff_log[ff_log_r][c] = coh->ct_symb_ff_buf[r][c]; } + } - assert(log_r <= NSYMROWPILOT*FRAMES); - assert(noise_r <= NSYMROWPILOT*COHPSK_M*FRAMES); - assert(log_data_r <= NSYMROW*FRAMES); - - printf("\r [%d]", f+1); + for (r = 0; r < NSYMROW; r++, log_data_r++) { + for (c = 0; c < COHPSK_NC * COHPSK_ND; c++) { + rx_amp_log[log_data_r][c] = coh->amp_[r][c]; + rx_phi_log[log_data_r][c] = coh->phi_[r][c]; + rx_symb_log[log_data_r][c] = coh->rx_symb[r][c]; + } + } + memcpy(&rx_bits_log[COHPSK_BITS_PER_FRAME * log_bits], rx_bits, + sizeof(int) * COHPSK_BITS_PER_FRAME); + log_bits++; + f_est_log[f_est_samples] = coh->f_est; + sig_rms_log[f_est_samples] = coh->sig_rms; + noise_rms_log[f_est_samples] = coh->noise_rms; + f_est_samples++; + ; } - printf("\n"); - - /*---------------------------------------------------------*\ - Dump logs to Octave file for evaluation - by tcohpsk.m Octave script - \*---------------------------------------------------------*/ - fout = fopen("tcohpsk_out.txt","wt"); - assert(fout != NULL); - fprintf(fout, "# Created by tcohpsk.c\n"); - octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, COHPSK_BITS_PER_FRAME*FRAMES); - octave_save_complex(fout, "tx_symb_log_c", (COMP*)tx_symb_log, NSYMROWPILOT*FRAMES, COHPSK_NC*COHPSK_ND, COHPSK_NC*COHPSK_ND); - octave_save_complex(fout, "tx_fdm_frame_log_c", (COMP*)tx_fdm_frame_log, 1, COHPSK_M*NSYMROWPILOT*FRAMES, COHPSK_M*NSYMROWPILOT*FRAMES); - octave_save_complex(fout, "ch_fdm_frame_log_c", (COMP*)ch_fdm_frame_log_out, 1, nout-1, nout-1); - //octave_save_complex(fout, "rx_fdm_frame_bb_log_c", (COMP*)rx_fdm_frame_bb_log, 1, M*NSYMROWPILOT*FRAMES, M*NSYMROWPILOT*FRAMES); - octave_save_complex(fout, "rx_baseband_log_c", (COMP*)coh->rx_baseband_log, COHPSK_NC*COHPSK_ND, coh->rx_baseband_log_col_index, coh->rx_baseband_log_col_sz); - octave_save_complex(fout, "rx_filt_log_c", (COMP*)coh->rx_filt_log, COHPSK_NC*COHPSK_ND, coh->rx_filt_log_col_index, coh->rx_filt_log_col_sz); - octave_save_complex(fout, "ch_symb_log_c", (COMP*)coh->ch_symb_log, coh->ch_symb_log_r, COHPSK_NC*COHPSK_ND, COHPSK_NC*COHPSK_ND); - octave_save_float(fout, "rx_timing_log_c", (float*)coh->rx_timing_log, 1, coh->rx_timing_log_index, coh->rx_timing_log_index); - octave_save_complex(fout, "ct_symb_ff_log_c", (COMP*)ct_symb_ff_log, NSYMROWPILOT*FRAMES, COHPSK_NC*COHPSK_ND, COHPSK_NC*COHPSK_ND); - octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, log_data_r, COHPSK_NC*COHPSK_ND, COHPSK_NC*COHPSK_ND); - octave_save_float(fout, "rx_phi_log_c", (float*)rx_phi_log, log_data_r, COHPSK_NC*COHPSK_ND, COHPSK_NC*COHPSK_ND); - octave_save_complex(fout, "rx_symb_log_c", (COMP*)rx_symb_log, log_data_r, COHPSK_NC*COHPSK_ND, COHPSK_NC*COHPSK_ND); - octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, COHPSK_BITS_PER_FRAME*log_bits); - octave_save_float(fout, "f_est_log_c", &f_est_log[1], 1, f_est_samples-1, f_est_samples-1); - octave_save_float(fout, "sig_rms_log_c", sig_rms_log, 1, f_est_samples, f_est_samples-1); - octave_save_float(fout, "noise_rms_log_c", noise_rms_log, 1, f_est_samples, f_est_samples); + assert(log_r <= NSYMROWPILOT * FRAMES); + assert(noise_r <= NSYMROWPILOT * COHPSK_M * FRAMES); + assert(log_data_r <= NSYMROW * FRAMES); + + printf("\r [%d]", f + 1); + } + printf("\n"); + + /*---------------------------------------------------------*\ + Dump logs to Octave file for evaluation + by tcohpsk.m Octave script + \*---------------------------------------------------------*/ + + fout = fopen("tcohpsk_out.txt", "wt"); + assert(fout != NULL); + fprintf(fout, "# Created by tcohpsk.c\n"); + octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, + COHPSK_BITS_PER_FRAME * FRAMES); + octave_save_complex(fout, "tx_symb_log_c", (COMP *)tx_symb_log, + NSYMROWPILOT * FRAMES, COHPSK_NC * COHPSK_ND, + COHPSK_NC * COHPSK_ND); + octave_save_complex(fout, "tx_fdm_frame_log_c", (COMP *)tx_fdm_frame_log, 1, + COHPSK_M * NSYMROWPILOT * FRAMES, + COHPSK_M * NSYMROWPILOT * FRAMES); + octave_save_complex(fout, "ch_fdm_frame_log_c", (COMP *)ch_fdm_frame_log_out, + 1, nout - 1, nout - 1); + // octave_save_complex(fout, "rx_fdm_frame_bb_log_c", + // (COMP*)rx_fdm_frame_bb_log, 1, M*NSYMROWPILOT*FRAMES, + // M*NSYMROWPILOT*FRAMES); + octave_save_complex(fout, "rx_baseband_log_c", (COMP *)coh->rx_baseband_log, + COHPSK_NC * COHPSK_ND, coh->rx_baseband_log_col_index, + coh->rx_baseband_log_col_sz); + octave_save_complex(fout, "rx_filt_log_c", (COMP *)coh->rx_filt_log, + COHPSK_NC * COHPSK_ND, coh->rx_filt_log_col_index, + coh->rx_filt_log_col_sz); + octave_save_complex(fout, "ch_symb_log_c", (COMP *)coh->ch_symb_log, + coh->ch_symb_log_r, COHPSK_NC * COHPSK_ND, + COHPSK_NC * COHPSK_ND); + octave_save_float(fout, "rx_timing_log_c", (float *)coh->rx_timing_log, 1, + coh->rx_timing_log_index, coh->rx_timing_log_index); + octave_save_complex(fout, "ct_symb_ff_log_c", (COMP *)ct_symb_ff_log, + NSYMROWPILOT * FRAMES, COHPSK_NC * COHPSK_ND, + COHPSK_NC * COHPSK_ND); + octave_save_float(fout, "rx_amp_log_c", (float *)rx_amp_log, log_data_r, + COHPSK_NC * COHPSK_ND, COHPSK_NC * COHPSK_ND); + octave_save_float(fout, "rx_phi_log_c", (float *)rx_phi_log, log_data_r, + COHPSK_NC * COHPSK_ND, COHPSK_NC * COHPSK_ND); + octave_save_complex(fout, "rx_symb_log_c", (COMP *)rx_symb_log, log_data_r, + COHPSK_NC * COHPSK_ND, COHPSK_NC * COHPSK_ND); + octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, + COHPSK_BITS_PER_FRAME * log_bits); + octave_save_float(fout, "f_est_log_c", &f_est_log[1], 1, f_est_samples - 1, + f_est_samples - 1); + octave_save_float(fout, "sig_rms_log_c", sig_rms_log, 1, f_est_samples, + f_est_samples - 1); + octave_save_float(fout, "noise_rms_log_c", noise_rms_log, 1, f_est_samples, + f_est_samples); #ifdef XX #endif - fclose(fout); + fclose(fout); - cohpsk_destroy(coh); + cohpsk_destroy(coh); - return 0; + return 0; } - diff --git a/unittest/tesno_est.c b/unittest/tesno_est.c index e198510..8937b1b 100644 --- a/unittest/tesno_est.c +++ b/unittest/tesno_est.c @@ -5,27 +5,28 @@ DATE CREATED: Mar 2021 Test for C port of Es/No estimator. - + \*---------------------------------------------------------------------------*/ #include +#include #include #include -#include #include "ofdm_internal.h" -int main(int argc, char *argv[]) -{ - FILE *fin = fopen(argv[1],"rb"); assert(fin != NULL); - size_t nsym = atoi(argv[2]); assert(nsym >= 0); - complex float rx_sym[nsym]; - size_t nread = fread(rx_sym, sizeof(complex float), nsym, fin); - assert(nread == nsym); - fclose(fin); - - float EsNodB = ofdm_esno_est_calc(rx_sym, nsym); - printf("%f\n",EsNodB); - - return 0; +int main(int argc, char *argv[]) { + FILE *fin = fopen(argv[1], "rb"); + assert(fin != NULL); + size_t nsym = atoi(argv[2]); + assert(nsym >= 0); + complex float rx_sym[nsym]; + size_t nread = fread(rx_sym, sizeof(complex float), nsym, fin); + assert(nread == nsym); + fclose(fin); + + float EsNodB = ofdm_esno_est_calc(rx_sym, nsym); + printf("%f\n", EsNodB); + + return 0; } diff --git a/unittest/tfdmdv.c b/unittest/tfdmdv.c index 6806a5d..e7fbca8 100644 --- a/unittest/tfdmdv.c +++ b/unittest/tfdmdv.c @@ -29,258 +29,291 @@ */ #include +#include #include #include #include -#include -#include "fdmdv_internal.h" #include "codec2_fdmdv.h" +#include "fdmdv_internal.h" #include "octave.h" #define FRAMES 35 -#define CHANNEL_BUF_SIZE (10*M_FAC) +#define CHANNEL_BUF_SIZE (10 * M_FAC) extern float pilot_coeff[]; -int main(int argc, char *argv[]) -{ - struct FDMDV *fdmdv; - int tx_bits[FDMDV_BITS_PER_FRAME]; - COMP tx_symbols[FDMDV_NC+1]; - COMP tx_fdm[M_FAC]; - float channel[CHANNEL_BUF_SIZE]; - int channel_count; - COMP rx_fdm[M_FAC+M_FAC/P]; - float foff_coarse; - int nin, next_nin; - COMP rx_fdm_fcorr[M_FAC+M_FAC/P]; - COMP rx_fdm_filter[M_FAC+M_FAC/P]; - COMP rx_filt[NC+1][P+1]; - float rx_timing; - float env[NT*P]; - COMP rx_symbols[FDMDV_NC+1]; - int rx_bits[FDMDV_BITS_PER_FRAME]; - float foff_fine; - int sync_bit, reliable_sync_bit; - - int tx_bits_log[FDMDV_BITS_PER_FRAME*FRAMES]; - COMP tx_symbols_log[(FDMDV_NC+1)*FRAMES]; - COMP tx_fdm_log[M_FAC*FRAMES]; - COMP pilot_baseband1_log[NPILOTBASEBAND*FRAMES]; - COMP pilot_baseband2_log[NPILOTBASEBAND*FRAMES]; - COMP pilot_lpf1_log[NPILOTLPF*FRAMES]; - COMP pilot_lpf2_log[NPILOTLPF*FRAMES]; - COMP S1_log[MPILOTFFT*FRAMES]; - COMP S2_log[MPILOTFFT*FRAMES]; - float foff_coarse_log[FRAMES]; - float foff_log[FRAMES]; - COMP rx_fdm_filter_log[(M_FAC+M_FAC/P)*FRAMES]; - int rx_fdm_filter_log_index; - COMP rx_filt_log[NC+1][(P+1)*FRAMES]; - int rx_filt_log_col_index; - float env_log[NT*P*FRAMES]; - float rx_timing_log[FRAMES]; - COMP rx_symbols_log[FDMDV_NC+1][FRAMES]; - COMP phase_difference_log[FDMDV_NC+1][FRAMES]; - float sig_est_log[FDMDV_NC+1][FRAMES]; - float noise_est_log[FDMDV_NC+1][FRAMES]; - int rx_bits_log[FDMDV_BITS_PER_FRAME*FRAMES]; - float foff_fine_log[FRAMES]; - int sync_bit_log[FRAMES]; - int sync_log[FRAMES]; - int nin_log[FRAMES]; - - FILE *fout; - int f,c,i,j; - - fdmdv = fdmdv_create(FDMDV_NC); - next_nin = M_FAC; - channel_count = 0; - - rx_fdm_filter_log_index = 0; - rx_filt_log_col_index = 0; - - printf("sizeof FDMDV states: %zd bytes\n", sizeof(struct FDMDV)); - - for(f=0; fprev_tx_symbols, tx_bits, &fdmdv->tx_pilot_bit, 0); - memcpy(fdmdv->prev_tx_symbols, tx_symbols, sizeof(COMP)*(FDMDV_NC+1)); - tx_filter_and_upconvert(tx_fdm, FDMDV_NC , tx_symbols, fdmdv->tx_filter_memory, - fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect); - - /* --------------------------------------------------------*\ - Channel - \*---------------------------------------------------------*/ - - nin = next_nin; - - // nin = M_FAC; // when debugging good idea to uncomment this to "open loop" - - /* add M_FAC tx samples to end of buffer */ - - assert((channel_count + M_FAC) < CHANNEL_BUF_SIZE); - for(i=0; iprev_tx_symbols, tx_bits, + &fdmdv->tx_pilot_bit, 0); + memcpy(fdmdv->prev_tx_symbols, tx_symbols, sizeof(COMP) * (FDMDV_NC + 1)); + tx_filter_and_upconvert(tx_fdm, FDMDV_NC, tx_symbols, + fdmdv->tx_filter_memory, fdmdv->phase_tx, + fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect); - for(i=0; ifbb_phase_rx, nin); + /* take nin samples from start of buffer */ - /* freq offset estimation and correction */ + for (i = 0; i < nin; i++) { + rx_fdm[i].real = channel[i]; + rx_fdm[i].imag = 0; + } - // fdmdv->sync = 0; // when debugging good idea to uncomment this to "open loop" + /* shift buffer back */ - foff_coarse = rx_est_freq_offset(fdmdv, rx_fdm, nin, !fdmdv->sync); + for (i = 0, j = nin; j < channel_count; i++, j++) channel[i] = channel[j]; + channel_count -= nin; - if (fdmdv->sync == 0) - fdmdv->foff = foff_coarse; - fdmdv_freq_shift(rx_fdm_fcorr, rx_fdm, -fdmdv->foff, &fdmdv->foff_phase_rect, nin); + /* --------------------------------------------------------*\ + Demodulator + \*---------------------------------------------------------*/ - /* baseband processing */ + /* shift down to complex baseband */ - rxdec_filter(rx_fdm_filter, rx_fdm_fcorr, fdmdv->rxdec_lpf_mem, nin); - down_convert_and_rx_filter(rx_filt, fdmdv->Nc, rx_fdm_filter, fdmdv->rx_fdm_mem, fdmdv->phase_rx, fdmdv->freq, - fdmdv->freq_pol, nin, M_FAC/Q); - rx_timing = rx_est_timing(rx_symbols, FDMDV_NC, rx_filt, fdmdv->rx_filter_mem_timing, env, nin, M_FAC); - foff_fine = qpsk_to_bits(rx_bits, &sync_bit, FDMDV_NC, fdmdv->phase_difference, fdmdv->prev_rx_symbols, rx_symbols, 0); + fdmdv_freq_shift(rx_fdm, rx_fdm, -FDMDV_FCENTRE, &fdmdv->fbb_phase_rx, nin); - //for(i=0; iprev_rx_symbols[i].real, fdmdv->prev_rx_symbols[i].imag, fdmdv->phase_difference[i].real, fdmdv->phase_difference[i].imag); - //if (f==1) - // exit(0); + /* freq offset estimation and correction */ - snr_update(fdmdv->sig_est, fdmdv->noise_est, FDMDV_NC, fdmdv->phase_difference); - memcpy(fdmdv->prev_rx_symbols, rx_symbols, sizeof(COMP)*(FDMDV_NC+1)); + // fdmdv->sync = 0; // when debugging good idea to uncomment this to "open + // loop" - next_nin = M_FAC; + foff_coarse = rx_est_freq_offset(fdmdv, rx_fdm, nin, !fdmdv->sync); - if (rx_timing > 2*M_FAC/P) - next_nin += M_FAC/P; + if (fdmdv->sync == 0) fdmdv->foff = foff_coarse; + fdmdv_freq_shift(rx_fdm_fcorr, rx_fdm, -fdmdv->foff, + &fdmdv->foff_phase_rect, nin); - if (rx_timing < 0) - next_nin -= M_FAC/P; + /* baseband processing */ - fdmdv->sync = freq_state(&reliable_sync_bit, sync_bit, &fdmdv->fest_state, &fdmdv->timer, fdmdv->sync_mem); - fdmdv->foff -= TRACK_COEFF*foff_fine; + rxdec_filter(rx_fdm_filter, rx_fdm_fcorr, fdmdv->rxdec_lpf_mem, nin); + down_convert_and_rx_filter(rx_filt, fdmdv->Nc, rx_fdm_filter, + fdmdv->rx_fdm_mem, fdmdv->phase_rx, fdmdv->freq, + fdmdv->freq_pol, nin, M_FAC / Q); + rx_timing = rx_est_timing(rx_symbols, FDMDV_NC, rx_filt, + fdmdv->rx_filter_mem_timing, env, nin, M_FAC); + foff_fine = + qpsk_to_bits(rx_bits, &sync_bit, FDMDV_NC, fdmdv->phase_difference, + fdmdv->prev_rx_symbols, rx_symbols, 0); - /* --------------------------------------------------------*\ - Log each vector - \*---------------------------------------------------------*/ + // for(i=0; iprev_rx_symbols[i].real, fdmdv->prev_rx_symbols[i].imag, + // fdmdv->phase_difference[i].real, + // fdmdv->phase_difference[i].imag); + // if (f==1) + // exit(0); - memcpy(&tx_bits_log[FDMDV_BITS_PER_FRAME*f], tx_bits, sizeof(int)*FDMDV_BITS_PER_FRAME); - memcpy(&tx_symbols_log[(FDMDV_NC+1)*f], tx_symbols, sizeof(COMP)*(FDMDV_NC+1)); - memcpy(&tx_fdm_log[M_FAC*f], tx_fdm, sizeof(COMP)*M_FAC); + snr_update(fdmdv->sig_est, fdmdv->noise_est, FDMDV_NC, + fdmdv->phase_difference); + memcpy(fdmdv->prev_rx_symbols, rx_symbols, sizeof(COMP) * (FDMDV_NC + 1)); - memcpy(&pilot_baseband1_log[f*NPILOTBASEBAND], fdmdv->pilot_baseband1, sizeof(COMP)*NPILOTBASEBAND); - memcpy(&pilot_baseband2_log[f*NPILOTBASEBAND], fdmdv->pilot_baseband2, sizeof(COMP)*NPILOTBASEBAND); - memcpy(&pilot_lpf1_log[f*NPILOTLPF], fdmdv->pilot_lpf1, sizeof(COMP)*NPILOTLPF); - memcpy(&pilot_lpf2_log[f*NPILOTLPF], fdmdv->pilot_lpf2, sizeof(COMP)*NPILOTLPF); - memcpy(&S1_log[f*MPILOTFFT], fdmdv->S1, sizeof(COMP)*MPILOTFFT); - memcpy(&S2_log[f*MPILOTFFT], fdmdv->S2, sizeof(COMP)*MPILOTFFT); - foff_coarse_log[f] = foff_coarse; - foff_log[f] = fdmdv->foff; - - /* rx filtering */ + next_nin = M_FAC; - for(i=0; i 2 * M_FAC / P) next_nin += M_FAC / P; - for(c=0; csync = freq_state(&reliable_sync_bit, sync_bit, &fdmdv->fest_state, + &fdmdv->timer, fdmdv->sync_mem); + fdmdv->foff -= TRACK_COEFF * foff_fine; - memcpy(&env_log[NT*P*f], env, sizeof(float)*NT*P); - rx_timing_log[f] = rx_timing; - nin_log[f] = nin; + /* --------------------------------------------------------*\ + Log each vector + \*---------------------------------------------------------*/ - for(c=0; cphase_difference[c]; - } + memcpy(&tx_bits_log[FDMDV_BITS_PER_FRAME * f], tx_bits, + sizeof(int) * FDMDV_BITS_PER_FRAME); + memcpy(&tx_symbols_log[(FDMDV_NC + 1) * f], tx_symbols, + sizeof(COMP) * (FDMDV_NC + 1)); + memcpy(&tx_fdm_log[M_FAC * f], tx_fdm, sizeof(COMP) * M_FAC); + + memcpy(&pilot_baseband1_log[f * NPILOTBASEBAND], fdmdv->pilot_baseband1, + sizeof(COMP) * NPILOTBASEBAND); + memcpy(&pilot_baseband2_log[f * NPILOTBASEBAND], fdmdv->pilot_baseband2, + sizeof(COMP) * NPILOTBASEBAND); + memcpy(&pilot_lpf1_log[f * NPILOTLPF], fdmdv->pilot_lpf1, + sizeof(COMP) * NPILOTLPF); + memcpy(&pilot_lpf2_log[f * NPILOTLPF], fdmdv->pilot_lpf2, + sizeof(COMP) * NPILOTLPF); + memcpy(&S1_log[f * MPILOTFFT], fdmdv->S1, sizeof(COMP) * MPILOTFFT); + memcpy(&S2_log[f * MPILOTFFT], fdmdv->S2, sizeof(COMP) * MPILOTFFT); + foff_coarse_log[f] = foff_coarse; + foff_log[f] = fdmdv->foff; + + /* rx filtering */ + + for (i = 0; i < nin; i++) + rx_fdm_filter_log[rx_fdm_filter_log_index + i] = rx_fdm_filter[i]; + rx_fdm_filter_log_index += nin; + + for (c = 0; c < NC + 1; c++) { + for (i = 0; i < (P * nin) / M_FAC; i++) + rx_filt_log[c][rx_filt_log_col_index + i] = rx_filt[c][i]; + } + rx_filt_log_col_index += (P * nin) / M_FAC; - /* qpsk_to_bits() */ + /* timing estimation */ - memcpy(&rx_bits_log[FDMDV_BITS_PER_FRAME*f], rx_bits, sizeof(int)*FDMDV_BITS_PER_FRAME); - for(c=0; csig_est[c]; - noise_est_log[c][f] = fdmdv->noise_est[c]; - } - foff_fine_log[f] = foff_fine; - sync_bit_log[f] = sync_bit; + memcpy(&env_log[NT * P * f], env, sizeof(float) * NT * P); + rx_timing_log[f] = rx_timing; + nin_log[f] = nin; - sync_log[f] = fdmdv->sync; + for (c = 0; c < FDMDV_NC + 1; c++) { + rx_symbols_log[c][f] = rx_symbols[c]; + phase_difference_log[c][f] = fdmdv->phase_difference[c]; } + /* qpsk_to_bits() */ - /*---------------------------------------------------------*\ - Dump logs to Octave file for evaluation - by tfdmdv.m Octave script - \*---------------------------------------------------------*/ - - fout = fopen("tfdmdv_out.txt","wt"); - assert(fout != NULL); - fprintf(fout, "# Created by tfdmdv.c\n"); - octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, FDMDV_BITS_PER_FRAME*FRAMES); - octave_save_complex(fout, "tx_symbols_log_c", tx_symbols_log, 1, (FDMDV_NC+1)*FRAMES, (FDMDV_NC+1)*FRAMES); - octave_save_complex(fout, "tx_fdm_log_c", (COMP*)tx_fdm_log, 1, M_FAC*FRAMES, M_FAC*FRAMES); - octave_save_complex(fout, "pilot_lut_c", (COMP*)fdmdv->pilot_lut, 1, NPILOT_LUT, NPILOT_LUT); - octave_save_complex(fout, "pilot_baseband1_log_c", pilot_baseband1_log, 1, NPILOTBASEBAND*FRAMES, NPILOTBASEBAND*FRAMES); - octave_save_complex(fout, "pilot_baseband2_log_c", pilot_baseband2_log, 1, NPILOTBASEBAND*FRAMES, NPILOTBASEBAND*FRAMES); - octave_save_float(fout, "pilot_coeff_c", pilot_coeff, 1, NPILOTCOEFF, NPILOTCOEFF); - octave_save_complex(fout, "pilot_lpf1_log_c", pilot_lpf1_log, 1, NPILOTLPF*FRAMES, NPILOTLPF*FRAMES); - octave_save_complex(fout, "pilot_lpf2_log_c", pilot_lpf2_log, 1, NPILOTLPF*FRAMES, NPILOTLPF*FRAMES); - octave_save_complex(fout, "S1_log_c", S1_log, 1, MPILOTFFT*FRAMES, MPILOTFFT*FRAMES); - octave_save_complex(fout, "S2_log_c", S2_log, 1, MPILOTFFT*FRAMES, MPILOTFFT*FRAMES); - octave_save_float(fout, "foff_log_c", foff_log, 1, FRAMES, FRAMES); - octave_save_float(fout, "foff_coarse_log_c", foff_coarse_log, 1, FRAMES, FRAMES); - octave_save_complex(fout, "rx_fdm_filter_log_c", (COMP*)rx_fdm_filter_log, 1, rx_fdm_filter_log_index, rx_fdm_filter_log_index); - octave_save_complex(fout, "rx_filt_log_c", (COMP*)rx_filt_log, (FDMDV_NC+1), rx_filt_log_col_index, (P+1)*FRAMES); - octave_save_float(fout, "env_log_c", env_log, 1, NT*P*FRAMES, NT*P*FRAMES); - octave_save_float(fout, "rx_timing_log_c", rx_timing_log, 1, FRAMES, FRAMES); - octave_save_complex(fout, "rx_symbols_log_c", (COMP*)rx_symbols_log, (FDMDV_NC+1), FRAMES, FRAMES); - octave_save_complex(fout, "phase_difference_log_c", (COMP*)phase_difference_log, (FDMDV_NC+1), FRAMES, FRAMES); - octave_save_float(fout, "sig_est_log_c", (float*)sig_est_log, (FDMDV_NC+1), FRAMES, FRAMES); - octave_save_float(fout, "noise_est_log_c", (float*)noise_est_log, (FDMDV_NC+1), FRAMES, FRAMES); - octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, FDMDV_BITS_PER_FRAME*FRAMES); - octave_save_float(fout, "foff_fine_log_c", foff_fine_log, 1, FRAMES, FRAMES); - octave_save_int(fout, "sync_bit_log_c", sync_bit_log, 1, FRAMES); - octave_save_int(fout, "sync_log_c", sync_log, 1, FRAMES); - octave_save_int(fout, "nin_log_c", nin_log, 1, FRAMES); - fclose(fout); - - fdmdv_destroy(fdmdv); - - return 0; + memcpy(&rx_bits_log[FDMDV_BITS_PER_FRAME * f], rx_bits, + sizeof(int) * FDMDV_BITS_PER_FRAME); + for (c = 0; c < FDMDV_NC + 1; c++) { + sig_est_log[c][f] = fdmdv->sig_est[c]; + noise_est_log[c][f] = fdmdv->noise_est[c]; + } + foff_fine_log[f] = foff_fine; + sync_bit_log[f] = sync_bit; + + sync_log[f] = fdmdv->sync; + } + + /*---------------------------------------------------------*\ + Dump logs to Octave file for evaluation + by tfdmdv.m Octave script + \*---------------------------------------------------------*/ + + fout = fopen("tfdmdv_out.txt", "wt"); + assert(fout != NULL); + fprintf(fout, "# Created by tfdmdv.c\n"); + octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, + FDMDV_BITS_PER_FRAME * FRAMES); + octave_save_complex(fout, "tx_symbols_log_c", tx_symbols_log, 1, + (FDMDV_NC + 1) * FRAMES, (FDMDV_NC + 1) * FRAMES); + octave_save_complex(fout, "tx_fdm_log_c", (COMP *)tx_fdm_log, 1, + M_FAC * FRAMES, M_FAC * FRAMES); + octave_save_complex(fout, "pilot_lut_c", (COMP *)fdmdv->pilot_lut, 1, + NPILOT_LUT, NPILOT_LUT); + octave_save_complex(fout, "pilot_baseband1_log_c", pilot_baseband1_log, 1, + NPILOTBASEBAND * FRAMES, NPILOTBASEBAND * FRAMES); + octave_save_complex(fout, "pilot_baseband2_log_c", pilot_baseband2_log, 1, + NPILOTBASEBAND * FRAMES, NPILOTBASEBAND * FRAMES); + octave_save_float(fout, "pilot_coeff_c", pilot_coeff, 1, NPILOTCOEFF, + NPILOTCOEFF); + octave_save_complex(fout, "pilot_lpf1_log_c", pilot_lpf1_log, 1, + NPILOTLPF * FRAMES, NPILOTLPF * FRAMES); + octave_save_complex(fout, "pilot_lpf2_log_c", pilot_lpf2_log, 1, + NPILOTLPF * FRAMES, NPILOTLPF * FRAMES); + octave_save_complex(fout, "S1_log_c", S1_log, 1, MPILOTFFT * FRAMES, + MPILOTFFT * FRAMES); + octave_save_complex(fout, "S2_log_c", S2_log, 1, MPILOTFFT * FRAMES, + MPILOTFFT * FRAMES); + octave_save_float(fout, "foff_log_c", foff_log, 1, FRAMES, FRAMES); + octave_save_float(fout, "foff_coarse_log_c", foff_coarse_log, 1, FRAMES, + FRAMES); + octave_save_complex(fout, "rx_fdm_filter_log_c", (COMP *)rx_fdm_filter_log, 1, + rx_fdm_filter_log_index, rx_fdm_filter_log_index); + octave_save_complex(fout, "rx_filt_log_c", (COMP *)rx_filt_log, + (FDMDV_NC + 1), rx_filt_log_col_index, (P + 1) * FRAMES); + octave_save_float(fout, "env_log_c", env_log, 1, NT * P * FRAMES, + NT * P * FRAMES); + octave_save_float(fout, "rx_timing_log_c", rx_timing_log, 1, FRAMES, FRAMES); + octave_save_complex(fout, "rx_symbols_log_c", (COMP *)rx_symbols_log, + (FDMDV_NC + 1), FRAMES, FRAMES); + octave_save_complex(fout, "phase_difference_log_c", + (COMP *)phase_difference_log, (FDMDV_NC + 1), FRAMES, + FRAMES); + octave_save_float(fout, "sig_est_log_c", (float *)sig_est_log, (FDMDV_NC + 1), + FRAMES, FRAMES); + octave_save_float(fout, "noise_est_log_c", (float *)noise_est_log, + (FDMDV_NC + 1), FRAMES, FRAMES); + octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, + FDMDV_BITS_PER_FRAME * FRAMES); + octave_save_float(fout, "foff_fine_log_c", foff_fine_log, 1, FRAMES, FRAMES); + octave_save_int(fout, "sync_bit_log_c", sync_bit_log, 1, FRAMES); + octave_save_int(fout, "sync_log_c", sync_log, 1, FRAMES); + octave_save_int(fout, "nin_log_c", nin_log, 1, FRAMES); + fclose(fout); + + fdmdv_destroy(fdmdv); + + return 0; } - diff --git a/unittest/tfifo.c b/unittest/tfifo.c index 0987db6..bedda4f 100644 --- a/unittest/tfifo.c +++ b/unittest/tfifo.c @@ -7,15 +7,16 @@ */ #include -#include #include +#include + #include "codec2_fifo.h" -#define FIFO_SZ 1024 +#define FIFO_SZ 1024 #define WRITE_SZ 10 -#define READ_SZ 8 -#define N_MAX 100 -#define LOOPS 1000000 +#define READ_SZ 8 +#define N_MAX 100 +#define LOOPS 1000000 int run_thread = 1; struct FIFO *f; @@ -28,79 +29,75 @@ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //#define USE_MUTEX int main() { - pthread_t awriter_thread; - int i,j; - short read_buf[READ_SZ]; - int n_out = 0; - int success; - - f = codec2_fifo_create(FIFO_SZ); - #ifdef USE_THREADS - pthread_create(&awriter_thread, NULL, writer_thread, NULL); - #endif - - for(i=0; i WRITE_SZ) { - for(i=0; i WRITE_SZ) { + for (i = 0; i < WRITE_SZ; i++) { + write_buf[i] = n_in++; + if (n_in == N_MAX) n_in = 0; } +#ifdef USE_MUTEX + pthread_mutex_lock(&mutex); +#endif + codec2_fifo_write(f, write_buf, WRITE_SZ); + pthread_mutex_unlock(&mutex); + } } void *writer_thread(void *data) { + while (run_thread) { + writer(); + } - while(run_thread) { - writer(); - } - - return NULL; + return NULL; } diff --git a/unittest/tfmfsk.c b/unittest/tfmfsk.c index c1b46d5..d6818e1 100644 --- a/unittest/tfmfsk.c +++ b/unittest/tfmfsk.c @@ -4,8 +4,8 @@ AUTHOR......: Brady O'Brien DATE CREATED: 8 February 2016 - C test driver for fmfsk_mod and fmfsk_demod in fmfsk.c. Reads a file with input - bits/rf and spits out modulated/demoduladed samples and a dump of internal + C test driver for fmfsk_mod and fmfsk_demod in fmfsk.c. Reads a file with +input bits/rf and spits out modulated/demoduladed samples and a dump of internal state. To run unit test, see octave/tfmfsk.m \*---------------------------------------------------------------------------*/ @@ -27,13 +27,14 @@ along with this program; if not, see . */ - //#define MODEMPROBE_ENABLE -#include "modem_probe.h" #include -/* Note: This is a dirty hack to force fsk.c to compile with modem probing enabled */ +#include "modem_probe.h" + +/* Note: This is a dirty hack to force fsk.c to compile with modem probing + * enabled */ #include "fmfsk.c" #define ST_BITS 10000 @@ -41,158 +42,159 @@ #define ST_RS 2400 #define ST_EBNO 8 -#define TEST_SELF_FULL 1 /* No-arg self test */ -#define TEST_MOD 2 /* Test modulator using in and out file */ -#define TEST_DEMOD 3 /* Test demodulator using in and out file */ - - -int main(int argc,char *argv[]){ - struct FMFSK *fmfsk; - int Fs,Rs; - FILE *fin,*fout; - - uint8_t *bitbuf = NULL; - float *modbuf = NULL; - uint8_t *bitbufp; - float *modbufp; - - size_t bitbufsize = 0; - size_t modbufsize = 0; - - int test_type; - - int i; - - fin = NULL; - fout = NULL; - - /* Set up full self-test */ - if(argc == 1){ - test_type = TEST_SELF_FULL; - modem_probe_init("fmfsk","fmfsk_tfmfsk_log.txt"); - Fs = ST_FS; - Rs = ST_RS; - } else if (argc<7){ +#define TEST_SELF_FULL 1 /* No-arg self test */ +#define TEST_MOD 2 /* Test modulator using in and out file */ +#define TEST_DEMOD 3 /* Test demodulator using in and out file */ + +int main(int argc, char *argv[]) { + struct FMFSK *fmfsk; + int Fs, Rs; + FILE *fin, *fout; + + uint8_t *bitbuf = NULL; + float *modbuf = NULL; + uint8_t *bitbufp; + float *modbufp; + + size_t bitbufsize = 0; + size_t modbufsize = 0; + + int test_type; + + int i; + + fin = NULL; + fout = NULL; + + /* Set up full self-test */ + if (argc == 1) { + test_type = TEST_SELF_FULL; + modem_probe_init("fmfsk", "fmfsk_tfmfsk_log.txt"); + Fs = ST_FS; + Rs = ST_RS; + } else if (argc < 7) { /* Not running any test */ - printf("Usage: %s [(M|D) SampleRate BitRate InputFile OutputFile OctaveLogFile]\n",argv[0]); - exit(1); - } else { + printf( + "Usage: %s [(M|D) SampleRate BitRate InputFile OutputFile " + "OctaveLogFile]\n", + argv[0]); + exit(1); + } else { /* Running stim-drivin test */ - /* Mod test */ - if(strcmp(argv[1],"M")==0 || strcmp(argv[1],"m")==0) { - test_type = TEST_MOD; - /* Demod test */ - } else if(strcmp(argv[1],"D")==0 || strcmp(argv[1],"d")==0) { - test_type = TEST_DEMOD; - } else { - printf("Must specify mod or demod test with M or D\n"); - exit(1); - } - /* Extract parameters */ - Fs = atoi(argv[2]); - Rs = atoi(argv[3]); - - /* Open files */ - fin = fopen(argv[4],"r"); - fout = fopen(argv[5],"w"); - - if(fin == NULL || fout == NULL){ - printf("Couldn't open test vector files\n"); - exit(1); - } - /* Init modem probing */ - modem_probe_init("fmfsk",argv[6]); - + /* Mod test */ + if (strcmp(argv[1], "M") == 0 || strcmp(argv[1], "m") == 0) { + test_type = TEST_MOD; + /* Demod test */ + } else if (strcmp(argv[1], "D") == 0 || strcmp(argv[1], "d") == 0) { + test_type = TEST_DEMOD; + } else { + printf("Must specify mod or demod test with M or D\n"); + exit(1); } - - srand(1); - - /* set up FSK */ - fmfsk = fmfsk_create(Fs,Rs); - /* Modulate! */ - if(test_type == TEST_MOD || test_type == TEST_SELF_FULL){ - /* Generate random bits for self test */ - if(test_type == TEST_SELF_FULL){ - bitbufsize = ST_BITS; - bitbuf = (uint8_t*) malloc(sizeof(uint8_t)*ST_BITS); - for(i=0; inbit,fin) == fmfsk->nbit){ - i++; - bitbufp+=fmfsk->nbit; - /* Make sure we don't break the buffer */ - if(i*fmfsk->nbit > bitbufsize){ - bitbuf = realloc(bitbuf,sizeof(uint8_t)*(bitbufsize+fmfsk->nbit)); - bitbufsize += fmfsk->nbit; - } - } - } - /* Allocate modulation buffer */ - modbuf = (float*)malloc(sizeof(float)*(bitbufsize/fmfsk->nbit)*fmfsk->N*4); - modbufsize = (bitbufsize/fmfsk->nbit)*fmfsk->N; - /* Do the modulation */ - modbufp = modbuf; - bitbufp = bitbuf; - while( bitbufp < bitbuf+bitbufsize){ - fmfsk_mod(fmfsk, modbufp, bitbufp); - modbufp += fmfsk->N; - bitbufp += fmfsk->nbit; - } - /* For a mod-only test, write out the result */ - if(test_type == TEST_MOD){ - fwrite(modbuf,sizeof(float),modbufsize,fout); - free(modbuf); - } - /* Free bit buffer */ - free(bitbuf); + /* Extract parameters */ + Fs = atoi(argv[2]); + Rs = atoi(argv[3]); + + /* Open files */ + fin = fopen(argv[4], "r"); + fout = fopen(argv[5], "w"); + + if (fin == NULL || fout == NULL) { + printf("Couldn't open test vector files\n"); + exit(1); } - - /* Add channel imp here */ - - - /* Now test the demod */ - if(test_type == TEST_DEMOD || test_type == TEST_SELF_FULL){ - free(modbuf); - modbuf = malloc(sizeof(float)*(fmfsk->N+fmfsk->Ts*2)); - bitbuf = malloc(sizeof(uint8_t)*fmfsk->nbit); - /* Demod-only test */ - if(test_type == TEST_DEMOD){ - - //fprintf(stderr,"%d\n",(fmfsk->N+fmfsk->Ts*2)); - while( fread(modbuf,sizeof(float),fmfsk_nin(fmfsk),fin) == fmfsk_nin(fmfsk) ){ - fmfsk_demod(fmfsk,bitbuf,modbuf); - fwrite(bitbuf,sizeof(uint8_t),fmfsk->nbit,fout); - } - } - /* Demod after channel imp. and mod */ - else{ - bitbufp = bitbuf; - modbufp = modbuf; - while( modbufp < modbuf + modbufsize){ - fmfsk_demod(fmfsk,bitbuf,modbuf); - modbufp += fmfsk_nin(fmfsk); - } + /* Init modem probing */ + modem_probe_init("fmfsk", argv[6]); + } + + srand(1); + + /* set up FSK */ + fmfsk = fmfsk_create(Fs, Rs); + /* Modulate! */ + if (test_type == TEST_MOD || test_type == TEST_SELF_FULL) { + /* Generate random bits for self test */ + if (test_type == TEST_SELF_FULL) { + bitbufsize = ST_BITS; + bitbuf = (uint8_t *)malloc(sizeof(uint8_t) * ST_BITS); + for (i = 0; i < ST_BITS; i++) { + /* Generate a randomish bit */ + bitbuf[i] = (uint8_t)(rand() & 0x01); + } + } else { /* Load bits from a file */ + /* Figure out how many bits are in the input file */ + fseek(fin, 0L, SEEK_END); + bitbufsize = ftell(fin); + fseek(fin, 0L, SEEK_SET); + bitbuf = malloc(sizeof(uint8_t) * bitbufsize); + i = 0; + /* Read in some bits */ + bitbufp = bitbuf; + while (fread(bitbufp, sizeof(uint8_t), fmfsk->nbit, fin) == fmfsk->nbit) { + i++; + bitbufp += fmfsk->nbit; + /* Make sure we don't break the buffer */ + if (i * fmfsk->nbit > bitbufsize) { + bitbuf = + realloc(bitbuf, sizeof(uint8_t) * (bitbufsize + fmfsk->nbit)); + bitbufsize += fmfsk->nbit; } - free(bitbuf); + } + } + /* Allocate modulation buffer */ + modbuf = (float *)malloc(sizeof(float) * (bitbufsize / fmfsk->nbit) * + fmfsk->N * 4); + modbufsize = (bitbufsize / fmfsk->nbit) * fmfsk->N; + /* Do the modulation */ + modbufp = modbuf; + bitbufp = bitbuf; + while (bitbufp < bitbuf + bitbufsize) { + fmfsk_mod(fmfsk, modbufp, bitbufp); + modbufp += fmfsk->N; + bitbufp += fmfsk->nbit; } - - modem_probe_close(); - if(test_type == TEST_DEMOD || test_type == TEST_MOD){ - fclose(fin); - fclose(fout); + /* For a mod-only test, write out the result */ + if (test_type == TEST_MOD) { + fwrite(modbuf, sizeof(float), modbufsize, fout); + free(modbuf); } - fmfsk_destroy(fmfsk); - exit(0); + /* Free bit buffer */ + free(bitbuf); + } + + /* Add channel imp here */ + + /* Now test the demod */ + if (test_type == TEST_DEMOD || test_type == TEST_SELF_FULL) { + free(modbuf); + modbuf = malloc(sizeof(float) * (fmfsk->N + fmfsk->Ts * 2)); + bitbuf = malloc(sizeof(uint8_t) * fmfsk->nbit); + /* Demod-only test */ + if (test_type == TEST_DEMOD) { + // fprintf(stderr,"%d\n",(fmfsk->N+fmfsk->Ts*2)); + while (fread(modbuf, sizeof(float), fmfsk_nin(fmfsk), fin) == + fmfsk_nin(fmfsk)) { + fmfsk_demod(fmfsk, bitbuf, modbuf); + fwrite(bitbuf, sizeof(uint8_t), fmfsk->nbit, fout); + } + } + /* Demod after channel imp. and mod */ + else { + bitbufp = bitbuf; + modbufp = modbuf; + while (modbufp < modbuf + modbufsize) { + fmfsk_demod(fmfsk, bitbuf, modbuf); + modbufp += fmfsk_nin(fmfsk); + } + } + free(bitbuf); + } + + modem_probe_close(); + if (test_type == TEST_DEMOD || test_type == TEST_MOD) { + fclose(fin); + fclose(fout); + } + fmfsk_destroy(fmfsk); + exit(0); } - diff --git a/unittest/tfreedv_2400A_rawdata.c b/unittest/tfreedv_2400A_rawdata.c index 8007793..b81aa47 100644 --- a/unittest/tfreedv_2400A_rawdata.c +++ b/unittest/tfreedv_2400A_rawdata.c @@ -27,86 +27,87 @@ */ #include -#include "freedv_api.h" + #include "assert.h" +#include "freedv_api.h" -int main(int argc, char **argv) -{ - struct freedv *f; - int i; - - printf("freedv_api tests for mode 2400A\n"); - - printf("freedv_open(FREEDV_MODE_2400A) "); - f = freedv_open(FREEDV_MODE_2400A); - assert(f != NULL); - printf("Passed\n"); - - printf("freedv_get_mode() "); - int mode = freedv_get_mode(f); - assert(mode == FREEDV_MODE_2400A); - printf("Passed\n"); - - printf("freedv_get_n_max_modem_samples() "); - int max_samples = freedv_get_n_max_modem_samples(f); - assert(max_samples == 2040); - printf("%d Passed\n", max_samples); - - printf("freedv_get_n_nom_modem_samples() "); - int nom_samples = freedv_get_n_nom_modem_samples(f); - assert(nom_samples == 2000); - printf("%d Passed\n", nom_samples); - - printf("freedv_get_n_speech_samples() "); - int speech_samples = freedv_get_n_speech_samples(f); - assert(speech_samples == 320); - printf("%d Passed\n", speech_samples); - - printf("freedv_get_n_bits_per_codec_frame() "); - int codec_bits = freedv_get_bits_per_codec_frame(f); - assert(codec_bits == 52); - printf("%d Passed\n", codec_bits); - - printf("freedv_get_n_bits_per_modem_frame() "); - int frame_bits = freedv_get_bits_per_modem_frame(f); - assert(frame_bits == 52); - printf("%d Passed\n", frame_bits); - - printf("freedv_rawdatatx()/freedv_rawdatarx() "); - int frames = 0; - { - short mod[nom_samples * 10]; - /* Note: A codec frame is only 6.5 bytes! - so the seventh byte will be half empty! - */ - unsigned char payload[7] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x70 }; - for (i = 0; i < 10; i ++) { - freedv_rawdatatx(f, mod + i * nom_samples, payload); - } - int nin = 0; - for (i = 0; i < nom_samples * 9; i += nin) { - nin = freedv_nin(f); - unsigned char payload_rx[7] = {0}; - int r = freedv_rawdatarx(f, payload_rx, mod + i); - if (r) { - int b; - for (b = 0; b < 7; b++) { - if (payload[b] != payload_rx[b]) { - printf("Received codec bits 0x%02x do not match expected 0x%02x\n", payload_rx[b], payload[b]); - } - } - frames++; - } - } +int main(int argc, char **argv) { + struct freedv *f; + int i; + + printf("freedv_api tests for mode 2400A\n"); + + printf("freedv_open(FREEDV_MODE_2400A) "); + f = freedv_open(FREEDV_MODE_2400A); + assert(f != NULL); + printf("Passed\n"); + + printf("freedv_get_mode() "); + int mode = freedv_get_mode(f); + assert(mode == FREEDV_MODE_2400A); + printf("Passed\n"); + + printf("freedv_get_n_max_modem_samples() "); + int max_samples = freedv_get_n_max_modem_samples(f); + assert(max_samples == 2040); + printf("%d Passed\n", max_samples); + + printf("freedv_get_n_nom_modem_samples() "); + int nom_samples = freedv_get_n_nom_modem_samples(f); + assert(nom_samples == 2000); + printf("%d Passed\n", nom_samples); + + printf("freedv_get_n_speech_samples() "); + int speech_samples = freedv_get_n_speech_samples(f); + assert(speech_samples == 320); + printf("%d Passed\n", speech_samples); + + printf("freedv_get_n_bits_per_codec_frame() "); + int codec_bits = freedv_get_bits_per_codec_frame(f); + assert(codec_bits == 52); + printf("%d Passed\n", codec_bits); + + printf("freedv_get_n_bits_per_modem_frame() "); + int frame_bits = freedv_get_bits_per_modem_frame(f); + assert(frame_bits == 52); + printf("%d Passed\n", frame_bits); + + printf("freedv_rawdatatx()/freedv_rawdatarx() "); + int frames = 0; + { + short mod[nom_samples * 10]; + /* Note: A codec frame is only 6.5 bytes! + so the seventh byte will be half empty! + */ + unsigned char payload[7] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x70}; + for (i = 0; i < 10; i++) { + freedv_rawdatatx(f, mod + i * nom_samples, payload); } - if (!frames) { - printf("Did not decode any frames successfully\n"); - goto fail; + int nin = 0; + for (i = 0; i < nom_samples * 9; i += nin) { + nin = freedv_nin(f); + unsigned char payload_rx[7] = {0}; + int r = freedv_rawdatarx(f, payload_rx, mod + i); + if (r) { + int b; + for (b = 0; b < 7; b++) { + if (payload[b] != payload_rx[b]) { + printf("Received codec bits 0x%02x do not match expected 0x%02x\n", + payload_rx[b], payload[b]); + } + } + frames++; + } } - - printf("Tests passed\n"); - return 0; + } + if (!frames) { + printf("Did not decode any frames successfully\n"); + goto fail; + } + + printf("Tests passed\n"); + return 0; fail: - printf("Test failed\n"); - return 1; + printf("Test failed\n"); + return 1; } diff --git a/unittest/tfreedv_2400B_rawdata.c b/unittest/tfreedv_2400B_rawdata.c index 0af4e8e..f515bb5 100644 --- a/unittest/tfreedv_2400B_rawdata.c +++ b/unittest/tfreedv_2400B_rawdata.c @@ -27,86 +27,87 @@ */ #include -#include "freedv_api.h" + #include "assert.h" +#include "freedv_api.h" -int main(int argc, char **argv) -{ - struct freedv *f; - int i; - - printf("freedv_api tests for mode 2400B\n"); - - printf("freedv_open(FREEDV_MODE_2400B) "); - f = freedv_open(FREEDV_MODE_2400B); - assert(f != NULL); - printf("Passed\n"); - - printf("freedv_get_mode() "); - int mode = freedv_get_mode(f); - assert(mode == FREEDV_MODE_2400B); - printf("Passed\n"); - - printf("freedv_get_n_max_modem_samples() "); - int max_samples = freedv_get_n_max_modem_samples(f); - assert(max_samples == 1930); - printf("%d Passed\n", max_samples); - - printf("freedv_get_n_nom_modem_samples() "); - int nom_samples = freedv_get_n_nom_modem_samples(f); - assert(nom_samples == 1920); - printf("%d Passed\n", nom_samples); - - printf("freedv_get_n_speech_samples() "); - int speech_samples = freedv_get_n_speech_samples(f); - assert(speech_samples == 320); - printf("%d Passed\n", speech_samples); - - printf("freedv_get_n_bits_per_codec_frame() "); - int codec_bits = freedv_get_bits_per_codec_frame(f); - assert(codec_bits == 52); - printf("%d Passed\n", codec_bits); - - printf("freedv_get_n_bits_per_modem_frame() "); - int frame_bits = freedv_get_bits_per_modem_frame(f); - assert(frame_bits == 52); - printf("%d Passed\n", frame_bits); - - printf("freedv_rawdatatx()/freedv_rawdatarx() "); - int frames = 0; - { - short mod[nom_samples * 10]; - /* Note: A codec frame is only 6.5 bytes! - so the seventh byte will be half empty! - */ - unsigned char payload[7] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x70 }; - for (i = 0; i < 10; i ++) { - freedv_rawdatatx(f, mod + i * nom_samples, payload); - } - int nin = 0; - for (i = 0; i < nom_samples * 9; i += nin) { - nin = freedv_nin(f); - unsigned char payload_rx[7] = {0}; - int r = freedv_rawdatarx(f, payload_rx, mod + i); - if (r) { - int b; - for (b = 0; b < 7; b++) { - if (payload[b] != payload_rx[b]) { - printf("Received codec bits 0x%02x do not match expected 0x%02x\n", payload_rx[b], payload[b]); - } - } - frames++; - } - } +int main(int argc, char **argv) { + struct freedv *f; + int i; + + printf("freedv_api tests for mode 2400B\n"); + + printf("freedv_open(FREEDV_MODE_2400B) "); + f = freedv_open(FREEDV_MODE_2400B); + assert(f != NULL); + printf("Passed\n"); + + printf("freedv_get_mode() "); + int mode = freedv_get_mode(f); + assert(mode == FREEDV_MODE_2400B); + printf("Passed\n"); + + printf("freedv_get_n_max_modem_samples() "); + int max_samples = freedv_get_n_max_modem_samples(f); + assert(max_samples == 1930); + printf("%d Passed\n", max_samples); + + printf("freedv_get_n_nom_modem_samples() "); + int nom_samples = freedv_get_n_nom_modem_samples(f); + assert(nom_samples == 1920); + printf("%d Passed\n", nom_samples); + + printf("freedv_get_n_speech_samples() "); + int speech_samples = freedv_get_n_speech_samples(f); + assert(speech_samples == 320); + printf("%d Passed\n", speech_samples); + + printf("freedv_get_n_bits_per_codec_frame() "); + int codec_bits = freedv_get_bits_per_codec_frame(f); + assert(codec_bits == 52); + printf("%d Passed\n", codec_bits); + + printf("freedv_get_n_bits_per_modem_frame() "); + int frame_bits = freedv_get_bits_per_modem_frame(f); + assert(frame_bits == 52); + printf("%d Passed\n", frame_bits); + + printf("freedv_rawdatatx()/freedv_rawdatarx() "); + int frames = 0; + { + short mod[nom_samples * 10]; + /* Note: A codec frame is only 6.5 bytes! + so the seventh byte will be half empty! + */ + unsigned char payload[7] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x70}; + for (i = 0; i < 10; i++) { + freedv_rawdatatx(f, mod + i * nom_samples, payload); } - if (!frames) { - printf("Did not decode any frames successfully\n"); - goto fail; + int nin = 0; + for (i = 0; i < nom_samples * 9; i += nin) { + nin = freedv_nin(f); + unsigned char payload_rx[7] = {0}; + int r = freedv_rawdatarx(f, payload_rx, mod + i); + if (r) { + int b; + for (b = 0; b < 7; b++) { + if (payload[b] != payload_rx[b]) { + printf("Received codec bits 0x%02x do not match expected 0x%02x\n", + payload_rx[b], payload[b]); + } + } + frames++; + } } - - printf("Tests passed\n"); - return 0; + } + if (!frames) { + printf("Did not decode any frames successfully\n"); + goto fail; + } + + printf("Tests passed\n"); + return 0; fail: - printf("Test failed\n"); - return 1; + printf("Test failed\n"); + return 1; } diff --git a/unittest/tfreedv_800XA_rawdata.c b/unittest/tfreedv_800XA_rawdata.c index 2cf9bb7..2b34c41 100644 --- a/unittest/tfreedv_800XA_rawdata.c +++ b/unittest/tfreedv_800XA_rawdata.c @@ -27,121 +27,121 @@ */ #include -#include "freedv_api.h" + #include "assert.h" +#include "freedv_api.h" -int main(int argc, char **argv) -{ - struct freedv *f; - int i; - - printf("freedv_api tests for mode 800XA\n"); - - printf("freedv_open(FREEDV_MODE_800XA) "); - f = freedv_open(FREEDV_MODE_800XA); - assert(f != NULL); - printf("Passed\n"); - - printf("freedv_get_mode() "); - int mode = freedv_get_mode(f); - assert(mode == FREEDV_MODE_800XA); - printf("Passed\n"); - - printf("freedv_get_n_max_modem_samples() "); - int max_samples = freedv_get_n_max_modem_samples(f); - assert(max_samples == 660); - printf("%d Passed\n", max_samples); - - printf("freedv_get_n_nom_modem_samples() "); - int nom_samples = freedv_get_n_nom_modem_samples(f); - assert(nom_samples == 640); - printf("%d Passed\n", nom_samples); - - printf("freedv_get_n_speech_samples() "); - int speech_samples = freedv_get_n_speech_samples(f); - assert(speech_samples == 640); - printf("%d Passed\n", speech_samples); - - printf("freedv_get_n_bits_per_codec_frame() "); - int codec_bits = freedv_get_bits_per_codec_frame(f); - assert(codec_bits == 28); - printf("%d Passed\n", codec_bits); - - printf("freedv_get_n_bits_per_modem_frame() "); - int frame_bits = freedv_get_bits_per_modem_frame(f); - assert(frame_bits == 56); - printf("%d Passed\n", frame_bits); - - /* Note: A codec frame is only 3.5 bytes! - so the fourth and eight bytes will be half empty! - */ - unsigned char payload[8] = { 0x12, 0x34, 0x56, 0x70, 0x89, 0xab, 0xcd, 0xe0 }; - unsigned char payload_tx[7] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde }; - - printf("freedv_codec_frames_from_rawdata() "); - unsigned char codec_frames[8] = { 0 }; - freedv_codec_frames_from_rawdata(f, codec_frames, payload_tx); - int fails = 0; - for (i = 0; i < 8; i++) { - if (codec_frames[i] != payload[i]) { - printf("byte %d: 0x%02x does not match expected 0x%02x\n", i, codec_frames[i], payload[i]); - fails++; - } +int main(int argc, char **argv) { + struct freedv *f; + int i; + + printf("freedv_api tests for mode 800XA\n"); + + printf("freedv_open(FREEDV_MODE_800XA) "); + f = freedv_open(FREEDV_MODE_800XA); + assert(f != NULL); + printf("Passed\n"); + + printf("freedv_get_mode() "); + int mode = freedv_get_mode(f); + assert(mode == FREEDV_MODE_800XA); + printf("Passed\n"); + + printf("freedv_get_n_max_modem_samples() "); + int max_samples = freedv_get_n_max_modem_samples(f); + assert(max_samples == 660); + printf("%d Passed\n", max_samples); + + printf("freedv_get_n_nom_modem_samples() "); + int nom_samples = freedv_get_n_nom_modem_samples(f); + assert(nom_samples == 640); + printf("%d Passed\n", nom_samples); + + printf("freedv_get_n_speech_samples() "); + int speech_samples = freedv_get_n_speech_samples(f); + assert(speech_samples == 640); + printf("%d Passed\n", speech_samples); + + printf("freedv_get_n_bits_per_codec_frame() "); + int codec_bits = freedv_get_bits_per_codec_frame(f); + assert(codec_bits == 28); + printf("%d Passed\n", codec_bits); + + printf("freedv_get_n_bits_per_modem_frame() "); + int frame_bits = freedv_get_bits_per_modem_frame(f); + assert(frame_bits == 56); + printf("%d Passed\n", frame_bits); + + /* Note: A codec frame is only 3.5 bytes! + so the fourth and eight bytes will be half empty! + */ + unsigned char payload[8] = {0x12, 0x34, 0x56, 0x70, 0x89, 0xab, 0xcd, 0xe0}; + unsigned char payload_tx[7] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde}; + + printf("freedv_codec_frames_from_rawdata() "); + unsigned char codec_frames[8] = {0}; + freedv_codec_frames_from_rawdata(f, codec_frames, payload_tx); + int fails = 0; + for (i = 0; i < 8; i++) { + if (codec_frames[i] != payload[i]) { + printf("byte %d: 0x%02x does not match expected 0x%02x\n", i, + codec_frames[i], payload[i]); + fails++; } - if (fails) - goto fail; - printf("Passed\n"); - - printf("freedv_rawdata_from_codec_frames() "); - unsigned char rawdata[7] = { 0 }; - freedv_rawdata_from_codec_frames(f, rawdata, payload); - fails = 0; - for (i = 0; i < 7; i++) { - if (rawdata[i] != payload_tx[i]) { - printf("byte %d: 0x%02x does not match expected 0x%02x\n", i, rawdata[i], payload_tx[i]); - fails++; - } + } + if (fails) goto fail; + printf("Passed\n"); + + printf("freedv_rawdata_from_codec_frames() "); + unsigned char rawdata[7] = {0}; + freedv_rawdata_from_codec_frames(f, rawdata, payload); + fails = 0; + for (i = 0; i < 7; i++) { + if (rawdata[i] != payload_tx[i]) { + printf("byte %d: 0x%02x does not match expected 0x%02x\n", i, rawdata[i], + payload_tx[i]); + fails++; } - if (fails) - goto fail; - printf("Passed\n"); - - printf("freedv_rawdatatx()/freedv_rawdatarx() "); - int frames = 0; - fails = 0; - { - short mod[nom_samples * 10]; - for (i = 0; i < 10; i ++) { - freedv_rawdatatx(f, mod + i * nom_samples, payload_tx); - } - int nin = 0; - for (i = 0; i < nom_samples * 9; i += nin) { - nin = freedv_nin(f); - unsigned char payload_rx[8] = {0}; - int r = freedv_rawdatarx(f, payload_rx, mod + i); - if (r == 7) { - int b; - for (b = 0; b < 7; b++) { - if (payload_tx[b] != payload_rx[b]) { - printf("Received codec bits 0x%02x do not match expected 0x%02x\n", payload_rx[b], payload_tx[b]); - fails++; - } - } - frames++; - } - } + } + if (fails) goto fail; + printf("Passed\n"); + + printf("freedv_rawdatatx()/freedv_rawdatarx() "); + int frames = 0; + fails = 0; + { + short mod[nom_samples * 10]; + for (i = 0; i < 10; i++) { + freedv_rawdatatx(f, mod + i * nom_samples, payload_tx); } - if (!frames) { - printf("Did not decode any frames successfully\n"); - goto fail; + int nin = 0; + for (i = 0; i < nom_samples * 9; i += nin) { + nin = freedv_nin(f); + unsigned char payload_rx[8] = {0}; + int r = freedv_rawdatarx(f, payload_rx, mod + i); + if (r == 7) { + int b; + for (b = 0; b < 7; b++) { + if (payload_tx[b] != payload_rx[b]) { + printf("Received codec bits 0x%02x do not match expected 0x%02x\n", + payload_rx[b], payload_tx[b]); + fails++; + } + } + frames++; + } } - if (fails) - goto fail; - printf("Passed\n"); - - printf("Tests passed\n"); - return 0; + } + if (!frames) { + printf("Did not decode any frames successfully\n"); + goto fail; + } + if (fails) goto fail; + printf("Passed\n"); + + printf("Tests passed\n"); + return 0; fail: - printf("Test failed\n"); - return 1; + printf("Test failed\n"); + return 1; } diff --git a/unittest/tfreedv_data_channel.c b/unittest/tfreedv_data_channel.c index ef713eb..e94cadc 100644 --- a/unittest/tfreedv_data_channel.c +++ b/unittest/tfreedv_data_channel.c @@ -26,290 +26,257 @@ along with this program; if not, see . */ -#include "freedv_data_channel.h" - #include #include -unsigned char test_header[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; -unsigned char bcast_header[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +#include "freedv_data_channel.h" +unsigned char test_header[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; +unsigned char bcast_header[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct testvec { - char *testname; - - unsigned char *data; - size_t data_size; - - size_t frame_size; - - unsigned char *frame_data; - size_t frame_data_size; - - unsigned char *flags; + char *testname; + + unsigned char *data; + size_t data_size; + + size_t frame_size; + + unsigned char *frame_data; + size_t frame_data_size; + + unsigned char *flags; } testvec[] = { { "Regular packet, does not match header and no broadcast", - (unsigned char[]){ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x12 - }, + (unsigned char[]){0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12}, 0x12, 8, - (unsigned char[]){ - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x01, 0x02, - 0x03, 0x04, 0x05, 0x06, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x12, 0x47, 0x6e - }, + (unsigned char[]){0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x47, 0x6e}, 0x14, - (unsigned char[]){ 0x00, 0x00, 0x04 }, + (unsigned char[]){0x00, 0x00, 0x04}, }, { "Header", NULL, 0, 8, - (unsigned char[]){ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x5a, 0x60 }, + (unsigned char[]){0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x5a, 0x60}, 0x08, - (unsigned char[]){ 0x08 }, + (unsigned char[]){0x08}, }, { "Broadcast packet", - (unsigned char[]){ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22, - 0x33, 0x44, 0x55, 0x66, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11 - }, + (unsigned char[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22, 0x33, + 0x44, 0x55, 0x66, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11}, 0x19, 8, - (unsigned char[]){ - 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x3c, 0xbe - }, + (unsigned char[]){0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x3c, 0xbe}, 0x0f, - (unsigned char[]){ 0xc0, 0x07 }, + (unsigned char[]){0xc0, 0x07}, }, { "Broadcast packet, header does not match", - (unsigned char[]){ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0x22, - 0xbb, 0xcc, 0xdd, 0xee, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11 - }, + (unsigned char[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0x22, 0xbb, + 0xcc, 0xdd, 0xee, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11}, 0x19, 8, - (unsigned char[]){ - 0xaa, 0x22, - 0xbb, 0xcc, 0xdd, 0xee, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x1a, 0x68 - }, + (unsigned char[]){0xaa, 0x22, 0xbb, 0xcc, 0xdd, 0xee, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x1a, 0x68}, 0x15, - (unsigned char[]){ 0x40, 0x00, 0x05 }, + (unsigned char[]){0x40, 0x00, 0x05}, }, { "Header 6 bytes", NULL, 0, 6, - (unsigned char[]){ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }, + (unsigned char[]){0x11, 0x22, 0x33, 0x44, 0x55, 0x66}, 0x06, - (unsigned char[]){ 0x2f }, + (unsigned char[]){0x2f}, }, { "Broadcast packet (6 byte frames)", - (unsigned char[]){ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22, - 0x33, 0x44, 0x55, 0x66, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11 - }, + (unsigned char[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22, 0x33, + 0x44, 0x55, 0x66, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11}, 0x19, 6, - (unsigned char[]){ - 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x3c, 0xbe - }, + (unsigned char[]){0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x3c, 0xbe}, 0x0f, - (unsigned char[]){ 0xc0, 0x00, 0x03 }, + (unsigned char[]){0xc0, 0x00, 0x03}, }, { "Broadcast packet, header does not match (6 byte frames)", - (unsigned char[]){ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0x22, - 0xbb, 0xcc, 0xdd, 0xee, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11 - }, + (unsigned char[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaa, 0x22, 0xbb, + 0xcc, 0xdd, 0xee, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11}, 0x19, 6, - (unsigned char[]){ - 0xaa, 0x22, - 0xbb, 0xcc, 0xdd, 0xee, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x1a, 0x68 - }, + (unsigned char[]){0xaa, 0x22, 0xbb, 0xcc, 0xdd, 0xee, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x1a, 0x68}, 0x15, - (unsigned char[]){ 0x40, 0x00, 0x00, 0x03 }, + (unsigned char[]){0x40, 0x00, 0x00, 0x03}, }, }; - static int ret = 0; static int vector = 0; static size_t frame_data_pos = 0; static int rx_done = 0; -void *tx_cb_arg = (void*)0xaa55; -void *rx_cb_arg = (void*)0xbb44; +void *tx_cb_arg = (void *)0xaa55; +void *rx_cb_arg = (void *)0xbb44; -void tfreedv_data_callback_tx(void *arg, unsigned char *packet, size_t *size) -{ - if (tx_cb_arg != arg) { - ret++; - printf("FAIL: %s called with wrong argument value\n", __func__); - } - printf("--------------------------------------\n"); - printf("TX callback called for test %zd bytes data for test %d:\n'%s'\n", - testvec[vector].data_size, vector, - testvec[vector].testname); - - memcpy(packet, testvec[vector].data, testvec[vector].data_size); - *size = testvec[vector].data_size; - - return; +void tfreedv_data_callback_tx(void *arg, unsigned char *packet, size_t *size) { + if (tx_cb_arg != arg) { + ret++; + printf("FAIL: %s called with wrong argument value\n", __func__); + } + printf("--------------------------------------\n"); + printf("TX callback called for test %zd bytes data for test %d:\n'%s'\n", + testvec[vector].data_size, vector, testvec[vector].testname); + + memcpy(packet, testvec[vector].data, testvec[vector].data_size); + *size = testvec[vector].data_size; + + return; } -void tfreedv_data_callback_rx(void *arg, unsigned char *packet, size_t size) -{ - if (rx_cb_arg != arg) { - ret++; - printf("FAIL: %s called with wrong argument value\n", __func__); - } - printf("RX callback called with %zd bytes\n", size); - - if (testvec[vector].data_size) { - size_t data_size = testvec[vector].data_size; - if (data_size != size) { - printf("FAIL: Received size does not match test vector: %zd != %zd\n", - size, data_size); - ret++; - } else { - size_t i; - for (i = 0; i < data_size; i++) { - if (packet[i] != testvec[vector].data[i]) { - printf("FAIL: byte %zd does not match 0x%02x != 0x%02x\n", - i, packet[i], testvec[vector].data[i]); - ret++; - } - } - } +void tfreedv_data_callback_rx(void *arg, unsigned char *packet, size_t size) { + if (rx_cb_arg != arg) { + ret++; + printf("FAIL: %s called with wrong argument value\n", __func__); + } + printf("RX callback called with %zd bytes\n", size); + + if (testvec[vector].data_size) { + size_t data_size = testvec[vector].data_size; + if (data_size != size) { + printf("FAIL: Received size does not match test vector: %zd != %zd\n", + size, data_size); + ret++; } else { - if (size != 12) { - printf("FAIL: Received header is not 12 bytes: %zd\n", size); - ret++; - } else { - if (memcmp(packet, bcast_header, 6)) { - printf("FAIL: Header is not a broadcast!\n"); - ret++; - } - if (memcmp(packet+6, test_header, 6)) { - printf("FAIL: Header does not match!\n"); - ret++; - } + size_t i; + for (i = 0; i < data_size; i++) { + if (packet[i] != testvec[vector].data[i]) { + printf("FAIL: byte %zd does not match 0x%02x != 0x%02x\n", i, + packet[i], testvec[vector].data[i]); + ret++; } + } + } + } else { + if (size != 12) { + printf("FAIL: Received header is not 12 bytes: %zd\n", size); + ret++; + } else { + if (memcmp(packet, bcast_header, 6)) { + printf("FAIL: Header is not a broadcast!\n"); + ret++; + } + if (memcmp(packet + 6, test_header, 6)) { + printf("FAIL: Header does not match!\n"); + ret++; + } } - - rx_done = 1; + } + + rx_done = 1; } -int main(int argc, char **argv) -{ - struct freedv_data_channel *fdc; - - fdc = freedv_data_channel_create(); - - freedv_data_set_header(fdc, test_header); - freedv_data_set_cb_tx(fdc, tfreedv_data_callback_tx, tx_cb_arg); - freedv_data_set_cb_rx(fdc, tfreedv_data_callback_rx, rx_cb_arg); - - while (vector < sizeof(testvec)/sizeof(struct testvec)) { - size_t frame_size = testvec[vector].frame_size; - unsigned char frame[frame_size]; - int from, bcast, crc, end; - int i; - size_t check_size; - unsigned char flags; - int nr_frames; - - freedv_data_channel_tx_frame(fdc, frame, frame_size, &from, &bcast, &crc, &end); - - check_size = frame_size; - if (frame_data_pos + check_size > testvec[vector].frame_data_size) - check_size = testvec[vector].frame_data_size - frame_data_pos; - - flags = from * 0x80 + bcast * 0x40 + crc * 0x20 + end; - printf("0x%02x:", flags); - for (i = 0; i < check_size; i++) { - if (frame[i] != testvec[vector].frame_data[frame_data_pos + i]) { - printf(" [0x%02x!=0x%02x]", - frame[i], testvec[vector].frame_data[frame_data_pos + i]); - ret++; - } else { - printf(" 0x%02x", frame[i]); - } - } - printf("\n"); - - if (flags != testvec[vector].flags[frame_data_pos / frame_size]) { - printf("FAIL: Flags byte does not match 0x%02x != 0x%02x\n", - flags, testvec[vector].flags[frame_data_pos / frame_size]); - ret++; - } +int main(int argc, char **argv) { + struct freedv_data_channel *fdc; - freedv_data_channel_rx_frame(fdc, frame, frame_size, from, bcast, crc, end); - - frame_data_pos += frame_size; - - nr_frames = freedv_data_get_n_tx_frames(fdc, frame_size); - - if (frame_data_pos >= testvec[vector].frame_data_size) { - if (nr_frames) { - printf("FAIL: nr_frames is not zero: %d\n", nr_frames); - ret++; - } - vector++; - frame_data_pos = 0; - if (!rx_done) { - printf("FAIL: RX callback not executed\n"); - ret++; - } - rx_done = 0; - } else { - int vec_frames = (testvec[vector].frame_data_size - frame_data_pos); - vec_frames /= frame_size; - vec_frames++; - if (nr_frames != vec_frames) { - printf("FAIL: nr_frames != vec_frames: %d != %d\n", nr_frames, vec_frames); - ret++; - } - } + fdc = freedv_data_channel_create(); + + freedv_data_set_header(fdc, test_header); + freedv_data_set_cb_tx(fdc, tfreedv_data_callback_tx, tx_cb_arg); + freedv_data_set_cb_rx(fdc, tfreedv_data_callback_rx, rx_cb_arg); + + while (vector < sizeof(testvec) / sizeof(struct testvec)) { + size_t frame_size = testvec[vector].frame_size; + unsigned char frame[frame_size]; + int from, bcast, crc, end; + int i; + size_t check_size; + unsigned char flags; + int nr_frames; + + freedv_data_channel_tx_frame(fdc, frame, frame_size, &from, &bcast, &crc, + &end); + + check_size = frame_size; + if (frame_data_pos + check_size > testvec[vector].frame_data_size) + check_size = testvec[vector].frame_data_size - frame_data_pos; + + flags = from * 0x80 + bcast * 0x40 + crc * 0x20 + end; + printf("0x%02x:", flags); + for (i = 0; i < check_size; i++) { + if (frame[i] != testvec[vector].frame_data[frame_data_pos + i]) { + printf(" [0x%02x!=0x%02x]", frame[i], + testvec[vector].frame_data[frame_data_pos + i]); + ret++; + } else { + printf(" 0x%02x", frame[i]); + } } + printf("\n"); - freedv_data_channel_destroy(fdc); + if (flags != testvec[vector].flags[frame_data_pos / frame_size]) { + printf("FAIL: Flags byte does not match 0x%02x != 0x%02x\n", flags, + testvec[vector].flags[frame_data_pos / frame_size]); + ret++; + } + + freedv_data_channel_rx_frame(fdc, frame, frame_size, from, bcast, crc, end); + + frame_data_pos += frame_size; - printf("--------------------------------------\n"); - printf("tfreedv_data_channel test result: "); - if (ret) { - printf("Failed %d\n", ret); + nr_frames = freedv_data_get_n_tx_frames(fdc, frame_size); + + if (frame_data_pos >= testvec[vector].frame_data_size) { + if (nr_frames) { + printf("FAIL: nr_frames is not zero: %d\n", nr_frames); + ret++; + } + vector++; + frame_data_pos = 0; + if (!rx_done) { + printf("FAIL: RX callback not executed\n"); + ret++; + } + rx_done = 0; } else { - printf("Passed\n"); + int vec_frames = (testvec[vector].frame_data_size - frame_data_pos); + vec_frames /= frame_size; + vec_frames++; + if (nr_frames != vec_frames) { + printf("FAIL: nr_frames != vec_frames: %d != %d\n", nr_frames, + vec_frames); + ret++; + } } + } + + freedv_data_channel_destroy(fdc); + + printf("--------------------------------------\n"); + printf("tfreedv_data_channel test result: "); + if (ret) { + printf("Failed %d\n", ret); + } else { + printf("Passed\n"); + } - return ret; + return ret; } diff --git a/unittest/tfsk.c b/unittest/tfsk.c index 35aa970..337a350 100644 --- a/unittest/tfsk.c +++ b/unittest/tfsk.c @@ -27,13 +27,14 @@ along with this program; if not, see . */ - //#define MODEMPROBE_ENABLE -#include "modem_probe.h" #include -/* Note: This is a dirty hack to force fsk.c to compile with modem probing enabled */ +#include "modem_probe.h" + +/* Note: This is a dirty hack to force fsk.c to compile with modem probing + * enabled */ #include "fsk.c" #define ST_BITS 10000 @@ -44,189 +45,190 @@ #define ST_EBNO 8 #define ST_M 2 -#define TEST_SELF_FULL 1 /* No-arg self test */ -#define TEST_MOD 2 /* Test modulator using in and out file */ -#define TEST_MOD_H 3 /* Test modulator using in and out file */ -#define TEST_DEMOD 4 /* Test demodulator using in and out file */ -#define TEST_DEMOD_H 5 /* Test demodulator using in and out file */ - - -int main(int argc,char *argv[]){ - struct FSK *fsk; - int Fs,Rs,f1,fs,M, lock_nin; - FILE *fin,*fout; - - uint8_t *bitbuf = NULL; - float *modbuf = NULL; - uint8_t *bitbufp; - float *modbufp; - - size_t bitbufsize = 0; - size_t modbufsize = 0; - - int test_type; - - int i; - - fin = NULL; - fout = NULL; - - /* Set up full self-test */ - if(argc == 1){ - test_type = TEST_SELF_FULL; - modem_probe_init("fsk2","fsk2_tfsk_log.txt"); - Fs = ST_FS; - Rs = ST_RS; - f1 = ST_F1; - fs = ST_Fs; - M = ST_M; - lock_nin = 0; - } else if (argc<10){ +#define TEST_SELF_FULL 1 /* No-arg self test */ +#define TEST_MOD 2 /* Test modulator using in and out file */ +#define TEST_MOD_H 3 /* Test modulator using in and out file */ +#define TEST_DEMOD 4 /* Test demodulator using in and out file */ +#define TEST_DEMOD_H 5 /* Test demodulator using in and out file */ + +int main(int argc, char *argv[]) { + struct FSK *fsk; + int Fs, Rs, f1, fs, M, lock_nin; + FILE *fin, *fout; + + uint8_t *bitbuf = NULL; + float *modbuf = NULL; + uint8_t *bitbufp; + float *modbufp; + + size_t bitbufsize = 0; + size_t modbufsize = 0; + + int test_type; + + int i; + + fin = NULL; + fout = NULL; + + /* Set up full self-test */ + if (argc == 1) { + test_type = TEST_SELF_FULL; + modem_probe_init("fsk2", "fsk2_tfsk_log.txt"); + Fs = ST_FS; + Rs = ST_RS; + f1 = ST_F1; + fs = ST_Fs; + M = ST_M; + lock_nin = 0; + } else if (argc < 10) { /* Not running any test */ - printf("Usage: %s [(M|D|DX) Mode TXFreq1 TXFreqSpace SampleRate SymbolRate lock_nin InputFile OutputFile OctaveLogFile]\n",argv[0]); - exit(1); - } else { + printf( + "Usage: %s [(M|D|DX) Mode TXFreq1 TXFreqSpace SampleRate SymbolRate " + "lock_nin InputFile OutputFile OctaveLogFile]\n", + argv[0]); + exit(1); + } else { /* Running stim-drivin test */ - /* Mod test */ - if(strcmp(argv[1],"MX")==0){ - test_type = TEST_MOD_H; - } else if(strcmp(argv[1],"M")==0 || strcmp(argv[1],"m")==0) { - test_type = TEST_MOD; - /* Demod test */ - } else if(strcmp(argv[1],"DX")==0) { - test_type = TEST_DEMOD_H; - } else if(strcmp(argv[1],"D")==0 || strcmp(argv[1],"d")==0) { - test_type = TEST_DEMOD; - } else { - printf("Must specify mod or demod test with M or D\n"); - exit(1); - } - /* Extract parameters */ - M = atoi(argv[2]); - f1 = atoi(argv[3]); - fs = atoi(argv[4]); - Fs = atoi(argv[5]); - Rs = atoi(argv[6]); - lock_nin = atoi(argv[7]); - - /* Open files */ - fin = fopen(argv[8],"r"); - fout = fopen(argv[9],"w"); - - if(fin == NULL || fout == NULL){ - printf("Couldn't open test vector files\n"); - exit(1); - } - /* Init modem probing */ - modem_probe_init("fsk",argv[10]); - + /* Mod test */ + if (strcmp(argv[1], "MX") == 0) { + test_type = TEST_MOD_H; + } else if (strcmp(argv[1], "M") == 0 || strcmp(argv[1], "m") == 0) { + test_type = TEST_MOD; + /* Demod test */ + } else if (strcmp(argv[1], "DX") == 0) { + test_type = TEST_DEMOD_H; + } else if (strcmp(argv[1], "D") == 0 || strcmp(argv[1], "d") == 0) { + test_type = TEST_DEMOD; + } else { + printf("Must specify mod or demod test with M or D\n"); + exit(1); } - - srand(1); - /* set up FSK */ - if(test_type == TEST_DEMOD_H || test_type == TEST_MOD_H){ - fsk = fsk_create_hbr(Fs,Rs,M,10,FSK_DEFAULT_NSYM,f1,fs); - if(test_type == TEST_DEMOD_H) - test_type = TEST_DEMOD; - else - test_type = TEST_MOD; - }else{ - fsk = fsk_create(Fs,Rs,M,f1,fs); + /* Extract parameters */ + M = atoi(argv[2]); + f1 = atoi(argv[3]); + fs = atoi(argv[4]); + Fs = atoi(argv[5]); + Rs = atoi(argv[6]); + lock_nin = atoi(argv[7]); + + /* Open files */ + fin = fopen(argv[8], "r"); + fout = fopen(argv[9], "w"); + + if (fin == NULL || fout == NULL) { + printf("Couldn't open test vector files\n"); + exit(1); } - fsk_set_freq_est_limits(fsk, 300, 2800); - fsk->lock_nin = lock_nin; - - /* Modulate! */ - if(test_type == TEST_MOD || test_type == TEST_SELF_FULL){ - /* Generate random bits for self test */ - if(test_type == TEST_SELF_FULL){ - bitbufsize = ST_BITS; - bitbuf = (uint8_t*) malloc(sizeof(uint8_t)*ST_BITS); - for(i=0; iNbits,fin) == fsk->Nbits){ - i++; - bitbufp+=fsk->Nbits; - /* Make sure we don't break the buffer */ - if(i*fsk->Nbits > bitbufsize){ - bitbuf = realloc(bitbuf,sizeof(uint8_t)*(bitbufsize+fsk->Nbits)); - bitbufsize += fsk->Nbits; - } - } + /* Init modem probing */ + modem_probe_init("fsk", argv[10]); + } + + srand(1); + /* set up FSK */ + if (test_type == TEST_DEMOD_H || test_type == TEST_MOD_H) { + fsk = fsk_create_hbr(Fs, Rs, M, 10, FSK_DEFAULT_NSYM, f1, fs); + if (test_type == TEST_DEMOD_H) + test_type = TEST_DEMOD; + else + test_type = TEST_MOD; + } else { + fsk = fsk_create(Fs, Rs, M, f1, fs); + } + fsk_set_freq_est_limits(fsk, 300, 2800); + fsk->lock_nin = lock_nin; + + /* Modulate! */ + if (test_type == TEST_MOD || test_type == TEST_SELF_FULL) { + /* Generate random bits for self test */ + if (test_type == TEST_SELF_FULL) { + bitbufsize = ST_BITS; + bitbuf = (uint8_t *)malloc(sizeof(uint8_t) * ST_BITS); + for (i = 0; i < ST_BITS; i++) { + /* Generate a randomish bit */ + bitbuf[i] = (uint8_t)(rand() & 0x01); + } + } else { /* Load bits from a file */ + /* Figure out how many bits are in the input file */ + fseek(fin, 0L, SEEK_END); + bitbufsize = ftell(fin); + fseek(fin, 0L, SEEK_SET); + bitbuf = malloc(sizeof(uint8_t) * bitbufsize); + i = 0; + /* Read in some bits */ + bitbufp = bitbuf; + while (fread(bitbufp, sizeof(uint8_t), fsk->Nbits, fin) == fsk->Nbits) { + i++; + bitbufp += fsk->Nbits; + /* Make sure we don't break the buffer */ + if (i * fsk->Nbits > bitbufsize) { + bitbuf = realloc(bitbuf, sizeof(uint8_t) * (bitbufsize + fsk->Nbits)); + bitbufsize += fsk->Nbits; } - /* Allocate modulation buffer */ - modbuf = (float*)malloc(sizeof(float)*(bitbufsize/fsk->Nbits)*fsk->N*4); - modbufsize = (bitbufsize/fsk->Nbits)*fsk->N; - /* Do the modulation */ - modbufp = modbuf; - bitbufp = bitbuf; - while( bitbufp < bitbuf+bitbufsize){ - fsk_mod(fsk, modbufp, bitbufp, fsk->Nbits); - modbufp += fsk->N; - bitbufp += fsk->Nbits; - } - /* For a mod-only test, write out the result */ - if(test_type == TEST_MOD){ - fwrite(modbuf,sizeof(float),modbufsize,fout); - free(modbuf); - } - /* Free bit buffer */ - free(bitbuf); + } } - - /* Now test the demod */ - if(test_type == TEST_DEMOD || test_type == TEST_SELF_FULL){ - free(modbuf); - modbuf = malloc(sizeof(float)*(fsk->N+fsk->Ts*2)); - bitbuf = malloc(sizeof(uint8_t)*fsk->Nbits); - /* Demod-only test */ - if(test_type == TEST_DEMOD){ - while( fread(modbuf,sizeof(float),fsk_nin(fsk),fin) == fsk_nin(fsk) ){ - int n = fsk_nin(fsk); - COMP modbuf_comp[n]; - for(i=0; iNbits,fout); - } - } - /* Demod after channel imp. and mod */ - else{ - bitbufp = bitbuf; - modbufp = modbuf; - while( modbufp < modbuf + modbufsize){ - int n = fsk_nin(fsk); - COMP modbuf_comp[n]; - for(i=0; iNbits) * fsk->N * 4); + modbufsize = (bitbufsize / fsk->Nbits) * fsk->N; + /* Do the modulation */ + modbufp = modbuf; + bitbufp = bitbuf; + while (bitbufp < bitbuf + bitbufsize) { + fsk_mod(fsk, modbufp, bitbufp, fsk->Nbits); + modbufp += fsk->N; + bitbufp += fsk->Nbits; + } + /* For a mod-only test, write out the result */ + if (test_type == TEST_MOD) { + fwrite(modbuf, sizeof(float), modbufsize, fout); + free(modbuf); + } + /* Free bit buffer */ + free(bitbuf); + } + + /* Now test the demod */ + if (test_type == TEST_DEMOD || test_type == TEST_SELF_FULL) { + free(modbuf); + modbuf = malloc(sizeof(float) * (fsk->N + fsk->Ts * 2)); + bitbuf = malloc(sizeof(uint8_t) * fsk->Nbits); + /* Demod-only test */ + if (test_type == TEST_DEMOD) { + while (fread(modbuf, sizeof(float), fsk_nin(fsk), fin) == fsk_nin(fsk)) { + int n = fsk_nin(fsk); + COMP modbuf_comp[n]; + for (i = 0; i < n; i++) { + modbuf_comp[i].real = modbuf[i]; + modbuf_comp[i].imag = 0.0; } - free(bitbuf); + fsk_demod(fsk, bitbuf, modbuf_comp); + fwrite(bitbuf, sizeof(uint8_t), fsk->Nbits, fout); + } } - - modem_probe_close(); - if(test_type == TEST_DEMOD || test_type == TEST_MOD){ - fclose(fin); - fclose(fout); + /* Demod after channel imp. and mod */ + else { + bitbufp = bitbuf; + modbufp = modbuf; + while (modbufp < modbuf + modbufsize) { + int n = fsk_nin(fsk); + COMP modbuf_comp[n]; + for (i = 0; i < n; i++) { + modbuf_comp[i].real = modbuf[i]; + modbuf_comp[i].imag = 0.0; + } + fsk_demod(fsk, bitbuf, modbuf_comp); + modbufp += fsk_nin(fsk); + } } - fsk_destroy(fsk); - exit(0); + free(bitbuf); + } + + modem_probe_close(); + if (test_type == TEST_DEMOD || test_type == TEST_MOD) { + fclose(fin); + fclose(fout); + } + fsk_destroy(fsk); + exit(0); } - diff --git a/unittest/tfsk_llr.c b/unittest/tfsk_llr.c index c32c592..5929452 100644 --- a/unittest/tfsk_llr.c +++ b/unittest/tfsk_llr.c @@ -8,14 +8,15 @@ \*---------------------------------------------------------------------------*/ -#include #include +#include + #include "mpdecode_core.h" -#define M 4 -#define BPS 2 -#define NSYM 5 -#define V_EST 2 +#define M 4 +#define BPS 2 +#define NSYM 5 +#define V_EST 2 #define SNR_EST 10 /* Generated test vectors with: @@ -27,40 +28,33 @@ /* one col per symbol: 0 1 2 3 4 */ - float rx_filt[] = { - 1.0, 0.0, 0.0, 0.0, 1.0, /* filter 0 */ - 0.0, 1.0, 0.0, 0.0, 0.0, /* filter 1 */ - 0.0, 0.0, 1.0, 0.0, 0.0, /* filter 2 */ - 0.0, 0.0, 0.0, 1.0, 0.0 /* filter 3 */ +float rx_filt[] = { + 1.0, 0.0, 0.0, 0.0, 1.0, /* filter 0 */ + 0.0, 1.0, 0.0, 0.0, 0.0, /* filter 1 */ + 0.0, 0.0, 1.0, 0.0, 0.0, /* filter 2 */ + 0.0, 0.0, 0.0, 1.0, 0.0 /* filter 3 */ }; -float llrs_target[] = { - 7.3252, 7.3252, /* bit 0, 1 */ - 7.3252, -7.3252, /* 2, 3, ... */ - -7.3252, 7.3252, - -7.3252, -7.3252, - 7.3252, 7.3252 -}; +float llrs_target[] = {7.3252, 7.3252, /* bit 0, 1 */ + 7.3252, -7.3252, /* 2, 3, ... */ + -7.3252, 7.3252, -7.3252, -7.3252, 7.3252, 7.3252}; -int main(void) { - float llrs[BPS*NSYM] = {0}; - - fsk_rx_filt_to_llrs(llrs, rx_filt, V_EST, SNR_EST, M, NSYM); +int main(void) { + float llrs[BPS * NSYM] = {0}; - float error = 0.0; - for(int i=0; i + #include "freedv_api.h" -int main(void) { - printf("%s\n", freedv_get_hash()); - return 0; +int main(void) { + printf("%s\n", freedv_get_hash()); + return 0; } - - diff --git a/unittest/tnewamp1.c b/unittest/tnewamp1.c index f9b13d2..297f12d 100644 --- a/unittest/tnewamp1.c +++ b/unittest/tnewamp1.c @@ -28,274 +28,268 @@ along with this program; if not, see . */ -#include "defines.h" #include "codec2_fft.h" -#include "sine.h" -#include "nlp.h" +#include "defines.h" #include "dump.h" -#include "octave.h" #include "newamp1.h" +#include "nlp.h" +#include "octave.h" #include "quantise.h" +#include "sine.h" #define FRAMES 300 int main(int argc, char *argv[]) { - int Fs = 8000; - C2CONST c2const = c2const_create(Fs, N_S); - int n_samp = c2const.n_samp; - int m_pitch = c2const.m_pitch; - short buf[n_samp]; /* input/output buffer */ - float Sn[m_pitch]; /* float input speech samples */ - COMP Sw[FFT_ENC]; /* DFT of Sn[] */ - codec2_fft_cfg fft_fwd_cfg; /* fwd FFT states */ - float w[m_pitch]; /* time domain hamming window */ - float W[FFT_ENC]; /* DFT of w[] */ - MODEL model; - void *nlp_states; - codec2_fft_cfg phase_fft_fwd_cfg, phase_fft_inv_cfg; - float pitch, prev_f0; - int i,m,f,k; - - if (argc != 2) { - printf("usage: ./tnewamp1 RawFile\n"); - exit(1); + int Fs = 8000; + C2CONST c2const = c2const_create(Fs, N_S); + int n_samp = c2const.n_samp; + int m_pitch = c2const.m_pitch; + short buf[n_samp]; /* input/output buffer */ + float Sn[m_pitch]; /* float input speech samples */ + COMP Sw[FFT_ENC]; /* DFT of Sn[] */ + codec2_fft_cfg fft_fwd_cfg; /* fwd FFT states */ + float w[m_pitch]; /* time domain hamming window */ + float W[FFT_ENC]; /* DFT of w[] */ + MODEL model; + void *nlp_states; + codec2_fft_cfg phase_fft_fwd_cfg, phase_fft_inv_cfg; + float pitch, prev_f0; + int i, m, f, k; + + if (argc != 2) { + printf("usage: ./tnewamp1 RawFile\n"); + exit(1); + } + nlp_states = nlp_create(&c2const); + prev_f0 = 1.0 / P_MAX_S; + fft_fwd_cfg = codec2_fft_alloc(FFT_ENC, 0, NULL, NULL); + make_analysis_window(&c2const, fft_fwd_cfg, w, W); + + phase_fft_fwd_cfg = codec2_fft_alloc(NEWAMP1_PHASE_NFFT, 0, NULL, NULL); + phase_fft_inv_cfg = codec2_fft_alloc(NEWAMP1_PHASE_NFFT, 1, NULL, NULL); + + for (i = 0; i < m_pitch; i++) { + Sn[i] = 1.0; + } + + int K = 20; + float rate_K_sample_freqs_kHz[K]; + float model_octave[FRAMES][MAX_AMP + 2]; // model params in matrix format, + // useful for C <-> Octave + float rate_K_surface[FRAMES][K]; // rate K vecs for each frame, form a + // surface that makes pretty graphs + float rate_K_surface_no_mean[FRAMES][K]; // mean removed surface + float rate_K_surface_no_mean_[FRAMES][K]; // quantised mean removed surface + float mean[FRAMES]; + float mean_[FRAMES]; + float rate_K_surface_[FRAMES][K]; // quantised rate K vecs for each frame + float interpolated_surface_[FRAMES][K]; // dec/interpolated surface + // int voicing[FRAMES]; + int voicing_[FRAMES]; + float model_octave_[FRAMES][MAX_AMP + 2]; + COMP H[FRAMES][MAX_AMP]; + int indexes[FRAMES][NEWAMP1_N_INDEXES]; + float se = 0.0; + float eq[K]; + + for (k = 0; k < K; k++) eq[k] = 0.0; + + for (f = 0; f < FRAMES; f++) { + for (m = 0; m < MAX_AMP + 2; m++) { + model_octave[f][m] = 0.0; + model_octave_[f][m] = 0.0; } - nlp_states = nlp_create(&c2const); - prev_f0 = 1.0/P_MAX_S; - fft_fwd_cfg = codec2_fft_alloc(FFT_ENC, 0, NULL, NULL); - make_analysis_window(&c2const,fft_fwd_cfg, w, W); + for (m = 0; m < MAX_AMP; m++) { + H[f][m].real = 0.0; + H[f][m].imag = 0.0; + } + for (k = 0; k < K; k++) interpolated_surface_[f][k] = 0.0; + voicing_[f] = 0; + } - phase_fft_fwd_cfg = codec2_fft_alloc(NEWAMP1_PHASE_NFFT, 0, NULL, NULL); - phase_fft_inv_cfg = codec2_fft_alloc(NEWAMP1_PHASE_NFFT, 1, NULL, NULL); + mel_sample_freqs_kHz(rate_K_sample_freqs_kHz, K, ftomel(200.0), + ftomel(3700.0)); - for(i=0; i Octave - float rate_K_surface[FRAMES][K]; // rate K vecs for each frame, form a surface that makes pretty graphs - float rate_K_surface_no_mean[FRAMES][K]; // mean removed surface - float rate_K_surface_no_mean_[FRAMES][K]; // quantised mean removed surface - float mean[FRAMES]; - float mean_[FRAMES]; - float rate_K_surface_[FRAMES][K]; // quantised rate K vecs for each frame - float interpolated_surface_[FRAMES][K]; // dec/interpolated surface - //int voicing[FRAMES]; - int voicing_[FRAMES]; - float model_octave_[FRAMES][MAX_AMP+2]; - COMP H[FRAMES][MAX_AMP]; - int indexes[FRAMES][NEWAMP1_N_INDEXES]; - float se = 0.0; - float eq[K]; - - for(k=0; k= M) { + for (i = 0; i < M; i++) { + for (k = 0; k < K; k++) { + interpolated_surface_[f - M + i][k] = a_interpolated_surface_[i][k]; } + } + + /* store test vectors */ - fprintf(stderr,"\n\n"); - #endif - - //if (f == 7) - // exit(0); - - /* with f == 0, we don't store output, but memories are updated, helps to match - what happens in Codec 2 mode */ - - if (f >= M) { - for(i=0; i tnewamp1(\"../path/to/build_linux/src/hts1a\", \"../path/to/build_linux/unittest\")\n"); - return 0; + } + + fclose(fin); + + /* save vectors in Octave format */ + + FILE *fout = fopen("tnewamp1_out.txt", "wt"); + assert(fout != NULL); + fprintf(fout, "# Created by tnewamp1.c\n"); + octave_save_float(fout, "rate_K_surface_c", (float *)rate_K_surface, FRAMES, + K, K); + octave_save_float(fout, "mean_c", (float *)mean, 1, FRAMES, 1); + octave_save_float(fout, "eq_c", eq, 1, K, K); + octave_save_float(fout, "rate_K_surface_no_mean_c", + (float *)rate_K_surface_no_mean, FRAMES, K, K); + octave_save_float(fout, "rate_K_surface_no_mean__c", + (float *)rate_K_surface_no_mean_, FRAMES, K, K); + octave_save_float(fout, "mean__c", (float *)mean_, FRAMES, 1, 1); + octave_save_float(fout, "rate_K_surface__c", (float *)rate_K_surface_, FRAMES, + K, K); + octave_save_float(fout, "interpolated_surface__c", + (float *)interpolated_surface_, FRAMES, K, K); + octave_save_float(fout, "model_c", (float *)model_octave, FRAMES, MAX_AMP + 2, + MAX_AMP + 2); + octave_save_float(fout, "model__c", (float *)model_octave_, FRAMES, + MAX_AMP + 2, MAX_AMP + 2); + octave_save_int(fout, "voicing__c", (int *)voicing_, 1, FRAMES); + octave_save_complex(fout, "H_c", (COMP *)H, FRAMES, MAX_AMP, MAX_AMP); + fclose(fout); + + printf( + "Done! Now run\n octave:1> " + "tnewamp1(\"../path/to/build_linux/src/hts1a\", " + "\"../path/to/build_linux/unittest\")\n"); + return 0; } - diff --git a/unittest/tnlp.c b/unittest/tnlp.c index 82f0a96..4c64f23 100644 --- a/unittest/tnlp.c +++ b/unittest/tnlp.c @@ -25,19 +25,18 @@ along with this program; if not, see . */ - -#include +#include #include +#include #include -#include #include "defines.h" #include "dump.h" -#include "sine.h" -#include "nlp.h" #include "kiss_fft.h" +#include "nlp.h" +#include "sine.h" -int frames; +int frames; /*---------------------------------------------------------------------------*\ @@ -49,16 +48,15 @@ int frames; \*---------------------------------------------------------------------------*/ -int switch_present(sw,argc,argv) - char sw[]; /* switch in string form */ - int argc; /* number of command line arguments */ - char *argv[]; /* array of command line arguments in string form */ +int switch_present(sw, argc, argv) +char sw[]; /* switch in string form */ +int argc; /* number of command line arguments */ +char *argv[]; /* array of command line arguments in string form */ { - int i; /* loop variable */ + int i; /* loop variable */ - for(i=1; i +#include +#include +#include +#include #include #include -#include #include -#include -#include -#include -#include "ofdm_internal.h" +#include "HRA_112_112.h" /* generated by ldpc_fsk_lib.m:ldpc_decode() */ #include "codec2_ofdm.h" -#include "octave.h" -#include "test_bits_ofdm.h" #include "comp_prim.h" #include "mpdecode_core.h" +#include "octave.h" +#include "ofdm_internal.h" +#include "test_bits_ofdm.h" -#include "HRA_112_112.h" /* generated by ldpc_fsk_lib.m:ldpc_decode() */ - -#define NFRAMES 10 +#define NFRAMES 10 #define SAMPLE_CLOCK_OFFSET_PPM 100 -#define FOFF_HZ 0.5f +#define FOFF_HZ 0.5f -#define ASCALE (2E5f * 1.1491f / 2.0f) /* scale from shorts back to floats */ +#define ASCALE (2E5f * 1.1491f / 2.0f) /* scale from shorts back to floats */ -#define CODED_BITSPERFRAME 224 /* number of LDPC codeword bits/frame */ +#define CODED_BITSPERFRAME 224 /* number of LDPC codeword bits/frame */ /* QPSK constellation for symbol likelihood calculations */ static COMP S_matrix[] = { - { 1.0f, 0.0f}, - { 0.0f, 1.0f}, - { 0.0f, -1.0f}, - {-1.0f, 0.0f} -}; + {1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}}; /* constants we use a lot and don't want to have to deference all the time */ -static float ofdm_tx_centre; /* TX Center frequency */ -static float ofdm_rx_centre; /* RX Center frequency */ -static float ofdm_fs; /* Sample rate */ -static float ofdm_ts; /* Symbol cycle time */ -static float ofdm_rs; /* Symbol rate */ -static float ofdm_tcp; /* Cyclic prefix duration */ -static float ofdm_timing_mx_thresh; /* See 700D Part 4 Acquisition blog post and ofdm_dev.m routines for how this was set */ - -static int ofdm_nc; /* NS-1 data symbols between pilots */ +static float ofdm_tx_centre; /* TX Center frequency */ +static float ofdm_rx_centre; /* RX Center frequency */ +static float ofdm_fs; /* Sample rate */ +static float ofdm_ts; /* Symbol cycle time */ +static float ofdm_rs; /* Symbol rate */ +static float ofdm_tcp; /* Cyclic prefix duration */ +static float + ofdm_timing_mx_thresh; /* See 700D Part 4 Acquisition blog post and + ofdm_dev.m routines for how this was set */ + +static int ofdm_nc; /* NS-1 data symbols between pilots */ static int ofdm_ns; -static int ofdm_bps; /* Bits per symbol */ -static int ofdm_m; /* duration of each symbol in samples */ -static int ofdm_ncp; /* duration of CP in samples */ +static int ofdm_bps; /* Bits per symbol */ +static int ofdm_m; /* duration of each symbol in samples */ +static int ofdm_ncp; /* duration of CP in samples */ static int ofdm_ftwindowwidth; static int ofdm_bitsperframe; @@ -85,8 +82,9 @@ static int ofdm_samplesperframe; static int ofdm_samplespersymbol; static int ofdm_max_samplesperframe; static int ofdm_nrxbuf; -static int ofdm_ntxtbits; /* reserve bits/frame for auxiliary text information */ -static int ofdm_nuwbits; /* Unique word, used for positive indication of lock */ +static int + ofdm_ntxtbits; /* reserve bits/frame for auxiliary text information */ +static int ofdm_nuwbits; /* Unique word, used for positive indication of lock */ /*---------------------------------------------------------------------------*\ @@ -100,27 +98,29 @@ static int ofdm_nuwbits; /* Unique word, used for positive indication \*---------------------------------------------------------------------------*/ static int fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm) { - double f; - double tin = 0.0; - double step = 1.0 + sample_rate_ppm/1E6; - int t1, t2; - int tout = 0; - - while (tin < (double) (n-1)) { - t1 = (int) floor(tin); - t2 = (int) ceil(tin); - assert(t2 < n); - f = tin - (double) t1; - - out[tout].real = ((double)1.0-f)*(double)in[t1].real + f*(double)in[t2].real; - out[tout].imag = ((double)1.0-f)*(double)in[t1].imag + f*(double)in[t2].imag; - - tin += step; - tout++; - //printf("tin: %f tout: %d f: %f\n", tin, tout, f); - } - - return tout; + double f; + double tin = 0.0; + double step = 1.0 + sample_rate_ppm / 1E6; + int t1, t2; + int tout = 0; + + while (tin < (double)(n - 1)) { + t1 = (int)floor(tin); + t2 = (int)ceil(tin); + assert(t2 < n); + f = tin - (double)t1; + + out[tout].real = + ((double)1.0 - f) * (double)in[t1].real + f * (double)in[t2].real; + out[tout].imag = + ((double)1.0 - f) * (double)in[t1].imag + f * (double)in[t2].imag; + + tin += step; + tout++; + // printf("tin: %f tout: %d f: %f\n", tin, tout, f); + } + + return tout; } /*---------------------------------------------------------------------------*\ @@ -134,450 +134,493 @@ static int fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm) { \*---------------------------------------------------------------------------*/ -static void freq_shift(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, COMP *foff_phase_rect, int nin) { - float temp = (TAU * foff / ofdm_fs); - COMP foff_rect = { cosf(temp), sinf(temp) }; - int i; +static void freq_shift(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, + COMP *foff_phase_rect, int nin) { + float temp = (TAU * foff / ofdm_fs); + COMP foff_rect = {cosf(temp), sinf(temp)}; + int i; - for (i = 0; i < nin; i++) { - *foff_phase_rect = cmult(*foff_phase_rect, foff_rect); - rx_fdm_fcorr[i] = cmult(rx_fdm[i], *foff_phase_rect); - } + for (i = 0; i < nin; i++) { + *foff_phase_rect = cmult(*foff_phase_rect, foff_rect); + rx_fdm_fcorr[i] = cmult(rx_fdm[i], *foff_phase_rect); + } - /* normalise digital oscillator as the magnitude can drift over time */ + /* normalise digital oscillator as the magnitude can drift over time */ - float mag = cabsolute(*foff_phase_rect); - foff_phase_rect->real /= mag; - foff_phase_rect->imag /= mag; + float mag = cabsolute(*foff_phase_rect); + foff_phase_rect->real /= mag; + foff_phase_rect->imag /= mag; } -int main(int argc, char *argv[]) -{ - int opt_Nc = 0; - int ldpc_enable = 1; - struct OFDM *ofdm; - struct OFDM_CONFIG *ofdm_config; - - static struct option long_options[] = { - {"nc", required_argument, 0, 'n'}, - {"noldpc", no_argument, 0, 'l'}, - {0, 0, 0, 0} - }; - - int opt_index = 0; char c; - - while ((c = getopt_long (argc, argv, "n:l", long_options, &opt_index)) != -1) { - switch (c) { - case 'n': - opt_Nc = atoi(optarg); - fprintf(stderr, "Nc = %d\n", opt_Nc); - break; - case 'l': - ldpc_enable = 0; - fprintf(stderr, "LDPC disabled\n"); - break; - default: - fprintf(stderr,"usage: %s [Options]:\n [-l --noldpc]\n [-n --nc NumberoFCarriers]\n", argv[0]); - exit(1); - } +int main(int argc, char *argv[]) { + int opt_Nc = 0; + int ldpc_enable = 1; + struct OFDM *ofdm; + struct OFDM_CONFIG *ofdm_config; + + static struct option long_options[] = {{"nc", required_argument, 0, 'n'}, + {"noldpc", no_argument, 0, 'l'}, + {0, 0, 0, 0}}; + + int opt_index = 0; + char c; + + while ((c = getopt_long(argc, argv, "n:l", long_options, &opt_index)) != -1) { + switch (c) { + case 'n': + opt_Nc = atoi(optarg); + fprintf(stderr, "Nc = %d\n", opt_Nc); + break; + case 'l': + ldpc_enable = 0; + fprintf(stderr, "LDPC disabled\n"); + break; + default: + fprintf(stderr, + "usage: %s [Options]:\n [-l --noldpc]\n [-n --nc " + "NumberoFCarriers]\n", + argv[0]); + exit(1); } + } + + // init once to get a copy of default config params + + ofdm = ofdm_create(NULL); + assert(ofdm != NULL); + struct OFDM_CONFIG ofdm_config_default; + memcpy(&ofdm_config_default, ofdm_get_config_param(ofdm), + sizeof(struct OFDM_CONFIG)); + ofdm_destroy(ofdm); + + // now do a little customisation on default config, and re-create modem + // instance + + if (opt_Nc) ofdm_config_default.nc = opt_Nc; + // printf("ofdm_create() 2\n"); + ofdm = ofdm_create(&ofdm_config_default); + assert(ofdm != NULL); + ofdm_config = ofdm_get_config_param(ofdm); + ofdm_set_tx_bpf(ofdm, false); + + // same levels as Octave sim + ofdm->amp_scale = 1.0; + + // make local copies for convenience + ofdm_tx_centre = ofdm_config->tx_centre; + ofdm_rx_centre = ofdm_config->rx_centre; + ofdm_fs = ofdm_config->fs; + ofdm_ts = ofdm_config->ts; + ofdm_rs = ofdm_config->rs; + ofdm_tcp = ofdm_config->tcp; + ofdm_timing_mx_thresh = ofdm_config->timing_mx_thresh; + ofdm_nc = ofdm_config->nc; + ofdm_ns = ofdm_config->ns; + ofdm_bps = ofdm_config->bps; + ofdm_m = (int)(ofdm_config->fs / ofdm_config->rs); + ofdm_ncp = (int)(ofdm_config->tcp * ofdm_config->fs); + ofdm_ftwindowwidth = ofdm_config->ftwindowwidth; + ofdm_bitsperframe = ofdm_get_bits_per_frame(ofdm); + ofdm_rowsperframe = ofdm_bitsperframe / (ofdm_config->nc * ofdm_config->bps); + ofdm_samplesperframe = ofdm_get_samples_per_frame(ofdm); + ofdm_samplespersymbol = (ofdm->m + ofdm->ncp); + ofdm_max_samplesperframe = ofdm_get_max_samples_per_frame(ofdm); + ofdm_nrxbuf = ofdm->nrxbuf; + ofdm_ntxtbits = ofdm_config->txtbits; + ofdm_nuwbits = ofdm_config->nuwbits; + + int tx_bits[ofdm_samplesperframe]; + COMP tx[ofdm_samplesperframe]; /* one frame of tx samples */ + + int rx_bits[ofdm_bitsperframe]; /* one frame of rx bits */ + printf("Nc = %d ofdm_bitsperframe: %d\n", ofdm_nc, ofdm_bitsperframe); + + /* log arrays */ + + int tx_bits_log[ofdm_bitsperframe * NFRAMES]; + COMP tx_log[ofdm_samplesperframe * NFRAMES]; + COMP rx_log[ofdm_samplesperframe * NFRAMES]; + COMP rxbuf_in_log[ofdm_max_samplesperframe * NFRAMES]; + COMP rxbuf_log[ofdm_nrxbuf * NFRAMES]; + COMP rx_sym_log[(ofdm_ns + 3) * NFRAMES][ofdm_nc + 2]; + float phase_est_pilot_log[ofdm_rowsperframe * NFRAMES][ofdm_nc]; + COMP rx_np_log[ofdm_rowsperframe * ofdm_nc * NFRAMES]; + float rx_amp_log[ofdm_rowsperframe * ofdm_nc * NFRAMES]; + float foff_hz_log[NFRAMES]; + int rx_bits_log[ofdm_bitsperframe * NFRAMES]; + int timing_est_log[NFRAMES]; + int timing_valid_log[NFRAMES]; + float timing_mx_log[NFRAMES]; + float coarse_foff_est_hz_log[NFRAMES]; + int sample_point_log[NFRAMES]; + float symbol_likelihood_log[(CODED_BITSPERFRAME / ofdm_bps) * + (1 << ofdm_bps) * NFRAMES]; + float bit_likelihood_log[CODED_BITSPERFRAME * NFRAMES]; + int detected_data_log[CODED_BITSPERFRAME * NFRAMES]; + float mean_amp_log[NFRAMES]; + float snr_log[NFRAMES]; + + FILE *fout; + int f, i, j; + + /* set up LDPC code */ + + struct LDPC ldpc; + + ldpc.max_iter = HRA_112_112_MAX_ITER; + ldpc.dec_type = 0; + ldpc.q_scale_factor = 1; + ldpc.r_scale_factor = 1; + ldpc.CodeLength = HRA_112_112_CODELENGTH; + ldpc.NumberParityBits = HRA_112_112_NUMBERPARITYBITS; + ldpc.NumberRowsHcols = HRA_112_112_NUMBERROWSHCOLS; + ldpc.max_row_weight = HRA_112_112_MAX_ROW_WEIGHT; + ldpc.max_col_weight = HRA_112_112_MAX_COL_WEIGHT; + ldpc.H_rows = (uint16_t *)HRA_112_112_H_rows; + ldpc.H_cols = (uint16_t *)HRA_112_112_H_cols; + + /* Main Loop + * ---------------------------------------------------------------------*/ + + for (f = 0; f < NFRAMES; f++) { + /* --------------------------------------------------------*\ + Mod + \*---------------------------------------------------------*/ - // init once to get a copy of default config params - - ofdm = ofdm_create(NULL); - assert(ofdm != NULL); - struct OFDM_CONFIG ofdm_config_default; - memcpy(&ofdm_config_default, ofdm_get_config_param(ofdm), sizeof(struct OFDM_CONFIG)); - ofdm_destroy(ofdm); - - // now do a little customisation on default config, and re-create modem instance - - if (opt_Nc) - ofdm_config_default.nc = opt_Nc; - //printf("ofdm_create() 2\n"); - ofdm = ofdm_create(&ofdm_config_default); - assert(ofdm != NULL); - ofdm_config = ofdm_get_config_param(ofdm); - ofdm_set_tx_bpf(ofdm, false); - - // same levels as Octave sim - ofdm->amp_scale = 1.0; - - // make local copies for convenience - ofdm_tx_centre = ofdm_config->tx_centre; - ofdm_rx_centre = ofdm_config->rx_centre; - ofdm_fs = ofdm_config->fs; - ofdm_ts = ofdm_config->ts; - ofdm_rs = ofdm_config->rs; - ofdm_tcp = ofdm_config->tcp; - ofdm_timing_mx_thresh = ofdm_config->timing_mx_thresh; - ofdm_nc = ofdm_config->nc; - ofdm_ns = ofdm_config->ns; - ofdm_bps = ofdm_config->bps; - ofdm_m = (int) (ofdm_config->fs / ofdm_config->rs); - ofdm_ncp = (int) (ofdm_config->tcp * ofdm_config->fs); - ofdm_ftwindowwidth = ofdm_config->ftwindowwidth; - ofdm_bitsperframe = ofdm_get_bits_per_frame(ofdm); - ofdm_rowsperframe = ofdm_bitsperframe / (ofdm_config->nc * ofdm_config->bps); - ofdm_samplesperframe = ofdm_get_samples_per_frame(ofdm); - ofdm_samplespersymbol = (ofdm->m + ofdm->ncp); - ofdm_max_samplesperframe = ofdm_get_max_samples_per_frame(ofdm); - ofdm_nrxbuf = ofdm->nrxbuf; - ofdm_ntxtbits = ofdm_config->txtbits; - ofdm_nuwbits = ofdm_config->nuwbits; - - int tx_bits[ofdm_samplesperframe]; - COMP tx[ofdm_samplesperframe]; /* one frame of tx samples */ - - int rx_bits[ofdm_bitsperframe]; /* one frame of rx bits */ - printf("Nc = %d ofdm_bitsperframe: %d\n", ofdm_nc, ofdm_bitsperframe); - - /* log arrays */ - - int tx_bits_log[ofdm_bitsperframe*NFRAMES]; - COMP tx_log[ofdm_samplesperframe*NFRAMES]; - COMP rx_log[ofdm_samplesperframe*NFRAMES]; - COMP rxbuf_in_log[ofdm_max_samplesperframe*NFRAMES]; - COMP rxbuf_log[ofdm_nrxbuf*NFRAMES]; - COMP rx_sym_log[(ofdm_ns + 3)*NFRAMES][ofdm_nc + 2]; - float phase_est_pilot_log[ofdm_rowsperframe*NFRAMES][ofdm_nc]; - COMP rx_np_log[ofdm_rowsperframe*ofdm_nc*NFRAMES]; - float rx_amp_log[ofdm_rowsperframe*ofdm_nc*NFRAMES]; - float foff_hz_log[NFRAMES]; - int rx_bits_log[ofdm_bitsperframe*NFRAMES]; - int timing_est_log[NFRAMES]; - int timing_valid_log[NFRAMES]; - float timing_mx_log[NFRAMES]; - float coarse_foff_est_hz_log[NFRAMES]; - int sample_point_log[NFRAMES]; - float symbol_likelihood_log[ (CODED_BITSPERFRAME/ofdm_bps) * (1<tx_uw[i]; - } - for(i=ofdm_nuwbits; i 16384; - uint8_t txt_bits[ofdm_ntxtbits]; - for (i = 0; i < ofdm_ntxtbits; i++) - txt_bits[i] = 0; - - uint8_t tx_bits_char[ofdm_bitsperframe]; - ofdm_assemble_qpsk_modem_packet(ofdm, tx_bits_char, payload_bits, txt_bits); - for(i=0; itx_uw[i]; + } + for (i = ofdm_nuwbits; i < ofdm_nuwbits + ofdm_ntxtbits; i++) { + tx_bits[i] = 0; + } - ofdm_mod(ofdm, (COMP*)tx, tx_bits); + if (ldpc_enable) { + unsigned char ibits[HRA_112_112_NUMBERROWSHCOLS]; + unsigned char pbits[HRA_112_112_NUMBERPARITYBITS]; + + assert(HRA_112_112_NUMBERROWSHCOLS == ldpc.CodeLength / 2); + for (i = 0; i < ldpc.CodeLength / 2; i++) { + ibits[i] = payload_data_bits[i]; + } + encode(&ldpc, ibits, pbits); + for (j = 0, i = ofdm_nuwbits + ofdm_ntxtbits; j < ldpc.CodeLength / 2; + i++, j++) { + tx_bits[i] = ibits[j]; + } + for (j = 0; j < ldpc.CodeLength / 2; i++, j++) { + tx_bits[i] = pbits[j]; + } + assert(i == ofdm_bitsperframe); + } else { + int Npayloadbits = ofdm_bitsperframe - (ofdm_nuwbits + ofdm_ntxtbits); + uint16_t r[Npayloadbits]; + uint8_t payload_bits[Npayloadbits]; + + ofdm_rand(r, Npayloadbits); + for (i = 0; i < Npayloadbits; i++) payload_bits[i] = r[i] > 16384; + uint8_t txt_bits[ofdm_ntxtbits]; + for (i = 0; i < ofdm_ntxtbits; i++) txt_bits[i] = 0; + + uint8_t tx_bits_char[ofdm_bitsperframe]; + ofdm_assemble_qpsk_modem_packet(ofdm, tx_bits_char, payload_bits, + txt_bits); + for (i = 0; i < ofdm_bitsperframe; i++) tx_bits[i] = tx_bits_char[i]; + } - /* tx vector logging */ + ofdm_mod(ofdm, (COMP *)tx, tx_bits); - memcpy(&tx_bits_log[ofdm_bitsperframe*f], tx_bits, sizeof(int)*ofdm_bitsperframe); - memcpy(&tx_log[ofdm_samplesperframe*f], tx, sizeof(COMP)*ofdm_samplesperframe); - } + /* tx vector logging */ - /* --------------------------------------------------------*\ - Channel - \*---------------------------------------------------------*/ + memcpy(&tx_bits_log[ofdm_bitsperframe * f], tx_bits, + sizeof(int) * ofdm_bitsperframe); + memcpy(&tx_log[ofdm_samplesperframe * f], tx, + sizeof(COMP) * ofdm_samplesperframe); + } - fs_offset(rx_log, tx_log, ofdm_samplesperframe*NFRAMES, SAMPLE_CLOCK_OFFSET_PPM); + /* --------------------------------------------------------*\ + Channel + \*---------------------------------------------------------*/ - COMP foff_phase_rect = {1.0f, 0.0f}; + fs_offset(rx_log, tx_log, ofdm_samplesperframe * NFRAMES, + SAMPLE_CLOCK_OFFSET_PPM); - freq_shift(rx_log, rx_log, FOFF_HZ, &foff_phase_rect, ofdm_samplesperframe * NFRAMES); + COMP foff_phase_rect = {1.0f, 0.0f}; - /* --------------------------------------------------------*\ - Demod - \*---------------------------------------------------------*/ + freq_shift(rx_log, rx_log, FOFF_HZ, &foff_phase_rect, + ofdm_samplesperframe * NFRAMES); - /* Init/pre-load rx with ideal timing so we can test with timing estimation disabled */ + /* --------------------------------------------------------*\ + Demod + \*---------------------------------------------------------*/ - int Nsam = ofdm_samplesperframe*NFRAMES; - int prx = 0; - int nin = ofdm_samplesperframe + 2*ofdm_samplespersymbol; + /* Init/pre-load rx with ideal timing so we can test with timing estimation + * disabled */ - int lnew; - COMP rxbuf_in[ofdm_max_samplesperframe]; + int Nsam = ofdm_samplesperframe * NFRAMES; + int prx = 0; + int nin = ofdm_samplesperframe + 2 * ofdm_samplespersymbol; + + int lnew; + COMP rxbuf_in[ofdm_max_samplesperframe]; #define FRONT_LOAD #ifdef FRONT_LOAD - for (i=0; irxbuf[ofdm_nrxbuf-nin+i] = rx_log[prx].real + rx_log[prx].imag * I; - } + for (i = 0; i < nin; i++, prx++) { + ofdm->rxbuf[ofdm_nrxbuf - nin + i] = + rx_log[prx].real + rx_log[prx].imag * I; + } #endif - int nin_tot = 0; + int nin_tot = 0; - /* disable estimators for initial testing */ + /* disable estimators for initial testing */ - ofdm_set_verbose(ofdm, false); - ofdm_set_timing_enable(ofdm, true); - ofdm_set_foff_est_enable(ofdm, true); - ofdm_set_phase_est_enable(ofdm, true); + ofdm_set_verbose(ofdm, false); + ofdm_set_timing_enable(ofdm, true); + ofdm_set_foff_est_enable(ofdm, true); + ofdm_set_phase_est_enable(ofdm, true); //#define TESTING_FILE #ifdef TESTING_FILE - FILE *fin=fopen("~/codec2-dev/octave/ofdm_test.raw", "rb"); - assert(fin != NULL); - int Nbitsperframe = ofdm_bitsperframe; - int Nmaxsamperframe = ofdm_max_samplesperframe; - short rx_scaled[Nmaxsamperframe]; + FILE *fin = fopen("~/codec2-dev/octave/ofdm_test.raw", "rb"); + assert(fin != NULL); + int Nbitsperframe = ofdm_bitsperframe; + int Nmaxsamperframe = ofdm_max_samplesperframe; + short rx_scaled[Nmaxsamperframe]; #endif - /* start this with something sensible otherwise LDPC decode fails in tofdm.m */ + /* start this with something sensible otherwise LDPC decode fails in tofdm.m + */ - ofdm->mean_amp = 1.0; + ofdm->mean_amp = 1.0; - for(f=0; frx_np[j]); - ldpc_codeword_symbols[i].imag = cimagf(ofdm->rx_np[j]); - } + for (i = 0, j = (ofdm_nuwbits + ofdm_ntxtbits) / ofdm_bps; + i < (CODED_BITSPERFRAME / ofdm_bps); i++, j++) { + ldpc_codeword_symbols[i].real = crealf(ofdm->rx_np[j]); + ldpc_codeword_symbols[i].imag = cimagf(ofdm->rx_np[j]); + } - float *ldpc_codeword_symbol_amps = &ofdm->rx_amp[(ofdm_nuwbits+ofdm_ntxtbits)/ofdm_bps]; + float *ldpc_codeword_symbol_amps = + &ofdm->rx_amp[(ofdm_nuwbits + ofdm_ntxtbits) / ofdm_bps]; - Demod2D(symbol_likelihood, ldpc_codeword_symbols, S_matrix, EsNo, ldpc_codeword_symbol_amps, ofdm->mean_amp, CODED_BITSPERFRAME/ofdm_bps); - Somap(bit_likelihood, symbol_likelihood, 1<mean_amp, + CODED_BITSPERFRAME / ofdm_bps); + Somap(bit_likelihood, symbol_likelihood, 1 << ofdm_bps, ofdm_bps, + CODED_BITSPERFRAME / ofdm_bps); - float llr[CODED_BITSPERFRAME]; - int parityCheckCount; + float llr[CODED_BITSPERFRAME]; + int parityCheckCount; + // fprintf(stderr, "\n"); + for (i = 0; i < CODED_BITSPERFRAME; i++) { + llr[i] = -bit_likelihood[i]; + // fprintf(stderr, "%f ", llr[i]); + } - // fprintf(stderr, "\n"); - for(i=0; irxbuf[i]); - rxbuf_log[ofdm_nrxbuf*f+i].imag = cimagf(ofdm->rxbuf[i]); - } + assert(nin_tot < ofdm_samplesperframe * NFRAMES); + memcpy(&rxbuf_in_log[nin_tot], rxbuf_in, sizeof(COMP) * nin); + nin_tot += nin; - for (i = 0; i < (ofdm_ns + 3); i++) { - for (j = 0; j < (ofdm_nc + 2); j++) { - rx_sym_log[(ofdm_ns + 3)*f+i][j].real = crealf(ofdm->rx_sym[i][j]); - rx_sym_log[(ofdm_ns + 3)*f+i][j].imag = cimagf(ofdm->rx_sym[i][j]); - } - } + for (i = 0; i < ofdm_nrxbuf; i++) { + rxbuf_log[ofdm_nrxbuf * f + i].real = crealf(ofdm->rxbuf[i]); + rxbuf_log[ofdm_nrxbuf * f + i].imag = cimagf(ofdm->rxbuf[i]); + } - /* note corrected phase (rx no phase) is one big linear array for frame */ + for (i = 0; i < (ofdm_ns + 3); i++) { + for (j = 0; j < (ofdm_nc + 2); j++) { + rx_sym_log[(ofdm_ns + 3) * f + i][j].real = crealf(ofdm->rx_sym[i][j]); + rx_sym_log[(ofdm_ns + 3) * f + i][j].imag = cimagf(ofdm->rx_sym[i][j]); + } + } - for (i = 0; i < ofdm_rowsperframe*ofdm_nc; i++) { - rx_np_log[ofdm_rowsperframe*ofdm_nc*f + i].real = crealf(ofdm->rx_np[i]); - rx_np_log[ofdm_rowsperframe*ofdm_nc*f + i].imag = cimagf(ofdm->rx_np[i]); - } + /* note corrected phase (rx no phase) is one big linear array for frame */ - /* note phase/amp ests the same for each col, but check them all anyway */ + for (i = 0; i < ofdm_rowsperframe * ofdm_nc; i++) { + rx_np_log[ofdm_rowsperframe * ofdm_nc * f + i].real = + crealf(ofdm->rx_np[i]); + rx_np_log[ofdm_rowsperframe * ofdm_nc * f + i].imag = + cimagf(ofdm->rx_np[i]); + } - for (i = 0; i < ofdm_rowsperframe; i++) { - for (j = 0; j < ofdm_nc; j++) { - phase_est_pilot_log[ofdm_rowsperframe*f+i][j] = ofdm->aphase_est_pilot_log[ofdm_nc*i+j]; - rx_amp_log[ofdm_rowsperframe*ofdm_nc*f+ofdm_nc*i+j] = ofdm->rx_amp[ofdm_nc*i+j]; - } - } + /* note phase/amp ests the same for each col, but check them all anyway */ - foff_hz_log[f] = ofdm->foff_est_hz; - timing_est_log[f] = ofdm->timing_est + 1; /* offset by 1 to match Octave */ - timing_valid_log[f] = ofdm->timing_valid; - timing_mx_log[f] = ofdm->timing_mx; - coarse_foff_est_hz_log[f] = ofdm->coarse_foff_est_hz; - sample_point_log[f] = ofdm->sample_point + 1; /* offset by 1 to match Octave */ - float EsNodB = ofdm_esno_est_calc(ofdm->rx_np, ofdm_rowsperframe*ofdm_nc); - snr_log[f] = ofdm_snr_from_esno(ofdm, EsNodB); - mean_amp_log[f] = ofdm->mean_amp; - - memcpy(&rx_bits_log[ofdm_bitsperframe*f], rx_bits, sizeof(rx_bits)); - - if (ldpc_enable) { - for(i=0; i<(CODED_BITSPERFRAME/ofdm_bps) * (1<aphase_est_pilot_log[ofdm_nc * i + j]; + rx_amp_log[ofdm_rowsperframe * ofdm_nc * f + ofdm_nc * i + j] = + ofdm->rx_amp[ofdm_nc * i + j]; + } } - /*---------------------------------------------------------*\ - Dump logs to Octave file for evaluation - by tofdm.m Octave script - \*---------------------------------------------------------*/ - - fout = fopen("tofdm_out.txt","wt"); - assert(fout != NULL); - fprintf(fout, "# Created by tofdm.c\n"); - octave_save_complex(fout, "pilot_samples_c", (COMP*)ofdm->pilot_samples, 1, ofdm_samplespersymbol, ofdm_samplespersymbol); - octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, ofdm_bitsperframe*NFRAMES); - octave_save_complex(fout, "tx_log_c", (COMP*)tx_log, 1, ofdm_samplesperframe*NFRAMES, ofdm_samplesperframe*NFRAMES); - octave_save_complex(fout, "rx_log_c", (COMP*)rx_log, 1, ofdm_samplesperframe*NFRAMES, ofdm_samplesperframe*NFRAMES); - octave_save_complex(fout, "rxbuf_in_log_c", (COMP*)rxbuf_in_log, 1, nin_tot, nin_tot); - octave_save_complex(fout, "rxbuf_log_c", (COMP*)rxbuf_log, 1, ofdm_nrxbuf*NFRAMES, ofdm_nrxbuf*NFRAMES); - octave_save_complex(fout, "rx_sym_log_c", (COMP*)rx_sym_log, (ofdm_ns + 3)*NFRAMES, ofdm_nc + 2, ofdm_nc + 2); - octave_save_float(fout, "phase_est_pilot_log_c", (float*)phase_est_pilot_log, ofdm_rowsperframe*NFRAMES, ofdm_nc, ofdm_nc); - octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, 1, ofdm_rowsperframe*ofdm_nc*NFRAMES, ofdm_rowsperframe*ofdm_nc*NFRAMES); - octave_save_float(fout, "foff_hz_log_c", foff_hz_log, NFRAMES, 1, 1); - octave_save_int(fout, "timing_est_log_c", timing_est_log, NFRAMES, 1); - octave_save_int(fout, "timing_valid_log_c", timing_valid_log, NFRAMES, 1); - octave_save_float(fout, "timing_mx_log_c", timing_mx_log, NFRAMES, 1, 1); - octave_save_float(fout, "coarse_foff_est_hz_log_c", coarse_foff_est_hz_log, NFRAMES, 1, 1); - octave_save_int(fout, "sample_point_log_c", sample_point_log, NFRAMES, 1); - octave_save_complex(fout, "rx_np_log_c", (COMP*)rx_np_log, 1, ofdm_rowsperframe*ofdm_nc*NFRAMES, ofdm_rowsperframe*ofdm_nc*NFRAMES); - octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, ofdm_bitsperframe*NFRAMES); - octave_save_float(fout, "symbol_likelihood_log_c", symbol_likelihood_log, (CODED_BITSPERFRAME/ofdm_bps) * (1<foff_est_hz; + timing_est_log[f] = ofdm->timing_est + 1; /* offset by 1 to match Octave */ + timing_valid_log[f] = ofdm->timing_valid; + timing_mx_log[f] = ofdm->timing_mx; + coarse_foff_est_hz_log[f] = ofdm->coarse_foff_est_hz; + sample_point_log[f] = + ofdm->sample_point + 1; /* offset by 1 to match Octave */ + float EsNodB = ofdm_esno_est_calc(ofdm->rx_np, ofdm_rowsperframe * ofdm_nc); + snr_log[f] = ofdm_snr_from_esno(ofdm, EsNodB); + mean_amp_log[f] = ofdm->mean_amp; + + memcpy(&rx_bits_log[ofdm_bitsperframe * f], rx_bits, sizeof(rx_bits)); + + if (ldpc_enable) { + for (i = 0; i < (CODED_BITSPERFRAME / ofdm_bps) * (1 << ofdm_bps); i++) { + symbol_likelihood_log[(CODED_BITSPERFRAME / ofdm_bps) * + (1 << ofdm_bps) * f + + i] = symbol_likelihood[i]; + } + for (i = 0; i < CODED_BITSPERFRAME; i++) { + bit_likelihood_log[CODED_BITSPERFRAME * f + i] = bit_likelihood[i]; + detected_data_log[CODED_BITSPERFRAME * f + i] = out_char[i]; + } + } + } + + /*---------------------------------------------------------*\ + Dump logs to Octave file for evaluation + by tofdm.m Octave script + \*---------------------------------------------------------*/ + + fout = fopen("tofdm_out.txt", "wt"); + assert(fout != NULL); + fprintf(fout, "# Created by tofdm.c\n"); + octave_save_complex(fout, "pilot_samples_c", (COMP *)ofdm->pilot_samples, 1, + ofdm_samplespersymbol, ofdm_samplespersymbol); + octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, + ofdm_bitsperframe * NFRAMES); + octave_save_complex(fout, "tx_log_c", (COMP *)tx_log, 1, + ofdm_samplesperframe * NFRAMES, + ofdm_samplesperframe * NFRAMES); + octave_save_complex(fout, "rx_log_c", (COMP *)rx_log, 1, + ofdm_samplesperframe * NFRAMES, + ofdm_samplesperframe * NFRAMES); + octave_save_complex(fout, "rxbuf_in_log_c", (COMP *)rxbuf_in_log, 1, nin_tot, + nin_tot); + octave_save_complex(fout, "rxbuf_log_c", (COMP *)rxbuf_log, 1, + ofdm_nrxbuf * NFRAMES, ofdm_nrxbuf * NFRAMES); + octave_save_complex(fout, "rx_sym_log_c", (COMP *)rx_sym_log, + (ofdm_ns + 3) * NFRAMES, ofdm_nc + 2, ofdm_nc + 2); + octave_save_float(fout, "phase_est_pilot_log_c", (float *)phase_est_pilot_log, + ofdm_rowsperframe * NFRAMES, ofdm_nc, ofdm_nc); + octave_save_float(fout, "rx_amp_log_c", (float *)rx_amp_log, 1, + ofdm_rowsperframe * ofdm_nc * NFRAMES, + ofdm_rowsperframe * ofdm_nc * NFRAMES); + octave_save_float(fout, "foff_hz_log_c", foff_hz_log, NFRAMES, 1, 1); + octave_save_int(fout, "timing_est_log_c", timing_est_log, NFRAMES, 1); + octave_save_int(fout, "timing_valid_log_c", timing_valid_log, NFRAMES, 1); + octave_save_float(fout, "timing_mx_log_c", timing_mx_log, NFRAMES, 1, 1); + octave_save_float(fout, "coarse_foff_est_hz_log_c", coarse_foff_est_hz_log, + NFRAMES, 1, 1); + octave_save_int(fout, "sample_point_log_c", sample_point_log, NFRAMES, 1); + octave_save_complex(fout, "rx_np_log_c", (COMP *)rx_np_log, 1, + ofdm_rowsperframe * ofdm_nc * NFRAMES, + ofdm_rowsperframe * ofdm_nc * NFRAMES); + octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, + ofdm_bitsperframe * NFRAMES); + octave_save_float(fout, "symbol_likelihood_log_c", symbol_likelihood_log, + (CODED_BITSPERFRAME / ofdm_bps) * (1 << ofdm_bps) * NFRAMES, + 1, 1); + octave_save_float(fout, "bit_likelihood_log_c", bit_likelihood_log, + CODED_BITSPERFRAME * NFRAMES, 1, 1); + octave_save_int(fout, "detected_data_log_c", detected_data_log, 1, + CODED_BITSPERFRAME * NFRAMES); + octave_save_float(fout, "snr_log_c", snr_log, NFRAMES, 1, 1); + octave_save_float(fout, "mean_amp_log_c", mean_amp_log, NFRAMES, 1, 1); + fclose(fout); #ifdef TESTING_FILE - fclose(fin); + fclose(fin); #endif - ofdm_destroy(ofdm); + ofdm_destroy(ofdm); - return 0; + return 0; } diff --git a/unittest/tofdm_acq.c b/unittest/tofdm_acq.c index ee04d5e..cfb0f99 100644 --- a/unittest/tofdm_acq.c +++ b/unittest/tofdm_acq.c @@ -4,89 +4,91 @@ AUTHORS.....: David Rowe DATE CREATED: Mar 2021 - Tests for the acquistion (sync) parts of the C version of the OFDM modem. - This program outputs a file of Octave vectors that are loaded and - automatically tested against the Octave version of the modem by the Octave + Tests for the acquistion (sync) parts of the C version of the OFDM modem. + This program outputs a file of Octave vectors that are loaded and + automatically tested against the Octave version of the modem by the Octave script tofdm_acq.m \*---------------------------------------------------------------------------*/ #include +#include +#include #include #include -#include #include -#include -#include "ofdm_internal.h" #include "codec2_ofdm.h" #include "octave.h" +#include "ofdm_internal.h" #define MAX_FRAMES 500 -int main(int argc, char *argv[]) -{ - struct OFDM *ofdm; - struct OFDM_CONFIG ofdm_config; - - ofdm_init_mode("datac0", &ofdm_config); - ofdm = ofdm_create(&ofdm_config); - ofdm->data_mode = "burst"; - ofdm->verbose = 2; - ofdm->timing_mx_thresh = 0.15; - ofdm->postambledetectoren = 1; - assert(ofdm != NULL); - - int nin = ofdm_get_nin(ofdm); - int rxbufst = ofdm->rxbufst; - - FILE *fin = fopen(argv[1],"rb"); assert(fin != NULL); - short rx_scaled[ofdm_get_max_samples_per_frame(ofdm)]; - int f = 0; - - float timing_mx_log[MAX_FRAMES]; - int ct_est_log[MAX_FRAMES]; - float foff_est_log[MAX_FRAMES]; - int timing_valid_log[MAX_FRAMES]; - int nin_log[MAX_FRAMES]; - - while (fread(rx_scaled, sizeof (short), nin, fin) == nin) { - fprintf(stderr, "%3d ", f); - ofdm_sync_search_shorts(ofdm, rx_scaled, ofdm->amp_scale / 2.0f); - - if (f < MAX_FRAMES) { - timing_mx_log[f] = ofdm->timing_mx; - ct_est_log[f] = ofdm->ct_est; - foff_est_log[f] = ofdm->foff_est_hz; - timing_valid_log[f] = ofdm->timing_valid; - nin_log[f] = ofdm->nin; - } - f++; - - // reset these to defaults, as they get modified when timing_valid asserted - ofdm->nin = nin; - ofdm->rxbufst = rxbufst; +int main(int argc, char *argv[]) { + struct OFDM *ofdm; + struct OFDM_CONFIG ofdm_config; + + ofdm_init_mode("datac0", &ofdm_config); + ofdm = ofdm_create(&ofdm_config); + ofdm->data_mode = "burst"; + ofdm->verbose = 2; + ofdm->timing_mx_thresh = 0.15; + ofdm->postambledetectoren = 1; + assert(ofdm != NULL); + + int nin = ofdm_get_nin(ofdm); + int rxbufst = ofdm->rxbufst; + + FILE *fin = fopen(argv[1], "rb"); + assert(fin != NULL); + short rx_scaled[ofdm_get_max_samples_per_frame(ofdm)]; + int f = 0; + + float timing_mx_log[MAX_FRAMES]; + int ct_est_log[MAX_FRAMES]; + float foff_est_log[MAX_FRAMES]; + int timing_valid_log[MAX_FRAMES]; + int nin_log[MAX_FRAMES]; + + while (fread(rx_scaled, sizeof(short), nin, fin) == nin) { + fprintf(stderr, "%3d ", f); + ofdm_sync_search_shorts(ofdm, rx_scaled, ofdm->amp_scale / 2.0f); + + if (f < MAX_FRAMES) { + timing_mx_log[f] = ofdm->timing_mx; + ct_est_log[f] = ofdm->ct_est; + foff_est_log[f] = ofdm->foff_est_hz; + timing_valid_log[f] = ofdm->timing_valid; + nin_log[f] = ofdm->nin; } - fclose(fin); - - /*---------------------------------------------------------*\ - Dump logs to Octave file for evaluation - by tofdm_acq.m Octave script - \*---------------------------------------------------------*/ - - FILE *fout = fopen("tofdm_acq_out.txt","wt"); - assert(fout != NULL); - fprintf(fout, "# Created by tofdm_acq.c\n"); - octave_save_complex(fout, "tx_preamble_c", (COMP*)ofdm->tx_preamble, 1, ofdm->samplesperframe, ofdm->samplesperframe); - octave_save_complex(fout, "tx_postamble_c", (COMP*)ofdm->tx_postamble, 1, ofdm->samplesperframe, ofdm->samplesperframe); - octave_save_float(fout, "timing_mx_log_c", timing_mx_log, 1, f, f); - octave_save_float(fout, "foff_est_log_c", foff_est_log, 1, f, f); - octave_save_int(fout, "ct_est_log_c", ct_est_log, 1, f); - octave_save_int(fout, "timing_valid_log_c", timing_valid_log, 1, f); - octave_save_int(fout, "nin_log_c", nin_log, 1, f); - fclose(fout); - - ofdm_destroy(ofdm); - - return 0; + f++; + + // reset these to defaults, as they get modified when timing_valid asserted + ofdm->nin = nin; + ofdm->rxbufst = rxbufst; + } + fclose(fin); + + /*---------------------------------------------------------*\ + Dump logs to Octave file for evaluation + by tofdm_acq.m Octave script + \*---------------------------------------------------------*/ + + FILE *fout = fopen("tofdm_acq_out.txt", "wt"); + assert(fout != NULL); + fprintf(fout, "# Created by tofdm_acq.c\n"); + octave_save_complex(fout, "tx_preamble_c", (COMP *)ofdm->tx_preamble, 1, + ofdm->samplesperframe, ofdm->samplesperframe); + octave_save_complex(fout, "tx_postamble_c", (COMP *)ofdm->tx_postamble, 1, + ofdm->samplesperframe, ofdm->samplesperframe); + octave_save_float(fout, "timing_mx_log_c", timing_mx_log, 1, f, f); + octave_save_float(fout, "foff_est_log_c", foff_est_log, 1, f, f); + octave_save_int(fout, "ct_est_log_c", ct_est_log, 1, f); + octave_save_int(fout, "timing_valid_log_c", timing_valid_log, 1, f); + octave_save_int(fout, "nin_log_c", nin_log, 1, f); + fclose(fout); + + ofdm_destroy(ofdm); + + return 0; } diff --git a/unittest/tqam16.c b/unittest/tqam16.c index 21ae9d0..9e4c8d0 100644 --- a/unittest/tqam16.c +++ b/unittest/tqam16.c @@ -10,28 +10,26 @@ #include #include + #include "ofdm_internal.h" int main(void) { - int c; - for(c=0; c<16; c++) { - int tx_bits[4], rx_bits[4]; - for(int i=0; i<4; i++) - tx_bits[i] = (c >> (3-i)) & 0x1; - complex float symbol = qam16_mod(tx_bits); - qam16_demod(symbol, rx_bits); - if (memcmp(tx_bits, rx_bits, 4)) { - fprintf(stderr, "FAIL on %d!\ntx_bits: ",c); - for(int i=0; i<4; i++) fprintf(stderr, "%d ", tx_bits[i]); - fprintf(stderr, "%f %f\nrx_bits: ", creal(symbol), cimag(symbol)); - for(int i=0; i<4; i++) fprintf(stderr, "%d ", rx_bits[i]); - fprintf(stderr, "%f %f\n", creal(symbol), cimag(symbol)); - return 1; - } + int c; + for (c = 0; c < 16; c++) { + int tx_bits[4], rx_bits[4]; + for (int i = 0; i < 4; i++) tx_bits[i] = (c >> (3 - i)) & 0x1; + complex float symbol = qam16_mod(tx_bits); + qam16_demod(symbol, rx_bits); + if (memcmp(tx_bits, rx_bits, 4)) { + fprintf(stderr, "FAIL on %d!\ntx_bits: ", c); + for (int i = 0; i < 4; i++) fprintf(stderr, "%d ", tx_bits[i]); + fprintf(stderr, "%f %f\nrx_bits: ", creal(symbol), cimag(symbol)); + for (int i = 0; i < 4; i++) fprintf(stderr, "%d ", rx_bits[i]); + fprintf(stderr, "%f %f\n", creal(symbol), cimag(symbol)); + return 1; } + } - fprintf(stderr, "%d tested OK...\nPASS!\n", c); - return 0; + fprintf(stderr, "%d tested OK...\nPASS!\n", c); + return 0; } - - diff --git a/unittest/tquisk_filter.c b/unittest/tquisk_filter.c index f31e6bd..1879dff 100644 --- a/unittest/tquisk_filter.c +++ b/unittest/tquisk_filter.c @@ -2,46 +2,45 @@ tquisk_filter.c Unit test for complex band pass filters in src/filter.c - + cd codec2/build_linux ./misc/mksine - 1500 2 | unittest/tquisk_filter | aplay - + By adjusting the frequency you can audibly test filter response. */ #include #include -#include #include +#include + #include "filter.h" #include "filter_coef.h" -#define N 159 /* processing buffer size (odd number deliberate) */ -#define CENTRE 1500.0 -#define FS 8000.0 - +#define N 159 /* processing buffer size (odd number deliberate) */ +#define CENTRE 1500.0 +#define FS 8000.0 + int main() { - short buf_short[N]; - complex float buf[N]; - struct quisk_cfFilter *bpf; - int i; - - bpf = malloc(sizeof(struct quisk_cfFilter)); - assert(bpf != NULL); - quisk_filt_cfInit(bpf, filtP200S400, sizeof (filtP200S400) / sizeof (float)); - quisk_cfTune(bpf, CENTRE/FS); - - while(fread(buf_short, sizeof(short), N, stdin) == N) { - for(i=0; i -#include #include +#include void write_float_file(char fn[], float *values, int n) { - FILE *f=fopen(fn,"wb"); - assert(f != NULL); - assert(fwrite(values, sizeof(float), n, f) == n); - fclose(f); + FILE *f = fopen(fn, "wb"); + assert(f != NULL); + assert(fwrite(values, sizeof(float), n, f) == n); + fclose(f); } int main(void) { - /* we're only interested in searching the inner 2 values, outer elements should be - ignored */ - float target[] = {0.0,1.0,1.0,0.0}; - write_float_file("target.f32", target, 4); - float vq1[] = {1.0,0.9,0.9,1.0, /* this will be a better match on first stage */ - 2.0,0.8,0.8,2.0}; /* but after second stage should choose this */ - write_float_file("vq1.f32", vq1, 8); - float vq2[] = {10.0,0.3,0.3,10.0, - 20.0,0.2,0.2,20.0}; /* 0.8+0.2 == 1.0 so best 2nd stage entry */ - write_float_file("vq2.f32", vq2, 8); - return 0; + /* we're only interested in searching the inner 2 values, outer elements + should be ignored */ + float target[] = {0.0, 1.0, 1.0, 0.0}; + write_float_file("target.f32", target, 4); + float vq1[] = { + 1.0, 0.9, 0.9, 1.0, /* this will be a better match on first stage */ + 2.0, 0.8, 0.8, 2.0}; /* but after second stage should choose this */ + write_float_file("vq1.f32", vq1, 8); + float vq2[] = {10.0, 0.3, 0.3, 10.0, 20.0, + 0.2, 0.2, 20.0}; /* 0.8+0.2 == 1.0 so best 2nd stage entry */ + write_float_file("vq2.f32", vq2, 8); + return 0; } diff --git a/unittest/vq_mbest.c b/unittest/vq_mbest.c index a247f61..62b7e95 100644 --- a/unittest/vq_mbest.c +++ b/unittest/vq_mbest.c @@ -8,295 +8,293 @@ #include #include +#include #include -#include #include +#include #include -#include + #include "mbest.h" -#define MAX_K 20 +#define MAX_K 20 #define MAX_ENTRIES 4096 -#define MAX_STAGES 5 +#define MAX_STAGES 5 -void quant_mbest(float vec_out[], - int indexes[], - float vec_in[], - int num_stages, - float vqw[], float vq[], - int m[], int k, - int mbest_survivors); +void quant_mbest(float vec_out[], int indexes[], float vec_in[], int num_stages, + float vqw[], float vq[], int m[], int k, int mbest_survivors); int verbose = 0; int main(int argc, char *argv[]) { - float vq[MAX_STAGES*MAX_K*MAX_ENTRIES]; - float vqw[MAX_STAGES*MAX_K*MAX_ENTRIES]; - int m[MAX_STAGES]; - int k=0, mbest_survivors=1, num_stages=0; - char fnames[256], fn[256], *comma, *p; - FILE *fq; - float lower = -1E32; - int st = -1; - int en = -1; - int num = INT_MAX; - int output_vec_usage = 0; - - int o = 0; int opt_idx = 0; - while (o != -1) { - static struct option long_opts[] = { - {"k", required_argument, 0, 'k'}, - {"quant", required_argument, 0, 'q'}, - {"mbest", required_argument, 0, 'm'}, - {"lower", required_argument, 0, 'l'}, - {"verbose", required_argument, 0, 'v'}, - {"st", required_argument, 0, 't'}, - {"en", required_argument, 0, 'e'}, - {"num", required_argument, 0, 'n'}, - {"vec_usage", no_argument, 0, 'u'}, - {0, 0, 0, 0} - }; + float vq[MAX_STAGES * MAX_K * MAX_ENTRIES]; + float vqw[MAX_STAGES * MAX_K * MAX_ENTRIES]; + int m[MAX_STAGES]; + int k = 0, mbest_survivors = 1, num_stages = 0; + char fnames[256], fn[256], *comma, *p; + FILE *fq; + float lower = -1E32; + int st = -1; + int en = -1; + int num = INT_MAX; + int output_vec_usage = 0; + + int o = 0; + int opt_idx = 0; + while (o != -1) { + static struct option long_opts[] = {{"k", required_argument, 0, 'k'}, + {"quant", required_argument, 0, 'q'}, + {"mbest", required_argument, 0, 'm'}, + {"lower", required_argument, 0, 'l'}, + {"verbose", required_argument, 0, 'v'}, + {"st", required_argument, 0, 't'}, + {"en", required_argument, 0, 'e'}, + {"num", required_argument, 0, 'n'}, + {"vec_usage", no_argument, 0, 'u'}, + {0, 0, 0, 0}}; - o = getopt_long(argc,argv,"hk:q:m:vt:e:n:u",long_opts,&opt_idx); - switch (o) { - case 'k': - k = atoi(optarg); - assert(k <= MAX_K); - break; - case 'q': - /* load up list of comma delimited file names */ - strcpy(fnames, optarg); - p = fnames; - num_stages = 0; - do { - assert(num_stages < MAX_STAGES); - strcpy(fn, p); - comma = strchr(fn, ','); - if (comma) { - *comma = 0; - p = comma+1; - } - /* load quantiser file */ - fprintf(stderr, "stage: %d loading %s ... ", num_stages, fn); - fq=fopen(fn, "rb"); - if (fq == NULL) { - fprintf(stderr, "Couldn't open: %s\n", fn); - exit(1); - } - /* count how many entries m of dimension k are in this VQ file */ - m[num_stages] = 0; - float dummy[k]; - while (fread(dummy, sizeof(float), k, fq) == (size_t)k) - m[num_stages]++; - assert(m[num_stages] <= MAX_ENTRIES); - fprintf(stderr, "%d entries of vectors width %d\n", m[num_stages], k); - /* now load VQ into memory */ - rewind(fq); - int rd = fread(&vq[num_stages*k*MAX_ENTRIES], sizeof(float), m[num_stages]*k, fq); - assert(rd == m[num_stages]*k); - num_stages++; - fclose(fq); - } while(comma); - break; - case 'm': - mbest_survivors = atoi(optarg); - fprintf(stderr, "mbest_survivors = %d\n", mbest_survivors); - break; - case 'n': - num = atoi(optarg); - break; - case 'l': - lower = atof(optarg); - break; - case 't': - st = atoi(optarg); - break; - case 'e': - en = atoi(optarg); - break; - case 'u': - output_vec_usage = 1; - break; - case 'v': - verbose = 1; - break; - help: - fprintf(stderr, "\n"); - fprintf(stderr, "usage: %s -k dimension -q vq1.f32,vq2.f32,.... [Options]\n", argv[0]); - fprintf(stderr, "\n"); - fprintf(stderr, "input vectors on stdin, output quantised vectors on stdout\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "--lower lowermeanLimit Only count vectors with average above this level in distortion calculations\n"); - fprintf(stderr, "--mbest N number of survivors at each stage, set to 0 for standard VQ search\n"); - fprintf(stderr, "--st Kst start vector element for error calculation (default 0)\n"); - fprintf(stderr, "--en Ken end vector element for error calculation (default K-1)\n"); - fprintf(stderr, "--num numToProcess number of vectors to quantise (default to EOF)\n"); - fprintf(stderr, "--vec_usage Output a record of how many times each vector is used\n"); - fprintf(stderr, "-v Verbose\n"); + o = getopt_long(argc, argv, "hk:q:m:vt:e:n:u", long_opts, &opt_idx); + switch (o) { + case 'k': + k = atoi(optarg); + assert(k <= MAX_K); + break; + case 'q': + /* load up list of comma delimited file names */ + strcpy(fnames, optarg); + p = fnames; + num_stages = 0; + do { + assert(num_stages < MAX_STAGES); + strcpy(fn, p); + comma = strchr(fn, ','); + if (comma) { + *comma = 0; + p = comma + 1; + } + /* load quantiser file */ + fprintf(stderr, "stage: %d loading %s ... ", num_stages, fn); + fq = fopen(fn, "rb"); + if (fq == NULL) { + fprintf(stderr, "Couldn't open: %s\n", fn); exit(1); - } + } + /* count how many entries m of dimension k are in this VQ file */ + m[num_stages] = 0; + float dummy[k]; + while (fread(dummy, sizeof(float), k, fq) == (size_t)k) + m[num_stages]++; + assert(m[num_stages] <= MAX_ENTRIES); + fprintf(stderr, "%d entries of vectors width %d\n", m[num_stages], k); + /* now load VQ into memory */ + rewind(fq); + int rd = fread(&vq[num_stages * k * MAX_ENTRIES], sizeof(float), + m[num_stages] * k, fq); + assert(rd == m[num_stages] * k); + num_stages++; + fclose(fq); + } while (comma); + break; + case 'm': + mbest_survivors = atoi(optarg); + fprintf(stderr, "mbest_survivors = %d\n", mbest_survivors); + break; + case 'n': + num = atoi(optarg); + break; + case 'l': + lower = atof(optarg); + break; + case 't': + st = atoi(optarg); + break; + case 'e': + en = atoi(optarg); + break; + case 'u': + output_vec_usage = 1; + break; + case 'v': + verbose = 1; + break; + help: + fprintf(stderr, "\n"); + fprintf(stderr, + "usage: %s -k dimension -q vq1.f32,vq2.f32,.... [Options]\n", + argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, + "input vectors on stdin, output quantised vectors on stdout\n"); + fprintf(stderr, "\n"); + fprintf(stderr, + "--lower lowermeanLimit Only count vectors with average " + "above this level in distortion calculations\n"); + fprintf(stderr, + "--mbest N number of survivors at each stage, " + "set to 0 for standard VQ search\n"); + fprintf(stderr, + "--st Kst start vector element for error " + "calculation (default 0)\n"); + fprintf(stderr, + "--en Ken end vector element for error " + "calculation (default K-1)\n"); + fprintf(stderr, + "--num numToProcess number of vectors to quantise " + "(default to EOF)\n"); + fprintf(stderr, + "--vec_usage Output a record of how many times " + "each vector is used\n"); + fprintf(stderr, "-v Verbose\n"); + exit(1); } + } + + if ((num_stages == 0) || (k == 0)) goto help; - if ((num_stages == 0) || (k == 0)) - goto help; + /* default to measuring error on entire vector */ + if (st == -1) st = 0; + if (en == -1) en = k - 1; - /* default to measuring error on entire vector */ - if (st == -1) st = 0; - if (en == -1) en = k-1; + float w[k]; + for (int i = 0; i < st; i++) w[i] = 0.0; + for (int i = st; i <= en; i++) w[i] = 1.0; + for (int i = en + 1; i < k; i++) w[i] = 0.0; - float w[k]; - for(int i=0; ilist[j].index[s1]; - } - /* target is residual err[] vector given path to this candidate */ - for(i=0; ilist[0].index[num_stages-1-s]; - } + se1 = 0.0; + for (i = 0; i < k; i++) { + err[i] = vec_in[i]; + se1 += err[i] * err[i]; + } + se1 /= k; + + /* now quantise err[] using multi-stage mbest search, preserving + mbest_survivors at each stage */ + + mbest_search(vqw, err, k, m[0], mbest_stage[0], index); + if (verbose) mbest_print("Stage 1:", mbest_stage[0]); - /* OK put it all back together using best survivor */ - for(i=0; ilist[j].index[s1]; + } + /* target is residual err[] vector given path to this candidate */ + for (i = 0; i < k; i++) target[i] = err[i]; + for (s1 = 0; s1 < s; s1++) { + ind = index[s - s1]; + if (verbose) + fprintf(stderr, " s: %d s1: %d s-s1: %d ind: %d\n", s, s1, s - s1, + ind); + for (i = 0; i < k; i++) { + target[i] -= vqw[s1 * k * MAX_ENTRIES + ind * k + i]; } - se2 /= k; - pv(" err: ", err, k); - if (verbose) fprintf(stderr, " se2: %f\n", se2); + } + pv(" target: ", target, k); + mbest_search(&vqw[s * k * MAX_ENTRIES], target, k, m[s], mbest_stage[s], + index); } - pv(" vec_out: ",vec_out, k); + char str[80]; + sprintf(str, "Stage %d:", s + 1); + if (verbose) mbest_print(str, mbest_stage[s]); + } - pv("\n vec_in: ", vec_in, k); - pv(" vec_out: ", vec_out, k); + for (s = 0; s < num_stages; s++) { + indexes[s] = mbest_stage[num_stages - 1]->list[0].index[num_stages - 1 - s]; + } + + /* OK put it all back together using best survivor */ + for (i = 0; i < k; i++) vec_out[i] = 0.0; + for (s = 0; s < num_stages; s++) { + int ind = indexes[s]; + float se2 = 0.0; + for (i = 0; i < k; i++) { + err[i] -= vqw[s * k * MAX_ENTRIES + ind * k + i]; + vec_out[i] += vq[s * k * MAX_ENTRIES + ind * k + i]; + se2 += err[i] * err[i]; + } + se2 /= k; pv(" err: ", err, k); - if (verbose) fprintf(stderr, " se1: %f\n", se1); + if (verbose) fprintf(stderr, " se2: %f\n", se2); + } + pv(" vec_out: ", vec_out, k); + + pv("\n vec_in: ", vec_in, k); + pv(" vec_out: ", vec_out, k); + pv(" err: ", err, k); + if (verbose) fprintf(stderr, " se1: %f\n", se1); - for(i=0; i